summaryrefslogtreecommitdiff
path: root/Modules/_sqlite/cursor.c
diff options
context:
space:
mode:
Diffstat (limited to 'Modules/_sqlite/cursor.c')
-rw-r--r--Modules/_sqlite/cursor.c154
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 = {