summaryrefslogtreecommitdiffstats
path: root/contrib/tools/python3/src/Modules/_sqlite/cursor.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/tools/python3/src/Modules/_sqlite/cursor.c')
-rw-r--r--contrib/tools/python3/src/Modules/_sqlite/cursor.c86
1 files changed, 38 insertions, 48 deletions
diff --git a/contrib/tools/python3/src/Modules/_sqlite/cursor.c b/contrib/tools/python3/src/Modules/_sqlite/cursor.c
index 3f5cfef0c32..caeedbddb8d 100644
--- a/contrib/tools/python3/src/Modules/_sqlite/cursor.c
+++ b/contrib/tools/python3/src/Modules/_sqlite/cursor.c
@@ -130,14 +130,10 @@ stmt_reset(pysqlite_Statement *self)
{
int rc = SQLITE_OK;
- if (self->in_use && self->st) {
+ if (self->st != NULL) {
Py_BEGIN_ALLOW_THREADS
rc = sqlite3_reset(self->st);
Py_END_ALLOW_THREADS
-
- if (rc == SQLITE_OK) {
- self->in_use = 0;
- }
}
return rc;
@@ -666,6 +662,19 @@ bind_parameters(pysqlite_state *state, pysqlite_Statement *self,
return;
}
for (i = 0; i < num_params; i++) {
+ const char *name = sqlite3_bind_parameter_name(self->st, i+1);
+ if (name != NULL) {
+ int ret = PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
+ "Binding %d ('%s') is a named parameter, but you "
+ "supplied a sequence which requires nameless (qmark) "
+ "placeholders. Starting with Python 3.14 an "
+ "sqlite3.ProgrammingError will be raised.",
+ i+1, name);
+ if (ret < 0) {
+ return;
+ }
+ }
+
if (PyTuple_CheckExact(parameters)) {
PyObject *item = PyTuple_GET_ITEM(parameters, i);
current_param = Py_NewRef(item);
@@ -696,11 +705,10 @@ bind_parameters(pysqlite_state *state, pysqlite_Statement *self,
Py_DECREF(adapted);
if (rc != SQLITE_OK) {
- PyObject *exc, *val, *tb;
- PyErr_Fetch(&exc, &val, &tb);
+ PyObject *exc = PyErr_GetRaisedException();
sqlite3 *db = sqlite3_db_handle(self->st);
_pysqlite_seterror(state, db);
- _PyErr_ChainExceptions(exc, val, tb);
+ _PyErr_ChainExceptions1(exc);
return;
}
}
@@ -756,11 +764,10 @@ bind_parameters(pysqlite_state *state, pysqlite_Statement *self,
Py_DECREF(adapted);
if (rc != SQLITE_OK) {
- PyObject *exc, *val, *tb;
- PyErr_Fetch(&exc, &val, &tb);
+ PyObject *exc = PyErr_GetRaisedException();
sqlite3 *db = sqlite3_db_handle(self->st);
_pysqlite_seterror(state, db);
- _PyErr_ChainExceptions(exc, val, tb);
+ _PyErr_ChainExceptions1(exc);
return;
}
}
@@ -770,12 +777,6 @@ bind_parameters(pysqlite_state *state, pysqlite_Statement *self,
}
}
-static inline void
-stmt_mark_dirty(pysqlite_Statement *self)
-{
- self->in_use = 1;
-}
-
PyObject *
_pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation, PyObject* second_argument)
{
@@ -830,16 +831,12 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation
}
}
- if (self->statement != NULL) {
- /* There is an active statement */
- stmt_reset(self->statement);
- }
-
/* reset description */
Py_INCREF(Py_None);
Py_SETREF(self->description, Py_None);
if (self->statement) {
+ // Reset pending statements on this cursor.
(void)stmt_reset(self->statement);
}
@@ -856,7 +853,7 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation
goto error;
}
- if (self->statement->in_use) {
+ if (sqlite3_stmt_busy(self->statement->st)) {
Py_SETREF(self->statement,
pysqlite_statement_create(self->connection, operation));
if (self->statement == NULL) {
@@ -864,13 +861,13 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation
}
}
- stmt_reset(self->statement);
- stmt_mark_dirty(self->statement);
+ (void)stmt_reset(self->statement);
self->rowcount = self->statement->is_dml ? 0L : -1L;
/* We start a transaction implicitly before a DML statement.
SELECT is the only exception. See #9924. */
- if (self->connection->isolation_level
+ if (self->connection->autocommit == AUTOCOMMIT_LEGACY
+ && self->connection->isolation_level
&& self->statement->is_dml
&& sqlite3_get_autocommit(self->connection->db))
{
@@ -879,14 +876,13 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation
}
}
+ assert(!sqlite3_stmt_busy(self->statement->st));
while (1) {
parameters = PyIter_Next(parameters_iter);
if (!parameters) {
break;
}
- stmt_mark_dirty(self->statement);
-
bind_parameters(state, self->statement, parameters);
if (PyErr_Occurred()) {
goto error;
@@ -902,7 +898,6 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation
PyErr_Clear();
}
}
- (void)stmt_reset(self->statement);
_pysqlite_seterror(state, self->connection->db);
goto error;
}
@@ -944,16 +939,8 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation
}
}
- if (rc == SQLITE_DONE && !multiple) {
+ if (rc == SQLITE_DONE) {
if (self->statement->is_dml) {
- self->rowcount = (long)sqlite3_changes(self->connection->db);
- }
- stmt_reset(self->statement);
- Py_CLEAR(self->statement);
- }
-
- if (multiple) {
- if (self->statement->is_dml && rc == SQLITE_DONE) {
self->rowcount += (long)sqlite3_changes(self->connection->db);
}
stmt_reset(self->statement);
@@ -980,11 +967,17 @@ error:
self->locked = 0;
if (PyErr_Occurred()) {
+ if (self->statement) {
+ (void)stmt_reset(self->statement);
+ Py_CLEAR(self->statement);
+ }
self->rowcount = -1L;
return NULL;
- } else {
- return Py_NewRef((PyObject *)self);
}
+ if (self->statement && !sqlite3_stmt_busy(self->statement->st)) {
+ Py_CLEAR(self->statement);
+ }
+ return Py_NewRef((PyObject *)self);
}
/*[clinic input]
@@ -1052,7 +1045,9 @@ pysqlite_cursor_executescript_impl(pysqlite_Cursor *self,
// Commit if needed
sqlite3 *db = self->connection->db;
- if (!sqlite3_get_autocommit(db)) {
+ if (self->connection->autocommit == AUTOCOMMIT_LEGACY
+ && !sqlite3_get_autocommit(db))
+ {
int rc = SQLITE_OK;
Py_BEGIN_ALLOW_THREADS
@@ -1111,11 +1106,7 @@ pysqlite_cursor_iternext(pysqlite_Cursor *self)
sqlite3_stmt *stmt = self->statement->st;
assert(stmt != NULL);
- if (sqlite3_data_count(stmt) == 0) {
- (void)stmt_reset(self->statement);
- Py_CLEAR(self->statement);
- return NULL;
- }
+ assert(sqlite3_data_count(stmt) != 0);
self->locked = 1; // GH-80254: Prevent recursive use of cursors.
PyObject *row = _pysqlite_fetch_one_row(self);
@@ -1143,8 +1134,7 @@ pysqlite_cursor_iternext(pysqlite_Cursor *self)
PyObject *factory = self->row_factory;
PyObject *args[] = { (PyObject *)self, row, };
PyObject *new_row = PyObject_Vectorcall(factory, args, 2, NULL);
- Py_DECREF(row);
- row = new_row;
+ Py_SETREF(row, new_row);
}
return row;
}