From a5906b34cc8f49c7da8373c718ef3d02f0f7d49e Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sat, 13 Jun 2020 22:16:22 +0200 Subject: [PATCH 1/9] Convert module level functions except connect Note: Moves sqlite3.adapt from microprotocols.c to module.c --- Modules/_sqlite/clinic/module.c.h | 216 ++++++++++++++++++++++++++++++ Modules/_sqlite/microprotocols.c | 13 -- Modules/_sqlite/microprotocols.h | 5 - Modules/_sqlite/module.c | 163 ++++++++++++---------- 4 files changed, 309 insertions(+), 88 deletions(-) create mode 100644 Modules/_sqlite/clinic/module.c.h diff --git a/Modules/_sqlite/clinic/module.c.h b/Modules/_sqlite/clinic/module.c.h new file mode 100644 index 00000000000000..af9d39edb5168f --- /dev/null +++ b/Modules/_sqlite/clinic/module.c.h @@ -0,0 +1,216 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +PyDoc_STRVAR(pysqlite_complete_statement__doc__, +"complete_statement($module, statement, /)\n" +"--\n" +"\n" +"Checks if a string contains a complete SQL statement. Non-standard."); + +#define PYSQLITE_COMPLETE_STATEMENT_METHODDEF \ + {"complete_statement", (PyCFunction)pysqlite_complete_statement, METH_O, pysqlite_complete_statement__doc__}, + +static PyObject * +pysqlite_complete_statement_impl(PyObject *module, const char *statement); + +static PyObject * +pysqlite_complete_statement(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + const char *statement; + + if (!PyUnicode_Check(arg)) { + _PyArg_BadArgument("complete_statement", "argument", "str", arg); + goto exit; + } + Py_ssize_t statement_length; + statement = PyUnicode_AsUTF8AndSize(arg, &statement_length); + if (statement == NULL) { + goto exit; + } + if (strlen(statement) != (size_t)statement_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + return_value = pysqlite_complete_statement_impl(module, statement); + +exit: + return return_value; +} + +#if defined(HAVE_SHARED_CACHE) + +PyDoc_STRVAR(pysqlite_enable_shared_cache__doc__, +"enable_shared_cache($module, enable, /)\n" +"--\n" +"\n" +"Enable or disable shared cache mode for the calling thread.\n" +"\n" +"Experimental/Non-standard."); + +#define PYSQLITE_ENABLE_SHARED_CACHE_METHODDEF \ + {"enable_shared_cache", (PyCFunction)pysqlite_enable_shared_cache, METH_O, 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 *arg) +{ + PyObject *return_value = NULL; + int do_enable; + + do_enable = _PyLong_AsInt(arg); + if (do_enable == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = pysqlite_enable_shared_cache_impl(module, do_enable); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SHARED_CACHE) */ + +PyDoc_STRVAR(pysqlite_register_adapter__doc__, +"register_adapter($module, type, caster, /)\n" +"--\n" +"\n" +"Registers an adapter with pysqlite\'s adapter registry. Non-standard."); + +#define PYSQLITE_REGISTER_ADAPTER_METHODDEF \ + {"register_adapter", (PyCFunction)(void(*)(void))pysqlite_register_adapter, METH_FASTCALL, pysqlite_register_adapter__doc__}, + +static PyObject * +pysqlite_register_adapter_impl(PyObject *module, PyTypeObject *type, + PyObject *caster); + +static PyObject * +pysqlite_register_adapter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyTypeObject *type; + PyObject *caster; + + if (!_PyArg_CheckPositional("register_adapter", nargs, 2, 2)) { + goto exit; + } + type = (PyTypeObject *)args[0]; + caster = args[1]; + return_value = pysqlite_register_adapter_impl(module, type, caster); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_register_converter__doc__, +"register_converter($module, name, converter, /)\n" +"--\n" +"\n" +"Registers a converter with pysqlite. Non-standard."); + +#define PYSQLITE_REGISTER_CONVERTER_METHODDEF \ + {"register_converter", (PyCFunction)(void(*)(void))pysqlite_register_converter, METH_FASTCALL, pysqlite_register_converter__doc__}, + +static PyObject * +pysqlite_register_converter_impl(PyObject *module, PyObject *orig_name, + PyObject *callable); + +static PyObject * +pysqlite_register_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *orig_name; + PyObject *callable; + + if (!_PyArg_CheckPositional("register_converter", nargs, 2, 2)) { + goto exit; + } + if (!PyUnicode_Check(args[0])) { + _PyArg_BadArgument("register_converter", "argument 1", "str", args[0]); + goto exit; + } + if (PyUnicode_READY(args[0]) == -1) { + goto exit; + } + orig_name = args[0]; + callable = args[1]; + return_value = pysqlite_register_converter_impl(module, orig_name, callable); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_enable_callback_trace__doc__, +"enable_callback_tracebacks($module, enable, /)\n" +"--\n" +"\n" +"Enable or disable callback functions throwing errors to stderr."); + +#define PYSQLITE_ENABLE_CALLBACK_TRACE_METHODDEF \ + {"enable_callback_tracebacks", (PyCFunction)pysqlite_enable_callback_trace, METH_O, pysqlite_enable_callback_trace__doc__}, + +static PyObject * +pysqlite_enable_callback_trace_impl(PyObject *module, int enable); + +static PyObject * +pysqlite_enable_callback_trace(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int enable; + + enable = _PyLong_AsInt(arg); + if (enable == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = pysqlite_enable_callback_trace_impl(module, enable); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_adapt__doc__, +"adapt($module, obj, proto=PrepareProtocolType, alt=, /)\n" +"--\n" +"\n" +"Adapt given object to given protocol. Non-standard."); + +#define PYSQLITE_ADAPT_METHODDEF \ + {"adapt", (PyCFunction)(void(*)(void))pysqlite_adapt, METH_FASTCALL, pysqlite_adapt__doc__}, + +static PyObject * +pysqlite_adapt_impl(PyObject *module, PyObject *obj, PyObject *proto, + PyObject *alt); + +static PyObject * +pysqlite_adapt(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *obj; + PyObject *proto = (PyObject*)&pysqlite_PrepareProtocolType; + PyObject *alt = NULL; + + if (!_PyArg_CheckPositional("adapt", nargs, 1, 3)) { + goto exit; + } + obj = args[0]; + if (nargs < 2) { + goto skip_optional; + } + proto = args[1]; + if (nargs < 3) { + goto skip_optional; + } + alt = args[2]; +skip_optional: + return_value = pysqlite_adapt_impl(module, obj, proto, alt); + +exit: + return return_value; +} + +#ifndef PYSQLITE_ENABLE_SHARED_CACHE_METHODDEF + #define PYSQLITE_ENABLE_SHARED_CACHE_METHODDEF +#endif /* !defined(PYSQLITE_ENABLE_SHARED_CACHE_METHODDEF) */ +/*[clinic end generated code: output=2f740fe39ac0ec71 input=a9049054013a1b77]*/ diff --git a/Modules/_sqlite/microprotocols.c b/Modules/_sqlite/microprotocols.c index 3b2d7f42b87353..0ef1ff95a4971e 100644 --- a/Modules/_sqlite/microprotocols.c +++ b/Modules/_sqlite/microprotocols.c @@ -29,7 +29,6 @@ #include "microprotocols.h" #include "prepare_protocol.h" - /** the adapters registry **/ static PyObject *psyco_adapters = NULL; @@ -145,15 +144,3 @@ pysqlite_microprotocols_adapt(PyObject *obj, PyObject *proto, PyObject *alt) PyErr_SetString(pysqlite_ProgrammingError, "can't adapt"); return NULL; } - -/** module-level functions **/ - -PyObject * -pysqlite_adapt(pysqlite_Cursor *self, PyObject *args) -{ - PyObject *obj, *alt = NULL; - PyObject *proto = (PyObject*)&pysqlite_PrepareProtocolType; - - if (!PyArg_ParseTuple(args, "O|OO", &obj, &proto, &alt)) return NULL; - return pysqlite_microprotocols_adapt(obj, proto, alt); -} diff --git a/Modules/_sqlite/microprotocols.h b/Modules/_sqlite/microprotocols.h index 5418c2b98fd751..bdd863b1733aa1 100644 --- a/Modules/_sqlite/microprotocols.h +++ b/Modules/_sqlite/microprotocols.h @@ -44,9 +44,4 @@ extern int pysqlite_microprotocols_add( extern PyObject *pysqlite_microprotocols_adapt( PyObject *obj, PyObject *proto, PyObject *alt); -extern PyObject * - pysqlite_adapt(pysqlite_Cursor* self, PyObject *args); -#define pysqlite_adapt_doc \ - "adapt(obj, protocol, alternate) -> adapt obj to given protocol. Non-standard." - #endif /* !defined(PSYCOPG_MICROPROTOCOLS_H) */ diff --git a/Modules/_sqlite/module.c b/Modules/_sqlite/module.c index 82f58eb2480261..b7a3ac2eeea450 100644 --- a/Modules/_sqlite/module.c +++ b/Modules/_sqlite/module.c @@ -33,6 +33,12 @@ #error "SQLite 3.7.3 or higher required" #endif +#include "clinic/module.c.h" +/*[clinic input] +module _sqlite3 +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=81e330492d57488e]*/ + /* static objects at module-level */ PyObject *pysqlite_Error = NULL; @@ -102,18 +108,20 @@ Opens a connection to the SQLite database file *database*. You can use\n\ \":memory:\" to open a database connection to a database that resides in\n\ RAM instead of on disk."); -static PyObject* module_complete(PyObject* self, PyObject* args, PyObject* - kwargs) -{ - static char *kwlist[] = {"statement", NULL}; - char* statement; +/*[clinic input] +_sqlite3.complete_statement as pysqlite_complete_statement - PyObject* result; + statement: str + / - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &statement)) - { - return NULL; - } +Checks if a string contains a complete SQL statement. Non-standard. +[clinic start generated code]*/ + +static PyObject * +pysqlite_complete_statement_impl(PyObject *module, const char *statement) +/*[clinic end generated code: output=e55f1ff1952df558 input=b15b778a9c1b557b]*/ +{ + PyObject* result; if (sqlite3_complete(statement)) { result = Py_True; @@ -126,23 +134,23 @@ static PyObject* module_complete(PyObject* self, PyObject* args, PyObject* return result; } -PyDoc_STRVAR(module_complete_doc, -"complete_statement(sql)\n\ -\n\ -Checks if a string contains a complete SQL statement. Non-standard."); +/*[clinic input] +_sqlite3.enable_shared_cache as pysqlite_enable_shared_cache -static PyObject* module_enable_shared_cache(PyObject* self, PyObject* args, PyObject* - kwargs) + enable as do_enable: int + / + +Enable or disable shared cache mode for the calling thread. + +Experimental/Non-standard. +[clinic start generated code]*/ + +static PyObject * +pysqlite_enable_shared_cache_impl(PyObject *module, int do_enable) +/*[clinic end generated code: output=259c74eedee1516b input=6c608c515bd7caba]*/ { - static char *kwlist[] = {"do_enable", NULL}; - int do_enable; int rc; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i", kwlist, &do_enable)) - { - return NULL; - } - rc = sqlite3_enable_shared_cache(do_enable); if (rc != SQLITE_OK) { @@ -153,22 +161,23 @@ static PyObject* module_enable_shared_cache(PyObject* self, PyObject* args, PyOb } } -PyDoc_STRVAR(module_enable_shared_cache_doc, -"enable_shared_cache(do_enable)\n\ -\n\ -Enable or disable shared cache mode for the calling thread.\n\ -Experimental/Non-standard."); +/*[clinic input] +_sqlite3.register_adapter as pysqlite_register_adapter + + type: object(type='PyTypeObject *') + caster: object + / -static PyObject* module_register_adapter(PyObject* self, PyObject* args) +Registers an adapter with pysqlite's adapter registry. Non-standard. +[clinic start generated code]*/ + +static PyObject * +pysqlite_register_adapter_impl(PyObject *module, PyTypeObject *type, + PyObject *caster) +/*[clinic end generated code: output=a287e8db18e8af23 input=839dad90e2492725]*/ { - PyTypeObject* type; - PyObject* caster; int rc; - if (!PyArg_ParseTuple(args, "OO", &type, &caster)) { - return NULL; - } - /* a basic type is adapted; there's a performance optimization if that's not the case * (99 % of all usages) */ if (type == &PyLong_Type || type == &PyFloat_Type @@ -183,23 +192,25 @@ static PyObject* module_register_adapter(PyObject* self, PyObject* args) Py_RETURN_NONE; } -PyDoc_STRVAR(module_register_adapter_doc, -"register_adapter(type, callable)\n\ -\n\ -Registers an adapter with pysqlite's adapter registry. Non-standard."); +/*[clinic input] +_sqlite3.register_converter as pysqlite_register_converter + + name as orig_name: unicode + converter as callable: object + / -static PyObject* module_register_converter(PyObject* self, PyObject* args) +Registers a converter with pysqlite. Non-standard. +[clinic start generated code]*/ + +static PyObject * +pysqlite_register_converter_impl(PyObject *module, PyObject *orig_name, + PyObject *callable) +/*[clinic end generated code: output=a2f2bfeed7230062 input=e074cf7f4890544f]*/ { - PyObject* orig_name; PyObject* name = NULL; - PyObject* callable; PyObject* retval = NULL; _Py_IDENTIFIER(upper); - if (!PyArg_ParseTuple(args, "UO", &orig_name, &callable)) { - return NULL; - } - /* convert the name to upper case */ name = _PyObject_CallMethodIdNoArgs(orig_name, &PyId_upper); if (!name) { @@ -217,24 +228,42 @@ static PyObject* module_register_converter(PyObject* self, PyObject* args) return retval; } -PyDoc_STRVAR(module_register_converter_doc, -"register_converter(typename, callable)\n\ -\n\ -Registers a converter with pysqlite. Non-standard."); +/*[clinic input] +_sqlite3.enable_callback_tracebacks as pysqlite_enable_callback_trace -static PyObject* enable_callback_tracebacks(PyObject* self, PyObject* args) + enable: int + / + +Enable or disable callback functions throwing errors to stderr. +[clinic start generated code]*/ + +static PyObject * +pysqlite_enable_callback_trace_impl(PyObject *module, int enable) +/*[clinic end generated code: output=4ff1d051c698f194 input=cb79d3581eb77c40]*/ { - if (!PyArg_ParseTuple(args, "i", &_pysqlite_enable_callback_tracebacks)) { - return NULL; - } + _pysqlite_enable_callback_tracebacks = enable; Py_RETURN_NONE; } -PyDoc_STRVAR(enable_callback_tracebacks_doc, -"enable_callback_tracebacks(flag)\n\ -\n\ -Enable or disable callback functions throwing errors to stderr."); +/*[clinic input] +_sqlite3.adapt as pysqlite_adapt + + obj: object + proto: object(c_default='(PyObject*)&pysqlite_PrepareProtocolType') = PrepareProtocolType + alt: object = NULL + / + +Adapt given object to given protocol. Non-standard. +[clinic start generated code]*/ + +static PyObject * +pysqlite_adapt_impl(PyObject *module, PyObject *obj, PyObject *proto, + PyObject *alt) +/*[clinic end generated code: output=0c3927c5fcd23dd9 input=37bc55a5a6ee407c]*/ +{ + return pysqlite_microprotocols_adapt(obj, proto, alt); +} static void converters_init(PyObject* dict) { @@ -249,18 +278,12 @@ static void converters_init(PyObject* dict) static PyMethodDef module_methods[] = { {"connect", (PyCFunction)(void(*)(void))module_connect, METH_VARARGS | METH_KEYWORDS, module_connect_doc}, - {"complete_statement", (PyCFunction)(void(*)(void))module_complete, - METH_VARARGS | METH_KEYWORDS, module_complete_doc}, - {"enable_shared_cache", (PyCFunction)(void(*)(void))module_enable_shared_cache, - METH_VARARGS | METH_KEYWORDS, module_enable_shared_cache_doc}, - {"register_adapter", (PyCFunction)module_register_adapter, - METH_VARARGS, module_register_adapter_doc}, - {"register_converter", (PyCFunction)module_register_converter, - METH_VARARGS, module_register_converter_doc}, - {"adapt", (PyCFunction)pysqlite_adapt, METH_VARARGS, - pysqlite_adapt_doc}, - {"enable_callback_tracebacks", (PyCFunction)enable_callback_tracebacks, - METH_VARARGS, enable_callback_tracebacks_doc}, + PYSQLITE_ADAPT_METHODDEF + PYSQLITE_COMPLETE_STATEMENT_METHODDEF + PYSQLITE_ENABLE_CALLBACK_TRACE_METHODDEF + PYSQLITE_ENABLE_SHARED_CACHE_METHODDEF + PYSQLITE_REGISTER_ADAPTER_METHODDEF + PYSQLITE_REGISTER_CONVERTER_METHODDEF {NULL, NULL} }; From 2557de53ff46fec4f2011f88ef04b4f0c81e037c Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sat, 13 Jun 2020 23:38:44 +0200 Subject: [PATCH 2/9] Convert Connection --- Modules/_sqlite/clinic/connection.c.h | 685 ++++++++++++++++++++++++++ Modules/_sqlite/connection.c | 495 +++++++++++-------- Modules/_sqlite/connection.h | 4 - Modules/_sqlite/cursor.c | 3 +- 4 files changed, 977 insertions(+), 210 deletions(-) create mode 100644 Modules/_sqlite/clinic/connection.c.h diff --git a/Modules/_sqlite/clinic/connection.c.h b/Modules/_sqlite/clinic/connection.c.h new file mode 100644 index 00000000000000..ddae4a5b108817 --- /dev/null +++ b/Modules/_sqlite/clinic/connection.c.h @@ -0,0 +1,685 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +PyDoc_STRVAR(pysqlite_connection_cursor__doc__, +"cursor($self, /, factory=)\n" +"--\n" +"\n" +"Return a cursor for the connection."); + +#define PYSQLITE_CONNECTION_CURSOR_METHODDEF \ + {"cursor", (PyCFunction)(void(*)(void))pysqlite_connection_cursor, METH_FASTCALL|METH_KEYWORDS, pysqlite_connection_cursor__doc__}, + +static PyObject * +pysqlite_connection_cursor_impl(pysqlite_Connection *self, PyObject *factory); + +static PyObject * +pysqlite_connection_cursor(pysqlite_Connection *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"factory", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "cursor", 0}; + PyObject *argsbuf[1]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + PyObject *factory = NULL; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + factory = args[0]; +skip_optional_pos: + return_value = pysqlite_connection_cursor_impl(self, factory); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_connection_close__doc__, +"close($self, /)\n" +"--\n" +"\n" +"Closes the connection."); + +#define PYSQLITE_CONNECTION_CLOSE_METHODDEF \ + {"close", (PyCFunction)pysqlite_connection_close, METH_NOARGS, pysqlite_connection_close__doc__}, + +static PyObject * +pysqlite_connection_close_impl(pysqlite_Connection *self); + +static PyObject * +pysqlite_connection_close(pysqlite_Connection *self, PyObject *Py_UNUSED(ignored)) +{ + return pysqlite_connection_close_impl(self); +} + +PyDoc_STRVAR(pysqlite_connection_commit__doc__, +"commit($self, /)\n" +"--\n" +"\n" +"Commit the current transaction."); + +#define PYSQLITE_CONNECTION_COMMIT_METHODDEF \ + {"commit", (PyCFunction)pysqlite_connection_commit, METH_NOARGS, pysqlite_connection_commit__doc__}, + +static PyObject * +pysqlite_connection_commit_impl(pysqlite_Connection *self); + +static PyObject * +pysqlite_connection_commit(pysqlite_Connection *self, PyObject *Py_UNUSED(ignored)) +{ + return pysqlite_connection_commit_impl(self); +} + +PyDoc_STRVAR(pysqlite_connection_rollback__doc__, +"rollback($self, /)\n" +"--\n" +"\n" +"Roll back the current transaction."); + +#define PYSQLITE_CONNECTION_ROLLBACK_METHODDEF \ + {"rollback", (PyCFunction)pysqlite_connection_rollback, METH_NOARGS, pysqlite_connection_rollback__doc__}, + +static PyObject * +pysqlite_connection_rollback_impl(pysqlite_Connection *self); + +static PyObject * +pysqlite_connection_rollback(pysqlite_Connection *self, PyObject *Py_UNUSED(ignored)) +{ + return pysqlite_connection_rollback_impl(self); +} + +PyDoc_STRVAR(pysqlite_connection_create_function__doc__, +"create_function($self, /, name, narg, func, *, deterministic=False)\n" +"--\n" +"\n" +"Creates a new function. Non-standard."); + +#define PYSQLITE_CONNECTION_CREATE_FUNCTION_METHODDEF \ + {"create_function", (PyCFunction)(void(*)(void))pysqlite_connection_create_function, METH_FASTCALL|METH_KEYWORDS, pysqlite_connection_create_function__doc__}, + +static PyObject * +pysqlite_connection_create_function_impl(pysqlite_Connection *self, + const char *name, int narg, + PyObject *func, int deterministic); + +static PyObject * +pysqlite_connection_create_function(pysqlite_Connection *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"name", "narg", "func", "deterministic", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "create_function", 0}; + PyObject *argsbuf[4]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; + const char *name; + int narg; + PyObject *func; + int deterministic = 0; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf); + if (!args) { + goto exit; + } + if (!PyUnicode_Check(args[0])) { + _PyArg_BadArgument("create_function", "argument 'name'", "str", args[0]); + goto exit; + } + Py_ssize_t name_length; + name = PyUnicode_AsUTF8AndSize(args[0], &name_length); + if (name == NULL) { + goto exit; + } + if (strlen(name) != (size_t)name_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + narg = _PyLong_AsInt(args[1]); + if (narg == -1 && PyErr_Occurred()) { + goto exit; + } + func = args[2]; + if (!noptargs) { + goto skip_optional_kwonly; + } + deterministic = PyObject_IsTrue(args[3]); + if (deterministic < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = pysqlite_connection_create_function_impl(self, name, narg, func, deterministic); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_connection_create_aggregate__doc__, +"create_aggregate($self, /, name, n_arg, aggregate_class)\n" +"--\n" +"\n" +"Creates a new aggregate. Non-standard."); + +#define PYSQLITE_CONNECTION_CREATE_AGGREGATE_METHODDEF \ + {"create_aggregate", (PyCFunction)(void(*)(void))pysqlite_connection_create_aggregate, METH_FASTCALL|METH_KEYWORDS, pysqlite_connection_create_aggregate__doc__}, + +static PyObject * +pysqlite_connection_create_aggregate_impl(pysqlite_Connection *self, + const char *name, int n_arg, + PyObject *aggregate_class); + +static PyObject * +pysqlite_connection_create_aggregate(pysqlite_Connection *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"name", "n_arg", "aggregate_class", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "create_aggregate", 0}; + PyObject *argsbuf[3]; + const char *name; + int n_arg; + PyObject *aggregate_class; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf); + if (!args) { + goto exit; + } + if (!PyUnicode_Check(args[0])) { + _PyArg_BadArgument("create_aggregate", "argument 'name'", "str", args[0]); + goto exit; + } + Py_ssize_t name_length; + name = PyUnicode_AsUTF8AndSize(args[0], &name_length); + if (name == NULL) { + goto exit; + } + if (strlen(name) != (size_t)name_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + n_arg = _PyLong_AsInt(args[1]); + if (n_arg == -1 && PyErr_Occurred()) { + goto exit; + } + aggregate_class = args[2]; + return_value = pysqlite_connection_create_aggregate_impl(self, name, n_arg, aggregate_class); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_connection_set_authorizer__doc__, +"set_authorizer($self, authorizer_callback, /)\n" +"--\n" +"\n" +"Sets authorizer callback. Non-standard."); + +#define PYSQLITE_CONNECTION_SET_AUTHORIZER_METHODDEF \ + {"set_authorizer", (PyCFunction)pysqlite_connection_set_authorizer, METH_O, pysqlite_connection_set_authorizer__doc__}, + +PyDoc_STRVAR(pysqlite_connection_set_progress_handler__doc__, +"set_progress_handler($self, /, progress_handler, n)\n" +"--\n" +"\n" +"Sets progress handler callback. Non-standard."); + +#define PYSQLITE_CONNECTION_SET_PROGRESS_HANDLER_METHODDEF \ + {"set_progress_handler", (PyCFunction)(void(*)(void))pysqlite_connection_set_progress_handler, METH_FASTCALL|METH_KEYWORDS, pysqlite_connection_set_progress_handler__doc__}, + +static PyObject * +pysqlite_connection_set_progress_handler_impl(pysqlite_Connection *self, + PyObject *progress_handler, + int n); + +static PyObject * +pysqlite_connection_set_progress_handler(pysqlite_Connection *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"progress_handler", "n", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "set_progress_handler", 0}; + PyObject *argsbuf[2]; + PyObject *progress_handler; + int n; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + progress_handler = args[0]; + n = _PyLong_AsInt(args[1]); + if (n == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = pysqlite_connection_set_progress_handler_impl(self, progress_handler, n); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_connection_set_trace_callback__doc__, +"set_trace_callback($self, trace_callback, /)\n" +"--\n" +"\n" +"Sets a trace callback called for each SQL statement (passed as unicode).\n" +"\n" +"Non-standard."); + +#define PYSQLITE_CONNECTION_SET_TRACE_CALLBACK_METHODDEF \ + {"set_trace_callback", (PyCFunction)pysqlite_connection_set_trace_callback, METH_O, pysqlite_connection_set_trace_callback__doc__}, + +#if defined(HAVE_LOAD_EXTENSION) + +PyDoc_STRVAR(pysqlite_connection_enable_load_extension__doc__, +"enable_load_extension($self, enable, /)\n" +"--\n" +"\n" +"Enable dynamic loading of SQLite extension modules. Non-standard."); + +#define PYSQLITE_CONNECTION_ENABLE_LOAD_EXTENSION_METHODDEF \ + {"enable_load_extension", (PyCFunction)pysqlite_connection_enable_load_extension, METH_O, pysqlite_connection_enable_load_extension__doc__}, + +static PyObject * +pysqlite_connection_enable_load_extension_impl(pysqlite_Connection *self, + int onoff); + +static PyObject * +pysqlite_connection_enable_load_extension(pysqlite_Connection *self, PyObject *arg) +{ + PyObject *return_value = NULL; + int onoff; + + onoff = _PyLong_AsInt(arg); + if (onoff == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = pysqlite_connection_enable_load_extension_impl(self, onoff); + +exit: + return return_value; +} + +#endif /* defined(HAVE_LOAD_EXTENSION) */ + +#if defined(HAVE_LOAD_EXTENSION) + +PyDoc_STRVAR(pysqlite_connection_load_extension__doc__, +"load_extension($self, name, /)\n" +"--\n" +"\n" +"Load SQLite extension module. Non-standard."); + +#define PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF \ + {"load_extension", (PyCFunction)pysqlite_connection_load_extension, METH_O, pysqlite_connection_load_extension__doc__}, + +static PyObject * +pysqlite_connection_load_extension_impl(pysqlite_Connection *self, + const char *extension_name); + +static PyObject * +pysqlite_connection_load_extension(pysqlite_Connection *self, PyObject *arg) +{ + PyObject *return_value = NULL; + const char *extension_name; + + if (!PyUnicode_Check(arg)) { + _PyArg_BadArgument("load_extension", "argument", "str", arg); + goto exit; + } + Py_ssize_t extension_name_length; + extension_name = PyUnicode_AsUTF8AndSize(arg, &extension_name_length); + if (extension_name == NULL) { + goto exit; + } + if (strlen(extension_name) != (size_t)extension_name_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + return_value = pysqlite_connection_load_extension_impl(self, extension_name); + +exit: + return return_value; +} + +#endif /* defined(HAVE_LOAD_EXTENSION) */ + +PyDoc_STRVAR(pysqlite_connection_execute__doc__, +"execute($self, sql, /, parameters=)\n" +"--\n" +"\n" +"Executes a SQL statement. Non-standard."); + +#define PYSQLITE_CONNECTION_EXECUTE_METHODDEF \ + {"execute", (PyCFunction)(void(*)(void))pysqlite_connection_execute, METH_FASTCALL|METH_KEYWORDS, pysqlite_connection_execute__doc__}, + +static PyObject * +pysqlite_connection_execute_impl(pysqlite_Connection *self, PyObject *sql, + PyObject *parameters); + +static PyObject * +pysqlite_connection_execute(pysqlite_Connection *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"", "parameters", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "execute", 0}; + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + PyObject *sql; + PyObject *parameters = NULL; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!PyUnicode_Check(args[0])) { + _PyArg_BadArgument("execute", "argument 1", "str", args[0]); + goto exit; + } + if (PyUnicode_READY(args[0]) == -1) { + goto exit; + } + sql = args[0]; + if (!noptargs) { + goto skip_optional_pos; + } + parameters = args[1]; +skip_optional_pos: + return_value = pysqlite_connection_execute_impl(self, sql, parameters); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_connection_executemany__doc__, +"executemany($self, sql, parameters, /)\n" +"--\n" +"\n" +"Repeatedly executes a SQL statement. Non-standard."); + +#define PYSQLITE_CONNECTION_EXECUTEMANY_METHODDEF \ + {"executemany", (PyCFunction)(void(*)(void))pysqlite_connection_executemany, METH_FASTCALL, pysqlite_connection_executemany__doc__}, + +static PyObject * +pysqlite_connection_executemany_impl(pysqlite_Connection *self, + PyObject *sql, PyObject *parameters); + +static PyObject * +pysqlite_connection_executemany(pysqlite_Connection *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *sql; + PyObject *parameters; + + if (!_PyArg_CheckPositional("executemany", nargs, 2, 2)) { + goto exit; + } + if (!PyUnicode_Check(args[0])) { + _PyArg_BadArgument("executemany", "argument 1", "str", args[0]); + goto exit; + } + if (PyUnicode_READY(args[0]) == -1) { + goto exit; + } + sql = args[0]; + parameters = args[1]; + return_value = pysqlite_connection_executemany_impl(self, sql, parameters); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_connection_executescript__doc__, +"executescript($self, sql_script, /)\n" +"--\n" +"\n"); + +#define PYSQLITE_CONNECTION_EXECUTESCRIPT_METHODDEF \ + {"executescript", (PyCFunction)pysqlite_connection_executescript, METH_O, pysqlite_connection_executescript__doc__}, + +PyDoc_STRVAR(pysqlite_connection_interrupt__doc__, +"interrupt($self, /)\n" +"--\n" +"\n" +"Abort any pending database operation. Non-standard."); + +#define PYSQLITE_CONNECTION_INTERRUPT_METHODDEF \ + {"interrupt", (PyCFunction)pysqlite_connection_interrupt, METH_NOARGS, pysqlite_connection_interrupt__doc__}, + +static PyObject * +pysqlite_connection_interrupt_impl(pysqlite_Connection *self); + +static PyObject * +pysqlite_connection_interrupt(pysqlite_Connection *self, PyObject *Py_UNUSED(ignored)) +{ + return pysqlite_connection_interrupt_impl(self); +} + +PyDoc_STRVAR(pysqlite_connection_iterdump__doc__, +"iterdump($self, /)\n" +"--\n" +"\n" +"Returns iterator to the dump of the database in an SQL text format.\n" +"\n" +"Non-standard."); + +#define PYSQLITE_CONNECTION_ITERDUMP_METHODDEF \ + {"iterdump", (PyCFunction)pysqlite_connection_iterdump, METH_NOARGS, pysqlite_connection_iterdump__doc__}, + +static PyObject * +pysqlite_connection_iterdump_impl(pysqlite_Connection *self); + +static PyObject * +pysqlite_connection_iterdump(pysqlite_Connection *self, PyObject *Py_UNUSED(ignored)) +{ + return pysqlite_connection_iterdump_impl(self); +} + +#if defined(HAVE_BACKUP_API) + +PyDoc_STRVAR(pysqlite_connection_backup__doc__, +"backup($self, /, target=, *, pages=-1, progress=None,\n" +" name=\'main\', sleep=0.25)\n" +"--\n" +"\n"); + +#define PYSQLITE_CONNECTION_BACKUP_METHODDEF \ + {"backup", (PyCFunction)(void(*)(void))pysqlite_connection_backup, METH_FASTCALL|METH_KEYWORDS, pysqlite_connection_backup__doc__}, + +static PyObject * +pysqlite_connection_backup_impl(pysqlite_Connection *self, + pysqlite_Connection *target, int pages, + PyObject *progress, const char *name, + double sleep); + +static PyObject * +pysqlite_connection_backup(pysqlite_Connection *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"target", "pages", "progress", "name", "sleep", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "backup", 0}; + PyObject *argsbuf[5]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + pysqlite_Connection *target = NULL; + int pages = -1; + PyObject *progress = Py_None; + const char *name = "main"; + double sleep = 0.25; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[0]) { + if (!PyObject_TypeCheck(args[0], &pysqlite_ConnectionType)) { + _PyArg_BadArgument("backup", "argument 'target'", (&pysqlite_ConnectionType)->tp_name, args[0]); + goto exit; + } + target = (pysqlite_Connection *)args[0]; + if (!--noptargs) { + goto skip_optional_pos; + } + } +skip_optional_pos: + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[1]) { + pages = _PyLong_AsInt(args[1]); + if (pages == -1 && PyErr_Occurred()) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[2]) { + progress = args[2]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[3]) { + if (!PyUnicode_Check(args[3])) { + _PyArg_BadArgument("backup", "argument 'name'", "str", args[3]); + goto exit; + } + Py_ssize_t name_length; + name = PyUnicode_AsUTF8AndSize(args[3], &name_length); + if (name == NULL) { + goto exit; + } + if (strlen(name) != (size_t)name_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (PyFloat_CheckExact(args[4])) { + sleep = PyFloat_AS_DOUBLE(args[4]); + } + else + { + sleep = PyFloat_AsDouble(args[4]); + if (sleep == -1.0 && PyErr_Occurred()) { + goto exit; + } + } +skip_optional_kwonly: + return_value = pysqlite_connection_backup_impl(self, target, pages, progress, name, sleep); + +exit: + return return_value; +} + +#endif /* defined(HAVE_BACKUP_API) */ + +PyDoc_STRVAR(pysqlite_connection_create_collation__doc__, +"create_collation($self, name, callback, /)\n" +"--\n" +"\n" +"Creates a collation function. Non-standard."); + +#define PYSQLITE_CONNECTION_CREATE_COLLATION_METHODDEF \ + {"create_collation", (PyCFunction)(void(*)(void))pysqlite_connection_create_collation, METH_FASTCALL, pysqlite_connection_create_collation__doc__}, + +static PyObject * +pysqlite_connection_create_collation_impl(pysqlite_Connection *self, + PyObject *name, PyObject *callable); + +static PyObject * +pysqlite_connection_create_collation(pysqlite_Connection *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *name; + PyObject *callable; + + if (!_PyArg_CheckPositional("create_collation", nargs, 2, 2)) { + goto exit; + } + if (!PyUnicode_Check(args[0])) { + _PyArg_BadArgument("create_collation", "argument 1", "str", args[0]); + goto exit; + } + if (PyUnicode_READY(args[0]) == -1) { + goto exit; + } + name = args[0]; + callable = args[1]; + return_value = pysqlite_connection_create_collation_impl(self, name, callable); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_connection_enter__doc__, +"__enter__($self, /)\n" +"--\n" +"\n" +"Called when the connection is used as a context manager.\n" +"\n" +"Returns itself as a convenience to the caller."); + +#define PYSQLITE_CONNECTION_ENTER_METHODDEF \ + {"__enter__", (PyCFunction)pysqlite_connection_enter, METH_NOARGS, pysqlite_connection_enter__doc__}, + +static PyObject * +pysqlite_connection_enter_impl(pysqlite_Connection *self); + +static PyObject * +pysqlite_connection_enter(pysqlite_Connection *self, PyObject *Py_UNUSED(ignored)) +{ + return pysqlite_connection_enter_impl(self); +} + +PyDoc_STRVAR(pysqlite_connection_exit__doc__, +"__exit__($self, type, value, traceback, /)\n" +"--\n" +"\n" +"Called when the connection is used as a context manager.\n" +"\n" +"If there was any exception, a rollback takes place; otherwise we commit."); + +#define PYSQLITE_CONNECTION_EXIT_METHODDEF \ + {"__exit__", (PyCFunction)(void(*)(void))pysqlite_connection_exit, METH_FASTCALL, pysqlite_connection_exit__doc__}, + +static PyObject * +pysqlite_connection_exit_impl(pysqlite_Connection *self, PyObject *exc_type, + PyObject *exc_value, PyObject *exc_tb); + +static PyObject * +pysqlite_connection_exit(pysqlite_Connection *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *exc_type; + PyObject *exc_value; + PyObject *exc_tb; + + if (!_PyArg_CheckPositional("__exit__", nargs, 3, 3)) { + goto exit; + } + exc_type = args[0]; + exc_value = args[1]; + exc_tb = args[2]; + return_value = pysqlite_connection_exit_impl(self, exc_type, exc_value, exc_tb); + +exit: + return return_value; +} + +#ifndef PYSQLITE_CONNECTION_ENABLE_LOAD_EXTENSION_METHODDEF + #define PYSQLITE_CONNECTION_ENABLE_LOAD_EXTENSION_METHODDEF +#endif /* !defined(PYSQLITE_CONNECTION_ENABLE_LOAD_EXTENSION_METHODDEF) */ + +#ifndef PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF + #define PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF +#endif /* !defined(PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF) */ + +#ifndef PYSQLITE_CONNECTION_BACKUP_METHODDEF + #define PYSQLITE_CONNECTION_BACKUP_METHODDEF +#endif /* !defined(PYSQLITE_CONNECTION_BACKUP_METHODDEF) */ +/*[clinic end generated code: output=2f69688f7e0cf5b3 input=a9049054013a1b77]*/ diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index f765ba1df24669..30c8b5672a39fd 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -37,6 +37,13 @@ #define HAVE_TRACE_V2 #endif +#include "clinic/connection.c.h" +/*[clinic input] +module _sqlite3 +class _sqlite3.Connection "pysqlite_Connection *" "&pysqlite_ConnectionType" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=20047e60dfd58f65]*/ + _Py_IDENTIFIER(cursor); static const char * const begin_statements[] = { @@ -265,17 +272,20 @@ int pysqlite_connection_register_cursor(pysqlite_Connection* connection, PyObjec return 0; } -PyObject* pysqlite_connection_cursor(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) +/*[clinic input] +_sqlite3.Connection.cursor as pysqlite_connection_cursor + + factory: object = NULL + +Return a cursor for the connection. +[clinic start generated code]*/ + +static PyObject * +pysqlite_connection_cursor_impl(pysqlite_Connection *self, PyObject *factory) +/*[clinic end generated code: output=562432a9e6af2aa1 input=4127345aa091b650]*/ { - static char *kwlist[] = {"factory", NULL}; - PyObject* factory = NULL; PyObject* cursor; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, - &factory)) { - return NULL; - } - if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; } @@ -305,7 +315,15 @@ PyObject* pysqlite_connection_cursor(pysqlite_Connection* self, PyObject* args, return cursor; } -PyObject* pysqlite_connection_close(pysqlite_Connection* self, PyObject* args) +/*[clinic input] +_sqlite3.Connection.close as pysqlite_connection_close + +Closes the connection. +[clinic start generated code]*/ + +static PyObject * +pysqlite_connection_close_impl(pysqlite_Connection *self) +/*[clinic end generated code: output=a546a0da212c9b97 input=3d58064bbffaa3d3]*/ { int rc; @@ -385,7 +403,15 @@ PyObject* _pysqlite_connection_begin(pysqlite_Connection* self) } } -PyObject* pysqlite_connection_commit(pysqlite_Connection* self, PyObject* args) +/*[clinic input] +_sqlite3.Connection.commit as pysqlite_connection_commit + +Commit the current transaction. +[clinic start generated code]*/ + +static PyObject * +pysqlite_connection_commit_impl(pysqlite_Connection *self) +/*[clinic end generated code: output=3da45579e89407f2 input=39c12c04dda276a8]*/ { int rc; const char* tail; @@ -427,7 +453,15 @@ PyObject* pysqlite_connection_commit(pysqlite_Connection* self, PyObject* args) } } -PyObject* pysqlite_connection_rollback(pysqlite_Connection* self, PyObject* args) +/*[clinic input] +_sqlite3.Connection.rollback as pysqlite_connection_rollback + +Roll back the current transaction. +[clinic start generated code]*/ + +static PyObject * +pysqlite_connection_rollback_impl(pysqlite_Connection *self) +/*[clinic end generated code: output=b66fa0d43e7ef305 input=12d4e8d068942830]*/ { int rc; const char* tail; @@ -776,27 +810,31 @@ static void _destructor(void* args) Py_DECREF((PyObject*)args); } -PyObject* pysqlite_connection_create_function(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) -{ - static char *kwlist[] = {"name", "narg", "func", "deterministic", NULL}; +/*[clinic input] +_sqlite3.Connection.create_function as pysqlite_connection_create_function + + name: str + narg: int + func: object + * + deterministic: bool = False + +Creates a new function. Non-standard. +[clinic start generated code]*/ - PyObject* func; - char* name; - int narg; +static PyObject * +pysqlite_connection_create_function_impl(pysqlite_Connection *self, + const char *name, int narg, + PyObject *func, int deterministic) +/*[clinic end generated code: output=07d1877dd98c0308 input=f2edcf073e815beb]*/ +{ int rc; - int deterministic = 0; int flags = SQLITE_UTF8; if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; } - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "siO|$p", kwlist, - &name, &narg, &func, &deterministic)) - { - return NULL; - } - if (deterministic) { #if SQLITE_VERSION_NUMBER < 3008003 PyErr_SetString(pysqlite_NotSupportedError, @@ -830,23 +868,28 @@ PyObject* pysqlite_connection_create_function(pysqlite_Connection* self, PyObjec Py_RETURN_NONE; } -PyObject* pysqlite_connection_create_aggregate(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) -{ - PyObject* aggregate_class; +/*[clinic input] +_sqlite3.Connection.create_aggregate as pysqlite_connection_create_aggregate - int n_arg; - char* name; - static char *kwlist[] = { "name", "n_arg", "aggregate_class", NULL }; + name: str + n_arg: int + aggregate_class: object + +Creates a new aggregate. Non-standard. +[clinic start generated code]*/ + +static PyObject * +pysqlite_connection_create_aggregate_impl(pysqlite_Connection *self, + const char *name, int n_arg, + PyObject *aggregate_class) +/*[clinic end generated code: output=fbb2f858cfa4d8db input=c2e13bbf234500a5]*/ +{ int rc; if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; } - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "siO:create_aggregate", - kwlist, &name, &n_arg, &aggregate_class)) { - return NULL; - } Py_INCREF(aggregate_class); rc = sqlite3_create_function_v2(self->db, name, @@ -978,22 +1021,26 @@ static void _trace_callback(void* user_arg, const char* statement_string) #endif } -static PyObject* pysqlite_connection_set_authorizer(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) -{ - PyObject* authorizer_cb; +/*[clinic input] +_sqlite3.Connection.set_authorizer as pysqlite_connection_set_authorizer + + authorizer_callback as authorizer_cb: object + / + +Sets authorizer callback. Non-standard. +[clinic start generated code]*/ - static char *kwlist[] = { "authorizer_callback", NULL }; +static PyObject * +pysqlite_connection_set_authorizer(pysqlite_Connection *self, + PyObject *authorizer_cb) +/*[clinic end generated code: output=4f2f5f3f84d99092 input=1c43aa0c0939fec4]*/ +{ int rc; if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; } - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:set_authorizer", - kwlist, &authorizer_cb)) { - return NULL; - } - rc = sqlite3_set_authorizer(self->db, _authorizer_callback, (void*)authorizer_cb); if (rc != SQLITE_OK) { PyErr_SetString(pysqlite_OperationalError, "Error setting authorizer callback"); @@ -1006,19 +1053,22 @@ static PyObject* pysqlite_connection_set_authorizer(pysqlite_Connection* self, P Py_RETURN_NONE; } -static PyObject* pysqlite_connection_set_progress_handler(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) -{ - PyObject* progress_handler; - int n; +/*[clinic input] +_sqlite3.Connection.set_progress_handler as pysqlite_connection_set_progress_handler - static char *kwlist[] = { "progress_handler", "n", NULL }; + progress_handler: object + n: int - if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { - return NULL; - } +Sets progress handler callback. Non-standard. +[clinic start generated code]*/ - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi:set_progress_handler", - kwlist, &progress_handler, &n)) { +static PyObject * +pysqlite_connection_set_progress_handler_impl(pysqlite_Connection *self, + PyObject *progress_handler, + int n) +/*[clinic end generated code: output=35a7c10364cb1b04 input=857696c25f964c64]*/ +{ + if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; } @@ -1034,23 +1084,23 @@ static PyObject* pysqlite_connection_set_progress_handler(pysqlite_Connection* s Py_RETURN_NONE; } -/* - * Ref. - * - https://sqlite.org/c3ref/c_trace.html - * - https://sqlite.org/c3ref/trace_v2.html - */ -static PyObject* pysqlite_connection_set_trace_callback(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) -{ - PyObject* trace_callback; +/*[clinic input] +_sqlite3.Connection.set_trace_callback as pysqlite_connection_set_trace_callback - static char *kwlist[] = { "trace_callback", NULL }; + trace_callback: object + / - if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { - return NULL; - } +Sets a trace callback called for each SQL statement (passed as unicode). - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:set_trace_callback", - kwlist, &trace_callback)) { +Non-standard. +[clinic start generated code]*/ + +static PyObject * +pysqlite_connection_set_trace_callback(pysqlite_Connection *self, + PyObject *trace_callback) +/*[clinic end generated code: output=efd1bf439e81696c input=05a4a14360e0e034]*/ +{ + if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; } @@ -1076,19 +1126,26 @@ static PyObject* pysqlite_connection_set_trace_callback(pysqlite_Connection* sel } #ifndef SQLITE_OMIT_LOAD_EXTENSION -static PyObject* pysqlite_enable_load_extension(pysqlite_Connection* self, PyObject* args) +/*[clinic input] +_sqlite3.Connection.enable_load_extension as pysqlite_connection_enable_load_extension + + enable as onoff: int + / + +Enable dynamic loading of SQLite extension modules. Non-standard. +[clinic start generated code]*/ + +static PyObject * +pysqlite_connection_enable_load_extension_impl(pysqlite_Connection *self, + int onoff) +/*[clinic end generated code: output=9cac37190d388baf input=7df2986f1602d6bd]*/ { int rc; - int onoff; if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; } - if (!PyArg_ParseTuple(args, "i", &onoff)) { - return NULL; - } - rc = sqlite3_enable_load_extension(self->db, onoff); if (rc != SQLITE_OK) { @@ -1099,20 +1156,27 @@ static PyObject* pysqlite_enable_load_extension(pysqlite_Connection* self, PyObj } } -static PyObject* pysqlite_load_extension(pysqlite_Connection* self, PyObject* args) +/*[clinic input] +_sqlite3.Connection.load_extension as pysqlite_connection_load_extension + + name as extension_name: str + / + +Load SQLite extension module. Non-standard. +[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=0b711574560db9fc]*/ { int rc; - char* extension_name; char* errmsg; if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; } - if (!PyArg_ParseTuple(args, "s", &extension_name)) { - return NULL; - } - rc = sqlite3_load_extension(self->db, extension_name, 0, &errmsg); if (rc != 0) { PyErr_SetString(pysqlite_OperationalError, errmsg); @@ -1275,89 +1339,107 @@ PyObject* pysqlite_connection_call(pysqlite_Connection* self, PyObject* args, Py return NULL; } -PyObject* pysqlite_connection_execute(pysqlite_Connection* self, PyObject* args) +/*[clinic input] +_sqlite3.Connection.execute as pysqlite_connection_execute + + sql: unicode + / + parameters: object = NULL + +Executes a SQL statement. Non-standard. +[clinic start generated code]*/ + +static PyObject * +pysqlite_connection_execute_impl(pysqlite_Connection *self, PyObject *sql, + PyObject *parameters) +/*[clinic end generated code: output=5be05ae01ee17ee4 input=ec86c00fe1b371be]*/ { + _Py_IDENTIFIER(execute); PyObject* cursor = 0; PyObject* result = 0; - PyObject* method = 0; cursor = _PyObject_CallMethodIdNoArgs((PyObject*)self, &PyId_cursor); if (!cursor) { goto error; } - method = PyObject_GetAttrString(cursor, "execute"); - if (!method) { - Py_CLEAR(cursor); - goto error; - } - - result = PyObject_CallObject(method, args); + result = _PyObject_CallMethodIdObjArgs(cursor, &PyId_execute, sql, parameters, NULL); if (!result) { Py_CLEAR(cursor); } error: Py_XDECREF(result); - Py_XDECREF(method); return cursor; } -PyObject* pysqlite_connection_executemany(pysqlite_Connection* self, PyObject* args) +/*[clinic input] +_sqlite3.Connection.executemany as pysqlite_connection_executemany + + sql: unicode + parameters: object + / + +Repeatedly executes a SQL statement. Non-standard. +[clinic start generated code]*/ + +static PyObject * +pysqlite_connection_executemany_impl(pysqlite_Connection *self, + PyObject *sql, PyObject *parameters) +/*[clinic end generated code: output=776cd2fd20bfe71f input=4feab80659ffc82b]*/ { + _Py_IDENTIFIER(executemany); PyObject* cursor = 0; PyObject* result = 0; - PyObject* method = 0; cursor = _PyObject_CallMethodIdNoArgs((PyObject*)self, &PyId_cursor); if (!cursor) { goto error; } - method = PyObject_GetAttrString(cursor, "executemany"); - if (!method) { - Py_CLEAR(cursor); - goto error; - } - - result = PyObject_CallObject(method, args); + result = _PyObject_CallMethodIdObjArgs(cursor, &PyId_executemany, sql, + parameters, NULL); if (!result) { Py_CLEAR(cursor); } error: Py_XDECREF(result); - Py_XDECREF(method); return cursor; } -PyObject* pysqlite_connection_executescript(pysqlite_Connection* self, PyObject* args) +/*[clinic input] +_sqlite3.Connection.executescript as pysqlite_connection_executescript + + sql_script as script_obj: object + / + +[clinic start generated code]*/ + +static PyObject * +pysqlite_connection_executescript(pysqlite_Connection *self, + PyObject *script_obj) +/*[clinic end generated code: output=4c4f9d77aa0ae37d input=d577986d8f6bcaf4]*/ { + _Py_IDENTIFIER(executescript); PyObject* cursor = 0; PyObject* result = 0; - PyObject* method = 0; cursor = _PyObject_CallMethodIdNoArgs((PyObject*)self, &PyId_cursor); if (!cursor) { goto error; } - method = PyObject_GetAttrString(cursor, "executescript"); - if (!method) { - Py_CLEAR(cursor); - goto error; - } - - result = PyObject_CallObject(method, args); + result = _PyObject_CallMethodIdObjArgs(cursor, &PyId_executescript, + script_obj, NULL); if (!result) { Py_CLEAR(cursor); } error: Py_XDECREF(result); - Py_XDECREF(method); return cursor; } @@ -1417,8 +1499,15 @@ pysqlite_collation_callback( return result; } +/*[clinic input] +_sqlite3.Connection.interrupt as pysqlite_connection_interrupt + +Abort any pending database operation. Non-standard. +[clinic start generated code]*/ + static PyObject * -pysqlite_connection_interrupt(pysqlite_Connection* self, PyObject* args) +pysqlite_connection_interrupt_impl(pysqlite_Connection *self) +/*[clinic end generated code: output=f193204bc9e70b47 input=4bd0ad083cf93aa7]*/ { PyObject* retval = NULL; @@ -1439,8 +1528,17 @@ pysqlite_connection_interrupt(pysqlite_Connection* self, PyObject* args) * Class method of Connection to call the Python function _iterdump * of the sqlite3 module. */ +/*[clinic input] +_sqlite3.Connection.iterdump as pysqlite_connection_iterdump + +Returns iterator to the dump of the database in an SQL text format. + +Non-standard. +[clinic start generated code]*/ + static PyObject * -pysqlite_connection_iterdump(pysqlite_Connection* self, PyObject* args) +pysqlite_connection_iterdump_impl(pysqlite_Connection *self) +/*[clinic end generated code: output=586997aaf9808768 input=53bc907cb5eedb85]*/ { _Py_IDENTIFIER(_iterdump); PyObject* retval = NULL; @@ -1478,47 +1576,36 @@ pysqlite_connection_iterdump(pysqlite_Connection* self, PyObject* args) return retval; } +/*[clinic input] +_sqlite3.Connection.backup as pysqlite_connection_backup + + target: object(type='pysqlite_Connection *', subclass_of='&pysqlite_ConnectionType') = NULL + * + pages: int = -1 + progress: object = None + name: str = "main" + sleep: double = 0.250 + +[clinic start generated code]*/ + static PyObject * -pysqlite_connection_backup(pysqlite_Connection *self, PyObject *args, PyObject *kwds) +pysqlite_connection_backup_impl(pysqlite_Connection *self, + pysqlite_Connection *target, int pages, + PyObject *progress, const char *name, + double sleep) +/*[clinic end generated code: output=306a3e6a38c36334 input=bc8f97c01ea55042]*/ { - PyObject *target = NULL; - int pages = -1; - PyObject *progress = Py_None; - const char *name = "main"; int rc; int callback_error = 0; - PyObject *sleep_obj = NULL; - int sleep_ms = 250; + int sleep_ms = sleep * 1000.0; sqlite3 *bck_conn; sqlite3_backup *bck_handle; - static char *keywords[] = {"target", "pages", "progress", "name", "sleep", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|$iOsO:backup", keywords, - &pysqlite_ConnectionType, &target, - &pages, &progress, &name, &sleep_obj)) { - return NULL; - } - - if (sleep_obj != NULL) { - _PyTime_t sleep_secs; - if (_PyTime_FromSecondsObject(&sleep_secs, sleep_obj, - _PyTime_ROUND_TIMEOUT)) { - return NULL; - } - _PyTime_t ms = _PyTime_AsMilliseconds(sleep_secs, - _PyTime_ROUND_TIMEOUT); - if (ms < INT_MIN || ms > INT_MAX) { - PyErr_SetString(PyExc_OverflowError, "sleep is too large"); - return NULL; - } - sleep_ms = (int)ms; - } - if (!pysqlite_check_connection((pysqlite_Connection *)target)) { + if (!pysqlite_check_connection(target)) { return NULL; } - if ((pysqlite_Connection *)target == self) { + if (target == self) { PyErr_SetString(PyExc_ValueError, "target cannot be the same connection instance"); return NULL; } @@ -1526,7 +1613,7 @@ pysqlite_connection_backup(pysqlite_Connection *self, PyObject *args, PyObject * #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(((pysqlite_Connection *)target)->db)) { + if (!sqlite3_get_autocommit(target->db)) { PyErr_SetString(pysqlite_OperationalError, "target is in transaction"); return NULL; } @@ -1541,7 +1628,7 @@ pysqlite_connection_backup(pysqlite_Connection *self, PyObject *args, PyObject * pages = -1; } - bck_conn = ((pysqlite_Connection *)target)->db; + bck_conn = target->db; Py_BEGIN_ALLOW_THREADS bck_handle = sqlite3_backup_init(bck_conn, "main", self->db, name); @@ -1629,12 +1716,22 @@ pysqlite_connection_backup(pysqlite_Connection *self, PyObject *args, PyObject * } } +/*[clinic input] +_sqlite3.Connection.create_collation as pysqlite_connection_create_collation + + name: unicode + callback as callable: object + / + +Creates a collation function. Non-standard. +[clinic start generated code]*/ + static PyObject * -pysqlite_connection_create_collation(pysqlite_Connection* self, PyObject* args) +pysqlite_connection_create_collation_impl(pysqlite_Connection *self, + PyObject *name, PyObject *callable) +/*[clinic end generated code: output=0f63b8995565ae22 input=5c3898813a776cf2]*/ { - PyObject* callable; PyObject* uppercase_name = 0; - PyObject* name; PyObject* retval; Py_ssize_t i, len; _Py_IDENTIFIER(upper); @@ -1647,11 +1744,6 @@ pysqlite_connection_create_collation(pysqlite_Connection* self, PyObject* args) goto finally; } - if (!PyArg_ParseTuple(args, "UO:create_collation(name, callback)", - &name, &callable)) { - goto finally; - } - uppercase_name = _PyObject_CallMethodIdOneArg((PyObject *)&PyUnicode_Type, &PyId_upper, name); if (!uppercase_name) { @@ -1717,28 +1809,43 @@ pysqlite_connection_create_collation(pysqlite_Connection* self, PyObject* args) return retval; } -/* Called when the connection is used as a context manager. Returns itself as a - * convenience to the caller. */ +/*[clinic input] +_sqlite3.Connection.__enter__ as pysqlite_connection_enter + +Called when the connection is used as a context manager. + +Returns itself as a convenience to the caller. +[clinic start generated code]*/ + static PyObject * -pysqlite_connection_enter(pysqlite_Connection* self, PyObject* args) +pysqlite_connection_enter_impl(pysqlite_Connection *self) +/*[clinic end generated code: output=457b09726d3e9dcd input=127d7a4f17e86d8f]*/ { Py_INCREF(self); return (PyObject*)self; } -/** Called when the connection is used as a context manager. If there was any - * exception, a rollback takes place; otherwise we commit. */ +/*[clinic input] +_sqlite3.Connection.__exit__ as pysqlite_connection_exit + + type as exc_type: object + value as exc_value: object + traceback as exc_tb: object + / + +Called when the connection is used as a context manager. + +If there was any exception, a rollback takes place; otherwise we commit. +[clinic start generated code]*/ + static PyObject * -pysqlite_connection_exit(pysqlite_Connection* self, PyObject* args) +pysqlite_connection_exit_impl(pysqlite_Connection *self, PyObject *exc_type, + PyObject *exc_value, PyObject *exc_tb) +/*[clinic end generated code: output=0705200e9321202a input=bd66f1532c9c54a7]*/ { - PyObject* exc_type, *exc_value, *exc_tb; const char* method_name; PyObject* result; - if (!PyArg_ParseTuple(args, "OOO", &exc_type, &exc_value, &exc_tb)) { - return NULL; - } - if (exc_type == Py_None && exc_value == Py_None && exc_tb == Py_None) { method_name = "commit"; } else { @@ -1765,48 +1872,26 @@ static PyGetSetDef connection_getset[] = { }; static PyMethodDef connection_methods[] = { - {"cursor", (PyCFunction)(void(*)(void))pysqlite_connection_cursor, METH_VARARGS|METH_KEYWORDS, - PyDoc_STR("Return a cursor for the connection.")}, - {"close", (PyCFunction)pysqlite_connection_close, METH_NOARGS, - PyDoc_STR("Closes the connection.")}, - {"commit", (PyCFunction)pysqlite_connection_commit, METH_NOARGS, - PyDoc_STR("Commit the current transaction.")}, - {"rollback", (PyCFunction)pysqlite_connection_rollback, METH_NOARGS, - PyDoc_STR("Roll back the current transaction.")}, - {"create_function", (PyCFunction)(void(*)(void))pysqlite_connection_create_function, METH_VARARGS|METH_KEYWORDS, - PyDoc_STR("Creates a new function. Non-standard.")}, - {"create_aggregate", (PyCFunction)(void(*)(void))pysqlite_connection_create_aggregate, METH_VARARGS|METH_KEYWORDS, - PyDoc_STR("Creates a new aggregate. Non-standard.")}, - {"set_authorizer", (PyCFunction)(void(*)(void))pysqlite_connection_set_authorizer, METH_VARARGS|METH_KEYWORDS, - PyDoc_STR("Sets authorizer callback. Non-standard.")}, - #ifndef SQLITE_OMIT_LOAD_EXTENSION - {"enable_load_extension", (PyCFunction)pysqlite_enable_load_extension, METH_VARARGS, - PyDoc_STR("Enable dynamic loading of SQLite extension modules. Non-standard.")}, - {"load_extension", (PyCFunction)pysqlite_load_extension, METH_VARARGS, - PyDoc_STR("Load SQLite extension module. Non-standard.")}, - #endif - {"set_progress_handler", (PyCFunction)(void(*)(void))pysqlite_connection_set_progress_handler, METH_VARARGS|METH_KEYWORDS, - PyDoc_STR("Sets progress handler callback. Non-standard.")}, - {"set_trace_callback", (PyCFunction)(void(*)(void))pysqlite_connection_set_trace_callback, METH_VARARGS|METH_KEYWORDS, - PyDoc_STR("Sets a trace callback called for each SQL statement (passed as unicode). Non-standard.")}, - {"execute", (PyCFunction)pysqlite_connection_execute, METH_VARARGS, - PyDoc_STR("Executes a SQL statement. Non-standard.")}, - {"executemany", (PyCFunction)pysqlite_connection_executemany, METH_VARARGS, - PyDoc_STR("Repeatedly executes a SQL statement. Non-standard.")}, - {"executescript", (PyCFunction)pysqlite_connection_executescript, METH_VARARGS, - PyDoc_STR("Executes a multiple SQL statements at once. Non-standard.")}, - {"create_collation", (PyCFunction)pysqlite_connection_create_collation, METH_VARARGS, - PyDoc_STR("Creates a collation function. Non-standard.")}, - {"interrupt", (PyCFunction)pysqlite_connection_interrupt, METH_NOARGS, - PyDoc_STR("Abort any pending database operation. Non-standard.")}, - {"iterdump", (PyCFunction)pysqlite_connection_iterdump, METH_NOARGS, - PyDoc_STR("Returns iterator to the dump of the database in an SQL text format. Non-standard.")}, - {"backup", (PyCFunction)(void(*)(void))pysqlite_connection_backup, METH_VARARGS | METH_KEYWORDS, - PyDoc_STR("Makes a backup of the database. Non-standard.")}, - {"__enter__", (PyCFunction)pysqlite_connection_enter, METH_NOARGS, - PyDoc_STR("For context manager. Non-standard.")}, - {"__exit__", (PyCFunction)pysqlite_connection_exit, METH_VARARGS, - PyDoc_STR("For context manager. Non-standard.")}, + PYSQLITE_CONNECTION_BACKUP_METHODDEF + PYSQLITE_CONNECTION_CLOSE_METHODDEF + PYSQLITE_CONNECTION_COMMIT_METHODDEF + PYSQLITE_CONNECTION_CREATE_AGGREGATE_METHODDEF + PYSQLITE_CONNECTION_CREATE_COLLATION_METHODDEF + PYSQLITE_CONNECTION_CREATE_FUNCTION_METHODDEF + PYSQLITE_CONNECTION_CURSOR_METHODDEF + PYSQLITE_CONNECTION_ENABLE_LOAD_EXTENSION_METHODDEF + PYSQLITE_CONNECTION_ENTER_METHODDEF + PYSQLITE_CONNECTION_EXECUTEMANY_METHODDEF + PYSQLITE_CONNECTION_EXECUTESCRIPT_METHODDEF + PYSQLITE_CONNECTION_EXECUTE_METHODDEF + PYSQLITE_CONNECTION_EXIT_METHODDEF + PYSQLITE_CONNECTION_INTERRUPT_METHODDEF + PYSQLITE_CONNECTION_ITERDUMP_METHODDEF + PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF + PYSQLITE_CONNECTION_ROLLBACK_METHODDEF + PYSQLITE_CONNECTION_SET_AUTHORIZER_METHODDEF + PYSQLITE_CONNECTION_SET_PROGRESS_HANDLER_METHODDEF + PYSQLITE_CONNECTION_SET_TRACE_CALLBACK_METHODDEF {NULL, NULL} }; diff --git a/Modules/_sqlite/connection.h b/Modules/_sqlite/connection.h index 206085e00a00c7..8ea7d9cc3dee99 100644 --- a/Modules/_sqlite/connection.h +++ b/Modules/_sqlite/connection.h @@ -110,11 +110,7 @@ extern PyTypeObject pysqlite_ConnectionType; PyObject* pysqlite_connection_alloc(PyTypeObject* type, int aware); void pysqlite_connection_dealloc(pysqlite_Connection* self); -PyObject* pysqlite_connection_cursor(pysqlite_Connection* self, PyObject* args, PyObject* kwargs); -PyObject* pysqlite_connection_close(pysqlite_Connection* self, PyObject* args); PyObject* _pysqlite_connection_begin(pysqlite_Connection* self); -PyObject* pysqlite_connection_commit(pysqlite_Connection* self, PyObject* args); -PyObject* pysqlite_connection_rollback(pysqlite_Connection* self, PyObject* args); PyObject* pysqlite_connection_new(PyTypeObject* type, PyObject* args, PyObject* kw); int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject* kwargs); diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c index 5cfb4b97d61dfe..0376030edc154e 100644 --- a/Modules/_sqlite/cursor.c +++ b/Modules/_sqlite/cursor.c @@ -625,6 +625,7 @@ PyObject* pysqlite_cursor_executemany(pysqlite_Cursor* self, PyObject* args) static PyObject * pysqlite_cursor_executescript(pysqlite_Cursor* self, PyObject* args) { + _Py_IDENTIFIER(commit); PyObject* script_obj; const char* script_cstr; sqlite3_stmt* statement; @@ -652,7 +653,7 @@ pysqlite_cursor_executescript(pysqlite_Cursor* self, PyObject* args) } /* commit first */ - result = pysqlite_connection_commit(self->connection, NULL); + result = _PyObject_CallMethodIdNoArgs((PyObject *)self->connection, &PyId_commit); if (!result) { goto error; } From 6e1a726985319c212fee4ceb787510d8f29d095c Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sat, 13 Jun 2020 23:48:19 +0200 Subject: [PATCH 3/9] Convert Row --- Modules/_sqlite/clinic/row.c.h | 56 ++++++++++++++++++++++++++++++++++ Modules/_sqlite/row.c | 51 ++++++++++++++++++------------- 2 files changed, 86 insertions(+), 21 deletions(-) create mode 100644 Modules/_sqlite/clinic/row.c.h diff --git a/Modules/_sqlite/clinic/row.c.h b/Modules/_sqlite/clinic/row.c.h new file mode 100644 index 00000000000000..98e410219372e6 --- /dev/null +++ b/Modules/_sqlite/clinic/row.c.h @@ -0,0 +1,56 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +static PyObject * +pysqlite_row_new_impl(PyTypeObject *type, pysqlite_Cursor *cursor, + PyObject *data); + +static PyObject * +pysqlite_row_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + pysqlite_Cursor *cursor; + PyObject *data; + + if ((type == &pysqlite_RowType) && + !_PyArg_NoKeywords("Row", kwargs)) { + goto exit; + } + if (!_PyArg_CheckPositional("Row", PyTuple_GET_SIZE(args), 2, 2)) { + goto exit; + } + if (!PyObject_TypeCheck(PyTuple_GET_ITEM(args, 0), &pysqlite_CursorType)) { + _PyArg_BadArgument("Row", "argument 1", (&pysqlite_CursorType)->tp_name, PyTuple_GET_ITEM(args, 0)); + goto exit; + } + cursor = (pysqlite_Cursor *)PyTuple_GET_ITEM(args, 0); + if (!PyTuple_Check(PyTuple_GET_ITEM(args, 1))) { + _PyArg_BadArgument("Row", "argument 2", "tuple", PyTuple_GET_ITEM(args, 1)); + goto exit; + } + data = PyTuple_GET_ITEM(args, 1); + return_value = pysqlite_row_new_impl(type, cursor, data); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_row_keys__doc__, +"keys($self, /)\n" +"--\n" +"\n" +"Returns the keys of the row."); + +#define PYSQLITE_ROW_KEYS_METHODDEF \ + {"keys", (PyCFunction)pysqlite_row_keys, METH_NOARGS, pysqlite_row_keys__doc__}, + +static PyObject * +pysqlite_row_keys_impl(pysqlite_Row *self); + +static PyObject * +pysqlite_row_keys(pysqlite_Row *self, PyObject *Py_UNUSED(ignored)) +{ + return pysqlite_row_keys_impl(self); +} +/*[clinic end generated code: output=64c70362f4bfe669 input=a9049054013a1b77]*/ diff --git a/Modules/_sqlite/row.c b/Modules/_sqlite/row.c index 4b47108278a0ab..825ccba7205291 100644 --- a/Modules/_sqlite/row.c +++ b/Modules/_sqlite/row.c @@ -23,6 +23,13 @@ #include "row.h" #include "cursor.h" +#include "clinic/row.c.h" + +/*[clinic input] +module _sqlite3 +class _sqlite3.Row "pysqlite_Row *" "&pysqlite_RowType" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=5fe72209a8a6e40c]*/ void pysqlite_row_dealloc(pysqlite_Row* self) { @@ -32,30 +39,25 @@ void pysqlite_row_dealloc(pysqlite_Row* self) Py_TYPE(self)->tp_free((PyObject*)self); } +/*[clinic input] +@classmethod +_sqlite3.Row.__new__ as pysqlite_row_new + + cursor: object(type='pysqlite_Cursor *', subclass_of='&pysqlite_CursorType') + data: object(subclass_of='&PyTuple_Type') + / + +[clinic start generated code]*/ + static PyObject * -pysqlite_row_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) +pysqlite_row_new_impl(PyTypeObject *type, pysqlite_Cursor *cursor, + PyObject *data) +/*[clinic end generated code: output=10d58b09a819a4c1 input=3bb62e4657f18d81]*/ { pysqlite_Row *self; - PyObject* data; - pysqlite_Cursor* cursor; assert(type != NULL && type->tp_alloc != NULL); - if (!_PyArg_NoKeywords("Row", kwargs)) - return NULL; - if (!PyArg_ParseTuple(args, "OO", &cursor, &data)) - return NULL; - - if (!PyObject_TypeCheck((PyObject*)cursor, &pysqlite_CursorType)) { - PyErr_SetString(PyExc_TypeError, "instance of cursor required for first argument"); - return NULL; - } - - if (!PyTuple_Check(data)) { - PyErr_SetString(PyExc_TypeError, "tuple required for second argument"); - return NULL; - } - self = (pysqlite_Row *) type->tp_alloc(type, 0); if (self == NULL) return NULL; @@ -156,7 +158,15 @@ pysqlite_row_length(pysqlite_Row* self) return PyTuple_GET_SIZE(self->data); } -PyObject* pysqlite_row_keys(pysqlite_Row* self, PyObject *Py_UNUSED(ignored)) +/*[clinic input] +_sqlite3.Row.keys as pysqlite_row_keys + +Returns the keys of the row. +[clinic start generated code]*/ + +static PyObject * +pysqlite_row_keys_impl(pysqlite_Row *self) +/*[clinic end generated code: output=efe3dfb3af6edc07 input=7549a122827c5563]*/ { PyObject* list; Py_ssize_t nitems, i; @@ -221,8 +231,7 @@ static PySequenceMethods pysqlite_row_as_sequence = { static PyMethodDef pysqlite_row_methods[] = { - {"keys", (PyCFunction)pysqlite_row_keys, METH_NOARGS, - PyDoc_STR("Returns the keys of the row.")}, + PYSQLITE_ROW_KEYS_METHODDEF {NULL, NULL} }; From 311740ff18d780dc327c5a7264130fb07676e80c Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sun, 14 Jun 2020 00:07:04 +0200 Subject: [PATCH 4/9] Convert Cache --- Modules/_sqlite/cache.c | 55 +++++++++++++++++++++------- Modules/_sqlite/cache.h | 2 - Modules/_sqlite/clinic/cache.c.h | 63 ++++++++++++++++++++++++++++++++ Modules/_sqlite/cursor.c | 7 +++- 4 files changed, 109 insertions(+), 18 deletions(-) create mode 100644 Modules/_sqlite/clinic/cache.c.h diff --git a/Modules/_sqlite/cache.c b/Modules/_sqlite/cache.c index 758fc022f78108..4abfa270b2e72f 100644 --- a/Modules/_sqlite/cache.c +++ b/Modules/_sqlite/cache.c @@ -23,6 +23,13 @@ #include "cache.h" #include +#include "clinic/cache.c.h" + +/*[clinic input] +module _sqlite3 +class _sqlite3.Cache "pysqlite_Cache *" "&pysqlite_CacheType" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=94e9b64faa911d27]*/ /* only used internally */ pysqlite_Node* pysqlite_new_node(PyObject* key, PyObject* data) @@ -54,16 +61,19 @@ void pysqlite_node_dealloc(pysqlite_Node* self) Py_TYPE(self)->tp_free((PyObject*)self); } -int pysqlite_cache_init(pysqlite_Cache* self, PyObject* args, PyObject* kwargs) -{ - PyObject* factory; - int size = 10; +/*[clinic input] +_sqlite3.Cache.__init__ as pysqlite_cache_init - self->factory = NULL; + factory: object + size: int = 10 + / +[clinic start generated code]*/ - if (!PyArg_ParseTuple(args, "O|i", &factory, &size)) { - return -1; - } +static int +pysqlite_cache_init_impl(pysqlite_Cache *self, PyObject *factory, int size) +/*[clinic end generated code: output=3a3b3e0486364359 input=5c1df5f8291291b0]*/ +{ + self->factory = NULL; /* minimum cache size is 5 entries */ if (size < 5) { @@ -112,7 +122,18 @@ void pysqlite_cache_dealloc(pysqlite_Cache* self) Py_TYPE(self)->tp_free((PyObject*)self); } -PyObject* pysqlite_cache_get(pysqlite_Cache* self, PyObject* key) +/*[clinic input] +_sqlite3.Cache.get as pysqlite_cache_get + + key: object + / + +Gets an entry from the cache or calls the factory function to produce one. +[clinic start generated code]*/ + +static PyObject * +pysqlite_cache_get(pysqlite_Cache *self, PyObject *key) +/*[clinic end generated code: output=149ad799afafcdc8 input=07aef9c27e458441]*/ { pysqlite_Node* node; pysqlite_Node* ptr; @@ -217,7 +238,15 @@ PyObject* pysqlite_cache_get(pysqlite_Cache* self, PyObject* key) return node->data; } -PyObject* pysqlite_cache_display(pysqlite_Cache* self, PyObject* args) +/*[clinic input] +_sqlite3.Cache.display as pysqlite_cache_display + +For debugging only. +[clinic start generated code]*/ + +static PyObject * +pysqlite_cache_display_impl(pysqlite_Cache *self) +/*[clinic end generated code: output=4010f6d5a649271c input=916727d67499366c]*/ { pysqlite_Node* ptr; PyObject* prevkey; @@ -254,10 +283,8 @@ PyObject* pysqlite_cache_display(pysqlite_Cache* self, PyObject* args) } static PyMethodDef cache_methods[] = { - {"get", (PyCFunction)pysqlite_cache_get, METH_O, - PyDoc_STR("Gets an entry from the cache or calls the factory function to produce one.")}, - {"display", (PyCFunction)pysqlite_cache_display, METH_NOARGS, - PyDoc_STR("For debugging only.")}, + PYSQLITE_CACHE_GET_METHODDEF + PYSQLITE_CACHE_DISPLAY_METHODDEF {NULL, NULL} }; diff --git a/Modules/_sqlite/cache.h b/Modules/_sqlite/cache.h index 529010967c4f3a..9d988f9e95372b 100644 --- a/Modules/_sqlite/cache.h +++ b/Modules/_sqlite/cache.h @@ -65,9 +65,7 @@ extern PyTypeObject pysqlite_CacheType; int pysqlite_node_init(pysqlite_Node* self, PyObject* args, PyObject* kwargs); void pysqlite_node_dealloc(pysqlite_Node* self); -int pysqlite_cache_init(pysqlite_Cache* self, PyObject* args, PyObject* kwargs); void pysqlite_cache_dealloc(pysqlite_Cache* self); -PyObject* pysqlite_cache_get(pysqlite_Cache* self, PyObject* args); int pysqlite_cache_setup_types(void); diff --git a/Modules/_sqlite/clinic/cache.c.h b/Modules/_sqlite/clinic/cache.c.h new file mode 100644 index 00000000000000..c9706ad9714db3 --- /dev/null +++ b/Modules/_sqlite/clinic/cache.c.h @@ -0,0 +1,63 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +static int +pysqlite_cache_init_impl(pysqlite_Cache *self, PyObject *factory, int size); + +static int +pysqlite_cache_init(PyObject *self, PyObject *args, PyObject *kwargs) +{ + int return_value = -1; + PyObject *factory; + int size = 10; + + if (Py_IS_TYPE(self, &pysqlite_CacheType) && + !_PyArg_NoKeywords("Cache", kwargs)) { + goto exit; + } + if (!_PyArg_CheckPositional("Cache", PyTuple_GET_SIZE(args), 1, 2)) { + goto exit; + } + factory = PyTuple_GET_ITEM(args, 0); + if (PyTuple_GET_SIZE(args) < 2) { + goto skip_optional; + } + size = _PyLong_AsInt(PyTuple_GET_ITEM(args, 1)); + if (size == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional: + return_value = pysqlite_cache_init_impl((pysqlite_Cache *)self, factory, size); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_cache_get__doc__, +"get($self, key, /)\n" +"--\n" +"\n" +"Gets an entry from the cache or calls the factory function to produce one."); + +#define PYSQLITE_CACHE_GET_METHODDEF \ + {"get", (PyCFunction)pysqlite_cache_get, METH_O, pysqlite_cache_get__doc__}, + +PyDoc_STRVAR(pysqlite_cache_display__doc__, +"display($self, /)\n" +"--\n" +"\n" +"For debugging only."); + +#define PYSQLITE_CACHE_DISPLAY_METHODDEF \ + {"display", (PyCFunction)pysqlite_cache_display, METH_NOARGS, pysqlite_cache_display__doc__}, + +static PyObject * +pysqlite_cache_display_impl(pysqlite_Cache *self); + +static PyObject * +pysqlite_cache_display(pysqlite_Cache *self, PyObject *Py_UNUSED(ignored)) +{ + return pysqlite_cache_display_impl(self); +} +/*[clinic end generated code: output=60204e1295b95c6a input=a9049054013a1b77]*/ diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c index 0376030edc154e..5e97595fd1507a 100644 --- a/Modules/_sqlite/cursor.c +++ b/Modules/_sqlite/cursor.c @@ -368,6 +368,8 @@ static int check_cursor(pysqlite_Cursor* cur) static PyObject * _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* args) { + _Py_IDENTIFIER(get); + pysqlite_Statement *stmt; PyObject* operation; PyObject* parameters_list = NULL; PyObject* parameters_iter = NULL; @@ -462,8 +464,9 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* args) (void)pysqlite_statement_reset(self->statement); } - Py_XSETREF(self->statement, - (pysqlite_Statement *)pysqlite_cache_get(self->connection->statement_cache, func_args)); + stmt = (pysqlite_Statement *)_PyObject_CallMethodIdOneArg((PyObject *)self->connection->statement_cache, + &PyId_get, func_args); + Py_XSETREF(self->statement, stmt); Py_DECREF(func_args); if (!self->statement) { From d21accbb6ec89325f40f2a19e9ca4604c363469e Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sun, 14 Jun 2020 00:17:44 +0200 Subject: [PATCH 5/9] Convert PrepareProtocol --- Modules/_sqlite/clinic/prepare_protocol.c.h | 26 +++++++++++++++++++++ Modules/_sqlite/prepare_protocol.c | 15 +++++++++++- Modules/_sqlite/prepare_protocol.h | 1 - 3 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 Modules/_sqlite/clinic/prepare_protocol.c.h diff --git a/Modules/_sqlite/clinic/prepare_protocol.c.h b/Modules/_sqlite/clinic/prepare_protocol.c.h new file mode 100644 index 00000000000000..43897484f7899b --- /dev/null +++ b/Modules/_sqlite/clinic/prepare_protocol.c.h @@ -0,0 +1,26 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +static int +pysqlite_prepare_protocol_init_impl(pysqlite_PrepareProtocol *self); + +static int +pysqlite_prepare_protocol_init(PyObject *self, PyObject *args, PyObject *kwargs) +{ + int return_value = -1; + + if (Py_IS_TYPE(self, &pysqlite_PrepareProtocolType) && + !_PyArg_NoPositional("PrepareProtocol", args)) { + goto exit; + } + if (Py_IS_TYPE(self, &pysqlite_PrepareProtocolType) && + !_PyArg_NoKeywords("PrepareProtocol", kwargs)) { + goto exit; + } + return_value = pysqlite_prepare_protocol_init_impl((pysqlite_PrepareProtocol *)self); + +exit: + return return_value; +} +/*[clinic end generated code: output=97648812c954ace4 input=a9049054013a1b77]*/ diff --git a/Modules/_sqlite/prepare_protocol.c b/Modules/_sqlite/prepare_protocol.c index 05a2ca5a652f5e..04e01200a8308d 100644 --- a/Modules/_sqlite/prepare_protocol.c +++ b/Modules/_sqlite/prepare_protocol.c @@ -22,8 +22,21 @@ */ #include "prepare_protocol.h" +#include "clinic/prepare_protocol.c.h" -int pysqlite_prepare_protocol_init(pysqlite_PrepareProtocol* self, PyObject* args, PyObject* kwargs) +/*[clinic input] +module _sqlite3 +class _sqlite3.PrepareProtocol "pysqlite_PrepareProtocol *" "&pysqlite_PrepareProtocolType" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=4a79a14f268f3a66]*/ + +/*[clinic input] +_sqlite3.PrepareProtocol.__init__ as pysqlite_prepare_protocol_init +[clinic start generated code]*/ + +static int +pysqlite_prepare_protocol_init_impl(pysqlite_PrepareProtocol *self) +/*[clinic end generated code: output=3b31d0c14febd335 input=39127fc4f4923519]*/ { return 0; } diff --git a/Modules/_sqlite/prepare_protocol.h b/Modules/_sqlite/prepare_protocol.h index 3998a55e51cafe..7aecd263c25a1d 100644 --- a/Modules/_sqlite/prepare_protocol.h +++ b/Modules/_sqlite/prepare_protocol.h @@ -33,7 +33,6 @@ typedef struct extern PyTypeObject pysqlite_PrepareProtocolType; -int pysqlite_prepare_protocol_init(pysqlite_PrepareProtocol* self, PyObject* args, PyObject* kwargs); void pysqlite_prepare_protocol_dealloc(pysqlite_PrepareProtocol* self); int pysqlite_prepare_protocol_setup_types(void); From d5baf4576e6e52527e1ee92ab58bd1a7ae3536f9 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sun, 14 Jun 2020 00:50:07 +0200 Subject: [PATCH 6/9] Convert Cursor --- Modules/_sqlite/clinic/cursor.c.h | 289 ++++++++++++++++++++++++++++++ Modules/_sqlite/cursor.c | 196 +++++++++++++------- Modules/_sqlite/cursor.h | 7 - 3 files changed, 424 insertions(+), 68 deletions(-) create mode 100644 Modules/_sqlite/clinic/cursor.c.h diff --git a/Modules/_sqlite/clinic/cursor.c.h b/Modules/_sqlite/clinic/cursor.c.h new file mode 100644 index 00000000000000..46644a588d8222 --- /dev/null +++ b/Modules/_sqlite/clinic/cursor.c.h @@ -0,0 +1,289 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +static int +pysqlite_cursor_init_impl(pysqlite_Cursor *self, + pysqlite_Connection *connection); + +static int +pysqlite_cursor_init(PyObject *self, PyObject *args, PyObject *kwargs) +{ + int return_value = -1; + static const char * const _keywords[] = {"connection", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "Cursor", 0}; + PyObject *argsbuf[1]; + PyObject * const *fastargs; + Py_ssize_t nargs = PyTuple_GET_SIZE(args); + pysqlite_Connection *connection; + + fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 1, 1, 0, argsbuf); + if (!fastargs) { + goto exit; + } + if (!PyObject_TypeCheck(fastargs[0], &pysqlite_ConnectionType)) { + _PyArg_BadArgument("Cursor", "argument 'connection'", (&pysqlite_ConnectionType)->tp_name, fastargs[0]); + goto exit; + } + connection = (pysqlite_Connection *)fastargs[0]; + return_value = pysqlite_cursor_init_impl((pysqlite_Cursor *)self, connection); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_cursor_execute__doc__, +"execute($self, sql, /, parameters=)\n" +"--\n" +"\n" +"Executes a SQL statement."); + +#define PYSQLITE_CURSOR_EXECUTE_METHODDEF \ + {"execute", (PyCFunction)(void(*)(void))pysqlite_cursor_execute, METH_FASTCALL|METH_KEYWORDS, pysqlite_cursor_execute__doc__}, + +static PyObject * +pysqlite_cursor_execute_impl(pysqlite_Cursor *self, PyObject *sql, + PyObject *parameters); + +static PyObject * +pysqlite_cursor_execute(pysqlite_Cursor *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"", "parameters", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "execute", 0}; + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + PyObject *sql; + PyObject *parameters = NULL; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!PyUnicode_Check(args[0])) { + _PyArg_BadArgument("execute", "argument 1", "str", args[0]); + goto exit; + } + if (PyUnicode_READY(args[0]) == -1) { + goto exit; + } + sql = args[0]; + if (!noptargs) { + goto skip_optional_pos; + } + parameters = args[1]; +skip_optional_pos: + return_value = pysqlite_cursor_execute_impl(self, sql, parameters); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_cursor_executemany__doc__, +"executemany($self, sql, parameters, /)\n" +"--\n" +"\n" +"Repeatedly executes a SQL statement."); + +#define PYSQLITE_CURSOR_EXECUTEMANY_METHODDEF \ + {"executemany", (PyCFunction)(void(*)(void))pysqlite_cursor_executemany, METH_FASTCALL, pysqlite_cursor_executemany__doc__}, + +static PyObject * +pysqlite_cursor_executemany_impl(pysqlite_Cursor *self, PyObject *sql, + PyObject *parameters); + +static PyObject * +pysqlite_cursor_executemany(pysqlite_Cursor *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *sql; + PyObject *parameters; + + if (!_PyArg_CheckPositional("executemany", nargs, 2, 2)) { + goto exit; + } + if (!PyUnicode_Check(args[0])) { + _PyArg_BadArgument("executemany", "argument 1", "str", args[0]); + goto exit; + } + if (PyUnicode_READY(args[0]) == -1) { + goto exit; + } + sql = args[0]; + parameters = args[1]; + return_value = pysqlite_cursor_executemany_impl(self, sql, parameters); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_cursor_executescript__doc__, +"executescript($self, sql_script, /)\n" +"--\n" +"\n" +"Executes a multiple SQL statements at once. Non-standard."); + +#define PYSQLITE_CURSOR_EXECUTESCRIPT_METHODDEF \ + {"executescript", (PyCFunction)pysqlite_cursor_executescript, METH_O, pysqlite_cursor_executescript__doc__}, + +PyDoc_STRVAR(pysqlite_cursor_fetchone__doc__, +"fetchone($self, /)\n" +"--\n" +"\n" +"Fetches one row from the resultset."); + +#define PYSQLITE_CURSOR_FETCHONE_METHODDEF \ + {"fetchone", (PyCFunction)pysqlite_cursor_fetchone, METH_NOARGS, pysqlite_cursor_fetchone__doc__}, + +static PyObject * +pysqlite_cursor_fetchone_impl(pysqlite_Cursor *self); + +static PyObject * +pysqlite_cursor_fetchone(pysqlite_Cursor *self, PyObject *Py_UNUSED(ignored)) +{ + return pysqlite_cursor_fetchone_impl(self); +} + +PyDoc_STRVAR(pysqlite_cursor_fetchmany__doc__, +"fetchmany($self, /, size=cursor.arraysize)\n" +"--\n" +"\n" +"Fetches several rows from the resultset."); + +#define PYSQLITE_CURSOR_FETCHMANY_METHODDEF \ + {"fetchmany", (PyCFunction)(void(*)(void))pysqlite_cursor_fetchmany, METH_FASTCALL|METH_KEYWORDS, pysqlite_cursor_fetchmany__doc__}, + +static PyObject * +pysqlite_cursor_fetchmany_impl(pysqlite_Cursor *self, int maxrows); + +static PyObject * +pysqlite_cursor_fetchmany(pysqlite_Cursor *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"size", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "fetchmany", 0}; + PyObject *argsbuf[1]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + int maxrows = self->arraysize; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + maxrows = _PyLong_AsInt(args[0]); + if (maxrows == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional_pos: + return_value = pysqlite_cursor_fetchmany_impl(self, maxrows); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_cursor_fetchall__doc__, +"fetchall($self, /)\n" +"--\n" +"\n" +"Fetches all rows from the resultset."); + +#define PYSQLITE_CURSOR_FETCHALL_METHODDEF \ + {"fetchall", (PyCFunction)pysqlite_cursor_fetchall, METH_NOARGS, pysqlite_cursor_fetchall__doc__}, + +static PyObject * +pysqlite_cursor_fetchall_impl(pysqlite_Cursor *self); + +static PyObject * +pysqlite_cursor_fetchall(pysqlite_Cursor *self, PyObject *Py_UNUSED(ignored)) +{ + return pysqlite_cursor_fetchall_impl(self); +} + +PyDoc_STRVAR(pysqlite_cursor_setinputsizes__doc__, +"setinputsizes($self, sizes=None, /)\n" +"--\n" +"\n" +"Required by DB-API. Does nothing in pysqlite."); + +#define PYSQLITE_CURSOR_SETINPUTSIZES_METHODDEF \ + {"setinputsizes", (PyCFunction)(void(*)(void))pysqlite_cursor_setinputsizes, METH_FASTCALL, pysqlite_cursor_setinputsizes__doc__}, + +static PyObject * +pysqlite_cursor_setinputsizes_impl(pysqlite_Cursor *self, PyObject *sizes); + +static PyObject * +pysqlite_cursor_setinputsizes(pysqlite_Cursor *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *sizes = Py_None; + + if (!_PyArg_CheckPositional("setinputsizes", nargs, 0, 1)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + sizes = args[0]; +skip_optional: + return_value = pysqlite_cursor_setinputsizes_impl(self, sizes); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_cursor_setoutputsize__doc__, +"setoutputsize($self, size, column=None, /)\n" +"--\n" +"\n" +"Required by DB-API. Does nothing in pysqlite."); + +#define PYSQLITE_CURSOR_SETOUTPUTSIZE_METHODDEF \ + {"setoutputsize", (PyCFunction)(void(*)(void))pysqlite_cursor_setoutputsize, METH_FASTCALL, pysqlite_cursor_setoutputsize__doc__}, + +static PyObject * +pysqlite_cursor_setoutputsize_impl(pysqlite_Cursor *self, PyObject *size, + PyObject *column); + +static PyObject * +pysqlite_cursor_setoutputsize(pysqlite_Cursor *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *size; + PyObject *column = Py_None; + + if (!_PyArg_CheckPositional("setoutputsize", nargs, 1, 2)) { + goto exit; + } + size = args[0]; + if (nargs < 2) { + goto skip_optional; + } + column = args[1]; +skip_optional: + return_value = pysqlite_cursor_setoutputsize_impl(self, size, column); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_cursor_close__doc__, +"close($self, /)\n" +"--\n" +"\n" +"Closes the cursor."); + +#define PYSQLITE_CURSOR_CLOSE_METHODDEF \ + {"close", (PyCFunction)pysqlite_cursor_close, METH_NOARGS, pysqlite_cursor_close__doc__}, + +static PyObject * +pysqlite_cursor_close_impl(pysqlite_Cursor *self); + +static PyObject * +pysqlite_cursor_close(pysqlite_Cursor *self, PyObject *Py_UNUSED(ignored)) +{ + return pysqlite_cursor_close_impl(self); +} +/*[clinic end generated code: output=f07a9c61f46667e7 input=a9049054013a1b77]*/ diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c index 5e97595fd1507a..72d10be1528dbc 100644 --- a/Modules/_sqlite/cursor.c +++ b/Modules/_sqlite/cursor.c @@ -24,20 +24,29 @@ #include "cursor.h" #include "module.h" #include "util.h" +#include "clinic/cursor.c.h" + +/*[clinic input] +module _sqlite3 +class _sqlite3.Cursor "pysqlite_Cursor *" "&pysqlite_CursorType" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=614fc7b8f2be9384]*/ PyObject* pysqlite_cursor_iternext(pysqlite_Cursor* self); static const char errmsg_fetch_across_rollback[] = "Cursor needed to be reset because of commit/rollback and can no longer be fetched from."; -static int pysqlite_cursor_init(pysqlite_Cursor* self, PyObject* args, PyObject* kwargs) -{ - pysqlite_Connection* connection; +/*[clinic input] +_sqlite3.Cursor.__init__ as pysqlite_cursor_init - if (!PyArg_ParseTuple(args, "O!", &pysqlite_ConnectionType, &connection)) - { - return -1; - } + connection: object(type='pysqlite_Connection *', subclass_of='&pysqlite_ConnectionType') +[clinic start generated code]*/ +static int +pysqlite_cursor_init_impl(pysqlite_Cursor *self, + pysqlite_Connection *connection) +/*[clinic end generated code: output=ac59dce49a809ca8 input=f0026054692c59fb]*/ +{ Py_INCREF(connection); Py_XSETREF(self->connection, connection); Py_CLEAR(self->statement); @@ -366,11 +375,10 @@ static int check_cursor(pysqlite_Cursor* cur) } static PyObject * -_pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* args) +_pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation, PyObject* second_argument) { _Py_IDENTIFIER(get); pysqlite_Statement *stmt; - PyObject* operation; PyObject* parameters_list = NULL; PyObject* parameters_iter = NULL; PyObject* parameters = NULL; @@ -381,7 +389,6 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* args) int numcols; PyObject* descriptor; PyObject* column_name; - PyObject* second_argument = NULL; sqlite_int64 lastrowid; if (!check_cursor(self)) { @@ -394,11 +401,6 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* args) Py_CLEAR(self->next_row); if (multiple) { - /* executemany() */ - if (!PyArg_ParseTuple(args, "UO", &operation, &second_argument)) { - goto error; - } - if (PyIter_Check(second_argument)) { /* iterator */ Py_INCREF(second_argument); @@ -411,11 +413,6 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* args) } } } else { - /* execute() */ - if (!PyArg_ParseTuple(args, "U|O", &operation, &second_argument)) { - goto error; - } - parameters_list = PyList_New(0); if (!parameters_list) { goto error; @@ -615,30 +612,61 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* args) } } -PyObject* pysqlite_cursor_execute(pysqlite_Cursor* self, PyObject* args) +/*[clinic input] +_sqlite3.Cursor.execute as pysqlite_cursor_execute + + sql: unicode + / + parameters: object = NULL + +Executes a SQL statement. +[clinic start generated code]*/ + +static PyObject * +pysqlite_cursor_execute_impl(pysqlite_Cursor *self, PyObject *sql, + PyObject *parameters) +/*[clinic end generated code: output=d81b4655c7c0bbad input=6ecc5b737d9e8219]*/ { - return _pysqlite_query_execute(self, 0, args); + return _pysqlite_query_execute(self, 0, sql, parameters); } -PyObject* pysqlite_cursor_executemany(pysqlite_Cursor* self, PyObject* args) +/*[clinic input] +_sqlite3.Cursor.executemany as pysqlite_cursor_executemany + + sql: unicode + parameters: object + / + +Repeatedly executes a SQL statement. +[clinic start generated code]*/ + +static PyObject * +pysqlite_cursor_executemany_impl(pysqlite_Cursor *self, PyObject *sql, + PyObject *parameters) +/*[clinic end generated code: output=df8e2d0b7300aab6 input=a4140497fda2bf4c]*/ { - return _pysqlite_query_execute(self, 1, args); + return _pysqlite_query_execute(self, 1, sql, parameters); } +/*[clinic input] +_sqlite3.Cursor.executescript as pysqlite_cursor_executescript + + sql_script as script_obj: object + / + +Executes a multiple SQL statements at once. Non-standard. +[clinic start generated code]*/ + static PyObject * -pysqlite_cursor_executescript(pysqlite_Cursor* self, PyObject* args) +pysqlite_cursor_executescript(pysqlite_Cursor *self, PyObject *script_obj) +/*[clinic end generated code: output=115a8132b0f200fe input=38c6fa6de570bb9b]*/ { _Py_IDENTIFIER(commit); - PyObject* script_obj; const char* script_cstr; sqlite3_stmt* statement; int rc; PyObject* result; - if (!PyArg_ParseTuple(args, "O", &script_obj)) { - return NULL; - } - if (!check_cursor(self)) { return NULL; } @@ -775,7 +803,15 @@ PyObject* pysqlite_cursor_iternext(pysqlite_Cursor *self) return next_row; } -PyObject* pysqlite_cursor_fetchone(pysqlite_Cursor* self, PyObject* args) +/*[clinic input] +_sqlite3.Cursor.fetchone as pysqlite_cursor_fetchone + +Fetches one row from the resultset. +[clinic start generated code]*/ + +static PyObject * +pysqlite_cursor_fetchone_impl(pysqlite_Cursor *self) +/*[clinic end generated code: output=4bd2eabf5baaddb0 input=e78294ec5980fdba]*/ { PyObject* row; @@ -787,19 +823,22 @@ PyObject* pysqlite_cursor_fetchone(pysqlite_Cursor* self, PyObject* args) return row; } -PyObject* pysqlite_cursor_fetchmany(pysqlite_Cursor* self, PyObject* args, PyObject* kwargs) -{ - static char *kwlist[] = {"size", NULL}; +/*[clinic input] +_sqlite3.Cursor.fetchmany as pysqlite_cursor_fetchmany + + size as maxrows: int(c_default='self->arraysize') = cursor.arraysize + +Fetches several rows from the resultset. +[clinic start generated code]*/ +static PyObject * +pysqlite_cursor_fetchmany_impl(pysqlite_Cursor *self, int maxrows) +/*[clinic end generated code: output=a8ef31fea64d0906 input=d80ff999a7701ffb]*/ +{ PyObject* row; PyObject* list; - int maxrows = self->arraysize; int counter = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:fetchmany", kwlist, &maxrows)) { - return NULL; - } - list = PyList_New(0); if (!list) { return NULL; @@ -822,7 +861,15 @@ PyObject* pysqlite_cursor_fetchmany(pysqlite_Cursor* self, PyObject* args, PyObj } } -PyObject* pysqlite_cursor_fetchall(pysqlite_Cursor* self, PyObject* args) +/*[clinic input] +_sqlite3.Cursor.fetchall as pysqlite_cursor_fetchall + +Fetches all rows from the resultset. +[clinic start generated code]*/ + +static PyObject * +pysqlite_cursor_fetchall_impl(pysqlite_Cursor *self) +/*[clinic end generated code: output=d5da12aca2da4b27 input=f5d401086a8df25a]*/ { PyObject* row; PyObject* list; @@ -845,13 +892,49 @@ PyObject* pysqlite_cursor_fetchall(pysqlite_Cursor* self, PyObject* args) } } -PyObject* pysqlite_noop(pysqlite_Connection* self, PyObject* args) +/*[clinic input] +_sqlite3.Cursor.setinputsizes as pysqlite_cursor_setinputsizes + + sizes: object = None + / + +Required by DB-API. Does nothing in pysqlite. +[clinic start generated code]*/ + +static PyObject * +pysqlite_cursor_setinputsizes_impl(pysqlite_Cursor *self, PyObject *sizes) +/*[clinic end generated code: output=a06c12790bd05f2e input=d058d07e828431de]*/ { - /* don't care, return None */ Py_RETURN_NONE; } -PyObject* pysqlite_cursor_close(pysqlite_Cursor* self, PyObject* args) +/*[clinic input] +_sqlite3.Cursor.setoutputsize as pysqlite_cursor_setoutputsize + + size: object + column: object = None + / + +Required by DB-API. Does nothing in pysqlite. +[clinic start generated code]*/ + +static PyObject * +pysqlite_cursor_setoutputsize_impl(pysqlite_Cursor *self, PyObject *size, + PyObject *column) +/*[clinic end generated code: output=018d7e9129d45efe input=077b017da58b9389]*/ +{ + Py_RETURN_NONE; +} + +/*[clinic input] +_sqlite3.Cursor.close as pysqlite_cursor_close + +Closes the cursor. +[clinic start generated code]*/ + +static PyObject * +pysqlite_cursor_close_impl(pysqlite_Cursor *self) +/*[clinic end generated code: output=b6055e4ec6fe63b6 input=08b36552dbb9a986]*/ { if (!self->connection) { PyErr_SetString(pysqlite_ProgrammingError, @@ -873,24 +956,15 @@ PyObject* pysqlite_cursor_close(pysqlite_Cursor* self, PyObject* args) } static PyMethodDef cursor_methods[] = { - {"execute", (PyCFunction)pysqlite_cursor_execute, METH_VARARGS, - PyDoc_STR("Executes a SQL statement.")}, - {"executemany", (PyCFunction)pysqlite_cursor_executemany, METH_VARARGS, - PyDoc_STR("Repeatedly executes a SQL statement.")}, - {"executescript", (PyCFunction)pysqlite_cursor_executescript, METH_VARARGS, - PyDoc_STR("Executes a multiple SQL statements at once. Non-standard.")}, - {"fetchone", (PyCFunction)pysqlite_cursor_fetchone, METH_NOARGS, - PyDoc_STR("Fetches one row from the resultset.")}, - {"fetchmany", (PyCFunction)(void(*)(void))pysqlite_cursor_fetchmany, METH_VARARGS|METH_KEYWORDS, - PyDoc_STR("Fetches several rows from the resultset.")}, - {"fetchall", (PyCFunction)pysqlite_cursor_fetchall, METH_NOARGS, - PyDoc_STR("Fetches all rows from the resultset.")}, - {"close", (PyCFunction)pysqlite_cursor_close, METH_NOARGS, - PyDoc_STR("Closes the cursor.")}, - {"setinputsizes", (PyCFunction)pysqlite_noop, METH_VARARGS, - PyDoc_STR("Required by DB-API. Does nothing in pysqlite.")}, - {"setoutputsize", (PyCFunction)pysqlite_noop, METH_VARARGS, - PyDoc_STR("Required by DB-API. Does nothing in pysqlite.")}, + PYSQLITE_CURSOR_CLOSE_METHODDEF + PYSQLITE_CURSOR_EXECUTEMANY_METHODDEF + PYSQLITE_CURSOR_EXECUTESCRIPT_METHODDEF + PYSQLITE_CURSOR_EXECUTE_METHODDEF + PYSQLITE_CURSOR_FETCHALL_METHODDEF + PYSQLITE_CURSOR_FETCHMANY_METHODDEF + PYSQLITE_CURSOR_FETCHONE_METHODDEF + PYSQLITE_CURSOR_SETINPUTSIZES_METHODDEF + PYSQLITE_CURSOR_SETOUTPUTSIZE_METHODDEF {NULL, NULL} }; diff --git a/Modules/_sqlite/cursor.h b/Modules/_sqlite/cursor.h index 4a20e756f7829d..7f04ecde2edb06 100644 --- a/Modules/_sqlite/cursor.h +++ b/Modules/_sqlite/cursor.h @@ -54,15 +54,8 @@ typedef struct extern PyTypeObject pysqlite_CursorType; -PyObject* pysqlite_cursor_execute(pysqlite_Cursor* self, PyObject* args); -PyObject* pysqlite_cursor_executemany(pysqlite_Cursor* self, PyObject* args); PyObject* pysqlite_cursor_getiter(pysqlite_Cursor *self); PyObject* pysqlite_cursor_iternext(pysqlite_Cursor *self); -PyObject* pysqlite_cursor_fetchone(pysqlite_Cursor* self, PyObject* args); -PyObject* pysqlite_cursor_fetchmany(pysqlite_Cursor* self, PyObject* args, PyObject* kwargs); -PyObject* pysqlite_cursor_fetchall(pysqlite_Cursor* self, PyObject* args); -PyObject* pysqlite_noop(pysqlite_Connection* self, PyObject* args); -PyObject* pysqlite_cursor_close(pysqlite_Cursor* self, PyObject* args); int pysqlite_cursor_setup_types(void); From 144d84ad63b286bb56396beadc9fe528f20eec88 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sun, 14 Jun 2020 21:09:30 +0200 Subject: [PATCH 7/9] Convert sqlite3.connect() and Connection.__init__() --- Modules/_sqlite/clinic/connection.c.h | 103 ++++++++++++++++++++++- Modules/_sqlite/clinic/module.c.h | 114 +++++++++++++++++++++++++- Modules/_sqlite/connection.c | 43 +++++----- Modules/_sqlite/connection.h | 1 - Modules/_sqlite/module.c | 104 ++++++++++++++--------- 5 files changed, 299 insertions(+), 66 deletions(-) diff --git a/Modules/_sqlite/clinic/connection.c.h b/Modules/_sqlite/clinic/connection.c.h index ddae4a5b108817..1cb7d0739632dc 100644 --- a/Modules/_sqlite/clinic/connection.c.h +++ b/Modules/_sqlite/clinic/connection.c.h @@ -2,6 +2,107 @@ preserve [clinic start generated code]*/ +static int +pysqlite_connection_init_impl(pysqlite_Connection *self, + PyObject *database_obj, double timeout, + int detect_types, PyObject *isolation_level, + int check_same_thread, PyObject *factory, + int cached_statements, int uri); + +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]; + PyObject * const *fastargs; + Py_ssize_t nargs = PyTuple_GET_SIZE(args); + Py_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 1; + PyObject *database_obj; + double timeout = 5.0; + int detect_types = 0; + PyObject *isolation_level = NULL; + int check_same_thread = 1; + PyObject *factory = (PyObject*)&pysqlite_ConnectionType; + int cached_statements = 100; + int uri = 0; + + fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 1, 8, 0, argsbuf); + if (!fastargs) { + goto exit; + } + if (!PyUnicode_FSConverter(fastargs[0], &database_obj)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (fastargs[1]) { + if (PyFloat_CheckExact(fastargs[1])) { + timeout = PyFloat_AS_DOUBLE(fastargs[1]); + } + else + { + timeout = PyFloat_AsDouble(fastargs[1]); + if (timeout == -1.0 && PyErr_Occurred()) { + goto exit; + } + } + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (fastargs[2]) { + detect_types = _PyLong_AsInt(fastargs[2]); + if (detect_types == -1 && PyErr_Occurred()) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (fastargs[3]) { + isolation_level = fastargs[3]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (fastargs[4]) { + check_same_thread = _PyLong_AsInt(fastargs[4]); + if (check_same_thread == -1 && PyErr_Occurred()) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (fastargs[5]) { + factory = fastargs[5]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (fastargs[6]) { + cached_statements = _PyLong_AsInt(fastargs[6]); + if (cached_statements == -1 && PyErr_Occurred()) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } + uri = PyObject_IsTrue(fastargs[7]); + if (uri < 0) { + goto exit; + } +skip_optional_pos: + return_value = pysqlite_connection_init_impl((pysqlite_Connection *)self, database_obj, timeout, detect_types, isolation_level, check_same_thread, factory, cached_statements, uri); + +exit: + return return_value; +} + PyDoc_STRVAR(pysqlite_connection_cursor__doc__, "cursor($self, /, factory=)\n" "--\n" @@ -682,4 +783,4 @@ pysqlite_connection_exit(pysqlite_Connection *self, PyObject *const *args, Py_ss #ifndef PYSQLITE_CONNECTION_BACKUP_METHODDEF #define PYSQLITE_CONNECTION_BACKUP_METHODDEF #endif /* !defined(PYSQLITE_CONNECTION_BACKUP_METHODDEF) */ -/*[clinic end generated code: output=2f69688f7e0cf5b3 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=d1fb1f48710a3cd4 input=a9049054013a1b77]*/ diff --git a/Modules/_sqlite/clinic/module.c.h b/Modules/_sqlite/clinic/module.c.h index af9d39edb5168f..a4f5639e1e0237 100644 --- a/Modules/_sqlite/clinic/module.c.h +++ b/Modules/_sqlite/clinic/module.c.h @@ -2,6 +2,118 @@ preserve [clinic start generated code]*/ +PyDoc_STRVAR(pysqlite_connect__doc__, +"connect($module, /, database, timeout=5.0, detect_types=0,\n" +" isolation_level=, check_same_thread=1,\n" +" factory=ConnectionType, cached_statements=100, uri=False)\n" +"--\n" +"\n" +"Opens a connection to the SQLite database file database.\n" +"\n" +"You can use \":memory:\" to open a database connection to a database that resides\n" +"in RAM instead of on disk."); + +#define PYSQLITE_CONNECT_METHODDEF \ + {"connect", (PyCFunction)(void(*)(void))pysqlite_connect, METH_FASTCALL|METH_KEYWORDS, pysqlite_connect__doc__}, + +static PyObject * +pysqlite_connect_impl(PyObject *module, PyObject *database, double timeout, + int detect_types, PyObject *isolation_level, + int check_same_thread, PyObject *factory, + int cached_statements, int uri); + +static PyObject * +pysqlite_connect(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + 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, "connect", 0}; + PyObject *argsbuf[8]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + PyObject *database; + double timeout = 5.0; + int detect_types = 0; + PyObject *isolation_level = NULL; + int check_same_thread = 1; + PyObject *factory = (PyObject*)&pysqlite_ConnectionType; + int cached_statements = 100; + int uri = 0; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 8, 0, argsbuf); + if (!args) { + goto exit; + } + if (!PyUnicode_FSConverter(args[0], &database)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[1]) { + if (PyFloat_CheckExact(args[1])) { + timeout = PyFloat_AS_DOUBLE(args[1]); + } + else + { + timeout = PyFloat_AsDouble(args[1]); + if (timeout == -1.0 && PyErr_Occurred()) { + goto exit; + } + } + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (args[2]) { + detect_types = _PyLong_AsInt(args[2]); + if (detect_types == -1 && PyErr_Occurred()) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (args[3]) { + isolation_level = args[3]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (args[4]) { + check_same_thread = _PyLong_AsInt(args[4]); + if (check_same_thread == -1 && PyErr_Occurred()) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (args[5]) { + factory = args[5]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (args[6]) { + cached_statements = _PyLong_AsInt(args[6]); + if (cached_statements == -1 && PyErr_Occurred()) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } + uri = PyObject_IsTrue(args[7]); + if (uri < 0) { + goto exit; + } +skip_optional_pos: + return_value = pysqlite_connect_impl(module, database, timeout, detect_types, isolation_level, check_same_thread, factory, cached_statements, uri); + +exit: + return return_value; +} + PyDoc_STRVAR(pysqlite_complete_statement__doc__, "complete_statement($module, statement, /)\n" "--\n" @@ -213,4 +325,4 @@ pysqlite_adapt(PyObject *module, PyObject *const *args, Py_ssize_t nargs) #ifndef PYSQLITE_ENABLE_SHARED_CACHE_METHODDEF #define PYSQLITE_ENABLE_SHARED_CACHE_METHODDEF #endif /* !defined(PYSQLITE_ENABLE_SHARED_CACHE_METHODDEF) */ -/*[clinic end generated code: output=2f740fe39ac0ec71 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=5e0bb0b26046264e input=a9049054013a1b77]*/ diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index 30c8b5672a39fd..e6bd40bf50cd7a 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -58,33 +58,30 @@ static int pysqlite_connection_set_isolation_level(pysqlite_Connection* self, Py static void _pysqlite_drop_unused_cursor_references(pysqlite_Connection* self); -int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) -{ - static char *kwlist[] = { - "database", "timeout", "detect_types", "isolation_level", - "check_same_thread", "factory", "cached_statements", "uri", - NULL - }; +/*[clinic input] +_sqlite3.Connection.__init__ as pysqlite_connection_init + + database as database_obj: object(converter='PyUnicode_FSConverter') + timeout: double = 5.0 + detect_types: int = 0 + isolation_level: object = NULL + check_same_thread: int = 1 + factory: object(c_default='(PyObject*)&pysqlite_ConnectionType') = ConnectionType + cached_statements: int = 100 + uri: bool = False +[clinic start generated code]*/ +static int +pysqlite_connection_init_impl(pysqlite_Connection *self, + PyObject *database_obj, double timeout, + int detect_types, PyObject *isolation_level, + int check_same_thread, PyObject *factory, + int cached_statements, int uri) +/*[clinic end generated code: output=dc19df1c0e2b7b77 input=f7f8a772a2df3427]*/ +{ const char* database; - PyObject* database_obj; - int detect_types = 0; - PyObject* isolation_level = NULL; - PyObject* factory = NULL; - int check_same_thread = 1; - int cached_statements = 100; - int uri = 0; - double timeout = 5.0; int rc; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|diOiOip", kwlist, - PyUnicode_FSConverter, &database_obj, &timeout, &detect_types, - &isolation_level, &check_same_thread, - &factory, &cached_statements, &uri)) - { - return -1; - } - database = PyBytes_AsString(database_obj); self->initialized = 1; diff --git a/Modules/_sqlite/connection.h b/Modules/_sqlite/connection.h index 8ea7d9cc3dee99..967fea258f4785 100644 --- a/Modules/_sqlite/connection.h +++ b/Modules/_sqlite/connection.h @@ -112,7 +112,6 @@ PyObject* pysqlite_connection_alloc(PyTypeObject* type, int aware); void pysqlite_connection_dealloc(pysqlite_Connection* self); PyObject* _pysqlite_connection_begin(pysqlite_Connection* self); PyObject* pysqlite_connection_new(PyTypeObject* type, PyObject* args, PyObject* kw); -int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject* kwargs); int pysqlite_connection_register_cursor(pysqlite_Connection* connection, PyObject* cursor); int pysqlite_check_thread(pysqlite_Connection* self); diff --git a/Modules/_sqlite/module.c b/Modules/_sqlite/module.c index b7a3ac2eeea450..85a26e92ebd11d 100644 --- a/Modules/_sqlite/module.c +++ b/Modules/_sqlite/module.c @@ -56,58 +56,83 @@ PyObject* _pysqlite_converters = NULL; int _pysqlite_enable_callback_tracebacks = 0; int pysqlite_BaseTypeAdapted = 0; -static PyObject* module_connect(PyObject* self, PyObject* args, PyObject* - kwargs) -{ - /* Python seems to have no way of extracting a single keyword-arg at - * C-level, so this code is redundant with the one in connection_init in - * connection.c and must always be copied from there ... */ +/* Python seems to have no way of extracting a single keyword-arg at + * C-level, so this code is redundant with the one in connection_init in + * connection.c and must always be copied from there ... */ +/*[clinic input] +_sqlite3.connect as pysqlite_connect - static char *kwlist[] = { - "database", "timeout", "detect_types", "isolation_level", - "check_same_thread", "factory", "cached_statements", "uri", - NULL - }; - PyObject* database; - int detect_types = 0; - PyObject* isolation_level; - PyObject* factory = NULL; - int check_same_thread = 1; - int cached_statements; - int uri = 0; - double timeout = 5.0; + database: object(converter='PyUnicode_FSConverter') + timeout: double = 5.0 + detect_types: int = 0 + isolation_level: object = NULL + check_same_thread: int = 1 + factory: object(c_default='(PyObject*)&pysqlite_ConnectionType') = ConnectionType + cached_statements: int = 100 + uri: bool = False + +Opens 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]*/ + +static PyObject * +pysqlite_connect_impl(PyObject *module, PyObject *database, double timeout, + int detect_types, PyObject *isolation_level, + int check_same_thread, PyObject *factory, + int cached_statements, int uri) +/*[clinic end generated code: output=450ac9078b4868bb input=f9f43e3bd4497723]*/ +{ + PyObject* obj_timeout; + PyObject* obj_detect_types; + PyObject* obj_check_same_thread; + PyObject* obj_cached_statements; + PyObject* obj_uri; PyObject* result; + int decref_isolation_level = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|diOiOip", kwlist, - &database, &timeout, &detect_types, - &isolation_level, &check_same_thread, - &factory, &cached_statements, &uri)) - { + if (PySys_Audit("sqlite3.connect", "O", database) < 0) { return NULL; } - if (factory == NULL) { - factory = (PyObject*)&pysqlite_ConnectionType; + if (!isolation_level) { + isolation_level = PyUnicode_FromString(""); + if (!isolation_level) { + return NULL; + } + decref_isolation_level = 1; } - if (PySys_Audit("sqlite3.connect", "O", database) < 0) { - return NULL; + obj_timeout = PyFloat_FromDouble(timeout); + obj_detect_types = PyLong_FromLong(detect_types); + obj_check_same_thread = PyLong_FromLong(check_same_thread); + obj_cached_statements = PyLong_FromLong(cached_statements); + obj_uri = PyBool_FromLong(uri); + + result = PyObject_CallFunctionObjArgs(factory, + database, + obj_timeout, + obj_detect_types, + isolation_level, + obj_check_same_thread, + factory, + obj_cached_statements, + obj_uri, + NULL); + if (decref_isolation_level) { + Py_DECREF(isolation_level); } - - result = PyObject_Call(factory, args, kwargs); + Py_XDECREF(database); + Py_XDECREF(obj_timeout); + Py_XDECREF(obj_detect_types); + Py_XDECREF(obj_check_same_thread); + Py_XDECREF(obj_cached_statements); + Py_XDECREF(obj_uri); return result; } -PyDoc_STRVAR(module_connect_doc, -"connect(database[, timeout, detect_types, isolation_level,\n\ - check_same_thread, factory, cached_statements, uri])\n\ -\n\ -Opens a connection to the SQLite database file *database*. You can use\n\ -\":memory:\" to open a database connection to a database that resides in\n\ -RAM instead of on disk."); - /*[clinic input] _sqlite3.complete_statement as pysqlite_complete_statement @@ -276,10 +301,9 @@ static void converters_init(PyObject* dict) } static PyMethodDef module_methods[] = { - {"connect", (PyCFunction)(void(*)(void))module_connect, - METH_VARARGS | METH_KEYWORDS, module_connect_doc}, PYSQLITE_ADAPT_METHODDEF PYSQLITE_COMPLETE_STATEMENT_METHODDEF + PYSQLITE_CONNECT_METHODDEF PYSQLITE_ENABLE_CALLBACK_TRACE_METHODDEF PYSQLITE_ENABLE_SHARED_CACHE_METHODDEF PYSQLITE_REGISTER_ADAPTER_METHODDEF From dab5c43418056d273e47f33574f9c056fe58a49e Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sun, 14 Jun 2020 21:21:30 +0200 Subject: [PATCH 8/9] Add NEWS --- .../NEWS.d/next/Library/2020-06-12-12-05-59.bpo-40956._tvsZ7.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2020-06-12-12-05-59.bpo-40956._tvsZ7.rst diff --git a/Misc/NEWS.d/next/Library/2020-06-12-12-05-59.bpo-40956._tvsZ7.rst b/Misc/NEWS.d/next/Library/2020-06-12-12-05-59.bpo-40956._tvsZ7.rst new file mode 100644 index 00000000000000..59f41275c652f1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-06-12-12-05-59.bpo-40956._tvsZ7.rst @@ -0,0 +1 @@ +Use Argument Clinic in :mod:`sqlite3` From 822d50fd793df7b72bcf13891d49e66bddc190e5 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 8 Sep 2020 11:19:19 +0200 Subject: [PATCH 9/9] Sync clinic with master --- Modules/_sqlite/clinic/connection.c.h | 18 +++++------------- Modules/_sqlite/clinic/module.c.h | 10 +--------- 2 files changed, 6 insertions(+), 22 deletions(-) diff --git a/Modules/_sqlite/clinic/connection.c.h b/Modules/_sqlite/clinic/connection.c.h index 1cb7d0739632dc..dffb7ca30231fc 100644 --- a/Modules/_sqlite/clinic/connection.c.h +++ b/Modules/_sqlite/clinic/connection.c.h @@ -369,7 +369,7 @@ PyDoc_STRVAR(pysqlite_connection_set_trace_callback__doc__, #define PYSQLITE_CONNECTION_SET_TRACE_CALLBACK_METHODDEF \ {"set_trace_callback", (PyCFunction)pysqlite_connection_set_trace_callback, METH_O, pysqlite_connection_set_trace_callback__doc__}, -#if defined(HAVE_LOAD_EXTENSION) +#if !defined(SQLITE_OMIT_LOAD_EXTENSION) PyDoc_STRVAR(pysqlite_connection_enable_load_extension__doc__, "enable_load_extension($self, enable, /)\n" @@ -400,9 +400,9 @@ pysqlite_connection_enable_load_extension(pysqlite_Connection *self, PyObject *a return return_value; } -#endif /* defined(HAVE_LOAD_EXTENSION) */ +#endif /* !defined(SQLITE_OMIT_LOAD_EXTENSION) */ -#if defined(HAVE_LOAD_EXTENSION) +#if !defined(SQLITE_OMIT_LOAD_EXTENSION) PyDoc_STRVAR(pysqlite_connection_load_extension__doc__, "load_extension($self, name, /)\n" @@ -442,7 +442,7 @@ pysqlite_connection_load_extension(pysqlite_Connection *self, PyObject *arg) return return_value; } -#endif /* defined(HAVE_LOAD_EXTENSION) */ +#endif /* !defined(SQLITE_OMIT_LOAD_EXTENSION) */ PyDoc_STRVAR(pysqlite_connection_execute__doc__, "execute($self, sql, /, parameters=)\n" @@ -575,8 +575,6 @@ pysqlite_connection_iterdump(pysqlite_Connection *self, PyObject *Py_UNUSED(igno return pysqlite_connection_iterdump_impl(self); } -#if defined(HAVE_BACKUP_API) - PyDoc_STRVAR(pysqlite_connection_backup__doc__, "backup($self, /, target=, *, pages=-1, progress=None,\n" " name=\'main\', sleep=0.25)\n" @@ -677,8 +675,6 @@ pysqlite_connection_backup(pysqlite_Connection *self, PyObject *const *args, Py_ return return_value; } -#endif /* defined(HAVE_BACKUP_API) */ - PyDoc_STRVAR(pysqlite_connection_create_collation__doc__, "create_collation($self, name, callback, /)\n" "--\n" @@ -779,8 +775,4 @@ pysqlite_connection_exit(pysqlite_Connection *self, PyObject *const *args, Py_ss #ifndef PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF #define PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF #endif /* !defined(PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF) */ - -#ifndef PYSQLITE_CONNECTION_BACKUP_METHODDEF - #define PYSQLITE_CONNECTION_BACKUP_METHODDEF -#endif /* !defined(PYSQLITE_CONNECTION_BACKUP_METHODDEF) */ -/*[clinic end generated code: output=d1fb1f48710a3cd4 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=578e5f247210bbdf input=a9049054013a1b77]*/ diff --git a/Modules/_sqlite/clinic/module.c.h b/Modules/_sqlite/clinic/module.c.h index a4f5639e1e0237..76f6bb63f76569 100644 --- a/Modules/_sqlite/clinic/module.c.h +++ b/Modules/_sqlite/clinic/module.c.h @@ -151,8 +151,6 @@ pysqlite_complete_statement(PyObject *module, PyObject *arg) return return_value; } -#if defined(HAVE_SHARED_CACHE) - PyDoc_STRVAR(pysqlite_enable_shared_cache__doc__, "enable_shared_cache($module, enable, /)\n" "--\n" @@ -183,8 +181,6 @@ pysqlite_enable_shared_cache(PyObject *module, PyObject *arg) return return_value; } -#endif /* defined(HAVE_SHARED_CACHE) */ - PyDoc_STRVAR(pysqlite_register_adapter__doc__, "register_adapter($module, type, caster, /)\n" "--\n" @@ -321,8 +317,4 @@ pysqlite_adapt(PyObject *module, PyObject *const *args, Py_ssize_t nargs) exit: return return_value; } - -#ifndef PYSQLITE_ENABLE_SHARED_CACHE_METHODDEF - #define PYSQLITE_ENABLE_SHARED_CACHE_METHODDEF -#endif /* !defined(PYSQLITE_ENABLE_SHARED_CACHE_METHODDEF) */ -/*[clinic end generated code: output=5e0bb0b26046264e input=a9049054013a1b77]*/ +/*[clinic end generated code: output=79068baf73b272f8 input=a9049054013a1b77]*/