Updated to pysqlite 2.4.1. Documentation additions will come later.

This commit is contained in:
Gerhard Häring 2008-02-29 22:08:41 +00:00
parent 0e795e7d92
commit 1cc60ed214
17 changed files with 787 additions and 222 deletions

View file

@ -1,6 +1,6 @@
/* cursor.c - the cursor type
*
* Copyright (C) 2004-2006 Gerhard Häring <gh@ghaering.de>
* Copyright (C) 2004-2007 Gerhard Häring <gh@ghaering.de>
*
* This file is part of pysqlite.
*
@ -80,7 +80,7 @@ int pysqlite_cursor_init(pysqlite_Cursor* self, PyObject* args, PyObject* kwargs
if (!PyArg_ParseTuple(args, "O!", &pysqlite_ConnectionType, &connection))
{
return -1;
return -1;
}
Py_INCREF(connection);
@ -435,7 +435,7 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject*
if (multiple) {
/* executemany() */
if (!PyArg_ParseTuple(args, "OO", &operation, &second_argument)) {
return NULL;
return NULL;
}
if (!PyString_Check(operation) && !PyUnicode_Check(operation)) {
@ -457,7 +457,7 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject*
} else {
/* execute() */
if (!PyArg_ParseTuple(args, "O|O", &operation, &second_argument)) {
return NULL;
return NULL;
}
if (!PyString_Check(operation) && !PyUnicode_Check(operation)) {
@ -506,53 +506,11 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject*
operation_cstr = PyString_AsString(operation_bytestr);
}
/* reset description and rowcount */
/* reset description */
Py_DECREF(self->description);
Py_INCREF(Py_None);
self->description = Py_None;
Py_DECREF(self->rowcount);
self->rowcount = PyInt_FromLong(-1L);
if (!self->rowcount) {
goto error;
}
statement_type = detect_statement_type(operation_cstr);
if (self->connection->begin_statement) {
switch (statement_type) {
case STATEMENT_UPDATE:
case STATEMENT_DELETE:
case STATEMENT_INSERT:
case STATEMENT_REPLACE:
if (!self->connection->inTransaction) {
result = _pysqlite_connection_begin(self->connection);
if (!result) {
goto error;
}
Py_DECREF(result);
}
break;
case STATEMENT_OTHER:
/* it's a DDL statement or something similar
- we better COMMIT first so it works for all cases */
if (self->connection->inTransaction) {
result = pysqlite_connection_commit(self->connection, NULL);
if (!result) {
goto error;
}
Py_DECREF(result);
}
break;
case STATEMENT_SELECT:
if (multiple) {
PyErr_SetString(pysqlite_ProgrammingError,
"You cannot execute SELECT statements in executemany().");
goto error;
}
break;
}
}
func_args = PyTuple_New(1);
if (!func_args) {
goto error;
@ -590,6 +548,42 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject*
pysqlite_statement_reset(self->statement);
pysqlite_statement_mark_dirty(self->statement);
statement_type = detect_statement_type(operation_cstr);
if (self->connection->begin_statement) {
switch (statement_type) {
case STATEMENT_UPDATE:
case STATEMENT_DELETE:
case STATEMENT_INSERT:
case STATEMENT_REPLACE:
if (!self->connection->inTransaction) {
result = _pysqlite_connection_begin(self->connection);
if (!result) {
goto error;
}
Py_DECREF(result);
}
break;
case STATEMENT_OTHER:
/* it's a DDL statement or something similar
- we better COMMIT first so it works for all cases */
if (self->connection->inTransaction) {
result = pysqlite_connection_commit(self->connection, NULL);
if (!result) {
goto error;
}
Py_DECREF(result);
}
break;
case STATEMENT_SELECT:
if (multiple) {
PyErr_SetString(pysqlite_ProgrammingError,
"You cannot execute SELECT statements in executemany().");
goto error;
}
break;
}
}
while (1) {
parameters = PyIter_Next(parameters_iter);
if (!parameters) {
@ -603,11 +597,6 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject*
goto error;
}
if (pysqlite_build_row_cast_map(self) != 0) {
PyErr_SetString(pysqlite_OperationalError, "Error while building row_cast_map");
goto error;
}
/* Keep trying the SQL statement until the schema stops changing. */
while (1) {
/* Actually execute the SQL statement. */
@ -626,7 +615,8 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject*
continue;
} else {
/* If the database gave us an error, promote it to Python. */
_pysqlite_seterror(self->connection->db);
(void)pysqlite_statement_reset(self->statement);
_pysqlite_seterror(self->connection->db, NULL);
goto error;
}
} else {
@ -638,17 +628,23 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject*
PyErr_Clear();
}
}
_pysqlite_seterror(self->connection->db);
(void)pysqlite_statement_reset(self->statement);
_pysqlite_seterror(self->connection->db, NULL);
goto error;
}
}
if (rc == SQLITE_ROW || (rc == SQLITE_DONE && statement_type == STATEMENT_SELECT)) {
Py_BEGIN_ALLOW_THREADS
numcols = sqlite3_column_count(self->statement->st);
Py_END_ALLOW_THREADS
if (pysqlite_build_row_cast_map(self) != 0) {
PyErr_SetString(pysqlite_OperationalError, "Error while building row_cast_map");
goto error;
}
if (rc == SQLITE_ROW || (rc == SQLITE_DONE && statement_type == STATEMENT_SELECT)) {
if (self->description == Py_None) {
Py_BEGIN_ALLOW_THREADS
numcols = sqlite3_column_count(self->statement->st);
Py_END_ALLOW_THREADS
Py_DECREF(self->description);
self->description = PyTuple_New(numcols);
if (!self->description) {
@ -689,15 +685,11 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject*
case STATEMENT_DELETE:
case STATEMENT_INSERT:
case STATEMENT_REPLACE:
Py_BEGIN_ALLOW_THREADS
rowcount += (long)sqlite3_changes(self->connection->db);
Py_END_ALLOW_THREADS
Py_DECREF(self->rowcount);
self->rowcount = PyInt_FromLong(rowcount);
}
Py_DECREF(self->lastrowid);
if (statement_type == STATEMENT_INSERT) {
if (!multiple && statement_type == STATEMENT_INSERT) {
Py_BEGIN_ALLOW_THREADS
lastrowid = sqlite3_last_insert_rowid(self->connection->db);
Py_END_ALLOW_THREADS
@ -714,14 +706,27 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject*
}
error:
/* just to be sure (implicit ROLLBACKs with ON CONFLICT ROLLBACK/OR
* ROLLBACK could have happened */
#ifdef SQLITE_VERSION_NUMBER
#if SQLITE_VERSION_NUMBER >= 3002002
self->connection->inTransaction = !sqlite3_get_autocommit(self->connection->db);
#endif
#endif
Py_XDECREF(operation_bytestr);
Py_XDECREF(parameters);
Py_XDECREF(parameters_iter);
Py_XDECREF(parameters_list);
if (PyErr_Occurred()) {
Py_DECREF(self->rowcount);
self->rowcount = PyInt_FromLong(-1L);
return NULL;
} else {
Py_DECREF(self->rowcount);
self->rowcount = PyInt_FromLong(rowcount);
Py_INCREF(self);
return (PyObject*)self;
}
@ -748,7 +753,7 @@ PyObject* pysqlite_cursor_executescript(pysqlite_Cursor* self, PyObject* args)
int statement_completed = 0;
if (!PyArg_ParseTuple(args, "O", &script_obj)) {
return NULL;
return NULL;
}
if (!pysqlite_check_thread(self->connection) || !pysqlite_check_connection(self->connection)) {
@ -788,7 +793,7 @@ PyObject* pysqlite_cursor_executescript(pysqlite_Cursor* self, PyObject* args)
&statement,
&script_cstr);
if (rc != SQLITE_OK) {
_pysqlite_seterror(self->connection->db);
_pysqlite_seterror(self->connection->db, NULL);
goto error;
}
@ -796,17 +801,18 @@ PyObject* pysqlite_cursor_executescript(pysqlite_Cursor* self, PyObject* args)
rc = SQLITE_ROW;
while (rc == SQLITE_ROW) {
rc = _sqlite_step_with_busyhandler(statement, self->connection);
/* TODO: we probably need more error handling here */
}
if (rc != SQLITE_DONE) {
(void)sqlite3_finalize(statement);
_pysqlite_seterror(self->connection->db);
_pysqlite_seterror(self->connection->db, NULL);
goto error;
}
rc = sqlite3_finalize(statement);
if (rc != SQLITE_OK) {
_pysqlite_seterror(self->connection->db);
_pysqlite_seterror(self->connection->db, NULL);
goto error;
}
}
@ -864,8 +870,9 @@ PyObject* pysqlite_cursor_iternext(pysqlite_Cursor *self)
if (self->statement) {
rc = _sqlite_step_with_busyhandler(self->statement->st, self->connection);
if (rc != SQLITE_DONE && rc != SQLITE_ROW) {
(void)pysqlite_statement_reset(self->statement);
Py_DECREF(next_row);
_pysqlite_seterror(self->connection->db);
_pysqlite_seterror(self->connection->db, NULL);
return NULL;
}
@ -890,15 +897,17 @@ PyObject* pysqlite_cursor_fetchone(pysqlite_Cursor* self, PyObject* args)
return row;
}
PyObject* pysqlite_cursor_fetchmany(pysqlite_Cursor* self, PyObject* args)
PyObject* pysqlite_cursor_fetchmany(pysqlite_Cursor* self, PyObject* args, PyObject* kwargs)
{
static char *kwlist[] = {"size", NULL, NULL};
PyObject* row;
PyObject* list;
int maxrows = self->arraysize;
int counter = 0;
if (!PyArg_ParseTuple(args, "|i", &maxrows)) {
return NULL;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:fetchmany", kwlist, &maxrows)) {
return NULL;
}
list = PyList_New(0);
@ -992,7 +1001,7 @@ static PyMethodDef cursor_methods[] = {
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)pysqlite_cursor_fetchmany, METH_VARARGS,
{"fetchmany", (PyCFunction)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.")},