summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/dialects/sqlite/pysqlite.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2020-02-06 10:26:50 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2020-02-06 10:26:50 -0500
commitee1d914888113ceb9928ece6e0a715c813bdfcfa (patch)
tree78469e9a5054d2bed2d6d27d102b117ffbad209c /lib/sqlalchemy/dialects/sqlite/pysqlite.py
parent226f25fdce33b1427807de7decc6e8d11f678c99 (diff)
downloadsqlalchemy-ee1d914888113ceb9928ece6e0a715c813bdfcfa.tar.gz
Document SQLite "mixed binary" behavior
The Pysqlite driver can store a string value with or without an indicator that the value is to be retrieved as bytes or as a unicode string object. To suit the use case where a SQLite database has mixed values on a row by row basis, provide a recipe for a MixedBinary datatype. Change-Id: I9a166bd6fc673d8d46a53ab9697cb3d412e5fcee References: #5073
Diffstat (limited to 'lib/sqlalchemy/dialects/sqlite/pysqlite.py')
-rw-r--r--lib/sqlalchemy/dialects/sqlite/pysqlite.py38
1 files changed, 38 insertions, 0 deletions
diff --git a/lib/sqlalchemy/dialects/sqlite/pysqlite.py b/lib/sqlalchemy/dialects/sqlite/pysqlite.py
index 797a200c7..0585e69ad 100644
--- a/lib/sqlalchemy/dialects/sqlite/pysqlite.py
+++ b/lib/sqlalchemy/dialects/sqlite/pysqlite.py
@@ -243,6 +243,44 @@ require unicode, however, so that non-``unicode`` values passed inadvertently
will emit a warning. Pysqlite will emit an error if a non-``unicode`` string
is passed containing non-ASCII characters.
+Dealing with Mixed String / Binary Columns in Python 3
+------------------------------------------------------
+
+The SQLite database is weakly typed, and as such it is possible when using
+binary values, which in Python 3 are represented as ``b'some string'``, that a
+particular SQLite database can have data values within different rows where
+some of them will be returned as a ``b''`` value by the Pysqlite driver, and
+others will be returned as Python strings, e.g. ``''`` values. This situation
+is not known to occur if the SQLAlchemy :class:`.LargeBinary` datatype is used
+consistently, however if a particular SQLite database has data that was
+inserted using the Pysqlite driver directly, or when using the SQLAlchemy
+:class:`.String` type which was later changed to :class:`.LargeBinary`, the
+table will not be consistently readable because SQLAlchemy's
+:class:`.LargeBinary` datatype does not handle strings so it has no way of
+"encoding" a value that is in string format.
+
+To deal with a SQLite table that has mixed string / binary data in the
+same column, use a custom type that will check each row individually::
+
+ # note this is Python 3 only
+
+ from sqlalchemy import String
+ from sqlalchemy import TypeDecorator
+
+ class MixedBinary(TypeDecorator):
+ impl = String
+
+ def process_result_value(self, value, dialect):
+ if isinstance(value, str):
+ value = bytes(value, 'utf-8')
+ elif value is not None:
+ value = bytes(value)
+
+ return value
+
+Then use the above ``MixedBinary`` datatype in the place where
+:class:`.LargeBinary` would normally be used.
+
.. _pysqlite_serializable:
Serializable isolation / Savepoints / Transactional DDL