From a080c427c80e6195685f43b2f63546a9e4f6efa0 Mon Sep 17 00:00:00 2001 From: db Date: Thu, 28 Aug 2014 09:22:37 -0300 Subject: Fix module import for iterdump method (#2945). The python `pysqlcipher.dbapi2.Connection.iterdump` method is bound to the `pysqlite_connection_iterdump()` function in src/connection.c. This function should import the python `pysqlcipher.dump` module, which contains the function `_iterdump` with the actual implementation of the `pysqlcipher.dbapi2.Connection.iterdump` method. The `pysqlcipher` module was adapted from the `pysqlite2` module. When that was done we forgot to change the import of the `dump` module, which until now was being loaded from the old `pysqlite2` module, instead of being loaded from the correct `pysqlcipher` module. This was a bug and was forcing us to depend on `pysqlite2` to be able to use the `iterdump` method. This commit fixes that bug by loading the correct `pysqlcipher` module in the `pysqlite_connection_iterdump()` function in `src/connection.c`. --- src/connection.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/connection.c') diff --git a/src/connection.c b/src/connection.c index 481b9b5..7e4e96c 100644 --- a/src/connection.c +++ b/src/connection.c @@ -1442,7 +1442,7 @@ pysqlite_connection_iterdump(pysqlite_Connection* self, PyObject* args) goto finally; } - module = PyImport_ImportModule("pysqlite2.dump"); + module = PyImport_ImportModule("pysqlcipher.dump"); if (!module) { goto finally; } -- cgit v1.2.3 From bb9cc1216873604459724860d606283c398ea06b Mon Sep 17 00:00:00 2001 From: Ruben Pollan Date: Thu, 2 Feb 2017 20:25:20 +0100 Subject: [feat] add support for the blob interface Pysqlcipher support for the sqlite blob interface: https://sqlite.org/c3ref/blob_open.html Copying the code from the PR in pysqlite: https://github.com/ghaering/pysqlite/pull/93 --- src/connection.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 88 insertions(+), 2 deletions(-) (limited to 'src/connection.c') diff --git a/src/connection.c b/src/connection.c index 7e4e96c..115d15a 100644 --- a/src/connection.c +++ b/src/connection.c @@ -30,6 +30,8 @@ #include "util.h" #include "sqlitecompat.h" +#include "blob.h" + #ifdef PYSQLITE_EXPERIMENTAL #include "backup.h" #endif @@ -91,6 +93,7 @@ int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject self->statement_cache = NULL; self->statements = NULL; self->cursors = NULL; + self->blobs = NULL; Py_INCREF(Py_None); self->row_factory = Py_None; @@ -167,10 +170,12 @@ int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject self->created_statements = 0; self->created_cursors = 0; - /* Create lists of weak references to statements/cursors */ + /* Create lists of weak references to statements/cursors/blobs */ self->statements = PyList_New(0); self->cursors = PyList_New(0); - if (!self->statements || !self->cursors) { + self->blobs = PyList_New(0); + + if (!self->statements || !self->cursors || !self->blobs) { return -1; } @@ -293,6 +298,7 @@ void pysqlite_connection_dealloc(pysqlite_Connection* self) Py_XDECREF(self->collations); Py_XDECREF(self->statements); Py_XDECREF(self->cursors); + Py_XDECREF(self->blobs); self->ob_type->tp_free((PyObject*)self); } @@ -390,6 +396,82 @@ PyObject* pysqlite_connection_backup(pysqlite_Connection* self, PyObject* args, } #endif +PyObject* pysqlite_connection_blob(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) +{ + static char *kwlist[] = {"table", "column", "row", "flags", "dbname", NULL, NULL}; + int rc; + const char *dbname = "main", *table, *column; + sqlite3_int64 row; + int flags = 0; + sqlite3_blob* blob; + pysqlite_Blob *pyblob=0; + PyObject *weakref; + + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ssL|is", kwlist, + &table, &column, &row, &flags, &dbname)) { + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + rc = sqlite3_blob_open(self->db, dbname, table, column, row, flags, &blob); + Py_END_ALLOW_THREADS + + if (rc != SQLITE_OK) { + _pysqlite_seterror(self->db, NULL); + return NULL; + } + + pyblob = PyObject_New(pysqlite_Blob, &pysqlite_BlobType); + if (!pyblob){ + goto error; + } + + rc = pysqlite_blob_init(pyblob, self, blob); + if (rc) { + Py_CLEAR(pyblob); + goto error; + } + + // Add our blob to connection blobs list + weakref=PyWeakref_NewRef((PyObject*)pyblob, NULL); + if (!weakref){ + Py_CLEAR(pyblob); + goto error; + } + if (PyList_Append(self->blobs, weakref) != 0) { + Py_CLEAR(pyblob); + Py_CLEAR(weakref); + goto error; + } + Py_DECREF(weakref); + + return (PyObject*)pyblob; + +error: + Py_BEGIN_ALLOW_THREADS + sqlite3_blob_close(blob); + Py_END_ALLOW_THREADS + return NULL; +} + + +void pysqlite_close_all_blobs(pysqlite_Connection* self) +{ + int i; + PyObject* weakref; + PyObject* blob; + + for (i = 0; i < PyList_Size(self->blobs); i++) { + weakref = PyList_GetItem(self->blobs, i); + blob = PyWeakref_GetObject(weakref); + if (blob != Py_None) { + pysqlite_blob_close((pysqlite_Blob*)blob); + } + } +} + + PyObject* pysqlite_connection_close(pysqlite_Connection* self, PyObject* args) { PyObject* ret; @@ -401,6 +483,8 @@ PyObject* pysqlite_connection_close(pysqlite_Connection* self, PyObject* args) pysqlite_do_all_statements(self, ACTION_FINALIZE, 1); + pysqlite_close_all_blobs(self); + if (self->db) { if (self->apsw_connection) { ret = PyObject_CallMethod(self->apsw_connection, "close", ""); @@ -1597,6 +1681,8 @@ static PyMethodDef connection_methods[] = { {"backup", (PyCFunction)pysqlite_connection_backup, METH_VARARGS|METH_KEYWORDS, PyDoc_STR("Backup database.")}, #endif + {"blob", (PyCFunction)pysqlite_connection_blob, METH_VARARGS|METH_KEYWORDS, + PyDoc_STR("return a blob object")}, {"cursor", (PyCFunction)pysqlite_connection_cursor, METH_VARARGS|METH_KEYWORDS, PyDoc_STR("Return a cursor for the connection.")}, {"close", (PyCFunction)pysqlite_connection_close, METH_NOARGS, -- cgit v1.2.3