.. 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
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__ = (
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
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
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):
':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, "
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])
)
"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)
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(),
[('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').\