SELECT a.*, b.*, c.* FROM a LEFT OUTER JOIN (b JOIN c ON b.id = c.id) ON a.id
-This was due to the fact that SQLite, even today, cannot parse a statement of the above format::
+This was due to the fact that SQLite up until version **3.7.16** cannot parse a statement of the above format::
SQLite version 3.7.15.2 2013-01-09 11:53:05
Enter ".help" for instructions
JOIN item ON item.id = order_item_1.item_id AND item.type IN (?)
) AS anon_1 ON "order".id = anon_1.order_item_1_order_id
+.. note::
+
+ As of SQLAlchemy 1.1, the workarounds present in this feature for SQLite
+ will automatically disable themselves when SQLite version **3.7.16**
+ or greater is detected, as SQLite has repaired support for right-nested joins.
+
The :meth:`.Join.alias`, :func:`.aliased` and :func:`.with_polymorphic` functions now
support a new argument, ``flat=True``, which is used to construct aliases of joined-table
entities without embedding into a SELECT. This flag is not on by default, to help with
Using table or column names that explicitly have periods in them is
**not recommended**. While this is generally a bad idea for relational
databases in general, as the dot is a syntactically significant character,
-the SQLite driver has a bug which requires that SQLAlchemy filter out these
-dots in result sets.
+the SQLite driver up until version **3.10.0** of SQLite has a bug which
+requires that SQLAlchemy filter out these dots in result sets.
+
+.. note::
+
+ The following SQLite issue has been resolved as of version 3.10.0
+ of SQLite. SQLAlchemy as of **1.1** automatically disables its internal
+ workarounds based on detection of this version.
The bug, entirely outside of SQLAlchemy, can be illustrated thusly::
return self.execution_options.get("sqlite_raw_colnames", False)
def _translate_colname(self, colname):
+ # TODO: detect SQLite version 3.10.0 or greater;
+ # see [ticket:3633]
+
# adjust for dotted column names. SQLite
# in the case of UNION may store col names as
# "tablename.colname", or if using an attached database,
supports_empty_insert = False
supports_cast = True
supports_multivalues_insert = True
+
+ # TODO: detect version 3.7.16 or greater;
+ # see [ticket:3634]
supports_right_nested_joins = False
default_paramstyle = 'qmark'
eq_(r['user_name'], "john")
eq_(list(r.keys()), ["user_id", "user_name"])
- @testing.only_on("sqlite", "sqlite specific feature")
def test_column_accessor_sqlite_raw(self):
users.insert().execute(
dict(user_id=1, user_name='john'),
"query_users.user_name from query_users",
bind=testing.db).execution_options(sqlite_raw_colnames=True). \
execute().first()
- assert 'user_id' not in r
- assert 'user_name' not in r
- eq_(r['query_users.user_id'], 1)
- eq_(r['query_users.user_name'], "john")
- eq_(list(r.keys()), ["query_users.user_id", "query_users.user_name"])
- @testing.only_on("sqlite", "sqlite specific feature")
+ if testing.against("sqlite < 3.10.0"):
+ assert 'user_id' not in r
+ assert 'user_name' not in r
+ eq_(r['query_users.user_id'], 1)
+ eq_(r['query_users.user_name'], "john")
+
+ eq_(
+ list(r.keys()),
+ ["query_users.user_id", "query_users.user_name"])
+ else:
+ assert 'query_users.user_id' not in r
+ assert 'query_users.user_name' not in r
+ eq_(r['user_id'], 1)
+ eq_(r['user_name'], "john")
+
+ eq_(list(r.keys()), ["user_id", "user_name"])
+
def test_column_accessor_sqlite_translated(self):
users.insert().execute(
dict(user_id=1, user_name='john'),
bind=testing.db).execute().first()
eq_(r['user_id'], 1)
eq_(r['user_name'], "john")
- eq_(r['query_users.user_id'], 1)
- eq_(r['query_users.user_name'], "john")
+
+ if testing.against("sqlite < 3.10.0"):
+ eq_(r['query_users.user_id'], 1)
+ eq_(r['query_users.user_name'], "john")
+ else:
+ assert 'query_users.user_id' not in r
+ assert 'query_users.user_name'not in r
eq_(list(r.keys()), ["user_id", "user_name"])
def test_column_accessor_labels_w_dots(self):