Thread: error codes
I'd like to implement error codes. I think they would be pretty useful, although there are a few difficulties in the implementation I'd like to get some input on. Should every elog() have an error code? I'm not sure -- there are many elog() calls that will never been seen by the user, since the error they represent will be caught before control reaches the elog (e.g. parse errors, internal consistency checks, multiple elog(ERROR) for the same user error, etc.) Perhaps for those error messages that don't have numbers, we could just give them ERRNO_UNKNOWN or a similar constant. How should the backend code signal an error with an error number? Perhaps we could report errors with error numbers via a separate function, which would take the error number as its only param. For example: error(ERRNO_REF_INT_VIOLATION); The problem here is that many errors will require more information that that, in order for the client to handle them properly. For example, how should a COPY indicate that an RI violation has occured? Ideally, we'd like to allow the client application to know that in line a, column b, the literal value 'c' was not found in the referenced column d of the referenced table d. How should the error number be sent to the client, and would this require an FE/BE change? I think we can avoid that: including the error number in the error message itself, make PQgetErrorMessage() (and similar funcs) smart enough to remove the error number, and add a separate function (such as PQgetErrorNumber() ) to report the error number, if there is one. On a related note, it would be nice to get a consistent style of punctuation for elog() messages -- currently, some of them end in a period (e.g. "Database xxx does not exist in the system catalog."), while the majority do not. Which is better? Also, I think it was Bruce who mentioned that it would be nice to add function names, source files, and/or line numbers to error messages, instead of the current inconsistent method of sometimes specifying the function name in the elog() message. Would this be a good idea? Should all errors include this information? It would be relatively easy to replace elog() with a macro of the form: #define elog(...) real_elog(__FILE__, __LINE__, __VA_ARGS__) And then adjust real_elog() to report that information as appropriate. Cheers, Neil -- Neil Conway <neilconway@rogers.com> PGP Key ID: DB3C29FC
nconway@klamath.dyndns.org (Neil Conway) writes: > Should every elog() have an error code? I believe we decided that it'd be okay to use one or two codes defined like "internal error", "corrupted data", etc for all the elogs that are not-supposed-to-happen conditions. What error codes are really for is distinguishing different kinds of user mistakes, and so that's where you need specificness. > How should the backend code signal an error with an error number? Please read some of the archived discussions about this. All the points you mention have been brought up before. regards, tom lane
On Wed, Jul 17, 2002 at 03:57:56PM -0400, Tom Lane wrote: > nconway@klamath.dyndns.org (Neil Conway) writes: > > Should every elog() have an error code? > > I believe we decided that it'd be okay to use one or two codes defined > like "internal error", "corrupted data", etc for all the elogs that are > not-supposed-to-happen conditions. Ok, makes sense to me. > > How should the backend code signal an error with an error number? > > Please read some of the archived discussions about this. All the points > you mention have been brought up before. Woops -- I wasn't aware that this had been discussed before, my apologies. I'm reading the archives now... Peter: are you planning to implement this? Cheers, Neil -- Neil Conway <neilconway@rogers.com> PGP Key ID: DB3C29FC
Neil, attached are three email messages dealing with error message wording. I like Tom's idea of coding only the messages that are common/user errors and leaving the others with a catch-all code. We now have more elog levels in 7.3, so it should be easier to classify the messages. I can see this job as several parts: --------------------------------------------------------------------------- Cleanup of error wording, removal of function names. See attached emails for possible standard. --------------------------------------------------------------------------- Reporting of file, line, function reporting using GUC/SET variable. For function names I see in the gcc 3.1 docs at http://gcc.gnu.org/onlinedocs/gcc-3.1/cpp/Standard-Predefined-Macros.html: C99 introduces __func__, and GCC has provided __FUNCTION__ for a long time. Both of these are strings containing the name of the current function (there are slight semantic differences; see the GCC manual). Neither of them is a macro; the preprocessor does not know the name of the current function. They tend to be useful in conjunction with __FILE__ and __LINE__, though. My gcc 2.95 (gcc version 2.95.2 19991024) supports both __FUNCTION__ and __func__, even though they are not documented in the info manual pages I have. I think we will need a configure.in test for this because it isn't a macro you can #ifdef. --------------------------------------------------------------------------- Actual error code numbers/letters. I think the new elog levels will help with this. We have to decide if we want error numbers, or some pneumonic like NOATTR or CONSTVIOL. I suggest the latter. --------------------------------------------------------------------------- I think we have plenty of time to get this done for 7.3. -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 853-3000 + If your life is a hard drive, | 830 Blythe Avenue + Christ can be your backup. | Drexel Hill, Pennsylvania 19026
Neil Conway writes: > I'd like to implement error codes. I think they would be pretty useful, > although there are a few difficulties in the implementation I'd like > to get some input on. OK, allow me to pass on to you the accumulated wisdom on this topic. :-) > Should every elog() have an error code? The set of error codes should primarily be that defined by SQL99 part 2 clause 22 "Status codes" and PostgreSQL extensions that follow that spirit. That means that all those "can't happen" or "all is lost anyway" types should be lumped (perhaps in some implicit way) under "internal error". That means, yes, an error code should be returned in every case of an error, but it doesn't have to be a distinct error code for every condition. > How should the backend code signal an error with an error number? > The problem here is that many errors will require more information > that that, in order for the client to handle them properly. For > example, how should a COPY indicate that an RI violation has > occured? Ideally, we'd like to allow the client application to > know that in line a, column b, the literal value 'c' was > not found in the referenced column d of the referenced table d. Precisely. You will find that SQL99 part 2 clause 19 "Diagnostics management" defines all the fields that form part of a diagnostic (i.e., error or notice). This includes for example, fields that contain the name and schema of the table that was involved, if appropriate. (Again, appropriate PostgreSQL extensions could be made.) It is recommendable that this scheme be followed, so PL/pgSQL and ECPG, to name some candidates, could implement the GET DIAGNOSTICS statement as in the standard. (Notice that, for example, a diagnostic still contains a text message in addition to a code.) > How should the error number be sent to the client, and would this > require an FE/BE change? I think we can avoid that: including the > error number in the error message itself, make PQgetErrorMessage() > (and similar funcs) smart enough to remove the error number, and > add a separate function (such as PQgetErrorNumber() ) to report > the error number, if there is one. I would advise against trying to cram everything into a string. Consider the extra fields explained above. Consider being nice to old clients. Also, libpq allows that more than one error message might arrive per query cycle. Currently, the error messages are concatenated. That won't work anymore. You need a new API anyway. You need a new API for notices, too. One possiblity to justify a protocol change is to break something else with it, like a new copy protocol. > On a related note, it would be nice to get a consistent style of > punctuation for elog() messages -- currently, some of them end > in a period (e.g. "Database xxx does not exist in the system > catalog."), while the majority do not. Which is better? Yup, we've talked about that some time ago. I have a style guide mostly worked out for discussion. > It would be relatively easy to replace elog() with a macro of > the form: > > #define elog(...) real_elog(__FILE__, __LINE__, __VA_ARGS__) > > And then adjust real_elog() to report that information as > appropriate. And it would be relatively easy to break every old compiler that way... -- Peter Eisentraut peter_e@gmx.net
> Should every elog() have an error code? I'm not sure -- there are many > elog() calls that will never been seen by the user, since the error > they represent will be caught before control reaches the elog (e.g. > parse errors, internal consistency checks, multiple elog(ERROR) > for the same user error, etc.) Perhaps for those error messages > that don't have numbers, we could just give them ERRNO_UNKNOWN or > a similar constant. It might be cool to a little command utility "pg_error" or whatever that you pass an error code to and it prints out a very detailed description of the problem... Chris
Bruce wrote: > Actual error code numbers/letters. I think the new elog levels will > help with this. We have to decide if we want error numbers, or some > pneumonic like NOATTR or CONSTVIOL. I suggest the latter. Since there is an actual standard for error codes, I would strongly suggest to adhere. The standardized codes are SQLSTATE a char(5) (well standardized for many classes of db errors). Also common, but not so standardized is SQLCODE a long (only a very few are standardized, like 100 = 'no data found'). And also sqlca. Also look at ecpg for sqlcode and sqlca. A Quote from dec rdb: -------------------------------------------------------------------- o SQLCODE-This is the original SQL error handlingmechanism. It is an integer value. SQLCODE differentiates among errors (negative numbers), warnings (positivenumbers), succesful completion (0), and a special code of 100, which means no data. SQLCODE is a deprecatedfeature of the ANSI/ISO SQL standard. o SQLCA-This is an extension of the SQLCODE error handling mechanism. It contains other context information that supplements the SQLCODE value. SQLCA is not part of the ANSI/ISO SQL standard. However, many foreign databases such as DB2 and ORACLE RDBMS have defined proprietary semantics and syntax to implement it. o SQLSTATE-This is the error handling mechanism for the ANSI/ISO SQL standard. The SQLSTATE value is a character stringthat is associated with diagnostic information. To use the SQLSTATE status parameter, you must specify theSQL92 dialect and compile your module using DEC Rdb Version 6.0. -------------------------------------------------------------------- Andreas
Insisting on Andreas suggestion, why can't we just prefix all error message strings with the SQLState code? So all error messages would have the format CCSSS - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Where CCSSS is the standard SQLState code and the message text is a more specific description. Note that the standard allows for implementation-defined codes, so we can have our own CC classes and all the SSS subclasses that we need. -- Fernando Nasser Red Hat - Toronto E-Mail: fnasser@redhat.com 2323 Yonge Street, Suite #300 Toronto, Ontario M4P 2C9