diff options
Diffstat (limited to 'Modules/_sqlite')
| -rw-r--r-- | Modules/_sqlite/cache.c | 1 | ||||
| -rw-r--r-- | Modules/_sqlite/connection.c | 109 | ||||
| -rw-r--r-- | Modules/_sqlite/cursor.c | 17 | ||||
| -rw-r--r-- | Modules/_sqlite/module.c | 16 | ||||
| -rw-r--r-- | Modules/_sqlite/prepare_protocol.c | 1 | ||||
| -rw-r--r-- | Modules/_sqlite/row.c | 14 | ||||
| -rw-r--r-- | Modules/_sqlite/sqlitecompat.h | 63 | ||||
| -rw-r--r-- | Modules/_sqlite/statement.c | 33 | ||||
| -rw-r--r-- | Modules/_sqlite/util.c | 2 |
9 files changed, 135 insertions, 121 deletions
diff --git a/Modules/_sqlite/cache.c b/Modules/_sqlite/cache.c index 3693363..3689a4e 100644 --- a/Modules/_sqlite/cache.c +++ b/Modules/_sqlite/cache.c @@ -21,7 +21,6 @@ * 3. This notice may not be removed or altered from any source distribution. */ -#include "sqlitecompat.h" #include "cache.h" #include <limits.h> diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index 8cf2d6a..882424b 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -29,7 +29,6 @@ #include "cursor.h" #include "prepare_protocol.h" #include "util.h" -#include "sqlitecompat.h" #include "pythread.h" @@ -42,6 +41,8 @@ #endif #endif +_Py_IDENTIFIER(cursor); + static int pysqlite_connection_set_isolation_level(pysqlite_Connection* self, PyObject* isolation_level); static void _pysqlite_drop_unused_cursor_references(pysqlite_Connection* self); @@ -60,7 +61,11 @@ static void _sqlite3_result_error(sqlite3_context* ctx, const char* errmsg, int int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) { - static char *kwlist[] = {"database", "timeout", "detect_types", "isolation_level", "check_same_thread", "factory", "cached_statements", NULL, NULL}; + static char *kwlist[] = { + "database", "timeout", "detect_types", "isolation_level", + "check_same_thread", "factory", "cached_statements", "uri", + NULL + }; char* database; int detect_types = 0; @@ -68,11 +73,14 @@ int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject PyObject* factory = NULL; int check_same_thread = 1; int cached_statements = 100; + int uri = 0; double timeout = 5.0; int rc; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|diOiOi", kwlist, - &database, &timeout, &detect_types, &isolation_level, &check_same_thread, &factory, &cached_statements)) + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|diOiOip", kwlist, + &database, &timeout, &detect_types, + &isolation_level, &check_same_thread, + &factory, &cached_statements, &uri)) { return -1; } @@ -91,8 +99,19 @@ int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject Py_INCREF(&PyUnicode_Type); self->text_factory = (PyObject*)&PyUnicode_Type; +#ifdef SQLITE_OPEN_URI + Py_BEGIN_ALLOW_THREADS + rc = sqlite3_open_v2(database, &self->db, + SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | + (uri ? SQLITE_OPEN_URI : 0), NULL); +#else + if (uri) { + PyErr_SetString(pysqlite_NotSupportedError, "URIs not supported"); + return -1; + } Py_BEGIN_ALLOW_THREADS rc = sqlite3_open(database, &self->db); +#endif Py_END_ALLOW_THREADS if (rc != SQLITE_OK) { @@ -506,10 +525,16 @@ _pysqlite_set_result(sqlite3_context* context, PyObject* py_val) const char* buffer; Py_ssize_t buflen; if (PyObject_AsCharBuffer(py_val, &buffer, &buflen) != 0) { - PyErr_SetString(PyExc_ValueError, "could not convert BLOB to buffer"); + PyErr_SetString(PyExc_ValueError, + "could not convert BLOB to buffer"); return -1; } - sqlite3_result_blob(context, buffer, buflen, SQLITE_TRANSIENT); + if (buflen > INT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "BLOB longer than INT_MAX bytes"); + return -1; + } + sqlite3_result_blob(context, buffer, (int)buflen, SQLITE_TRANSIENT); } else { return -1; } @@ -682,6 +707,8 @@ void _pysqlite_final_callback(sqlite3_context* context) PyObject** aggregate_instance; _Py_IDENTIFIER(finalize); int ok; + PyObject *exception, *value, *tb; + int restore; #ifdef WITH_THREAD PyGILState_STATE threadstate; @@ -697,7 +724,12 @@ void _pysqlite_final_callback(sqlite3_context* context) goto error; } + /* Keep the exception (if any) of the last call to step() */ + PyErr_Fetch(&exception, &value, &tb); + restore = 1; + function_result = _PyObject_CallMethodId(*aggregate_instance, &PyId_finalize, ""); + Py_DECREF(*aggregate_instance); ok = 0; @@ -712,6 +744,17 @@ void _pysqlite_final_callback(sqlite3_context* context) PyErr_Clear(); } _sqlite3_result_error(context, "user-defined aggregate's 'finalize' method raised error", -1); +#if SQLITE_VERSION_NUMBER < 3003003 + /* with old SQLite versions, _sqlite3_result_error() sets a new Python + exception, so don't restore the previous exception */ + restore = 0; +#endif + } + + if (restore) { + /* Restore the exception (if any) of the last call to step(), + but clear also the current exception if finalize() failed */ + PyErr_Restore(exception, value, tb); } error: @@ -862,22 +905,29 @@ static int _authorizer_callback(void* user_arg, int action, const char* arg1, co gilstate = PyGILState_Ensure(); #endif + ret = PyObject_CallFunction((PyObject*)user_arg, "issss", action, arg1, arg2, dbname, access_attempt_source); - if (!ret) { - if (_enable_callback_tracebacks) { + if (ret == NULL) { + if (_enable_callback_tracebacks) PyErr_Print(); - } else { + else PyErr_Clear(); - } rc = SQLITE_DENY; - } else { + } + else { if (PyLong_Check(ret)) { rc = _PyLong_AsInt(ret); - if (rc == -1 && PyErr_Occurred()) + if (rc == -1 && PyErr_Occurred()) { + if (_enable_callback_tracebacks) + PyErr_Print(); + else + PyErr_Clear(); rc = SQLITE_DENY; - } else { + } + } + else { rc = SQLITE_DENY; } Py_DECREF(ret); @@ -1190,9 +1240,8 @@ PyObject* pysqlite_connection_call(pysqlite_Connection* self, PyObject* args, Py return NULL; } - if (!PyArg_ParseTuple(args, "O", &sql)) { + if (!PyArg_ParseTuple(args, "O", &sql)) return NULL; - } _pysqlite_drop_unused_statement_references(self); @@ -1208,7 +1257,6 @@ PyObject* pysqlite_connection_call(pysqlite_Connection* self, PyObject* args, Py statement->in_weakreflist = NULL; rc = pysqlite_statement_create(statement, self, sql); - if (rc != SQLITE_OK) { if (rc == PYSQLITE_TOO_MUCH_SQL) { PyErr_SetString(pysqlite_Warning, "You can only execute one statement at a time."); @@ -1218,25 +1266,23 @@ PyObject* pysqlite_connection_call(pysqlite_Connection* self, PyObject* args, Py (void)pysqlite_statement_reset(statement); _pysqlite_seterror(self->db, NULL); } + goto error; + } - Py_CLEAR(statement); - } else { - weakref = PyWeakref_NewRef((PyObject*)statement, NULL); - if (!weakref) { - Py_CLEAR(statement); - goto error; - } - - if (PyList_Append(self->statements, weakref) != 0) { - Py_CLEAR(weakref); - goto error; - } - + weakref = PyWeakref_NewRef((PyObject*)statement, NULL); + if (weakref == NULL) + goto error; + if (PyList_Append(self->statements, weakref) != 0) { Py_DECREF(weakref); + goto error; } + Py_DECREF(weakref); -error: return (PyObject*)statement; + +error: + Py_DECREF(statement); + return NULL; } PyObject* pysqlite_connection_execute(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) @@ -1244,7 +1290,6 @@ PyObject* pysqlite_connection_execute(pysqlite_Connection* self, PyObject* args, PyObject* cursor = 0; PyObject* result = 0; PyObject* method = 0; - _Py_IDENTIFIER(cursor); cursor = _PyObject_CallMethodId((PyObject*)self, &PyId_cursor, ""); if (!cursor) { @@ -1274,7 +1319,6 @@ PyObject* pysqlite_connection_executemany(pysqlite_Connection* self, PyObject* a PyObject* cursor = 0; PyObject* result = 0; PyObject* method = 0; - _Py_IDENTIFIER(cursor); cursor = _PyObject_CallMethodId((PyObject*)self, &PyId_cursor, ""); if (!cursor) { @@ -1304,7 +1348,6 @@ PyObject* pysqlite_connection_executescript(pysqlite_Connection* self, PyObject* PyObject* cursor = 0; PyObject* result = 0; PyObject* method = 0; - _Py_IDENTIFIER(cursor); cursor = _PyObject_CallMethodId((PyObject*)self, &PyId_cursor, ""); if (!cursor) { diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c index 09c13d4..ce92af6 100644 --- a/Modules/_sqlite/cursor.c +++ b/Modules/_sqlite/cursor.c @@ -24,7 +24,6 @@ #include "cursor.h" #include "module.h" #include "util.h" -#include "sqlitecompat.h" PyObject* pysqlite_cursor_iternext(pysqlite_Cursor* self); @@ -338,6 +337,11 @@ PyObject* _pysqlite_fetch_one_row(pysqlite_Cursor* self) if (self->connection->text_factory == (PyObject*)&PyUnicode_Type) { converted = PyUnicode_FromStringAndSize(val_str, nbytes); if (!converted) { +#ifdef Py_DEBUG + /* in debug mode, type_call() fails with an assertion + error if an exception is set when it is called */ + PyErr_Clear(); +#endif colname = sqlite3_column_name(self->statement->st, i); if (!colname) { colname = "<unknown column name>"; @@ -864,10 +868,15 @@ PyObject* pysqlite_cursor_iternext(pysqlite_Cursor *self) } next_row_tuple = self->next_row; + assert(next_row_tuple != NULL); self->next_row = NULL; if (self->row_factory != Py_None) { next_row = PyObject_CallFunction(self->row_factory, "OO", self, next_row_tuple); + if (next_row == NULL) { + self->next_row = next_row_tuple; + return NULL; + } Py_DECREF(next_row_tuple); } else { next_row = next_row_tuple; @@ -884,6 +893,12 @@ PyObject* pysqlite_cursor_iternext(pysqlite_Cursor *self) if (rc == SQLITE_ROW) { self->next_row = _pysqlite_fetch_one_row(self); + if (self->next_row == NULL) { + (void)pysqlite_statement_reset(self->statement); + Py_DECREF(next_row); + _pysqlite_seterror(self->connection->db, NULL); + return NULL; + } } } diff --git a/Modules/_sqlite/module.c b/Modules/_sqlite/module.c index bea6d6a..7a7e860 100644 --- a/Modules/_sqlite/module.c +++ b/Modules/_sqlite/module.c @@ -50,19 +50,26 @@ static PyObject* module_connect(PyObject* self, PyObject* args, PyObject* * C-level, so this code is redundant with the one in connection_init in * connection.c and must always be copied from there ... */ - static char *kwlist[] = {"database", "timeout", "detect_types", "isolation_level", "check_same_thread", "factory", "cached_statements", NULL, NULL}; + static char *kwlist[] = { + "database", "timeout", "detect_types", "isolation_level", + "check_same_thread", "factory", "cached_statements", "uri", + NULL + }; char* database; int detect_types = 0; PyObject* isolation_level; PyObject* factory = NULL; int check_same_thread = 1; int cached_statements; + int uri = 0; double timeout = 5.0; PyObject* result; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|diOiOi", kwlist, - &database, &timeout, &detect_types, &isolation_level, &check_same_thread, &factory, &cached_statements)) + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|diOiOip", kwlist, + &database, &timeout, &detect_types, + &isolation_level, &check_same_thread, + &factory, &cached_statements, &uri)) { return NULL; } @@ -77,7 +84,8 @@ static PyObject* module_connect(PyObject* self, PyObject* args, PyObject* } PyDoc_STRVAR(module_connect_doc, -"connect(database[, timeout, isolation_level, detect_types, factory])\n\ +"connect(database[, timeout, detect_types, isolation_level,\n\ + check_same_thread, factory, cached_statements, uri])\n\ \n\ Opens a connection to the SQLite database file *database*. You can use\n\ \":memory:\" to open a database connection to a database that resides in\n\ diff --git a/Modules/_sqlite/prepare_protocol.c b/Modules/_sqlite/prepare_protocol.c index fc68874..f2c85f9 100644 --- a/Modules/_sqlite/prepare_protocol.c +++ b/Modules/_sqlite/prepare_protocol.c @@ -21,7 +21,6 @@ * 3. This notice may not be removed or altered from any source distribution. */ -#include "sqlitecompat.h" #include "prepare_protocol.h" int pysqlite_prepare_protocol_init(pysqlite_PrepareProtocol* self, PyObject* args, PyObject* kwargs) diff --git a/Modules/_sqlite/row.c b/Modules/_sqlite/row.c index b50658c..4a87a04 100644 --- a/Modules/_sqlite/row.c +++ b/Modules/_sqlite/row.c @@ -23,7 +23,6 @@ #include "row.h" #include "cursor.h" -#include "sqlitecompat.h" void pysqlite_row_dealloc(pysqlite_Row* self) { @@ -68,7 +67,7 @@ PyObject* pysqlite_row_subscript(pysqlite_Row* self, PyObject* idx) { long _idx; char* key; - int nitems, i; + Py_ssize_t nitems, i; char* compare_key; char* p1; @@ -89,7 +88,10 @@ PyObject* pysqlite_row_subscript(pysqlite_Row* self, PyObject* idx) nitems = PyTuple_Size(self->description); for (i = 0; i < nitems; i++) { - compare_key = _PyUnicode_AsString(PyTuple_GET_ITEM(PyTuple_GET_ITEM(self->description, i), 0)); + PyObject *obj; + obj = PyTuple_GET_ITEM(self->description, i); + obj = PyTuple_GET_ITEM(obj, 0); + compare_key = _PyUnicode_AsString(obj); if (!compare_key) { return NULL; } @@ -121,10 +123,12 @@ PyObject* pysqlite_row_subscript(pysqlite_Row* self, PyObject* idx) PyErr_SetString(PyExc_IndexError, "No item with that key"); return NULL; - } else if (PySlice_Check(idx)) { + } + else if (PySlice_Check(idx)) { PyErr_SetString(PyExc_ValueError, "slices not implemented, yet"); return NULL; - } else { + } + else { PyErr_SetString(PyExc_IndexError, "Index must be int or string"); return NULL; } diff --git a/Modules/_sqlite/sqlitecompat.h b/Modules/_sqlite/sqlitecompat.h deleted file mode 100644 index cf20f16..0000000 --- a/Modules/_sqlite/sqlitecompat.h +++ /dev/null @@ -1,63 +0,0 @@ -/* sqlitecompat.h - compatibility macros - * - * Copyright (C) 2006-2010 Gerhard Häring <gh@ghaering.de> - * - * This file is part of pysqlite. - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ - -#include "Python.h" - -#ifndef PYSQLITE_COMPAT_H -#define PYSQLITE_COMPAT_H - -/* define Py_ssize_t for pre-2.5 versions of Python */ - -#if PY_VERSION_HEX < 0x02050000 -typedef int Py_ssize_t; -typedef int (*lenfunc)(PyObject*); -#endif - - -/* define PyDict_CheckExact for pre-2.4 versions of Python */ -#ifndef PyDict_CheckExact -#define PyDict_CheckExact(op) ((op)->ob_type == &PyDict_Type) -#endif - -/* define Py_CLEAR for pre-2.4 versions of Python */ -#ifndef Py_CLEAR -#define Py_CLEAR(op) \ - do { \ - if (op) { \ - PyObject *tmp = (PyObject *)(op); \ - (op) = NULL; \ - Py_DECREF(tmp); \ - } \ - } while (0) -#endif - -#ifndef PyVarObject_HEAD_INIT -#define PyVarObject_HEAD_INIT(type, size) \ - PyObject_HEAD_INIT(type) size, -#endif - -#ifndef Py_TYPE -#define Py_TYPE(ob) ((ob)->ob_type) -#endif - -#endif diff --git a/Modules/_sqlite/statement.c b/Modules/_sqlite/statement.c index 471a067..66b4a52 100644 --- a/Modules/_sqlite/statement.c +++ b/Modules/_sqlite/statement.c @@ -27,7 +27,6 @@ #include "microprotocols.h" #include "prepare_protocol.h" #include "util.h" -#include "sqlitecompat.h" /* prototypes */ static int pysqlite_check_remaining_sql(const char* tail); @@ -133,18 +132,26 @@ int pysqlite_statement_bind_parameter(pysqlite_Statement* self, int pos, PyObjec break; case TYPE_UNICODE: string = _PyUnicode_AsStringAndSize(parameter, &buflen); - if (string != NULL) - rc = sqlite3_bind_text(self->st, pos, string, buflen, SQLITE_TRANSIENT); - else - rc = -1; + if (string == NULL) + return -1; + if (buflen > INT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "string longer than INT_MAX bytes"); + return -1; + } + rc = sqlite3_bind_text(self->st, pos, string, (int)buflen, SQLITE_TRANSIENT); break; case TYPE_BUFFER: - if (PyObject_AsCharBuffer(parameter, &buffer, &buflen) == 0) { - rc = sqlite3_bind_blob(self->st, pos, buffer, buflen, SQLITE_TRANSIENT); - } else { + if (PyObject_AsCharBuffer(parameter, &buffer, &buflen) != 0) { PyErr_SetString(PyExc_ValueError, "could not convert BLOB to buffer"); - rc = -1; + return -1; + } + if (buflen > INT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "BLOB longer than INT_MAX bytes"); + return -1; } + rc = sqlite3_bind_blob(self->st, pos, buffer, buflen, SQLITE_TRANSIENT); break; case TYPE_UNKNOWN: rc = -1; @@ -177,7 +184,7 @@ void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* para int i; int rc; int num_params_needed; - int num_params; + Py_ssize_t num_params; Py_BEGIN_ALLOW_THREADS num_params_needed = sqlite3_bind_parameter_count(self->st); @@ -193,7 +200,9 @@ void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* para num_params = PySequence_Size(parameters); } if (num_params != num_params_needed) { - PyErr_Format(pysqlite_ProgrammingError, "Incorrect number of bindings supplied. The current statement uses %d, and there are %d supplied.", + PyErr_Format(pysqlite_ProgrammingError, + "Incorrect number of bindings supplied. The current " + "statement uses %d, and there are %zd supplied.", num_params_needed, num_params); return; } @@ -249,7 +258,7 @@ void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* para current_param = PyDict_GetItemString(parameters, binding_name); Py_XINCREF(current_param); } else { - current_param = PyMapping_GetItemString(parameters, (char*)binding_name); + current_param = PyMapping_GetItemString(parameters, binding_name); } if (!current_param) { PyErr_Format(pysqlite_ProgrammingError, "You did not supply a value for binding %d.", i); diff --git a/Modules/_sqlite/util.c b/Modules/_sqlite/util.c index d88bc3f..312fe3b 100644 --- a/Modules/_sqlite/util.c +++ b/Modules/_sqlite/util.c @@ -132,7 +132,7 @@ _pysqlite_long_from_int64(sqlite_int64 value) } # endif #endif - return PyLong_FromLong(value); + return PyLong_FromLong(Py_SAFE_DOWNCAST(value, sqlite_int64, long)); } sqlite_int64 |
