_hints = util.immutabledict()
named_with_column = False
+ _return_defaults = None
+
is_dml = True
@classmethod
for server_flag, updated_timestamp in connection.execute(stmt):
print(server_flag, updated_timestamp)
- The given collection of column expressions should be derived from
- the table that is
- the target of the INSERT, UPDATE, or DELETE. While
- :class:`_schema.Column`
- objects are typical, the elements can also be expressions::
+ The given collection of column expressions should be derived from the
+ table that is the target of the INSERT, UPDATE, or DELETE. While
+ :class:`_schema.Column` objects are typical, the elements can also be
+ expressions::
stmt = table.insert().returning(
(table.c.first_name + " " + table.c.last_name).
"""
+ if self._return_defaults:
+ raise exc.InvalidRequestError(
+ "return_defaults() is already configured on this statement"
+ )
+ if self._returning:
+ util.warn(
+ "The returning() method does not currently support multiple "
+ "additive calls. The existing RETURNING clause being "
+ "replaced by new columns."
+ )
self._returning = cols
def _exported_columns_iterator(self):
:attr:`_engine.CursorResult.inserted_primary_key_rows`
"""
+ if self._returning:
+ raise exc.InvalidRequestError(
+ "RETURNING is already configured on this statement"
+ )
self._return_defaults = cols or True
import itertools
from sqlalchemy import Boolean
+from sqlalchemy import delete
from sqlalchemy import exc as sa_exc
from sqlalchemy import func
+from sqlalchemy import insert
from sqlalchemy import Integer
from sqlalchemy import MetaData
from sqlalchemy import select
from sqlalchemy import Sequence
from sqlalchemy import String
from sqlalchemy import testing
+from sqlalchemy import update
from sqlalchemy.testing import assert_raises_message
+from sqlalchemy.testing import AssertsCompiledSQL
from sqlalchemy.testing import AssertsExecutionResults
from sqlalchemy.testing import engines
from sqlalchemy.testing import eq_
table = GoofyType = seq = None
+class ReturnCombinationTests(fixtures.TestBase, AssertsCompiledSQL):
+ __dialect__ = "postgresql"
+
+ @testing.fixture
+ def table_fixture(self):
+ return Table(
+ "foo",
+ MetaData(),
+ Column("id", Integer, primary_key=True),
+ Column("q", Integer, server_default="5"),
+ Column("x", Integer),
+ Column("y", Integer),
+ )
+
+ @testing.combinations(
+ (
+ insert,
+ "INSERT INTO foo (id, q, x, y) "
+ "VALUES (%(id)s, %(q)s, %(x)s, %(y)s)",
+ ),
+ (update, "UPDATE foo SET id=%(id)s, q=%(q)s, x=%(x)s, y=%(y)s"),
+ (delete, "DELETE FROM foo"),
+ argnames="dml_fn, sql_frag",
+ id_="na",
+ )
+ def test_return_combinations(self, table_fixture, dml_fn, sql_frag):
+ t = table_fixture
+ stmt = dml_fn(t)
+
+ stmt = stmt.returning(t.c.x)
+
+ with testing.expect_warnings(
+ r"The returning\(\) method does not currently "
+ "support multiple additive calls."
+ ):
+ stmt = stmt.returning(t.c.y)
+
+ self.assert_compile(
+ stmt,
+ "%s RETURNING foo.y" % (sql_frag),
+ )
+
+ def test_return_no_return_defaults(self, table_fixture):
+ t = table_fixture
+
+ stmt = t.insert()
+
+ stmt = stmt.returning(t.c.x)
+
+ assert_raises_message(
+ sa_exc.InvalidRequestError,
+ "RETURNING is already configured on this statement",
+ stmt.return_defaults,
+ )
+
+ def test_return_defaults_no_returning(self, table_fixture):
+ t = table_fixture
+
+ stmt = t.insert()
+
+ stmt = stmt.return_defaults()
+
+ assert_raises_message(
+ sa_exc.InvalidRequestError,
+ r"return_defaults\(\) is already configured on this statement",
+ stmt.returning,
+ t.c.x,
+ )
+
+
class ReturningTest(fixtures.TestBase, AssertsExecutionResults):
__requires__ = ("returning",)
__backend__ = True