Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
82 commits
Select commit Hold shift + click to select a range
10d3a65
Add sqlite3.Connection.autocommit for PEP 249 compliant behaviour
erlend-aasland Jun 11, 2022
6ca9045
Add basic tests
erlend-aasland Jun 14, 2022
5772676
Add documentation
erlend-aasland Jun 14, 2022
06609f3
Add NEWS
erlend-aasland Jun 14, 2022
8b6b866
Add What's New
erlend-aasland Jun 14, 2022
a604a57
Document DEPRECATED_TRANSACTION_CONTROL
erlend-aasland Jun 14, 2022
cbc1041
Fix setattr behaviour
erlend-aasland Jun 14, 2022
41b898c
Suggest new behaviour starting with Python 3.14
erlend-aasland Jun 15, 2022
b11ebd2
Simplify implicit rollback test
erlend-aasland Jun 15, 2022
d3009d4
Address Alex' review
erlend-aasland Jun 15, 2022
fb98615
Reorder if condition to add emphasis to deprecated behaviour
erlend-aasland Jun 15, 2022
5e4626e
Add context manager tests
erlend-aasland Jun 15, 2022
a8e3b9e
Improve 5e4626ecf47a679ba5fa8846472af16fb325cac5
erlend-aasland Jun 15, 2022
d46e9be
Add executescript tests
erlend-aasland Jun 15, 2022
c2e2f1a
Improve docs
erlend-aasland Jun 15, 2022
3bf3ee1
Add missing versionadded
erlend-aasland Jun 16, 2022
757f70b
Try to further improve the docs
erlend-aasland Jun 16, 2022
a5ef40c
Nano-optimisation
erlend-aasland Jun 16, 2022
ae37fbb
Explicit downcast
erlend-aasland Jun 17, 2022
341e0dd
Clarify execute*, commit, rollback, and close
erlend-aasland Jun 17, 2022
77651c0
Incorporate gh-93890 changes
erlend-aasland Jun 17, 2022
0ac782c
Improve
erlend-aasland Jun 17, 2022
7743f34
Merge branch 'main' into sqlite-autocommit
erlend-aasland Jun 19, 2022
6628e30
commit/rollback wordings
erlend-aasland Jun 19, 2022
060bd3a
Fix merge
erlend-aasland Jun 19, 2022
c96adbf
Doc: reword context manager section
erlend-aasland Jun 20, 2022
a7c7c4c
Autocommit is keyword only
erlend-aasland Jun 24, 2022
f1c5843
Isolation level is not yet deprecated (soon it will be though)
erlend-aasland Jun 24, 2022
491426e
Merge remote-tracking branch 'upstream/main' into sqlite-autocommit
erlend-aasland Jun 24, 2022
05879a9
Merge branch 'main' into sqlite-autocommit
erlend-aasland Jun 27, 2022
97ad734
Use macro as C default
erlend-aasland Jun 27, 2022
bf3a857
Merge branch 'main' into sqlite-autocommit
erlend-aasland Jul 8, 2022
60f7224
Merge branch 'main' into sqlite-autocommit
erlend-aasland Jul 18, 2022
7f645ee
Pass keywords to factory function
erlend-aasland Jul 20, 2022
88fb2b9
Merge branch 'main' into sqlite-autocommit
erlend-aasland Jul 20, 2022
4deed17
Adjust commit/rollback and remove redundant info
erlend-aasland Jul 20, 2022
f3a9e37
Merge branch 'main' into sqlite-autocommit
erlend-aasland Jul 23, 2022
2981a6b
Fix docstring
erlend-aasland Jul 23, 2022
a5b7864
Revert unneeded doc changes
erlend-aasland Jul 23, 2022
fd6659a
Fix autocommit enum
erlend-aasland Jul 23, 2022
52e3736
Sync with main bco. recent doc updates
erlend-aasland Jul 26, 2022
6e92073
Merge branch 'main' into sqlite-autocommit
erlend-aasland Jul 30, 2022
59fbd29
Merge branch 'main' into sqlite-autocommit
erlend-aasland Aug 3, 2022
894fcce
Add autocommit to connect signature
erlend-aasland Aug 3, 2022
fff4307
Merge branch 'main' into sqlite-autocommit
erlend-aasland Aug 8, 2022
4ac0fa0
Address Alex's second review
erlend-aasland Aug 8, 2022
64c6482
Adjust headings
erlend-aasland Aug 8, 2022
e4947d0
Use versionadded iso. versionchanged
erlend-aasland Aug 8, 2022
5981536
Remove some no-ops
erlend-aasland Aug 8, 2022
527e6a3
Three adjustments:
erlend-aasland Aug 8, 2022
697b65a
Address Alex's last round of review
erlend-aasland Aug 15, 2022
4299874
Sync with main bco. recent Argument Clinic changes
erlend-aasland Aug 15, 2022
76122be
Regen all
erlend-aasland Aug 15, 2022
6902738
Explicit logic in set_autocommit
erlend-aasland Aug 15, 2022
c37ebb5
Tweak naming: connection_txn_stmt => connection_exec_stmt
erlend-aasland Aug 15, 2022
2e9083c
Merge branch 'main' into sqlite-autocommit
erlend-aasland Aug 18, 2022
b944a90
Address review: improve wording for connection close()
erlend-aasland Aug 18, 2022
bce921f
Sync with main
erlend-aasland Oct 28, 2022
78e04f0
Fix bad merge
erlend-aasland Oct 28, 2022
bd91e34
Remove implicit commit for cx.autocommit = False
erlend-aasland Oct 28, 2022
9d66daa
Doc: make the autocommit reference more to the point; expand in the e…
erlend-aasland Oct 28, 2022
d4c0583
Address most of CAM's review
erlend-aasland Oct 29, 2022
a3aa9aa
Better naming for the constant; don't mention deprecations (yet)
erlend-aasland Oct 29, 2022
c9b05ff
Fix default role
erlend-aasland Oct 30, 2022
d5e33f1
Make it explicit that isolation_level is ignored if autocommit is Tru…
erlend-aasland Oct 30, 2022
0cf022a
Reflow
erlend-aasland Oct 30, 2022
5009372
Address review: COMPAT_TRANSACTIONAL_CONTROL => LEGACY_TRANSACTION_CO…
erlend-aasland Oct 31, 2022
2c9b117
Address more of CAM's review
erlend-aasland Oct 31, 2022
de3bd4e
Try to address the rest of CAM's review
erlend-aasland Oct 31, 2022
fca9c56
Sync with main
erlend-aasland Nov 6, 2022
7de6bf3
Address more of CAM's remarks
erlend-aasland Nov 6, 2022
e0fa134
Prevent segfault if implicitly rolling back during interpreter shutdown
erlend-aasland Nov 6, 2022
e0bedf6
Update Doc/library/sqlite3.rst
Nov 7, 2022
e33946a
Address last batch of CAM's comments
erlend-aasland Nov 7, 2022
cd15505
Last bit
erlend-aasland Nov 8, 2022
4feefa1
Update Doc/library/sqlite3.rst
Nov 11, 2022
720ac11
Sync with main
erlend-aasland Nov 11, 2022
f7c2ae4
Update Doc/library/sqlite3.rst
Nov 11, 2022
88e1420
Sync with main
erlend-aasland Nov 12, 2022
7b87830
Address review: remove unneeded assert in test_autocommit_setget_invalid
erlend-aasland Nov 12, 2022
8322683
Address review: add test for rollback() if autocommit is True
erlend-aasland Nov 12, 2022
aca1e22
Address review: fixup context manager docs
erlend-aasland Nov 12, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Add sqlite3.Connection.autocommit for PEP 249 compliant behaviour
  • Loading branch information
