Mercurial > cpython-lru_cache-weakref
diff Modules/_sqlite/cursor.c @ 46178:e06e08e8fdce
Bring sqlite3 module up-to-date with what's now in 2.6. Almost. I intentionally
left out the stuff about creating a connection object from a APSW connection.
| author | Gerhard Häring <gh@ghaering.de> |
|---|---|
| date | Sat, 29 Mar 2008 00:45:29 +0000 |
| parents | fc6f90545cb4 |
| children | 51eff2fd9527 |
line wrap: on
line diff
--- a/Modules/_sqlite/cursor.c Sat Mar 29 00:41:18 2008 +0000 +++ b/Modules/_sqlite/cursor.c Sat Mar 29 00:45:29 2008 +0000 @@ -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 @@ if (!PyArg_ParseTuple(args, "O!", &pysqlite_ConnectionType, &connection)) { - return -1; + return -1; } Py_INCREF(connection); @@ -255,23 +255,6 @@ PyObject* pysqlite_unicode_from_string(const char* val_str, int optimize) { - const char* check; - int is_ascii = 0; - - if (optimize) { - is_ascii = 1; - - check = val_str; - while (*check) { - if (*check & 0x80) { - is_ascii = 0; - break; - } - - check++; - } - } - return PyUnicode_FromString(val_str); } @@ -432,10 +415,14 @@ PyObject* descriptor; PyObject* second_argument = NULL; long rowcount = 0; + 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; @@ -443,7 +430,7 @@ if (multiple) { /* executemany() */ if (!PyArg_ParseTuple(args, "OO", &operation, &second_argument)) { - return NULL; + return NULL; } if (!PyUnicode_Check(operation)) { @@ -465,7 +452,7 @@ } else { /* execute() */ if (!PyArg_ParseTuple(args, "O|O", &operation, &second_argument)) { - return NULL; + return NULL; } if (!PyUnicode_Check(operation)) { @@ -507,17 +494,48 @@ if (operation == NULL) goto error; - /* reset description and rowcount */ + /* reset description */ Py_DECREF(self->description); Py_INCREF(Py_None); self->description = Py_None; - Py_DECREF(self->rowcount); - self->rowcount = PyLong_FromLong(-1L); - if (!self->rowcount) { + 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) { @@ -599,7 +617,7 @@ pysqlite_statement_mark_dirty(self->statement); - pysqlite_statement_bind_parameters(self->statement, parameters); + pysqlite_statement_bind_parameters(self->statement, parameters, allow_8bit_chars); if (PyErr_Occurred()) { goto error; } @@ -627,7 +645,8 @@ 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 { @@ -639,17 +658,27 @@ PyErr_Clear(); } } - _pysqlite_seterror(self->connection->db); + (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) { @@ -690,15 +719,11 @@ 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 = PyLong_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 @@ -715,13 +740,26 @@ } 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()) { + Py_DECREF(self->rowcount); + self->rowcount = PyLong_FromLong(-1L); return NULL; } else { + Py_DECREF(self->rowcount); + self->rowcount = PyLong_FromLong(rowcount); + Py_INCREF(self); return (PyObject*)self; } @@ -748,7 +786,7 @@ 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)) { @@ -784,7 +822,7 @@ &statement, &script_cstr); if (rc != SQLITE_OK) { - _pysqlite_seterror(self->connection->db); + _pysqlite_seterror(self->connection->db, NULL); goto error; } @@ -792,17 +830,18 @@ 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; } } @@ -860,8 +899,9 @@ 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; } @@ -886,15 +926,17 @@ 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); @@ -988,7 +1030,7 @@ 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.")},
