Forum OpenACS Q&A: Obtaining the real DB error

Collapse
Posted by Randy O'Meara on
I'm interested in obtaining (programatically) the real reason for a DB insert failure. For example, that a duplicate key insert was attempted. I have named constraints so I can parse the error string to intuit what the error was. Is there a way to obtain this information?

Randy

Collapse
Posted by Jade Rubick on
I can't answer that question, but I can say that if you're working with postgres, you should download the most recent driver. It shows much more meaningful error codes. 😊
Collapse
Posted by Randy O'Meara on
Thank you, Jade. I am able to see the error. I just need to program responses to DB errors. There must be a method to access the real error. Do folks just throw up a generic "there was an error" message and disregard dealing with it?
Collapse
Posted by Jade Rubick on
I haven't done this much, but a lot of good error messages can be shown when you're using ad_form or ad_page_contract. Maybe you can give us more info on what you're trying to do?

ad_form's error handling is especially good.

Collapse
Posted by Randy O'Meara on
For example, there is a table defined with a unique constraint on the name column, which is text. A form is filled out with ad_form and submitted. A record insert is attempted with a duplicate name. An error is generated at the pl/pgsql level  when the insert is performed since the unique constraint is violated. The insert query actually utilizes the xql mechanism and is performed by a call to a defined __new pl/pgsql function, so I do have a function where I can react to errors very close to the DB and possibly pass the error details back to the caller.

In this simple example, without knowing the actual DB error, I might just blindly guess that this particular constraint has been violated and inform the user to change the name. My guess could definitely be wrong. Bad Solution...

Add another constraint to the same table and the guessing approach is not valid at all. Even with just the single constraint, the cause of a DB error could be completely unrelated to it.

I could retrieve all the names of the objects (or cache all the names) and verify the constraint is honored before attempting the __new call. Another (really) Bad Solution...

I know that the cause of a DB error is known at the pl/pgsql level. I'm just looking for a general way to retrieve this information so that I can deal with the cause programatically, in my tcl program... for error control and recovery. Is there no interface or mechanism available to retrieve these details? I have seen no examples of this if it exists.

For what it's worth, the table is a subtyped acs_object and I've followed the standard convention of defining *__{new,delete,name} pl/pgsql functions and used define_function_args on each.

Thanks for taking the time to help.

Randy

Collapse
Posted by Tom Jackson on

Oracle does provide numbered error messages, but I think postgresql is a little lazy in this respect.

Trying to catch this error in pl is not the right solution, I don't think. The error handling in pl is really practically useless. Actually all it might do is to mask the actual error message from being displayed. At any rate, an error will still result, so I don't see the point.

You could check the db beforehand for the unique constraint error. Or if all other error checking is done, probably the only error that will show up is a unique constraint violation, and that leaves you with just catching the insert statement, checking to make sure this was the cause, and then reporting the result back to the user.

Collapse
Posted by Vlad Seryakov on
Insert this after line 410 in nspostgres.c, i added Ns_DbSetException specifically for this purpose.

nspostgres.c:410
    default:
    Ns_Log(Error, "%s: result status: %d message: %s", asfuncname,
              PQresultStatus(nsConn->res), PQerrorMessage(nsConn->conn));
    Ns_DbSetException(handle,"ERROR",PQerrorMessage(nsConn->conn));
        return NS_ERROR;
    }

Collapse
Posted by Randy O'Meara on
Thank you, Vlad. I'm assuming (without analyzing the aolserver code) that your solution would send the error on through to the aolserver ns_dberror tcl api. Is this true? Have you also created an oacs interface that makes the error available in an ad_* api call? Maybe placed within ad_conn? Could you share with me how you do this? If not, I'll dig up the info myself.

I'm amazed that there is no standardized method of dealing with DB errors programatically within oacs. I grep'd all 4.6.3 packages and there was no mention of ns_dberror anywhere.

Randy

Collapse
Posted by Randy O'Meara on
Don, are you reading this thread?

I see, from a google search, that you and Lamar had quite a lengthy discussion regarding propagating db error indications and information through the postgres driver (thread in acs-pg-dev in March 2000: http://www.geocrawler.com/mail/thread.php3?subject=%5BAcs-pg-dev%5D+New+nspostgres.c+in+AOLserver+CVS&list=684).
I'm wondering if there are some hooks at the tcl level where I could access this information to use in dealing with exceptions?

Randy