Imported Upstream version 0.5.4 upstream upstream/0.5.4
authorDongHun Kwak <dh0128.kwak@samsung.com>
Wed, 19 Feb 2025 03:00:32 +0000 (12:00 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Wed, 19 Feb 2025 03:00:32 +0000 (12:00 +0900)
13 files changed:
PKG-INFO
README.md
pysqlite3.egg-info/PKG-INFO
setup.py
src/blob.c
src/connection.c
src/cursor.c
src/module.c
src/prepare_protocol.c
src/row.c
src/statement.c
src/util.c
src/util.h

index a42bc2351fa30154837f42cb9dfc3b44843066a0..634fb3c07df65e6d5c883e69f36fa4e0b8b4925b 100644 (file)
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: pysqlite3
-Version: 0.4.7
+Version: 0.5.4
 Summary: DB-API 2.0 interface for Sqlite 3.x
 Home-page: https://github.com/coleifer/pysqlite3
 Author: Charles Leifer
index 81ab244158e6d162e8c6ea1285fd3012472ddbd6..146e12ace02d32e4e18164bb9803c2b2af89384e 100644 (file)
--- a/README.md
+++ b/README.md
@@ -24,7 +24,14 @@ dependencies.
 Building with System SQLite
 ---------------------------
 
-To build `pysqlite3` linked against the system SQLite, run:
+If you intend to use the system SQLite, you can install with:
+
+```
+$ pip install pysqlite3
+```
+
+Alternatively you can clone or download the repo and use `setup.py` to
+build `pysqlite3` linked against the system SQLite:
 
 ```
 $ python setup.py build
@@ -61,7 +68,7 @@ Using the binary package
 
 A binary package (wheel) is available for linux with a completely
 self-contained  `pysqlite3`, statically-linked against the most recent release
-of SQLite.
+of SQLite with many features/extensions enabled.
 
 ```
 $ pip install pysqlite3-binary
index a42bc2351fa30154837f42cb9dfc3b44843066a0..634fb3c07df65e6d5c883e69f36fa4e0b8b4925b 100644 (file)
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: pysqlite3
-Version: 0.4.7
+Version: 0.5.4
 Summary: DB-API 2.0 interface for Sqlite 3.x
 Home-page: https://github.com/coleifer/pysqlite3
 Author: Charles Leifer
index 9efe6375821f32a3bfa938f4f01adb585f48d135..a4b3c4849f1abea35b5de8a9a530acedf4ffe9e4 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -12,7 +12,7 @@ from setuptools import Extension
 # If you need to change anything, it should be enough to change setup.cfg.
 
 PACKAGE_NAME = 'pysqlite3'
-VERSION = '0.4.7'
+VERSION = '0.5.4'
 
 # define sqlite sources
 sources = [os.path.join('src', source)
@@ -159,11 +159,5 @@ def get_setup_args():
     )
 
 
-def main():
-    try:
-        setuptools.setup(**get_setup_args())
-    except BaseException as ex:
-        log.info(str(ex))
-
 if __name__ == "__main__":
-    main()
+    setuptools.setup(**get_setup_args())
index 70b327a8911879823387b6bf11edd918eb04a443..111cea231b59cefdda6369698cdd3069032798e6 100644 (file)
@@ -24,13 +24,15 @@ int pysqlite_blob_init(pysqlite_Blob *self, pysqlite_Connection* connection,
 static void remove_blob_from_connection_blob_list(pysqlite_Blob *self)
 {
     Py_ssize_t i;
-    PyObject *item;
+    PyObject *item, *ref;
 
     for (i = 0; i < PyList_GET_SIZE(self->connection->blobs); i++) {
         item = PyList_GET_ITEM(self->connection->blobs, i);
-        if (PyWeakref_GetObject(item) == (PyObject *)self) {
-            PyList_SetSlice(self->connection->blobs, i, i+1, NULL);
-            break;
+        if (PyWeakref_GetRef(item, &ref) == 1) {
+            if (ref == (PyObject *)self) {
+                PyList_SetSlice(self->connection->blobs, i, i+1, NULL);
+                break;
+            }
         }
     }
 }
index 7b1bd1203d0ef6b4095743f10e0b5cec99123f92..b787d4cd16e3d9012050a88a646ea2c28aa36478 100644 (file)
 #define HAVE_BACKUP_API
 #endif
 
+#if SQLITE_VERSION_NUMBER >= 3014002
+#define HAVE_TRACE_V2
+#endif
+
 #if SQLITE_VERSION_NUMBER >= 3025000
 #define HAVE_WINDOW_FUNCTION
 #endif
 
+#if SQLITE_HAS_CODEC
+#define HAVE_ENCRYPTION
+#endif
+
+#if PY_VERSION_HEX < 0x030D0000
+    #define PyLong_AsInt _PyLong_AsInt
+#endif
+
 _Py_IDENTIFIER(cursor);
 
 static const char * const begin_statements[] = {
@@ -221,9 +233,7 @@ void pysqlite_do_all_statements(pysqlite_Connection* self, int action, int reset
 
     for (i = 0; i < PyList_Size(self->statements); i++) {
         weakref = PyList_GetItem(self->statements, i);
-        statement = PyWeakref_GetObject(weakref);
-        if (statement != Py_None) {
-            Py_INCREF(statement);
+        if (PyWeakref_GetRef(weakref, &statement) == 1) {
             if (action == ACTION_RESET) {
                 (void)pysqlite_statement_reset((pysqlite_Statement*)statement);
             } else {
@@ -236,9 +246,9 @@ void pysqlite_do_all_statements(pysqlite_Connection* self, int action, int reset
     if (reset_cursors) {
         for (i = 0; i < PyList_Size(self->cursors); i++) {
             weakref = PyList_GetItem(self->cursors, i);
-            cursor = (pysqlite_Cursor*)PyWeakref_GetObject(weakref);
-            if ((PyObject*)cursor != Py_None) {
+            if (PyWeakref_GetRef(weakref, (PyObject**)&cursor) == 1) {
                 cursor->reset = 1;
+                Py_DECREF(cursor);
             }
         }
     }
@@ -404,9 +414,9 @@ static void pysqlite_close_all_blobs(pysqlite_Connection *self)
 
     for (i = 0; i < PyList_GET_SIZE(self->blobs); i++) {
         weakref = PyList_GET_ITEM(self->blobs, i);
-        blob = PyWeakref_GetObject(weakref);
-        if (blob != Py_None) {
+        if (PyWeakref_GetRef(weakref, &blob) == 1) {
             pysqlite_blob_close((pysqlite_Blob*)blob);
+            Py_DECREF(blob);
         }
     }
 }
@@ -722,7 +732,7 @@ static void _pysqlite_step_callback(sqlite3_context *context, int argc, sqlite3_
     aggregate_instance = (PyObject**)sqlite3_aggregate_context(context, sizeof(PyObject*));
 
     if (*aggregate_instance == NULL) {
-        *aggregate_instance = _PyObject_CallNoArg(aggregate_class);
+        *aggregate_instance = PyObject_CallObject(aggregate_class, NULL);
 
         if (PyErr_Occurred()) {
             *aggregate_instance = 0;
@@ -928,6 +938,7 @@ static void _pysqlite_drop_unused_statement_references(pysqlite_Connection* self
 {
     PyObject* new_list;
     PyObject* weakref;
+    PyObject* ref;
     int i;
 
     /* we only need to do this once in a while */
@@ -944,7 +955,8 @@ static void _pysqlite_drop_unused_statement_references(pysqlite_Connection* self
 
     for (i = 0; i < PyList_Size(self->statements); i++) {
         weakref = PyList_GetItem(self->statements, i);
-        if (PyWeakref_GetObject(weakref) != Py_None) {
+        if (PyWeakref_GetRef(weakref, &ref) == 1) {
+            Py_DECREF(ref);
             if (PyList_Append(new_list, weakref) != 0) {
                 Py_DECREF(new_list);
                 return;
@@ -959,6 +971,7 @@ static void _pysqlite_drop_unused_cursor_references(pysqlite_Connection* self)
 {
     PyObject* new_list;
     PyObject* weakref;
+    PyObject* ref;
     int i;
 
     /* we only need to do this once in a while */
@@ -975,7 +988,8 @@ static void _pysqlite_drop_unused_cursor_references(pysqlite_Connection* self)
 
     for (i = 0; i < PyList_Size(self->cursors); i++) {
         weakref = PyList_GetItem(self->cursors, i);
-        if (PyWeakref_GetObject(weakref) != Py_None) {
+        if (PyWeakref_GetRef(weakref, &ref) == 1) {
+            Py_DECREF(ref);
             if (PyList_Append(new_list, weakref) != 0) {
                 Py_DECREF(new_list);
                 return;
@@ -1146,7 +1160,7 @@ static int _authorizer_callback(void* user_arg, int action, const char* arg1, co
     }
     else {
         if (PyLong_Check(ret)) {
-            rc = _PyLong_AsInt(ret);
+            rc = PyLong_AsInt(ret);
             if (rc == -1 && PyErr_Occurred()) {
                 if (_pysqlite_enable_callback_tracebacks)
                     PyErr_Print();
@@ -1172,7 +1186,7 @@ static int _progress_handler(void* user_arg)
     PyGILState_STATE gilstate;
 
     gilstate = PyGILState_Ensure();
-    ret = _PyObject_CallNoArg((PyObject*)user_arg);
+    ret = PyObject_CallObject((PyObject*)user_arg, NULL);
 
     if (!ret) {
         if (_pysqlite_enable_callback_tracebacks) {
@@ -1192,16 +1206,60 @@ static int _progress_handler(void* user_arg)
     return rc;
 }
 
+#ifdef HAVE_TRACE_V2
+static int _trace_callback(unsigned int type, void *ctx, void *stmt, void *sql)
+{
+    if (type != SQLITE_TRACE_STMT) {
+        return 0;
+    }
+
+    PyGILState_STATE gilstate = PyGILState_Ensure();
+    PyObject *py_statement = NULL;
+    const char *expanded_sql = sqlite3_expanded_sql((sqlite3_stmt *)stmt);
+    if (expanded_sql == NULL) {
+        sqlite3 *db = sqlite3_db_handle((sqlite3_stmt *)stmt);
+        if (sqlite3_errcode(db) == SQLITE_NOMEM) {
+            (void)PyErr_NoMemory();
+            goto exit;
+        }
+        PyErr_SetString(pysqlite_DataError, "Expanded SQL string exceeds the maximum string length");
+        if (_pysqlite_enable_callback_tracebacks) {
+            PyErr_Print();
+        } else {
+            PyErr_Clear();
+        }
+
+        py_statement = PyUnicode_FromString((const char *)sql);
+    } else {
+        py_statement = PyUnicode_FromString(expanded_sql);
+        sqlite3_free((void *)expanded_sql);
+    }
+
+    if (py_statement) {
+        PyObject *ret = PyObject_CallFunctionObjArgs((PyObject*)ctx, py_statement, NULL);
+        Py_DECREF(py_statement);
+        Py_XDECREF(ret);
+    }
+
+    if (PyErr_Occurred()) {
+        if (_pysqlite_enable_callback_tracebacks) {
+            PyErr_Print();
+        } else {
+            PyErr_Clear();
+        }
+    }
+exit:
+    PyGILState_Release(gilstate);
+    return 0;
+}
+#else
 static void _trace_callback(void* user_arg, const char* statement_string)
 {
     PyObject *py_statement = NULL;
     PyObject *ret = NULL;
 
-    PyGILState_STATE gilstate;
-
-    gilstate = PyGILState_Ensure();
-    py_statement = PyUnicode_DecodeUTF8(statement_string,
-            strlen(statement_string), "replace");
+    PyGILState_STATE gilstate = PyGILState_Ensure();
+    py_statement = PyUnicode_FromString(statement_string);
     if (py_statement) {
         ret = PyObject_CallFunctionObjArgs((PyObject*)user_arg, py_statement, NULL);
         Py_DECREF(py_statement);
@@ -1219,6 +1277,7 @@ static void _trace_callback(void* user_arg, const char* statement_string)
 
     PyGILState_Release(gilstate);
 }
+#endif
 
 static PyObject* pysqlite_connection_set_authorizer(pysqlite_Connection* self, PyObject* args, PyObject* kwargs)
 {
@@ -1300,10 +1359,18 @@ static PyObject* pysqlite_connection_set_trace_callback(pysqlite_Connection* sel
 
     if (trace_callback == Py_None) {
         /* None clears the trace callback previously set */
+#ifdef HAVE_TRACE_V2
+        sqlite3_trace_v2(self->db, SQLITE_TRACE_STMT, NULL, (void*)0);
+#else
         sqlite3_trace(self->db, 0, (void*)0);
+#endif
         Py_XSETREF(self->function_pinboard_trace_callback, NULL);
     } else {
+#ifdef HAVE_TRACE_V2
+        sqlite3_trace_v2(self->db, SQLITE_TRACE_STMT, _trace_callback, trace_callback);
+#else
         sqlite3_trace(self->db, _trace_callback, trace_callback);
+#endif
         Py_INCREF(trace_callback);
         Py_XSETREF(self->function_pinboard_trace_callback, trace_callback);
     }
@@ -1417,8 +1484,6 @@ pysqlite_connection_set_isolation_level(pysqlite_Connection* self, PyObject* iso
         self->begin_statement = NULL;
     } else {
         const char * const *candidate;
-        PyObject *uppercase_level;
-        _Py_IDENTIFIER(upper);
 
         if (!PyUnicode_Check(isolation_level)) {
             PyErr_Format(PyExc_TypeError,
@@ -1427,17 +1492,14 @@ pysqlite_connection_set_isolation_level(pysqlite_Connection* self, PyObject* iso
             return -1;
         }
 
-        uppercase_level = _PyObject_CallMethodIdObjArgs(
-                        (PyObject *)&PyUnicode_Type, &PyId_upper,
-                        isolation_level, NULL);
-        if (!uppercase_level) {
+        const char *level = PyUnicode_AsUTF8(isolation_level);
+        if (level == NULL) {
             return -1;
         }
         for (candidate = begin_statements; *candidate; candidate++) {
-            if (_PyUnicode_EqualToASCIIString(uppercase_level, *candidate + 6))
+            if (sqlite3_stricmp(level, *candidate + 6) == 0)
                 break;
         }
-        Py_DECREF(uppercase_level);
         if (!*candidate) {
             PyErr_SetString(PyExc_ValueError,
                             "invalid value for isolation_level");
@@ -1462,9 +1524,6 @@ PyObject* pysqlite_connection_call(pysqlite_Connection* self, PyObject* args, Py
         return NULL;
     }
 
-    if (!_PyArg_NoKeywords(MODULE_NAME ".Connection", kwargs))
-        return NULL;
-
     if (!PyArg_ParseTuple(args, "U", &sql))
         return NULL;
 
@@ -1681,35 +1740,18 @@ pysqlite_connection_backup(pysqlite_Connection *self, PyObject *args, PyObject *
     const char *name = "main";
     int rc;
     int callback_error = 0;
-    PyObject *sleep_obj = NULL;
-    int sleep_ms = 250;
+    double sleep_s = 0.25;
+    int sleep_ms = 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,
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|$iOsd:backup", keywords,
                                      &pysqlite_ConnectionType, &target,
-                                     &pages, &progress, &name, &sleep_obj)) {
+                                     &pages, &progress, &name, &sleep_s)) {
         return NULL;
     }
 
-    // XXX: We use _PyTime_ROUND_CEILING to support 3.6.x, but it should
-    // use _PyTime_ROUND_TIMEOUT instead.
-    if (sleep_obj != NULL) {
-        _PyTime_t sleep_secs;
-        if (_PyTime_FromSecondsObject(&sleep_secs, sleep_obj,
-                                      _PyTime_ROUND_CEILING)) {
-            return NULL;
-        }
-        _PyTime_t ms = _PyTime_AsMilliseconds(sleep_secs,
-                                              _PyTime_ROUND_CEILING);
-        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)) {
         return NULL;
     }
@@ -1718,6 +1760,11 @@ pysqlite_connection_backup(pysqlite_Connection *self, PyObject *args, PyObject *
         PyErr_SetString(PyExc_ValueError, "target cannot be the same connection instance");
         return NULL;
     }
+    if (sleep_s < 0) {
+        PyErr_SetString(PyExc_ValueError, "sleep must be greater-than or equal to zero");
+        return NULL;
+    }
+    sleep_ms = (int)(sleep_s * 1000.0);
 
 #if SQLITE_VERSION_NUMBER < 3008008
     /* Since 3.8.8 this is already done, per commit
@@ -1804,15 +1851,10 @@ static PyObject *
 pysqlite_connection_create_collation(pysqlite_Connection* self, PyObject* args)
 {
     PyObject* callable;
-    PyObject* uppercase_name = 0;
-    PyObject* name;
+    PyObject* name = NULL;
     PyObject* retval;
-    Py_ssize_t i, len;
-    _Py_IDENTIFIER(upper);
-    const char *uppercase_name_str;
+    const char *name_str;
     int rc;
-    unsigned int kind;
-    const void *data;
 
     if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {
         goto finally;
@@ -1823,32 +1865,8 @@ pysqlite_connection_create_collation(pysqlite_Connection* self, PyObject* args)
         goto finally;
     }
 
-    uppercase_name = _PyObject_CallMethodIdObjArgs((PyObject *)&PyUnicode_Type,
-                                                   &PyId_upper, name, NULL);
-    if (!uppercase_name) {
-        goto finally;
-    }
-
-    if (PyUnicode_READY(uppercase_name))
-        goto finally;
-    len = PyUnicode_GET_LENGTH(uppercase_name);
-    kind = PyUnicode_KIND(uppercase_name);
-    data = PyUnicode_DATA(uppercase_name);
-    for (i=0; i<len; i++) {
-        Py_UCS4 ch = PyUnicode_READ(kind, data, i);
-        if ((ch >= '0' && ch <= '9')
-         || (ch >= 'A' && ch <= 'Z')
-         || (ch == '_'))
-        {
-            continue;
-        } else {
-            PyErr_SetString(pysqlite_ProgrammingError, "invalid character in collation name");
-            goto finally;
-        }
-    }
-
-    uppercase_name_str = PyUnicode_AsUTF8(uppercase_name);
-    if (!uppercase_name_str)
+    name_str = PyUnicode_AsUTF8(name);
+    if (!name_str)
         goto finally;
 
     if (callable != Py_None && !PyCallable_Check(callable)) {
@@ -1857,27 +1875,25 @@ pysqlite_connection_create_collation(pysqlite_Connection* self, PyObject* args)
     }
 
     if (callable != Py_None) {
-        if (PyDict_SetItem(self->collations, uppercase_name, callable) == -1)
+        if (PyDict_SetItem(self->collations, name, callable) == -1)
             goto finally;
     } else {
-        if (PyDict_DelItem(self->collations, uppercase_name) == -1)
+        if (PyDict_DelItem(self->collations, name) == -1)
             goto finally;
     }
 
     rc = sqlite3_create_collation(self->db,
-                                  uppercase_name_str,
+                                  name_str,
                                   SQLITE_UTF8,
                                   (callable != Py_None) ? callable : NULL,
                                   (callable != Py_None) ? pysqlite_collation_callback : NULL);
     if (rc != SQLITE_OK) {
-        PyDict_DelItem(self->collations, uppercase_name);
+        PyDict_DelItem(self->collations, name);
         _pysqlite_seterror(self->db);
         goto finally;
     }
 
 finally:
-    Py_XDECREF(uppercase_name);
-
     if (PyErr_Occurred()) {
         retval = NULL;
     } else {
@@ -1925,6 +1941,52 @@ pysqlite_connection_exit(pysqlite_Connection* self, PyObject* args)
     Py_RETURN_FALSE;
 }
 
+#ifdef HAVE_ENCRYPTION
+PyObject* pysqlite_connection_key(pysqlite_Connection *self, PyObject *args)
+{
+    Py_buffer key_buffer;
+    int rc;
+
+    if (!pysqlite_check_connection(self)) {
+        return NULL;
+    }
+    if (!PyArg_ParseTuple(args, "s*", &key_buffer)) {
+        return NULL;
+    }
+
+    rc = sqlite3_key(self->db, key_buffer.buf, key_buffer.len);
+    PyBuffer_Release(&key_buffer);
+
+    if (rc != SQLITE_OK) {
+        PyErr_SetString(pysqlite_OperationalError, sqlite3_errstr(rc));
+        return NULL;
+    }
+    Py_RETURN_NONE;
+}
+
+PyObject* pysqlite_connection_rekey(pysqlite_Connection *self, PyObject *args)
+{
+    Py_buffer key_buffer;
+    int rc;
+
+    if (!pysqlite_check_connection(self)) {
+        return NULL;
+    }
+    if (!PyArg_ParseTuple(args, "s*", &key_buffer)) {
+        return NULL;
+    }
+
+    rc = sqlite3_rekey(self->db, key_buffer.buf, key_buffer.len);
+    PyBuffer_Release(&key_buffer);
+
+    if (rc != SQLITE_OK) {
+        PyErr_SetString(pysqlite_OperationalError, sqlite3_errstr(rc));
+        return NULL;
+    }
+    Py_RETURN_NONE;
+}
+#endif
+
 static const char connection_doc[] =
 PyDoc_STR("SQLite database connection object.");
 
@@ -1976,6 +2038,12 @@ static PyMethodDef connection_methods[] = {
         PyDoc_STR("Creates a collation function. Non-standard.")},
     {"interrupt", (PyCFunction)pysqlite_connection_interrupt, METH_NOARGS,
         PyDoc_STR("Abort any pending database operation. Non-standard.")},
+#ifdef HAVE_ENCRYPTION
+    {"set_key", (PyCFunction)(void(*)(void))pysqlite_connection_key, METH_VARARGS,
+        PyDoc_STR("Set encryption key for database. Non-standard.")},
+    {"reset_key", (PyCFunction)(void(*)(void))pysqlite_connection_rekey, METH_VARARGS,
+        PyDoc_STR("Set encryption key for database. Non-standard.")},
+#endif
     #ifdef HAVE_BACKUP_API
     {"backup", (PyCFunction)(void(*)(void))pysqlite_connection_backup, METH_VARARGS | METH_KEYWORDS,
         PyDoc_STR("Makes a backup of the database. Non-standard.")},
index 553b56c979bc0f775e60716ccf9e027a96c1ff83..7cdbff70bd6b3df106b6e83d3901635946c37aae 100644 (file)
@@ -219,6 +219,15 @@ _pysqlite_build_column_name(pysqlite_Cursor *self, const char *colname)
     return PyUnicode_FromStringAndSize(colname, len);
 }
 
+static PyObject *
+_pysqlite_build_column_decltype(pysqlite_Cursor *self, const char *decltype)
+{
+    if (!decltype) {
+        Py_RETURN_NONE;
+    }
+    return PyUnicode_FromStringAndSize(decltype, strlen(decltype));
+}
+
 /*
  * Returns a row from the currently active SQLite statement
  *
@@ -378,6 +387,7 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* args)
     PyObject* result;
     int numcols;
     PyObject* column_name;
+    PyObject* column_decltype;
     PyObject* second_argument = NULL;
     sqlite_int64 lastrowid;
 
@@ -526,7 +536,7 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* args)
         }
 
         if (pysqlite_build_row_cast_map(self) != 0) {
-            _PyErr_FormatFromCause(pysqlite_OperationalError, "Error while building row_cast_map");
+            PyErr_Format(pysqlite_OperationalError, "Error while building row_cast_map");
             goto error;
         }
 
@@ -541,6 +551,7 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* args)
             }
             for (i = 0; i < numcols; i++) {
                 const char *colname;
+                const char *decltype;
                 colname = sqlite3_column_name(self->statement->st, i);
                 if (colname == NULL) {
                     PyErr_NoMemory();
@@ -550,10 +561,18 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* args)
                 if (!column_name) {
                     goto error;
                 }
-                PyObject *descriptor = PyTuple_Pack(7, column_name,
+                decltype = sqlite3_column_decltype(self->statement->st, i);
+                column_decltype = _pysqlite_build_column_decltype(self, decltype);
+                if (!column_decltype) {
+                    Py_DECREF(column_name);
+                    goto error;
+                }
+
+                PyObject *descriptor = PyTuple_Pack(7, column_name, column_decltype,
                                                     Py_None, Py_None, Py_None,
-                                                    Py_None, Py_None, Py_None);
+                                                    Py_None, Py_None);
                 Py_DECREF(column_name);
+                Py_DECREF(column_decltype);
                 if (descriptor == NULL) {
                     goto error;
                 }
index 7aa2abf9b168ea13d1cfe86cad82969859bf0a8d..3ee9be679ebc65e92d27bada6b3418e490e2878e 100644 (file)
@@ -438,6 +438,12 @@ PyMODINIT_FUNC PyInit__sqlite3(void)
     PyObject *tmp_obj;
     int i;
 
+    int rc = sqlite3_initialize();
+    if (rc != SQLITE_OK) {
+        PyErr_SetString(PyExc_ImportError, sqlite3_errstr(rc));
+        return NULL;
+    }
+
     module = PyModule_Create(&_sqlite3module);
 
     if (!module ||
index f2c85f9af6cb68a98dd1210ae4269f636d202bfb..7d074e7753fd2328f5421e1d7273217f0d5f014b 100644 (file)
@@ -77,7 +77,10 @@ PyTypeObject pysqlite_PrepareProtocolType= {
 
 extern int pysqlite_prepare_protocol_setup_types(void)
 {
+    int rc;
     pysqlite_PrepareProtocolType.tp_new = PyType_GenericNew;
-    Py_TYPE(&pysqlite_PrepareProtocolType)= &PyType_Type;
-    return PyType_Ready(&pysqlite_PrepareProtocolType);
+    //Py_TYPE(&pysqlite_PrepareProtocolType)= &PyType_Type;
+    rc = PyType_Ready(&pysqlite_PrepareProtocolType);
+    return rc;
+    //return PyType_Ready(&pysqlite_PrepareProtocolType);
 }
index 6ab092b4c7132db8b3c10ea7c60d0a5cb11744c6..bd86fa964f770872d00c7c38b751d9a61322f4c8 100644 (file)
--- a/src/row.c
+++ b/src/row.c
@@ -41,8 +41,6 @@ pysqlite_row_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
 
     assert(type != NULL && type->tp_alloc != NULL);
 
-    if (!_PyArg_NoKeywords("Row", kwargs))
-        return NULL;
     if (!PyArg_ParseTuple(args, "OO", &cursor, &data))
         return NULL;
 
index fb1b8bd95946b31cae7288d6bb7d675c749271fc..cea35968aef559c4df19aefb1878064f995d5c2a 100644 (file)
@@ -104,7 +104,8 @@ int pysqlite_statement_create(pysqlite_Statement* self, pysqlite_Connection* con
                             PyOS_strnicmp(p, "alter", 5) &&
                             PyOS_strnicmp(p, "analyze", 7) &&
                             PyOS_strnicmp(p, "reindex", 7) &&
-                            PyOS_strnicmp(p, "vacuum", 6));
+                            PyOS_strnicmp(p, "vacuum", 6) &&
+                            PyOS_strnicmp(p, "pragma", 6));
             break;
         }
     }
index ebf0cb548abb975a219ae7fcc567ce92188c7fc9..143bc12b743459c84a2567d8e93bf726eb5af46c 100644 (file)
@@ -157,9 +157,15 @@ _pysqlite_long_as_int64(PyObject * py_val)
     }
     else if (sizeof(value) < sizeof(sqlite_int64)) {
         sqlite_int64 int64val;
+#if PY_VERSION_HEX < 0x030D0000
         if (_PyLong_AsByteArray((PyLongObject *)py_val,
                                 (unsigned char *)&int64val, sizeof(int64val),
                                 IS_LITTLE_ENDIAN, 1 /* signed */) >= 0) {
+#else
+        if (_PyLong_AsByteArray((PyLongObject *)py_val,
+                                (unsigned char *)&int64val, sizeof(int64val),
+                                IS_LITTLE_ENDIAN, 1 /* signed */, 1) >= 0) {
+#endif
             return int64val;
         }
     }
index 2cc5c8b9d866c2e84ea5bef7afee5dba33626677..679170deb9c670c6b425276423cfc20f28fdfa0d 100644 (file)
@@ -39,4 +39,46 @@ int _pysqlite_seterror(sqlite3* db);
 
 sqlite_int64 _pysqlite_long_as_int64(PyObject * value);
 
+#ifndef _Py_CAST
+#  define _Py_CAST(type, expr) ((type)(expr))
+#endif
+
+// Cast argument to PyObject* type.
+#ifndef _PyObject_CAST
+#  define _PyObject_CAST(op) _Py_CAST(PyObject*, op)
+#endif
+
+#if PY_VERSION_HEX < 0x030A00A3 && !defined(Py_NewRef)
+static inline PyObject* _Py_NewRef(PyObject *obj)
+{
+    Py_INCREF(obj);
+    return obj;
+}
+#define Py_NewRef(obj) _Py_NewRef(_PyObject_CAST(obj))
+#endif
+
+#if PY_VERSION_HEX < 0x030D0000
+static inline int PyWeakref_GetRef(PyObject *ref, PyObject **pobj)
+{
+    PyObject *obj;
+    if (ref != NULL && !PyWeakref_Check(ref)) {
+        *pobj = NULL;
+        PyErr_SetString(PyExc_TypeError, "expected a weakref");
+        return -1;
+    }
+    obj = PyWeakref_GetObject(ref);
+    if (obj == NULL) {
+        // SystemError if ref is NULL
+        *pobj = NULL;
+        return -1;
+    }
+    if (obj == Py_None) {
+        *pobj = NULL;
+        return 0;
+    }
+    *pobj = Py_NewRef(obj);
+    return (*pobj != NULL);
+}
+#endif
+
 #endif