I was hoping to work on removing some of the difficulty this weekend but I think it would be a good to have a full discussion and hammering out of details first.

As Erik pointed out in the template thread, our error handling is a mess.  In some cases we are returning undef, in some cases we are throwing localised strings.  The undef cases make for a few problems, but the localised strings mean we have no machine-readable error handling and is far worse.  Among the problems with that:

1.  If you want to, say, get the details of a GL transaction, you have to have a locale object.  If you are running a program from outside the LSMB directory, that is easier said than done.

2.  If something goes wrong, you cannot determine what the error was and handle it.

This is a problem on both old and new code but it is a much bigger problem on old code.

I think the easiest way of rectifying the situation is to recognise the code is fairly database-centric and build an error handling mechanism which largely extends the SQL State/message approach.

I am going to suggest we standardise on the following:

1.  We have a particular exception class (maybe an external one, maybe I write PGObject::Util::Exception).  That exception class has four fields:
   a) an error code based on the SQL State table for current PostgreSQL
   b) an optional log message, and
   c) an optional query string
   d) an optional list of parameters which caused the error

2.  When a database errors, we throw the sql state, query string, parameters, and a log message of class and method which caused the error.

3.  Not found returns undef.  If we must throw an exception we use 02000 as the SQL state.  I expect that this is most common in the old code.  In new code we could turn this into a 404 code if we want to.

4.  Precondition checks croak with states that typically start with 22.  In new code we could turn this into a 400 error code.

Does this seem reasonable?
Best Wishes,
Chris Travers

Efficito:  Hosted Accounting and ERP.  Robust and Flexible.  No vendor lock-in.