Skip to content

bpo-9303: Migrate sqlite3 module to _v2 API to enhance performance #359

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Mar 3, 2017
2 changes: 2 additions & 0 deletions Misc/NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,8 @@ Extension Modules
Library
-------

- bpo-9303: Migrate sqlite3 module to _v2 API. Patch by Aviv Palivoda.

- bpo-28963: Fix out of bound iteration in asyncio.Future.remove_done_callback
implemented in C.

Expand Down
12 changes: 7 additions & 5 deletions Modules/_sqlite/connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject
return -1;
}
Py_BEGIN_ALLOW_THREADS
/* No need to use sqlite3_open_v2 as sqlite3_open(filename, db) is the
same as sqlite3_open_v2(filename, db, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, NULL). */
rc = sqlite3_open(database, &self->db);
#endif
Py_END_ALLOW_THREADS
Expand Down Expand Up @@ -241,7 +243,7 @@ void pysqlite_connection_dealloc(pysqlite_Connection* self)
/* Clean up if user has not called .close() explicitly. */
if (self->db) {
Py_BEGIN_ALLOW_THREADS
sqlite3_close(self->db);
SQLITE3_CLOSE(self->db);
Py_END_ALLOW_THREADS
}

Expand Down Expand Up @@ -334,7 +336,7 @@ PyObject* pysqlite_connection_close(pysqlite_Connection* self, PyObject* args)

if (self->db) {
Py_BEGIN_ALLOW_THREADS
rc = sqlite3_close(self->db);
rc = SQLITE3_CLOSE(self->db);
Py_END_ALLOW_THREADS

if (rc != SQLITE_OK) {
Expand Down Expand Up @@ -375,7 +377,7 @@ PyObject* _pysqlite_connection_begin(pysqlite_Connection* self)
sqlite3_stmt* statement;

Py_BEGIN_ALLOW_THREADS
rc = sqlite3_prepare(self->db, self->begin_statement, -1, &statement, &tail);
rc = SQLITE3_PREPARE(self->db, self->begin_statement, -1, &statement, &tail);
Py_END_ALLOW_THREADS

if (rc != SQLITE_OK) {
Expand Down Expand Up @@ -417,7 +419,7 @@ PyObject* pysqlite_connection_commit(pysqlite_Connection* self, PyObject* args)
if (!sqlite3_get_autocommit(self->db)) {

Py_BEGIN_ALLOW_THREADS
rc = sqlite3_prepare(self->db, "COMMIT", -1, &statement, &tail);
rc = SQLITE3_PREPARE(self->db, "COMMIT", -1, &statement, &tail);
Py_END_ALLOW_THREADS
if (rc != SQLITE_OK) {
_pysqlite_seterror(self->db, NULL);
Expand Down Expand Up @@ -460,7 +462,7 @@ PyObject* pysqlite_connection_rollback(pysqlite_Connection* self, PyObject* args
pysqlite_do_all_statements(self, ACTION_RESET, 1);

Py_BEGIN_ALLOW_THREADS
rc = sqlite3_prepare(self->db, "ROLLBACK", -1, &statement, &tail);
rc = SQLITE3_PREPARE(self->db, "ROLLBACK", -1, &statement, &tail);
Py_END_ALLOW_THREADS
if (rc != SQLITE_OK) {
_pysqlite_seterror(self->db, NULL);
Expand Down
4 changes: 3 additions & 1 deletion Modules/_sqlite/cursor.c
Original file line number Diff line number Diff line change
Expand Up @@ -548,8 +548,10 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject*
/* If it worked, let's get out of the loop */
break;
}
#if SQLITE_VERSION_NUMBER < 3003009
/* Something went wrong. Re-set the statement and try again. */
rc = pysqlite_statement_reset(self->statement);
#endif
if (rc == SQLITE_SCHEMA) {
/* If this was a result of the schema changing, let's try
again. */
Expand Down Expand Up @@ -706,7 +708,7 @@ PyObject* pysqlite_cursor_executescript(pysqlite_Cursor* self, PyObject* args)

while (1) {
Py_BEGIN_ALLOW_THREADS
rc = sqlite3_prepare(self->connection->db,
rc = SQLITE3_PREPARE(self->connection->db,
script_cstr,
-1,
&statement,
Expand Down
4 changes: 2 additions & 2 deletions Modules/_sqlite/statement.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ int pysqlite_statement_create(pysqlite_Statement* self, pysqlite_Connection* con
}

Py_BEGIN_ALLOW_THREADS
rc = sqlite3_prepare(connection->db,
rc = SQLITE3_PREPARE(connection->db,
sql_cstr,
-1,
&self->st,
Expand Down Expand Up @@ -334,7 +334,7 @@ int pysqlite_statement_recompile(pysqlite_Statement* self, PyObject* params)
}

Py_BEGIN_ALLOW_THREADS
rc = sqlite3_prepare(self->db,
rc = SQLITE3_PREPARE(self->db,
sql_cstr,
-1,
&new_st,
Expand Down
5 changes: 4 additions & 1 deletion Modules/_sqlite/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,13 @@ int _pysqlite_seterror(sqlite3* db, sqlite3_stmt* st)
{
int errorcode;

/* SQLite often doesn't report anything useful, unless you reset the statement first */
#if SQLITE_VERSION_NUMBER < 3003009
/* SQLite often doesn't report anything useful, unless you reset the statement first.
When using sqlite3_prepare_v2 this is not needed. */
if (st != NULL) {
(void)sqlite3_reset(st);
}
#endif

errorcode = sqlite3_errcode(db);

Expand Down
12 changes: 12 additions & 0 deletions Modules/_sqlite/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,16 @@ int _pysqlite_seterror(sqlite3* db, sqlite3_stmt* st);
PyObject * _pysqlite_long_from_int64(sqlite_int64 value);
sqlite_int64 _pysqlite_long_as_int64(PyObject * value);

#if SQLITE_VERSION_NUMBER >= 3003009
#define SQLITE3_PREPARE sqlite3_prepare_v2
#else
#define SQLITE3_PREPARE sqlite3_prepare
#endif

#if SQLITE_VERSION_NUMBER >= 3007014
#define SQLITE3_CLOSE sqlite3_close_v2
#else
#define SQLITE3_CLOSE sqlite3_close
#endif

#endif