diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2022-03-25 17:08:48 -0400 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2022-03-30 14:04:52 -0400 |
| commit | 4e754a8914a1c2c16c97bdf363d2e24bfa823730 (patch) | |
| tree | db723242b4e4c0d4c7f15c167857dd79fdfa6ccb /test | |
| parent | dba480ebaf89c0b5ea787661583de9da3928920f (diff) | |
| download | sqlalchemy-4e754a8914a1c2c16c97bdf363d2e24bfa823730.tar.gz | |
pep-484: the pep-484ening, SQL part three
hitting DML which is causing us to open up the
ColumnCollection structure a bit, as we do put anonymous
column expressions with None here. However, we still want
Table /TableClause to have named column collections that
don't return None, so parametrize the "key" in this
collection also.
* rename some "immutable" elements to "readonly". we change
the contents of immutablecolumncollection underneath, so it's
not "immutable"
Change-Id: I2593995a4e5c6eae874bed5bf76117198be8ae97
Diffstat (limited to 'test')
| -rw-r--r-- | test/base/test_utils.py | 38 | ||||
| -rw-r--r-- | test/profiles.txt | 22 | ||||
| -rw-r--r-- | test/sql/test_quote.py | 44 | ||||
| -rw-r--r-- | test/sql/test_returning.py | 110 | ||||
| -rw-r--r-- | test/sql/test_selectable.py | 18 |
5 files changed, 202 insertions, 30 deletions
diff --git a/test/base/test_utils.py b/test/base/test_utils.py index 67fcc8870..fc61e39b6 100644 --- a/test/base/test_utils.py +++ b/test/base/test_utils.py @@ -357,8 +357,8 @@ class ImmutableTest(fixtures.TestBase): with expect_raises_message(TypeError, "object is immutable"): m() - def test_immutable_properties(self): - d = util.ImmutableProperties({3: 4}) + def test_readonly_properties(self): + d = util.ReadOnlyProperties({3: 4}) calls = ( lambda: d.__delitem__(1), lambda: d.__setitem__(2, 3), @@ -563,7 +563,7 @@ class ColumnCollectionCommon(testing.AssertsCompiledSQL): eq_(keys, ["c1", "foo", "c3"]) ne_(id(keys), id(cc.keys())) - ci = cc.as_immutable() + ci = cc.as_readonly() eq_(ci.keys(), ["c1", "foo", "c3"]) def test_values(self): @@ -576,7 +576,7 @@ class ColumnCollectionCommon(testing.AssertsCompiledSQL): eq_(val, [c1, c2, c3]) ne_(id(val), id(cc.values())) - ci = cc.as_immutable() + ci = cc.as_readonly() eq_(ci.values(), [c1, c2, c3]) def test_items(self): @@ -589,7 +589,7 @@ class ColumnCollectionCommon(testing.AssertsCompiledSQL): eq_(items, [("c1", c1), ("foo", c2), ("c3", c3)]) ne_(id(items), id(cc.items())) - ci = cc.as_immutable() + ci = cc.as_readonly() eq_(ci.items(), [("c1", c1), ("foo", c2), ("c3", c3)]) def test_key_index_error(self): @@ -732,7 +732,7 @@ class ColumnCollectionTest(ColumnCollectionCommon, fixtures.TestBase): self._assert_collection_integrity(cc) - ci = cc.as_immutable() + ci = cc.as_readonly() eq_(ci._all_columns, [c1, c2a, c3, c2b]) eq_(list(ci), [c1, c2a, c3, c2b]) eq_(ci.keys(), ["c1", "c2", "c3", "c2"]) @@ -763,7 +763,7 @@ class ColumnCollectionTest(ColumnCollectionCommon, fixtures.TestBase): self._assert_collection_integrity(cc) - ci = cc.as_immutable() + ci = cc.as_readonly() eq_(ci._all_columns, [c1, c2a, c3, c2b]) eq_(list(ci), [c1, c2a, c3, c2b]) eq_(ci.keys(), ["c1", "c2", "c3", "c2"]) @@ -786,7 +786,7 @@ class ColumnCollectionTest(ColumnCollectionCommon, fixtures.TestBase): assert cc.contains_column(c2) self._assert_collection_integrity(cc) - ci = cc.as_immutable() + ci = cc.as_readonly() eq_(ci._all_columns, [c1, c2, c3, c2]) eq_(list(ci), [c1, c2, c3, c2]) @@ -821,7 +821,7 @@ class DedupeColumnCollectionTest(ColumnCollectionCommon, fixtures.TestBase): c2.key = "foo" cc = self._column_collection(columns=[("c1", c1), ("foo", c2)]) - ci = cc.as_immutable() + ci = cc.as_readonly() d = {"cc": cc, "ci": ci} @@ -922,7 +922,7 @@ class DedupeColumnCollectionTest(ColumnCollectionCommon, fixtures.TestBase): assert cc.contains_column(c2) self._assert_collection_integrity(cc) - ci = cc.as_immutable() + ci = cc.as_readonly() eq_(ci._all_columns, [c1, c2, c3]) eq_(list(ci), [c1, c2, c3]) @@ -944,13 +944,13 @@ class DedupeColumnCollectionTest(ColumnCollectionCommon, fixtures.TestBase): assert cc.contains_column(c2) self._assert_collection_integrity(cc) - ci = cc.as_immutable() + ci = cc.as_readonly() eq_(ci._all_columns, [c1, c2, c3]) eq_(list(ci), [c1, c2, c3]) def test_replace(self): cc = DedupeColumnCollection() - ci = cc.as_immutable() + ci = cc.as_readonly() c1, c2a, c3, c2b = ( column("c1"), @@ -979,7 +979,7 @@ class DedupeColumnCollectionTest(ColumnCollectionCommon, fixtures.TestBase): def test_replace_key_matches_name_of_another(self): cc = DedupeColumnCollection() - ci = cc.as_immutable() + ci = cc.as_readonly() c1, c2a, c3, c2b = ( column("c1"), @@ -1009,7 +1009,7 @@ class DedupeColumnCollectionTest(ColumnCollectionCommon, fixtures.TestBase): def test_replace_key_matches(self): cc = DedupeColumnCollection() - ci = cc.as_immutable() + ci = cc.as_readonly() c1, c2a, c3, c2b = ( column("c1"), @@ -1041,7 +1041,7 @@ class DedupeColumnCollectionTest(ColumnCollectionCommon, fixtures.TestBase): def test_replace_name_matches(self): cc = DedupeColumnCollection() - ci = cc.as_immutable() + ci = cc.as_readonly() c1, c2a, c3, c2b = ( column("c1"), @@ -1073,7 +1073,7 @@ class DedupeColumnCollectionTest(ColumnCollectionCommon, fixtures.TestBase): def test_replace_no_match(self): cc = DedupeColumnCollection() - ci = cc.as_immutable() + ci = cc.as_readonly() c1, c2, c3, c4 = column("c1"), column("c2"), column("c3"), column("c4") c4.key = "X" @@ -1123,7 +1123,7 @@ class DedupeColumnCollectionTest(ColumnCollectionCommon, fixtures.TestBase): cc = DedupeColumnCollection( columns=[("c1", c1), ("c2", c2), ("c3", c3)] ) - ci = cc.as_immutable() + ci = cc.as_readonly() eq_(cc._all_columns, [c1, c2, c3]) eq_(list(cc), [c1, c2, c3]) @@ -1184,7 +1184,7 @@ class DedupeColumnCollectionTest(ColumnCollectionCommon, fixtures.TestBase): def test_dupes_extend(self): cc = DedupeColumnCollection() - ci = cc.as_immutable() + ci = cc.as_readonly() c1, c2a, c3, c2b = ( column("c1"), @@ -3044,7 +3044,7 @@ class TestProperties(fixtures.TestBase): def test_pickle_immuatbleprops(self): data = {"hello": "bla"} - props = util.Properties(data).as_immutable() + props = util.Properties(data).as_readonly() for loader, dumper in picklers(): s = dumper(props) diff --git a/test/profiles.txt b/test/profiles.txt index 074b649f2..31f72bd16 100644 --- a/test/profiles.txt +++ b/test/profiles.txt @@ -69,17 +69,17 @@ test.aaa_profiling.test_compiler.CompileTest.test_update x86_64_linux_cpython_3. # TEST: test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause x86_64_linux_cpython_3.10_mariadb_mysqldb_dbapiunicode_cextensions 174 -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause x86_64_linux_cpython_3.10_mariadb_mysqldb_dbapiunicode_nocextensions 174 -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause x86_64_linux_cpython_3.10_mariadb_pymysql_dbapiunicode_cextensions 174 -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause x86_64_linux_cpython_3.10_mariadb_pymysql_dbapiunicode_nocextensions 174 -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause x86_64_linux_cpython_3.10_mssql_pyodbc_dbapiunicode_cextensions 174 -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause x86_64_linux_cpython_3.10_oracle_cx_oracle_dbapiunicode_cextensions 174 -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause x86_64_linux_cpython_3.10_oracle_cx_oracle_dbapiunicode_nocextensions 174 -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause x86_64_linux_cpython_3.10_postgresql_psycopg2_dbapiunicode_cextensions 174 -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause x86_64_linux_cpython_3.10_postgresql_psycopg2_dbapiunicode_nocextensions 174 -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_cextensions 170 -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 173 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause x86_64_linux_cpython_3.10_mariadb_mysqldb_dbapiunicode_cextensions 180 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause x86_64_linux_cpython_3.10_mariadb_mysqldb_dbapiunicode_nocextensions 180 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause x86_64_linux_cpython_3.10_mariadb_pymysql_dbapiunicode_cextensions 180 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause x86_64_linux_cpython_3.10_mariadb_pymysql_dbapiunicode_nocextensions 180 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause x86_64_linux_cpython_3.10_mssql_pyodbc_dbapiunicode_cextensions 180 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause x86_64_linux_cpython_3.10_oracle_cx_oracle_dbapiunicode_cextensions 180 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause x86_64_linux_cpython_3.10_oracle_cx_oracle_dbapiunicode_nocextensions 180 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause x86_64_linux_cpython_3.10_postgresql_psycopg2_dbapiunicode_cextensions 180 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause x86_64_linux_cpython_3.10_postgresql_psycopg2_dbapiunicode_nocextensions 180 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_cextensions 180 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 180 # TEST: test.aaa_profiling.test_misc.CacheKeyTest.test_statement_key_is_cached diff --git a/test/sql/test_quote.py b/test/sql/test_quote.py index 9812f84c1..7d90bc67b 100644 --- a/test/sql/test_quote.py +++ b/test/sql/test_quote.py @@ -252,6 +252,50 @@ class QuoteTest(fixtures.TestBase, AssertsCompiledSQL): eq_(repr(name), repr("姓名")) + def test_literal_column_label_embedded_select_samename_explicit_quote( + self, + ): + col = sql.literal_column("NEEDS QUOTES").label( + quoted_name("NEEDS QUOTES", True) + ) + + self.assert_compile( + select(col).subquery().select(), + 'SELECT anon_1."NEEDS QUOTES" FROM ' + '(SELECT NEEDS QUOTES AS "NEEDS QUOTES") AS anon_1', + ) + + def test_literal_column_label_embedded_select_diffname_explicit_quote( + self, + ): + col = sql.literal_column("NEEDS QUOTES").label( + quoted_name("NEEDS QUOTES_", True) + ) + + self.assert_compile( + select(col).subquery().select(), + 'SELECT anon_1."NEEDS QUOTES_" FROM ' + '(SELECT NEEDS QUOTES AS "NEEDS QUOTES_") AS anon_1', + ) + + def test_literal_column_label_embedded_select_diffname(self): + col = sql.literal_column("NEEDS QUOTES").label("NEEDS QUOTES_") + + self.assert_compile( + select(col).subquery().select(), + 'SELECT anon_1."NEEDS QUOTES_" FROM (SELECT NEEDS QUOTES AS ' + '"NEEDS QUOTES_") AS anon_1', + ) + + def test_literal_column_label_embedded_select_samename(self): + col = sql.literal_column("NEEDS QUOTES").label("NEEDS QUOTES") + + self.assert_compile( + select(col).subquery().select(), + 'SELECT anon_1."NEEDS QUOTES" FROM (SELECT NEEDS QUOTES AS ' + '"NEEDS QUOTES") AS anon_1', + ) + def test_lower_case_names(self): # Create table with quote defaults metadata = MetaData() diff --git a/test/sql/test_returning.py b/test/sql/test_returning.py index 138e7a4c6..ffbab3223 100644 --- a/test/sql/test_returning.py +++ b/test/sql/test_returning.py @@ -1,6 +1,7 @@ import itertools from sqlalchemy import Boolean +from sqlalchemy import column from sqlalchemy import delete from sqlalchemy import exc as sa_exc from sqlalchemy import func @@ -10,9 +11,11 @@ from sqlalchemy import MetaData from sqlalchemy import select from sqlalchemy import Sequence from sqlalchemy import String +from sqlalchemy import table from sqlalchemy import testing from sqlalchemy import type_coerce from sqlalchemy import update +from sqlalchemy.sql.sqltypes import NullType from sqlalchemy.testing import assert_raises_message from sqlalchemy.testing import AssertsCompiledSQL from sqlalchemy.testing import AssertsExecutionResults @@ -88,6 +91,113 @@ class ReturnCombinationTests(fixtures.TestBase, AssertsCompiledSQL): t.c.x, ) + def test_named_expressions_selected_columns(self, table_fixture): + table = table_fixture + stmt = ( + table.insert() + .values(goofy="someOTHERgoofy") + .returning(func.lower(table.c.x).label("goof")) + ) + self.assert_compile( + select(stmt.exported_columns.goof), + "SELECT lower(foo.x) AS goof FROM foo", + ) + + def test_anon_expressions_selected_columns(self, table_fixture): + table = table_fixture + stmt = ( + table.insert() + .values(goofy="someOTHERgoofy") + .returning(func.lower(table.c.x)) + ) + self.assert_compile( + select(stmt.exported_columns[0]), + "SELECT lower(foo.x) AS lower_1 FROM foo", + ) + + def test_returning_fromclause(self): + t = table("t", column("x"), column("y"), column("z")) + stmt = t.update().returning(t) + + self.assert_compile( + stmt, + "UPDATE t SET x=%(x)s, y=%(y)s, z=%(z)s RETURNING t.x, t.y, t.z", + ) + + eq_( + stmt.returning_column_descriptions, + [ + { + "name": "x", + "type": testing.eq_type_affinity(NullType), + "expr": t.c.x, + }, + { + "name": "y", + "type": testing.eq_type_affinity(NullType), + "expr": t.c.y, + }, + { + "name": "z", + "type": testing.eq_type_affinity(NullType), + "expr": t.c.z, + }, + ], + ) + + cte = stmt.cte("c") + + stmt = select(cte.c.z) + self.assert_compile( + stmt, + "WITH c AS (UPDATE t SET x=%(x)s, y=%(y)s, z=%(z)s " + "RETURNING t.x, t.y, t.z) SELECT c.z FROM c", + ) + + def test_returning_inspectable(self): + t = table("t", column("x"), column("y"), column("z")) + + class HasClauseElement: + def __clause_element__(self): + return t + + stmt = update(HasClauseElement()).returning(HasClauseElement()) + + eq_( + stmt.returning_column_descriptions, + [ + { + "name": "x", + "type": testing.eq_type_affinity(NullType), + "expr": t.c.x, + }, + { + "name": "y", + "type": testing.eq_type_affinity(NullType), + "expr": t.c.y, + }, + { + "name": "z", + "type": testing.eq_type_affinity(NullType), + "expr": t.c.z, + }, + ], + ) + + self.assert_compile( + stmt, + "UPDATE t SET x=%(x)s, y=%(y)s, z=%(z)s " + "RETURNING t.x, t.y, t.z", + ) + cte = stmt.cte("c") + + stmt = select(cte.c.z) + self.assert_compile( + stmt, + "WITH c AS (UPDATE t SET x=%(x)s, y=%(y)s, z=%(z)s " + "RETURNING t.x, t.y, t.z) SELECT c.z FROM c", + ) + class ReturningTest(fixtures.TablesTest, AssertsExecutionResults): __requires__ = ("returning",) diff --git a/test/sql/test_selectable.py b/test/sql/test_selectable.py index 4944f2d57..ca5f43bb6 100644 --- a/test/sql/test_selectable.py +++ b/test/sql/test_selectable.py @@ -208,6 +208,24 @@ class SelectableTest( {"name": "table1", "table": table1}, [], ), + ( + table1.alias("some_alias"), + None, + { + "name": "some_alias", + "table": testing.eq_clause_element(table1.alias("some_alias")), + }, + [], + ), + ( + table1.join(table2), + None, + { + "name": None, + "table": testing.eq_clause_element(table1.join(table2)), + }, + [], + ), argnames="entity, cols, expected_entity, expected_returning", ) def test_dml_descriptions( |
