summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/build/changelog/changelog_08.rst51
-rw-r--r--doc/build/changelog/changelog_09.rst72
-rw-r--r--doc/build/changelog/migration_09.rst54
-rw-r--r--doc/build/dialects/firebird.rst10
-rw-r--r--lib/sqlalchemy/connectors/pyodbc.py31
-rw-r--r--lib/sqlalchemy/dialects/firebird/__init__.py2
-rw-r--r--lib/sqlalchemy/dialects/firebird/fdb.py8
-rw-r--r--lib/sqlalchemy/dialects/mssql/base.py1
-rw-r--r--lib/sqlalchemy/dialects/mysql/base.py2
-rw-r--r--lib/sqlalchemy/engine/default.py2
-rw-r--r--lib/sqlalchemy/ext/mutable.py4
-rw-r--r--lib/sqlalchemy/schema.py18
-rw-r--r--lib/sqlalchemy/sql/compiler.py54
-rw-r--r--lib/sqlalchemy/sql/expression.py13
-rw-r--r--lib/sqlalchemy/sql/operators.py5
-rw-r--r--lib/sqlalchemy/testing/engines.py8
-rw-r--r--lib/sqlalchemy/testing/suite/__init__.py1
-rw-r--r--lib/sqlalchemy/testing/suite/test_select.py83
-rw-r--r--setup.cfg1
-rw-r--r--test/dialect/test_mysql.py13
-rw-r--r--test/engine/test_reflection.py35
-rw-r--r--test/ext/test_mutable.py12
-rw-r--r--test/orm/test_eager_relations.py12
-rw-r--r--test/profiles.txt50
-rw-r--r--test/requirements.py7
-rw-r--r--test/sql/test_compiler.py71
-rw-r--r--test/sql/test_metadata.py24
-rw-r--r--test/sql/test_operators.py13
-rw-r--r--test/sql/test_query.py2
-rw-r--r--test/sql/test_selectable.py12
30 files changed, 597 insertions, 74 deletions
diff --git a/doc/build/changelog/changelog_08.rst b/doc/build/changelog/changelog_08.rst
index 211668867..82e65272b 100644
--- a/doc/build/changelog/changelog_08.rst
+++ b/doc/build/changelog/changelog_08.rst
@@ -7,6 +7,57 @@
:version: 0.8.2
.. change::
+ :tags: bug, mysql
+ :tickets: 2721
+
+ The ``deferrable`` keyword argument on :class:`.ForeignKey` and
+ :class:`.ForeignKeyConstraint` will not render the ``DEFERRABLE`` keyword
+ on the MySQL dialect. For a long time we left this in place because
+ a non-deferrable foreign key would act very differently than a deferrable
+ one, but some environments just disable FKs on MySQL, so we'll be less
+ opinionated here.
+
+ .. change::
+ :tags: bug, ext, orm
+ :tickets: 2730
+
+ Fixed bug where :class:`.MutableDict` didn't report a change event
+ when ``clear()`` was called.
+
+ .. change::
+ :tags: bug, sql
+ :tickets: 2738
+
+ Fixed bug whereby joining a select() of a table "A" with multiple
+ foreign key paths to a table "B", to that table "B", would fail
+ to produce the "ambiguous join condition" error that would be
+ reported if you join table "A" directly to "B"; it would instead
+ produce a join condition with multiple criteria.
+
+ .. change::
+ :tags: bug, sql, reflection
+ :tickets: 2728
+
+ Fixed bug whereby using :meth:`.MetaData.reflect` across a remote
+ schema as well as a local schema could produce wrong results
+ in the case where both schemas had a table of the same name.
+
+ .. change::
+ :tags: bug, sql
+ :tickets: 2726
+
+ Removed the "not implemented" ``__iter__()`` call from the base
+ :class:`.ColumnOperators` class, while this was introduced
+ in 0.8.0 to prevent an endless, memory-growing loop when one also
+ implements a ``__getitem__()`` method on a custom
+ operator and then calls erroneously ``list()`` on that object,
+ it had the effect of causing column elements to report that they
+ were in fact iterable types which then throw an error when you try
+ to iterate. There's no real way to have both sides here so we
+ stick with Python best practices. Careful with implementing
+ ``__getitem__()`` on your custom operators!
+
+ .. change::
:tags: feature, orm
:tickets: 2736
diff --git a/doc/build/changelog/changelog_09.rst b/doc/build/changelog/changelog_09.rst
index baddf7e2a..c5ee84a7b 100644
--- a/doc/build/changelog/changelog_09.rst
+++ b/doc/build/changelog/changelog_09.rst
@@ -7,6 +7,78 @@
:version: 0.9.0
.. change::
+ :tags: bug, mysql
+ :tickets: 2721
+
+ The ``deferrable`` keyword argument on :class:`.ForeignKey` and
+ :class:`.ForeignKeyConstraint` will not render the ``DEFERRABLE`` keyword
+ on the MySQL dialect. For a long time we left this in place because
+ a non-deferrable foreign key would act very differently than a deferrable
+ one, but some environments just disable FKs on MySQL, so we'll be less
+ opinionated here. Also in 0.8.2.
+
+ .. change::
+ :tags: bug, ext, orm
+ :tickets: 2730
+
+ Fixed bug where :class:`.MutableDict` didn't report a change event
+ when ``clear()`` was called. Also in 0.8.2
+
+ .. change::
+ :tags: bug, sql
+ :tickets: 2738
+
+ Fixed bug whereby joining a select() of a table "A" with multiple
+ foreign key paths to a table "B", to that table "B", would fail
+ to produce the "ambiguous join condition" error that would be
+ reported if you join table "A" directly to "B"; it would instead
+ produce a join condition with multiple criteria. Also in 0.8.2.
+
+ .. change::
+ :tags: bug, sql, reflection
+ :tickets: 2728
+
+ Fixed bug whereby using :meth:`.MetaData.reflect` across a remote
+ schema as well as a local schema could produce wrong results
+ in the case where both schemas had a table of the same name.
+ Also in 0.8.2.
+
+ .. change::
+ :tags: bug, sql
+ :tickets: 2726
+
+ Removed the "not implemented" ``__iter__()`` call from the base
+ :class:`.ColumnOperators` class, while this was introduced
+ in 0.8.0 to prevent an endless, memory-growing loop when one also
+ implements a ``__getitem__()`` method on a custom
+ operator and then calls erroneously ``list()`` on that object,
+ it had the effect of causing column elements to report that they
+ were in fact iterable types which then throw an error when you try
+ to iterate. There's no real way to have both sides here so we
+ stick with Python best practices. Careful with implementing
+ ``__getitem__()`` on your custom operators! Also in 0.8.2.
+
+ .. change::
+ :tags: feature, sql
+ :tickets: 1068
+
+ A :class:`.Label` construct will now render as its name alone
+ in an ``ORDER BY`` clause, if that label is also referred to
+ in the columns clause of the select, instead of rewriting the
+ full expression. This gives the database a better chance to
+ optimize the evaulation of the same expression in two different
+ contexts.
+
+ .. change::
+ :tags: feature, firebird
+ :tickets: 2504
+
+ The ``fdb`` dialect is now the default dialect when
+ specified without a dialect qualifier, i.e. ``firebird://``,
+ per the Firebird project publishing ``fdb`` as their
+ official Python driver.
+
+ .. change::
:tags: feature, general
:tickets: 2671
diff --git a/doc/build/changelog/migration_09.rst b/doc/build/changelog/migration_09.rst
index 969bfb624..03c84d8d9 100644
--- a/doc/build/changelog/migration_09.rst
+++ b/doc/build/changelog/migration_09.rst
@@ -124,4 +124,58 @@ to 0.9 without issue.
:ticket:`2736`
+Behavioral Improvements
+=======================
+
+Improvements that should produce no compatibility issues, but are good
+to be aware of in case there are unexpected issues.
+
+Label constructs can now render as their name alone in an ORDER BY
+------------------------------------------------------------------
+
+For the case where a :class:`.Label` is used in both the columns clause
+as well as the ORDER BY clause of a SELECT, the label will render as
+just it's name in the ORDER BY clause, assuming the underlying dialect
+reports support of this feature.
+
+E.g. an example like::
+
+ from sqlalchemy.sql import table, column, select, func
+
+ t = table('t', column('c1'), column('c2'))
+ expr = (func.foo(t.c.c1) + t.c.c2).label("expr")
+
+ stmt = select([expr]).order_by(expr)
+
+ print stmt
+
+Prior to 0.9 would render as::
+
+ SELECT foo(t.c1) + t.c2 AS expr
+ FROM t ORDER BY foo(t.c1) + t.c2
+
+And now renders as::
+
+ SELECT foo(t.c1) + t.c2 AS expr
+ FROM t ORDER BY expr
+
+The ORDER BY only renders the label if the label isn't further embedded into an expression within the ORDER BY, other than a simple ``ASC`` or ``DESC``.
+
+The above format works on all databases tested, but might have compatibility issues with older database versions (MySQL 4? Oracle 8? etc.). Based on user reports we can add rules
+that will disable the feature based on database version detection.
+
+:ticket:`1068`
+
+Dialect Changes
+===============
+
+Firebird ``fdb`` is now the default Firebird dialect.
+-----------------------------------------------------
+
+The ``fdb`` dialect is now used if an engine is created without a dialect
+specifier, i.e. ``firebird://``. ``fdb`` is a ``kinterbasdb`` compatible
+DBAPI which per the Firebird project is now their official Python driver.
+
+:ticket:`2504`
+
diff --git a/doc/build/dialects/firebird.rst b/doc/build/dialects/firebird.rst
index d5b6b2ffd..d6e9726af 100644
--- a/doc/build/dialects/firebird.rst
+++ b/doc/build/dialects/firebird.rst
@@ -5,12 +5,12 @@ Firebird
.. automodule:: sqlalchemy.dialects.firebird.base
-kinterbasdb
------------
-
-.. automodule:: sqlalchemy.dialects.firebird.kinterbasdb
-
fdb
---
.. automodule:: sqlalchemy.dialects.firebird.fdb
+
+kinterbasdb
+-----------
+
+.. automodule:: sqlalchemy.dialects.firebird.kinterbasdb
diff --git a/lib/sqlalchemy/connectors/pyodbc.py b/lib/sqlalchemy/connectors/pyodbc.py
index 784344b82..6b4e3036d 100644
--- a/lib/sqlalchemy/connectors/pyodbc.py
+++ b/lib/sqlalchemy/connectors/pyodbc.py
@@ -16,9 +16,12 @@ class PyODBCConnector(Connector):
driver = 'pyodbc'
supports_sane_multi_rowcount = False
- # PyODBC unicode is broken on UCS-4 builds
- supports_unicode = sys.maxunicode == 65535
- supports_unicode_statements = supports_unicode
+
+ if util.py2k:
+ # PyODBC unicode is broken on UCS-4 builds
+ supports_unicode = sys.maxunicode == 65535
+ supports_unicode_statements = supports_unicode
+
supports_native_decimal = True
default_paramstyle = 'named'
@@ -121,15 +124,19 @@ class PyODBCConnector(Connector):
self.freetds_driver_version = dbapi_con.getinfo(
pyodbc.SQL_DRIVER_VER)
- if not util.py3k:
- self.supports_unicode_statements = (
- not self.freetds and not self.easysoft)
- if self._user_supports_unicode_binds is not None:
- self.supports_unicode_binds = self._user_supports_unicode_binds
- else:
- self.supports_unicode_binds = (
- not self.freetds or self.freetds_driver_version >= '0.91'
- ) and not self.easysoft
+ self.supports_unicode_statements = (
+ not util.py2k or
+ (not self.freetds and not self.easysoft)
+ )
+
+ if self._user_supports_unicode_binds is not None:
+ self.supports_unicode_binds = self._user_supports_unicode_binds
+ elif util.py2k:
+ self.supports_unicode_binds = (
+ not self.freetds or self.freetds_driver_version >= '0.91'
+ ) and not self.easysoft
+ else:
+ self.supports_unicode_binds = True
# run other initialization which asks for user name, etc.
super(PyODBCConnector, self).initialize(connection)
diff --git a/lib/sqlalchemy/dialects/firebird/__init__.py b/lib/sqlalchemy/dialects/firebird/__init__.py
index 0f4853bfb..e57457a39 100644
--- a/lib/sqlalchemy/dialects/firebird/__init__.py
+++ b/lib/sqlalchemy/dialects/firebird/__init__.py
@@ -6,7 +6,7 @@
from sqlalchemy.dialects.firebird import base, kinterbasdb, fdb
-base.dialect = kinterbasdb.dialect
+base.dialect = fdb.dialect
from sqlalchemy.dialects.firebird.base import \
SMALLINT, BIGINT, FLOAT, FLOAT, DATE, TIME, \
diff --git a/lib/sqlalchemy/dialects/firebird/fdb.py b/lib/sqlalchemy/dialects/firebird/fdb.py
index 292f15c72..8d0bd3d78 100644
--- a/lib/sqlalchemy/dialects/firebird/fdb.py
+++ b/lib/sqlalchemy/dialects/firebird/fdb.py
@@ -15,11 +15,11 @@
.. versionadded:: 0.8 - Support for the fdb Firebird driver.
-Status
-------
-
-The fdb dialect is new and not yet tested (can't get fdb to build).
+ .. versionchanged:: 0.9 - The fdb dialect is now the default dialect
+ under the ``firebird://`` URL space, as ``fdb`` is now the official
+ Python driver for Firebird.
+The dialect currently accepts the same arguments as the Kinterbasdb driver.
"""
diff --git a/lib/sqlalchemy/dialects/mssql/base.py b/lib/sqlalchemy/dialects/mssql/base.py
index a5d789be1..3c329fe5e 100644
--- a/lib/sqlalchemy/dialects/mssql/base.py
+++ b/lib/sqlalchemy/dialects/mssql/base.py
@@ -1172,6 +1172,7 @@ class MSDialect(default.DefaultDialect):
columns = ischema.columns
whereclause = self._unicode_cast(columns.c.table_name) == tablename
+
if owner:
whereclause = sql.and_(whereclause,
columns.c.table_schema == owner)
diff --git a/lib/sqlalchemy/dialects/mysql/base.py b/lib/sqlalchemy/dialects/mysql/base.py
index ad4650f6d..03827edb7 100644
--- a/lib/sqlalchemy/dialects/mysql/base.py
+++ b/lib/sqlalchemy/dialects/mysql/base.py
@@ -1567,6 +1567,8 @@ class MySQLDDLCompiler(compiler.DDLCompiler):
(self.preparer.format_table(constraint.table),
qual, const)
+ def define_constraint_deferrability(self, constraint):
+ return ""
class MySQLTypeCompiler(compiler.GenericTypeCompiler):
def _extend_numeric(self, type_, spec):
diff --git a/lib/sqlalchemy/engine/default.py b/lib/sqlalchemy/engine/default.py
index 7d558f5ff..2ad7002c4 100644
--- a/lib/sqlalchemy/engine/default.py
+++ b/lib/sqlalchemy/engine/default.py
@@ -54,6 +54,8 @@ class DefaultDialect(interfaces.Dialect):
supports_native_enum = False
supports_native_boolean = False
+ supports_simple_order_by_label = True
+
# if the NUMERIC type
# returns decimal.Decimal.
# *not* the FLOAT type however.
diff --git a/lib/sqlalchemy/ext/mutable.py b/lib/sqlalchemy/ext/mutable.py
index b1b851f72..ca27f172f 100644
--- a/lib/sqlalchemy/ext/mutable.py
+++ b/lib/sqlalchemy/ext/mutable.py
@@ -616,6 +616,10 @@ class MutableDict(Mutable, dict):
dict.__delitem__(self, key)
self.changed()
+ def clear(self):
+ dict.clear(self)
+ self.changed()
+
@classmethod
def coerce(cls, key, value):
"""Convert plain dictionary to MutableDict."""
diff --git a/lib/sqlalchemy/schema.py b/lib/sqlalchemy/schema.py
index 3a74cbd59..94df6751c 100644
--- a/lib/sqlalchemy/schema.py
+++ b/lib/sqlalchemy/schema.py
@@ -1134,7 +1134,8 @@ class Column(SchemaItem, expression.ColumnClause):
information is not transferred.
"""
- fk = [ForeignKey(f.column) for f in self.foreign_keys]
+ fk = [ForeignKey(f.column, _constraint=f.constraint)
+ for f in self.foreign_keys]
if name is None and self.name is None:
raise exc.InvalidRequestError("Cannot initialize a sub-selectable"
" with this Column object until it's 'name' has "
@@ -2711,13 +2712,22 @@ class MetaData(SchemaItem):
bind.dialect.get_view_names(conn, schema)
)
+ if schema is not None:
+ available_w_schema = util.OrderedSet(["%s.%s" % (schema, name)
+ for name in available])
+ else:
+ available_w_schema = available
+
current = set(self.tables)
if only is None:
- load = [name for name in available if name not in current]
+ load = [name for name, schname in
+ zip(available, available_w_schema)
+ if schname not in current]
elif util.callable(only):
- load = [name for name in available
- if name not in current and only(name, self)]
+ load = [name for name, schname in
+ zip(available, available_w_schema)
+ if schname not in current and only(name, self)]
else:
missing = [name for name in only if name not in available]
if missing:
diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py
index c29b45450..dd2a6e08c 100644
--- a/lib/sqlalchemy/sql/compiler.py
+++ b/lib/sqlalchemy/sql/compiler.py
@@ -387,16 +387,22 @@ class SQLCompiler(engine.Compiled):
def visit_label(self, label,
add_to_result_map=None,
within_label_clause=False,
- within_columns_clause=False, **kw):
+ within_columns_clause=False,
+ render_label_as_label=None,
+ **kw):
# only render labels within the columns clause
# or ORDER BY clause of a select. dialect-specific compilers
# can modify this behavior.
- if within_columns_clause and not within_label_clause:
+ render_label_with_as = within_columns_clause and not within_label_clause
+ render_label_only = render_label_as_label is label
+
+ if render_label_only or render_label_with_as:
if isinstance(label.name, sql._truncated_label):
labelname = self._truncated_identifier("colident", label.name)
else:
labelname = label.name
+ if render_label_with_as:
if add_to_result_map is not None:
add_to_result_map(
labelname,
@@ -411,6 +417,8 @@ class SQLCompiler(engine.Compiled):
**kw) + \
OPERATORS[operators.as_] + \
self.preparer.format_label(label, labelname)
+ elif render_label_only:
+ return labelname
else:
return label.element._compiler_dispatch(self,
within_columns_clause=False,
@@ -506,7 +514,11 @@ class SQLCompiler(engine.Compiled):
def visit_false(self, expr, **kw):
return 'false'
- def visit_clauselist(self, clauselist, **kwargs):
+ def visit_clauselist(self, clauselist, order_by_select=None, **kw):
+ if order_by_select is not None:
+ return self._order_by_clauselist(
+ clauselist, order_by_select, **kw)
+
sep = clauselist.operator
if sep is None:
sep = " "
@@ -514,8 +526,32 @@ class SQLCompiler(engine.Compiled):
sep = OPERATORS[clauselist.operator]
return sep.join(
s for s in
- (c._compiler_dispatch(self, **kwargs)
- for c in clauselist.clauses)
+ (
+ c._compiler_dispatch(self, **kw)
+ for c in clauselist.clauses)
+ if s)
+
+ def _order_by_clauselist(self, clauselist, order_by_select, **kw):
+ # look through raw columns collection for labels.
+ # note that its OK we aren't expanding tables and other selectables
+ # here; we can only add a label in the ORDER BY for an individual
+ # label expression in the columns clause.
+
+ raw_col = set(l._order_by_label_element.name
+ for l in order_by_select._raw_columns
+ if l._order_by_label_element is not None)
+
+ return ", ".join(
+ s for s in
+ (
+ c._compiler_dispatch(self,
+ render_label_as_label=
+ c._order_by_label_element if
+ c._order_by_label_element is not None and
+ c._order_by_label_element.name in raw_col
+ else None,
+ **kw)
+ for c in clauselist.clauses)
if s)
def visit_case(self, clause, **kwargs):
@@ -1284,7 +1320,13 @@ class SQLCompiler(engine.Compiled):
text += " \nHAVING " + t
if select._order_by_clause.clauses:
- text += self.order_by_clause(select, **kwargs)
+ if self.dialect.supports_simple_order_by_label:
+ order_by_select = select
+ else:
+ order_by_select = None
+
+ text += self.order_by_clause(select,
+ order_by_select=order_by_select, **kwargs)
if select._limit is not None or select._offset is not None:
text += self.limit_clause(select)
if select.for_update:
diff --git a/lib/sqlalchemy/sql/expression.py b/lib/sqlalchemy/sql/expression.py
index e7ef3cb72..f0c6134e5 100644
--- a/lib/sqlalchemy/sql/expression.py
+++ b/lib/sqlalchemy/sql/expression.py
@@ -1659,6 +1659,8 @@ class ClauseElement(Visitable):
is_selectable = False
is_clause_element = True
+ _order_by_label_element = None
+
def _clone(self):
"""Create a shallow copy of this ClauseElement.
@@ -3679,6 +3681,13 @@ class UnaryExpression(ColumnElement):
self.type = sqltypes.to_instance(type_)
self.negate = negate
+ @util.memoized_property
+ def _order_by_label_element(self):
+ if self.modifier in (operators.desc_op, operators.asc_op):
+ return self.element._order_by_label_element
+ else:
+ return None
+
@property
def _from_objects(self):
return self.element._from_objects
@@ -4327,6 +4336,10 @@ class Label(ColumnElement):
self._proxies = [element]
@util.memoized_property
+ def _order_by_label_element(self):
+ return self
+
+ @util.memoized_property
def type(self):
return sqltypes.to_instance(
self._type or getattr(self._element, 'type', None)
diff --git a/lib/sqlalchemy/sql/operators.py b/lib/sqlalchemy/sql/operators.py
index 4afb3db48..128442158 100644
--- a/lib/sqlalchemy/sql/operators.py
+++ b/lib/sqlalchemy/sql/operators.py
@@ -313,11 +313,6 @@ class ColumnOperators(Operators):
"""
return self.operate(neg)
- def __iter__(self):
- """Block calls to list() from calling __getitem__() endlessly."""
-
- raise NotImplementedError("Class %s is not iterable" % self.__class__)
-
def __getitem__(self, index):
"""Implement the [] operator.
diff --git a/lib/sqlalchemy/testing/engines.py b/lib/sqlalchemy/testing/engines.py
index efc0103f2..d8c1709e7 100644
--- a/lib/sqlalchemy/testing/engines.py
+++ b/lib/sqlalchemy/testing/engines.py
@@ -47,13 +47,13 @@ class ConnectionKiller(object):
self._safe(rec._close)
def _after_test_ctx(self):
- pass
# this can cause a deadlock with pg8000 - pg8000 acquires
# prepared statment lock inside of rollback() - if async gc
# is collecting in finalize_fairy, deadlock.
- # not sure if this should be if pypy/jython only
- #for conn in self.conns:
- # self._safe(conn.rollback)
+ # not sure if this should be if pypy/jython only.
+ # note that firebird/fdb definitely needs this though
+ for conn in self.conns:
+ self._safe(conn.rollback)
def _stop_test_ctx(self):
if config.options.low_connections:
diff --git a/lib/sqlalchemy/testing/suite/__init__.py b/lib/sqlalchemy/testing/suite/__init__.py
index f65dd1a34..780aa40aa 100644
--- a/lib/sqlalchemy/testing/suite/__init__.py
+++ b/lib/sqlalchemy/testing/suite/__init__.py
@@ -2,6 +2,7 @@
from sqlalchemy.testing.suite.test_ddl import *
from sqlalchemy.testing.suite.test_insert import *
from sqlalchemy.testing.suite.test_sequence import *
+from sqlalchemy.testing.suite.test_select import *
from sqlalchemy.testing.suite.test_results import *
from sqlalchemy.testing.suite.test_update_delete import *
from sqlalchemy.testing.suite.test_reflection import *
diff --git a/lib/sqlalchemy/testing/suite/test_select.py b/lib/sqlalchemy/testing/suite/test_select.py
new file mode 100644
index 000000000..b040c8f25
--- /dev/null
+++ b/lib/sqlalchemy/testing/suite/test_select.py
@@ -0,0 +1,83 @@
+from .. import fixtures, config
+from ..assertions import eq_
+
+from sqlalchemy import Integer, String, select, func
+
+from ..schema import Table, Column
+
+
+class OrderByLabelTest(fixtures.TablesTest):
+ """Test the dialect sends appropriate ORDER BY expressions when
+ labels are used.
+
+ This essentially exercises the "supports_simple_order_by_label"
+ setting.
+
+ """
+ @classmethod
+ def define_tables(cls, metadata):
+ Table("some_table", metadata,
+ Column('id', Integer, primary_key=True),
+ Column('x', Integer),
+ Column('y', Integer),
+ Column('q', String(50)),
+ Column('p', String(50))
+ )
+
+ @classmethod
+ def insert_data(cls):
+ config.db.execute(
+ cls.tables.some_table.insert(),
+ [
+ {"id": 1, "x": 1, "y": 2, "q": "q1", "p": "p3"},
+ {"id": 2, "x": 2, "y": 3, "q": "q2", "p": "p2"},
+ {"id": 3, "x": 3, "y": 4, "q": "q3", "p": "p1"},
+ ]
+ )
+
+ def _assert_result(self, select, result):
+ eq_(
+ config.db.execute(select).fetchall(),
+ result
+ )
+
+ def test_plain(self):
+ table = self.tables.some_table
+ lx = table.c.x.label('lx')
+ self._assert_result(
+ select([lx]).order_by(lx),
+ [(1, ), (2, ), (3, )]
+ )
+
+ def test_composed_int(self):
+ table = self.tables.some_table
+ lx = (table.c.x + table.c.y).label('lx')
+ self._assert_result(
+ select([lx]).order_by(lx),
+ [(3, ), (5, ), (7, )]
+ )
+
+ def test_composed_multiple(self):
+ table = self.tables.some_table
+ lx = (table.c.x + table.c.y).label('lx')
+ ly = (func.lower(table.c.q) + table.c.p).label('ly')
+ self._assert_result(
+ select([lx, ly]).order_by(lx, ly.desc()),
+ [(3, u'q1p3'), (5, u'q2p2'), (7, u'q3p1')]
+ )
+
+ def test_plain_desc(self):
+ table = self.tables.some_table
+ lx = table.c.x.label('lx')
+ self._assert_result(
+ select([lx]).order_by(lx.desc()),
+ [(3, ), (2, ), (1, )]
+ )
+
+ def test_composed_int_desc(self):
+ table = self.tables.some_table
+ lx = (table.c.x + table.c.y).label('lx')
+ self._assert_result(
+ select([lx]).order_by(lx.desc()),
+ [(7, ), (5, ), (3, )]
+ )
diff --git a/setup.cfg b/setup.cfg
index 9c53e32ad..61c868a16 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -32,6 +32,7 @@ pg8000=postgresql+pg8000://scott:tiger@127.0.0.1:5432/test
postgresql_jython=postgresql+zxjdbc://scott:tiger@127.0.0.1:5432/test
mysql_jython=mysql+zxjdbc://scott:tiger@127.0.0.1:5432/test
mysql=mysql://scott:tiger@127.0.0.1:3306/test
+mssql=mssql+pyodbc://scott:tiger@ms_2005
oursql=mysql+oursql://scott:tiger@127.0.0.1:3306/test
pymysql=mysql+pymysql://scott:tiger@127.0.0.1:3306/test?use_unicode=0&charset=utf8
oracle=oracle://scott:tiger@127.0.0.1:1521
diff --git a/test/dialect/test_mysql.py b/test/dialect/test_mysql.py
index 728098d3a..2c459dead 100644
--- a/test/dialect/test_mysql.py
+++ b/test/dialect/test_mysql.py
@@ -82,6 +82,19 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL):
"PRIMARY KEY (data) USING btree)",
dialect=mysql.dialect())
+ def test_skip_deferrable_kw(self):
+ m = MetaData()
+ t1 = Table('t1', m, Column('id', Integer, primary_key=True))
+ t2 = Table('t2', m, Column('id', Integer,
+ ForeignKey('t1.id', deferrable=True),
+ primary_key=True))
+
+ self.assert_compile(
+ schema.CreateTable(t2),
+ "CREATE TABLE t2 (id INTEGER NOT NULL, "
+ "PRIMARY KEY (id), FOREIGN KEY(id) REFERENCES t1 (id))"
+ )
+
class DialectTest(fixtures.TestBase):
__only_on__ = 'mysql'
diff --git a/test/engine/test_reflection.py b/test/engine/test_reflection.py
index a562ef73b..ac0fa5153 100644
--- a/test/engine/test_reflection.py
+++ b/test/engine/test_reflection.py
@@ -1146,15 +1146,13 @@ class UnicodeReflectionTest(fixtures.TestBase):
class SchemaTest(fixtures.TestBase):
@testing.requires.schemas
- @testing.fails_on_everything_except("postgresql", "unimplemented feature")
+ @testing.requires.cross_schema_fk_reflection
def test_has_schema(self):
eq_(testing.db.dialect.has_schema(testing.db, 'test_schema'), True)
eq_(testing.db.dialect.has_schema(testing.db, 'sa_fake_schema_123'), False)
- @testing.crashes('firebird', 'No schema support')
+ @testing.requires.schemas
@testing.fails_on('sqlite', 'FIXME: unknown')
- # fixme: revisit these below.
- @testing.fails_on('access', 'FIXME: unknown')
@testing.fails_on('sybase', 'FIXME: unknown')
def test_explicit_default_schema(self):
engine = testing.db
@@ -1193,9 +1191,7 @@ class SchemaTest(fixtures.TestBase):
finally:
metadata.drop_all()
- @testing.crashes('firebird', 'No schema support')
- # fixme: revisit these below.
- @testing.fails_on('access', 'FIXME: unknown')
+ @testing.requires.schemas
@testing.fails_on('sybase', 'FIXME: unknown')
def test_explicit_default_schema_metadata(self):
engine = testing.db
@@ -1245,6 +1241,31 @@ class SchemaTest(fixtures.TestBase):
'test_schema.email_addresses'])
)
+ @testing.requires.schemas
+ @testing.requires.cross_schema_fk_reflection
+ @testing.provide_metadata
+ def test_reflect_all_schemas_default_overlap(self):
+ t1 = Table('t', self.metadata,
+ Column('id', Integer, primary_key=True))
+
+ t2 = Table('t', self.metadata,
+ Column('id1', sa.ForeignKey('t.id')),
+ schema="test_schema"
+ )
+
+ self.metadata.create_all()
+ m2 = MetaData()
+ m2.reflect(testing.db, schema="test_schema")
+
+ m3 = MetaData()
+ m3.reflect(testing.db)
+ m3.reflect(testing.db, schema="test_schema")
+
+ eq_(
+ set((t.name, t.schema) for t in m2.tables.values()),
+ set((t.name, t.schema) for t in m3.tables.values())
+ )
+
diff --git a/test/ext/test_mutable.py b/test/ext/test_mutable.py
index 4516e3ac2..bda9e5382 100644
--- a/test/ext/test_mutable.py
+++ b/test/ext/test_mutable.py
@@ -74,6 +74,18 @@ class _MutableDictTestBase(object):
eq_(f1.data, {'a': 'c'})
+ def test_clear(self):
+ sess = Session()
+
+ f1 = Foo(data={'a': 'b'})
+ sess.add(f1)
+ sess.commit()
+
+ f1.data.clear()
+ sess.commit()
+
+ eq_(f1.data, {})
+
def test_replace(self):
sess = Session()
f1 = Foo(data={'a': 'b'})
diff --git a/test/orm/test_eager_relations.py b/test/orm/test_eager_relations.py
index d59d515f4..52f45a2d4 100644
--- a/test/orm/test_eager_relations.py
+++ b/test/orm/test_eager_relations.py
@@ -1386,8 +1386,7 @@ class SubqueryAliasingTest(fixtures.MappedTest, testing.AssertsCompiledSQL):
"AS anon_1_a_id, b_1.id AS b_1_id, b_1.a_id AS "
"b_1_a_id, b_1.value AS b_1_value FROM (SELECT "
"(SELECT sum(b.value) AS sum_1 FROM b WHERE b.a_id = a.id) "
- "AS anon_2, a.id AS a_id FROM a ORDER BY (SELECT "
- "sum(b.value) AS sum_1 FROM b WHERE b.a_id = a.id) "
+ "AS anon_2, a.id AS a_id FROM a ORDER BY anon_2 "
"LIMIT :param_1) AS anon_1 LEFT OUTER JOIN b AS b_1 ON "
"anon_1.a_id = b_1.a_id ORDER BY anon_1.anon_2"
)
@@ -1409,8 +1408,7 @@ class SubqueryAliasingTest(fixtures.MappedTest, testing.AssertsCompiledSQL):
"AS anon_1_a_id, b_1.id AS b_1_id, b_1.a_id AS "
"b_1_a_id, b_1.value AS b_1_value FROM (SELECT "
"(SELECT sum(b.value) AS sum_1 FROM b WHERE b.a_id = a.id) "
- "AS anon_2, a.id AS a_id FROM a ORDER BY (SELECT "
- "sum(b.value) AS sum_1 FROM b WHERE b.a_id = a.id) DESC "
+ "AS anon_2, a.id AS a_id FROM a ORDER BY anon_2 DESC "
"LIMIT :param_1) AS anon_1 LEFT OUTER JOIN b AS b_1 ON "
"anon_1.a_id = b_1.a_id ORDER BY anon_1.anon_2 DESC"
)
@@ -1433,8 +1431,7 @@ class SubqueryAliasingTest(fixtures.MappedTest, testing.AssertsCompiledSQL):
"AS anon_1_a_id, b_1.id AS b_1_id, b_1.a_id AS "
"b_1_a_id, b_1.value AS b_1_value FROM (SELECT "
"(SELECT sum(b.value) AS sum_1 FROM b WHERE b.a_id = a.id) "
- "AS anon_2, a.id AS a_id FROM a ORDER BY (SELECT "
- "sum(b.value) AS sum_1 FROM b WHERE b.a_id = a.id) "
+ "AS anon_2, a.id AS a_id FROM a ORDER BY anon_2 "
"LIMIT :param_1) AS anon_1 LEFT OUTER JOIN b AS b_1 ON "
"anon_1.a_id = b_1.a_id ORDER BY anon_1.anon_2"
)
@@ -1479,8 +1476,7 @@ class SubqueryAliasingTest(fixtures.MappedTest, testing.AssertsCompiledSQL):
"AS anon_1_foo, b_1.id AS b_1_id, b_1.a_id AS "
"b_1_a_id, b_1.value AS b_1_value FROM (SELECT a.id "
"AS a_id, (SELECT sum(b.value) AS sum_1 FROM b WHERE "
- "b.a_id = a.id) AS foo FROM a ORDER BY (SELECT "
- "sum(b.value) AS sum_1 FROM b WHERE b.a_id = a.id) "
+ "b.a_id = a.id) AS foo FROM a ORDER BY foo "
"LIMIT :param_1) AS anon_1 LEFT OUTER JOIN b AS b_1 "
"ON anon_1.a_id = b_1.a_id ORDER BY "
"anon_1.foo"
diff --git a/test/profiles.txt b/test/profiles.txt
index 74c61a07e..4d8964639 100644
--- a/test/profiles.txt
+++ b/test/profiles.txt
@@ -1,27 +1,29 @@
-# /Users/classic/dev/sqlalchemy/test/profiles.txt
+# /mnt/hgfs/classic/dev/sqlalchemy/test/profiles.txt
# This file is written out on a per-environment basis.
-# For each test in aaa_profiling, the corresponding function and
+# For each test in aaa_profiling, the corresponding function and
# environment is located within this file. If it doesn't exist,
# the test is skipped.
-# If a callcount does exist, it is compared to what we received.
+# If a callcount does exist, it is compared to what we received.
# assertions are raised if the counts do not match.
-#
-# To add a new callcount test, apply the function_call_count
-# decorator and re-run the tests using the --write-profiles
+#
+# To add a new callcount test, apply the function_call_count
+# decorator and re-run the tests using the --write-profiles
# option - this file will be rewritten including the new count.
-#
+#
# TEST: test.aaa_profiling.test_compiler.CompileTest.test_insert
test.aaa_profiling.test_compiler.CompileTest.test_insert 2.6_sqlite_pysqlite_nocextensions 67
test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_mysql_mysqldb_cextensions 67
test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_mysql_mysqldb_nocextensions 67
+test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_oracle_cx_oracle_nocextensions 67
test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_postgresql_psycopg2_cextensions 67
test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_postgresql_psycopg2_nocextensions 67
test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_sqlite_pysqlite_cextensions 67
test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_sqlite_pysqlite_nocextensions 67
test.aaa_profiling.test_compiler.CompileTest.test_insert 3.2_postgresql_psycopg2_nocextensions 69
test.aaa_profiling.test_compiler.CompileTest.test_insert 3.2_sqlite_pysqlite_nocextensions 69
+test.aaa_profiling.test_compiler.CompileTest.test_insert 3.3_oracle_cx_oracle_nocextensions 71
test.aaa_profiling.test_compiler.CompileTest.test_insert 3.3_postgresql_psycopg2_nocextensions 69
test.aaa_profiling.test_compiler.CompileTest.test_insert 3.3_sqlite_pysqlite_nocextensions 69
@@ -30,12 +32,14 @@ test.aaa_profiling.test_compiler.CompileTest.test_insert 3.3_sqlite_pysqlite_noc
test.aaa_profiling.test_compiler.CompileTest.test_select 2.6_sqlite_pysqlite_nocextensions 141
test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_mysql_mysqldb_cextensions 141
test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_mysql_mysqldb_nocextensions 141
+test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_oracle_cx_oracle_nocextensions 141
test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_postgresql_psycopg2_cextensions 141
test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_postgresql_psycopg2_nocextensions 141
test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_sqlite_pysqlite_cextensions 141
test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_sqlite_pysqlite_nocextensions 141
test.aaa_profiling.test_compiler.CompileTest.test_select 3.2_postgresql_psycopg2_nocextensions 151
test.aaa_profiling.test_compiler.CompileTest.test_select 3.2_sqlite_pysqlite_nocextensions 151
+test.aaa_profiling.test_compiler.CompileTest.test_select 3.3_oracle_cx_oracle_nocextensions 153
test.aaa_profiling.test_compiler.CompileTest.test_select 3.3_postgresql_psycopg2_nocextensions 151
test.aaa_profiling.test_compiler.CompileTest.test_select 3.3_sqlite_pysqlite_nocextensions 151
@@ -44,12 +48,14 @@ test.aaa_profiling.test_compiler.CompileTest.test_select 3.3_sqlite_pysqlite_noc
test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.6_sqlite_pysqlite_nocextensions 175
test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_mysql_mysqldb_cextensions 175
test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_mysql_mysqldb_nocextensions 175
+test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_oracle_cx_oracle_nocextensions 175
test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_postgresql_psycopg2_cextensions 175
test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_postgresql_psycopg2_nocextensions 175
test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_sqlite_pysqlite_cextensions 175
test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_sqlite_pysqlite_nocextensions 175
test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.2_postgresql_psycopg2_nocextensions 185
test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.2_sqlite_pysqlite_nocextensions 185
+test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.3_oracle_cx_oracle_nocextensions 187
test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.3_postgresql_psycopg2_nocextensions 185
test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.3_sqlite_pysqlite_nocextensions 185
@@ -58,12 +64,14 @@ test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.3_sqlite_pysql
test.aaa_profiling.test_compiler.CompileTest.test_update 2.6_sqlite_pysqlite_nocextensions 70
test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_mysql_mysqldb_cextensions 70
test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_mysql_mysqldb_nocextensions 70
+test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_oracle_cx_oracle_nocextensions 70
test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_postgresql_psycopg2_cextensions 70
test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_postgresql_psycopg2_nocextensions 70
test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_sqlite_pysqlite_cextensions 70
test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_sqlite_pysqlite_nocextensions 70
test.aaa_profiling.test_compiler.CompileTest.test_update 3.2_postgresql_psycopg2_nocextensions 70
test.aaa_profiling.test_compiler.CompileTest.test_update 3.2_sqlite_pysqlite_nocextensions 70
+test.aaa_profiling.test_compiler.CompileTest.test_update 3.3_oracle_cx_oracle_nocextensions 72
test.aaa_profiling.test_compiler.CompileTest.test_update 3.3_postgresql_psycopg2_nocextensions 70
test.aaa_profiling.test_compiler.CompileTest.test_update 3.3_sqlite_pysqlite_nocextensions 70
@@ -72,12 +80,14 @@ test.aaa_profiling.test_compiler.CompileTest.test_update 3.3_sqlite_pysqlite_noc
test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.6_sqlite_pysqlite_nocextensions 137
test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_mysql_mysqldb_cextensions 137
test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_mysql_mysqldb_nocextensions 137
+test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_oracle_cx_oracle_nocextensions 137
test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_postgresql_psycopg2_cextensions 137
test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_postgresql_psycopg2_nocextensions 137
test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_sqlite_pysqlite_cextensions 137
test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_sqlite_pysqlite_nocextensions 137
test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.2_postgresql_psycopg2_nocextensions 136
test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.2_sqlite_pysqlite_nocextensions 136
+test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.3_oracle_cx_oracle_nocextensions 138
test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.3_postgresql_psycopg2_nocextensions 136
test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.3_sqlite_pysqlite_nocextensions 136
@@ -86,12 +96,14 @@ test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.3_sqlite_
test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity 2.6_sqlite_pysqlite_nocextensions 17987
test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity 2.7_mysql_mysqldb_cextensions 17987
test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity 2.7_mysql_mysqldb_nocextensions 17987
+test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity 2.7_oracle_cx_oracle_nocextensions 17987
test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity 2.7_postgresql_psycopg2_cextensions 17987
test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity 2.7_postgresql_psycopg2_nocextensions 17987
test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity 2.7_sqlite_pysqlite_cextensions 17987
test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity 2.7_sqlite_pysqlite_nocextensions 17987
test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity 3.2_postgresql_psycopg2_nocextensions 18987
test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity 3.2_sqlite_pysqlite_nocextensions 18987
+test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity 3.3_oracle_cx_oracle_nocextensions 18987
test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity 3.3_postgresql_psycopg2_nocextensions 18987
test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity 3.3_sqlite_pysqlite_nocextensions 18987
@@ -100,12 +112,14 @@ test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_
test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.6_sqlite_pysqlite_nocextensions 154319
test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.7_mysql_mysqldb_cextensions 124069
test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.7_mysql_mysqldb_nocextensions 126819
+test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.7_oracle_cx_oracle_nocextensions 128319
test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.7_postgresql_psycopg2_cextensions 116569
test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.7_postgresql_psycopg2_nocextensions 119319
test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.7_sqlite_pysqlite_cextensions 151569
test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.7_sqlite_pysqlite_nocextensions 154319
test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 3.2_postgresql_psycopg2_nocextensions 121790
test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 3.2_sqlite_pysqlite_nocextensions 121822
+test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 3.3_oracle_cx_oracle_nocextensions 130792
test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 3.3_postgresql_psycopg2_nocextensions 121822
# TEST: test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks
@@ -113,11 +127,13 @@ test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_
test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.6_sqlite_pysqlite_nocextensions 21744
test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.7_mysql_mysqldb_cextensions 19838
test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.7_mysql_mysqldb_nocextensions 20098
+test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.7_oracle_cx_oracle_nocextensions 20152
test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.7_postgresql_psycopg2_cextensions 19237
test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.7_postgresql_psycopg2_nocextensions 19467
test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.7_sqlite_pysqlite_cextensions 21530
test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.7_sqlite_pysqlite_nocextensions 21790
test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 3.2_postgresql_psycopg2_nocextensions 20424
+test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 3.3_oracle_cx_oracle_nocextensions 21244
test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 3.3_postgresql_psycopg2_nocextensions 20344
# TEST: test.aaa_profiling.test_orm.MergeTest.test_merge_load
@@ -125,11 +141,13 @@ test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 3.
test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.6_sqlite_pysqlite_nocextensions 1521
test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_mysql_mysqldb_cextensions 1388
test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_mysql_mysqldb_nocextensions 1413
+test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_oracle_cx_oracle_nocextensions 1349
test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_postgresql_psycopg2_cextensions 1296
test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_postgresql_psycopg2_nocextensions 1321
test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_sqlite_pysqlite_cextensions 1496
test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_sqlite_pysqlite_nocextensions 1521
test.aaa_profiling.test_orm.MergeTest.test_merge_load 3.2_postgresql_psycopg2_nocextensions 1332
+test.aaa_profiling.test_orm.MergeTest.test_merge_load 3.3_oracle_cx_oracle_nocextensions 1366
test.aaa_profiling.test_orm.MergeTest.test_merge_load 3.3_postgresql_psycopg2_nocextensions 1357
# TEST: test.aaa_profiling.test_orm.MergeTest.test_merge_no_load
@@ -137,12 +155,14 @@ test.aaa_profiling.test_orm.MergeTest.test_merge_load 3.3_postgresql_psycopg2_no
test.aaa_profiling.test_orm.MergeTest.test_merge_no_load 2.6_sqlite_pysqlite_nocextensions 122,18
test.aaa_profiling.test_orm.MergeTest.test_merge_no_load 2.7_mysql_mysqldb_cextensions 122,18
test.aaa_profiling.test_orm.MergeTest.test_merge_no_load 2.7_mysql_mysqldb_nocextensions 122,18
+test.aaa_profiling.test_orm.MergeTest.test_merge_no_load 2.7_oracle_cx_oracle_nocextensions 122,18
test.aaa_profiling.test_orm.MergeTest.test_merge_no_load 2.7_postgresql_psycopg2_cextensions 122,18
test.aaa_profiling.test_orm.MergeTest.test_merge_no_load 2.7_postgresql_psycopg2_nocextensions 122,18
test.aaa_profiling.test_orm.MergeTest.test_merge_no_load 2.7_sqlite_pysqlite_cextensions 122,18
test.aaa_profiling.test_orm.MergeTest.test_merge_no_load 2.7_sqlite_pysqlite_nocextensions 122,18
test.aaa_profiling.test_orm.MergeTest.test_merge_no_load 3.2_postgresql_psycopg2_nocextensions 127,19
test.aaa_profiling.test_orm.MergeTest.test_merge_no_load 3.2_sqlite_pysqlite_nocextensions 127,19
+test.aaa_profiling.test_orm.MergeTest.test_merge_no_load 3.3_oracle_cx_oracle_nocextensions 134,19
test.aaa_profiling.test_orm.MergeTest.test_merge_no_load 3.3_postgresql_psycopg2_nocextensions 127,19
test.aaa_profiling.test_orm.MergeTest.test_merge_no_load 3.3_sqlite_pysqlite_nocextensions 127,19
@@ -151,12 +171,14 @@ test.aaa_profiling.test_orm.MergeTest.test_merge_no_load 3.3_sqlite_pysqlite_noc
test.aaa_profiling.test_pool.QueuePoolTest.test_first_connect 2.6_sqlite_pysqlite_nocextensions 82
test.aaa_profiling.test_pool.QueuePoolTest.test_first_connect 2.7_mysql_mysqldb_cextensions 82
test.aaa_profiling.test_pool.QueuePoolTest.test_first_connect 2.7_mysql_mysqldb_nocextensions 82
+test.aaa_profiling.test_pool.QueuePoolTest.test_first_connect 2.7_oracle_cx_oracle_nocextensions 82
test.aaa_profiling.test_pool.QueuePoolTest.test_first_connect 2.7_postgresql_psycopg2_cextensions 82
test.aaa_profiling.test_pool.QueuePoolTest.test_first_connect 2.7_postgresql_psycopg2_nocextensions 82
test.aaa_profiling.test_pool.QueuePoolTest.test_first_connect 2.7_sqlite_pysqlite_cextensions 82
test.aaa_profiling.test_pool.QueuePoolTest.test_first_connect 2.7_sqlite_pysqlite_nocextensions 82
test.aaa_profiling.test_pool.QueuePoolTest.test_first_connect 3.2_postgresql_psycopg2_nocextensions 70
test.aaa_profiling.test_pool.QueuePoolTest.test_first_connect 3.2_sqlite_pysqlite_nocextensions 70
+test.aaa_profiling.test_pool.QueuePoolTest.test_first_connect 3.3_oracle_cx_oracle_nocextensions 69
test.aaa_profiling.test_pool.QueuePoolTest.test_first_connect 3.3_postgresql_psycopg2_nocextensions 69
test.aaa_profiling.test_pool.QueuePoolTest.test_first_connect 3.3_sqlite_pysqlite_nocextensions 69
@@ -165,12 +187,14 @@ test.aaa_profiling.test_pool.QueuePoolTest.test_first_connect 3.3_sqlite_pysqlit
test.aaa_profiling.test_pool.QueuePoolTest.test_second_connect 2.6_sqlite_pysqlite_nocextensions 29
test.aaa_profiling.test_pool.QueuePoolTest.test_second_connect 2.7_mysql_mysqldb_cextensions 29
test.aaa_profiling.test_pool.QueuePoolTest.test_second_connect 2.7_mysql_mysqldb_nocextensions 29
+test.aaa_profiling.test_pool.QueuePoolTest.test_second_connect 2.7_oracle_cx_oracle_nocextensions 29
test.aaa_profiling.test_pool.QueuePoolTest.test_second_connect 2.7_postgresql_psycopg2_cextensions 29
test.aaa_profiling.test_pool.QueuePoolTest.test_second_connect 2.7_postgresql_psycopg2_nocextensions 29
test.aaa_profiling.test_pool.QueuePoolTest.test_second_connect 2.7_sqlite_pysqlite_cextensions 29
test.aaa_profiling.test_pool.QueuePoolTest.test_second_connect 2.7_sqlite_pysqlite_nocextensions 29
test.aaa_profiling.test_pool.QueuePoolTest.test_second_connect 3.2_postgresql_psycopg2_nocextensions 23
test.aaa_profiling.test_pool.QueuePoolTest.test_second_connect 3.2_sqlite_pysqlite_nocextensions 23
+test.aaa_profiling.test_pool.QueuePoolTest.test_second_connect 3.3_oracle_cx_oracle_nocextensions 22
test.aaa_profiling.test_pool.QueuePoolTest.test_second_connect 3.3_postgresql_psycopg2_nocextensions 22
test.aaa_profiling.test_pool.QueuePoolTest.test_second_connect 3.3_sqlite_pysqlite_nocextensions 22
@@ -179,12 +203,14 @@ test.aaa_profiling.test_pool.QueuePoolTest.test_second_connect 3.3_sqlite_pysqli
test.aaa_profiling.test_pool.QueuePoolTest.test_second_samethread_connect 2.6_sqlite_pysqlite_nocextensions 6
test.aaa_profiling.test_pool.QueuePoolTest.test_second_samethread_connect 2.7_mysql_mysqldb_cextensions 6
test.aaa_profiling.test_pool.QueuePoolTest.test_second_samethread_connect 2.7_mysql_mysqldb_nocextensions 6
+test.aaa_profiling.test_pool.QueuePoolTest.test_second_samethread_connect 2.7_oracle_cx_oracle_nocextensions 6
test.aaa_profiling.test_pool.QueuePoolTest.test_second_samethread_connect 2.7_postgresql_psycopg2_cextensions 6
test.aaa_profiling.test_pool.QueuePoolTest.test_second_samethread_connect 2.7_postgresql_psycopg2_nocextensions 6
test.aaa_profiling.test_pool.QueuePoolTest.test_second_samethread_connect 2.7_sqlite_pysqlite_cextensions 6
test.aaa_profiling.test_pool.QueuePoolTest.test_second_samethread_connect 2.7_sqlite_pysqlite_nocextensions 6
test.aaa_profiling.test_pool.QueuePoolTest.test_second_samethread_connect 3.2_postgresql_psycopg2_nocextensions 7
test.aaa_profiling.test_pool.QueuePoolTest.test_second_samethread_connect 3.2_sqlite_pysqlite_nocextensions 7
+test.aaa_profiling.test_pool.QueuePoolTest.test_second_samethread_connect 3.3_oracle_cx_oracle_nocextensions 7
test.aaa_profiling.test_pool.QueuePoolTest.test_second_samethread_connect 3.3_postgresql_psycopg2_nocextensions 7
test.aaa_profiling.test_pool.QueuePoolTest.test_second_samethread_connect 3.3_sqlite_pysqlite_nocextensions 7
@@ -193,12 +219,14 @@ test.aaa_profiling.test_pool.QueuePoolTest.test_second_samethread_connect 3.3_sq
test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_connection_execute 2.6_sqlite_pysqlite_nocextensions 43
test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_connection_execute 2.7_mysql_mysqldb_cextensions 41
test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_connection_execute 2.7_mysql_mysqldb_nocextensions 43
+test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_connection_execute 2.7_oracle_cx_oracle_nocextensions 43
test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_connection_execute 2.7_postgresql_psycopg2_cextensions 41
test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_connection_execute 2.7_postgresql_psycopg2_nocextensions 43
test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_connection_execute 2.7_sqlite_pysqlite_cextensions 41
test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_connection_execute 2.7_sqlite_pysqlite_nocextensions 43
test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_connection_execute 3.2_postgresql_psycopg2_nocextensions 41
test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_connection_execute 3.2_sqlite_pysqlite_nocextensions 41
+test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_connection_execute 3.3_oracle_cx_oracle_nocextensions 41
test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_connection_execute 3.3_postgresql_psycopg2_nocextensions 41
test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_connection_execute 3.3_sqlite_pysqlite_nocextensions 41
@@ -207,12 +235,14 @@ test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_connection_execute
test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_engine_execute 2.6_sqlite_pysqlite_nocextensions 68
test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_engine_execute 2.7_mysql_mysqldb_cextensions 66
test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_engine_execute 2.7_mysql_mysqldb_nocextensions 68
+test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_engine_execute 2.7_oracle_cx_oracle_nocextensions 68
test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_engine_execute 2.7_postgresql_psycopg2_cextensions 66
test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_engine_execute 2.7_postgresql_psycopg2_nocextensions 68
test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_engine_execute 2.7_sqlite_pysqlite_cextensions 66
test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_engine_execute 2.7_sqlite_pysqlite_nocextensions 68
test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_engine_execute 3.2_postgresql_psycopg2_nocextensions 66
test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_engine_execute 3.2_sqlite_pysqlite_nocextensions 66
+test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_engine_execute 3.3_oracle_cx_oracle_nocextensions 66
test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_engine_execute 3.3_postgresql_psycopg2_nocextensions 66
test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_engine_execute 3.3_sqlite_pysqlite_nocextensions 66
@@ -221,12 +251,14 @@ test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_engine_execute 3.3_
test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.6_sqlite_pysqlite_nocextensions 14
test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.7_mysql_mysqldb_cextensions 14
test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.7_mysql_mysqldb_nocextensions 14
+test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.7_oracle_cx_oracle_nocextensions 14
test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.7_postgresql_psycopg2_cextensions 14
test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.7_postgresql_psycopg2_nocextensions 14
test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.7_sqlite_pysqlite_cextensions 14
test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.7_sqlite_pysqlite_nocextensions 14
test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 3.2_postgresql_psycopg2_nocextensions 15
test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 3.2_sqlite_pysqlite_nocextensions 15
+test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 3.3_oracle_cx_oracle_nocextensions 15
test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 3.3_postgresql_psycopg2_nocextensions 15
test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 3.3_sqlite_pysqlite_nocextensions 15
@@ -235,12 +267,14 @@ test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 3.3
test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.6_sqlite_pysqlite_nocextensions 15447
test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_mysql_mysqldb_cextensions 485
test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_mysql_mysqldb_nocextensions 15505
+test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_oracle_cx_oracle_nocextensions 35582
test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_postgresql_psycopg2_cextensions 20471
test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_postgresql_psycopg2_nocextensions 35491
test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_sqlite_pysqlite_cextensions 427
test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_sqlite_pysqlite_nocextensions 15447
test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.2_postgresql_psycopg2_nocextensions 14459
test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.2_sqlite_pysqlite_nocextensions 14430
+test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.3_oracle_cx_oracle_nocextensions 14548
test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.3_postgresql_psycopg2_nocextensions 14457
test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.3_sqlite_pysqlite_nocextensions 14430
@@ -249,12 +283,14 @@ test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.3_sqlite_pysqlite_
test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.6_sqlite_pysqlite_nocextensions 15447
test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_mysql_mysqldb_cextensions 485
test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_mysql_mysqldb_nocextensions 45505
+test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_oracle_cx_oracle_nocextensions 35572
test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_postgresql_psycopg2_cextensions 20471
test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_postgresql_psycopg2_nocextensions 35491
test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_sqlite_pysqlite_cextensions 427
test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_sqlite_pysqlite_nocextensions 15447
test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.2_postgresql_psycopg2_nocextensions 14459
test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.2_sqlite_pysqlite_nocextensions 14430
+test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.3_oracle_cx_oracle_nocextensions 14548
test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.3_postgresql_psycopg2_nocextensions 14457
test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.3_sqlite_pysqlite_nocextensions 14430
diff --git a/test/requirements.py b/test/requirements.py
index c09c0df99..78544a396 100644
--- a/test/requirements.py
+++ b/test/requirements.py
@@ -240,6 +240,13 @@ class DefaultRequirements(SuiteRequirements):
"firebird"
], "no schema support")
+ @property
+ def cross_schema_fk_reflection(self):
+ """target system must support reflection of inter-schema foreign keys
+ """
+ return only_on([
+ "postgresql"
+ ])
@property
def update_nowait(self):
diff --git a/test/sql/test_compiler.py b/test/sql/test_compiler.py
index 9cb0e6bbe..473a422a2 100644
--- a/test/sql/test_compiler.py
+++ b/test/sql/test_compiler.py
@@ -748,6 +748,77 @@ class SelectTest(fixtures.TestBase, AssertsCompiledSQL):
'foo || :param_1')
+ def test_order_by_labels_enabled(self):
+ lab1 = (table1.c.myid + 12).label('foo')
+ lab2 = func.somefunc(table1.c.name).label('bar')
+ dialect = default.DefaultDialect()
+
+ self.assert_compile(select([lab1, lab2]).order_by(lab1, desc(lab2)),
+ "SELECT mytable.myid + :myid_1 AS foo, "
+ "somefunc(mytable.name) AS bar FROM mytable "
+ "ORDER BY foo, bar DESC",
+ dialect=dialect
+ )
+
+ # the function embedded label renders as the function
+ self.assert_compile(
+ select([lab1, lab2]).order_by(func.hoho(lab1), desc(lab2)),
+ "SELECT mytable.myid + :myid_1 AS foo, "
+ "somefunc(mytable.name) AS bar FROM mytable "
+ "ORDER BY hoho(mytable.myid + :myid_1), bar DESC",
+ dialect=dialect
+ )
+
+ # binary expressions render as the expression without labels
+ self.assert_compile(select([lab1, lab2]).order_by(lab1 + "test"),
+ "SELECT mytable.myid + :myid_1 AS foo, "
+ "somefunc(mytable.name) AS bar FROM mytable "
+ "ORDER BY mytable.myid + :myid_1 + :param_1",
+ dialect=dialect
+ )
+
+ # labels within functions in the columns clause render
+ # with the expression
+ self.assert_compile(
+ select([lab1, func.foo(lab1)]).order_by(lab1, func.foo(lab1)),
+ "SELECT mytable.myid + :myid_1 AS foo, "
+ "foo(mytable.myid + :myid_1) AS foo_1 FROM mytable "
+ "ORDER BY foo, foo(mytable.myid + :myid_1)",
+ dialect=dialect
+ )
+
+
+ lx = (table1.c.myid + table1.c.myid).label('lx')
+ ly = (func.lower(table1.c.name) + table1.c.description).label('ly')
+
+ self.assert_compile(
+ select([lx, ly]).order_by(lx, ly.desc()),
+ "SELECT mytable.myid + mytable.myid AS lx, "
+ "lower(mytable.name) || mytable.description AS ly "
+ "FROM mytable ORDER BY lx, ly DESC",
+ dialect=dialect
+ )
+
+ def test_order_by_labels_disabled(self):
+ lab1 = (table1.c.myid + 12).label('foo')
+ lab2 = func.somefunc(table1.c.name).label('bar')
+ dialect = default.DefaultDialect()
+ dialect.supports_simple_order_by_label = False
+ self.assert_compile(select([lab1, lab2]).order_by(lab1, desc(lab2)),
+ "SELECT mytable.myid + :myid_1 AS foo, "
+ "somefunc(mytable.name) AS bar FROM mytable "
+ "ORDER BY mytable.myid + :myid_1, somefunc(mytable.name) DESC",
+ dialect=dialect
+ )
+ self.assert_compile(
+ select([lab1, lab2]).order_by(func.hoho(lab1), desc(lab2)),
+ "SELECT mytable.myid + :myid_1 AS foo, "
+ "somefunc(mytable.name) AS bar FROM mytable "
+ "ORDER BY hoho(mytable.myid + :myid_1), "
+ "somefunc(mytable.name) DESC",
+ dialect=dialect
+ )
+
def test_conjunctions(self):
a, b, c = 'a', 'b', 'c'
x = and_(a, b, c)
diff --git a/test/sql/test_metadata.py b/test/sql/test_metadata.py
index c0873862d..8f0280765 100644
--- a/test/sql/test_metadata.py
+++ b/test/sql/test_metadata.py
@@ -1211,6 +1211,30 @@ class ConstraintTest(fixtures.TestBase):
schema.CreateTable(t1).compile
)
+ def test_constraint_copied_to_proxy_ok(self):
+ m = MetaData()
+ t1 = Table('t1', m, Column('id', Integer, primary_key=True))
+ t2 = Table('t2', m, Column('id', Integer, ForeignKey('t1.id'),
+ primary_key=True))
+
+ s = tsa.select([t2])
+ t2fk = list(t2.c.id.foreign_keys)[0]
+ sfk = list(s.c.id.foreign_keys)[0]
+
+ # the two FKs share the ForeignKeyConstraint
+ is_(
+ t2fk.constraint,
+ sfk.constraint
+ )
+
+ # but the ForeignKeyConstraint isn't
+ # aware of the select's FK
+ eq_(
+ t2fk.constraint.elements,
+ [t2fk]
+ )
+
+
class ColumnDefinitionTest(AssertsCompiledSQL, fixtures.TestBase):
"""Test Column() construction."""
diff --git a/test/sql/test_operators.py b/test/sql/test_operators.py
index d1db733e0..b3919d0da 100644
--- a/test/sql/test_operators.py
+++ b/test/sql/test_operators.py
@@ -15,7 +15,7 @@ from sqlalchemy.dialects import mysql, firebird, postgresql, oracle, \
sqlite, mssql
from sqlalchemy import util
import datetime
-
+import collections
from sqlalchemy import text, literal_column
class LoopOperate(operators.ColumnOperators):
@@ -352,17 +352,16 @@ class ExtensionOperatorTest(fixtures.TestBase, testing.AssertsCompiledSQL):
"x -> :x_1"
)
- def test_no_endless_list_call(self):
+ @testing.requires.python26
+ def test_op_not_an_iterator(self):
+ # see [ticket:2726]
class MyType(UserDefinedType):
class comparator_factory(UserDefinedType.Comparator):
def __getitem__(self, index):
return self.op("->")(index)
- assert_raises_message(
- NotImplementedError,
- "Class <class 'sqlalchemy.schema.Column'> is not iterable",
- list, Column('x', MyType())
- )
+ col = Column('x', MyType())
+ assert not isinstance(col, collections.Iterable)
def test_lshift(self):
class MyType(UserDefinedType):
diff --git a/test/sql/test_query.py b/test/sql/test_query.py
index 3e9045fa5..ae029b11c 100644
--- a/test/sql/test_query.py
+++ b/test/sql/test_query.py
@@ -708,8 +708,6 @@ class QueryTest(fixtures.TestBase):
use_labels=labels),
[(3, 'a'), (2, 'b'), (1, None)])
- @testing.fails_on('mssql+pyodbc',
- "pyodbc result row doesn't support slicing")
def test_column_slices(self):
users.insert().execute(user_id=1, user_name='john')
users.insert().execute(user_id=2, user_name='jack')
diff --git a/test/sql/test_selectable.py b/test/sql/test_selectable.py
index 2ef952c65..2ac04dce3 100644
--- a/test/sql/test_selectable.py
+++ b/test/sql/test_selectable.py
@@ -788,11 +788,16 @@ class JoinConditionTest(fixtures.TestBase, AssertsExecutionResults, AssertsCompi
Column('id', Integer),
Column('t1id', ForeignKey('t1.id')),
Column('t2id', ForeignKey('t2.id')))
- t4 = Table('t4', m,
- Column('id', Integer),
+ t4 = Table('t4', m, Column('id', Integer),
Column('t2id', ForeignKey('t2.id')))
+ t5 = Table('t5', m,
+ Column('t1id1', ForeignKey('t1.id')),
+ Column('t1id2', ForeignKey('t1.id')),
+ )
+
t1t2 = t1.join(t2)
t2t3 = t2.join(t3)
+
for (left, right, a_subset, expected) in [
(t1, t2, None, t1.c.id == t2.c.t1id),
(t1t2, t3, t2, t1t2.c.t2_id == t3.c.t2id),
@@ -806,12 +811,15 @@ class JoinConditionTest(fixtures.TestBase, AssertsExecutionResults, AssertsCompi
assert expected.compare(sql_util.join_condition(left,
right, a_subset=a_subset))
+
# these are ambiguous, or have no joins
for left, right, a_subset in [
(t1t2, t3, None),
(t2t3, t1, None),
(t1, t4, None),
(t1t2, t2t3, None),
+ (t5, t1, None),
+ (t5.select(use_labels=True), t1, None)
]:
assert_raises(
exc.ArgumentError,