]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Fixed bug in type_coerce() whereby typing information
authorMike Bayer <mike_mp@zzzcomputing.com>
Mon, 12 Nov 2012 20:48:40 +0000 (15:48 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Mon, 12 Nov 2012 20:48:40 +0000 (15:48 -0500)
could be lost if the statement were used as a subquery
inside of another statement, as well as other similar
situations.  Among other things, would cause
typing information to be lost when the Oracle/mssql dialects
would apply limit/offset wrappings. [ticket:2603]

doc/build/changelog/changelog_08.rst
lib/sqlalchemy/dialects/oracle/__init__.py
lib/sqlalchemy/dialects/oracle/base.py
lib/sqlalchemy/sql/expression.py
test/dialect/test_oracle.py
test/orm/test_query.py
test/sql/test_selectable.py
test/sql/test_types.py

index 0d552d54638538aaaca3bacd9e2af1304e39489b..0571798ce7bde8657c6ec5423df599ca60642e4c 100644 (file)
@@ -6,6 +6,17 @@
 .. changelog::
     :version: 0.8.0b2
 
+    .. change::
+        :tags: sql, bug
+        :tickets: 2603
+
+        Fixed bug in type_coerce() whereby typing information
+        could be lost if the statement were used as a subquery
+        inside of another statement, as well as other similar
+        situations.  Among other things, would cause
+        typing information to be lost when the Oracle/mssql dialects
+        would apply limit/offset wrappings.
+
     .. change::
         :tags: orm, bug
         :tickets: 2602
index 34192530a5ca89836f045450e20cf57c1f596603..a4235f0235c0273af66d5bd8ae190d29db65e5f4 100644 (file)
@@ -12,7 +12,7 @@ from sqlalchemy.dialects.oracle.base import \
     VARCHAR, NVARCHAR, CHAR, DATE, DATETIME, NUMBER,\
     BLOB, BFILE, CLOB, NCLOB, TIMESTAMP, RAW,\
     FLOAT, DOUBLE_PRECISION, LONG, dialect, INTERVAL,\
-    VARCHAR2, NVARCHAR2, ROWID
+    VARCHAR2, NVARCHAR2, ROWID, dialect
 
 
 __all__ = (
index 7b1470f63652a9a2fe99eee5528634a88b8b33dc..7a4d835c9af63aca2581c16da7864690cf052fdd 100644 (file)
@@ -586,7 +586,7 @@ class OracleCompiler(compiler.SQLCompiler):
                     limitselect._is_wrapper = True
 
                     offsetselect = sql.select(
-                             [c for c in limitselect.c if c.key!='ora_rn'])
+                             [c for c in limitselect.c if c.key != 'ora_rn'])
                     offsetselect._oracle_visit = True
                     offsetselect._is_wrapper = True
 
@@ -594,7 +594,7 @@ class OracleCompiler(compiler.SQLCompiler):
                     if not self.dialect.use_binds_for_limits:
                         offset_value = sql.literal_column("%d" % offset_value)
                     offsetselect.append_whereclause(
-                             sql.literal_column("ora_rn")>offset_value)
+                             sql.literal_column("ora_rn") > offset_value)
 
                     offsetselect.for_update = select.for_update
                     select = offsetselect
index 91f10cf3c1ea8da1b98f69e2b06ed7fa95ba2394..1d3be7de1795145b798897f561c285dfee56b6bc 100644 (file)
@@ -4256,6 +4256,8 @@ class Label(ColumnElement):
         e = self.element._make_proxy(selectable,
                                 name=name if name else self.name)
         e._proxies.append(self)
+        if self._type is not None:
+            e.type = self._type
         return e
 
 class ColumnClause(Immutable, ColumnElement):
index edb7be8402727b140ecbab47f4c3e9ba8ecd17ad..3e7ebf012155e3d765ecab5d1733399a6e3ca640 100644 (file)
@@ -206,9 +206,18 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL):
                             ':ROWNUM_1) WHERE ora_rn > :ora_rn_1 FOR '
                             'UPDATE')
 
+    def test_limit_preserves_typing_information(self):
+        class MyType(TypeDecorator):
+            impl = Integer
+
+        stmt = select([type_coerce(column('x'), MyType).label('foo')]).limit(1)
+        dialect = oracle.dialect()
+        compiled = stmt.compile(dialect=dialect)
+        assert isinstance(compiled.result_map['foo'][-1], MyType)
+
     def test_use_binds_for_limits_disabled(self):
         t = table('sometable', column('col1'), column('col2'))
-        dialect = oracle.OracleDialect(use_binds_for_limits = False)
+        dialect = oracle.OracleDialect(use_binds_for_limits=False)
 
         self.assert_compile(select([t]).limit(10),
                 "SELECT col1, col2 FROM (SELECT sometable.col1 AS col1, "
index 137fdcd95d3d3d14bbc1dd18a339b9ce707d68b0..9bf728de228fdba04697e0786650817ea98fd1d3 100644 (file)
@@ -133,9 +133,10 @@ class RowTupleTest(QueryTest):
         mapper(User, users)
 
         s = Session()
-        row = s.\
+        q = s.\
                     query(User, type_coerce(users.c.id, MyType).label('foo')).\
-                    filter(User.id == 7).first()
+                    filter(User.id == 7)
+        row = q.first()
         eq_(
             row, (User(id=7), [7])
         )
index 53c9018cdee314f5a063783e8d45002c02bfb2c2..65dc654702735857eaa9b7872340dbca1f7fb4f2 100644 (file)
@@ -228,6 +228,15 @@ class SelectableTest(fixtures.TestBase, AssertsExecutionResults, AssertsCompiled
             "table1.col3, table1.colx FROM table1) AS anon_1"
         )
 
+    def test_type_coerce_preserve_subq(self):
+        class MyType(TypeDecorator):
+            impl = Integer
+
+        stmt = select([type_coerce(column('x'), MyType).label('foo')])
+        stmt2 = stmt.select()
+        assert isinstance(stmt._raw_columns[0].type, MyType)
+        assert isinstance(stmt.c.foo.type, MyType)
+        assert isinstance(stmt2.c.foo.type, MyType)
 
     def test_select_on_table(self):
         sel = select([table1, table2], use_labels=True)
index 5f80e794718878250db6246c6fdb25cf9cae4176..b229694481d6f02e24d8c2c6152975119382ff16 100644 (file)
@@ -408,7 +408,7 @@ class UserDefinedTest(fixtures.TablesTest, AssertsCompiledSQL):
         t = Table('t', metadata, Column('data', String(50)))
         metadata.create_all()
 
-        t.insert().values(data=type_coerce('d1BIND_OUT',MyType)).execute()
+        t.insert().values(data=type_coerce('d1BIND_OUT', MyType)).execute()
 
         eq_(
             select([type_coerce(t.c.data, MyType)]).execute().fetchall(),
@@ -420,6 +420,11 @@ class UserDefinedTest(fixtures.TablesTest, AssertsCompiledSQL):
             [('d1', 'd1BIND_OUT')]
         )
 
+        eq_(
+            select([t.c.data, type_coerce(t.c.data, MyType)]).select().execute().fetchall(),
+            [('d1', 'd1BIND_OUT')]
+        )
+
         eq_(
             select([t.c.data, type_coerce(t.c.data, MyType)]).\
                         where(type_coerce(t.c.data, MyType) == 'd1BIND_OUT').\