cpython/Modules/_sqlite/cursor.c
Georg Brandl f78e02b798 Merged revisions 63562,63570,63728,63734,63784,63788,63802,63817,63827,63839,63887,63975,63998 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r63562 | martin.v.loewis | 2008-05-23 17:06:50 +0200 (Fri, 23 May 2008) | 2 lines

  Patch #1722225: Support QNX 6.
........
  r63570 | trent.nelson | 2008-05-23 22:33:14 +0200 (Fri, 23 May 2008) | 1 line

  Introduce a user macro named $(externalsDir), which should point to the root directory of where all the external sources should live.  Developers can change this value if their external sources live elsewhere.  The default of '..\..' matches the current status quo.
........
  r63728 | gregory.p.smith | 2008-05-26 23:16:34 +0200 (Mon, 26 May 2008) | 4 lines

  Fix issue2589: there was a potential integer overflow leading to
  memory corruption on esoteric platforms and incorrect behavior on
  normal platforms.
........
  r63734 | gregory.p.smith | 2008-05-27 00:07:28 +0200 (Tue, 27 May 2008) | 3 lines

  Fix issue2588: Do not execute str[size-1] = '\0' when a 0 size is
  passed in.  (The assert won't prevent this in non-debug builds).
........
  r63784 | raymond.hettinger | 2008-05-29 10:38:23 +0200 (Thu, 29 May 2008) | 1 line

  Fix two typos.
........
  r63788 | facundo.batista | 2008-05-29 18:39:26 +0200 (Thu, 29 May 2008) | 6 lines


  Fixed the semantic of timeout for socket.create_connection and
  all the upper level libraries that use it, including urllib2.
  Added and fixed some tests, and changed docs correspondingly.
  Thanks to John J Lee for the patch and the pusing, :)
........
  r63802 | mark.dickinson | 2008-05-30 04:46:53 +0200 (Fri, 30 May 2008) | 2 lines

  Fix typo in testSum
........
  r63817 | raymond.hettinger | 2008-05-30 20:20:50 +0200 (Fri, 30 May 2008) | 8 lines

  * Mark intermedidate computes values (hi, lo, yr) as volatile.
  * Expand comments.
  * Swap variable names in the sum_exact code so that x and y
    are consistently chosen as the larger and smaller magnitude
    values respectively.
........
  r63827 | raymond.hettinger | 2008-05-31 05:24:31 +0200 (Sat, 31 May 2008) | 1 line

  Implement heapq in terms of less-than (to match list.sort()).
........
  r63839 | gerhard.haering | 2008-05-31 23:33:27 +0200 (Sat, 31 May 2008) | 2 lines

  Fixed rowcount for SELECT statements. They're -1 now (again), for better DB-API 2.0 compliance.
........
  r63887 | gregory.p.smith | 2008-06-02 06:05:52 +0200 (Mon, 02 Jun 2008) | 4 lines

  Fix issue 2782: be less strict about the format string type in strftime.
  Accept unicode and anything else ParseTuple "s#" can deal with.  This
  matches the time.strftime behavior.
........
  r63975 | neal.norwitz | 2008-06-06 06:47:01 +0200 (Fri, 06 Jun 2008) | 3 lines

  Aldo Cortesi confirmed this is still needed for OpenBSD 4.2 and 4.3.
  (I didn't regen configure, since I don't have a working autoconf.)
........
  r63998 | raymond.hettinger | 2008-06-06 23:47:51 +0200 (Fri, 06 Jun 2008) | 1 line

  Issue 3501: Make heapq support both __le__ and __lt__.
........
2008-06-10 17:40:04 +00:00

1107 lines
35 KiB
C