erlend-aasland committed Jun 14, 2022
commit 10d3a652b99390ea1e0aee539d473a144b01dbbe
26 changes: 18 additions & 8 deletions Modules/_sqlite/clinic/connection.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 18 additions & 10 deletions Modules/_sqlite/clinic/module.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

147 changes: 115 additions & 32 deletions Modules/_sqlite/connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,30 @@ isolation_level_converter(PyObject *str_or_none, const char **result)
return 1;
}

static int
autocommit_converter(PyObject *val, enum autocommit_mode *result)
{
if (Py_IsTrue(val)) {
*result = AUTOCOMMIT_ENABLED;
return 1;
}
if (Py_IsFalse(val)) {
*result = AUTOCOMMIT_DISABLED;
return 1;
}
if (PyLong_Check(val) &&
PyLong_AsLong(val) == DEPRECATED_TRANSACTION_CONTROL)
{
*result = AUTOCOMMIT_COMPAT;
return 1;
}

PyErr_SetString(PyExc_ValueError,
"autocommit must be True, False, or "
"sqlite3.DEPRECATED_TRANSACTION_CONTROL");
return 0;
}

#define clinic_state() (pysqlite_get_state_by_type(Py_TYPE(self)))
#include "clinic/connection.c.h"
#undef clinic_state
Expand Down Expand Up @@ -132,13 +156,37 @@ new_statement_cache(pysqlite_Connection *self, pysqlite_state *state,
return res;
}

