diff --git a/Doc/includes/sqlite3/text_factory.py b/Doc/includes/sqlite3/text_factory.py index 22c2970..bdffd36 100644 --- a/Doc/includes/sqlite3/text_factory.py +++ b/Doc/includes/sqlite3/text_factory.py @@ -30,14 +30,3 @@ cur.execute("select ?", ("this is latin1 and would normally create errors" + "\xe4\xf6\xfc".encode("latin1"),)) row = cur.fetchone() assert type(row[0]) == str - -# sqlite3 offers a built-in optimized text_factory that will return bytestring -# objects, if the data is in ASCII only, and otherwise return unicode objects -con.text_factory = sqlite3.OptimizedUnicode -cur.execute("select ?", (AUSTRIA,)) -row = cur.fetchone() -assert type(row[0]) == str - -cur.execute("select ?", ("Germany",)) -row = cur.fetchone() -assert type(row[0]) == str diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst index f3acdc5..a1f3112 100644 --- a/Doc/library/sqlite3.rst +++ b/Doc/library/sqlite3.rst @@ -436,10 +436,6 @@ Connection Objects :mod:`sqlite3` module will return Unicode objects for ``TEXT``. If you want to return bytestrings instead, you can set it to :class:`bytes`. - For efficiency reasons, there's also a way to return :class:`str` objects - only for non-ASCII data, and :class:`bytes` otherwise. To activate it, set - this attribute to :const:`sqlite3.OptimizedUnicode`. - You can also set it to any other callable that accepts a single bytestring parameter and returns the resulting object. @@ -447,6 +443,14 @@ Connection Objects .. literalinclude:: ../includes/sqlite3/text_factory.py + .. note:: + + In Python 2.x, setting this attribute to + :const:`sqlite3.OptimizedUnicode` caused Unicode objects to be + returned for non-ASCII data and bytestrings to be returned for + ASCII data. In Python 3.x, :const:`sqlite3.OptimizedUnicode` has + no effect and :class:`str` objects are always returned. + .. attribute:: Connection.total_changes diff --git a/Lib/sqlite3/test/factory.py b/Lib/sqlite3/test/factory.py index 5569585..9e833ae 100644 --- a/Lib/sqlite3/test/factory.py +++ b/Lib/sqlite3/test/factory.py @@ -178,6 +178,8 @@ class TextFactoryTests(unittest.TestCase): self.assertTrue(row[0].endswith("reich"), "column must contain original data") def CheckOptimizedUnicode(self): + # In py3k, str objects are always returned when text_factory + # is OptimizedUnicode self.con.text_factory = sqlite.OptimizedUnicode austria = "Österreich" germany = "Deutchland" diff --git a/Modules/_sqlite/connection.h b/Modules/_sqlite/connection.h index c8e2f7c..f534409 100644 --- a/Modules/_sqlite/connection.h +++ b/Modules/_sqlite/connection.h @@ -83,8 +83,8 @@ typedef struct /* Determines how bytestrings from SQLite are converted to Python objects: * - PyUnicode_Type: Python Unicode objects are constructed from UTF-8 bytestrings - * - OptimizedUnicode: Like before, but for ASCII data, only PyStrings are created. - * - PyBytes_Type: PyStrings are created as-is. + * - OptimizedUnicode: Alias for PyUnicode_Type (for backwards compatiblity) + * - PyBytes_Type: PyStrings are created as-is. * - Any custom callable: Any object returned from the callable called with the bytestring * as single parameter. */ diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c index 99a8612..8a56d3c 100644 --- a/Modules/_sqlite/cursor.c +++ b/Modules/_sqlite/cursor.c @@ -267,11 +267,6 @@ PyObject* _pysqlite_build_column_name(const char* colname) } } -PyObject* pysqlite_unicode_from_string(const char* val_str, Py_ssize_t size, int optimize) -{ - return PyUnicode_FromStringAndSize(val_str, size); -} - /* * Returns a row from the currently active SQLite statement * @@ -355,12 +350,8 @@ PyObject* _pysqlite_fetch_one_row(pysqlite_Cursor* self) } else if (coltype == SQLITE_TEXT) { val_str = (const char*)sqlite3_column_text(self->statement->st, i); nbytes = sqlite3_column_bytes(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, nbytes, - self->connection->text_factory == pysqlite_OptimizedUnicode ? 1 : 0); - + if (self->connection->text_factory == (PyObject*)&PyUnicode_Type) { + converted = PyUnicode_FromStringAndSize(val_str, nbytes); if (!converted) { colname = sqlite3_column_name(self->statement->st, i); if (!colname) { @@ -459,7 +450,6 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* int statement_type; PyObject* descriptor; PyObject* second_argument = NULL; - int allow_8bit_chars; if (!check_cursor(self)) { goto error; @@ -468,10 +458,6 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* self->locked = 1; self->reset = 0; - /* 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 != pysqlite_OptimizedUnicode)); - Py_XDECREF(self->next_row); self->next_row = NULL; @@ -630,7 +616,7 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* pysqlite_statement_mark_dirty(self->statement); - pysqlite_statement_bind_parameters(self->statement, parameters, allow_8bit_chars); + pysqlite_statement_bind_parameters(self->statement, parameters); if (PyErr_Occurred()) { goto error; } diff --git a/Modules/_sqlite/module.c b/Modules/_sqlite/module.c index 406d787..5e5ea81 100644 --- a/Modules/_sqlite/module.c +++ b/Modules/_sqlite/module.c @@ -37,7 +37,7 @@ PyObject* pysqlite_Error, *pysqlite_Warning, *pysqlite_InterfaceError, *pysqlite_DatabaseError, *pysqlite_InternalError, *pysqlite_OperationalError, *pysqlite_ProgrammingError, - *pysqlite_IntegrityError, *pysqlite_DataError, *pysqlite_NotSupportedError, *pysqlite_OptimizedUnicode; + *pysqlite_IntegrityError, *pysqlite_DataError, *pysqlite_NotSupportedError; PyObject* converters; int _enable_callback_tracebacks; @@ -407,13 +407,9 @@ PyMODINIT_FUNC PyInit__sqlite3(void) } PyDict_SetItemString(dict, "NotSupportedError", pysqlite_NotSupportedError); - /* We just need "something" unique for pysqlite_OptimizedUnicode. It does not really - * need to be a string subclass. Just anything that can act as a special - * marker for us. So I pulled PyCell_Type out of my magic hat. - */ - Py_INCREF((PyObject*)&PyCell_Type); - pysqlite_OptimizedUnicode = (PyObject*)&PyCell_Type; - PyDict_SetItemString(dict, "OptimizedUnicode", pysqlite_OptimizedUnicode); + /* OptimizedUnicode is an alias for str for backwards compatibility */ + Py_INCREF((PyObject*)&PyUnicode_Type); + PyDict_SetItemString(dict, "OptimizedUnicode", (PyObject*)&PyUnicode_Type); /* Set integer constants */ for (i = 0; _int_constants[i].constant_name != 0; i++) { diff --git a/Modules/_sqlite/module.h b/Modules/_sqlite/module.h index 0eddb67..b51724b 100644 --- a/Modules/_sqlite/module.h +++ b/Modules/_sqlite/module.h @@ -38,8 +38,6 @@ extern PyObject* pysqlite_IntegrityError; extern PyObject* pysqlite_DataError; extern PyObject* pysqlite_NotSupportedError; -extern PyObject* pysqlite_OptimizedUnicode; - /* the functions time.time() and time.sleep() */ extern PyObject* time_time; extern PyObject* time_sleep; diff --git a/Modules/_sqlite/statement.c b/Modules/_sqlite/statement.c index cc9c310..9884860 100644 --- a/Modules/_sqlite/statement.c +++ b/Modules/_sqlite/statement.c @@ -87,7 +87,7 @@ int pysqlite_statement_create(pysqlite_Statement* self, pysqlite_Connection* con return rc; } -int pysqlite_statement_bind_parameter(pysqlite_Statement* self, int pos, PyObject* parameter, int allow_8bit_chars) +int pysqlite_statement_bind_parameter(pysqlite_Statement* self, int pos, PyObject* parameter) { int rc = SQLITE_OK; PY_LONG_LONG longlongval; @@ -166,7 +166,7 @@ static int _need_adapt(PyObject* obj) } } -void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* parameters, int allow_8bit_chars) +void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* parameters) { PyObject* current_param; PyObject* adapted; @@ -220,7 +220,7 @@ void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* para } } - rc = pysqlite_statement_bind_parameter(self, i + 1, adapted, allow_8bit_chars); + rc = pysqlite_statement_bind_parameter(self, i + 1, adapted); Py_DECREF(adapted); if (rc != SQLITE_OK) { @@ -265,7 +265,7 @@ void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* para } } - rc = pysqlite_statement_bind_parameter(self, i, adapted, allow_8bit_chars); + rc = pysqlite_statement_bind_parameter(self, i, adapted); Py_DECREF(adapted); if (rc != SQLITE_OK) { diff --git a/Modules/_sqlite/statement.h b/Modules/_sqlite/statement.h index e5da42e..4681443 100644 --- a/Modules/_sqlite/statement.h +++ b/Modules/_sqlite/statement.h @@ -46,8 +46,8 @@ extern PyTypeObject pysqlite_StatementType; int pysqlite_statement_create(pysqlite_Statement* self, pysqlite_Connection* connection, PyObject* sql); void pysqlite_statement_dealloc(pysqlite_Statement* self); -int pysqlite_statement_bind_parameter(pysqlite_Statement* self, int pos, PyObject* parameter, int allow_8bit_chars); -void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* parameters, int allow_8bit_chars); +int pysqlite_statement_bind_parameter(pysqlite_Statement* self, int pos, PyObject* parameter); +void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* parameters); int pysqlite_statement_recompile(pysqlite_Statement* self, PyObject* parameters); int pysqlite_statement_finalize(pysqlite_Statement* self);