Skip to content

Commit a93dcaa

Browse files
author
Erlend E. Aasland
committed
bpo-45041: Simplify sqlite3.Cursor.executemany
- minimise number of times we save/restore thread state - optimise SQLite C API usage - simplify error handling
1 parent eb263f9 commit a93dcaa

File tree

1 file changed

+25
-42
lines changed

1 file changed

+25
-42
lines changed

Modules/_sqlite/cursor.c

Lines changed: 25 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -729,19 +729,13 @@ pysqlite_cursor_executescript_impl(pysqlite_Cursor *self,
729729
const char *sql_script)
730730
/*[clinic end generated code: output=8fd726dde1c65164 input=1ac0693dc8db02a8]*/
731731
{
732-
_Py_IDENTIFIER(commit);
733-
sqlite3_stmt* statement;
734-
int rc;
735-
size_t sql_len;
736-
PyObject* result;
737-
738732
if (!check_cursor(self)) {
739733
return NULL;
740734
}
741735

742736
self->reset = 0;
743737

744-
sql_len = strlen(sql_script);
738+
size_t sql_len = strlen(sql_script);
745739
int max_length = sqlite3_limit(self->connection->db,
746740
SQLITE_LIMIT_LENGTH, -1);
747741
if (sql_len >= (unsigned)max_length) {
@@ -750,47 +744,37 @@ pysqlite_cursor_executescript_impl(pysqlite_Cursor *self,
750744
return NULL;
751745
}
752746

753-
/* commit first */
754-
result = _PyObject_CallMethodIdNoArgs((PyObject *)self->connection, &PyId_commit);
755-
if (!result) {
756-
goto error;
757-
}
758-
Py_DECREF(result);
759-
760-
pysqlite_state *state = self->connection->state;
761-
while (1) {
762-
const char *tail;
747+
// Commit if needed
748+
sqlite3 *db = self->connection->db;
749+
if (!sqlite3_get_autocommit(db)) {
750+
int rc = SQLITE_OK;
763751

764752
Py_BEGIN_ALLOW_THREADS
765-
rc = sqlite3_prepare_v2(self->connection->db,
766-
sql_script,
767-
(int)sql_len + 1,
768-
&statement,
769-
&tail);
753+
rc = sqlite3_exec(db, "COMMIT", NULL, NULL, NULL);
770754
Py_END_ALLOW_THREADS
755+
771756
if (rc != SQLITE_OK) {
772-
_pysqlite_seterror(state, self->connection->db);
773757
goto error;
774758
}
759+
}
775760

776-
/* execute statement, and ignore results of SELECT statements */
777-
do {
778-
rc = pysqlite_step(statement);
779-
if (PyErr_Occurred()) {
780-
(void)sqlite3_finalize(statement);
781-
goto error;
782-
}
783-
} while (rc == SQLITE_ROW);
761+
while (1) {
762+
int rc;
763+
const char *tail;
784764

785-
if (rc != SQLITE_DONE) {
786-
(void)sqlite3_finalize(statement);
787-
_pysqlite_seterror(state, self->connection->db);
788-
goto error;
765+
Py_BEGIN_ALLOW_THREADS
766+
sqlite3_stmt *stmt;
767+
rc = sqlite3_prepare_v2(db, sql_script, (int)sql_len + 1, &stmt,
768+
&tail);
769+
if (rc == SQLITE_OK) {
770+
do {
771+
(void)sqlite3_step(stmt);
772+
} while (rc == SQLITE_ROW);
773+
rc = sqlite3_finalize(stmt);
789774
}
775+
Py_END_ALLOW_THREADS
790776

791-
rc = sqlite3_finalize(statement);
792777
if (rc != SQLITE_OK) {
793-
_pysqlite_seterror(state, self->connection->db);
794778
goto error;
795779
}
796780

@@ -801,12 +785,11 @@ pysqlite_cursor_executescript_impl(pysqlite_Cursor *self,
801785
sql_script = tail;
802786
}
803787

788+
return Py_NewRef((PyObject *)self);
789+
804790
error:
805-
if (PyErr_Occurred()) {
806-
return NULL;
807-
} else {
808-
return Py_NewRef((PyObject *)self);
809-
}
791+
_pysqlite_seterror(self->connection->state, db);
792+
return NULL;
810793
}
811794

812795
static PyObject *

0 commit comments

Comments
 (0)