summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2014-02-16 17:10:05 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2014-02-16 17:10:05 -0500
commit79f801eae889ee6ee098ce3cd3b0ca98b852d2f5 (patch)
treeb10b159c45984b9414f57c4b2bbd18dff3ed4f1f
parent198a900bd19dd6ef21f642dccfc8f5bd3321181a (diff)
downloadsqlalchemy-79f801eae889ee6ee098ce3cd3b0ca98b852d2f5.tar.gz
- changelog + documentation for pullreq github:65
-rw-r--r--doc/build/changelog/changelog_09.rst14
-rw-r--r--lib/sqlalchemy/dialects/sqlite/base.py63
2 files changed, 71 insertions, 6 deletions
diff --git a/doc/build/changelog/changelog_09.rst b/doc/build/changelog/changelog_09.rst
index 5cdbcbb24..8e113f217 100644
--- a/doc/build/changelog/changelog_09.rst
+++ b/doc/build/changelog/changelog_09.rst
@@ -15,6 +15,20 @@
:version: 0.9.3
.. change::
+ :tags: sqlite
+ :pullreq: github:65
+
+ Support has been added to SQLite type reflection to fully support
+ the "type affinity" contract specified at http://www.sqlite.org/datatype3.html.
+ In this scheme, keywords like ``INT``, ``CHAR``, ``BLOB`` or
+ ``REAL`` located in the type name generically associate the type with
+ one of five affinities. Pull request courtesy Erich Blume.
+
+ .. seealso::
+
+ :ref:`sqlite_type_reflection`
+
+ .. change::
:tags: postgresql
:pullreq: github:64
diff --git a/lib/sqlalchemy/dialects/sqlite/base.py b/lib/sqlalchemy/dialects/sqlite/base.py
index fb4657675..b285bc8ca 100644
--- a/lib/sqlalchemy/dialects/sqlite/base.py
+++ b/lib/sqlalchemy/dialects/sqlite/base.py
@@ -124,6 +124,56 @@ new connections through the usage of events::
:ref:`event_toplevel` - SQLAlchemy event API.
+.. _sqlite_type_reflection:
+
+Type Reflection
+---------------
+
+SQLite types are unlike those of most other database backends, in that
+the string name of the type usually does not correspond to a "type" in a
+one-to-one fashion. Instead, SQLite links per-column typing behavior
+to one of five so-called "type affinities" based on a string matching
+pattern for the type.
+
+SQLAlchemy's reflection process, when inspecting types, uses a simple
+lookup table to link the keywords returned to provided SQLAlchemy types.
+This lookup table is present within the SQLite dialect as it is for all
+other dialects. However, the SQLite dialect has a different "fallback"
+routine for when a particular type name is not located in the lookup map;
+it instead implements the SQLite "type affinity" scheme located at
+http://www.sqlite.org/datatype3.html section 2.1.
+
+The provided typemap will make direct associations from an exact string
+name match for the following types:
+
+:class:`~.types.BIGINT`, :class:`~.types.BLOB`,
+:class:`~.types.BOOLEAN`, :class:`~.types.BOOLEAN`,
+:class:`~.types.CHAR`, :class:`~.types.DATE`,
+:class:`~.types.DATETIME`, :class:`~.types.FLOAT`,
+:class:`~.types.DECIMAL`, :class:`~.types.FLOAT`,
+:class:`~.types.INTEGER`, :class:`~.types.INTEGER`,
+:class:`~.types.NUMERIC`, :class:`~.types.REAL`,
+:class:`~.types.SMALLINT`, :class:`~.types.TEXT`,
+:class:`~.types.TIME`, :class:`~.types.TIMESTAMP`,
+:class:`~.types.VARCHAR`, :class:`~.types.NVARCHAR`,
+:class:`~.types.NCHAR`
+
+When a type name does not match one of the above types, the "type affinity"
+lookup is used instead:
+
+* :class:`~.types.INTEGER` is returned if the type name includes the
+ string ``INT``
+* :class:`~.types.TEXT` is returned if the type name includes the
+ :string ``CHAR``, ``CLOB`` or ``TEXT``
+* :class:`~.types.NullType` is returned if the type name includes the
+ string ``BLOB``
+* :class:`~.types.REAL` is returned if the type name includes the string
+ ``REAL``, ``FLOA`` or ``DOUB``.
+* Otherwise, the :class:`~.types.NUMERIC` type is used.
+
+.. versionadded:: 0.9.3 Support for SQLite type affinity rules when reflecting
+ columns.
+
"""
import datetime
@@ -814,7 +864,7 @@ class SQLiteDialect(default.DefaultDialect):
else:
coltype = ''
args = ''
- coltype = self._resolve_col_affinity(coltype)
+ coltype = self._resolve_type_affinity(coltype)
if args is not None:
args = re.findall(r'(\d+)', args)
coltype = coltype(*[int(a) for a in args])
@@ -831,7 +881,7 @@ class SQLiteDialect(default.DefaultDialect):
'primary_key': primary_key,
}
- def _resolve_col_affinity(self, coltype):
+ def _resolve_type_affinity(self, coltype):
"""Return a data type from a reflected column, using affinity tules.
SQLite's goal for universal compatability introduces some complexity
@@ -846,17 +896,18 @@ class SQLiteDialect(default.DefaultDialect):
providing access to smarter reflection utilities by regcognizing
column definitions that SQLite only supports through affinity (like
DATE and DOUBLE).
+
"""
if coltype in self.ischema_names:
return self.ischema_names[coltype]
- if 'INT' in coltype:
+ elif 'INT' in coltype:
return sqltypes.INTEGER
elif 'CHAR' in coltype or 'CLOB' in coltype or 'TEXT' in coltype:
- return sqltypes.TEXT,
- elif 'BLOB' in coltype or not coltype:
+ return sqltypes.TEXT
+ elif 'BLOB' in coltype or not coltype:
return sqltypes.NullType
elif 'REAL' in coltype or 'FLOA' in coltype or 'DOUB' in coltype:
- return sqltype.REAL
+ return sqltypes.REAL
else:
return sqltypes.NUMERIC