summaryrefslogtreecommitdiffstats
path: root/contrib/tools/python3/Modules/_sqlite/connection.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/tools/python3/Modules/_sqlite/connection.c')
-rw-r--r--contrib/tools/python3/Modules/_sqlite/connection.c355
1 files changed, 203 insertions, 152 deletions
diff --git a/contrib/tools/python3/Modules/_sqlite/connection.c b/contrib/tools/python3/Modules/_sqlite/connection.c
index 1450037ca95..5f888ac19ec 100644
--- a/contrib/tools/python3/Modules/_sqlite/connection.c
+++ b/contrib/tools/python3/Modules/_sqlite/connection.c
@@ -21,8 +21,12 @@
* 3. This notice may not be removed or altered from any source distribution.
*/
+#ifndef Py_BUILD_CORE_BUILTIN
+# define Py_BUILD_CORE_MODULE 1
+#endif
+
#include "module.h"
-#include "structmember.h" // PyMemberDef
+
#include "connection.h"
#include "statement.h"
#include "cursor.h"
@@ -30,11 +34,13 @@
#include "prepare_protocol.h"
#include "util.h"
-#include <stdbool.h>
+#include "pycore_import.h" // _PyImport_GetModuleAttrString()
+#include "pycore_modsupport.h" // _PyArg_NoKeywords()
+#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
+#include "pycore_pylifecycle.h" // _Py_IsInterpreterFinalizing()
+#include "pycore_weakref.h"
-#if SQLITE_VERSION_NUMBER >= 3014000
-#define HAVE_TRACE_V2
-#endif
+#include <stdbool.h>
#if SQLITE_VERSION_NUMBER >= 3025000
#define HAVE_WINDOW_FUNCTIONS
@@ -70,16 +76,10 @@ isolation_level_converter(PyObject *str_or_none, const char **result)
*result = NULL;
}
else if (PyUnicode_Check(str_or_none)) {
- Py_ssize_t sz;
- const char *str = PyUnicode_AsUTF8AndSize(str_or_none, &sz);
+ const char *str = _PyUnicode_AsUTF8NoNUL(str_or_none);
if (str == NULL) {
return 0;
}
- if (strlen(str) != (size_t)sz) {
- PyErr_SetString(PyExc_ValueError, "embedded null character");
- return 0;
- }
-
const char *level = get_isolation_level(str);
if (level == NULL) {
return 0;
@@ -142,8 +142,9 @@ class _sqlite3.Connection "pysqlite_Connection *" "clinic_state()->ConnectionTyp
[clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=67369db2faf80891]*/
-static void _pysqlite_drop_unused_cursor_references(pysqlite_Connection* self);
-static void free_callback_context(callback_context *ctx);
+static int _pysqlite_drop_unused_cursor_references(pysqlite_Connection* self);
+static void incref_callback_context(callback_context *ctx);
+static void decref_callback_context(callback_context *ctx);
static void set_callback_context(callback_context **ctx_pp,
callback_context *ctx);
static int connection_close(pysqlite_Connection *self);
@@ -209,11 +210,11 @@ class sqlite3_int64_converter(CConverter):
[python start generated code]*/
/*[python end generated code: output=da39a3ee5e6b4b0d input=dff8760fb1eba6a1]*/
-// NB: This needs to be in sync with the sqlite3.connect docstring
/*[clinic input]
_sqlite3.Connection.__init__ as pysqlite_connection_init
database: object
+ * [from 3.15]
timeout: double = 5.0
detect_types: int = 0
isolation_level: IsolationLevel = ""
@@ -232,7 +233,7 @@ pysqlite_connection_init_impl(pysqlite_Connection *self, PyObject *database,
int check_same_thread, PyObject *factory,
int cache_size, int uri,
enum autocommit_mode autocommit)
-/*[clinic end generated code: output=cba057313ea7712f input=9b0ab6c12f674fa3]*/
+/*[clinic end generated code: output=cba057313ea7712f input=219c3dbecbae7d99]*/
{
if (PySys_Audit("sqlite3.connect", "O", database) < 0) {
return -1;
@@ -348,6 +349,34 @@ error:
return -1;
}
+/*[clinic input]
+# Create a new destination 'connect' for the docstring and methoddef only.
+# This makes it possible to keep the signatures for Connection.__init__ and
+# sqlite3.connect() synchronised.
+output push
+destination connect new file '{dirname}/clinic/_sqlite3.connect.c.h'
+
+# Only output the docstring and the PyMethodDef entry.
+output everything suppress
+output docstring_definition connect
+output methoddef_define connect
+
+# Define the sqlite3.connect function by cloning Connection.__init__.
+_sqlite3.connect as pysqlite_connect = _sqlite3.Connection.__init__
+
+Open a connection to the SQLite database file 'database'.
+
+You can use ":memory:" to open a database connection to a database that
+resides in RAM instead of on disk.
+[clinic start generated code]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=92260edff95d1720]*/
+
+/*[clinic input]
+# Restore normal Argument Clinic operation for the rest of this file.
+output pop
+[clinic start generated code]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=b899ba9273edcce7]*/
+
#define VISIT_CALLBACK_CONTEXT(ctx) \
do { \
if (ctx) { \
@@ -406,16 +435,11 @@ free_callback_contexts(pysqlite_Connection *self)
static void
remove_callbacks(sqlite3 *db)
{
- 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(db != NULL);
+ int 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_progress_handler(db, 0, 0, (void *)0);
@@ -467,6 +491,14 @@ connection_finalize(PyObject *self)
}
/* Clean up if user has not called .close() explicitly. */
+ if (con->db) {
+ if (PyErr_ResourceWarning(self, 1, "unclosed database in %R", self)) {
+ /* Spurious errors can appear at shutdown */
+ if (PyErr_ExceptionMatches(PyExc_Warning)) {
+ PyErr_WriteUnraisable(self);
+ }
+ }
+ }
if (connection_close(con) < 0) {
if (teardown) {
PyErr_Clear();
@@ -525,7 +557,10 @@ pysqlite_connection_cursor_impl(pysqlite_Connection *self, PyObject *factory)
return NULL;
}
- _pysqlite_drop_unused_cursor_references(self);
+ if (_pysqlite_drop_unused_cursor_references(self) < 0) {
+ Py_DECREF(cursor);
+ return NULL;
+ }
if (cursor && self->row_factory != Py_None) {
Py_INCREF(self->row_factory);
@@ -542,8 +577,8 @@ _sqlite3.Connection.blobopen as blobopen
Table name.
column as col: str
Column name.
- row: sqlite3_int64
- Row index.
+ rowid as row: sqlite3_int64
+ Row id.
/
*
readonly: bool = False
@@ -557,7 +592,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=23576bd1108d8774]*/
+/*[clinic end generated code: output=6a02d43efb885d1c input=cc3d4b47dac08401]*/
{
if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {
return NULL;
@@ -896,8 +931,9 @@ func_callback(sqlite3_context *context, int argc, sqlite3_value **argv)
args = _pysqlite_build_py_params(context, argc, argv);
if (args) {
callback_context *ctx = (callback_context *)sqlite3_user_data(context);
- assert(ctx != NULL);
+ incref_callback_context(ctx);
py_retval = PyObject_CallObject(ctx->callable, args);
+ decref_callback_context(ctx);
Py_DECREF(args);
}
@@ -924,7 +960,7 @@ step_callback(sqlite3_context *context, int argc, sqlite3_value **params)
PyObject* stepmethod = NULL;
callback_context *ctx = (callback_context *)sqlite3_user_data(context);
- assert(ctx != NULL);
+ incref_callback_context(ctx);
aggregate_instance = (PyObject**)sqlite3_aggregate_context(context, sizeof(PyObject*));
if (aggregate_instance == NULL) {
@@ -962,6 +998,7 @@ step_callback(sqlite3_context *context, int argc, sqlite3_value **params)
}
error:
+ decref_callback_context(ctx);
Py_XDECREF(stepmethod);
Py_XDECREF(function_result);
@@ -993,9 +1030,10 @@ final_callback(sqlite3_context *context)
PyObject *exc = PyErr_GetRaisedException();
callback_context *ctx = (callback_context *)sqlite3_user_data(context);
- assert(ctx != NULL);
+ incref_callback_context(ctx);
function_result = PyObject_CallMethodNoArgs(*aggregate_instance,
ctx->state->str_finalize);
+ decref_callback_context(ctx);
Py_DECREF(*aggregate_instance);
ok = 0;
@@ -1023,35 +1061,36 @@ error:
PyGILState_Release(threadstate);
}
-static void _pysqlite_drop_unused_cursor_references(pysqlite_Connection* self)
+static int
+_pysqlite_drop_unused_cursor_references(pysqlite_Connection* self)
{
- PyObject* new_list;
- PyObject* weakref;
- int i;
-
/* we only need to do this once in a while */
if (self->created_cursors++ < 200) {
- return;
+ return 0;
}
self->created_cursors = 0;
- new_list = PyList_New(0);
+ PyObject* new_list = PyList_New(0);
if (!new_list) {
- return;
+ return -1;
}
- for (i = 0; i < PyList_Size(self->cursors); i++) {
- weakref = PyList_GetItem(self->cursors, i);
- if (PyWeakref_GetObject(weakref) != Py_None) {
- if (PyList_Append(new_list, weakref) != 0) {
- Py_DECREF(new_list);
- return;
- }
+ assert(PyList_CheckExact(self->cursors));
+ Py_ssize_t imax = PyList_GET_SIZE(self->cursors);
+ for (Py_ssize_t i = 0; i < imax; i++) {
+ PyObject* weakref = PyList_GET_ITEM(self->cursors, i);
+ if (_PyWeakref_IsDead(weakref)) {
+ continue;
+ }
+ if (PyList_Append(new_list, weakref) != 0) {
+ Py_DECREF(new_list);
+ return -1;
}
}
Py_SETREF(self->cursors, new_list);
+ return 0;
}
/* Allocate a UDF/callback context structure. In order to ensure that the state
@@ -1064,12 +1103,16 @@ static callback_context *
create_callback_context(PyTypeObject *cls, PyObject *callable)
{
callback_context *ctx = PyMem_Malloc(sizeof(callback_context));
- if (ctx != NULL) {
- PyObject *module = PyType_GetModule(cls);
- ctx->callable = Py_NewRef(callable);
- ctx->module = Py_NewRef(module);
- ctx->state = pysqlite_get_state(module);
+ if (ctx == NULL) {
+ PyErr_NoMemory();
+ return NULL;
}
+
+ PyObject *module = PyType_GetModule(cls);
+ ctx->refcount = 1;
+ ctx->callable = Py_NewRef(callable);
+ ctx->module = Py_NewRef(module);
+ ctx->state = pysqlite_get_state(module);
return ctx;
}
@@ -1077,11 +1120,33 @@ static void
free_callback_context(callback_context *ctx)
{
assert(ctx != NULL);
+ assert(ctx->refcount == 0);
Py_XDECREF(ctx->callable);
Py_XDECREF(ctx->module);
PyMem_Free(ctx);
}
+static inline void
+incref_callback_context(callback_context *ctx)
+{
+ assert(PyGILState_Check());
+ assert(ctx != NULL);
+ assert(ctx->refcount > 0);
+ ctx->refcount++;
+}
+
+static inline void
+decref_callback_context(callback_context *ctx)
+{
+ assert(PyGILState_Check());
+ assert(ctx != NULL);
+ assert(ctx->refcount > 0);
+ ctx->refcount--;
+ if (ctx->refcount == 0) {
+ free_callback_context(ctx);
+ }
+}
+
static void
set_callback_context(callback_context **ctx_pp, callback_context *ctx)
{
@@ -1089,7 +1154,7 @@ set_callback_context(callback_context **ctx_pp, callback_context *ctx)
callback_context *tmp = *ctx_pp;
*ctx_pp = ctx;
if (tmp != NULL) {
- free_callback_context(tmp);
+ decref_callback_context(tmp);
}
}
@@ -1100,7 +1165,7 @@ destructor_callback(void *ctx)
// This function may be called without the GIL held, so we need to
// ensure that we destroy 'ctx' with the GIL held.
PyGILState_STATE gstate = PyGILState_Ensure();
- free_callback_context((callback_context *)ctx);
+ decref_callback_context((callback_context *)ctx);
PyGILState_Release(gstate);
}
}
@@ -1113,6 +1178,7 @@ _sqlite3.Connection.create_function as pysqlite_connection_create_function
name: str
narg: int
func: object
+ / [from 3.15]
*
deterministic: bool = False
@@ -1124,7 +1190,7 @@ pysqlite_connection_create_function_impl(pysqlite_Connection *self,
PyTypeObject *cls, const char *name,
int narg, PyObject *func,
int deterministic)
-/*[clinic end generated code: output=8a811529287ad240 input=b3e8e1d8ddaffbef]*/
+/*[clinic end generated code: output=8a811529287ad240 input=c7c313b0ca8b519e]*/
{
int rc;
int flags = SQLITE_UTF8;
@@ -1134,18 +1200,7 @@ pysqlite_connection_create_function_impl(pysqlite_Connection *self,
}
if (deterministic) {
-#if SQLITE_VERSION_NUMBER < 3008003
- PyErr_SetString(self->NotSupportedError,
- "deterministic=True requires SQLite 3.8.3 or higher");
- return NULL;
-#else
- if (sqlite3_libversion_number() < 3008003) {
- PyErr_SetString(self->NotSupportedError,
- "deterministic=True requires SQLite 3.8.3 or higher");
- return NULL;
- }
flags |= SQLITE_DETERMINISTIC;
-#endif
}
callback_context *ctx = create_callback_context(cls, func);
if (ctx == NULL) {
@@ -1155,7 +1210,7 @@ pysqlite_connection_create_function_impl(pysqlite_Connection *self,
func_callback,
NULL,
NULL,
- &destructor_callback); // will decref func
+ &destructor_callback); // will free 'ctx'
if (rc != SQLITE_OK) {
/* Workaround for SQLite bug: no error code or string is available here */
@@ -1179,7 +1234,7 @@ inverse_callback(sqlite3_context *context, int argc, sqlite3_value **params)
PyGILState_STATE gilstate = PyGILState_Ensure();
callback_context *ctx = (callback_context *)sqlite3_user_data(context);
- assert(ctx != NULL);
+ incref_callback_context(ctx);
int size = sizeof(PyObject *);
PyObject **cls = (PyObject **)sqlite3_aggregate_context(context, size);
@@ -1211,6 +1266,7 @@ inverse_callback(sqlite3_context *context, int argc, sqlite3_value **params)
Py_DECREF(res);
exit:
+ decref_callback_context(ctx);
Py_XDECREF(method);
PyGILState_Release(gilstate);
}
@@ -1227,7 +1283,7 @@ value_callback(sqlite3_context *context)
PyGILState_STATE gilstate = PyGILState_Ensure();
callback_context *ctx = (callback_context *)sqlite3_user_data(context);
- assert(ctx != NULL);
+ incref_callback_context(ctx);
int size = sizeof(PyObject *);
PyObject **cls = (PyObject **)sqlite3_aggregate_context(context, size);
@@ -1235,6 +1291,8 @@ value_callback(sqlite3_context *context)
assert(*cls != NULL);
PyObject *res = PyObject_CallMethodNoArgs(*cls, ctx->state->str_value);
+ decref_callback_context(ctx);
+
if (res == NULL) {
int attr_err = PyErr_ExceptionMatches(PyExc_AttributeError);
set_sqlite_error(context, attr_err
@@ -1326,6 +1384,7 @@ _sqlite3.Connection.create_aggregate as pysqlite_connection_create_aggregate
name: str
n_arg: int
aggregate_class: object
+ / [from 3.15]
Creates a new aggregate.
[clinic start generated code]*/
@@ -1335,7 +1394,7 @@ pysqlite_connection_create_aggregate_impl(pysqlite_Connection *self,
PyTypeObject *cls,
const char *name, int n_arg,
PyObject *aggregate_class)
-/*[clinic end generated code: output=1b02d0f0aec7ff96 input=68a2a26366d4c686]*/
+/*[clinic end generated code: output=1b02d0f0aec7ff96 input=8087056db6eae1cf]*/
{
int rc;
@@ -1351,7 +1410,7 @@ pysqlite_connection_create_aggregate_impl(pysqlite_Connection *self,
0,
&step_callback,
&final_callback,
- &destructor_callback); // will decref func
+ &destructor_callback); // will free 'ctx'
if (rc != SQLITE_OK) {
/* Workaround for SQLite bug: no error code or string is available here */
PyErr_SetString(self->OperationalError, "Error creating aggregate");
@@ -1361,7 +1420,7 @@ pysqlite_connection_create_aggregate_impl(pysqlite_Connection *self,
}
static int
-authorizer_callback(void *ctx, int action, const char *arg1,
+authorizer_callback(void *ctx_vp, int action, const char *arg1,
const char *arg2 , const char *dbname,
const char *access_attempt_source)
{
@@ -1370,8 +1429,9 @@ authorizer_callback(void *ctx, int action, const char *arg1,
PyObject *ret;
int rc = SQLITE_DENY;
- assert(ctx != NULL);
- PyObject *callable = ((callback_context *)ctx)->callable;
+ callback_context *ctx = (callback_context *)ctx_vp;
+ incref_callback_context(ctx);
+ PyObject *callable = ctx->callable;
ret = PyObject_CallFunction(callable, "issss", action, arg1, arg2, dbname,
access_attempt_source);
@@ -1381,7 +1441,7 @@ authorizer_callback(void *ctx, int action, const char *arg1,
}
else {
if (PyLong_Check(ret)) {
- rc = _PyLong_AsInt(ret);
+ rc = PyLong_AsInt(ret);
if (rc == -1 && PyErr_Occurred()) {
print_or_clear_traceback(ctx);
rc = SQLITE_DENY;
@@ -1393,21 +1453,23 @@ authorizer_callback(void *ctx, int action, const char *arg1,
Py_DECREF(ret);
}
+ decref_callback_context(ctx);
PyGILState_Release(gilstate);
return rc;
}
static int
-progress_callback(void *ctx)
+progress_callback(void *ctx_vp)
{
PyGILState_STATE gilstate = PyGILState_Ensure();
int rc;
PyObject *ret;
- assert(ctx != NULL);
- PyObject *callable = ((callback_context *)ctx)->callable;
- ret = PyObject_CallNoArgs(callable);
+ callback_context *ctx = (callback_context *)ctx_vp;
+ incref_callback_context(ctx);
+
+ ret = PyObject_CallNoArgs(ctx->callable);
if (!ret) {
/* abort query if error occurred */
rc = -1;
@@ -1420,11 +1482,11 @@ progress_callback(void *ctx)
print_or_clear_traceback(ctx);
}
+ decref_callback_context(ctx);
PyGILState_Release(gilstate);
return rc;
}
-#ifdef HAVE_TRACE_V2
/*
* From https://sqlite.org/c3ref/trace_v2.html:
* The integer return value from the callback is currently ignored, though this
@@ -1432,26 +1494,20 @@ progress_callback(void *ctx)
* to ensure future compatibility.
*/
static int
-trace_callback(unsigned int type, void *ctx, void *stmt, void *sql)
-#else
-static void
-trace_callback(void *ctx, const char *sql)
-#endif
+trace_callback(unsigned int type, void *ctx_vp, void *stmt, void *sql)
{
-#ifdef HAVE_TRACE_V2
if (type != SQLITE_TRACE_STMT) {
return 0;
}
-#endif
PyGILState_STATE gilstate = PyGILState_Ensure();
- assert(ctx != NULL);
- pysqlite_state *state = ((callback_context *)ctx)->state;
+ callback_context *ctx = (callback_context *)ctx_vp;
+ incref_callback_context(ctx);
+ pysqlite_state *state = ctx->state;
assert(state != NULL);
PyObject *py_statement = NULL;
-#ifdef HAVE_TRACE_V2
const char *expanded_sql = sqlite3_expanded_sql((sqlite3_stmt *)stmt);
if (expanded_sql == NULL) {
sqlite3 *db = sqlite3_db_handle((sqlite3_stmt *)stmt);
@@ -1462,7 +1518,7 @@ trace_callback(void *ctx, const char *sql)
PyErr_SetString(state->DataError,
"Expanded SQL string exceeds the maximum string length");
- print_or_clear_traceback((callback_context *)ctx);
+ print_or_clear_traceback(ctx);
// Fall back to unexpanded sql
py_statement = PyUnicode_FromString((const char *)sql);
@@ -1471,47 +1527,36 @@ trace_callback(void *ctx, const char *sql)
py_statement = PyUnicode_FromString(expanded_sql);
sqlite3_free((void *)expanded_sql);
}
-#else
- if (sql == NULL) {
- PyErr_SetString(state->DataError,
- "Expanded SQL string exceeds the maximum string length");
- print_or_clear_traceback((callback_context *)ctx);
- goto exit;
- }
- py_statement = PyUnicode_FromString(sql);
-#endif
if (py_statement) {
- PyObject *callable = ((callback_context *)ctx)->callable;
- PyObject *ret = PyObject_CallOneArg(callable, py_statement);
+ PyObject *ret = PyObject_CallOneArg(ctx->callable, py_statement);
Py_DECREF(py_statement);
Py_XDECREF(ret);
}
if (PyErr_Occurred()) {
- print_or_clear_traceback((callback_context *)ctx);
+ print_or_clear_traceback(ctx);
}
exit:
+ decref_callback_context(ctx);
PyGILState_Release(gilstate);
-#ifdef HAVE_TRACE_V2
return 0;
-#endif
}
/*[clinic input]
_sqlite3.Connection.set_authorizer as pysqlite_connection_set_authorizer
cls: defining_class
- /
authorizer_callback as callable: object
+ / [from 3.15]
-Sets authorizer callback.
+Set authorizer callback.
[clinic start generated code]*/
static PyObject *
pysqlite_connection_set_authorizer_impl(pysqlite_Connection *self,
PyTypeObject *cls,
PyObject *callable)
-/*[clinic end generated code: output=75fa60114fc971c3 input=605d32ba92dd3eca]*/
+/*[clinic end generated code: output=75fa60114fc971c3 input=a52bd4937c588752]*/
{
if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {
return NULL;
@@ -1543,18 +1588,25 @@ pysqlite_connection_set_authorizer_impl(pysqlite_Connection *self,
_sqlite3.Connection.set_progress_handler as pysqlite_connection_set_progress_handler
cls: defining_class
- /
progress_handler as callable: object
+ A callable that takes no arguments.
+ If the callable returns non-zero, the current query is terminated,
+ and an exception is raised.
+ / [from 3.15]
n: int
+ The number of SQLite virtual machine instructions that are
+ executed between invocations of 'progress_handler'.
-Sets progress handler callback.
+Set progress handler callback.
+
+If 'progress_handler' is None or 'n' is 0, the progress handler is disabled.
[clinic start generated code]*/
static PyObject *
pysqlite_connection_set_progress_handler_impl(pysqlite_Connection *self,
PyTypeObject *cls,
PyObject *callable, int n)
-/*[clinic end generated code: output=0739957fd8034a50 input=f7c1837984bd86db]*/
+/*[clinic end generated code: output=0739957fd8034a50 input=b4d6e2ef8b4d32f9]*/
{
if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {
return NULL;
@@ -1580,17 +1632,17 @@ pysqlite_connection_set_progress_handler_impl(pysqlite_Connection *self,
_sqlite3.Connection.set_trace_callback as pysqlite_connection_set_trace_callback
cls: defining_class
- /
trace_callback as callable: object
+ / [from 3.15]
-Sets a trace callback called for each SQL statement (passed as unicode).
+Set a trace callback called for each SQL statement (passed as unicode).
[clinic start generated code]*/
static PyObject *
pysqlite_connection_set_trace_callback_impl(pysqlite_Connection *self,
PyTypeObject *cls,
PyObject *callable)
-/*[clinic end generated code: output=d91048c03bfcee05 input=351a94210c5f81bb]*/
+/*[clinic end generated code: output=d91048c03bfcee05 input=d705d592ec03cf28]*/
{
if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {
return NULL;
@@ -1604,11 +1656,7 @@ pysqlite_connection_set_trace_callback_impl(pysqlite_Connection *self,
* - https://sqlite.org/c3ref/c_trace.html
* - https://sqlite.org/c3ref/trace_v2.html
*/
-#ifdef HAVE_TRACE_V2
sqlite3_trace_v2(self->db, SQLITE_TRACE_STMT, 0, 0);
-#else
- sqlite3_trace(self->db, 0, (void*)0);
-#endif
set_callback_context(&self->trace_ctx, NULL);
}
else {
@@ -1616,11 +1664,7 @@ pysqlite_connection_set_trace_callback_impl(pysqlite_Connection *self,
if (ctx == NULL) {
return NULL;
}
-#ifdef HAVE_TRACE_V2
sqlite3_trace_v2(self->db, SQLITE_TRACE_STMT, trace_callback, ctx);
-#else
- sqlite3_trace(self->db, trace_callback, ctx);
-#endif
set_callback_context(&self->trace_ctx, ctx);
}
@@ -1908,6 +1952,8 @@ collation_callback(void *context, int text1_length, const void *text1_data,
PyObject* retval = NULL;
long longval;
int result = 0;
+ callback_context *ctx = (callback_context *)context;
+ incref_callback_context(ctx);
/* This callback may be executed multiple times per sqlite3_step(). Bail if
* the previous call failed */
@@ -1924,8 +1970,6 @@ collation_callback(void *context, int text1_length, const void *text1_data,
goto finally;
}
- callback_context *ctx = (callback_context *)context;
- assert(ctx != NULL);
PyObject *args[] = { NULL, string1, string2 }; // Borrowed refs.
size_t nargsf = 2 | PY_VECTORCALL_ARGUMENTS_OFFSET;
retval = PyObject_Vectorcall(ctx->callable, args + 1, nargsf, NULL);
@@ -1947,6 +1991,7 @@ collation_callback(void *context, int text1_length, const void *text1_data,
}
finally:
+ decref_callback_context(ctx);
Py_XDECREF(string1);
Py_XDECREF(string2);
Py_XDECREF(retval);
@@ -1985,12 +2030,17 @@ finally:
/*[clinic input]
_sqlite3.Connection.iterdump as pysqlite_connection_iterdump
+ *
+ filter: object = None
+ An optional LIKE pattern for database objects to dump
+
Returns iterator to the dump of the database in an SQL text format.
[clinic start generated code]*/
static PyObject *
-pysqlite_connection_iterdump_impl(pysqlite_Connection *self)
-/*[clinic end generated code: output=586997aaf9808768 input=1911ca756066da89]*/
+pysqlite_connection_iterdump_impl(pysqlite_Connection *self,
+ PyObject *filter)
+/*[clinic end generated code: output=fd81069c4bdeb6b0 input=4ae6d9a898f108df]*/
{
if (!pysqlite_check_connection(self)) {
return NULL;
@@ -2004,9 +2054,16 @@ pysqlite_connection_iterdump_impl(pysqlite_Connection *self)
}
return NULL;
}
-
- PyObject *retval = PyObject_CallOneArg(iterdump, (PyObject *)self);
+ PyObject *args[3] = {NULL, (PyObject *)self, filter};
+ PyObject *kwnames = Py_BuildValue("(s)", "filter");
+ if (!kwnames) {
+ Py_DECREF(iterdump);
+ return NULL;
+ }
+ Py_ssize_t nargsf = 1 | PY_VECTORCALL_ARGUMENTS_OFFSET;
+ PyObject *retval = PyObject_Vectorcall(iterdump, args + 1, nargsf, kwnames);
Py_DECREF(iterdump);
+ Py_DECREF(kwnames);
return retval;
}
@@ -2048,15 +2105,6 @@ pysqlite_connection_backup_impl(pysqlite_Connection *self,
return NULL;
}
-#if SQLITE_VERSION_NUMBER < 3008008
- /* Since 3.8.8 this is already done, per commit
- https://www.sqlite.org/src/info/169b5505498c0a7e */
- if (!sqlite3_get_autocommit(target->db)) {
- PyErr_SetString(self->OperationalError, "target is in transaction");
- return NULL;
- }
-#endif
-
if (progress != Py_None && !PyCallable_Check(progress)) {
PyErr_SetString(PyExc_TypeError, "progress argument must be a callable");
return NULL;
@@ -2167,7 +2215,7 @@ pysqlite_connection_create_collation_impl(pysqlite_Connection *self,
* the context before returning.
*/
if (callable != Py_None) {
- free_callback_context(ctx);
+ decref_callback_context(ctx);
}
_pysqlite_seterror(self->state, self->db);
return NULL;
@@ -2419,12 +2467,8 @@ 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
@@ -2568,6 +2612,12 @@ set_autocommit(pysqlite_Connection *self, PyObject *val, void *Py_UNUSED(ctx))
return 0;
}
+static PyObject *
+get_sig(PyObject *self, void *Py_UNUSED(ctx))
+{
+ return PyUnicode_FromString("(sql, /)");
+}
+
static const char connection_doc[] =
PyDoc_STR("SQLite database connection object.");
@@ -2577,6 +2627,7 @@ static PyGetSetDef connection_getset[] = {
{"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},
+ {"__text_signature__", get_sig, (setter)0},
{NULL}
};
@@ -2614,18 +2665,18 @@ static PyMethodDef connection_methods[] = {
static struct PyMemberDef connection_members[] =
{
- {"Warning", T_OBJECT, offsetof(pysqlite_Connection, Warning), READONLY},
- {"Error", T_OBJECT, offsetof(pysqlite_Connection, Error), READONLY},
- {"InterfaceError", T_OBJECT, offsetof(pysqlite_Connection, InterfaceError), READONLY},
- {"DatabaseError", T_OBJECT, offsetof(pysqlite_Connection, DatabaseError), READONLY},
- {"DataError", T_OBJECT, offsetof(pysqlite_Connection, DataError), READONLY},
- {"OperationalError", T_OBJECT, offsetof(pysqlite_Connection, OperationalError), READONLY},
- {"IntegrityError", T_OBJECT, offsetof(pysqlite_Connection, IntegrityError), READONLY},
- {"InternalError", T_OBJECT, offsetof(pysqlite_Connection, InternalError), READONLY},
- {"ProgrammingError", T_OBJECT, offsetof(pysqlite_Connection, ProgrammingError), READONLY},
- {"NotSupportedError", T_OBJECT, offsetof(pysqlite_Connection, NotSupportedError), READONLY},
- {"row_factory", T_OBJECT, offsetof(pysqlite_Connection, row_factory)},
- {"text_factory", T_OBJECT, offsetof(pysqlite_Connection, text_factory)},
+ {"Warning", _Py_T_OBJECT, offsetof(pysqlite_Connection, Warning), Py_READONLY},
+ {"Error", _Py_T_OBJECT, offsetof(pysqlite_Connection, Error), Py_READONLY},
+ {"InterfaceError", _Py_T_OBJECT, offsetof(pysqlite_Connection, InterfaceError), Py_READONLY},
+ {"DatabaseError", _Py_T_OBJECT, offsetof(pysqlite_Connection, DatabaseError), Py_READONLY},
+ {"DataError", _Py_T_OBJECT, offsetof(pysqlite_Connection, DataError), Py_READONLY},
+ {"OperationalError", _Py_T_OBJECT, offsetof(pysqlite_Connection, OperationalError), Py_READONLY},
+ {"IntegrityError", _Py_T_OBJECT, offsetof(pysqlite_Connection, IntegrityError), Py_READONLY},
+ {"InternalError", _Py_T_OBJECT, offsetof(pysqlite_Connection, InternalError), Py_READONLY},
+ {"ProgrammingError", _Py_T_OBJECT, offsetof(pysqlite_Connection, ProgrammingError), Py_READONLY},
+ {"NotSupportedError", _Py_T_OBJECT, offsetof(pysqlite_Connection, NotSupportedError), Py_READONLY},
+ {"row_factory", _Py_T_OBJECT, offsetof(pysqlite_Connection, row_factory)},
+ {"text_factory", _Py_T_OBJECT, offsetof(pysqlite_Connection, text_factory)},
{NULL}
};