summaryrefslogtreecommitdiff
path: root/test/sql
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2021-12-17 18:04:47 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2022-01-14 16:54:13 -0500
commit06f83c26ea3636eaec0b85fc9d733ab4bfb827ec (patch)
tree13d43b9007f956bf514d757ce6781a378125fc3e /test/sql
parenta869dc8fe3cd579ed9bab665d215a6c3e3d8a4ca (diff)
downloadsqlalchemy-06f83c26ea3636eaec0b85fc9d733ab4bfb827ec.tar.gz
track item schema names to identify name collisions w/ default schema
Added an additional lookup step to the compiler which will track all FROM clauses which are tables, that may have the same name shared in multiple schemas where one of the schemas is the implicit "default" schema; in this case, the table name when referring to that name without a schema qualification will be rendered with an anonymous alias name at the compiler level in order to disambiguate the two (or more) names. The approach of schema-qualifying the normally unqualified name with the server-detected "default schema name" value was also considered, however this approach doesn't apply to Oracle nor is it accepted by SQL Server, nor would it work with multiple entries in the PostgreSQL search path. The name collision issue resolved here has been identified as affecting at least Oracle, PostgreSQL, SQL Server, MySQL and MariaDB. Fixes: #7471 Change-Id: Id65e7ca8c43fe8d95777084e8d5ec140ebcd784d
Diffstat (limited to 'test/sql')
-rw-r--r--test/sql/test_compiler.py72
1 files changed, 72 insertions, 0 deletions
diff --git a/test/sql/test_compiler.py b/test/sql/test_compiler.py
index 5ea1110c6..c273dbbf8 100644
--- a/test/sql/test_compiler.py
+++ b/test/sql/test_compiler.py
@@ -5624,6 +5624,78 @@ class SchemaTest(fixtures.TestBase, AssertsCompiledSQL):
render_schema_translate=True,
)
+ def test_schema_non_schema_disambiguation(self):
+ """test #7471"""
+
+ t1 = table("some_table", column("id"), column("q"))
+ t2 = table("some_table", column("id"), column("p"), schema="foo")
+
+ self.assert_compile(
+ select(t1, t2),
+ "SELECT some_table_1.id, some_table_1.q, "
+ "foo.some_table.id AS id_1, foo.some_table.p "
+ "FROM some_table AS some_table_1, foo.some_table",
+ )
+
+ self.assert_compile(
+ select(t1, t2).set_label_style(LABEL_STYLE_TABLENAME_PLUS_COL),
+ # the original "tablename_colname" label is preserved despite
+ # the alias of some_table
+ "SELECT some_table_1.id AS some_table_id, some_table_1.q AS "
+ "some_table_q, foo.some_table.id AS foo_some_table_id, "
+ "foo.some_table.p AS foo_some_table_p "
+ "FROM some_table AS some_table_1, foo.some_table",
+ )
+
+ self.assert_compile(
+ select(t1, t2).join_from(t1, t2, t1.c.id == t2.c.id),
+ "SELECT some_table_1.id, some_table_1.q, "
+ "foo.some_table.id AS id_1, foo.some_table.p "
+ "FROM some_table AS some_table_1 "
+ "JOIN foo.some_table ON some_table_1.id = foo.some_table.id",
+ )
+
+ self.assert_compile(
+ select(t1, t2).where(t1.c.id == t2.c.id),
+ "SELECT some_table_1.id, some_table_1.q, "
+ "foo.some_table.id AS id_1, foo.some_table.p "
+ "FROM some_table AS some_table_1, foo.some_table "
+ "WHERE some_table_1.id = foo.some_table.id",
+ )
+
+ self.assert_compile(
+ select(t1).where(t1.c.id == t2.c.id),
+ "SELECT some_table_1.id, some_table_1.q "
+ "FROM some_table AS some_table_1, foo.some_table "
+ "WHERE some_table_1.id = foo.some_table.id",
+ )
+
+ subq = select(t1).where(t1.c.id == t2.c.id).subquery()
+ self.assert_compile(
+ select(t2).select_from(t2).join(subq, t2.c.id == subq.c.id),
+ "SELECT foo.some_table.id, foo.some_table.p "
+ "FROM foo.some_table JOIN "
+ "(SELECT some_table_1.id AS id, some_table_1.q AS q "
+ "FROM some_table AS some_table_1, foo.some_table "
+ "WHERE some_table_1.id = foo.some_table.id) AS anon_1 "
+ "ON foo.some_table.id = anon_1.id",
+ )
+
+ self.assert_compile(
+ select(t1, subq.c.id)
+ .select_from(t1)
+ .join(subq, t1.c.id == subq.c.id),
+ # some_table is only aliased inside the subquery. this is not
+ # any challenge for the compiler, just checking as this is a new
+ # source of aliasing.
+ "SELECT some_table.id, some_table.q, anon_1.id AS id_1 "
+ "FROM some_table "
+ "JOIN (SELECT some_table_1.id AS id, some_table_1.q AS q "
+ "FROM some_table AS some_table_1, foo.some_table "
+ "WHERE some_table_1.id = foo.some_table.id) AS anon_1 "
+ "ON some_table.id = anon_1.id",
+ )
+
def test_alias(self):
a = alias(table4, "remtable")
self.assert_compile(