aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/tools/python3/src/Modules/_sqlite
diff options
context:
space:
mode:
authorshadchin <shadchin@yandex-team.com>2024-02-12 07:53:52 +0300
committerDaniil Cherednik <dcherednik@ydb.tech>2024-02-14 14:26:16 +0000
commit31f2a419764a8ba77c2a970cfc80056c6cd06756 (patch)
treec1995d239eba8571cefc640f6648e1d5dd4ce9e2 /contrib/tools/python3/src/Modules/_sqlite
parentfe2ef02b38d9c85d80060963b265a1df9f38c3bb (diff)
downloadydb-31f2a419764a8ba77c2a970cfc80056c6cd06756.tar.gz
Update Python from 3.11.8 to 3.12.2
Diffstat (limited to 'contrib/tools/python3/src/Modules/_sqlite')
-rw-r--r--contrib/tools/python3/src/Modules/_sqlite/clinic/blob.c.h8
-rw-r--r--contrib/tools/python3/src/Modules/_sqlite/clinic/connection.c.h499
-rw-r--r--contrib/tools/python3/src/Modules/_sqlite/clinic/cursor.c.h38
-rw-r--r--contrib/tools/python3/src/Modules/_sqlite/clinic/module.c.h73
-rw-r--r--contrib/tools/python3/src/Modules/_sqlite/clinic/row.c.h12
-rw-r--r--contrib/tools/python3/src/Modules/_sqlite/connection.c447
-rw-r--r--contrib/tools/python3/src/Modules/_sqlite/connection.h7
-rw-r--r--contrib/tools/python3/src/Modules/_sqlite/cursor.c86
-rw-r--r--contrib/tools/python3/src/Modules/_sqlite/microprotocols.c4
-rw-r--r--contrib/tools/python3/src/Modules/_sqlite/module.c92
-rw-r--r--contrib/tools/python3/src/Modules/_sqlite/module.h2
-rw-r--r--contrib/tools/python3/src/Modules/_sqlite/statement.c1
-rw-r--r--contrib/tools/python3/src/Modules/_sqlite/statement.h1
-rw-r--r--contrib/tools/python3/src/Modules/_sqlite/ya.make5
14 files changed, 1000 insertions, 275 deletions
diff --git a/contrib/tools/python3/src/Modules/_sqlite/clinic/blob.c.h b/contrib/tools/python3/src/Modules/_sqlite/clinic/blob.c.h
index b467c99e2e..f3d8a35be4 100644
--- a/contrib/tools/python3/src/Modules/_sqlite/clinic/blob.c.h
+++ b/contrib/tools/python3/src/Modules/_sqlite/clinic/blob.c.h
@@ -2,6 +2,12 @@
preserve
[clinic start generated code]*/
+#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+# include "pycore_gc.h" // PyGC_Head
+# include "pycore_runtime.h" // _Py_ID()
+#endif
+
+
PyDoc_STRVAR(blob_close__doc__,
"close($self, /)\n"
"--\n"
@@ -213,4 +219,4 @@ blob_exit(pysqlite_Blob *self, PyObject *const *args, Py_ssize_t nargs)
exit:
return return_value;
}
-/*[clinic end generated code: output=382cbf0977bb158a input=a9049054013a1b77]*/
+/*[clinic end generated code: output=ad6a402f70e85977 input=a9049054013a1b77]*/
diff --git a/contrib/tools/python3/src/Modules/_sqlite/clinic/connection.c.h b/contrib/tools/python3/src/Modules/_sqlite/clinic/connection.c.h
index 4bdf98b693..417abcc462 100644
--- a/contrib/tools/python3/src/Modules/_sqlite/clinic/connection.c.h
+++ b/contrib/tools/python3/src/Modules/_sqlite/clinic/connection.c.h
@@ -2,20 +2,50 @@
preserve
[clinic start generated code]*/
+#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+# include "pycore_gc.h" // PyGC_Head
+# include "pycore_runtime.h" // _Py_ID()
+#endif
+
+
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);
+ int cache_size, int uri,
+ enum autocommit_mode autocommit);
static int
pysqlite_connection_init(PyObject *self, PyObject *args, PyObject *kwargs)
{
int return_value = -1;
- static const char * const _keywords[] = {"database", "timeout", "detect_types", "isolation_level", "check_same_thread", "factory", "cached_statements", "uri", NULL};
- static _PyArg_Parser _parser = {NULL, _keywords, "Connection", 0};
- PyObject *argsbuf[8];
+ #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+
+ #define NUM_KEYWORDS 9
+ static struct {
+ PyGC_Head _this_is_not_used;
+ PyObject_VAR_HEAD
+ PyObject *ob_item[NUM_KEYWORDS];
+ } _kwtuple = {
+ .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_item = { &_Py_ID(database), &_Py_ID(timeout), &_Py_ID(detect_types), &_Py_ID(isolation_level), &_Py_ID(check_same_thread), &_Py_ID(factory), &_Py_ID(cached_statements), &_Py_ID(uri), &_Py_ID(autocommit), },
+ };
+ #undef NUM_KEYWORDS
+ #define KWTUPLE (&_kwtuple.ob_base.ob_base)
+
+ #else // !Py_BUILD_CORE
+ # define KWTUPLE NULL
+ #endif // !Py_BUILD_CORE
+
+ static const char * const _keywords[] = {"database", "timeout", "detect_types", "isolation_level", "check_same_thread", "factory", "cached_statements", "uri", "autocommit", NULL};
+ static _PyArg_Parser _parser = {
+ .keywords = _keywords,
+ .fname = "Connection",
+ .kwtuple = KWTUPLE,
+ };
+ #undef KWTUPLE
+ PyObject *argsbuf[9];
PyObject * const *fastargs;
Py_ssize_t nargs = PyTuple_GET_SIZE(args);
Py_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 1;
@@ -27,6 +57,7 @@ pysqlite_connection_init(PyObject *self, PyObject *args, PyObject *kwargs)
PyObject *factory = (PyObject*)clinic_state()->ConnectionType;
int cache_size = 128;
int uri = 0;
+ enum autocommit_mode autocommit = LEGACY_TRANSACTION_CONTROL;
fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 1, 8, 0, argsbuf);
if (!fastargs) {
@@ -69,8 +100,8 @@ pysqlite_connection_init(PyObject *self, PyObject *args, PyObject *kwargs)
}
}
if (fastargs[4]) {
- check_same_thread = _PyLong_AsInt(fastargs[4]);
- if (check_same_thread == -1 && PyErr_Occurred()) {
+ check_same_thread = PyObject_IsTrue(fastargs[4]);
+ if (check_same_thread < 0) {
goto exit;
}
if (!--noptargs) {
@@ -92,12 +123,24 @@ pysqlite_connection_init(PyObject *self, PyObject *args, PyObject *kwargs)
goto skip_optional_pos;
}
}
- uri = PyObject_IsTrue(fastargs[7]);
- if (uri < 0) {
- goto exit;
+ if (fastargs[7]) {
+ uri = PyObject_IsTrue(fastargs[7]);
+ if (uri < 0) {
+ goto exit;
+ }
+ if (!--noptargs) {
+ goto skip_optional_pos;
+ }
}
skip_optional_pos:
- return_value = pysqlite_connection_init_impl((pysqlite_Connection *)self, database, timeout, detect_types, isolation_level, check_same_thread, factory, cache_size, uri);
+ if (!noptargs) {
+ goto skip_optional_kwonly;
+ }
+ if (!autocommit_converter(fastargs[8], &autocommit)) {
+ goto exit;
+ }
+skip_optional_kwonly:
+ return_value = pysqlite_connection_init_impl((pysqlite_Connection *)self, database, timeout, detect_types, isolation_level, check_same_thread, factory, cache_size, uri, autocommit);
exit:
return return_value;
@@ -119,8 +162,31 @@ static PyObject *
pysqlite_connection_cursor(pysqlite_Connection *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
+ #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+
+ #define NUM_KEYWORDS 1
+ static struct {
+ PyGC_Head _this_is_not_used;
+ PyObject_VAR_HEAD
+ PyObject *ob_item[NUM_KEYWORDS];
+ } _kwtuple = {
+ .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_item = { &_Py_ID(factory), },
+ };
+ #undef NUM_KEYWORDS
+ #define KWTUPLE (&_kwtuple.ob_base.ob_base)
+
+ #else // !Py_BUILD_CORE
+ # define KWTUPLE NULL
+ #endif // !Py_BUILD_CORE
+
static const char * const _keywords[] = {"factory", NULL};
- static _PyArg_Parser _parser = {NULL, _keywords, "cursor", 0};
+ static _PyArg_Parser _parser = {
+ .keywords = _keywords,
+ .fname = "cursor",
+ .kwtuple = KWTUPLE,
+ };
+ #undef KWTUPLE
PyObject *argsbuf[1];
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
PyObject *factory = NULL;
@@ -168,8 +234,31 @@ static PyObject *
blobopen(pysqlite_Connection *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
+ #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+
+ #define NUM_KEYWORDS 2
+ static struct {
+ PyGC_Head _this_is_not_used;
+ PyObject_VAR_HEAD
+ PyObject *ob_item[NUM_KEYWORDS];
+ } _kwtuple = {
+ .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_item = { &_Py_ID(readonly), &_Py_ID(name), },
+ };
+ #undef NUM_KEYWORDS
+ #define KWTUPLE (&_kwtuple.ob_base.ob_base)
+
+ #else // !Py_BUILD_CORE
+ # define KWTUPLE NULL
+ #endif // !Py_BUILD_CORE
+
static const char * const _keywords[] = {"", "", "", "readonly", "name", NULL};
- static _PyArg_Parser _parser = {NULL, _keywords, "blobopen", 0};
+ static _PyArg_Parser _parser = {
+ .keywords = _keywords,
+ .fname = "blobopen",
+ .kwtuple = KWTUPLE,
+ };
+ #undef KWTUPLE
PyObject *argsbuf[5];
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3;
const char *table;
@@ -215,8 +304,8 @@ blobopen(pysqlite_Connection *self, PyObject *const *args, Py_ssize_t nargs, PyO
goto skip_optional_kwonly;
}
if (args[3]) {
- readonly = _PyLong_AsInt(args[3]);
- if (readonly == -1 && PyErr_Occurred()) {
+ readonly = PyObject_IsTrue(args[3]);
+ if (readonly < 0) {
goto exit;
}
if (!--noptargs) {
@@ -322,8 +411,31 @@ static PyObject *
pysqlite_connection_create_function(pysqlite_Connection *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
+ #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+
+ #define NUM_KEYWORDS 4
+ static struct {
+ PyGC_Head _this_is_not_used;
+ PyObject_VAR_HEAD
+ PyObject *ob_item[NUM_KEYWORDS];
+ } _kwtuple = {
+ .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_item = { &_Py_ID(name), &_Py_ID(narg), &_Py_ID(func), &_Py_ID(deterministic), },
+ };
+ #undef NUM_KEYWORDS
+ #define KWTUPLE (&_kwtuple.ob_base.ob_base)
+
+ #else // !Py_BUILD_CORE
+ # define KWTUPLE NULL
+ #endif // !Py_BUILD_CORE
+
static const char * const _keywords[] = {"name", "narg", "func", "deterministic", NULL};
- static _PyArg_Parser _parser = {NULL, _keywords, "create_function", 0};
+ static _PyArg_Parser _parser = {
+ .keywords = _keywords,
+ .fname = "create_function",
+ .kwtuple = KWTUPLE,
+ };
+ #undef KWTUPLE
PyObject *argsbuf[4];
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3;
const char *name;
@@ -396,8 +508,19 @@ static PyObject *
create_window_function(pysqlite_Connection *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
+ #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+ # define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty)
+ #else
+ # define KWTUPLE NULL
+ #endif
+
static const char * const _keywords[] = {"", "", "", NULL};
- static _PyArg_Parser _parser = {NULL, _keywords, "create_window_function", 0};
+ static _PyArg_Parser _parser = {
+ .keywords = _keywords,
+ .fname = "create_window_function",
+ .kwtuple = KWTUPLE,
+ };
+ #undef KWTUPLE
PyObject *argsbuf[3];
const char *name;
int num_params;
@@ -452,8 +575,31 @@ static PyObject *
pysqlite_connection_create_aggregate(pysqlite_Connection *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
+ #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+
+ #define NUM_KEYWORDS 3
+ static struct {
+ PyGC_Head _this_is_not_used;
+ PyObject_VAR_HEAD
+ PyObject *ob_item[NUM_KEYWORDS];
+ } _kwtuple = {
+ .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_item = { &_Py_ID(name), &_Py_ID(n_arg), &_Py_ID(aggregate_class), },
+ };
+ #undef NUM_KEYWORDS
+ #define KWTUPLE (&_kwtuple.ob_base.ob_base)
+
+ #else // !Py_BUILD_CORE
+ # define KWTUPLE NULL
+ #endif // !Py_BUILD_CORE
+
static const char * const _keywords[] = {"name", "n_arg", "aggregate_class", NULL};
- static _PyArg_Parser _parser = {NULL, _keywords, "create_aggregate", 0};
+ static _PyArg_Parser _parser = {
+ .keywords = _keywords,
+ .fname = "create_aggregate",
+ .kwtuple = KWTUPLE,
+ };
+ #undef KWTUPLE
PyObject *argsbuf[3];
const char *name;
int n_arg;
@@ -505,8 +651,31 @@ static PyObject *
pysqlite_connection_set_authorizer(pysqlite_Connection *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
+ #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+
+ #define NUM_KEYWORDS 1
+ static struct {
+ PyGC_Head _this_is_not_used;
+ PyObject_VAR_HEAD
+ PyObject *ob_item[NUM_KEYWORDS];
+ } _kwtuple = {
+ .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_item = { &_Py_ID(authorizer_callback), },
+ };
+ #undef NUM_KEYWORDS
+ #define KWTUPLE (&_kwtuple.ob_base.ob_base)
+
+ #else // !Py_BUILD_CORE
+ # define KWTUPLE NULL
+ #endif // !Py_BUILD_CORE
+
static const char * const _keywords[] = {"authorizer_callback", NULL};
- static _PyArg_Parser _parser = {NULL, _keywords, "set_authorizer", 0};
+ static _PyArg_Parser _parser = {
+ .keywords = _keywords,
+ .fname = "set_authorizer",
+ .kwtuple = KWTUPLE,
+ };
+ #undef KWTUPLE
PyObject *argsbuf[1];
PyObject *callable;
@@ -539,8 +708,31 @@ static PyObject *
pysqlite_connection_set_progress_handler(pysqlite_Connection *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
+ #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+
+ #define NUM_KEYWORDS 2
+ static struct {
+ PyGC_Head _this_is_not_used;
+ PyObject_VAR_HEAD
+ PyObject *ob_item[NUM_KEYWORDS];
+ } _kwtuple = {
+ .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_item = { &_Py_ID(progress_handler), &_Py_ID(n), },
+ };
+ #undef NUM_KEYWORDS
+ #define KWTUPLE (&_kwtuple.ob_base.ob_base)
+
+ #else // !Py_BUILD_CORE
+ # define KWTUPLE NULL
+ #endif // !Py_BUILD_CORE
+
static const char * const _keywords[] = {"progress_handler", "n", NULL};
- static _PyArg_Parser _parser = {NULL, _keywords, "set_progress_handler", 0};
+ static _PyArg_Parser _parser = {
+ .keywords = _keywords,
+ .fname = "set_progress_handler",
+ .kwtuple = KWTUPLE,
+ };
+ #undef KWTUPLE
PyObject *argsbuf[2];
PyObject *callable;
int n;
@@ -578,8 +770,31 @@ static PyObject *
pysqlite_connection_set_trace_callback(pysqlite_Connection *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
+ #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+
+ #define NUM_KEYWORDS 1
+ static struct {
+ PyGC_Head _this_is_not_used;
+ PyObject_VAR_HEAD
+ PyObject *ob_item[NUM_KEYWORDS];
+ } _kwtuple = {
+ .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_item = { &_Py_ID(trace_callback), },
+ };
+ #undef NUM_KEYWORDS
+ #define KWTUPLE (&_kwtuple.ob_base.ob_base)
+
+ #else // !Py_BUILD_CORE
+ # define KWTUPLE NULL
+ #endif // !Py_BUILD_CORE
+
static const char * const _keywords[] = {"trace_callback", NULL};
- static _PyArg_Parser _parser = {NULL, _keywords, "set_trace_callback", 0};
+ static _PyArg_Parser _parser = {
+ .keywords = _keywords,
+ .fname = "set_trace_callback",
+ .kwtuple = KWTUPLE,
+ };
+ #undef KWTUPLE
PyObject *argsbuf[1];
PyObject *callable;
@@ -615,8 +830,8 @@ pysqlite_connection_enable_load_extension(pysqlite_Connection *self, PyObject *a
PyObject *return_value = NULL;
int onoff;
- onoff = _PyLong_AsInt(arg);
- if (onoff == -1 && PyErr_Occurred()) {
+ onoff = PyObject_IsTrue(arg);
+ if (onoff < 0) {
goto exit;
}
return_value = pysqlite_connection_enable_load_extension_impl(self, onoff);
@@ -630,30 +845,63 @@ exit:
#if defined(PY_SQLITE_ENABLE_LOAD_EXTENSION)
PyDoc_STRVAR(pysqlite_connection_load_extension__doc__,
-"load_extension($self, name, /)\n"
+"load_extension($self, name, /, *, entrypoint=None)\n"
"--\n"
"\n"
"Load SQLite extension module.");
#define PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF \
- {"load_extension", (PyCFunction)pysqlite_connection_load_extension, METH_O, pysqlite_connection_load_extension__doc__},
+ {"load_extension", _PyCFunction_CAST(pysqlite_connection_load_extension), METH_FASTCALL|METH_KEYWORDS, pysqlite_connection_load_extension__doc__},
static PyObject *
pysqlite_connection_load_extension_impl(pysqlite_Connection *self,
- const char *extension_name);
+ const char *extension_name,
+ const char *entrypoint);
static PyObject *
-pysqlite_connection_load_extension(pysqlite_Connection *self, PyObject *arg)
+pysqlite_connection_load_extension(pysqlite_Connection *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
+ #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+
+ #define NUM_KEYWORDS 1
+ static struct {
+ PyGC_Head _this_is_not_used;
+ PyObject_VAR_HEAD
+ PyObject *ob_item[NUM_KEYWORDS];
+ } _kwtuple = {
+ .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_item = { &_Py_ID(entrypoint), },
+ };
+ #undef NUM_KEYWORDS
+ #define KWTUPLE (&_kwtuple.ob_base.ob_base)
+
+ #else // !Py_BUILD_CORE
+ # define KWTUPLE NULL
+ #endif // !Py_BUILD_CORE
+
+ static const char * const _keywords[] = {"", "entrypoint", NULL};
+ static _PyArg_Parser _parser = {
+ .keywords = _keywords,
+ .fname = "load_extension",
+ .kwtuple = KWTUPLE,
+ };
+ #undef KWTUPLE
+ PyObject *argsbuf[2];
+ Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
const char *extension_name;
+ const char *entrypoint = NULL;
- if (!PyUnicode_Check(arg)) {
- _PyArg_BadArgument("load_extension", "argument", "str", arg);
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ if (!PyUnicode_Check(args[0])) {
+ _PyArg_BadArgument("load_extension", "argument 1", "str", args[0]);
goto exit;
}
Py_ssize_t extension_name_length;
- extension_name = PyUnicode_AsUTF8AndSize(arg, &extension_name_length);
+ extension_name = PyUnicode_AsUTF8AndSize(args[0], &extension_name_length);
if (extension_name == NULL) {
goto exit;
}
@@ -661,7 +909,29 @@ pysqlite_connection_load_extension(pysqlite_Connection *self, PyObject *arg)
PyErr_SetString(PyExc_ValueError, "embedded null character");
goto exit;
}
- return_value = pysqlite_connection_load_extension_impl(self, extension_name);
+ if (!noptargs) {
+ goto skip_optional_kwonly;
+ }
+ if (args[1] == Py_None) {
+ entrypoint = NULL;
+ }
+ else if (PyUnicode_Check(args[1])) {
+ Py_ssize_t entrypoint_length;
+ entrypoint = PyUnicode_AsUTF8AndSize(args[1], &entrypoint_length);
+ if (entrypoint == NULL) {
+ goto exit;
+ }
+ if (strlen(entrypoint) != (size_t)entrypoint_length) {
+ PyErr_SetString(PyExc_ValueError, "embedded null character");
+ goto exit;
+ }
+ }
+ else {
+ _PyArg_BadArgument("load_extension", "argument 'entrypoint'", "str or None", args[1]);
+ goto exit;
+ }
+skip_optional_kwonly:
+ return_value = pysqlite_connection_load_extension_impl(self, extension_name, entrypoint);
exit:
return return_value;
@@ -814,8 +1084,31 @@ static PyObject *
pysqlite_connection_backup(pysqlite_Connection *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
+ #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+
+ #define NUM_KEYWORDS 5
+ static struct {
+ PyGC_Head _this_is_not_used;
+ PyObject_VAR_HEAD
+ PyObject *ob_item[NUM_KEYWORDS];
+ } _kwtuple = {
+ .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_item = { &_Py_ID(target), &_Py_ID(pages), &_Py_ID(progress), &_Py_ID(name), &_Py_ID(sleep), },
+ };
+ #undef NUM_KEYWORDS
+ #define KWTUPLE (&_kwtuple.ob_base.ob_base)
+
+ #else // !Py_BUILD_CORE
+ # define KWTUPLE NULL
+ #endif // !Py_BUILD_CORE
+
static const char * const _keywords[] = {"target", "pages", "progress", "name", "sleep", NULL};
- static _PyArg_Parser _parser = {NULL, _keywords, "backup", 0};
+ static _PyArg_Parser _parser = {
+ .keywords = _keywords,
+ .fname = "backup",
+ .kwtuple = KWTUPLE,
+ };
+ #undef KWTUPLE
PyObject *argsbuf[5];
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
pysqlite_Connection *target;
@@ -905,8 +1198,19 @@ static PyObject *
pysqlite_connection_create_collation(pysqlite_Connection *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
+ #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+ # define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty)
+ #else
+ # define KWTUPLE NULL
+ #endif
+
static const char * const _keywords[] = {"", "", NULL};
- static _PyArg_Parser _parser = {NULL, _keywords, "create_collation", 0};
+ static _PyArg_Parser _parser = {
+ .keywords = _keywords,
+ .fname = "create_collation",
+ .kwtuple = KWTUPLE,
+ };
+ #undef KWTUPLE
PyObject *argsbuf[2];
const char *name;
PyObject *callable;
@@ -961,8 +1265,31 @@ static PyObject *
serialize(pysqlite_Connection *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
+ #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+
+ #define NUM_KEYWORDS 1
+ static struct {
+ PyGC_Head _this_is_not_used;
+ PyObject_VAR_HEAD
+ PyObject *ob_item[NUM_KEYWORDS];
+ } _kwtuple = {
+ .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_item = { &_Py_ID(name), },
+ };
+ #undef NUM_KEYWORDS
+ #define KWTUPLE (&_kwtuple.ob_base.ob_base)
+
+ #else // !Py_BUILD_CORE
+ # define KWTUPLE NULL
+ #endif // !Py_BUILD_CORE
+
static const char * const _keywords[] = {"name", NULL};
- static _PyArg_Parser _parser = {NULL, _keywords, "serialize", 0};
+ static _PyArg_Parser _parser = {
+ .keywords = _keywords,
+ .fname = "serialize",
+ .kwtuple = KWTUPLE,
+ };
+ #undef KWTUPLE
PyObject *argsbuf[1];
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
const char *name = "main";
@@ -1027,8 +1354,31 @@ static PyObject *
deserialize(pysqlite_Connection *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
+ #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+
+ #define NUM_KEYWORDS 1
+ static struct {
+ PyGC_Head _this_is_not_used;
+ PyObject_VAR_HEAD
+ PyObject *ob_item[NUM_KEYWORDS];
+ } _kwtuple = {
+ .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_item = { &_Py_ID(name), },
+ };
+ #undef NUM_KEYWORDS
+ #define KWTUPLE (&_kwtuple.ob_base.ob_base)
+
+ #else // !Py_BUILD_CORE
+ # define KWTUPLE NULL
+ #endif // !Py_BUILD_CORE
+
static const char * const _keywords[] = {"", "name", NULL};
- static _PyArg_Parser _parser = {NULL, _keywords, "deserialize", 0};
+ static _PyArg_Parser _parser = {
+ .keywords = _keywords,
+ .fname = "deserialize",
+ .kwtuple = KWTUPLE,
+ };
+ #undef KWTUPLE
PyObject *argsbuf[2];
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
Py_buffer data = {NULL, NULL};
@@ -1217,6 +1567,85 @@ exit:
return return_value;
}
+PyDoc_STRVAR(setconfig__doc__,
+"setconfig($self, op, enable=True, /)\n"
+"--\n"
+"\n"
+"Set a boolean connection configuration option.\n"
+"\n"
+" op\n"
+" The configuration verb; one of the sqlite3.SQLITE_DBCONFIG codes.");
+
+#define SETCONFIG_METHODDEF \
+ {"setconfig", _PyCFunction_CAST(setconfig), METH_FASTCALL, setconfig__doc__},
+
+static PyObject *
+setconfig_impl(pysqlite_Connection *self, int op, int enable);
+
+static PyObject *
+setconfig(pysqlite_Connection *self, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ int op;
+ int enable = 1;
+
+ if (!_PyArg_CheckPositional("setconfig", nargs, 1, 2)) {
+ goto exit;
+ }
+ op = _PyLong_AsInt(args[0]);
+ if (op == -1 && PyErr_Occurred()) {
+ goto exit;
+ }
+ if (nargs < 2) {
+ goto skip_optional;
+ }
+ enable = PyObject_IsTrue(args[1]);
+ if (enable < 0) {
+ goto exit;
+ }
+skip_optional:
+ return_value = setconfig_impl(self, op, enable);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(getconfig__doc__,
+"getconfig($self, op, /)\n"
+"--\n"
+"\n"
+"Query a boolean connection configuration option.\n"
+"\n"
+" op\n"
+" The configuration verb; one of the sqlite3.SQLITE_DBCONFIG codes.");
+
+#define GETCONFIG_METHODDEF \
+ {"getconfig", (PyCFunction)getconfig, METH_O, getconfig__doc__},
+
+static int
+getconfig_impl(pysqlite_Connection *self, int op);
+
+static PyObject *
+getconfig(pysqlite_Connection *self, PyObject *arg)
+{
+ PyObject *return_value = NULL;
+ int op;
+ int _return_value;
+
+ op = _PyLong_AsInt(arg);
+ if (op == -1 && PyErr_Occurred()) {
+ goto exit;
+ }
+ _return_value = getconfig_impl(self, op);
+ if ((_return_value == -1) && PyErr_Occurred()) {
+ goto exit;
+ }
+ return_value = PyBool_FromLong((long)_return_value);
+
+exit:
+ return return_value;
+}
+
#ifndef CREATE_WINDOW_FUNCTION_METHODDEF
#define CREATE_WINDOW_FUNCTION_METHODDEF
#endif /* !defined(CREATE_WINDOW_FUNCTION_METHODDEF) */
@@ -1236,4 +1665,4 @@ exit:
#ifndef DESERIALIZE_METHODDEF
#define DESERIALIZE_METHODDEF
#endif /* !defined(DESERIALIZE_METHODDEF) */
-/*[clinic end generated code: output=67e5b3dbade4a15b input=a9049054013a1b77]*/
+/*[clinic end generated code: output=834a99827555bf1a input=a9049054013a1b77]*/
diff --git a/contrib/tools/python3/src/Modules/_sqlite/clinic/cursor.c.h b/contrib/tools/python3/src/Modules/_sqlite/clinic/cursor.c.h
index b29c333074..43e912d134 100644
--- a/contrib/tools/python3/src/Modules/_sqlite/clinic/cursor.c.h
+++ b/contrib/tools/python3/src/Modules/_sqlite/clinic/cursor.c.h
@@ -2,6 +2,12 @@
preserve
[clinic start generated code]*/
+#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+# include "pycore_gc.h" // PyGC_Head
+# include "pycore_runtime.h" // _Py_ID()
+#endif
+
+
static int
pysqlite_cursor_init_impl(pysqlite_Cursor *self,
pysqlite_Connection *connection);
@@ -10,10 +16,11 @@ static int
pysqlite_cursor_init(PyObject *self, PyObject *args, PyObject *kwargs)
{
int return_value = -1;
+ PyTypeObject *base_tp = clinic_state()->CursorType;
pysqlite_Connection *connection;
- if ((Py_IS_TYPE(self, clinic_state()->CursorType) ||
- Py_TYPE(self)->tp_new == clinic_state()->CursorType->tp_new) &&
+ if ((Py_IS_TYPE(self, base_tp) ||
+ Py_TYPE(self)->tp_new == base_tp->tp_new) &&
!_PyArg_NoKeywords("Cursor", kwargs)) {
goto exit;
}
@@ -186,8 +193,31 @@ static PyObject *
pysqlite_cursor_fetchmany(pysqlite_Cursor *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
+ #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+
+ #define NUM_KEYWORDS 1
+ static struct {
+ PyGC_Head _this_is_not_used;
+ PyObject_VAR_HEAD
+ PyObject *ob_item[NUM_KEYWORDS];
+ } _kwtuple = {
+ .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_item = { &_Py_ID(size), },
+ };
+ #undef NUM_KEYWORDS
+ #define KWTUPLE (&_kwtuple.ob_base.ob_base)
+
+ #else // !Py_BUILD_CORE
+ # define KWTUPLE NULL
+ #endif // !Py_BUILD_CORE
+
static const char * const _keywords[] = {"size", NULL};
- static _PyArg_Parser _parser = {NULL, _keywords, "fetchmany", 0};
+ static _PyArg_Parser _parser = {
+ .keywords = _keywords,
+ .fname = "fetchmany",
+ .kwtuple = KWTUPLE,
+ };
+ #undef KWTUPLE
PyObject *argsbuf[1];
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
int maxrows = self->arraysize;
@@ -289,4 +319,4 @@ pysqlite_cursor_close(pysqlite_Cursor *self, PyObject *Py_UNUSED(ignored))
{
return pysqlite_cursor_close_impl(self);
}
-/*[clinic end generated code: output=2b9c6a3ca8a8caff input=a9049054013a1b77]*/
+/*[clinic end generated code: output=1f82e3c9791bb9a5 input=a9049054013a1b77]*/
diff --git a/contrib/tools/python3/src/Modules/_sqlite/clinic/module.c.h b/contrib/tools/python3/src/Modules/_sqlite/clinic/module.c.h
index f5278078a3..12f6083588 100644
--- a/contrib/tools/python3/src/Modules/_sqlite/clinic/module.c.h
+++ b/contrib/tools/python3/src/Modules/_sqlite/clinic/module.c.h
@@ -2,6 +2,12 @@
preserve
[clinic start generated code]*/
+#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+# include "pycore_gc.h" // PyGC_Head
+# include "pycore_runtime.h" // _Py_ID()
+#endif
+
+
PyDoc_STRVAR(pysqlite_complete_statement__doc__,
"complete_statement($module, /, statement)\n"
"--\n"
@@ -18,8 +24,31 @@ static PyObject *
pysqlite_complete_statement(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
+ #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+
+ #define NUM_KEYWORDS 1
+ static struct {
+ PyGC_Head _this_is_not_used;
+ PyObject_VAR_HEAD
+ PyObject *ob_item[NUM_KEYWORDS];
+ } _kwtuple = {
+ .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_item = { &_Py_ID(statement), },
+ };
+ #undef NUM_KEYWORDS
+ #define KWTUPLE (&_kwtuple.ob_base.ob_base)
+
+ #else // !Py_BUILD_CORE
+ # define KWTUPLE NULL
+ #endif // !Py_BUILD_CORE
+
static const char * const _keywords[] = {"statement", NULL};
- static _PyArg_Parser _parser = {NULL, _keywords, "complete_statement", 0};
+ static _PyArg_Parser _parser = {
+ .keywords = _keywords,
+ .fname = "complete_statement",
+ .kwtuple = KWTUPLE,
+ };
+ #undef KWTUPLE
PyObject *argsbuf[1];
const char *statement;
@@ -46,46 +75,6 @@ exit:
return return_value;
}
-PyDoc_STRVAR(pysqlite_enable_shared_cache__doc__,
-"enable_shared_cache($module, /, do_enable)\n"
-"--\n"
-"\n"
-"Enable or disable shared cache mode for the calling thread.\n"
-"\n"
-"This method is deprecated and will be removed in Python 3.12.\n"
-"Shared cache is strongly discouraged by the SQLite 3 documentation.\n"
-"If shared cache must be used, open the database in URI mode using\n"
-"the cache=shared query parameter.");
-
-#define PYSQLITE_ENABLE_SHARED_CACHE_METHODDEF \
- {"enable_shared_cache", _PyCFunction_CAST(pysqlite_enable_shared_cache), METH_FASTCALL|METH_KEYWORDS, pysqlite_enable_shared_cache__doc__},
-
-static PyObject *
-pysqlite_enable_shared_cache_impl(PyObject *module, int do_enable);
-
-static PyObject *
-pysqlite_enable_shared_cache(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
-{
- PyObject *return_value = NULL;
- static const char * const _keywords[] = {"do_enable", NULL};
- static _PyArg_Parser _parser = {NULL, _keywords, "enable_shared_cache", 0};
- PyObject *argsbuf[1];
- int do_enable;
-
- args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
- if (!args) {
- goto exit;
- }
- do_enable = _PyLong_AsInt(args[0]);
- if (do_enable == -1 && PyErr_Occurred()) {
- goto exit;
- }
- return_value = pysqlite_enable_shared_cache_impl(module, do_enable);
-
-exit:
- return return_value;
-}
-
PyDoc_STRVAR(pysqlite_register_adapter__doc__,
"register_adapter($module, type, adapter, /)\n"
"--\n"
@@ -222,4 +211,4 @@ skip_optional:
exit:
return return_value;
}
-/*[clinic end generated code: output=ecaf4e0a239c2685 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=39d38c6cfc455042 input=a9049054013a1b77]*/
diff --git a/contrib/tools/python3/src/Modules/_sqlite/clinic/row.c.h b/contrib/tools/python3/src/Modules/_sqlite/clinic/row.c.h
index c936ef75fd..89a48fd52d 100644
--- a/contrib/tools/python3/src/Modules/_sqlite/clinic/row.c.h
+++ b/contrib/tools/python3/src/Modules/_sqlite/clinic/row.c.h
@@ -2,6 +2,12 @@
preserve
[clinic start generated code]*/
+#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+# include "pycore_gc.h" // PyGC_Head
+# include "pycore_runtime.h" // _Py_ID()
+#endif
+
+
static PyObject *
pysqlite_row_new_impl(PyTypeObject *type, pysqlite_Cursor *cursor,
PyObject *data);
@@ -10,11 +16,11 @@ static PyObject *
pysqlite_row_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
{
PyObject *return_value = NULL;
+ PyTypeObject *base_tp = clinic_state()->RowType;
pysqlite_Cursor *cursor;
PyObject *data;
- if ((type == clinic_state()->RowType ||
- type->tp_init == clinic_state()->RowType->tp_init) &&
+ if ((type == base_tp || type->tp_init == base_tp->tp_init) &&
!_PyArg_NoKeywords("Row", kwargs)) {
goto exit;
}
@@ -54,4 +60,4 @@ pysqlite_row_keys(pysqlite_Row *self, PyObject *Py_UNUSED(ignored))
{
return pysqlite_row_keys_impl(self);
}
-/*[clinic end generated code: output=9d54919dbb4ba5f1 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=157b31ac3f6af1ba input=a9049054013a1b77]*/
diff --git a/contrib/tools/python3/src/Modules/_sqlite/connection.c b/contrib/tools/python3/src/Modules/_sqlite/connection.c
index e3650de7fb..12e5c135aa 100644
--- a/contrib/tools/python3/src/Modules/_sqlite/connection.c
+++ b/contrib/tools/python3/src/Modules/_sqlite/connection.c
@@ -30,6 +30,8 @@
#include "prepare_protocol.h"
#include "util.h"
+#include <stdbool.h>
+
#if SQLITE_VERSION_NUMBER >= 3014000
#define HAVE_TRACE_V2
#endif
@@ -93,6 +95,30 @@ isolation_level_converter(PyObject *str_or_none, const char **result)
}
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) == LEGACY_TRANSACTION_CONTROL)
+ {
+ *result = AUTOCOMMIT_LEGACY;
+ return 1;
+ }
+
+ PyErr_SetString(PyExc_ValueError,
+ "autocommit must be True, False, or "
+ "sqlite3.LEGACY_TRANSACTION_CONTROL");
+ return 0;
+}
+
+static int
sqlite3_int64_converter(PyObject *obj, sqlite3_int64 *result)
{
if (!PyLong_Check(obj)) {
@@ -120,7 +146,7 @@ static void _pysqlite_drop_unused_cursor_references(pysqlite_Connection* self);
static void free_callback_context(callback_context *ctx);
static void set_callback_context(callback_context **ctx_pp,
callback_context *ctx);
-static void connection_close(pysqlite_Connection *self);
+static int connection_close(pysqlite_Connection *self);
PyObject *_pysqlite_query_execute(pysqlite_Cursor *, int, PyObject *, PyObject *);
static PyObject *
@@ -146,17 +172,42 @@ new_statement_cache(pysqlite_Connection *self, pysqlite_state *state,
return res;
}
+static inline int
+connection_exec_stmt(pysqlite_Connection *self, const char *sql)
+{
+ int rc;
+ Py_BEGIN_ALLOW_THREADS
+ int len = (int)strlen(sql) + 1;
+ sqlite3_stmt *stmt;
+ rc = sqlite3_prepare_v2(self->db, sql, len, &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"
+
class sqlite3_int64_converter(CConverter):
type = "sqlite3_int64"
converter = "sqlite3_int64_converter"
[python start generated code]*/
-/*[python end generated code: output=da39a3ee5e6b4b0d input=e9bee126e0500e61]*/
+/*[python end generated code: output=da39a3ee5e6b4b0d input=dff8760fb1eba6a1]*/
// NB: This needs to be in sync with the sqlite3.connect docstring
/*[clinic input]
@@ -166,10 +217,12 @@ _sqlite3.Connection.__init__ as pysqlite_connection_init
timeout: double = 5.0
detect_types: int = 0
isolation_level: IsolationLevel = ""
- check_same_thread: bool(accept={int}) = True
+ check_same_thread: bool = True
factory: object(c_default='(PyObject*)clinic_state()->ConnectionType') = ConnectionType
cached_statements as cache_size: int = 128
uri: bool = False
+ *
+ autocommit: Autocommit(c_default='LEGACY_TRANSACTION_CONTROL') = sqlite3.LEGACY_TRANSACTION_CONTROL
[clinic start generated code]*/
static int
@@ -177,8 +230,9 @@ 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=9b0ab6c12f674fa3]*/
{
if (PySys_Audit("sqlite3.connect", "O", database) < 0) {
return -1;
@@ -190,10 +244,13 @@ pysqlite_connection_init_impl(pysqlite_Connection *self, PyObject *database,
}
if (self->initialized) {
+ self->initialized = 0;
+
PyTypeObject *tp = Py_TYPE(self);
tp->tp_clear((PyObject *)self);
- connection_close(self);
- self->initialized = 0;
+ if (connection_close(self) < 0) {
+ return -1;
+ }
}
// Create and configure SQLite database object.
@@ -245,6 +302,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;
@@ -274,6 +332,12 @@ pysqlite_connection_init_impl(pysqlite_Connection *self, PyObject *database,
}
self->initialized = 1;
+
+ if (autocommit == AUTOCOMMIT_DISABLED) {
+ if (connection_exec_stmt(self, "BEGIN") < 0) {
+ return -1;
+ }
+ }
return 0;
error:
@@ -340,31 +404,90 @@ free_callback_contexts(pysqlite_Connection *self)
}
static void
-connection_close(pysqlite_Connection *self)
+remove_callbacks(sqlite3 *db)
{
- if (self->db) {
- free_callback_contexts(self);
+ assert(db != NULL);
+ /* None of these APIs can fail, as long as they are given a valid
+ * database pointer. */
+ int rc;
+#ifdef HAVE_TRACE_V2
+ rc = sqlite3_trace_v2(db, SQLITE_TRACE_STMT, 0, 0);
+ assert(rc == SQLITE_OK), (void)rc;
+#else
+ sqlite3_trace(db, 0, (void*)0);
+#endif
- sqlite3 *db = self->db;
- self->db = NULL;
+ sqlite3_progress_handler(db, 0, 0, (void *)0);
- Py_BEGIN_ALLOW_THREADS
- int rc = sqlite3_close_v2(db);
- assert(rc == SQLITE_OK), (void)rc;
- Py_END_ALLOW_THREADS
+ rc = sqlite3_set_authorizer(db, NULL, NULL);
+ assert(rc == SQLITE_OK), (void)rc;
+}
+
+static int
+connection_close(pysqlite_Connection *self)
+{
+ if (self->db == NULL) {
+ return 0;
+ }
+
+ int rc = 0;
+ if (self->autocommit == AUTOCOMMIT_DISABLED &&
+ !sqlite3_get_autocommit(self->db))
+ {
+ if (connection_exec_stmt(self, "ROLLBACK") < 0) {
+ rc = -1;
+ }
}
+
+ sqlite3 *db = self->db;
+ self->db = NULL;
+
+ Py_BEGIN_ALLOW_THREADS
+ /* The v2 close call always returns SQLITE_OK if given a valid database
+ * pointer (which we do), so we can safely ignore the return value */
+ (void)sqlite3_close_v2(db);
+ Py_END_ALLOW_THREADS
+
+ free_callback_contexts(self);
+ return rc;
}
static void
-connection_dealloc(pysqlite_Connection *self)
+connection_finalize(PyObject *self)
{
- PyTypeObject *tp = Py_TYPE(self);
- PyObject_GC_UnTrack(self);
- tp->tp_clear((PyObject *)self);
+ pysqlite_Connection *con = (pysqlite_Connection *)self;
+ PyObject *exc = PyErr_GetRaisedException();
+
+ /* If close is implicitly called as a result of interpreter
+ * tear-down, we must not call back into Python. */
+ PyInterpreterState *interp = PyInterpreterState_Get();
+ int teardown = _Py_IsInterpreterFinalizing(interp);
+ if (teardown && con->db) {
+ remove_callbacks(con->db);
+ }
/* Clean up if user has not called .close() explicitly. */
- connection_close(self);
+ if (connection_close(con) < 0) {
+ if (teardown) {
+ PyErr_Clear();
+ }
+ else {
+ PyErr_WriteUnraisable((PyObject *)self);
+ }
+ }
+
+ PyErr_SetRaisedException(exc);
+}
+static void
+connection_dealloc(PyObject *self)
+{
+ if (PyObject_CallFinalizerFromDealloc(self) < 0) {
+ return;
+ }
+ PyTypeObject *tp = Py_TYPE(self);
+ PyObject_GC_UnTrack(self);
+ tp->tp_clear(self);
tp->tp_free(self);
Py_DECREF(tp);
}
@@ -423,7 +546,7 @@ _sqlite3.Connection.blobopen as blobopen
Row index.
/
*
- readonly: bool(accept={int}) = False
+ readonly: bool = False
Open the BLOB without write permissions.
name: str = "main"
Database name.
@@ -434,7 +557,7 @@ Open and return a BLOB object.
static PyObject *
blobopen_impl(pysqlite_Connection *self, const char *table, const char *col,
sqlite3_int64 row, int readonly, const char *name)
-/*[clinic end generated code: output=6a02d43efb885d1c input=4180b11a0591d80d]*/
+/*[clinic end generated code: output=6a02d43efb885d1c input=23576bd1108d8774]*/
{
if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {
return NULL;
@@ -512,7 +635,9 @@ pysqlite_connection_close_impl(pysqlite_Connection *self)
pysqlite_close_all_blobs(self);
Py_CLEAR(self->statement_cache);
- connection_close(self);
+ if (connection_close(self) < 0) {
+ return NULL;
+ }
Py_RETURN_NONE;
}
@@ -556,24 +681,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_LEGACY) {
+ if (!sqlite3_get_autocommit(self->db)) {
+ if (connection_exec_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_exec_stmt(self, "COMMIT") < 0) {
+ return NULL;
+ }
+ if (connection_exec_stmt(self, "BEGIN") < 0) {
return NULL;
}
}
-
Py_RETURN_NONE;
}
@@ -593,25 +715,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_LEGACY) {
+ if (!sqlite3_get_autocommit(self->db)) {
+ if (connection_exec_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_exec_stmt(self, "ROLLBACK") < 0) {
+ return NULL;
+ }
+ if (connection_exec_stmt(self, "BEGIN") < 0) {
return NULL;
}
-
}
-
Py_RETURN_NONE;
}
@@ -853,7 +971,6 @@ final_callback(sqlite3_context *context)
PyObject* function_result;
PyObject** aggregate_instance;
int ok;
- PyObject *exception, *value, *tb;
aggregate_instance = (PyObject**)sqlite3_aggregate_context(context, 0);
if (aggregate_instance == NULL) {
@@ -868,7 +985,7 @@ final_callback(sqlite3_context *context)
}
// Keep the exception (if any) of the last call to step, value, or inverse
- PyErr_Fetch(&exception, &value, &tb);
+ PyObject *exc = PyErr_GetRaisedException();
callback_context *ctx = (callback_context *)sqlite3_user_data(context);
assert(ctx != NULL);
@@ -883,7 +1000,7 @@ final_callback(sqlite3_context *context)
}
if (!ok) {
int attr_err = PyErr_ExceptionMatches(PyExc_AttributeError);
- _PyErr_ChainExceptions(exception, value, tb);
+ _PyErr_ChainExceptions1(exc);
/* Note: contrary to the step, value, and inverse callbacks, SQLite
* does _not_, as of SQLite 3.38.0, propagate errors to sqlite3_step()
@@ -894,7 +1011,7 @@ final_callback(sqlite3_context *context)
: "user-defined aggregate's 'finalize' method raised error");
}
else {
- PyErr_Restore(exception, value, tb);
+ PyErr_SetRaisedException(exc);
}
error:
@@ -1509,7 +1626,7 @@ pysqlite_connection_set_trace_callback_impl(pysqlite_Connection *self,
/*[clinic input]
_sqlite3.Connection.enable_load_extension as pysqlite_connection_enable_load_extension
- enable as onoff: bool(accept={int})
+ enable as onoff: bool
/
Enable dynamic loading of SQLite extension modules.
@@ -1518,7 +1635,7 @@ Enable dynamic loading of SQLite extension modules.
static PyObject *
pysqlite_connection_enable_load_extension_impl(pysqlite_Connection *self,
int onoff)
-/*[clinic end generated code: output=9cac37190d388baf input=5f00e93f7a9d3540]*/
+/*[clinic end generated code: output=9cac37190d388baf input=2a1e87931486380f]*/
{
int rc;
@@ -1547,14 +1664,17 @@ _sqlite3.Connection.load_extension as pysqlite_connection_load_extension
name as extension_name: str
/
+ *
+ entrypoint: str(accept={str, NoneType}) = None
Load SQLite extension module.
[clinic start generated code]*/
static PyObject *
pysqlite_connection_load_extension_impl(pysqlite_Connection *self,
- const char *extension_name)
-/*[clinic end generated code: output=47eb1d7312bc97a7 input=edd507389d89d621]*/
+ const char *extension_name,
+ const char *entrypoint)
+/*[clinic end generated code: output=7e61a7add9de0286 input=c36b14ea702e04f5]*/
{
int rc;
char* errmsg;
@@ -1567,7 +1687,7 @@ pysqlite_connection_load_extension_impl(pysqlite_Connection *self,
return NULL;
}
- rc = sqlite3_load_extension(self->db, extension_name, 0, &errmsg);
+ rc = sqlite3_load_extension(self->db, extension_name, entrypoint, &errmsg);
if (rc != 0) {
PyErr_SetString(self->OperationalError, errmsg);
return NULL;
@@ -1607,9 +1727,8 @@ static PyObject* pysqlite_connection_get_total_changes(pysqlite_Connection* self
{
if (!pysqlite_check_connection(self)) {
return NULL;
- } else {
- return Py_BuildValue("i", sqlite3_total_changes(self->db));
}
+ return PyLong_FromLong(sqlite3_total_changes(self->db));
}
static PyObject* pysqlite_connection_get_in_transaction(pysqlite_Connection* self, void* unused)
@@ -1868,43 +1987,21 @@ static PyObject *
pysqlite_connection_iterdump_impl(pysqlite_Connection *self)
/*[clinic end generated code: output=586997aaf9808768 input=1911ca756066da89]*/
{
- PyObject* retval = NULL;
- PyObject* module = NULL;
- PyObject* module_dict;
- PyObject* pyfn_iterdump;
-
if (!pysqlite_check_connection(self)) {
- goto finally;
- }
-
- module = PyImport_ImportModule(MODULE_NAME ".dump");
- if (!module) {
- goto finally;
- }
-
- module_dict = PyModule_GetDict(module);
- if (!module_dict) {
- goto finally;
+ return NULL;
}
- PyObject *meth = PyUnicode_InternFromString("_iterdump");
- if (meth == NULL) {
- goto finally;
- }
- pyfn_iterdump = PyDict_GetItemWithError(module_dict, meth);
- Py_DECREF(meth);
- if (!pyfn_iterdump) {
+ PyObject *iterdump = _PyImport_GetModuleAttrString(MODULE_NAME ".dump", "_iterdump");
+ if (!iterdump) {
if (!PyErr_Occurred()) {
PyErr_SetString(self->OperationalError,
"Failed to obtain _iterdump() reference");
}
- goto finally;
+ return NULL;
}
- retval = PyObject_CallOneArg(pyfn_iterdump, (PyObject *)self);
-
-finally:
- Py_XDECREF(module);
+ PyObject *retval = PyObject_CallOneArg(iterdump, (PyObject *)self);
+ Py_DECREF(iterdump);
return retval;
}
@@ -2244,15 +2341,14 @@ pysqlite_connection_exit_impl(pysqlite_Connection *self, PyObject *exc_type,
if (commit) {
/* Commit failed; try to rollback in order to unlock the database.
* If rollback also fails, chain the exceptions. */
- PyObject *exc, *val, *tb;
- PyErr_Fetch(&exc, &val, &tb);
+ PyObject *exc = PyErr_GetRaisedException();
result = pysqlite_connection_rollback_impl(self);
if (result == NULL) {
- _PyErr_ChainExceptions(exc, val, tb);
+ _PyErr_ChainExceptions1(exc);
}
else {
Py_DECREF(result);
- PyErr_Restore(exc, val, tb);
+ PyErr_SetRaisedException(exc);
}
}
return NULL;
@@ -2312,6 +2408,161 @@ getlimit_impl(pysqlite_Connection *self, int category)
return setlimit_impl(self, category, -1);
}
+static inline bool
+is_int_config(const int op)
+{
+ switch (op) {
+ case SQLITE_DBCONFIG_ENABLE_FKEY:
+ case SQLITE_DBCONFIG_ENABLE_TRIGGER:
+#if SQLITE_VERSION_NUMBER >= 3012002
+ case SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER:
+#endif
+#if SQLITE_VERSION_NUMBER >= 3013000
+ case SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION:
+#endif
+#if SQLITE_VERSION_NUMBER >= 3016000
+ case SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE:
+#endif
+#if SQLITE_VERSION_NUMBER >= 3020000
+ case SQLITE_DBCONFIG_ENABLE_QPSG:
+#endif
+#if SQLITE_VERSION_NUMBER >= 3022000
+ case SQLITE_DBCONFIG_TRIGGER_EQP:
+#endif
+#if SQLITE_VERSION_NUMBER >= 3024000
+ case SQLITE_DBCONFIG_RESET_DATABASE:
+#endif
+#if SQLITE_VERSION_NUMBER >= 3026000
+ case SQLITE_DBCONFIG_DEFENSIVE:
+#endif
+#if SQLITE_VERSION_NUMBER >= 3028000
+ case SQLITE_DBCONFIG_WRITABLE_SCHEMA:
+#endif
+#if SQLITE_VERSION_NUMBER >= 3029000
+ case SQLITE_DBCONFIG_DQS_DDL:
+ case SQLITE_DBCONFIG_DQS_DML:
+ case SQLITE_DBCONFIG_LEGACY_ALTER_TABLE:
+#endif
+#if SQLITE_VERSION_NUMBER >= 3030000
+ case SQLITE_DBCONFIG_ENABLE_VIEW:
+#endif
+#if SQLITE_VERSION_NUMBER >= 3031000
+ case SQLITE_DBCONFIG_LEGACY_FILE_FORMAT:
+ case SQLITE_DBCONFIG_TRUSTED_SCHEMA:
+#endif
+ return true;
+ default:
+ return false;
+ }
+}
+
+/*[clinic input]
+_sqlite3.Connection.setconfig as setconfig
+
+ op: int
+ The configuration verb; one of the sqlite3.SQLITE_DBCONFIG codes.
+ enable: bool = True
+ /
+
+Set a boolean connection configuration option.
+[clinic start generated code]*/
+
+static PyObject *
+setconfig_impl(pysqlite_Connection *self, int op, int enable)
+/*[clinic end generated code: output=c60b13e618aff873 input=a10f1539c2d7da6b]*/
+{
+ if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {
+ return NULL;
+ }
+ if (!is_int_config(op)) {
+ return PyErr_Format(PyExc_ValueError, "unknown config 'op': %d", op);
+ }
+
+ int actual;
+ int rc = sqlite3_db_config(self->db, op, enable, &actual);
+ if (rc != SQLITE_OK) {
+ (void)_pysqlite_seterror(self->state, self->db);
+ return NULL;
+ }
+ if (enable != actual) {
+ PyErr_SetString(self->state->OperationalError, "Unable to set config");
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+/*[clinic input]
+_sqlite3.Connection.getconfig as getconfig -> bool
+
+ op: int
+ The configuration verb; one of the sqlite3.SQLITE_DBCONFIG codes.
+ /
+
+Query a boolean connection configuration option.
+[clinic start generated code]*/
+
+static int
+getconfig_impl(pysqlite_Connection *self, int op)
+/*[clinic end generated code: output=25ac05044c7b78a3 input=b0526d7e432e3f2f]*/
+{
+ if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {
+ return -1;
+ }
+ if (!is_int_config(op)) {
+ PyErr_Format(PyExc_ValueError, "unknown config 'op': %d", op);
+ return -1;
+ }
+
+ int current;
+ int rc = sqlite3_db_config(self->db, op, -1, &current);
+ if (rc != SQLITE_OK) {
+ (void)_pysqlite_seterror(self->state, self->db);
+ return -1;
+ }
+ return current;
+}
+
+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(LEGACY_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;
+ }
+ if (self->autocommit == AUTOCOMMIT_ENABLED) {
+ if (!sqlite3_get_autocommit(self->db)) {
+ if (connection_exec_stmt(self, "COMMIT") < 0) {
+ return -1;
+ }
+ }
+ }
+ else if (self->autocommit == AUTOCOMMIT_DISABLED) {
+ if (sqlite3_get_autocommit(self->db)) {
+ if (connection_exec_stmt(self, "BEGIN") < 0) {
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
static const char connection_doc[] =
PyDoc_STR("SQLite database connection object.");
@@ -2320,6 +2571,7 @@ 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}
};
@@ -2350,6 +2602,8 @@ static PyMethodDef connection_methods[] = {
DESERIALIZE_METHODDEF
CREATE_WINDOW_FUNCTION_METHODDEF
BLOBOPEN_METHODDEF
+ SETCONFIG_METHODDEF
+ GETCONFIG_METHODDEF
{NULL, NULL}
};
@@ -2371,6 +2625,7 @@ static struct PyMemberDef connection_members[] =
};
static PyType_Slot connection_slots[] = {
+ {Py_tp_finalize, connection_finalize},
{Py_tp_dealloc, connection_dealloc},
{Py_tp_doc, (void *)connection_doc},
{Py_tp_methods, connection_methods},
diff --git a/contrib/tools/python3/src/Modules/_sqlite/connection.h b/contrib/tools/python3/src/Modules/_sqlite/connection.h
index 629fe3d3a9..1df92065a5 100644
--- a/contrib/tools/python3/src/Modules/_sqlite/connection.h
+++ b/contrib/tools/python3/src/Modules/_sqlite/connection.h
@@ -39,6 +39,12 @@ typedef struct _callback_context
pysqlite_state *state;
} callback_context;
+enum autocommit_mode {
+ AUTOCOMMIT_LEGACY = LEGACY_TRANSACTION_CONTROL,
+ AUTOCOMMIT_ENABLED = 1,
+ AUTOCOMMIT_DISABLED = 0,
+};
+
typedef struct
{
PyObject_HEAD
@@ -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 */
diff --git a/contrib/tools/python3/src/Modules/_sqlite/cursor.c b/contrib/tools/python3/src/Modules/_sqlite/cursor.c
index 3f5cfef0c3..caeedbddb8 100644
--- a/contrib/tools/python3/src/Modules/_sqlite/cursor.c
+++ b/contrib/tools/python3/src/Modules/_sqlite/cursor.c
@@ -130,14 +130,10 @@ stmt_reset(pysqlite_Statement *self)
{
int rc = SQLITE_OK;
- if (self->in_use && self->st) {
+ if (self->st != NULL) {
Py_BEGIN_ALLOW_THREADS
rc = sqlite3_reset(self->st);
Py_END_ALLOW_THREADS
-
- if (rc == SQLITE_OK) {
- self->in_use = 0;
- }
}
return rc;
@@ -666,6 +662,19 @@ bind_parameters(pysqlite_state *state, pysqlite_Statement *self,
return;
}
for (i = 0; i < num_params; i++) {
+ const char *name = sqlite3_bind_parameter_name(self->st, i+1);
+ if (name != NULL) {
+ int ret = PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
+ "Binding %d ('%s') is a named parameter, but you "
+ "supplied a sequence which requires nameless (qmark) "
+ "placeholders. Starting with Python 3.14 an "
+ "sqlite3.ProgrammingError will be raised.",
+ i+1, name);
+ if (ret < 0) {
+ return;
+ }
+ }
+
if (PyTuple_CheckExact(parameters)) {
PyObject *item = PyTuple_GET_ITEM(parameters, i);
current_param = Py_NewRef(item);
@@ -696,11 +705,10 @@ bind_parameters(pysqlite_state *state, pysqlite_Statement *self,
Py_DECREF(adapted);
if (rc != SQLITE_OK) {
- PyObject *exc, *val, *tb;
- PyErr_Fetch(&exc, &val, &tb);
+ PyObject *exc = PyErr_GetRaisedException();
sqlite3 *db = sqlite3_db_handle(self->st);
_pysqlite_seterror(state, db);
- _PyErr_ChainExceptions(exc, val, tb);
+ _PyErr_ChainExceptions1(exc);
return;
}
}
@@ -756,11 +764,10 @@ bind_parameters(pysqlite_state *state, pysqlite_Statement *self,
Py_DECREF(adapted);
if (rc != SQLITE_OK) {
- PyObject *exc, *val, *tb;
- PyErr_Fetch(&exc, &val, &tb);
+ PyObject *exc = PyErr_GetRaisedException();
sqlite3 *db = sqlite3_db_handle(self->st);
_pysqlite_seterror(state, db);
- _PyErr_ChainExceptions(exc, val, tb);
+ _PyErr_ChainExceptions1(exc);
return;
}
}
@@ -770,12 +777,6 @@ bind_parameters(pysqlite_state *state, pysqlite_Statement *self,
}
}
-static inline void
-stmt_mark_dirty(pysqlite_Statement *self)
-{
- self->in_use = 1;
-}
-
PyObject *
_pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation, PyObject* second_argument)
{
@@ -830,16 +831,12 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation
}
}
- if (self->statement != NULL) {
- /* There is an active statement */
- stmt_reset(self->statement);
- }
-
/* reset description */
Py_INCREF(Py_None);
Py_SETREF(self->description, Py_None);
if (self->statement) {
+ // Reset pending statements on this cursor.
(void)stmt_reset(self->statement);
}
@@ -856,7 +853,7 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation
goto error;
}
- if (self->statement->in_use) {
+ if (sqlite3_stmt_busy(self->statement->st)) {
Py_SETREF(self->statement,
pysqlite_statement_create(self->connection, operation));
if (self->statement == NULL) {
@@ -864,13 +861,13 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation
}
}
- stmt_reset(self->statement);
- stmt_mark_dirty(self->statement);
+ (void)stmt_reset(self->statement);
self->rowcount = self->statement->is_dml ? 0L : -1L;
/* We start a transaction implicitly before a DML statement.
SELECT is the only exception. See #9924. */
- if (self->connection->isolation_level
+ if (self->connection->autocommit == AUTOCOMMIT_LEGACY
+ && self->connection->isolation_level
&& self->statement->is_dml
&& sqlite3_get_autocommit(self->connection->db))
{
@@ -879,14 +876,13 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation
}
}
+ assert(!sqlite3_stmt_busy(self->statement->st));
while (1) {
parameters = PyIter_Next(parameters_iter);
if (!parameters) {
break;
}
- stmt_mark_dirty(self->statement);
-
bind_parameters(state, self->statement, parameters);
if (PyErr_Occurred()) {
goto error;
@@ -902,7 +898,6 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation
PyErr_Clear();
}
}
- (void)stmt_reset(self->statement);
_pysqlite_seterror(state, self->connection->db);
goto error;
}
@@ -944,16 +939,8 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation
}
}
- if (rc == SQLITE_DONE && !multiple) {
+ if (rc == SQLITE_DONE) {
if (self->statement->is_dml) {
- self->rowcount = (long)sqlite3_changes(self->connection->db);
- }
- stmt_reset(self->statement);
- Py_CLEAR(self->statement);
- }
-
- if (multiple) {
- if (self->statement->is_dml && rc == SQLITE_DONE) {
self->rowcount += (long)sqlite3_changes(self->connection->db);
}
stmt_reset(self->statement);
@@ -980,11 +967,17 @@ error:
self->locked = 0;
if (PyErr_Occurred()) {
+ if (self->statement) {
+ (void)stmt_reset(self->statement);
+ Py_CLEAR(self->statement);
+ }
self->rowcount = -1L;
return NULL;
- } else {
- return Py_NewRef((PyObject *)self);
}
+ if (self->statement && !sqlite3_stmt_busy(self->statement->st)) {
+ Py_CLEAR(self->statement);
+ }
+ return Py_NewRef((PyObject *)self);
}
/*[clinic input]
@@ -1052,7 +1045,9 @@ pysqlite_cursor_executescript_impl(pysqlite_Cursor *self,
// Commit if needed
sqlite3 *db = self->connection->db;
- if (!sqlite3_get_autocommit(db)) {
+ if (self->connection->autocommit == AUTOCOMMIT_LEGACY
+ && !sqlite3_get_autocommit(db))
+ {
int rc = SQLITE_OK;
Py_BEGIN_ALLOW_THREADS
@@ -1111,11 +1106,7 @@ pysqlite_cursor_iternext(pysqlite_Cursor *self)
sqlite3_stmt *stmt = self->statement->st;
assert(stmt != NULL);
- if (sqlite3_data_count(stmt) == 0) {
- (void)stmt_reset(self->statement);
- Py_CLEAR(self->statement);
- return NULL;
- }
+ assert(sqlite3_data_count(stmt) != 0);
self->locked = 1; // GH-80254: Prevent recursive use of cursors.
PyObject *row = _pysqlite_fetch_one_row(self);
@@ -1143,8 +1134,7 @@ pysqlite_cursor_iternext(pysqlite_Cursor *self)
PyObject *factory = self->row_factory;
PyObject *args[] = { (PyObject *)self, row, };
PyObject *new_row = PyObject_Vectorcall(factory, args, 2, NULL);
- Py_DECREF(row);
- row = new_row;
+ Py_SETREF(row, new_row);
}
return row;
}
diff --git a/contrib/tools/python3/src/Modules/_sqlite/microprotocols.c b/contrib/tools/python3/src/Modules/_sqlite/microprotocols.c
index a79f0067b1..148220d0f9 100644
--- a/contrib/tools/python3/src/Modules/_sqlite/microprotocols.c
+++ b/contrib/tools/python3/src/Modules/_sqlite/microprotocols.c
@@ -57,7 +57,7 @@ pysqlite_microprotocols_add(pysqlite_state *state, PyTypeObject *type,
assert(type != NULL);
assert(proto != NULL);
- key = Py_BuildValue("(OO)", (PyObject*)type, proto);
+ key = PyTuple_Pack(2, (PyObject *)type, proto);
if (!key) {
return -1;
}
@@ -81,7 +81,7 @@ pysqlite_microprotocols_adapt(pysqlite_state *state, PyObject *obj,
way to get a quotable object to be its instance */
/* look for an adapter in the registry */
- key = Py_BuildValue("(OO)", (PyObject*)Py_TYPE(obj), proto);
+ key = PyTuple_Pack(2, (PyObject *)Py_TYPE(obj), proto);
if (!key) {
return NULL;
}
diff --git a/contrib/tools/python3/src/Modules/_sqlite/module.c b/contrib/tools/python3/src/Modules/_sqlite/module.c
index e633a63ae9..27bd42f459 100644
--- a/contrib/tools/python3/src/Modules/_sqlite/module.c
+++ b/contrib/tools/python3/src/Modules/_sqlite/module.c
@@ -46,7 +46,8 @@ module _sqlite3
PyDoc_STRVAR(module_connect_doc,
"connect($module, /, database, timeout=5.0, detect_types=0,\n"
" isolation_level='', check_same_thread=True,\n"
-" factory=ConnectionType, cached_statements=128, uri=False)\n"
+" factory=ConnectionType, cached_statements=128, uri=False, *,\n"
+" autocommit=sqlite3.LEGACY_TRANSACTION_CONTROL)\n"
"--\n"
"\n"
"Opens a connection to the SQLite database file database.\n"
@@ -102,36 +103,6 @@ pysqlite_complete_statement_impl(PyObject *module, const char *statement)
}
/*[clinic input]
-_sqlite3.enable_shared_cache as pysqlite_enable_shared_cache
-
- do_enable: int
-
-Enable or disable shared cache mode for the calling thread.
-
-This method is deprecated and will be removed in Python 3.12.
-Shared cache is strongly discouraged by the SQLite 3 documentation.
-If shared cache must be used, open the database in URI mode using
-the cache=shared query parameter.
-[clinic start generated code]*/
-
-static PyObject *
-pysqlite_enable_shared_cache_impl(PyObject *module, int do_enable)
-/*[clinic end generated code: output=259c74eedee1516b input=26e40d5971d3487d]*/
-{
- int rc;
-
- rc = sqlite3_enable_shared_cache(do_enable);
-
- if (rc != SQLITE_OK) {
- pysqlite_state *state = pysqlite_get_state(module);
- PyErr_SetString(state->OperationalError, "Changing the shared_cache flag failed");
- return NULL;
- } else {
- Py_RETURN_NONE;
- }
-}
-
-/*[clinic input]
_sqlite3.register_adapter as pysqlite_register_adapter
type: object(type='PyTypeObject *')
@@ -254,14 +225,8 @@ static int converters_init(PyObject* module)
static int
load_functools_lru_cache(PyObject *module)
{
- PyObject *functools = PyImport_ImportModule("functools");
- if (functools == NULL) {
- return -1;
- }
-
pysqlite_state *state = pysqlite_get_state(module);
- state->lru_cache = PyObject_GetAttrString(functools, "lru_cache");
- Py_DECREF(functools);
+ state->lru_cache = _PyImport_GetModuleAttrString("functools", "lru_cache");
if (state->lru_cache == NULL) {
return -1;
}
@@ -273,7 +238,6 @@ static PyMethodDef module_methods[] = {
PYSQLITE_COMPLETE_STATEMENT_METHODDEF
PYSQLITE_CONNECT_METHODDEF
PYSQLITE_ENABLE_CALLBACK_TRACE_METHODDEF
- PYSQLITE_ENABLE_SHARED_CACHE_METHODDEF
PYSQLITE_REGISTER_ADAPTER_METHODDEF
PYSQLITE_REGISTER_CONVERTER_METHODDEF
{NULL, NULL}
@@ -535,6 +499,49 @@ add_integer_constants(PyObject *module) {
#if SQLITE_VERSION_NUMBER >= 3008007
ADD_INT(SQLITE_LIMIT_WORKER_THREADS);
#endif
+
+ /*
+ * Database connection configuration options.
+ * See https://www.sqlite.org/c3ref/c_dbconfig_defensive.html
+ */
+ ADD_INT(SQLITE_DBCONFIG_ENABLE_FKEY);
+ ADD_INT(SQLITE_DBCONFIG_ENABLE_TRIGGER);
+#if SQLITE_VERSION_NUMBER >= 3012002
+ ADD_INT(SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER);
+#endif
+#if SQLITE_VERSION_NUMBER >= 3013000
+ ADD_INT(SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION);
+#endif
+#if SQLITE_VERSION_NUMBER >= 3016000
+ ADD_INT(SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE);
+#endif
+#if SQLITE_VERSION_NUMBER >= 3020000
+ ADD_INT(SQLITE_DBCONFIG_ENABLE_QPSG);
+#endif
+#if SQLITE_VERSION_NUMBER >= 3022000
+ ADD_INT(SQLITE_DBCONFIG_TRIGGER_EQP);
+#endif
+#if SQLITE_VERSION_NUMBER >= 3024000
+ ADD_INT(SQLITE_DBCONFIG_RESET_DATABASE);
+#endif
+#if SQLITE_VERSION_NUMBER >= 3026000
+ ADD_INT(SQLITE_DBCONFIG_DEFENSIVE);
+#endif
+#if SQLITE_VERSION_NUMBER >= 3028000
+ ADD_INT(SQLITE_DBCONFIG_WRITABLE_SCHEMA);
+#endif
+#if SQLITE_VERSION_NUMBER >= 3029000
+ ADD_INT(SQLITE_DBCONFIG_DQS_DDL);
+ ADD_INT(SQLITE_DBCONFIG_DQS_DML);
+ ADD_INT(SQLITE_DBCONFIG_LEGACY_ALTER_TABLE);
+#endif
+#if SQLITE_VERSION_NUMBER >= 3030000
+ ADD_INT(SQLITE_DBCONFIG_ENABLE_VIEW);
+#endif
+#if SQLITE_VERSION_NUMBER >= 3031000
+ ADD_INT(SQLITE_DBCONFIG_LEGACY_FILE_FORMAT);
+ ADD_INT(SQLITE_DBCONFIG_TRUSTED_SCHEMA);
+#endif
#undef ADD_INT
return 0;
}
@@ -735,7 +742,7 @@ module_exec(PyObject *module)
goto error;
}
- if (PyModule_AddStringConstant(module, "version", PYSQLITE_VERSION) < 0) {
+ if (PyModule_AddStringConstant(module, "_deprecated_version", PYSQLITE_VERSION) < 0) {
goto error;
}
@@ -743,6 +750,10 @@ module_exec(PyObject *module)
goto error;
}
+ if (PyModule_AddIntMacro(module, LEGACY_TRANSACTION_CONTROL) < 0) {
+ goto error;
+ }
+
int threadsafety = get_threadsafety(state);
if (threadsafety < 0) {
goto error;
@@ -774,6 +785,7 @@ error:
static struct PyModuleDef_Slot module_slots[] = {
{Py_mod_exec, module_exec},
+ {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
{0, NULL},
};
diff --git a/contrib/tools/python3/src/Modules/_sqlite/module.h b/contrib/tools/python3/src/Modules/_sqlite/module.h
index 7deba22ffe..daa22091d3 100644
--- a/contrib/tools/python3/src/Modules/_sqlite/module.h
+++ b/contrib/tools/python3/src/Modules/_sqlite/module.h
@@ -26,6 +26,8 @@
#define PY_SSIZE_T_CLEAN
#include "Python.h"
+#define LEGACY_TRANSACTION_CONTROL -1
+
#define PYSQLITE_VERSION "2.6.0"
#define MODULE_NAME "sqlite3"
diff --git a/contrib/tools/python3/src/Modules/_sqlite/statement.c b/contrib/tools/python3/src/Modules/_sqlite/statement.c
index aee460747b..229bfc3b50 100644
--- a/contrib/tools/python3/src/Modules/_sqlite/statement.c
+++ b/contrib/tools/python3/src/Modules/_sqlite/statement.c
@@ -88,7 +88,6 @@ pysqlite_statement_create(pysqlite_Connection *connection, PyObject *sql)
}
self->st = stmt;
- self->in_use = 0;
self->is_dml = is_dml;
PyObject_GC_Track(self);
diff --git a/contrib/tools/python3/src/Modules/_sqlite/statement.h b/contrib/tools/python3/src/Modules/_sqlite/statement.h
index 5e61227424..11a6464b1a 100644
--- a/contrib/tools/python3/src/Modules/_sqlite/statement.h
+++ b/contrib/tools/python3/src/Modules/_sqlite/statement.h
@@ -33,7 +33,6 @@ typedef struct
{
PyObject_HEAD
sqlite3_stmt* st;
- int in_use;
int is_dml;
} pysqlite_Statement;
diff --git a/contrib/tools/python3/src/Modules/_sqlite/ya.make b/contrib/tools/python3/src/Modules/_sqlite/ya.make
index f9aac2dab3..d0d953c7e6 100644
--- a/contrib/tools/python3/src/Modules/_sqlite/ya.make
+++ b/contrib/tools/python3/src/Modules/_sqlite/ya.make
@@ -2,9 +2,9 @@
LIBRARY()
-VERSION(3.11.8)
+VERSION(3.12.2)
-ORIGINAL_SOURCE(https://github.com/python/cpython/archive/v3.11.8.tar.gz)
+ORIGINAL_SOURCE(https://github.com/python/cpython/archive/v3.12.2.tar.gz)
LICENSE(Python-2.0)
@@ -14,6 +14,7 @@ PEERDIR(
ADDINCL(
contrib/libs/sqlite3
+ contrib/tools/python3/src/Include/internal
)
IF (USE_SYSTEM_PYTHON)