Skip to content

Commit

Permalink
bpo-44165: Optimise sqlite3 statement preparation by passing string s…
Browse files Browse the repository at this point in the history
…ize (GH-26206)
  • Loading branch information
Erlend Egeberg Aasland committed Jun 2, 2021
1 parent ee76375 commit a384b6c
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 7 deletions.
4 changes: 2 additions & 2 deletions Modules/_sqlite/connection.c
Expand Up @@ -451,7 +451,7 @@ pysqlite_connection_commit_impl(pysqlite_Connection *self)
if (!sqlite3_get_autocommit(self->db)) {

Py_BEGIN_ALLOW_THREADS
rc = sqlite3_prepare_v2(self->db, "COMMIT", -1, &statement, NULL);
rc = sqlite3_prepare_v2(self->db, "COMMIT", 7, &statement, NULL);
Py_END_ALLOW_THREADS
if (rc != SQLITE_OK) {
_pysqlite_seterror(self->db);
Expand Down Expand Up @@ -501,7 +501,7 @@ pysqlite_connection_rollback_impl(pysqlite_Connection *self)
pysqlite_do_all_statements(self, ACTION_RESET, 1);

Py_BEGIN_ALLOW_THREADS
rc = sqlite3_prepare_v2(self->db, "ROLLBACK", -1, &statement, NULL);
rc = sqlite3_prepare_v2(self->db, "ROLLBACK", 9, &statement, NULL);
Py_END_ALLOW_THREADS
if (rc != SQLITE_OK) {
_pysqlite_seterror(self->db);
Expand Down
20 changes: 16 additions & 4 deletions Modules/_sqlite/cursor.c
Expand Up @@ -696,6 +696,7 @@ pysqlite_cursor_executescript(pysqlite_Cursor *self, PyObject *script_obj)
const char* script_cstr;
sqlite3_stmt* statement;
int rc;
Py_ssize_t sql_len;
PyObject* result;

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

if (PyUnicode_Check(script_obj)) {
script_cstr = PyUnicode_AsUTF8(script_obj);
script_cstr = PyUnicode_AsUTF8AndSize(script_obj, &sql_len);
if (!script_cstr) {
return NULL;
}

int max_length = sqlite3_limit(self->connection->db,
SQLITE_LIMIT_LENGTH, -1);
if (sql_len >= max_length) {
PyErr_SetString(pysqlite_DataError, "query string is too large");
return NULL;
}
} else {
PyErr_SetString(PyExc_ValueError, "script argument must be unicode.");
return NULL;
Expand All @@ -722,12 +730,14 @@ pysqlite_cursor_executescript(pysqlite_Cursor *self, PyObject *script_obj)
Py_DECREF(result);

while (1) {
const char *tail;

Py_BEGIN_ALLOW_THREADS
rc = sqlite3_prepare_v2(self->connection->db,
script_cstr,
-1,
(int)sql_len + 1,
&statement,
&script_cstr);
&tail);
Py_END_ALLOW_THREADS
if (rc != SQLITE_OK) {
_pysqlite_seterror(self->connection->db);
Expand Down Expand Up @@ -755,9 +765,11 @@ pysqlite_cursor_executescript(pysqlite_Cursor *self, PyObject *script_obj)
goto error;
}

if (*script_cstr == (char)0) {
if (*tail == (char)0) {
break;
}
sql_len -= (tail - script_cstr);
script_cstr = tail;
}

error:
Expand Down
8 changes: 7 additions & 1 deletion Modules/_sqlite/statement.c
Expand Up @@ -66,6 +66,12 @@ pysqlite_statement_create(pysqlite_Connection *connection, PyObject *sql)
Py_TYPE(sql)->tp_name);
return NULL;
}

int max_length = sqlite3_limit(connection->db, SQLITE_LIMIT_LENGTH, -1);
if (sql_cstr_len >= max_length) {
PyErr_SetString(pysqlite_DataError, "query string is too large");
return PYSQLITE_TOO_MUCH_SQL;
}
if (strlen(sql_cstr) != (size_t)sql_cstr_len) {
PyErr_SetString(PyExc_ValueError,
"the query contains a null character");
Expand Down Expand Up @@ -106,7 +112,7 @@ pysqlite_statement_create(pysqlite_Connection *connection, PyObject *sql)
Py_BEGIN_ALLOW_THREADS
rc = sqlite3_prepare_v2(self->db,
sql_cstr,
-1,
(int)sql_cstr_len + 1,
&self->st,
&tail);
Py_END_ALLOW_THREADS
Expand Down

0 comments on commit a384b6c

Please sign in to comment.