-
-
Notifications
You must be signed in to change notification settings - Fork 33.8k
bpo-16379: expose SQLite error codes and error names in sqlite3
#27786
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 30 commits
83ab267
eeb10f4
42636f9
f224223
31467e3
679280d
8aa0859
e4195c0
a4a0762
c18d227
67e49e8
1893ced
67ea5f2
6ced38c
467f7ba
4abd093
70507dd
b617192
db053b9
98106dd
0567938
16889a1
a7a1cf8
772a29c
fa5a1af
cf551b1
a3646c9
8a49659
8d11bc5
7a69798
b9a5a77
3589a6a
a3c45b6
5a5683c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| Add SQLite error code and name to :mod:`sqlite3` exceptions. | ||
| Patch by Aviv Palivoda, Daniel Shahaf, and Erlend E. Aasland. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -36,27 +36,18 @@ pysqlite_step(sqlite3_stmt *statement) | |
| return rc; | ||
| } | ||
|
|
||
| /** | ||
| * Checks the SQLite error code and sets the appropriate DB-API exception. | ||
| * Returns the error code (0 means no error occurred). | ||
| */ | ||
| int | ||
| _pysqlite_seterror(pysqlite_state *state, sqlite3 *db) | ||
| static PyObject * | ||
| get_exception_class(pysqlite_state *state, int errorcode) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is slighly confusing because normally returning seems that is handling an error
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I see now that it can be a bit confusing. I'll add a comment. Thanks!
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| { | ||
| int errorcode = sqlite3_errcode(db); | ||
|
|
||
| switch (errorcode) | ||
| { | ||
| switch (errorcode) { | ||
| case SQLITE_OK: | ||
| PyErr_Clear(); | ||
| break; | ||
| return NULL; | ||
| case SQLITE_INTERNAL: | ||
| case SQLITE_NOTFOUND: | ||
| PyErr_SetString(state->InternalError, sqlite3_errmsg(db)); | ||
| break; | ||
| return state->InternalError; | ||
| case SQLITE_NOMEM: | ||
| (void)PyErr_NoMemory(); | ||
| break; | ||
| return PyErr_NoMemory(); | ||
| case SQLITE_ERROR: | ||
| case SQLITE_PERM: | ||
| case SQLITE_ABORT: | ||
|
|
@@ -70,26 +61,84 @@ _pysqlite_seterror(pysqlite_state *state, sqlite3 *db) | |
| case SQLITE_PROTOCOL: | ||
| case SQLITE_EMPTY: | ||
| case SQLITE_SCHEMA: | ||
| PyErr_SetString(state->OperationalError, sqlite3_errmsg(db)); | ||
| break; | ||
| return state->OperationalError; | ||
| case SQLITE_CORRUPT: | ||
| PyErr_SetString(state->DatabaseError, sqlite3_errmsg(db)); | ||
| break; | ||
| return state->DatabaseError; | ||
| case SQLITE_TOOBIG: | ||
| PyErr_SetString(state->DataError, sqlite3_errmsg(db)); | ||
| break; | ||
| return state->DataError; | ||
| case SQLITE_CONSTRAINT: | ||
| case SQLITE_MISMATCH: | ||
| PyErr_SetString(state->IntegrityError, sqlite3_errmsg(db)); | ||
| break; | ||
| return state->IntegrityError; | ||
| case SQLITE_MISUSE: | ||
| PyErr_SetString(state->ProgrammingError, sqlite3_errmsg(db)); | ||
| break; | ||
| return state->ProgrammingError; | ||
| default: | ||
| PyErr_SetString(state->DatabaseError, sqlite3_errmsg(db)); | ||
| break; | ||
| return state->DatabaseError; | ||
| } | ||
| } | ||
|
|
||
| static void | ||
| raise_exception(PyObject *type, int errcode, const char *errmsg) | ||
| { | ||
| PyObject *exc = NULL; | ||
| PyObject *args[] = { PyUnicode_FromString(errmsg), }; | ||
| if (args[0] == NULL) { | ||
| goto exit; | ||
| } | ||
| exc = PyObject_Vectorcall(type, args, 1, NULL); | ||
| Py_DECREF(args[0]); | ||
| if (exc == NULL) { | ||
| goto exit; | ||
| } | ||
|
|
||
| PyObject *code = PyLong_FromLong(errcode); | ||
| if (code == NULL) { | ||
| goto exit; | ||
| } | ||
| int rc = PyObject_SetAttrString(exc, "sqlite_errorcode", code); | ||
| Py_DECREF(code); | ||
| if (rc < 0) { | ||
| goto exit; | ||
| } | ||
|
|
||
| const char *error_name = pysqlite_error_name(errcode); | ||
| PyObject *name; | ||
| if (error_name) { | ||
| name = PyUnicode_FromString(error_name); | ||
| } | ||
| else { | ||
| name = PyUnicode_InternFromString("unknown"); | ||
| } | ||
| if (name == NULL) { | ||
| goto exit; | ||
| } | ||
| rc = PyObject_SetAttrString(exc, "sqlite_errorname", name); | ||
| Py_DECREF(name); | ||
| if (rc < 0) { | ||
| goto exit; | ||
| } | ||
|
|
||
| PyErr_SetObject(type, exc); | ||
|
|
||
| exit: | ||
| Py_XDECREF(exc); | ||
| } | ||
|
|
||
| /** | ||
| * Checks the SQLite error code and sets the appropriate DB-API exception. | ||
| * Returns the error code (0 means no error occurred). | ||
| */ | ||
| int | ||
| _pysqlite_seterror(pysqlite_state *state, sqlite3 *db) | ||
| { | ||
| int errorcode = sqlite3_errcode(db); | ||
| PyObject *exc_class = get_exception_class(state, errorcode); | ||
| if (exc_class == NULL) { | ||
| return errorcode; | ||
| } | ||
|
|
||
| /* Create and set the exception. */ | ||
| const char *errmsg = sqlite3_errmsg(db); | ||
| raise_exception(exc_class, errorcode, errmsg); | ||
| return errorcode; | ||
| } | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.