diff options
Diffstat (limited to 'Modules/_sqlite/cursor.c')
-rw-r--r-- | Modules/_sqlite/cursor.c | 154 |
1 files changed, 35 insertions, 119 deletions
diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c index e1676de907..39f7a6508c 100644 --- a/Modules/_sqlite/cursor.c +++ b/Modules/_sqlite/cursor.c @@ -27,45 +27,7 @@ PyObject* pysqlite_cursor_iternext(pysqlite_Cursor* self); -static char* errmsg_fetch_across_rollback = "Cursor needed to be reset because of commit/rollback and can no longer be fetched from."; - -static pysqlite_StatementKind detect_statement_type(const char* statement) -{ - char buf[20]; - const char* src; - char* dst; - - src = statement; - /* skip over whitepace */ - while (*src == '\r' || *src == '\n' || *src == ' ' || *src == '\t') { - src++; - } - - if (*src == 0) - return STATEMENT_INVALID; - - dst = buf; - *dst = 0; - while (Py_ISALPHA(*src) && (dst - buf) < ((Py_ssize_t)sizeof(buf) - 2)) { - *dst++ = Py_TOLOWER(*src++); - } - - *dst = 0; - - if (!strcmp(buf, "select")) { - return STATEMENT_SELECT; - } else if (!strcmp(buf, "insert")) { - return STATEMENT_INSERT; - } else if (!strcmp(buf, "update")) { - return STATEMENT_UPDATE; - } else if (!strcmp(buf, "delete")) { - return STATEMENT_DELETE; - } else if (!strcmp(buf, "replace")) { - return STATEMENT_REPLACE; - } else { - return STATEMENT_OTHER; - } -} +static const char errmsg_fetch_across_rollback[] = "Cursor needed to be reset because of commit/rollback and can no longer be fetched from."; static int pysqlite_cursor_init(pysqlite_Cursor* self, PyObject* args, PyObject* kwargs) { @@ -143,7 +105,7 @@ PyObject* _pysqlite_get_converter(PyObject* key) PyObject* retval; _Py_IDENTIFIER(upper); - upcase_key = _PyObject_CallMethodId(key, &PyId_upper, ""); + upcase_key = _PyObject_CallMethodId(key, &PyId_upper, NULL); if (!upcase_key) { return NULL; } @@ -242,8 +204,7 @@ PyObject* _pysqlite_build_column_name(const char* colname) const char* pos; if (!colname) { - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } for (pos = colname;; pos++) { @@ -428,9 +389,9 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* PyObject* func_args; PyObject* result; int numcols; - int statement_type; PyObject* descriptor; PyObject* second_argument = NULL; + sqlite_int64 lastrowid; if (!check_cursor(self)) { goto error; @@ -504,14 +465,14 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* pysqlite_statement_reset(self->statement); } - operation_cstr = _PyUnicode_AsStringAndSize(operation, &operation_len); + operation_cstr = PyUnicode_AsUTF8AndSize(operation, &operation_len); if (operation_cstr == NULL) goto error; /* reset description and rowcount */ Py_INCREF(Py_None); Py_SETREF(self->description, Py_None); - self->rowcount = -1L; + self->rowcount = 0L; func_args = PyTuple_New(1); if (!func_args) { @@ -550,43 +511,19 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* pysqlite_statement_reset(self->statement); pysqlite_statement_mark_dirty(self->statement); - statement_type = detect_statement_type(operation_cstr); - if (self->connection->begin_statement) { - switch (statement_type) { - case STATEMENT_UPDATE: - case STATEMENT_DELETE: - case STATEMENT_INSERT: - case STATEMENT_REPLACE: - if (!self->connection->inTransaction) { - result = _pysqlite_connection_begin(self->connection); - if (!result) { - goto error; - } - Py_DECREF(result); - } - break; - case STATEMENT_OTHER: - /* it's a DDL statement or something similar - - we better COMMIT first so it works for all cases */ - if (self->connection->inTransaction) { - result = pysqlite_connection_commit(self->connection, NULL); - if (!result) { - goto error; - } - Py_DECREF(result); - } - break; - case STATEMENT_SELECT: - if (multiple) { - PyErr_SetString(pysqlite_ProgrammingError, - "You cannot execute SELECT statements in executemany()."); - goto error; - } - break; + /* For backwards compatibility reasons, do not start a transaction if a + DDL statement is encountered. If anybody wants transactional DDL, + they can issue a BEGIN statement manually. */ + if (self->connection->begin_statement && !sqlite3_stmt_readonly(self->statement->st) && !self->statement->is_ddl) { + if (sqlite3_get_autocommit(self->connection->db)) { + result = _pysqlite_connection_begin(self->connection); + if (!result) { + goto error; + } + Py_DECREF(result); } } - while (1) { parameters = PyIter_Next(parameters_iter); if (!parameters) { @@ -672,6 +609,20 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* } } + if (!sqlite3_stmt_readonly(self->statement->st)) { + self->rowcount += (long)sqlite3_changes(self->connection->db); + } else { + self->rowcount= -1L; + } + + if (!multiple) { + Py_DECREF(self->lastrowid); + Py_BEGIN_ALLOW_THREADS + lastrowid = sqlite3_last_insert_rowid(self->connection->db); + Py_END_ALLOW_THREADS + self->lastrowid = _pysqlite_long_from_int64(lastrowid); + } + if (rc == SQLITE_ROW) { if (multiple) { PyErr_SetString(pysqlite_ProgrammingError, "executemany() can only execute DML statements."); @@ -686,29 +637,6 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* Py_CLEAR(self->statement); } - switch (statement_type) { - case STATEMENT_UPDATE: - case STATEMENT_DELETE: - case STATEMENT_INSERT: - case STATEMENT_REPLACE: - if (self->rowcount == -1L) { - self->rowcount = 0L; - } - self->rowcount += (long)sqlite3_changes(self->connection->db); - } - - Py_DECREF(self->lastrowid); - if (!multiple && statement_type == STATEMENT_INSERT) { - sqlite_int64 lastrowid; - Py_BEGIN_ALLOW_THREADS - lastrowid = sqlite3_last_insert_rowid(self->connection->db); - Py_END_ALLOW_THREADS - self->lastrowid = _pysqlite_long_from_int64(lastrowid); - } else { - Py_INCREF(Py_None); - self->lastrowid = Py_None; - } - if (multiple) { pysqlite_statement_reset(self->statement); } @@ -716,15 +644,6 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* } error: - /* just to be sure (implicit ROLLBACKs with ON CONFLICT ROLLBACK/OR - * ROLLBACK could have happened */ - #ifdef SQLITE_VERSION_NUMBER - #if SQLITE_VERSION_NUMBER >= 3002002 - if (self->connection && self->connection->db) - self->connection->inTransaction = !sqlite3_get_autocommit(self->connection->db); - #endif - #endif - Py_XDECREF(parameters); Py_XDECREF(parameters_iter); Py_XDECREF(parameters_list); @@ -770,7 +689,7 @@ PyObject* pysqlite_cursor_executescript(pysqlite_Cursor* self, PyObject* args) self->reset = 0; if (PyUnicode_Check(script_obj)) { - script_cstr = _PyUnicode_AsString(script_obj); + script_cstr = PyUnicode_AsUTF8(script_obj); if (!script_cstr) { return NULL; } @@ -913,8 +832,7 @@ PyObject* pysqlite_cursor_fetchone(pysqlite_Cursor* self, PyObject* args) row = pysqlite_cursor_iternext(self); if (!row && !PyErr_Occurred()) { - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } return row; @@ -995,8 +913,7 @@ PyObject* pysqlite_cursor_fetchall(pysqlite_Cursor* self, PyObject* args) PyObject* pysqlite_noop(pysqlite_Connection* self, PyObject* args) { /* don't care, return None */ - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } PyObject* pysqlite_cursor_close(pysqlite_Cursor* self, PyObject* args) @@ -1012,8 +929,7 @@ PyObject* pysqlite_cursor_close(pysqlite_Cursor* self, PyObject* args) self->closed = 1; - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } static PyMethodDef cursor_methods[] = { @@ -1049,7 +965,7 @@ static struct PyMemberDef cursor_members[] = {NULL} }; -static char cursor_doc[] = +static const char cursor_doc[] = PyDoc_STR("SQLite database cursor class."); PyTypeObject pysqlite_CursorType = { |