summaryrefslogtreecommitdiff
path: root/test/sql/test_insert.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2022-05-31 10:48:16 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2022-05-31 13:00:14 -0400
commitd1142c6e9f6fb0e52bd496c56bdc88047df66c55 (patch)
treefaf4c63574152fe306120db83d35b5e167620b3c /test/sql/test_insert.py
parentd97de97eff21af3bdacffc2b625feb7e0bd6c18c (diff)
downloadsqlalchemy-d1142c6e9f6fb0e52bd496c56bdc88047df66c55.tar.gz
raise informative error when selectable can't be extended
An informative error is raised for the use case where :meth:`.Insert.from_select` is being passed a "compound select" object such as a UNION, yet the INSERT statement needs to append additional columns to support Python-side or explicit SQL defaults from the table metadata. In this case a subquery of the compound object should be passed. Fixes: #8073 Change-Id: Ic4a5dbf84ec49d2451901be05cb9cf6ae93f02b7
Diffstat (limited to 'test/sql/test_insert.py')
-rw-r--r--test/sql/test_insert.py70
1 files changed, 70 insertions, 0 deletions
diff --git a/test/sql/test_insert.py b/test/sql/test_insert.py
index 2f9f9a4f7..3a6217f67 100644
--- a/test/sql/test_insert.py
+++ b/test/sql/test_insert.py
@@ -24,6 +24,7 @@ from sqlalchemy.testing import assert_raises
from sqlalchemy.testing import assert_raises_message
from sqlalchemy.testing import AssertsCompiledSQL
from sqlalchemy.testing import eq_
+from sqlalchemy.testing import expect_raises_message
from sqlalchemy.testing import expect_warnings
from sqlalchemy.testing import fixtures
@@ -662,6 +663,75 @@ class InsertTest(_InsertTestBase, fixtures.TablesTest, AssertsCompiledSQL):
checkparams={"name_1": "foo", "foo": None},
)
+ def test_insert_from_select_fn_defaults_compound(self):
+ """test #8073"""
+
+ metadata = MetaData()
+
+ table = Table(
+ "sometable",
+ metadata,
+ Column("id", Integer, primary_key=True),
+ Column("foo", Integer, default="foo"),
+ Column("bar", Integer, default="bar"),
+ )
+ table1 = self.tables.mytable
+ sel = (
+ select(table1.c.myid)
+ .where(table1.c.name == "foo")
+ .union(select(table1.c.myid).where(table1.c.name == "foo"))
+ )
+ ins = table.insert().from_select(["id"], sel)
+ with expect_raises_message(
+ exc.CompileError,
+ r"Can't extend statement for INSERT..FROM SELECT to include "
+ r"additional default-holding column\(s\) 'foo', 'bar'. "
+ r"Convert the selectable to a subquery\(\) first, or pass "
+ r"include_defaults=False to Insert.from_select\(\) to skip these "
+ r"columns.",
+ ):
+ ins.compile()
+
+ def test_insert_from_select_fn_defaults_compound_subquery(self):
+ """test #8073"""
+
+ metadata = MetaData()
+
+ def foo(ctx):
+ return 12
+
+ table = Table(
+ "sometable",
+ metadata,
+ Column("id", Integer, primary_key=True),
+ Column("foo", Integer, default="foo"),
+ Column("bar", Integer, default="bar"),
+ )
+ table1 = self.tables.mytable
+ sel = (
+ select(table1.c.myid)
+ .where(table1.c.name == "foo")
+ .union(select(table1.c.myid).where(table1.c.name == "foo"))
+ .subquery()
+ )
+
+ ins = table.insert().from_select(["id"], sel)
+ self.assert_compile(
+ ins,
+ "INSERT INTO sometable (id, foo, bar) SELECT anon_1.myid, "
+ ":foo AS anon_2, :bar AS anon_3 FROM "
+ "(SELECT mytable.myid AS myid FROM mytable "
+ "WHERE mytable.name = :name_1 UNION "
+ "SELECT mytable.myid AS myid FROM mytable "
+ "WHERE mytable.name = :name_2) AS anon_1",
+ checkparams={
+ "foo": None,
+ "bar": None,
+ "name_1": "foo",
+ "name_2": "foo",
+ },
+ )
+
def test_insert_from_select_dont_mutate_raw_columns(self):
# test [ticket:3603]
from sqlalchemy import table