From 6247967ad2415dd8babc40a1463109d5582678f6 Mon Sep 17 00:00:00 2001 From: Charles Leifer Date: Fri, 14 May 2021 10:13:01 -0500 Subject: [PATCH] Apply some patches from upstream. --- src/blob.c | 10 +++++----- src/connection.c | 40 +++++++++++++++++++++------------------ src/cursor.c | 44 +++++++++++++++++++++---------------------- src/module.c | 27 +++++++++++++------------- src/util.c | 14 ++++---------- src/util.h | 2 +- test/userfunctions.py | 5 +++++ 7 files changed, 71 insertions(+), 71 deletions(-) diff --git a/src/blob.c b/src/blob.c index 2d5a649..c3dabac 100644 --- a/src/blob.c +++ b/src/blob.c @@ -129,7 +129,7 @@ static PyObject* inner_read(pysqlite_Blob *self, int read_length, int offset) PyErr_SetString(pysqlite_OperationalError, "Cannot operate on modified blob"); } else { - _pysqlite_seterror(self->connection->db, NULL); + _pysqlite_seterror(self->connection->db); } return NULL; } @@ -184,7 +184,7 @@ static int write_inner(pysqlite_Blob *self, const void *buf, Py_ssize_t len, int PyErr_SetString(pysqlite_OperationalError, "Cannot operate on modified blob"); } else { - _pysqlite_seterror(self->connection->db, NULL); + _pysqlite_seterror(self->connection->db); } return -1; } @@ -446,7 +446,7 @@ static PyObject * pysqlite_blob_subscript(pysqlite_Blob *self, PyObject *item) PyErr_SetString(pysqlite_OperationalError, "Cannot operate on modified blob"); } else { - _pysqlite_seterror(self->connection->db, NULL); + _pysqlite_seterror(self->connection->db); } PyMem_Free(result_buf); PyMem_Free(data_buff); @@ -557,7 +557,7 @@ static int pysqlite_blob_ass_subscript(pysqlite_Blob *self, PyObject *item, PyOb PyErr_SetString(pysqlite_OperationalError, "Cannot operate on modified blob"); } else { - _pysqlite_seterror(self->connection->db, NULL); + _pysqlite_seterror(self->connection->db); } PyMem_Free(data_buff); rc = -1; @@ -581,7 +581,7 @@ static int pysqlite_blob_ass_subscript(pysqlite_Blob *self, PyObject *item, PyOb PyErr_SetString(pysqlite_OperationalError, "Cannot operate on modified blob"); } else { - _pysqlite_seterror(self->connection->db, NULL); + _pysqlite_seterror(self->connection->db); } PyMem_Free(data_buff); rc = -1; diff --git a/src/connection.c b/src/connection.c index 7947251..7291a4b 100644 --- a/src/connection.c +++ b/src/connection.c @@ -135,7 +135,7 @@ int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject Py_DECREF(database_obj); if (rc != SQLITE_OK) { - _pysqlite_seterror(self->db, NULL); + _pysqlite_seterror(self->db); return -1; } @@ -359,7 +359,7 @@ PyObject* pysqlite_connection_blob(pysqlite_Connection *self, PyObject *args, Py_END_ALLOW_THREADS if (rc != SQLITE_OK) { - _pysqlite_seterror(self->db, NULL); + _pysqlite_seterror(self->db); return NULL; } @@ -427,7 +427,7 @@ PyObject* pysqlite_connection_close(pysqlite_Connection* self, PyObject* args) rc = sqlite3_close_v2(self->db); if (rc != SQLITE_OK) { - _pysqlite_seterror(self->db, NULL); + _pysqlite_seterror(self->db); return NULL; } else { self->db = NULL; @@ -467,13 +467,13 @@ PyObject* _pysqlite_connection_begin(pysqlite_Connection* self) Py_END_ALLOW_THREADS if (rc != SQLITE_OK) { - _pysqlite_seterror(self->db, statement); + _pysqlite_seterror(self->db); goto error; } rc = pysqlite_step(statement, self); if (rc != SQLITE_DONE) { - _pysqlite_seterror(self->db, statement); + _pysqlite_seterror(self->db); } Py_BEGIN_ALLOW_THREADS @@ -481,7 +481,7 @@ PyObject* _pysqlite_connection_begin(pysqlite_Connection* self) Py_END_ALLOW_THREADS if (rc != SQLITE_OK && !PyErr_Occurred()) { - _pysqlite_seterror(self->db, NULL); + _pysqlite_seterror(self->db); } error: @@ -507,20 +507,20 @@ PyObject* pysqlite_connection_commit(pysqlite_Connection* self, PyObject* args) rc = sqlite3_prepare_v2(self->db, "COMMIT", -1, &statement, NULL); Py_END_ALLOW_THREADS if (rc != SQLITE_OK) { - _pysqlite_seterror(self->db, NULL); + _pysqlite_seterror(self->db); goto error; } rc = pysqlite_step(statement, self); if (rc != SQLITE_DONE) { - _pysqlite_seterror(self->db, statement); + _pysqlite_seterror(self->db); } Py_BEGIN_ALLOW_THREADS rc = sqlite3_finalize(statement); Py_END_ALLOW_THREADS if (rc != SQLITE_OK && !PyErr_Occurred()) { - _pysqlite_seterror(self->db, NULL); + _pysqlite_seterror(self->db); } } @@ -549,20 +549,20 @@ PyObject* pysqlite_connection_rollback(pysqlite_Connection* self, PyObject* args rc = sqlite3_prepare_v2(self->db, "ROLLBACK", -1, &statement, NULL); Py_END_ALLOW_THREADS if (rc != SQLITE_OK) { - _pysqlite_seterror(self->db, NULL); + _pysqlite_seterror(self->db); goto error; } rc = pysqlite_step(statement, self); if (rc != SQLITE_DONE) { - _pysqlite_seterror(self->db, statement); + _pysqlite_seterror(self->db); } Py_BEGIN_ALLOW_THREADS rc = sqlite3_finalize(statement); Py_END_ALLOW_THREADS if (rc != SQLITE_OK && !PyErr_Occurred()) { - _pysqlite_seterror(self->db, NULL); + _pysqlite_seterror(self->db); } } @@ -662,7 +662,7 @@ PyObject* _pysqlite_build_py_params(sqlite3_context *context, int argc, sqlite3_ return NULL; } - PyTuple_SetItem(args, i, cur_py_value); + PyTuple_SET_ITEM(args, i, cur_py_value); } @@ -778,8 +778,12 @@ void _pysqlite_final_callback(sqlite3_context* context) threadstate = PyGILState_Ensure(); - aggregate_instance = (PyObject**)sqlite3_aggregate_context(context, sizeof(PyObject*)); - if (!*aggregate_instance) { + aggregate_instance = (PyObject**)sqlite3_aggregate_context(context, 0); + if (aggregate_instance == NULL) { + /* No rows matched the query, the step handler was never called. */ + goto error; + } + else if (!*aggregate_instance) { /* this branch is executed if there was an exception in the aggregate's * __init__ */ @@ -1480,7 +1484,7 @@ PyObject* pysqlite_connection_call(pysqlite_Connection* self, PyObject* args, Py PyErr_SetString(pysqlite_Warning, "SQL is of wrong type. Must be string."); } else { (void)pysqlite_statement_reset(statement); - _pysqlite_seterror(self->db, NULL); + _pysqlite_seterror(self->db); } goto error; } @@ -1768,7 +1772,7 @@ pysqlite_connection_backup(pysqlite_Connection *self, PyObject *args, PyObject * rc = sqlite3_backup_finish(bck_handle); Py_END_ALLOW_THREADS } else { - rc = _pysqlite_seterror(bck_conn, NULL); + rc = _pysqlite_seterror(bck_conn); } if (!callback_error && rc != SQLITE_OK) { @@ -1861,7 +1865,7 @@ pysqlite_connection_create_collation(pysqlite_Connection* self, PyObject* args) (callable != Py_None) ? pysqlite_collation_callback : NULL); if (rc != SQLITE_OK) { PyDict_DelItem(self->collations, uppercase_name); - _pysqlite_seterror(self->db, NULL); + _pysqlite_seterror(self->db); goto finally; } diff --git a/src/cursor.c b/src/cursor.c index 4e801ae..553b56c 100644 --- a/src/cursor.c +++ b/src/cursor.c @@ -327,7 +327,7 @@ _pysqlite_fetch_one_row(pysqlite_Cursor* self) if (!converted) { goto error; } - PyTuple_SetItem(row, i, converted); + PyTuple_SET_ITEM(row, i, converted); } if (PyErr_Occurred()) @@ -377,7 +377,6 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* args) PyObject* func_args; PyObject* result; int numcols; - PyObject* descriptor; PyObject* column_name; PyObject* second_argument = NULL; sqlite_int64 lastrowid; @@ -522,7 +521,7 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* args) } } (void)pysqlite_statement_reset(self->statement); - _pysqlite_seterror(self->connection->db, NULL); + _pysqlite_seterror(self->connection->db); goto error; } @@ -541,24 +540,24 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* args) goto error; } for (i = 0; i < numcols; i++) { - descriptor = PyTuple_New(7); - if (!descriptor) { + const char *colname; + colname = sqlite3_column_name(self->statement->st, i); + if (colname == NULL) { + PyErr_NoMemory(); goto error; } - column_name = _pysqlite_build_column_name(self, - sqlite3_column_name(self->statement->st, i)); + column_name = _pysqlite_build_column_name(self, colname); if (!column_name) { - Py_DECREF(descriptor); goto error; } - PyTuple_SetItem(descriptor, 0, column_name); - Py_INCREF(Py_None); PyTuple_SetItem(descriptor, 1, Py_None); - Py_INCREF(Py_None); PyTuple_SetItem(descriptor, 2, Py_None); - Py_INCREF(Py_None); PyTuple_SetItem(descriptor, 3, Py_None); - Py_INCREF(Py_None); PyTuple_SetItem(descriptor, 4, Py_None); - Py_INCREF(Py_None); PyTuple_SetItem(descriptor, 5, Py_None); - Py_INCREF(Py_None); PyTuple_SetItem(descriptor, 6, Py_None); - PyTuple_SetItem(self->description, i, descriptor); + PyObject *descriptor = PyTuple_Pack(7, column_name, + Py_None, Py_None, Py_None, + Py_None, Py_None, Py_None); + Py_DECREF(column_name); + if (descriptor == NULL) { + goto error; + } + PyTuple_SET_ITEM(self->description, i, descriptor); } } @@ -667,29 +666,28 @@ pysqlite_cursor_executescript(pysqlite_Cursor* self, PyObject* args) &script_cstr); Py_END_ALLOW_THREADS if (rc != SQLITE_OK) { - _pysqlite_seterror(self->connection->db, NULL); + _pysqlite_seterror(self->connection->db); goto error; } /* execute statement, and ignore results of SELECT statements */ - rc = SQLITE_ROW; - while (rc == SQLITE_ROW) { + do { rc = pysqlite_step(statement, self->connection); if (PyErr_Occurred()) { (void)sqlite3_finalize(statement); goto error; } - } + } while (rc == SQLITE_ROW); if (rc != SQLITE_DONE) { (void)sqlite3_finalize(statement); - _pysqlite_seterror(self->connection->db, NULL); + _pysqlite_seterror(self->connection->db); goto error; } rc = sqlite3_finalize(statement); if (rc != SQLITE_OK) { - _pysqlite_seterror(self->connection->db, NULL); + _pysqlite_seterror(self->connection->db); goto error; } @@ -755,7 +753,7 @@ PyObject* pysqlite_cursor_iternext(pysqlite_Cursor *self) if (rc != SQLITE_DONE && rc != SQLITE_ROW) { (void)pysqlite_statement_reset(self->statement); Py_DECREF(next_row); - _pysqlite_seterror(self->connection->db, NULL); + _pysqlite_seterror(self->connection->db); return NULL; } diff --git a/src/module.c b/src/module.c index 6659d33..590f597 100644 --- a/src/module.c +++ b/src/module.c @@ -74,8 +74,6 @@ static PyObject* module_connect(PyObject* self, PyObject* args, PyObject* int uri = 0; double timeout = 5.0; - PyObject* result; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|diOiOipiz", kwlist, &database, &timeout, &detect_types, &isolation_level, &check_same_thread, @@ -89,9 +87,7 @@ static PyObject* module_connect(PyObject* self, PyObject* args, PyObject* factory = (PyObject*)&pysqlite_ConnectionType; } - result = PyObject_Call(factory, args, kwargs); - - return result; + return PyObject_Call(factory, args, kwargs); } PyDoc_STRVAR(module_connect_doc, @@ -441,6 +437,11 @@ PyMODINIT_FUNC PyInit__sqlite3(void) PyObject *module, *dict; PyObject *tmp_obj; int i; + int rc = sqlite3_initialize(); + if (rc != SQLITE_OK) { + PyErr_SetString(PyExc_ImportError, sqlite3_errstr(rc)); + return NULL; + } module = PyModule_Create(&_sqlite3module); @@ -453,8 +454,7 @@ PyMODINIT_FUNC PyInit__sqlite3(void) (pysqlite_prepare_protocol_setup_types() < 0) || (pysqlite_blob_setup_types() < 0) ) { - Py_XDECREF(module); - return NULL; + goto error; } Py_INCREF(&pysqlite_ConnectionType); @@ -570,12 +570,11 @@ PyMODINIT_FUNC PyInit__sqlite3(void) /* initialize the default converters */ converters_init(dict); -error: - if (PyErr_Occurred()) - { - PyErr_SetString(PyExc_ImportError, MODULE_NAME ": init failed"); - Py_DECREF(module); - module = NULL; - } return module; + +error: + sqlite3_shutdown(); + PyErr_SetString(PyExc_ImportError, MODULE_NAME ": init failed"); + Py_XDECREF(module); + return NULL; } diff --git a/src/util.c b/src/util.c index 82e5d5a..ebf0cb5 100644 --- a/src/util.c +++ b/src/util.c @@ -28,15 +28,9 @@ int pysqlite_step(sqlite3_stmt* statement, pysqlite_Connection* connection) { int rc; - if (statement == NULL) { - /* this is a workaround for SQLite 3.5 and later. it now apparently - * returns NULL for "no-operation" statements */ - rc = SQLITE_OK; - } else { - Py_BEGIN_ALLOW_THREADS - rc = sqlite3_step(statement); - Py_END_ALLOW_THREADS - } + Py_BEGIN_ALLOW_THREADS + rc = sqlite3_step(statement); + Py_END_ALLOW_THREADS return rc; } @@ -45,7 +39,7 @@ int pysqlite_step(sqlite3_stmt* statement, pysqlite_Connection* connection) * Checks the SQLite error code and sets the appropriate DB-API exception. * Returns the error code (0 means no error occurred). */ -int _pysqlite_seterror(sqlite3* db, sqlite3_stmt* st) +int _pysqlite_seterror(sqlite3* db) { PyObject *exc_class; int errorcode = sqlite3_errcode(db); diff --git a/src/util.h b/src/util.h index 52c5724..f6eb713 100644 --- a/src/util.h +++ b/src/util.h @@ -35,7 +35,7 @@ int pysqlite_step(sqlite3_stmt* statement, pysqlite_Connection* connection); * Checks the SQLite error code and sets the appropriate DB-API exception. * Returns the error code (0 means no error occurred). */ -int _pysqlite_seterror(sqlite3* db, sqlite3_stmt* st); +int _pysqlite_seterror(sqlite3* db); sqlite_int64 _pysqlite_long_as_int64(PyObject * value); diff --git a/test/userfunctions.py b/test/userfunctions.py index adcf2bc..ffdc619 100644 --- a/test/userfunctions.py +++ b/test/userfunctions.py @@ -407,6 +407,11 @@ class AggregateTests(unittest.TestCase): val = cur.fetchone()[0] self.assertEqual(val, 60) + def CheckAggrNoMatch(self): + cur = self.con.execute('select mysum(i) from (select 1 as i) where i == 0') + val = cur.fetchone()[0] + self.assertIsNone(val) + @unittest.skipIf(sqlite.sqlite_version_info < (3, 25, 0), 'requires sqlite with window-function support')