aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Modules/_sqlite/connection.c
diff options
context:
space:
mode:
authorErlend E. Aasland <erlend.aasland@protonmail.com>2023-04-26 21:57:48 +0200
committerGitHub <noreply@github.com>2023-04-26 19:57:48 +0000
commitbb8aa7a2b41ad7649d66909e5266fcee039e63ed (patch)
tree69b936d96b77a82a34968934abdb97632efa455c /Modules/_sqlite/connection.c
parent222c63fc6b91f42e7cc53574615f4e9b7a33c28f (diff)
downloadcpython-bb8aa7a2b41ad7649d66909e5266fcee039e63ed.tar.gz
cpython-bb8aa7a2b41ad7649d66909e5266fcee039e63ed.zip
gh-103489: Add get/set config methods to sqlite3.Connection (#103506)
Diffstat (limited to 'Modules/_sqlite/connection.c')
-rw-r--r--Modules/_sqlite/connection.c117
1 files changed, 117 insertions, 0 deletions
diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c
index e3a373d85ff..aec3aa8bbf4 100644
--- a/Modules/_sqlite/connection.c
+++ b/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
@@ -2343,6 +2345,119 @@ 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))
@@ -2424,6 +2539,8 @@ static PyMethodDef connection_methods[] = {
DESERIALIZE_METHODDEF
CREATE_WINDOW_FUNCTION_METHODDEF
BLOBOPEN_METHODDEF
+ SETCONFIG_METHODDEF
+ GETCONFIG_METHODDEF
{NULL, NULL}
};