mirror of
https://github.com/psycopg/psycopg2.git
synced 2024-11-22 00:46:33 +03:00
Merge remote-tracking branch 'origin/errors-module-c'
This commit is contained in:
commit
16b35ac77b
|
@ -10,8 +10,9 @@
|
|||
|
||||
.. versionadded:: 2.8
|
||||
|
||||
This module contains the classes psycopg raises upon receiving an error from
|
||||
the database with a :sql:`SQLSTATE` value attached. The module is generated
|
||||
This module exposes the classes psycopg raises upon receiving an error from
|
||||
the database with a :sql:`SQLSTATE` value attached (available in the
|
||||
`~psycopg2.Error.pgcode` attribute). The content of the module is generated
|
||||
from the PostgreSQL source code and includes classes for every error defined
|
||||
by PostgreSQL in versions between 9.1 and 11.
|
||||
|
||||
|
@ -53,8 +54,16 @@ idiomatic error handler:
|
|||
except psycopg2.errors.LockNotAvailable:
|
||||
locked = True
|
||||
|
||||
For completeness, the module also exposes all the DB-API-defined classes and
|
||||
:ref:`a few psycopg-specific exceptions <extension-exceptions>` previously
|
||||
exposed by the `!extensions` module. One stop shop for all your mistakes...
|
||||
For completeness, the module also exposes all the :ref:`DB-API-defined
|
||||
exceptions <dbapi-exceptions>` and :ref:`a few psycopg-specific ones
|
||||
<extension-exceptions>` exposed by the `!extensions` module. One stop shop
|
||||
for all your mistakes...
|
||||
|
||||
.. autofunction:: lookup
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
try:
|
||||
cur.execute("LOCK TABLE mytable IN ACCESS EXCLUSIVE MODE NOWAIT")
|
||||
except psycopg2.errors.lookup("55P03"):
|
||||
locked = True
|
||||
|
|
|
@ -137,14 +137,15 @@ available through the following exceptions:
|
|||
.. exception:: Warning
|
||||
|
||||
Exception raised for important warnings like data truncations while
|
||||
inserting, etc. It is a subclass of the Python `~exceptions.StandardError`.
|
||||
inserting, etc. It is a subclass of the Python `StandardError`
|
||||
(`Exception` on Python 3).
|
||||
|
||||
.. exception:: Error
|
||||
|
||||
Exception that is the base class of all other error exceptions. You can
|
||||
use this to catch all errors with one single `!except` statement. Warnings
|
||||
are not considered errors and thus not use this class as base. It
|
||||
is a subclass of the Python `!StandardError`.
|
||||
is a subclass of the Python `StandardError` (`Exception` on Python 3).
|
||||
|
||||
.. attribute:: pgerror
|
||||
|
||||
|
|
1329
lib/errors.py
1329
lib/errors.py
File diff suppressed because it is too large
Load Diff
|
@ -39,5 +39,7 @@ typedef struct {
|
|||
} errorObject;
|
||||
|
||||
HIDDEN PyObject *error_text_from_chars(errorObject *self, const char *str);
|
||||
HIDDEN BORROWED PyObject *exception_from_sqlstate(const char *sqlstate);
|
||||
HIDDEN BORROWED PyObject *base_exception_from_sqlstate(const char *sqlstate);
|
||||
|
||||
#endif /* PSYCOPG_ERROR_H */
|
||||
|
|
|
@ -38,6 +38,104 @@ error_text_from_chars(errorObject *self, const char *str)
|
|||
}
|
||||
|
||||
|
||||
/* Return the Python exception corresponding to an SQLSTATE error
|
||||
* code. A list of error codes can be found at:
|
||||
* https://www.postgresql.org/docs/current/static/errcodes-appendix.html
|
||||
*/
|
||||
BORROWED PyObject *
|
||||
exception_from_sqlstate(const char *sqlstate)
|
||||
{
|
||||
PyObject *exc;
|
||||
|
||||
/* First look up an exception of the proper class */
|
||||
exc = PyDict_GetItemString(sqlstate_errors, sqlstate);
|
||||
if (exc) {
|
||||
return exc;
|
||||
}
|
||||
else {
|
||||
PyErr_Clear();
|
||||
return base_exception_from_sqlstate(sqlstate);
|
||||
}
|
||||
}
|
||||
|
||||
BORROWED PyObject *
|
||||
base_exception_from_sqlstate(const char *sqlstate)
|
||||
{
|
||||
switch (sqlstate[0]) {
|
||||
case '0':
|
||||
switch (sqlstate[1]) {
|
||||
case 'A': /* Class 0A - Feature Not Supported */
|
||||
return NotSupportedError;
|
||||
}
|
||||
break;
|
||||
case '2':
|
||||
switch (sqlstate[1]) {
|
||||
case '0': /* Class 20 - Case Not Found */
|
||||
case '1': /* Class 21 - Cardinality Violation */
|
||||
return ProgrammingError;
|
||||
case '2': /* Class 22 - Data Exception */
|
||||
return DataError;
|
||||
case '3': /* Class 23 - Integrity Constraint Violation */
|
||||
return IntegrityError;
|
||||
case '4': /* Class 24 - Invalid Cursor State */
|
||||
case '5': /* Class 25 - Invalid Transaction State */
|
||||
return InternalError;
|
||||
case '6': /* Class 26 - Invalid SQL Statement Name */
|
||||
case '7': /* Class 27 - Triggered Data Change Violation */
|
||||
case '8': /* Class 28 - Invalid Authorization Specification */
|
||||
return OperationalError;
|
||||
case 'B': /* Class 2B - Dependent Privilege Descriptors Still Exist */
|
||||
case 'D': /* Class 2D - Invalid Transaction Termination */
|
||||
case 'F': /* Class 2F - SQL Routine Exception */
|
||||
return InternalError;
|
||||
}
|
||||
break;
|
||||
case '3':
|
||||
switch (sqlstate[1]) {
|
||||
case '4': /* Class 34 - Invalid Cursor Name */
|
||||
return OperationalError;
|
||||
case '8': /* Class 38 - External Routine Exception */
|
||||
case '9': /* Class 39 - External Routine Invocation Exception */
|
||||
case 'B': /* Class 3B - Savepoint Exception */
|
||||
return InternalError;
|
||||
case 'D': /* Class 3D - Invalid Catalog Name */
|
||||
case 'F': /* Class 3F - Invalid Schema Name */
|
||||
return ProgrammingError;
|
||||
}
|
||||
break;
|
||||
case '4':
|
||||
switch (sqlstate[1]) {
|
||||
case '0': /* Class 40 - Transaction Rollback */
|
||||
return TransactionRollbackError;
|
||||
case '2': /* Class 42 - Syntax Error or Access Rule Violation */
|
||||
case '4': /* Class 44 - WITH CHECK OPTION Violation */
|
||||
return ProgrammingError;
|
||||
}
|
||||
break;
|
||||
case '5':
|
||||
/* Class 53 - Insufficient Resources
|
||||
Class 54 - Program Limit Exceeded
|
||||
Class 55 - Object Not In Prerequisite State
|
||||
Class 57 - Operator Intervention
|
||||
Class 58 - System Error (errors external to PostgreSQL itself) */
|
||||
if (!strcmp(sqlstate, "57014"))
|
||||
return QueryCanceledError;
|
||||
else
|
||||
return OperationalError;
|
||||
case 'F': /* Class F0 - Configuration File Error */
|
||||
return InternalError;
|
||||
case 'H': /* Class HV - Foreign Data Wrapper Error (SQL/MED) */
|
||||
return OperationalError;
|
||||
case 'P': /* Class P0 - PL/pgSQL Error */
|
||||
return InternalError;
|
||||
case 'X': /* Class XX - Internal Error */
|
||||
return InternalError;
|
||||
}
|
||||
/* return DatabaseError as a fallback */
|
||||
return DatabaseError;
|
||||
}
|
||||
|
||||
|
||||
static const char pgerror_doc[] =
|
||||
"The error message returned by the backend, if available, else None";
|
||||
|
||||
|
|
124
psycopg/pqpath.c
124
psycopg/pqpath.c
|
@ -77,130 +77,6 @@ strip_severity(const char *msg)
|
|||
return msg;
|
||||
}
|
||||
|
||||
/* Return a Python exception from a SQLSTATE from psycopg2.errors */
|
||||
BORROWED static PyObject *
|
||||
exception_from_module(const char *sqlstate)
|
||||
{
|
||||
PyObject *rv = NULL;
|
||||
PyObject *m = NULL;
|
||||
PyObject *map = NULL;
|
||||
|
||||
if (!(m = PyImport_ImportModule("psycopg2.errors"))) { goto exit; }
|
||||
if (!(map = PyObject_GetAttrString(m, "_by_sqlstate"))) { goto exit; }
|
||||
if (!PyDict_Check(map)) {
|
||||
Dprintf("'psycopg2.errors._by_sqlstate' is not a dict!");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* get the sqlstate class (borrowed reference), or fail trying. */
|
||||
rv = PyDict_GetItemString(map, sqlstate);
|
||||
|
||||
exit:
|
||||
/* We exit with a borrowed object, or a NULL but no error
|
||||
* If an error did happen in this function, we don't want to clobber the
|
||||
* database error. So better reporting it, albeit with the wrong class. */
|
||||
PyErr_Clear();
|
||||
|
||||
Py_XDECREF(map);
|
||||
Py_XDECREF(m);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* Returns the Python exception corresponding to an SQLSTATE error
|
||||
code. A list of error codes can be found at:
|
||||
|
||||
https://www.postgresql.org/docs/current/static/errcodes-appendix.html */
|
||||
BORROWED static PyObject *
|
||||
exception_from_sqlstate(const char *sqlstate)
|
||||
{
|
||||
PyObject *exc;
|
||||
|
||||
/* First look up an exception of the proper class from the Python module */
|
||||
exc = exception_from_module(sqlstate);
|
||||
if (exc) {
|
||||
return exc;
|
||||
}
|
||||
else {
|
||||
PyErr_Clear();
|
||||
}
|
||||
|
||||
/*
|
||||
* IMPORTANT: if you change anything in this function you should change
|
||||
* make_errors.py accordingly.
|
||||
*/
|
||||
switch (sqlstate[0]) {
|
||||
case '0':
|
||||
switch (sqlstate[1]) {
|
||||
case 'A': /* Class 0A - Feature Not Supported */
|
||||
return NotSupportedError;
|
||||
}
|
||||
break;
|
||||
case '2':
|
||||
switch (sqlstate[1]) {
|
||||
case '0': /* Class 20 - Case Not Found */
|
||||
case '1': /* Class 21 - Cardinality Violation */
|
||||
return ProgrammingError;
|
||||
case '2': /* Class 22 - Data Exception */
|
||||
return DataError;
|
||||
case '3': /* Class 23 - Integrity Constraint Violation */
|
||||
return IntegrityError;
|
||||
case '4': /* Class 24 - Invalid Cursor State */
|
||||
case '5': /* Class 25 - Invalid Transaction State */
|
||||
return InternalError;
|
||||
case '6': /* Class 26 - Invalid SQL Statement Name */
|
||||
case '7': /* Class 27 - Triggered Data Change Violation */
|
||||
case '8': /* Class 28 - Invalid Authorization Specification */
|
||||
return OperationalError;
|
||||
case 'B': /* Class 2B - Dependent Privilege Descriptors Still Exist */
|
||||
case 'D': /* Class 2D - Invalid Transaction Termination */
|
||||
case 'F': /* Class 2F - SQL Routine Exception */
|
||||
return InternalError;
|
||||
}
|
||||
break;
|
||||
case '3':
|
||||
switch (sqlstate[1]) {
|
||||
case '4': /* Class 34 - Invalid Cursor Name */
|
||||
return OperationalError;
|
||||
case '8': /* Class 38 - External Routine Exception */
|
||||
case '9': /* Class 39 - External Routine Invocation Exception */
|
||||
case 'B': /* Class 3B - Savepoint Exception */
|
||||
return InternalError;
|
||||
case 'D': /* Class 3D - Invalid Catalog Name */
|
||||
case 'F': /* Class 3F - Invalid Schema Name */
|
||||
return ProgrammingError;
|
||||
}
|
||||
break;
|
||||
case '4':
|
||||
switch (sqlstate[1]) {
|
||||
case '0': /* Class 40 - Transaction Rollback */
|
||||
return TransactionRollbackError;
|
||||
case '2': /* Class 42 - Syntax Error or Access Rule Violation */
|
||||
case '4': /* Class 44 - WITH CHECK OPTION Violation */
|
||||
return ProgrammingError;
|
||||
}
|
||||
break;
|
||||
case '5':
|
||||
/* Class 53 - Insufficient Resources
|
||||
Class 54 - Program Limit Exceeded
|
||||
Class 55 - Object Not In Prerequisite State
|
||||
Class 57 - Operator Intervention
|
||||
Class 58 - System Error (errors external to PostgreSQL itself) */
|
||||
if (!strcmp(sqlstate, "57014"))
|
||||
return QueryCanceledError;
|
||||
else
|
||||
return OperationalError;
|
||||
case 'F': /* Class F0 - Configuration File Error */
|
||||
return InternalError;
|
||||
case 'H': /* Class HV - Foreign Data Wrapper Error (SQL/MED) */
|
||||
return OperationalError;
|
||||
case 'P': /* Class P0 - PL/pgSQL Error */
|
||||
return InternalError;
|
||||
case 'X': /* Class XX - Internal Error */
|
||||
return InternalError;
|
||||
}
|
||||
/* return DatabaseError as a fallback */
|
||||
return DatabaseError;
|
||||
}
|
||||
|
||||
/* pq_raise - raise a python exception of the right kind
|
||||
|
||||
|
|
|
@ -53,6 +53,9 @@ extern HIDDEN PyObject *Error, *Warning, *InterfaceError, *DatabaseError,
|
|||
*IntegrityError, *DataError, *NotSupportedError;
|
||||
extern HIDDEN PyObject *QueryCanceledError, *TransactionRollbackError;
|
||||
|
||||
/* sqlstate -> exception map */
|
||||
extern HIDDEN PyObject *sqlstate_errors;
|
||||
|
||||
/* postgresql<->python encoding map */
|
||||
extern HIDDEN PyObject *psycoEncodings;
|
||||
|
||||
|
|
|
@ -62,6 +62,8 @@
|
|||
#include "psycopg/adapter_datetime.h"
|
||||
|
||||
HIDDEN PyObject *psycoEncodings = NULL;
|
||||
HIDDEN PyObject *sqlstate_errors = NULL;
|
||||
|
||||
#ifdef PSYCOPG_DEBUG
|
||||
HIDDEN int psycopg_debug_enabled = 0;
|
||||
#endif
|
||||
|
@ -671,7 +673,7 @@ static struct {
|
|||
|
||||
|
||||
RAISES_NEG static int
|
||||
errors_init(PyObject *module)
|
||||
basic_errors_init(PyObject *module)
|
||||
{
|
||||
/* the names of the exceptions here reflect the organization of the
|
||||
psycopg2 module and not the fact the the original error objects
|
||||
|
@ -680,6 +682,7 @@ errors_init(PyObject *module)
|
|||
int i;
|
||||
PyObject *dict = NULL;
|
||||
PyObject *str = NULL;
|
||||
PyObject *errmodule = NULL;
|
||||
int rv = -1;
|
||||
|
||||
Dprintf("psycopgmodule: initializing basic exceptions");
|
||||
|
@ -707,6 +710,11 @@ errors_init(PyObject *module)
|
|||
Py_CLEAR(dict);
|
||||
}
|
||||
|
||||
if (!(errmodule = PyImport_ImportModule("psycopg2.errors"))) {
|
||||
/* don't inject the exceptions into the errors module */
|
||||
PyErr_Clear();
|
||||
}
|
||||
|
||||
for (i = 0; exctable[i].name; i++) {
|
||||
char *name;
|
||||
if (NULL == exctable[i].exc) { continue; }
|
||||
|
@ -720,17 +728,115 @@ errors_init(PyObject *module)
|
|||
Py_DECREF(*exctable[i].exc);
|
||||
goto exit;
|
||||
}
|
||||
if (errmodule) {
|
||||
Py_INCREF(*exctable[i].exc);
|
||||
if (0 > PyModule_AddObject(errmodule, name, *exctable[i].exc)) {
|
||||
Py_DECREF(*exctable[i].exc);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rv = 0;
|
||||
|
||||
exit:
|
||||
Py_XDECREF(errmodule);
|
||||
Py_XDECREF(str);
|
||||
Py_XDECREF(dict);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
/* mapping between sqlstate and exception name */
|
||||
static struct {
|
||||
char *sqlstate;
|
||||
char *name;
|
||||
} sqlstate_table[] = {
|
||||
#include "sqlstate_errors.h"
|
||||
{NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
|
||||
RAISES_NEG static int
|
||||
sqlstate_errors_init(PyObject *module)
|
||||
{
|
||||
int i;
|
||||
char namebuf[120];
|
||||
char prefix[] = "psycopg2.errors.";
|
||||
char *suffix;
|
||||
size_t bufsize;
|
||||
PyObject *exc = NULL;
|
||||
PyObject *errmodule = NULL;
|
||||
int rv = -1;
|
||||
|
||||
Dprintf("psycopgmodule: initializing sqlstate exceptions");
|
||||
|
||||
if (sqlstate_errors) {
|
||||
PyErr_SetString(PyExc_SystemError,
|
||||
"sqlstate_errors_init(): already called");
|
||||
goto exit;
|
||||
}
|
||||
if (!(errmodule = PyImport_ImportModule("psycopg2.errors"))) {
|
||||
/* don't inject the exceptions into the errors module */
|
||||
PyErr_Clear();
|
||||
}
|
||||
if (!(sqlstate_errors = PyDict_New())) {
|
||||
goto exit;
|
||||
}
|
||||
Py_INCREF(sqlstate_errors);
|
||||
if (0 > PyModule_AddObject(module, "sqlstate_errors", sqlstate_errors)) {
|
||||
Py_DECREF(sqlstate_errors);
|
||||
return -1;
|
||||
}
|
||||
|
||||
strcpy(namebuf, prefix);
|
||||
suffix = namebuf + sizeof(prefix) - 1;
|
||||
bufsize = sizeof(namebuf) - sizeof(prefix) - 1;
|
||||
/* If this 0 gets deleted the buffer was too small. */
|
||||
namebuf[sizeof(namebuf) - 1] = '\0';
|
||||
|
||||
for (i = 0; sqlstate_table[i].sqlstate; i++) {
|
||||
PyObject *base;
|
||||
|
||||
base = base_exception_from_sqlstate(sqlstate_table[i].sqlstate);
|
||||
strncpy(suffix, sqlstate_table[i].name, bufsize);
|
||||
if (namebuf[sizeof(namebuf) - 1] != '\0') {
|
||||
PyErr_SetString(
|
||||
PyExc_SystemError, "sqlstate_errors_init(): buffer too small");
|
||||
goto exit;
|
||||
}
|
||||
if (!(exc = PyErr_NewException(namebuf, base, NULL))) {
|
||||
goto exit;
|
||||
}
|
||||
if (0 > PyDict_SetItemString(
|
||||
sqlstate_errors, sqlstate_table[i].sqlstate, exc)) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Expose the exceptions to psycopg2.errors */
|
||||
if (errmodule) {
|
||||
if (0 > PyModule_AddObject(
|
||||
errmodule, sqlstate_table[i].name, exc)) {
|
||||
goto exit;
|
||||
}
|
||||
else {
|
||||
exc = NULL; /* ref stolen by the module */
|
||||
}
|
||||
}
|
||||
else {
|
||||
Py_CLEAR(exc);
|
||||
}
|
||||
}
|
||||
|
||||
rv = 0;
|
||||
|
||||
exit:
|
||||
Py_XDECREF(errmodule);
|
||||
Py_XDECREF(exc);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
RAISES_NEG static int
|
||||
add_module_constants(PyObject *module)
|
||||
{
|
||||
|
@ -1012,7 +1118,8 @@ INIT_MODULE(_psycopg)(void)
|
|||
if (0 > encodings_init(module)) { goto exit; }
|
||||
if (0 > typecast_init(module)) { goto exit; }
|
||||
if (0 > adapters_init(module)) { goto exit; }
|
||||
if (0 > errors_init(module)) { goto exit; }
|
||||
if (0 > basic_errors_init(module)) { goto exit; }
|
||||
if (0 > sqlstate_errors_init(module)) { goto exit; }
|
||||
|
||||
Dprintf("psycopgmodule: module initialization complete");
|
||||
|
||||
|
|
318
psycopg/sqlstate_errors.h
Normal file
318
psycopg/sqlstate_errors.h
Normal file
|
@ -0,0 +1,318 @@
|
|||
/*
|
||||
* Autogenerated by 'scripts/make_errors.py'.
|
||||
*/
|
||||
|
||||
|
||||
/* Class 02 - No Data (this is also a warning class per the SQL standard) */
|
||||
{"02000", "NoData"},
|
||||
{"02001", "NoAdditionalDynamicResultSetsReturned"},
|
||||
|
||||
/* Class 03 - SQL Statement Not Yet Complete */
|
||||
{"03000", "SqlStatementNotYetComplete"},
|
||||
|
||||
/* Class 08 - Connection Exception */
|
||||
{"08000", "ConnectionException"},
|
||||
{"08001", "SqlclientUnableToEstablishSqlconnection"},
|
||||
{"08003", "ConnectionDoesNotExist"},
|
||||
{"08004", "SqlserverRejectedEstablishmentOfSqlconnection"},
|
||||
{"08006", "ConnectionFailure"},
|
||||
{"08007", "TransactionResolutionUnknown"},
|
||||
{"08P01", "ProtocolViolation"},
|
||||
|
||||
/* Class 09 - Triggered Action Exception */
|
||||
{"09000", "TriggeredActionException"},
|
||||
|
||||
/* Class 0A - Feature Not Supported */
|
||||
{"0A000", "FeatureNotSupported"},
|
||||
|
||||
/* Class 0B - Invalid Transaction Initiation */
|
||||
{"0B000", "InvalidTransactionInitiation"},
|
||||
|
||||
/* Class 0F - Locator Exception */
|
||||
{"0F000", "LocatorException"},
|
||||
{"0F001", "InvalidLocatorSpecification"},
|
||||
|
||||
/* Class 0L - Invalid Grantor */
|
||||
{"0L000", "InvalidGrantor"},
|
||||
{"0LP01", "InvalidGrantOperation"},
|
||||
|
||||
/* Class 0P - Invalid Role Specification */
|
||||
{"0P000", "InvalidRoleSpecification"},
|
||||
|
||||
/* Class 0Z - Diagnostics Exception */
|
||||
{"0Z000", "DiagnosticsException"},
|
||||
{"0Z002", "StackedDiagnosticsAccessedWithoutActiveHandler"},
|
||||
|
||||
/* Class 20 - Case Not Found */
|
||||
{"20000", "CaseNotFound"},
|
||||
|
||||
/* Class 21 - Cardinality Violation */
|
||||
{"21000", "CardinalityViolation"},
|
||||
|
||||
/* Class 22 - Data Exception */
|
||||
{"22000", "DataException"},
|
||||
{"22001", "StringDataRightTruncation"},
|
||||
{"22002", "NullValueNoIndicatorParameter"},
|
||||
{"22003", "NumericValueOutOfRange"},
|
||||
{"22004", "NullValueNotAllowed"},
|
||||
{"22005", "ErrorInAssignment"},
|
||||
{"22007", "InvalidDatetimeFormat"},
|
||||
{"22008", "DatetimeFieldOverflow"},
|
||||
{"22009", "InvalidTimeZoneDisplacementValue"},
|
||||
{"2200B", "EscapeCharacterConflict"},
|
||||
{"2200C", "InvalidUseOfEscapeCharacter"},
|
||||
{"2200D", "InvalidEscapeOctet"},
|
||||
{"2200F", "ZeroLengthCharacterString"},
|
||||
{"2200G", "MostSpecificTypeMismatch"},
|
||||
{"2200H", "SequenceGeneratorLimitExceeded"},
|
||||
{"2200L", "NotAnXmlDocument"},
|
||||
{"2200M", "InvalidXmlDocument"},
|
||||
{"2200N", "InvalidXmlContent"},
|
||||
{"2200S", "InvalidXmlComment"},
|
||||
{"2200T", "InvalidXmlProcessingInstruction"},
|
||||
{"22010", "InvalidIndicatorParameterValue"},
|
||||
{"22011", "SubstringError"},
|
||||
{"22012", "DivisionByZero"},
|
||||
{"22013", "InvalidPrecedingOrFollowingSize"},
|
||||
{"22014", "InvalidArgumentForNtileFunction"},
|
||||
{"22015", "IntervalFieldOverflow"},
|
||||
{"22016", "InvalidArgumentForNthValueFunction"},
|
||||
{"22018", "InvalidCharacterValueForCast"},
|
||||
{"22019", "InvalidEscapeCharacter"},
|
||||
{"2201B", "InvalidRegularExpression"},
|
||||
{"2201E", "InvalidArgumentForLogarithm"},
|
||||
{"2201F", "InvalidArgumentForPowerFunction"},
|
||||
{"2201G", "InvalidArgumentForWidthBucketFunction"},
|
||||
{"2201W", "InvalidRowCountInLimitClause"},
|
||||
{"2201X", "InvalidRowCountInResultOffsetClause"},
|
||||
{"22021", "CharacterNotInRepertoire"},
|
||||
{"22022", "IndicatorOverflow"},
|
||||
{"22023", "InvalidParameterValue"},
|
||||
{"22024", "UnterminatedCString"},
|
||||
{"22025", "InvalidEscapeSequence"},
|
||||
{"22026", "StringDataLengthMismatch"},
|
||||
{"22027", "TrimError"},
|
||||
{"2202E", "ArraySubscriptError"},
|
||||
{"2202G", "InvalidTablesampleRepeat"},
|
||||
{"2202H", "InvalidTablesampleArgument"},
|
||||
{"22P01", "FloatingPointException"},
|
||||
{"22P02", "InvalidTextRepresentation"},
|
||||
{"22P03", "InvalidBinaryRepresentation"},
|
||||
{"22P04", "BadCopyFileFormat"},
|
||||
{"22P05", "UntranslatableCharacter"},
|
||||
{"22P06", "NonstandardUseOfEscapeCharacter"},
|
||||
|
||||
/* Class 23 - Integrity Constraint Violation */
|
||||
{"23000", "IntegrityConstraintViolation"},
|
||||
{"23001", "RestrictViolation"},
|
||||
{"23502", "NotNullViolation"},
|
||||
{"23503", "ForeignKeyViolation"},
|
||||
{"23505", "UniqueViolation"},
|
||||
{"23514", "CheckViolation"},
|
||||
{"23P01", "ExclusionViolation"},
|
||||
|
||||
/* Class 24 - Invalid Cursor State */
|
||||
{"24000", "InvalidCursorState"},
|
||||
|
||||
/* Class 25 - Invalid Transaction State */
|
||||
{"25000", "InvalidTransactionState"},
|
||||
{"25001", "ActiveSqlTransaction"},
|
||||
{"25002", "BranchTransactionAlreadyActive"},
|
||||
{"25003", "InappropriateAccessModeForBranchTransaction"},
|
||||
{"25004", "InappropriateIsolationLevelForBranchTransaction"},
|
||||
{"25005", "NoActiveSqlTransactionForBranchTransaction"},
|
||||
{"25006", "ReadOnlySqlTransaction"},
|
||||
{"25007", "SchemaAndDataStatementMixingNotSupported"},
|
||||
{"25008", "HeldCursorRequiresSameIsolationLevel"},
|
||||
{"25P01", "NoActiveSqlTransaction"},
|
||||
{"25P02", "InFailedSqlTransaction"},
|
||||
{"25P03", "IdleInTransactionSessionTimeout"},
|
||||
|
||||
/* Class 26 - Invalid SQL Statement Name */
|
||||
{"26000", "InvalidSqlStatementName"},
|
||||
|
||||
/* Class 27 - Triggered Data Change Violation */
|
||||
{"27000", "TriggeredDataChangeViolation"},
|
||||
|
||||
/* Class 28 - Invalid Authorization Specification */
|
||||
{"28000", "InvalidAuthorizationSpecification"},
|
||||
{"28P01", "InvalidPassword"},
|
||||
|
||||
/* Class 2B - Dependent Privilege Descriptors Still Exist */
|
||||
{"2B000", "DependentPrivilegeDescriptorsStillExist"},
|
||||
{"2BP01", "DependentObjectsStillExist"},
|
||||
|
||||
/* Class 2D - Invalid Transaction Termination */
|
||||
{"2D000", "InvalidTransactionTermination"},
|
||||
|
||||
/* Class 2F - SQL Routine Exception */
|
||||
{"2F000", "SqlRoutineException"},
|
||||
{"2F002", "ModifyingSqlDataNotPermitted"},
|
||||
{"2F003", "ProhibitedSqlStatementAttempted"},
|
||||
{"2F004", "ReadingSqlDataNotPermitted"},
|
||||
{"2F005", "FunctionExecutedNoReturnStatement"},
|
||||
|
||||
/* Class 34 - Invalid Cursor Name */
|
||||
{"34000", "InvalidCursorName"},
|
||||
|
||||
/* Class 38 - External Routine Exception */
|
||||
{"38000", "ExternalRoutineException"},
|
||||
{"38001", "ContainingSqlNotPermitted"},
|
||||
{"38002", "ModifyingSqlDataNotPermittedExt"},
|
||||
{"38003", "ProhibitedSqlStatementAttemptedExt"},
|
||||
{"38004", "ReadingSqlDataNotPermittedExt"},
|
||||
|
||||
/* Class 39 - External Routine Invocation Exception */
|
||||
{"39000", "ExternalRoutineInvocationException"},
|
||||
{"39001", "InvalidSqlstateReturned"},
|
||||
{"39004", "NullValueNotAllowedExt"},
|
||||
{"39P01", "TriggerProtocolViolated"},
|
||||
{"39P02", "SrfProtocolViolated"},
|
||||
{"39P03", "EventTriggerProtocolViolated"},
|
||||
|
||||
/* Class 3B - Savepoint Exception */
|
||||
{"3B000", "SavepointException"},
|
||||
{"3B001", "InvalidSavepointSpecification"},
|
||||
|
||||
/* Class 3D - Invalid Catalog Name */
|
||||
{"3D000", "InvalidCatalogName"},
|
||||
|
||||
/* Class 3F - Invalid Schema Name */
|
||||
{"3F000", "InvalidSchemaName"},
|
||||
|
||||
/* Class 40 - Transaction Rollback */
|
||||
{"40000", "TransactionRollback"},
|
||||
{"40001", "SerializationFailure"},
|
||||
{"40002", "TransactionIntegrityConstraintViolation"},
|
||||
{"40003", "StatementCompletionUnknown"},
|
||||
{"40P01", "DeadlockDetected"},
|
||||
|
||||
/* Class 42 - Syntax Error or Access Rule Violation */
|
||||
{"42000", "SyntaxErrorOrAccessRuleViolation"},
|
||||
{"42501", "InsufficientPrivilege"},
|
||||
{"42601", "SyntaxError"},
|
||||
{"42602", "InvalidName"},
|
||||
{"42611", "InvalidColumnDefinition"},
|
||||
{"42622", "NameTooLong"},
|
||||
{"42701", "DuplicateColumn"},
|
||||
{"42702", "AmbiguousColumn"},
|
||||
{"42703", "UndefinedColumn"},
|
||||
{"42704", "UndefinedObject"},
|
||||
{"42710", "DuplicateObject"},
|
||||
{"42712", "DuplicateAlias"},
|
||||
{"42723", "DuplicateFunction"},
|
||||
{"42725", "AmbiguousFunction"},
|
||||
{"42803", "GroupingError"},
|
||||
{"42804", "DatatypeMismatch"},
|
||||
{"42809", "WrongObjectType"},
|
||||
{"42830", "InvalidForeignKey"},
|
||||
{"42846", "CannotCoerce"},
|
||||
{"42883", "UndefinedFunction"},
|
||||
{"428C9", "GeneratedAlways"},
|
||||
{"42939", "ReservedName"},
|
||||
{"42P01", "UndefinedTable"},
|
||||
{"42P02", "UndefinedParameter"},
|
||||
{"42P03", "DuplicateCursor"},
|
||||
{"42P04", "DuplicateDatabase"},
|
||||
{"42P05", "DuplicatePreparedStatement"},
|
||||
{"42P06", "DuplicateSchema"},
|
||||
{"42P07", "DuplicateTable"},
|
||||
{"42P08", "AmbiguousParameter"},
|
||||
{"42P09", "AmbiguousAlias"},
|
||||
{"42P10", "InvalidColumnReference"},
|
||||
{"42P11", "InvalidCursorDefinition"},
|
||||
{"42P12", "InvalidDatabaseDefinition"},
|
||||
{"42P13", "InvalidFunctionDefinition"},
|
||||
{"42P14", "InvalidPreparedStatementDefinition"},
|
||||
{"42P15", "InvalidSchemaDefinition"},
|
||||
{"42P16", "InvalidTableDefinition"},
|
||||
{"42P17", "InvalidObjectDefinition"},
|
||||
{"42P18", "IndeterminateDatatype"},
|
||||
{"42P19", "InvalidRecursion"},
|
||||
{"42P20", "WindowingError"},
|
||||
{"42P21", "CollationMismatch"},
|
||||
{"42P22", "IndeterminateCollation"},
|
||||
|
||||
/* Class 44 - WITH CHECK OPTION Violation */
|
||||
{"44000", "WithCheckOptionViolation"},
|
||||
|
||||
/* Class 53 - Insufficient Resources */
|
||||
{"53000", "InsufficientResources"},
|
||||
{"53100", "DiskFull"},
|
||||
{"53200", "OutOfMemory"},
|
||||
{"53300", "TooManyConnections"},
|
||||
{"53400", "ConfigurationLimitExceeded"},
|
||||
|
||||
/* Class 54 - Program Limit Exceeded */
|
||||
{"54000", "ProgramLimitExceeded"},
|
||||
{"54001", "StatementTooComplex"},
|
||||
{"54011", "TooManyColumns"},
|
||||
{"54023", "TooManyArguments"},
|
||||
|
||||
/* Class 55 - Object Not In Prerequisite State */
|
||||
{"55000", "ObjectNotInPrerequisiteState"},
|
||||
{"55006", "ObjectInUse"},
|
||||
{"55P02", "CantChangeRuntimeParam"},
|
||||
{"55P03", "LockNotAvailable"},
|
||||
|
||||
/* Class 57 - Operator Intervention */
|
||||
{"57000", "OperatorIntervention"},
|
||||
{"57014", "QueryCanceled"},
|
||||
{"57P01", "AdminShutdown"},
|
||||
{"57P02", "CrashShutdown"},
|
||||
{"57P03", "CannotConnectNow"},
|
||||
{"57P04", "DatabaseDropped"},
|
||||
|
||||
/* Class 58 - System Error (errors external to PostgreSQL itself) */
|
||||
{"58000", "SystemError"},
|
||||
{"58030", "IoError"},
|
||||
{"58P01", "UndefinedFile"},
|
||||
{"58P02", "DuplicateFile"},
|
||||
|
||||
/* Class 72 - Snapshot Failure */
|
||||
{"72000", "SnapshotTooOld"},
|
||||
|
||||
/* Class F0 - Configuration File Error */
|
||||
{"F0000", "ConfigFileError"},
|
||||
{"F0001", "LockFileExists"},
|
||||
|
||||
/* Class HV - Foreign Data Wrapper Error (SQL/MED) */
|
||||
{"HV000", "FdwError"},
|
||||
{"HV001", "FdwOutOfMemory"},
|
||||
{"HV002", "FdwDynamicParameterValueNeeded"},
|
||||
{"HV004", "FdwInvalidDataType"},
|
||||
{"HV005", "FdwColumnNameNotFound"},
|
||||
{"HV006", "FdwInvalidDataTypeDescriptors"},
|
||||
{"HV007", "FdwInvalidColumnName"},
|
||||
{"HV008", "FdwInvalidColumnNumber"},
|
||||
{"HV009", "FdwInvalidUseOfNullPointer"},
|
||||
{"HV00A", "FdwInvalidStringFormat"},
|
||||
{"HV00B", "FdwInvalidHandle"},
|
||||
{"HV00C", "FdwInvalidOptionIndex"},
|
||||
{"HV00D", "FdwInvalidOptionName"},
|
||||
{"HV00J", "FdwOptionNameNotFound"},
|
||||
{"HV00K", "FdwReplyHandle"},
|
||||
{"HV00L", "FdwUnableToCreateExecution"},
|
||||
{"HV00M", "FdwUnableToCreateReply"},
|
||||
{"HV00N", "FdwUnableToEstablishConnection"},
|
||||
{"HV00P", "FdwNoSchemas"},
|
||||
{"HV00Q", "FdwSchemaNotFound"},
|
||||
{"HV00R", "FdwTableNotFound"},
|
||||
{"HV010", "FdwFunctionSequenceError"},
|
||||
{"HV014", "FdwTooManyHandles"},
|
||||
{"HV021", "FdwInconsistentDescriptorInformation"},
|
||||
{"HV024", "FdwInvalidAttributeValue"},
|
||||
{"HV090", "FdwInvalidStringLengthOrBufferLength"},
|
||||
{"HV091", "FdwInvalidDescriptorFieldIdentifier"},
|
||||
|
||||
/* Class P0 - PL/pgSQL Error */
|
||||
{"P0000", "PlpgsqlError"},
|
||||
{"P0001", "RaiseException"},
|
||||
{"P0002", "NoDataFound"},
|
||||
{"P0003", "TooManyRows"},
|
||||
{"P0004", "AssertFailure"},
|
||||
|
||||
/* Class XX - Internal Error */
|
||||
{"XX000", "InternalError_"},
|
||||
{"XX001", "DataCorrupted"},
|
||||
{"XX002", "IndexCorrupted"},
|
|
@ -17,6 +17,7 @@ The script can be run at a new PostgreSQL release to refresh the module.
|
|||
# License for more details.
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import urllib2
|
||||
|
@ -24,34 +25,19 @@ from collections import defaultdict
|
|||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) != 2:
|
||||
print("usage: %s /path/to/errors.py" % sys.argv[0], file=sys.stderr)
|
||||
return 2
|
||||
filename = os.path.join(
|
||||
os.path.dirname(__file__), "../psycopg/sqlstate_errors.h")
|
||||
|
||||
filename = sys.argv[1]
|
||||
|
||||
file_start = read_base_file(filename)
|
||||
# If you add a version to the list fix the docs (in errors.rst)
|
||||
classes, errors = fetch_errors(
|
||||
['9.1', '9.2', '9.3', '9.4', '9.5', '9.6', '10', '11'])
|
||||
|
||||
f = open(filename, "w")
|
||||
for line in file_start:
|
||||
print(line, file=f)
|
||||
print("/*\n * Autogenerated by 'scripts/make_errors.py'.\n */\n", file=f)
|
||||
for line in generate_module_data(classes, errors):
|
||||
print(line, file=f)
|
||||
|
||||
|
||||
def read_base_file(filename):
|
||||
rv = []
|
||||
for line in open(filename):
|
||||
rv.append(line.rstrip("\n"))
|
||||
if line.startswith("# autogenerated"):
|
||||
return rv
|
||||
|
||||
raise ValueError("can't find the separator. Is this the right file?")
|
||||
|
||||
|
||||
def parse_errors_txt(url):
|
||||
classes = {}
|
||||
errors = defaultdict(dict)
|
||||
|
@ -112,12 +98,7 @@ def fetch_errors(versions):
|
|||
|
||||
|
||||
def generate_module_data(classes, errors):
|
||||
tmpl = """
|
||||
|
||||
@for_sqlstate(%(errcode)r)
|
||||
class %(cls)s(%(base)s):
|
||||
pass\
|
||||
"""
|
||||
tmpl = '{"%(errcode)s", "%(cls)s"},'
|
||||
specific = {
|
||||
'38002': 'ModifyingSqlDataNotPermittedExt',
|
||||
'38003': 'ProhibitedSqlStatementAttemptedExt',
|
||||
|
@ -137,7 +118,7 @@ class %(cls)s(%(base)s):
|
|||
# success and warning - never raised
|
||||
continue
|
||||
|
||||
yield "\n\n# %s" % clslabel
|
||||
yield "\n/* %s */" % clslabel
|
||||
|
||||
for errcode, errlabel in sorted(errors[clscode].items()):
|
||||
if errcode in specific:
|
||||
|
@ -150,81 +131,9 @@ class %(cls)s(%(base)s):
|
|||
|
||||
yield tmpl % {
|
||||
'cls': clsname,
|
||||
'base': get_base_class_name(errcode),
|
||||
'errcode': errcode
|
||||
}
|
||||
|
||||
|
||||
def get_base_class_name(errcode):
|
||||
"""
|
||||
This is a python porting of exception_from_sqlstate code in pqpath.c
|
||||
"""
|
||||
if errcode[0] == '0':
|
||||
if errcode[1] == 'A': # Class 0A - Feature Not Supported
|
||||
return 'NotSupportedError'
|
||||
elif errcode[0] == '2':
|
||||
if errcode[1] in '01':
|
||||
# Class 20 - Case Not Found
|
||||
# Class 21 - Cardinality Violation
|
||||
return 'ProgrammingError'
|
||||
elif errcode[1] == '2': # Class 22 - Data Exception
|
||||
return 'DataError'
|
||||
elif errcode[1] == '3': # Class 23 - Integrity Constraint Violation
|
||||
return 'IntegrityError'
|
||||
elif errcode[1] in '45':
|
||||
# Class 24 - Invalid Cursor State
|
||||
# Class 25 - Invalid Transaction State
|
||||
return 'InternalError'
|
||||
elif errcode[1] in '678':
|
||||
# Class 26 - Invalid SQL Statement Name
|
||||
# Class 27 - Triggered Data Change Violation
|
||||
# Class 28 - Invalid Authorization Specification
|
||||
return 'OperationalError'
|
||||
elif errcode[1] in 'BDF':
|
||||
# Class 2B - Dependent Privilege Descriptors Still Exist
|
||||
# Class 2D - Invalid Transaction Termination
|
||||
# Class 2F - SQL Routine Exception
|
||||
return 'InternalError'
|
||||
elif errcode[0] == '3':
|
||||
if errcode[1] == '4': # Class 34 - Invalid Cursor Name
|
||||
return 'OperationalError'
|
||||
if errcode[1] in '89B':
|
||||
# Class 38 - External Routine Exception
|
||||
# Class 39 - External Routine Invocation Exception
|
||||
# Class 3B - Savepoint Exception
|
||||
return 'InternalError'
|
||||
if errcode[1] in 'DF':
|
||||
# Class 3D - Invalid Catalog Name
|
||||
# Class 3F - Invalid Schema Name
|
||||
return 'ProgrammingError'
|
||||
elif errcode[0] == '4':
|
||||
if errcode[1] == '0': # Class 40 - Transaction Rollback
|
||||
return 'TransactionRollbackError'
|
||||
if errcode[1] in '24':
|
||||
# Class 42 - Syntax Error or Access Rule Violation
|
||||
# Class 44 - WITH CHECK OPTION Violation
|
||||
return 'ProgrammingError'
|
||||
elif errcode[0] == '5':
|
||||
if errcode == "57014":
|
||||
return 'QueryCanceledError'
|
||||
# Class 53 - Insufficient Resources
|
||||
# Class 54 - Program Limit Exceeded
|
||||
# Class 55 - Object Not In Prerequisite State
|
||||
# Class 57 - Operator Intervention
|
||||
# Class 58 - System Error (errors external to PostgreSQL itself)
|
||||
else:
|
||||
return 'OperationalError'
|
||||
elif errcode[0] == 'F': # Class F0 - Configuration File Error
|
||||
return 'InternalError'
|
||||
elif errcode[0] == 'H': # Class HV - Foreign Data Wrapper Error (SQL/MED)
|
||||
return 'OperationalError'
|
||||
elif errcode[0] == 'P': # Class P0 - PL/pgSQL Error
|
||||
return 'InternalError'
|
||||
elif errcode[0] == 'X': # Class XX - Internal Error
|
||||
return 'InternalError'
|
||||
|
||||
return 'DatabaseError'
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
|
|
2
setup.py
2
setup.py
|
@ -515,7 +515,7 @@ depends = [
|
|||
'adapter_list.h', 'adapter_pboolean.h', 'adapter_pdecimal.h',
|
||||
'adapter_pint.h', 'adapter_pfloat.h', 'adapter_qstring.h',
|
||||
'microprotocols.h', 'microprotocols_proto.h',
|
||||
'typecast.h', 'typecast_binary.h',
|
||||
'typecast.h', 'typecast_binary.h', 'sqlstate_errors.h',
|
||||
|
||||
# included sources
|
||||
'typecast_array.c', 'typecast_basic.c', 'typecast_binary.c',
|
||||
|
|
|
@ -43,14 +43,14 @@ class ErrorsTests(ConnectingTestCase):
|
|||
def test_exception_class_fallback(self):
|
||||
cur = self.conn.cursor()
|
||||
|
||||
from psycopg2 import errors
|
||||
x = errors._by_sqlstate.pop('42P01')
|
||||
from psycopg2._psycopg import sqlstate_errors
|
||||
x = sqlstate_errors.pop('42P01')
|
||||
try:
|
||||
cur.execute("select * from nonexist")
|
||||
except psycopg2.Error as exc:
|
||||
e = exc
|
||||
finally:
|
||||
errors._by_sqlstate['42P01'] = x
|
||||
sqlstate_errors['42P01'] = x
|
||||
|
||||
self.assertEqual(type(e), self.conn.ProgrammingError)
|
||||
|
||||
|
@ -62,6 +62,25 @@ class ErrorsTests(ConnectingTestCase):
|
|||
with self.assertRaises(KeyError):
|
||||
errors.lookup('XXXXX')
|
||||
|
||||
def test_has_base_exceptions(self):
|
||||
import psycopg2
|
||||
from psycopg2 import errors
|
||||
|
||||
excs = []
|
||||
for n in dir(psycopg2):
|
||||
obj = getattr(psycopg2, n)
|
||||
if isinstance(obj, type) and issubclass(obj, Exception):
|
||||
excs.append(obj)
|
||||
|
||||
self.assert_(len(excs) > 8, str(excs))
|
||||
|
||||
excs.append(psycopg2.extensions.QueryCanceledError)
|
||||
excs.append(psycopg2.extensions.TransactionRollbackError)
|
||||
|
||||
for exc in excs:
|
||||
self.assert_(hasattr(errors, exc.__name__))
|
||||
self.assert_(getattr(errors, exc.__name__) is exc)
|
||||
|
||||
|
||||
def test_suite():
|
||||
return unittest.TestLoader().loadTestsFromName(__name__)
|
||||
|
|
Loading…
Reference in New Issue
Block a user