static inline int
connection_txn_stmt(pysqlite_Connection *self, const char *sql)
{
int rc;
Py_BEGIN_ALLOW_THREADS
sqlite3_stmt *stmt;
rc = sqlite3_prepare_v2(self->db, sql, -1, &stmt, NULL);
if (rc == SQLITE_OK) {
(void)sqlite3_step(stmt);
rc = sqlite3_finalize(stmt);
}
Py_END_ALLOW_THREADS

if (rc != SQLITE_OK) {
(void)_pysqlite_seterror(self->state, self->db);
return -1;
}
return 0;
}

/*[python input]
class IsolationLevel_converter(CConverter):
type = "const char *"
converter = "isolation_level_converter"

class Autocommit_converter(CConverter):
type = "enum autocommit_mode"
converter = "autocommit_converter"

[python start generated code]*/
/*[python end generated code: output=da39a3ee5e6b4b0d input=cbcfe85b253061c2]*/
/*[python end generated code: output=da39a3ee5e6b4b0d input=bc2aa6c7ba0c5f8f]*/

/*[clinic input]
_sqlite3.Connection.__init__ as pysqlite_connection_init
Expand All @@ -151,15 +199,17 @@ _sqlite3.Connection.__init__ as pysqlite_connection_init
factory: object(c_default='(PyObject*)clinic_state()->ConnectionType') = ConnectionType
cached_statements as cache_size: int = 128
uri: bool = False
autocommit: Autocommit(c_default='-1') = sqlite3.DEPRECATED_TRANSACTION_CONTROL
[clinic start generated code]*/

