Commit bc35bebb authored by Petri Lehtinen's avatar Petri Lehtinen

Undocument and clean up sqlite3.OptimizedUnicode

Closes #13921.
parent f0f9679d
...@@ -30,14 +30,3 @@ cur.execute("select ?", ("this is latin1 and would normally create errors" + ...@@ -30,14 +30,3 @@ cur.execute("select ?", ("this is latin1 and would normally create errors" +
"\xe4\xf6\xfc".encode("latin1"),)) "\xe4\xf6\xfc".encode("latin1"),))
row = cur.fetchone() row = cur.fetchone()
assert type(row[0]) == str 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
...@@ -436,10 +436,6 @@ Connection Objects ...@@ -436,10 +436,6 @@ Connection Objects
:mod:`sqlite3` module will return Unicode objects for ``TEXT``. If you want to :mod:`sqlite3` module will return Unicode objects for ``TEXT``. If you want to
return bytestrings instead, you can set it to :class:`bytes`. 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 You can also set it to any other callable that accepts a single bytestring
parameter and returns the resulting object. parameter and returns the resulting object.
......
...@@ -178,6 +178,8 @@ class TextFactoryTests(unittest.TestCase): ...@@ -178,6 +178,8 @@ class TextFactoryTests(unittest.TestCase):
self.assertTrue(row[0].endswith("reich"), "column must contain original data") self.assertTrue(row[0].endswith("reich"), "column must contain original data")
def CheckOptimizedUnicode(self): def CheckOptimizedUnicode(self):
# In py3k, str objects are always returned when text_factory
# is OptimizedUnicode
self.con.text_factory = sqlite.OptimizedUnicode self.con.text_factory = sqlite.OptimizedUnicode
austria = "sterreich" austria = "sterreich"
germany = "Deutchland" germany = "Deutchland"
......
...@@ -466,6 +466,10 @@ Core and Builtins ...@@ -466,6 +466,10 @@ Core and Builtins
Library Library
------- -------
- Issue #13921: Undocument and clean up sqlite3.OptimizedUnicode,
which is obsolete in Python 3.x. It's now aliased to str for
backwards compatibility.
- When '' is a path (e.g. in sys.path), make sure __file__ uses the current - When '' is a path (e.g. in sys.path), make sure __file__ uses the current
working directory instead of '' in importlib. working directory instead of '' in importlib.
......
...@@ -83,8 +83,7 @@ typedef struct ...@@ -83,8 +83,7 @@ typedef struct
/* Determines how bytestrings from SQLite are converted to Python objects: /* Determines how bytestrings from SQLite are converted to Python objects:
* - PyUnicode_Type: Python Unicode objects are constructed from UTF-8 bytestrings * - PyUnicode_Type: Python Unicode objects are constructed from UTF-8 bytestrings
* - OptimizedUnicode: Like before, but for ASCII data, only PyStrings are created. * - PyBytes_Type: The bytestrings are returned as-is.
* - PyBytes_Type: PyStrings are created as-is.
* - Any custom callable: Any object returned from the callable called with the bytestring * - Any custom callable: Any object returned from the callable called with the bytestring
* as single parameter. * as single parameter.
*/ */
......
...@@ -267,11 +267,6 @@ PyObject* _pysqlite_build_column_name(const char* colname) ...@@ -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 * Returns a row from the currently active SQLite statement
* *
...@@ -355,12 +350,8 @@ PyObject* _pysqlite_fetch_one_row(pysqlite_Cursor* self) ...@@ -355,12 +350,8 @@ PyObject* _pysqlite_fetch_one_row(pysqlite_Cursor* self)
} else if (coltype == SQLITE_TEXT) { } else if (coltype == SQLITE_TEXT) {
val_str = (const char*)sqlite3_column_text(self->statement->st, i); val_str = (const char*)sqlite3_column_text(self->statement->st, i);
nbytes = sqlite3_column_bytes(self->statement->st, i); nbytes = sqlite3_column_bytes(self->statement->st, i);
if ((self->connection->text_factory == (PyObject*)&PyUnicode_Type) if (self->connection->text_factory == (PyObject*)&PyUnicode_Type) {
|| (self->connection->text_factory == pysqlite_OptimizedUnicode)) { converted = PyUnicode_FromStringAndSize(val_str, nbytes);
converted = pysqlite_unicode_from_string(val_str, nbytes,
self->connection->text_factory == pysqlite_OptimizedUnicode ? 1 : 0);
if (!converted) { if (!converted) {
colname = sqlite3_column_name(self->statement->st, i); colname = sqlite3_column_name(self->statement->st, i);
if (!colname) { if (!colname) {
...@@ -459,7 +450,6 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* ...@@ -459,7 +450,6 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject*
int statement_type; int statement_type;
PyObject* descriptor; PyObject* descriptor;
PyObject* second_argument = NULL; PyObject* second_argument = NULL;
int allow_8bit_chars;
if (!check_cursor(self)) { if (!check_cursor(self)) {
goto error; goto error;
...@@ -468,10 +458,6 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* ...@@ -468,10 +458,6 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject*
self->locked = 1; self->locked = 1;
self->reset = 0; 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); Py_XDECREF(self->next_row);
self->next_row = NULL; self->next_row = NULL;
...@@ -630,7 +616,7 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* ...@@ -630,7 +616,7 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject*
pysqlite_statement_mark_dirty(self->statement); 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()) { if (PyErr_Occurred()) {
goto error; goto error;
} }
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
PyObject* pysqlite_Error, *pysqlite_Warning, *pysqlite_InterfaceError, *pysqlite_DatabaseError, PyObject* pysqlite_Error, *pysqlite_Warning, *pysqlite_InterfaceError, *pysqlite_DatabaseError,
*pysqlite_InternalError, *pysqlite_OperationalError, *pysqlite_ProgrammingError, *pysqlite_InternalError, *pysqlite_OperationalError, *pysqlite_ProgrammingError,
*pysqlite_IntegrityError, *pysqlite_DataError, *pysqlite_NotSupportedError, *pysqlite_OptimizedUnicode; *pysqlite_IntegrityError, *pysqlite_DataError, *pysqlite_NotSupportedError;
PyObject* converters; PyObject* converters;
int _enable_callback_tracebacks; int _enable_callback_tracebacks;
...@@ -407,13 +407,13 @@ PyMODINIT_FUNC PyInit__sqlite3(void) ...@@ -407,13 +407,13 @@ PyMODINIT_FUNC PyInit__sqlite3(void)
} }
PyDict_SetItemString(dict, "NotSupportedError", pysqlite_NotSupportedError); PyDict_SetItemString(dict, "NotSupportedError", pysqlite_NotSupportedError);
/* We just need "something" unique for pysqlite_OptimizedUnicode. It does not really /* In Python 2.x, setting Connection.text_factory to
* need to be a string subclass. Just anything that can act as a special OptimizedUnicode caused Unicode objects to be returned for
* marker for us. So I pulled PyCell_Type out of my magic hat. non-ASCII data and bytestrings to be returned for ASCII data.
*/ Now OptimizedUnicode is an alias for str, so it has no
Py_INCREF((PyObject*)&PyCell_Type); effect. */
pysqlite_OptimizedUnicode = (PyObject*)&PyCell_Type; Py_INCREF((PyObject*)&PyUnicode_Type);
PyDict_SetItemString(dict, "OptimizedUnicode", pysqlite_OptimizedUnicode); PyDict_SetItemString(dict, "OptimizedUnicode", (PyObject*)&PyUnicode_Type);
/* Set integer constants */ /* Set integer constants */
for (i = 0; _int_constants[i].constant_name != 0; i++) { for (i = 0; _int_constants[i].constant_name != 0; i++) {
......
...@@ -38,8 +38,6 @@ extern PyObject* pysqlite_IntegrityError; ...@@ -38,8 +38,6 @@ extern PyObject* pysqlite_IntegrityError;
extern PyObject* pysqlite_DataError; extern PyObject* pysqlite_DataError;
extern PyObject* pysqlite_NotSupportedError; extern PyObject* pysqlite_NotSupportedError;
extern PyObject* pysqlite_OptimizedUnicode;
/* the functions time.time() and time.sleep() */ /* the functions time.time() and time.sleep() */
extern PyObject* time_time; extern PyObject* time_time;
extern PyObject* time_sleep; extern PyObject* time_sleep;
......
...@@ -87,7 +87,7 @@ int pysqlite_statement_create(pysqlite_Statement* self, pysqlite_Connection* con ...@@ -87,7 +87,7 @@ int pysqlite_statement_create(pysqlite_Statement* self, pysqlite_Connection* con
return rc; 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; int rc = SQLITE_OK;
PY_LONG_LONG longlongval; PY_LONG_LONG longlongval;
...@@ -166,7 +166,7 @@ static int _need_adapt(PyObject* obj) ...@@ -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* current_param;
PyObject* adapted; PyObject* adapted;
...@@ -220,7 +220,7 @@ void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* para ...@@ -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); Py_DECREF(adapted);
if (rc != SQLITE_OK) { if (rc != SQLITE_OK) {
...@@ -265,7 +265,7 @@ void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* para ...@@ -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); Py_DECREF(adapted);
if (rc != SQLITE_OK) { if (rc != SQLITE_OK) {
......
...@@ -46,8 +46,8 @@ extern PyTypeObject pysqlite_StatementType; ...@@ -46,8 +46,8 @@ extern PyTypeObject pysqlite_StatementType;
int pysqlite_statement_create(pysqlite_Statement* self, pysqlite_Connection* connection, PyObject* sql); int pysqlite_statement_create(pysqlite_Statement* self, pysqlite_Connection* connection, PyObject* sql);
void pysqlite_statement_dealloc(pysqlite_Statement* self); void pysqlite_statement_dealloc(pysqlite_Statement* self);
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);
void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* parameters, int allow_8bit_chars); void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* parameters);
int pysqlite_statement_recompile(pysqlite_Statement* self, PyObject* parameters); int pysqlite_statement_recompile(pysqlite_Statement* self, PyObject* parameters);
int pysqlite_statement_finalize(pysqlite_Statement* self); int pysqlite_statement_finalize(pysqlite_Statement* self);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment