.. changelog::
:version: 0.9.9
+ .. change::
+ :tags: bug, sql
+ :versions: 1.0.0
+ :tickets: 3248
+
+ Fixed issue where the columns from a SELECT embedded in an
+ INSERT, either through the values clause or as a "from select",
+ would pollute the column types used in the result set produced by
+ the RETURNING clause when columns from both statements shared the
+ same name, leading to potential errors or mis-adaptation when
+ retrieving the returning rows.
+
.. change::
:tags: bug, orm, sqlite
:versions: 1.0.0
)
def visit_insert(self, insert_stmt, **kw):
+ self.stack.append(
+ {'correlate_froms': set(),
+ "iswrapper": False,
+ "asfrom_froms": set(),
+ "selectable": insert_stmt})
+
self.isinsert = True
colparams = self._get_colparams(insert_stmt, **kw)
if self.returning and not self.returning_precedes_values:
text += " " + returning_clause
+ self.stack.pop(-1)
+
return text
def update_limit_clause(self, update_stmt):
is_(
comp.result_map['t1_a'][1][2], t1.c.a
)
+
+ def test_insert_with_select_values(self):
+ astring = Column('a', String)
+ aint = Column('a', Integer)
+ m = MetaData()
+ Table('t1', m, astring)
+ t2 = Table('t2', m, aint)
+
+ stmt = t2.insert().values(a=select([astring])).returning(aint)
+ comp = stmt.compile(dialect=postgresql.dialect())
+ eq_(
+ comp.result_map,
+ {'a': ('a', (aint, 'a', 'a'), aint.type)}
+ )
+
+ def test_insert_from_select(self):
+ astring = Column('a', String)
+ aint = Column('a', Integer)
+ m = MetaData()
+ Table('t1', m, astring)
+ t2 = Table('t2', m, aint)
+
+ stmt = t2.insert().from_select(['a'], select([astring])).\
+ returning(aint)
+ comp = stmt.compile(dialect=postgresql.dialect())
+ eq_(
+ comp.result_map,
+ {'a': ('a', (aint, 'a', 'a'), aint.type)}
+ )
eq_(result2.fetchall(), [(2, False), ])
+class CompositeStatementTest(fixtures.TestBase):
+ __requires__ = 'returning',
+ __backend__ = True
+
+ @testing.provide_metadata
+ def test_select_doesnt_pollute_result(self):
+ class MyType(TypeDecorator):
+ impl = Integer
+
+ def process_result_value(self, value, dialect):
+ raise Exception("I have not been selected")
+
+ t1 = Table(
+ 't1', self.metadata,
+ Column('x', MyType())
+ )
+
+ t2 = Table(
+ 't2', self.metadata,
+ Column('x', Integer)
+ )
+
+ self.metadata.create_all(testing.db)
+ with testing.db.connect() as conn:
+ conn.execute(t1.insert().values(x=5))
+
+ stmt = t2.insert().values(
+ x=select([t1.c.x]).as_scalar()).returning(t2.c.x)
+
+ result = conn.execute(stmt)
+ eq_(result.scalar(), 5)
+
+
class SequenceReturningTest(fixtures.TestBase):
__requires__ = 'returning', 'sequences'
__backend__ = True