static int
pysqlite_connection_init_impl(pysqlite_Connection *self, PyObject *database,
double timeout, int detect_types,
const char *isolation_level,
int check_same_thread, PyObject *factory,
int cache_size, int uri)
/*[clinic end generated code: output=839eb2fee4293bda input=b8ce63dc6f70a383]*/
int cache_size, int uri,
enum autocommit_mode autocommit)
/*[clinic end generated code: output=cba057313ea7712f input=82b8f749d645f63d]*/
{
if (PySys_Audit("sqlite3.connect", "O", database) < 0) {
return -1;
Expand Down Expand Up @@ -226,6 +276,7 @@ pysqlite_connection_init_impl(pysqlite_Connection *self, PyObject *database,
self->state = state;
self->detect_types = detect_types;
self->isolation_level = isolation_level;
self->autocommit = autocommit;
self->check_same_thread = check_same_thread;
self->thread_ident = PyThread_get_thread_ident();
self->statement_cache = statement_cache;
Expand Down Expand Up @@ -255,6 +306,10 @@ pysqlite_connection_init_impl(pysqlite_Connection *self, PyObject *database,
}

self->initialized = 1;

if (autocommit == AUTOCOMMIT_DISABLED) {
(void)connection_txn_stmt(self, "BEGIN");
}
return 0;

error:
Expand Down Expand Up @@ -324,6 +379,12 @@ static void
connection_close(pysqlite_Connection *self)
{
if (self->db) {
if (self->autocommit == AUTOCOMMIT_DISABLED &&
!sqlite3_get_autocommit(self->db))
{
(void)connection_txn_stmt(self, "ROLLBACK");
}

free_callback_contexts(self);

sqlite3 *db = self->db;
Expand Down Expand Up @@ -533,24 +594,21 @@ pysqlite_connection_commit_impl(pysqlite_Connection *self)
return NULL;
}

if (!sqlite3_get_autocommit(self->db)) {
int rc;

Py_BEGIN_ALLOW_THREADS
sqlite3_stmt *statement;
rc = sqlite3_prepare_v2(self->db, "COMMIT", 7, &statement, NULL);
if (rc == SQLITE_OK) {
(void)sqlite3_step(statement);
rc = sqlite3_finalize(statement);
if (self->autocommit == AUTOCOMMIT_COMPAT) {
if (!sqlite3_get_autocommit(self->db)) {
if (connection_txn_stmt(self, "COMMIT") < 0) {
return NULL;
}
}
Py_END_ALLOW_THREADS

if (rc != SQLITE_OK) {
(void)_pysqlite_seterror(self->state, self->db);
}
else if (self->autocommit == AUTOCOMMIT_DISABLED) {
if (connection_txn_stmt(self, "COMMIT") < 0) {
return NULL;
}
if (connection_txn_stmt(self, "BEGIN") < 0) {
return NULL;
}
}

Py_RETURN_NONE;
}

Expand All @@ -568,25 +626,21 @@ pysqlite_connection_rollback_impl(pysqlite_Connection *self)
return NULL;
}

if (!sqlite3_get_autocommit(self->db)) {
int rc;

Py_BEGIN_ALLOW_THREADS
sqlite3_stmt *statement;
rc = sqlite3_prepare_v2(self->db, "ROLLBACK", 9, &statement, NULL);
if (rc == SQLITE_OK) {
(void)sqlite3_step(statement);
rc = sqlite3_finalize(statement);
if (self->autocommit == AUTOCOMMIT_COMPAT) {
if (!sqlite3_get_autocommit(self->db)) {
if (connection_txn_stmt(self, "ROLLBACK") < 0) {
return NULL;
}
}
Py_END_ALLOW_THREADS

if (rc != SQLITE_OK) {
(void)_pysqlite_seterror(self->state, self->db);
}
else if (self->autocommit == AUTOCOMMIT_DISABLED) {
if (connection_txn_stmt(self, "ROLLBACK") < 0) {
return NULL;
}
if (connection_txn_stmt(self, "BEGIN") < 0) {
return NULL;
}

}

Py_RETURN_NONE;
}

Expand Down Expand Up @@ -2264,13 +2318,42 @@ getlimit_impl(pysqlite_Connection *self, int category)
}


static PyObject *
get_autocommit(pysqlite_Connection *self, void *Py_UNUSED(ctx))
{
if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {
return NULL;
}
if (self->autocommit == AUTOCOMMIT_ENABLED) {
Py_RETURN_TRUE;
}
if (self->autocommit == AUTOCOMMIT_DISABLED) {
Py_RETURN_FALSE;
}
return PyLong_FromLong(DEPRECATED_TRANSACTION_CONTROL);
}

static int
set_autocommit(pysqlite_Connection *self, PyObject *val, void *Py_UNUSED(ctx))
{
if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {
return -1;
}
if (!autocommit_converter(val, &self->autocommit)) {
return -1;
}
return 0;
}


static const char connection_doc[] =
PyDoc_STR("SQLite database connection object.");

static PyGetSetDef connection_getset[] = {
{"isolation_level", (getter)pysqlite_connection_get_isolation_level, (setter)pysqlite_connection_set_isolation_level},
{"total_changes", (getter)pysqlite_connection_get_total_changes, (setter)0},
{"in_transaction", (getter)pysqlite_connection_get_in_transaction, (setter)0},
{"autocommit", (getter)get_autocommit, (setter)set_autocommit},
{NULL}
};

Expand Down
7 changes: 7 additions & 0 deletions Modules/_sqlite/connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ typedef struct _callback_context
pysqlite_state *state;
} callback_context;

enum autocommit_mode {
AUTOCOMMIT_COMPAT,
AUTOCOMMIT_ENABLED,
AUTOCOMMIT_DISABLED,
};

typedef struct
{
PyObject_HEAD
Expand All @@ -51,6 +57,7 @@ typedef struct

/* NULL for autocommit, otherwise a string with the isolation level */
const char *isolation_level;
enum autocommit_mode autocommit;

/* 1 if a check should be performed for each API call if the connection is
* used from the same thread it was created in */
Expand Down
Loading