Skip to content

Commit a384b6c

Browse files
author
Erlend Egeberg Aasland
authored
bpo-44165: Optimise sqlite3 statement preparation by passing string size (GH-26206)
1 parent ee76375 commit a384b6c

File tree

3 files changed

+25
-7
lines changed

3 files changed

+25
-7
lines changed

Modules/_sqlite/connection.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,7 @@ pysqlite_connection_commit_impl(pysqlite_Connection *self)
451451
if (!sqlite3_get_autocommit(self->db)) {
452452

453453
Py_BEGIN_ALLOW_THREADS
454-
rc = sqlite3_prepare_v2(self->db, "COMMIT", -1, &statement, NULL);
454+
rc = sqlite3_prepare_v2(self->db, "COMMIT", 7, &statement, NULL);
455455
Py_END_ALLOW_THREADS
456456
if (rc != SQLITE_OK) {
457457
_pysqlite_seterror(self->db);
@@ -501,7 +501,7 @@ pysqlite_connection_rollback_impl(pysqlite_Connection *self)
501501
pysqlite_do_all_statements(self, ACTION_RESET, 1);
502502

503503
Py_BEGIN_ALLOW_THREADS
504-
rc = sqlite3_prepare_v2(self->db, "ROLLBACK", -1, &statement, NULL);
504+
rc = sqlite3_prepare_v2(self->db, "ROLLBACK", 9, &statement, NULL);
505505
Py_END_ALLOW_THREADS
506506
if (rc != SQLITE_OK) {
507507
_pysqlite_seterror(self->db);

Modules/_sqlite/cursor.c

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -696,6 +696,7 @@ pysqlite_cursor_executescript(pysqlite_Cursor *self, PyObject *script_obj)
696696
const char* script_cstr;
697697
sqlite3_stmt* statement;
698698
int rc;
699+
Py_ssize_t sql_len;
699700
PyObject* result;
700701

701702
if (!check_cursor(self)) {
@@ -705,10 +706,17 @@ pysqlite_cursor_executescript(pysqlite_Cursor *self, PyObject *script_obj)
705706
self->reset = 0;
706707

707708
if (PyUnicode_Check(script_obj)) {
708-
script_cstr = PyUnicode_AsUTF8(script_obj);
709+
script_cstr = PyUnicode_AsUTF8AndSize(script_obj, &sql_len);
709710
if (!script_cstr) {
710711
return NULL;
711712
}
713+
714+
int max_length = sqlite3_limit(self->connection->db,
715+
SQLITE_LIMIT_LENGTH, -1);
716+
if (sql_len >= max_length) {
717+
PyErr_SetString(pysqlite_DataError, "query string is too large");
718+
return NULL;
719+
}
712720
} else {
713721
PyErr_SetString(PyExc_ValueError, "script argument must be unicode.");
714722
return NULL;
@@ -722,12 +730,14 @@ pysqlite_cursor_executescript(pysqlite_Cursor *self, PyObject *script_obj)
722730
Py_DECREF(result);
723731

724732
while (1) {
733+
const char *tail;
734+
725735
Py_BEGIN_ALLOW_THREADS
726736
rc = sqlite3_prepare_v2(self->connection->db,
727737
script_cstr,
728-
-1,
738+
(int)sql_len + 1,
729739
&statement,
730-
&script_cstr);
740+
&tail);
731741
Py_END_ALLOW_THREADS
732742
if (rc != SQLITE_OK) {
733743
_pysqlite_seterror(self->connection->db);
@@ -755,9 +765,11 @@ pysqlite_cursor_executescript(pysqlite_Cursor *self, PyObject *script_obj)
755765
goto error;
756766
}
757767

758-
if (*script_cstr == (char)0) {
768+
if (*tail == (char)0) {
759769
break;
760770
}
771+
sql_len -= (tail - script_cstr);
772+
script_cstr = tail;
761773
}
762774

763775
error:

Modules/_sqlite/statement.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@ pysqlite_statement_create(pysqlite_Connection *connection, PyObject *sql)
6666
Py_TYPE(sql)->tp_name);
6767
return NULL;
6868
}
69+
70+
int max_length = sqlite3_limit(connection->db, SQLITE_LIMIT_LENGTH, -1);
71+
if (sql_cstr_len >= max_length) {
72+
PyErr_SetString(pysqlite_DataError, "query string is too large");
73+
return PYSQLITE_TOO_MUCH_SQL;
74+
}
6975
if (strlen(sql_cstr) != (size_t)sql_cstr_len) {
7076
PyErr_SetString(PyExc_ValueError,
7177
"the query contains a null character");
@@ -106,7 +112,7 @@ pysqlite_statement_create(pysqlite_Connection *connection, PyObject *sql)
106112
Py_BEGIN_ALLOW_THREADS
107113
rc = sqlite3_prepare_v2(self->db,
108114
sql_cstr,
109-
-1,
115+
(int)sql_cstr_len + 1,
110116
&self->st,
111117
&tail);
112118
Py_END_ALLOW_THREADS

0 commit comments

Comments
 (0)