summaryrefslogtreecommitdiffstats
path: root/Modules/_sqlite
diff options
context:
space:
mode:
Diffstat (limited to 'Modules/_sqlite')
-rw-r--r--Modules/_sqlite/cache.c1
-rw-r--r--Modules/_sqlite/connection.c109
-rw-r--r--Modules/_sqlite/cursor.c17
-rw-r--r--Modules/_sqlite/module.c16
-rw-r--r--Modules/_sqlite/prepare_protocol.c1
-rw-r--r--Modules/_sqlite/row.c14
-rw-r--r--Modules/_sqlite/sqlitecompat.h63
-rw-r--r--Modules/_sqlite/statement.c33
-rw-r--r--Modules/_sqlite/util.c2
9 files changed, 135 insertions, 121 deletions
diff --git a/Modules/_sqlite/cache.c b/Modules/_sqlite/cache.c
index 3693363..3689a4e 100644
--- a/Modules/_sqlite/cache.c
+++ b/Modules/_sqlite/cache.c
@@ -21,7 +21,6 @@
* 3. This notice may not be removed or altered from any source distribution.
*/
-#include "sqlitecompat.h"
#include "cache.h"
#include <limits.h>
diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c
index 8cf2d6a..882424b 100644
--- a/Modules/_sqlite/connection.c
+++ b/Modules/_sqlite/connection.c
@@ -29,7 +29,6 @@
#include "cursor.h"
#include "prepare_protocol.h"
#include "util.h"
-#include "sqlitecompat.h"
#include "pythread.h"
@@ -42,6 +41,8 @@
#endif
#endif
+_Py_IDENTIFIER(cursor);
+
static int pysqlite_connection_set_isolation_level(pysqlite_Connection* self, PyObject* isolation_level);
static void _pysqlite_drop_unused_cursor_references(pysqlite_Connection* self);
@@ -60,7 +61,11 @@ static void _sqlite3_result_error(sqlite3_context* ctx, const char* errmsg, int
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", NULL, NULL};
+ static char *kwlist[] = {
+ "database", "timeout", "detect_types", "isolation_level",
+ "check_same_thread", "factory", "cached_statements", "uri",
+ NULL
+ };
char* database;
int detect_types = 0;
@@ -68,11 +73,14 @@ int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject
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, "s|diOiOi", kwlist,
- &database, &timeout, &detect_types, &isolation_level, &check_same_thread, &factory, &cached_statements))
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|diOiOip", kwlist,
+ &database, &timeout, &detect_types,
+ &isolation_level, &check_same_thread,
+ &factory, &cached_statements, &uri))
{
return -1;
}
@@ -91,8 +99,19 @@ int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject
Py_INCREF(&PyUnicode_Type);
self->text_factory = (PyObject*)&PyUnicode_Type;
+#ifdef SQLITE_OPEN_URI
+ Py_BEGIN_ALLOW_THREADS
+ rc = sqlite3_open_v2(database, &self->db,
+ SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
+ (uri ? SQLITE_OPEN_URI : 0), NULL);
+#else
+ if (uri) {
+ PyErr_SetString(pysqlite_NotSupportedError, "URIs not supported");
+ return -1;
+ }
Py_BEGIN_ALLOW_THREADS
rc = sqlite3_open(database, &self->db);
+#endif
Py_END_ALLOW_THREADS
if (rc != SQLITE_OK) {
@@ -506,10 +525,16 @@ _pysqlite_set_result(sqlite3_context* context, PyObject* py_val)
const char* buffer;
Py_ssize_t buflen;
if (PyObject_AsCharBuffer(py_val, &buffer, &buflen) != 0) {
- PyErr_SetString(PyExc_ValueError, "could not convert BLOB to buffer");
+ PyErr_SetString(PyExc_ValueError,
+ "could not convert BLOB to buffer");
return -1;
}
- sqlite3_result_blob(context, buffer, buflen, SQLITE_TRANSIENT);
+ if (buflen > INT_MAX) {
+ PyErr_SetString(PyExc_OverflowError,
+ "BLOB longer than INT_MAX bytes");
+ return -1;
+ }
+ sqlite3_result_blob(context, buffer, (int)buflen, SQLITE_TRANSIENT);
} else {
return -1;
}
@@ -682,6 +707,8 @@ void _pysqlite_final_callback(sqlite3_context* context)
PyObject** aggregate_instance;
_Py_IDENTIFIER(finalize);
int ok;
+ PyObject *exception, *value, *tb;
+ int restore;
#ifdef WITH_THREAD
PyGILState_STATE threadstate;
@@ -697,7 +724,12 @@ void _pysqlite_final_callback(sqlite3_context* context)
goto error;
}
+ /* Keep the exception (if any) of the last call to step() */
+ PyErr_Fetch(&exception, &value, &tb);
+ restore = 1;
+
function_result = _PyObject_CallMethodId(*aggregate_instance, &PyId_finalize, "");
+
Py_DECREF(*aggregate_instance);
ok = 0;
@@ -712,6 +744,17 @@ void _pysqlite_final_callback(sqlite3_context* context)
PyErr_Clear();
}
_sqlite3_result_error(context, "user-defined aggregate's 'finalize' method raised error", -1);
+#if SQLITE_VERSION_NUMBER < 3003003
+ /* with old SQLite versions, _sqlite3_result_error() sets a new Python
+ exception, so don't restore the previous exception */
+ restore = 0;
+#endif
+ }
+
+ if (restore) {
+ /* Restore the exception (if any) of the last call to step(),
+ but clear also the current exception if finalize() failed */
+ PyErr_Restore(exception, value, tb);
}
error:
@@ -862,22 +905,29 @@ static int _authorizer_callback(void* user_arg, int action, const char* arg1, co
gilstate = PyGILState_Ensure();
#endif
+
ret = PyObject_CallFunction((PyObject*)user_arg, "issss", action, arg1, arg2, dbname, access_attempt_source);
- if (!ret) {
- if (_enable_callback_tracebacks) {
+ if (ret == NULL) {
+ if (_enable_callback_tracebacks)
PyErr_Print();
- } else {
+ else
PyErr_Clear();
- }
rc = SQLITE_DENY;
- } else {
+ }
+ else {
if (PyLong_Check(ret)) {
rc = _PyLong_AsInt(ret);
- if (rc == -1 && PyErr_Occurred())
+ if (rc == -1 && PyErr_Occurred()) {
+ if (_enable_callback_tracebacks)
+ PyErr_Print();
+ else
+ PyErr_Clear();
rc = SQLITE_DENY;
- } else {
+ }
+ }
+ else {
rc = SQLITE_DENY;
}
Py_DECREF(ret);
@@ -1190,9 +1240,8 @@ PyObject* pysqlite_connection_call(pysqlite_Connection* self, PyObject* args, Py
return NULL;
}
- if (!PyArg_ParseTuple(args, "O", &sql)) {
+ if (!PyArg_ParseTuple(args, "O", &sql))
return NULL;
- }
_pysqlite_drop_unused_statement_references(self);
@@ -1208,7 +1257,6 @@ PyObject* pysqlite_connection_call(pysqlite_Connection* self, PyObject* args, Py
statement->in_weakreflist = NULL;
rc = pysqlite_statement_create(statement, self, sql);
-
if (rc != SQLITE_OK) {
if (rc == PYSQLITE_TOO_MUCH_SQL) {
PyErr_SetString(pysqlite_Warning, "You can only execute one statement at a time.");
@@ -1218,25 +1266,23 @@ PyObject* pysqlite_connection_call(pysqlite_Connection* self, PyObject* args, Py
(void)pysqlite_statement_reset(statement);
_pysqlite_seterror(self->db, NULL);
}
+ goto error;
+ }
- Py_CLEAR(statement);
- } else {
- weakref = PyWeakref_NewRef((PyObject*)statement, NULL);
- if (!weakref) {
- Py_CLEAR(statement);
- goto error;
- }
-
- if (PyList_Append(self->statements, weakref) != 0) {
- Py_CLEAR(weakref);
- goto error;
- }
-
+ weakref = PyWeakref_NewRef((PyObject*)statement, NULL);
+ if (weakref == NULL)
+ goto error;
+ if (PyList_Append(self->statements, weakref) != 0) {
Py_DECREF(weakref);
+ goto error;
}
+ Py_DECREF(weakref);
-error:
return (PyObject*)statement;
+
+error:
+ Py_DECREF(statement);
+ return NULL;
}
PyObject* pysqlite_connection_execute(pysqlite_Connection* self, PyObject* args, PyObject* kwargs)
@@ -1244,7 +1290,6 @@ PyObject* pysqlite_connection_execute(pysqlite_Connection* self, PyObject* args,
PyObject* cursor = 0;
PyObject* result = 0;
PyObject* method = 0;
- _Py_IDENTIFIER(cursor);
cursor = _PyObject_CallMethodId((PyObject*)self, &PyId_cursor, "");
if (!cursor) {
@@ -1274,7 +1319,6 @@ PyObject* pysqlite_connection_executemany(pysqlite_Connection* self, PyObject* a
PyObject* cursor = 0;
PyObject* result = 0;
PyObject* method = 0;
- _Py_IDENTIFIER(cursor);
cursor = _PyObject_CallMethodId((PyObject*)self, &PyId_cursor, "");
if (!cursor) {
@@ -1304,7 +1348,6 @@ PyObject* pysqlite_connection_executescript(pysqlite_Connection* self, PyObject*
PyObject* cursor = 0;
PyObject* result = 0;
PyObject* method = 0;
- _Py_IDENTIFIER(cursor);
cursor = _PyObject_CallMethodId((PyObject*)self, &PyId_cursor, "");
if (!cursor) {
diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c
index 09c13d4..ce92af6 100644
--- a/Modules/_sqlite/cursor.c
+++ b/Modules/_sqlite/cursor.c
@@ -24,7 +24,6 @@
#include "cursor.h"
#include "module.h"
#include "util.h"
-#include "sqlitecompat.h"
PyObject* pysqlite_cursor_iternext(pysqlite_Cursor* self);
@@ -338,6 +337,11 @@ PyObject* _pysqlite_fetch_one_row(pysqlite_Cursor* self)
if (self->connection->text_factory == (PyObject*)&PyUnicode_Type) {
converted = PyUnicode_FromStringAndSize(val_str, nbytes);
if (!converted) {
+#ifdef Py_DEBUG
+ /* in debug mode, type_call() fails with an assertion
+ error if an exception is set when it is called */
+ PyErr_Clear();
+#endif
colname = sqlite3_column_name(self->statement->st, i);
if (!colname) {
colname = "<unknown column name>";
@@ -864,10 +868,15 @@ PyObject* pysqlite_cursor_iternext(pysqlite_Cursor *self)
}
next_row_tuple = self->next_row;
+ assert(next_row_tuple != NULL);
self->next_row = NULL;
if (self->row_factory != Py_None) {
next_row = PyObject_CallFunction(self->row_factory, "OO", self, next_row_tuple);
+ if (next_row == NULL) {
+ self->next_row = next_row_tuple;
+ return NULL;
+ }
Py_DECREF(next_row_tuple);
} else {
next_row = next_row_tuple;
@@ -884,6 +893,12 @@ PyObject* pysqlite_cursor_iternext(pysqlite_Cursor *self)
if (rc == SQLITE_ROW) {
self->next_row = _pysqlite_fetch_one_row(self);
+ if (self->next_row == NULL) {
+ (void)pysqlite_statement_reset(self->statement);
+ Py_DECREF(next_row);
+ _pysqlite_seterror(self->connection->db, NULL);
+ return NULL;
+ }
}
}
diff --git a/Modules/_sqlite/module.c b/Modules/_sqlite/module.c
index bea6d6a..7a7e860 100644
--- a/Modules/_sqlite/module.c
+++ b/Modules/_sqlite/module.c
@@ -50,19 +50,26 @@ static PyObject* module_connect(PyObject* self, PyObject* args, PyObject*
* C-level, so this code is redundant with the one in connection_init in
* connection.c and must always be copied from there ... */
- static char *kwlist[] = {"database", "timeout", "detect_types", "isolation_level", "check_same_thread", "factory", "cached_statements", NULL, NULL};
+ static char *kwlist[] = {
+ "database", "timeout", "detect_types", "isolation_level",
+ "check_same_thread", "factory", "cached_statements", "uri",
+ NULL
+ };
char* 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;
PyObject* result;
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|diOiOi", kwlist,
- &database, &timeout, &detect_types, &isolation_level, &check_same_thread, &factory, &cached_statements))
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|diOiOip", kwlist,
+ &database, &timeout, &detect_types,
+ &isolation_level, &check_same_thread,
+ &factory, &cached_statements, &uri))
{
return NULL;
}
@@ -77,7 +84,8 @@ static PyObject* module_connect(PyObject* self, PyObject* args, PyObject*
}
PyDoc_STRVAR(module_connect_doc,
-"connect(database[, timeout, isolation_level, detect_types, factory])\n\
+"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\
diff --git a/Modules/_sqlite/prepare_protocol.c b/Modules/_sqlite/prepare_protocol.c
index fc68874..f2c85f9 100644
--- a/Modules/_sqlite/prepare_protocol.c
+++ b/Modules/_sqlite/prepare_protocol.c
@@ -21,7 +21,6 @@
* 3. This notice may not be removed or altered from any source distribution.
*/
-#include "sqlitecompat.h"
#include "prepare_protocol.h"
int pysqlite_prepare_protocol_init(pysqlite_PrepareProtocol* self, PyObject* args, PyObject* kwargs)
diff --git a/Modules/_sqlite/row.c b/Modules/_sqlite/row.c
index b50658c..4a87a04 100644
--- a/Modules/_sqlite/row.c
+++ b/Modules/_sqlite/row.c
@@ -23,7 +23,6 @@
#include "row.h"
#include "cursor.h"
-#include "sqlitecompat.h"
void pysqlite_row_dealloc(pysqlite_Row* self)
{
@@ -68,7 +67,7 @@ PyObject* pysqlite_row_subscript(pysqlite_Row* self, PyObject* idx)
{
long _idx;
char* key;
- int nitems, i;
+ Py_ssize_t nitems, i;
char* compare_key;
char* p1;
@@ -89,7 +88,10 @@ PyObject* pysqlite_row_subscript(pysqlite_Row* self, PyObject* idx)
nitems = PyTuple_Size(self->description);
for (i = 0; i < nitems; i++) {
- compare_key = _PyUnicode_AsString(PyTuple_GET_ITEM(PyTuple_GET_ITEM(self->description, i), 0));
+ PyObject *obj;
+ obj = PyTuple_GET_ITEM(self->description, i);
+ obj = PyTuple_GET_ITEM(obj, 0);
+ compare_key = _PyUnicode_AsString(obj);
if (!compare_key) {
return NULL;
}
@@ -121,10 +123,12 @@ PyObject* pysqlite_row_subscript(pysqlite_Row* self, PyObject* idx)
PyErr_SetString(PyExc_IndexError, "No item with that key");
return NULL;
- } else if (PySlice_Check(idx)) {
+ }
+ else if (PySlice_Check(idx)) {
PyErr_SetString(PyExc_ValueError, "slices not implemented, yet");
return NULL;
- } else {
+ }
+ else {
PyErr_SetString(PyExc_IndexError, "Index must be int or string");
return NULL;
}
diff --git a/Modules/_sqlite/sqlitecompat.h b/Modules/_sqlite/sqlitecompat.h
deleted file mode 100644
index cf20f16..0000000
--- a/Modules/_sqlite/sqlitecompat.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/* sqlitecompat.h - compatibility macros
- *
- * Copyright (C) 2006-2010 Gerhard Häring <gh@ghaering.de>
- *
- * This file is part of pysqlite.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty. In no event will the authors be held liable for any damages
- * arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must not
- * claim that you wrote the original software. If you use this software
- * in a product, an acknowledgment in the product documentation would be
- * appreciated but is not required.
- * 2. Altered source versions must be plainly marked as such, and must not be
- * misrepresented as being the original software.
- * 3. This notice may not be removed or altered from any source distribution.
- */
-
-#include "Python.h"
-
-#ifndef PYSQLITE_COMPAT_H
-#define PYSQLITE_COMPAT_H
-
-/* define Py_ssize_t for pre-2.5 versions of Python */
-
-#if PY_VERSION_HEX < 0x02050000
-typedef int Py_ssize_t;
-typedef int (*lenfunc)(PyObject*);
-#endif
-
-
-/* define PyDict_CheckExact for pre-2.4 versions of Python */
-#ifndef PyDict_CheckExact
-#define PyDict_CheckExact(op) ((op)->ob_type == &PyDict_Type)
-#endif
-
-/* define Py_CLEAR for pre-2.4 versions of Python */
-#ifndef Py_CLEAR
-#define Py_CLEAR(op) \
- do { \
- if (op) { \
- PyObject *tmp = (PyObject *)(op); \
- (op) = NULL; \
- Py_DECREF(tmp); \
- } \
- } while (0)
-#endif
-
-#ifndef PyVarObject_HEAD_INIT
-#define PyVarObject_HEAD_INIT(type, size) \
- PyObject_HEAD_INIT(type) size,
-#endif
-
-#ifndef Py_TYPE
-#define Py_TYPE(ob) ((ob)->ob_type)
-#endif
-
-#endif
diff --git a/Modules/_sqlite/statement.c b/Modules/_sqlite/statement.c
index 471a067..66b4a52 100644
--- a/Modules/_sqlite/statement.c
+++ b/Modules/_sqlite/statement.c
@@ -27,7 +27,6 @@
#include "microprotocols.h"
#include "prepare_protocol.h"
#include "util.h"
-#include "sqlitecompat.h"
/* prototypes */
static int pysqlite_check_remaining_sql(const char* tail);
@@ -133,18 +132,26 @@ int pysqlite_statement_bind_parameter(pysqlite_Statement* self, int pos, PyObjec
break;
case TYPE_UNICODE:
string = _PyUnicode_AsStringAndSize(parameter, &buflen);
- if (string != NULL)
- rc = sqlite3_bind_text(self->st, pos, string, buflen, SQLITE_TRANSIENT);
- else
- rc = -1;
+ if (string == NULL)
+ return -1;
+ if (buflen > INT_MAX) {
+ PyErr_SetString(PyExc_OverflowError,
+ "string longer than INT_MAX bytes");
+ return -1;
+ }
+ rc = sqlite3_bind_text(self->st, pos, string, (int)buflen, SQLITE_TRANSIENT);
break;
case TYPE_BUFFER:
- if (PyObject_AsCharBuffer(parameter, &buffer, &buflen) == 0) {
- rc = sqlite3_bind_blob(self->st, pos, buffer, buflen, SQLITE_TRANSIENT);
- } else {
+ if (PyObject_AsCharBuffer(parameter, &buffer, &buflen) != 0) {
PyErr_SetString(PyExc_ValueError, "could not convert BLOB to buffer");
- rc = -1;
+ return -1;
+ }
+ if (buflen > INT_MAX) {
+ PyErr_SetString(PyExc_OverflowError,
+ "BLOB longer than INT_MAX bytes");
+ return -1;
}
+ rc = sqlite3_bind_blob(self->st, pos, buffer, buflen, SQLITE_TRANSIENT);
break;
case TYPE_UNKNOWN:
rc = -1;
@@ -177,7 +184,7 @@ void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* para
int i;
int rc;
int num_params_needed;
- int num_params;
+ Py_ssize_t num_params;
Py_BEGIN_ALLOW_THREADS
num_params_needed = sqlite3_bind_parameter_count(self->st);
@@ -193,7 +200,9 @@ void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* para
num_params = PySequence_Size(parameters);
}
if (num_params != num_params_needed) {
- PyErr_Format(pysqlite_ProgrammingError, "Incorrect number of bindings supplied. The current statement uses %d, and there are %d supplied.",
+ PyErr_Format(pysqlite_ProgrammingError,
+ "Incorrect number of bindings supplied. The current "
+ "statement uses %d, and there are %zd supplied.",
num_params_needed, num_params);
return;
}
@@ -249,7 +258,7 @@ void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* para
current_param = PyDict_GetItemString(parameters, binding_name);
Py_XINCREF(current_param);
} else {
- current_param = PyMapping_GetItemString(parameters, (char*)binding_name);
+ current_param = PyMapping_GetItemString(parameters, binding_name);
}
if (!current_param) {
PyErr_Format(pysqlite_ProgrammingError, "You did not supply a value for binding %d.", i);
diff --git a/Modules/_sqlite/util.c b/Modules/_sqlite/util.c
index d88bc3f..312fe3b 100644
--- a/Modules/_sqlite/util.c
+++ b/Modules/_sqlite/util.c
@@ -132,7 +132,7 @@ _pysqlite_long_from_int64(sqlite_int64 value)
}
# endif
#endif
- return PyLong_FromLong(value);
+ return PyLong_FromLong(Py_SAFE_DOWNCAST(value, sqlite_int64, long));
}
sqlite_int64