| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -71,14 +71,6 @@ class _sqlite3.Connection "pysqlite_Connection *" "clinic_state()->ConnectionTyp | |||
| 71 | 71 | ||
| 72 | 72 | _Py_IDENTIFIER(cursor); | |
| 73 | 73 | ||
| 74 | - static const char * const begin_statements[] = { | ||
| 75 | - "BEGIN ", | ||
| 76 | - "BEGIN DEFERRED", | ||
| 77 | - "BEGIN IMMEDIATE", | ||
| 78 | - "BEGIN EXCLUSIVE", | ||
| 79 | - NULL | ||
| 80 | - }; | ||
| 81 | - | ||
| 82 | 74 | static void _pysqlite_drop_unused_cursor_references(pysqlite_Connection* self); | |
| 83 | 75 | static void free_callback_context(callback_context *ctx); | |
| 84 | 76 | static void set_callback_context(callback_context **ctx_pp, | |
@@ -108,25 +100,21 @@ new_statement_cache(pysqlite_Connection *self, pysqlite_state *state, | |||
| 108 | 100 | return res; | |
| 109 | 101 | } | |
| 110 | 102 | ||
| 111 | - static inline const char * | ||
| 112 | - begin_stmt_to_isolation_level(const char *begin_stmt) | ||
| 113 | - { | ||
| 114 | - assert(begin_stmt != NULL); | ||
| 115 | - | ||
| 116 | - // All begin statements start with "BEGIN "; add strlen("BEGIN ") to get | ||
| 117 | - // the isolation level. | ||
| 118 | - return begin_stmt + 6; | ||
| 119 | - } | ||
| 120 | - | ||
| 121 | 103 | static const char * | |
| 122 | - get_begin_statement(const char *level) | ||
| 104 | + get_isolation_level(const char *level) | ||
| 123 | 105 | { | |
| 124 | 106 | assert(level != NULL); | |
| 125 | - for (int i = 0; begin_statements[i] != NULL; i++) { | ||
| 126 | - const char *stmt = begin_statements[i]; | ||
| 127 | - const char *candidate = begin_stmt_to_isolation_level(stmt); | ||
| 107 | + static const char *const allowed_levels[] = { | ||
| 108 | + "", | ||
| 109 | + "DEFERRED", | ||
| 110 | + "IMMEDIATE", | ||
| 111 | + "EXCLUSIVE", | ||
| 112 | + NULL | ||
| 113 | + }; | ||
| 114 | + for (int i = 0; allowed_levels[i] != NULL; i++) { | ||
| 115 | + const char *candidate = allowed_levels[i]; | ||
| 128 | 116 | if (sqlite3_stricmp(level, candidate) == 0) { | |
| 129 | - return begin_statements[i]; | ||
| 117 | + return candidate; | ||
| 130 | 118 | } | |
| 131 | 119 | } | |
| 132 | 120 | PyErr_SetString(PyExc_ValueError, | |
@@ -202,10 +190,10 @@ pysqlite_connection_init_impl(pysqlite_Connection *self, | |||
| 202 | 190 | } | |
| 203 | 191 | ||
| 204 | 192 | // Convert isolation level to begin statement. | |
| 205 | - const char *begin_statement = NULL; | ||
| 193 | + const char *level = NULL; | ||
| 206 | 194 | if (isolation_level != NULL) { | |
| 207 | - begin_statement = get_begin_statement(isolation_level); | ||
| 208 | - if (begin_statement == NULL) { | ||
| 195 | + level = get_isolation_level(isolation_level); | ||
| 196 | + if (level == NULL) { | ||
| 209 | 197 | return -1; | |
| 210 | 198 | } | |
| 211 | 199 | } | |
@@ -227,7 +215,7 @@ pysqlite_connection_init_impl(pysqlite_Connection *self, | |||
| 227 | 215 | self->db = db; | |
| 228 | 216 | self->state = state; | |
| 229 | 217 | self->detect_types = detect_types; | |
| 230 | - self->begin_statement = begin_statement; | ||
| 218 | + self->isolation_level = level; | ||
| 231 | 219 | self->check_same_thread = check_same_thread; | |
| 232 | 220 | self->thread_ident = PyThread_get_thread_ident(); | |
| 233 | 221 | self->statement_cache = statement_cache; | |
@@ -1345,10 +1333,8 @@ static PyObject* pysqlite_connection_get_isolation_level(pysqlite_Connection* se | |||
| 1345 | 1333 | if (!pysqlite_check_connection(self)) { | |
| 1346 | 1334 | return NULL; | |
| 1347 | 1335 | } | |
| 1348 | - if (self->begin_statement != NULL) { | ||
| 1349 | - const char *stmt = self->begin_statement; | ||
| 1350 | - const char *iso_level = begin_stmt_to_isolation_level(stmt); | ||
| 1351 | - return PyUnicode_FromString(iso_level); | ||
| 1336 | + if (self->isolation_level != NULL) { | ||
| 1337 | + return PyUnicode_FromString(self->isolation_level); | ||
| 1352 | 1338 | } | |
| 1353 | 1339 | Py_RETURN_NONE; | |
| 1354 | 1340 | } | |
@@ -1381,7 +1367,7 @@ pysqlite_connection_set_isolation_level(pysqlite_Connection* self, PyObject* iso | |||
| 1381 | 1367 | return -1; | |
| 1382 | 1368 | } | |
| 1383 | 1369 | if (Py_IsNone(isolation_level)) { | |
| 1384 | - self->begin_statement = NULL; | ||
| 1370 | + self->isolation_level = NULL; | ||
| 1385 | 1371 | ||
| 1386 | 1372 | // Execute a COMMIT to re-enable autocommit mode | |
| 1387 | 1373 | PyObject *res = pysqlite_connection_commit_impl(self); | |
@@ -1400,11 +1386,11 @@ pysqlite_connection_set_isolation_level(pysqlite_Connection* self, PyObject* iso | |||
| 1400 | 1386 | PyErr_SetString(PyExc_ValueError, "embedded null character"); | |
| 1401 | 1387 | return -1; | |
| 1402 | 1388 | } | |
| 1403 | - const char *stmt = get_begin_statement(cstr_level); | ||
| 1404 | - if (stmt == NULL) { | ||
| 1389 | + const char *level = get_isolation_level(cstr_level); | ||
| 1390 | + if (level == NULL) { | ||
| 1405 | 1391 | return -1; | |
| 1406 | 1392 | } | |
| 1407 | - self->begin_statement = stmt; | ||
| 1393 | + self->isolation_level = level; | ||
| 1408 | 1394 | } | |
| 1409 | 1395 | else { | |
| 1410 | 1396 | PyErr_SetString(PyExc_TypeError, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -42,15 +42,15 @@ typedef struct _callback_context | |||
| 42 | 42 | typedef struct | |
| 43 | 43 | { | |
| 44 | 44 | PyObject_HEAD | |
| 45 | - sqlite3* db; | ||
| 45 | + sqlite3 *db; | ||
| 46 | 46 | pysqlite_state *state; | |
| 47 | 47 | ||
| 48 | 48 | /* the type detection mode. Only 0, PARSE_DECLTYPES, PARSE_COLNAMES or a | |
| 49 | 49 | * bitwise combination thereof makes sense */ | |
| 50 | 50 | int detect_types; | |
| 51 | 51 | ||
| 52 | - /* NULL for autocommit, otherwise a string with the BEGIN statement */ | ||
| 53 | - const char* begin_statement; | ||
| 52 | + /* NULL for autocommit, otherwise a string with the isolation level */ | ||
| 53 | + const char *isolation_level; | ||
| 54 | 54 | ||
| 55 | 55 | /* 1 if a check should be performed for each API call if the connection is | |
| 56 | 56 | * used from the same thread it was created in */ | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -430,12 +430,18 @@ static int check_cursor(pysqlite_Cursor* cur) | |||
| 430 | 430 | static int | |
| 431 | 431 | begin_transaction(pysqlite_Connection *self) | |
| 432 | 432 | { | |
| 433 | + assert(self->isolation_level != NULL); | ||
| 433 | 434 | int rc; | |
| 434 | 435 | ||
| 435 | 436 | Py_BEGIN_ALLOW_THREADS | |
| 436 | 437 | sqlite3_stmt *statement; | |
| 437 | - rc = sqlite3_prepare_v2(self->db, self->begin_statement, -1, &statement, | ||
| 438 | - NULL); | ||
| 438 | + char begin_stmt[16] = "BEGIN "; | ||
| 439 | + #ifdef Py_DEBUG | ||
| 440 | + size_t len = strlen(self->isolation_level); | ||
| 441 | + assert(len <= 9); | ||
| 442 | + #endif | ||
| 443 | + (void)strcat(begin_stmt, self->isolation_level); | ||
| 444 | + rc = sqlite3_prepare_v2(self->db, begin_stmt, -1, &statement, NULL); | ||
| 439 | 445 | if (rc == SQLITE_OK) { | |
| 440 | 446 | (void)sqlite3_step(statement); | |
| 441 | 447 | rc = sqlite3_finalize(statement); | |
@@ -555,7 +561,7 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation | |||
| 555 | 561 | ||
| 556 | 562 | /* We start a transaction implicitly before a DML statement. | |
| 557 | 563 | SELECT is the only exception. See #9924. */ | |
| 558 | - if (self->connection->begin_statement | ||
| 564 | + if (self->connection->isolation_level | ||
| 559 | 565 | && self->statement->is_dml | |
| 560 | 566 | && sqlite3_get_autocommit(self->connection->db)) | |
| 561 | 567 | { | |
| Back | FazBrowse Home | New Git URL |
0 commit comments