/* cursor.c - the cursor type
*
* Copyright (C) 2004-2007 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 "cursor.h"
#include "module.h"
#include "util.h"
#include "sqlitecompat.h"
/* used to decide wether to call PyLong_FromLong or PyLong_FromLongLong */
#ifndef INT32_MIN
#define INT32_MIN (-2147483647 - 1)
#endif
#ifndef INT32_MAX
#define INT32_MAX 2147483647
#endif
PyObject* pysqlite_cursor_iternext(pysqlite_Cursor* self);
static pysqlite_StatementKind detect_statement_type(const char* statement)
{
char buf[20];
const char* src;
char* dst;
src = statement;
/* skip over whitepace */
while (*src == '\r' || *src == '\n' || *src == ' ' || *src == '\t') {
src++;
}
if (*src == 0)
return STATEMENT_INVALID;
dst = buf;
*dst = 0;
while (isalpha(*src) && dst - buf < sizeof(buf) - 2) {
*dst++ = tolower(*src++);
}
*dst = 0;
if (!strcmp(buf, "select")) {
return STATEMENT_SELECT;
} else if (!strcmp(buf, "insert")) {
return STATEMENT_INSERT;
} else if (!strcmp(buf, "update")) {
return STATEMENT_UPDATE;
} else if (!strcmp(buf, "delete")) {
return STATEMENT_DELETE;
} else if (!strcmp(buf, "replace")) {
return STATEMENT_REPLACE;
} else {
return STATEMENT_OTHER;
}
}
int pysqlite_cursor_init(pysqlite_Cursor* self, PyObject* args, PyObject* kwargs)
{
pysqlite_Connection* connection;
if (!PyArg_ParseTuple(args, "O!", &pysqlite_ConnectionType, &connection))
{
return -1;
}
Py_INCREF(connection);
self->connection = connection;
self->statement = NULL;
self->next_row = NULL;
self->row_cast_map = PyList_New(0);
if (!self->row_cast_map) {
return -1;
}
Py_INCREF(Py_None);
self->description = Py_None;
Py_INCREF(Py_None);
self->lastrowid= Py_None;
self->arraysize = 1;
self->rowcount = -1L;
Py_INCREF(Py_None);
self->row_factory = Py_None;
if (!pysqlite_check_thread(self->connection)) {
return -1;
}
return 0;
}
void pysqlite_cursor_dealloc(pysqlite_Cursor* self)
{
int rc;
/* Reset the statement if the user has not closed the cursor */
if (self->statement) {
rc = pysqlite_statement_reset(self->statement);
Py_DECREF(self->statement);
}
Py_XDECREF(self->connection);
Py_XDECREF(self->row_cast_map);
Py_XDECREF(self->description);
Py_XDECREF(self->lastrowid);
Py_XDECREF(self->row_factory);
Py_XDECREF(self->next_row);
Py_TYPE(self)->tp_free((PyObject*)self);
}
PyObject* _pysqlite_get_converter(PyObject* key)
{
PyObject* upcase_key;
PyObject* retval;
upcase_key = PyObject_CallMethod(key, "upper", "");
if (!upcase_key) {
return NULL;
}
retval = PyDict_GetItem(converters, upcase_key);
Py_DECREF(upcase_key);
return retval;
}
int pysqlite_build_row_cast_map(pysqlite_Cursor* self)
{
int i;
const char* type_start = (const char*)-1;
const char* pos;
const char* colname;
const char* decltype;
PyObject* py_decltype;
PyObject* converter;
PyObject* key;
if (!self->connection->detect_types) {
return 0;
}
Py_XDECREF(self->row_cast_map);
self->row_cast_map = PyList_New(0);
for (i = 0; i < sqlite3_column_count(self->statement->st); i++) {
converter = NULL;
if (self->connection->detect_types & PARSE_COLNAMES) {
colname = sqlite3_column_name(self->statement->st, i);
if (colname) {
for (pos = colname; *pos != 0; pos++) {
if (*pos == '[') {
type_start = pos + 1;
} else if (*pos == ']' && type_start != (const char*)-1) {
key = PyUnicode_FromStringAndSize(type_start, pos - type_start);
if (!key) {
/* creating a string failed, but it is too complicated
* to propagate the error here, we just assume there is
* no converter and proceed */
break;
}
converter = _pysqlite_get_converter(key);
Py_DECREF(key);
break;
}
}
}
}
if (!converter && self->connection->detect_types & PARSE_DECLTYPES) {
decltype = sqlite3_column_decltype(self->statement->st, i);
if (decltype) {
for (pos = decltype;;pos++) {
/* Converter names are split at '(' and blanks.
* This allows 'INTEGER NOT NULL' to be treated as 'INTEGER' and
* 'NUMBER(10)' to be treated as 'NUMBER', for example.
* In other words, it will work as people expect it to work.*/
if (*pos == ' ' || *pos == '(' || *pos == 0) {
py_decltype = PyUnicode_FromStringAndSize(decltype, pos - decltype);
if (!py_decltype) {
return -1;
}
break;
}
}
converter = _pysqlite_get_converter(py_decltype);
Py_DECREF(py_decltype);
}
}
if (!converter) {
converter = Py_None;
}
if (PyList_Append(self->row_cast_map, converter) != 0) {
if (converter != Py_None) {
Py_DECREF(converter);
}
Py_XDECREF(self->row_cast_map);
self->row_cast_map = NULL;
return -1;
}
}
return 0;
}
PyObject* _pysqlite_build_column_name(const char* colname)
{
const char* pos;
if (!colname) {
Py_INCREF(Py_None);
return Py_None;
}
for (pos = colname;; pos++) {
if (*pos == 0 || *pos == '[') {
if ((*pos == '[') && (pos > colname) && (*(pos-1) == ' ')) {
pos--;
}
return PyUnicode_FromStringAndSize(colname, pos - colname);
}
}
}
PyObject* pysqlite_unicode_from_string(const char* val_str, int optimize)
{
return PyUnicode_FromString(val_str);
}
/*
* Returns a row from the currently active SQLite statement
*
* Precondidition:
* - sqlite3_step() has been called before and it returned SQLITE_ROW.
*/
PyObject* _pysqlite_fetch_one_row(pysqlite_Cursor* self)
{
int i, numcols;
PyObject* row;
PyObject* item = NULL;
int coltype;
PY_LONG_LONG intval;
PyObject* converter;
PyObject* converted;
Py_ssize_t nbytes;
PyObject* buffer;
const char* val_str;
char buf[200];
const char* colname;
PyObject* buf_bytes;
PyObject* error_obj;
Py_BEGIN_ALLOW_THREADS
numcols = sqlite3_data_count(self->statement->st);
Py_END_ALLOW_THREADS
row = PyTuple_New(numcols);
if (!row) {
return NULL;
}
for (i = 0; i < numcols; i++) {
if (self->connection->detect_types) {
converter = PyList_GetItem(self->row_cast_map, i);
if (!converter) {
converter = Py_None;
}
} else {
converter = Py_None;
}
if (converter != Py_None) {
nbytes = sqlite3_column_bytes(self->statement->st, i);
val_str = (const char*)sqlite3_column_blob(self->statement->st, i);
if (!val_str) {
Py_INCREF(Py_None);
converted = Py_None;
} else {
item = PyBytes_FromStringAndSize(val_str, nbytes);
if (!item) {
return NULL;
}
converted = PyObject_CallFunction(converter, "O", item);
Py_DECREF(item);
if (!converted) {
break;
}
}
} else {
Py_BEGIN_ALLOW_THREADS
coltype = sqlite3_column_type(self->statement->st, i);
Py_END_ALLOW_THREADS
if (coltype == SQLITE_NULL) {
Py_INCREF(Py_None);
converted = Py_None;
} else if (coltype == SQLITE_INTEGER) {
intval = sqlite3_column_int64(self->statement->st, i);
if (intval < INT32_MIN || intval > INT32_MAX) {
converted = PyLong_FromLongLong(intval);
} else {
converted = PyLong_FromLong((long)intval);
}
} else if (coltype == SQLITE_FLOAT) {
converted = PyFloat_FromDouble(sqlite3_column_double(self->statement->st, i));
} else if (coltype == SQLITE_TEXT) {
val_str = (const char*)sqlite3_column_text(self->statement->st, i);
if ((self->connection->text_factory == (PyObject*)&PyUnicode_Type)
|| (self->connection->text_factory == pysqlite_OptimizedUnicode)) {
converted = pysqlite_unicode_from_string(val_str,
self->connection->text_factory == pysqlite_OptimizedUnicode ? 1 : 0);
if (!converted) {
colname = sqlite3_column_name(self->statement->st, i);
if (!colname) {
colname = "<unknown column name>";
}
PyOS_snprintf(buf, sizeof(buf) - 1, "Could not decode to UTF-8 column '%s' with text '%s'",
colname , val_str);
buf_bytes = PyByteArray_FromStringAndSize(buf, strlen(buf));
if (!buf_bytes) {
PyErr_SetString(pysqlite_OperationalError, "Could not decode to UTF-8");
} else {
error_obj = PyUnicode_FromEncodedObject(buf_bytes, "ascii", "replace");
if (!error_obj) {
PyErr_SetString(pysqlite_OperationalError, "Could not decode to UTF-8");
} else {
PyErr_SetObject(pysqlite_OperationalError, error_obj);
Py_DECREF(error_obj);
}
Py_DECREF(buf_bytes);
}
}
} else if (self->connection->text_factory == (PyObject*)&PyBytes_Type) {
converted = PyBytes_FromString(val_str);
} else if (self->connection->text_factory == (PyObject*)&PyByteArray_Type) {
converted = PyByteArray_FromStringAndSize(val_str, strlen(val_str));
} else {
converted = PyObject_CallFunction(self->connection->text_factory, "y", val_str);
}
} else {
/* coltype == SQLITE_BLOB */
nbytes = sqlite3_column_bytes(self->statement->st, i);
buffer = PyBytes_FromStringAndSize(
sqlite3_column_blob(self->statement->st, i), nbytes);
if (!buffer) {
break;
}
converted = buffer;
}
}
if (converted) {
PyTuple_SetItem(row, i, converted);
} else {
Py_INCREF(Py_None);
PyTuple_SetItem(row, i, Py_None);
}
}
if (PyErr_Occurred()) {
Py_DECREF(row);
row = NULL;
}
return row;
}
PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* args)
{
PyObject* operation;
const char* operation_cstr;
Py_ssize_t operation_len;
PyObject* parameters_list = NULL;
PyObject* parameters_iter = NULL;
PyObject* parameters = NULL;
int i;
int rc;
PyObject* func_args;
PyObject* result;
int numcols;
PY_LONG_LONG lastrowid;
int statement_type;
PyObject* descriptor;
PyObject* second_argument = NULL;
int allow_8bit_chars;
if (!pysqlite_check_thread(self->connection) || !pysqlite_check_connection(self->connection)) {
return NULL;
}
/* Make shooting yourself in the foot with not utf-8 decodable 8-bit-strings harder */
allow_8bit_chars = ((self->connection->text_factory != (PyObject*)&PyUnicode_Type) &&
(self->connection->text_factory != (PyObject*)&PyUnicode_Type && pysqlite_OptimizedUnicode));
Py_XDECREF(self->next_row);
self->next_row = NULL;
if (multiple) {
/* executemany() */
if (!PyArg_ParseTuple(args, "OO", &operation, &second_argument)) {
return NULL;
}
if (!PyUnicode_Check(operation)) {
PyErr_SetString(PyExc_ValueError, "operation parameter must be str");
return NULL;
}
if (PyIter_Check(second_argument)) {
/* iterator */
Py_INCREF(second_argument);
parameters_iter = second_argument;
} else {
/* sequence */
parameters_iter = PyObject_GetIter(second_argument);
if (!parameters_iter) {
return NULL;
}
}
} else {
/* execute() */
if (!PyArg_ParseTuple(args, "O|O", &operation, &second_argument)) {
return NULL;
}
if (!PyUnicode_Check(operation)) {
PyErr_SetString(PyExc_ValueError, "operation parameter must be str");
return NULL;
}
parameters_list = PyList_New(0);
if (!parameters_list) {
return NULL;
}
if (second_argument == NULL) {
second_argument = PyTuple_New(0);
if (!second_argument) {
goto error;
}
} else {
Py_INCREF(second_argument);
}
if (PyList_Append(parameters_list, second_argument) != 0) {
Py_DECREF(second_argument);
goto error;
}
Py_DECREF(second_argument);
parameters_iter = PyObject_GetIter(parameters_list);
if (!parameters_iter) {
goto error;
}
}
if (self->statement != NULL) {
/* There is an active statement */
rc = pysqlite_statement_reset(self->statement);
}
operation_cstr = PyUnicode_AsStringAndSize(operation, &operation_len);
if (operation == NULL)
goto error;
/* reset description and rowcount */
Py_DECREF(self->description);
Py_INCREF(Py_None);
self->description = Py_None;
self->rowcount = -1L;
func_args = PyTuple_New(1);
if (!func_args) {
goto error;
}
Py_INCREF(operation);
if (PyTuple_SetItem(func_args, 0, operation) != 0) {
goto error;
}
if (self->statement) {
(void)pysqlite_statement_reset(self->statement);
Py_DECREF(self->statement);
}
self->statement = (pysqlite_Statement*)pysqlite_cache_get(self->connection->statement_cache, func_args);
Py_DECREF(func_args);
if (!self->statement) {
goto error;
}
if (self->statement->in_use) {
Py_DECREF(self->statement);
self->statement = PyObject_New(pysqlite_Statement, &pysqlite_StatementType);
if (!self->statement) {
goto error;
}
rc = pysqlite_statement_create(self->statement, self->connection, operation);
if (rc != SQLITE_OK) {
self->statement = 0;
goto error;
}
}
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;
}
}
func_args = PyTuple_New(1);
if (!func_args) {
goto error;
}
Py_INCREF(operation);
if (PyTuple_SetItem(func_args, 0, operation) != 0) {
goto error;
}
if (self->statement) {
(void)pysqlite_statement_reset(self->statement);
Py_DECREF(self->statement);
}
self->statement = (pysqlite_Statement*)pysqlite_cache_get(self->connection->statement_cache, func_args);
Py_DECREF(func_args);
if (!self->statement) {
goto error;
}
if (self->statement->in_use) {
Py_DECREF(self->statement);
self->statement = PyObject_New(pysqlite_Statement, &pysqlite_StatementType);
if (!self->statement) {
goto error;
}
rc = pysqlite_statement_create(self->statement, self->connection, operation);
if (rc != SQLITE_OK) {
self->statement = 0;
goto error;
}
}
pysqlite_statement_reset(self->statement);
pysqlite_statement_mark_dirty(self->statement);
while (1) {
parameters = PyIter_Next(parameters_iter);
if (!parameters) {
break;
}
pysqlite_statement_mark_dirty(self->statement);
pysqlite_statement_bind_parameters(self->statement, parameters, allow_8bit_chars);
if (PyErr_Occurred()) {
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. */
rc = _sqlite_step_with_busyhandler(self->statement->st, self->connection);
if (rc == SQLITE_DONE || rc == SQLITE_ROW) {
/* If it worked, let's get out of the loop */
break;
}
/* Something went wrong. Re-set the statement and try again. */
rc = pysqlite_statement_reset(self->statement);
if (rc == SQLITE_SCHEMA) {
/* If this was a result of the schema changing, let's try
again. */
rc = pysqlite_statement_recompile(self->statement, parameters);
if (rc == SQLITE_OK) {
continue;
} else {
/* If the database gave us an error, promote it to Python. */
(void)pysqlite_statement_reset(self->statement);
_pysqlite_seterror(self->connection->db, NULL);
goto error;
}
} else {
if (PyErr_Occurred()) {
/* there was an error that occurred in a user-defined callback */
if (_enable_callback_tracebacks) {
PyErr_Print();
} else {
PyErr_Clear();
}
}
(void)pysqlite_statement_reset(self->statement);
_pysqlite_seterror(self->connection->db, NULL);
goto error;
}
}
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)) {
Py_BEGIN_ALLOW_THREADS
numcols = sqlite3_column_count(self->statement->st);
Py_END_ALLOW_THREADS
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) {
goto error;
}
for (i = 0; i < numcols; i++) {
descriptor = PyTuple_New(7);
if (!descriptor) {
goto error;
}
PyTuple_SetItem(descriptor, 0, _pysqlite_build_column_name(sqlite3_column_name(self->statement->st, i)));
Py_INCREF(Py_None); PyTuple_SetItem(descriptor, 1, Py_None);
Py_INCREF(Py_None); PyTuple_SetItem(descriptor, 2, Py_None);
Py_INCREF(Py_None); PyTuple_SetItem(descriptor, 3, Py_None);
Py_INCREF(Py_None); PyTuple_SetItem(descriptor, 4, Py_None);
Py_INCREF(Py_None); PyTuple_SetItem(descriptor, 5, Py_None);
Py_INCREF(Py_None); PyTuple_SetItem(descriptor, 6, Py_None);
PyTuple_SetItem(self->description, i, descriptor);
}
}
}
if (rc == SQLITE_ROW) {
if (multiple) {
PyErr_SetString(pysqlite_ProgrammingError, "executemany() can only execute DML statements.");
goto error;
}
self->next_row = _pysqlite_fetch_one_row(self);
} else if (rc == SQLITE_DONE && !multiple) {
pysqlite_statement_reset(self->statement);
Py_DECREF(self->statement);
self->statement = 0;
}
switch (statement_type) {
case STATEMENT_UPDATE:
case STATEMENT_DELETE:
case STATEMENT_INSERT:
case STATEMENT_REPLACE:
if (self->rowcount == -1L) {
self->rowcount = 0L;
}
self->rowcount += (long)sqlite3_changes(self->connection->db);
}
Py_DECREF(self->lastrowid);
if (!multiple && statement_type == STATEMENT_INSERT) {
Py_BEGIN_ALLOW_THREADS
lastrowid = sqlite3_last_insert_rowid(self->connection->db);
Py_END_ALLOW_THREADS
self->lastrowid = PyLong_FromLong((long)lastrowid);
} else {
Py_INCREF(Py_None);
self->lastrowid = Py_None;
}
if (multiple) {
rc = pysqlite_statement_reset(self->statement);
}
Py_XDECREF(parameters);
}
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(parameters);
Py_XDECREF(parameters_iter);
Py_XDECREF(parameters_list);
if (PyErr_Occurred()) {
self->rowcount = -1L;
return NULL;
} else {
Py_INCREF(self);
return (PyObject*)self;
}
}
PyObject* pysqlite_cursor_execute(pysqlite_Cursor* self, PyObject* args)
{
return _pysqlite_query_execute(self, 0, args);
}
PyObject* pysqlite_cursor_executemany(pysqlite_Cursor* self, PyObject* args)
{
return _pysqlite_query_execute(self, 1, args);
}
PyObject* pysqlite_cursor_executescript(pysqlite_Cursor* self, PyObject* args)
{
PyObject* script_obj;
PyObject* script_str = NULL;
const char* script_cstr;
sqlite3_stmt* statement;
int rc;
PyObject* result;
int statement_completed = 0;
if (!PyArg_ParseTuple(args, "O", &script_obj)) {
return NULL;
}
if (!pysqlite_check_thread(self->connection) || !pysqlite_check_connection(self->connection)) {
return NULL;
}
if (PyUnicode_Check(script_obj)) {
script_cstr = PyUnicode_AsString(script_obj);
if (!script_cstr) {
return NULL;
}
} else {
PyErr_SetString(PyExc_ValueError, "script argument must be unicode.");
return NULL;
}
/* commit first */
result = pysqlite_connection_commit(self->connection, NULL);
if (!result) {
goto error;
}
Py_DECREF(result);
while (1) {
if (!sqlite3_complete(script_cstr)) {
break;
}
statement_completed = 1;
rc = sqlite3_prepare(self->connection->db,
script_cstr,
-1,
&statement,
&script_cstr);
if (rc != SQLITE_OK) {
_pysqlite_seterror(self->connection->db, NULL);
goto error;
}
/* execute statement, and ignore results of SELECT statements */
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, NULL);
goto error;
}
rc = sqlite3_finalize(statement);
if (rc != SQLITE_OK) {
_pysqlite_seterror(self->connection->db, NULL);
goto error;
}
}
error:
Py_XDECREF(script_str);
if (!statement_completed) {
PyErr_SetString(pysqlite_ProgrammingError, "you did not provide a complete SQL statement");
}
if (PyErr_Occurred()) {
return NULL;
} else {
Py_INCREF(self);
return (PyObject*)self;
}
}
PyObject* pysqlite_cursor_getiter(pysqlite_Cursor *self)
{
Py_INCREF(self);
return (PyObject*)self;
}
PyObject* pysqlite_cursor_iternext(pysqlite_Cursor *self)
{
PyObject* next_row_tuple;
PyObject* next_row;
int rc;
if (!pysqlite_check_thread(self->connection) || !pysqlite_check_connection(self->connection)) {
return NULL;
}
if (!self->next_row) {
if (self->statement) {
(void)pysqlite_statement_reset(self->statement);
Py_DECREF(self->statement);
self->statement = NULL;
}
return NULL;
}
next_row_tuple = self->next_row;
self->next_row = NULL;
if (self->row_factory != Py_None) {
next_row = PyObject_CallFunction(self->row_factory, "OO", self, next_row_tuple);
Py_DECREF(next_row_tuple);
} else {
next_row = next_row_tuple;
}
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, NULL);
return NULL;
}
if (rc == SQLITE_ROW) {
self->next_row = _pysqlite_fetch_one_row(self);
}
}
return next_row;
}
PyObject* pysqlite_cursor_fetchone(pysqlite_Cursor* self, PyObject* args)
{
PyObject* row;
row = pysqlite_cursor_iternext(self);
if (!row && !PyErr_Occurred()) {
Py_INCREF(Py_None);
return Py_None;
}
return row;
}
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_ParseTupleAndKeywords(args, kwargs, "|i:fetchmany", kwlist, &maxrows)) {
return NULL;
}
list = PyList_New(0);
if (!list) {
return NULL;
}
/* just make sure we enter the loop */
row = Py_None;
while (row) {
row = pysqlite_cursor_iternext(self);
if (row) {
PyList_Append(list, row);
Py_DECREF(row);
} else {
break;
}
if (++counter == maxrows) {
break;
}
}
if (PyErr_Occurred()) {
Py_DECREF(list);
return NULL;
} else {
return list;
}
}
PyObject* pysqlite_cursor_fetchall(pysqlite_Cursor* self, PyObject* args)
{
PyObject* row;
PyObject* list;
list = PyList_New(0);
if (!list) {
return NULL;
}
/* just make sure we enter the loop */
row = (PyObject*)Py_None;
while (row) {
row = pysqlite_cursor_iternext(self);
if (row) {
PyList_Append(list, row);
Py_DECREF(row);
}
}
if (PyErr_Occurred()) {
Py_DECREF(list);
return NULL;
} else {
return list;
}
}
PyObject* pysqlite_noop(pysqlite_Connection* self, PyObject* args)
{
/* don't care, return None */
Py_INCREF(Py_None);
return Py_None;
}
PyObject* pysqlite_cursor_close(pysqlite_Cursor* self, PyObject* args)
{
if (!pysqlite_check_thread(self->connection) || !pysqlite_check_connection(self->connection)) {
return NULL;
}
if (self->statement) {
(void)pysqlite_statement_reset(self->statement);
Py_DECREF(self->statement);
self->statement = 0;
}
Py_INCREF(Py_None);
return Py_None;
}
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)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.")},
{NULL, NULL}
};
static struct PyMemberDef cursor_members[] =
{
{"connection", T_OBJECT, offsetof(pysqlite_Cursor, connection), READONLY},
{"description", T_OBJECT, offsetof(pysqlite_Cursor, description), READONLY},
{"arraysize", T_INT, offsetof(pysqlite_Cursor, arraysize), 0},
{"lastrowid", T_OBJECT, offsetof(pysqlite_Cursor, lastrowid), READONLY},
{"rowcount", T_LONG, offsetof(pysqlite_Cursor, rowcount), READONLY},
{"row_factory", T_OBJECT, offsetof(pysqlite_Cursor, row_factory), 0},
{NULL}
};
static char cursor_doc[] =
PyDoc_STR("SQLite database cursor class.");
PyTypeObject pysqlite_CursorType = {
PyVarObject_HEAD_INIT(NULL, 0)
MODULE_NAME ".Cursor", /* tp_name */
sizeof(pysqlite_Cursor), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)pysqlite_cursor_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
cursor_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
(getiterfunc)pysqlite_cursor_getiter, /* tp_iter */
(iternextfunc)pysqlite_cursor_iternext, /* tp_iternext */
cursor_methods, /* tp_methods */
cursor_members, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)pysqlite_cursor_init, /* tp_init */
0, /* tp_alloc */
0, /* tp_new */
0 /* tp_free */
};
extern int pysqlite_cursor_setup_types(void)
{
pysqlite_CursorType.tp_new = PyType_GenericNew;
return PyType_Ready(&pysqlite_CursorType);
}