diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2019-06-15 18:06:50 -0400 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2019-06-15 20:38:39 -0400 |
| commit | 009acc95b8804b5b62fbd43c6fdd61d6fd407ef7 (patch) | |
| tree | b6e8d799be87d73b3f981c7a876b8c22a18809d4 /test/sql | |
| parent | de08740d7c21fa9dcef453bfd07a3defa428e88f (diff) | |
| download | sqlalchemy-009acc95b8804b5b62fbd43c6fdd61d6fd407ef7.tar.gz | |
Turn off the is_literal flag when proxying literal_column() to Label
Fixed a series of quoting issues which all stemmed from the concept of the
:func:`.literal_column` construct, which when being "proxied" through a
subquery to be referred towards by a label that matches its text, the label
would not have quoting rules applied to it, even if the string in the
:class:`.Label` were set up as a :class:`.quoted_name` construct. Not
applying quoting to the text of the :class:`.Label` is a bug because this
text is strictly a SQL identifier name and not a SQL expression, and the
string should not have quotes embedded into it already unlike the
:func:`.literal_column` which it may be applied towards. The existing
behavior of a non-labeled :func:`.literal_column` being propagated as is on
the outside of a subquery is maintained in order to help with manual
quoting schemes, although it's not clear if valid SQL can be generated for
such a construct in any case.
Fixes: #4730
Change-Id: I300941f27872fc4298c74a1d1ed65aef1a5cdd82
Diffstat (limited to 'test/sql')
| -rw-r--r-- | test/sql/test_quote.py | 102 | ||||
| -rw-r--r-- | test/sql/test_text.py | 44 |
2 files changed, 144 insertions, 2 deletions
diff --git a/test/sql/test_quote.py b/test/sql/test_quote.py index 49dfbba9f..8ef472878 100644 --- a/test/sql/test_quote.py +++ b/test/sql/test_quote.py @@ -695,6 +695,108 @@ class QuoteTest(fixtures.TestBase, AssertsCompiledSQL): ') AS "Alias1"', ) + def test_literal_column_label_embedded_select_samename(self): + col = sql.literal_column("NEEDS QUOTES").label("NEEDS QUOTES") + + # embedded SELECT use case, going away in 1.4 however use a + # SelectStatementGrouping here when that merges + self.assert_compile( + select([col]).select(), + 'SELECT "NEEDS QUOTES" FROM (SELECT NEEDS QUOTES AS ' + '"NEEDS QUOTES")', + ) + + def test_literal_column_label_alias_samename(self): + col = sql.literal_column("NEEDS QUOTES").label("NEEDS QUOTES") + + self.assert_compile( + select([col]).alias().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_") + + # embedded SELECT use case, going away in 1.4 however use a + # SelectStatementGrouping here when that merges + self.assert_compile( + select([col]).select(), + 'SELECT "NEEDS QUOTES_" FROM (SELECT NEEDS QUOTES AS ' + '"NEEDS QUOTES_")', + ) + + def test_literal_column_label_alias_diffname(self): + col = sql.literal_column("NEEDS QUOTES").label("NEEDS QUOTES_") + + self.assert_compile( + select([col]).alias().select(), + 'SELECT anon_1."NEEDS QUOTES_" FROM (SELECT NEEDS QUOTES AS ' + '"NEEDS QUOTES_") AS anon_1', + ) + + def test_literal_column_label_embedded_select_samename_explcit_quote(self): + col = sql.literal_column("NEEDS QUOTES").label( + quoted_name("NEEDS QUOTES", True) + ) + + # embedded SELECT use case, going away in 1.4 however use a + # SelectStatementGrouping here when that merges + self.assert_compile( + select([col]).select(), + 'SELECT "NEEDS QUOTES" FROM ' + '(SELECT NEEDS QUOTES AS "NEEDS QUOTES")', + ) + + def test_literal_column_label_alias_samename_explcit_quote(self): + col = sql.literal_column("NEEDS QUOTES").label( + quoted_name("NEEDS QUOTES", True) + ) + + self.assert_compile( + select([col]).alias().select(), + 'SELECT anon_1."NEEDS QUOTES" FROM ' + '(SELECT NEEDS QUOTES AS "NEEDS QUOTES") AS anon_1', + ) + + def test_literal_column_label_embedded_select_diffname_explcit_quote(self): + col = sql.literal_column("NEEDS QUOTES").label( + quoted_name("NEEDS QUOTES_", True) + ) + + # embedded SELECT use case, going away in 1.4 however use a + # SelectStatementGrouping here when that merges + self.assert_compile( + select([col]).select(), + 'SELECT "NEEDS QUOTES_" FROM ' + '(SELECT NEEDS QUOTES AS "NEEDS QUOTES_")', + ) + + def test_literal_column_label_alias_diffname_explcit_quote(self): + col = sql.literal_column("NEEDS QUOTES").label( + quoted_name("NEEDS QUOTES_", True) + ) + + self.assert_compile( + select([col]).alias().select(), + 'SELECT anon_1."NEEDS QUOTES_" FROM ' + '(SELECT NEEDS QUOTES AS "NEEDS QUOTES_") AS anon_1', + ) + + def test_literal_column_wo_label_currently_maintained(self): + # test related to [ticket:4730] where we are maintaining that + # literal_column() proxied outwards *without* a label is maintained + # as is; in most cases literal_column would need proxying however + # at least if the column is being used to generate quoting in some + # way, it's maintined as given + col = sql.literal_column('"NEEDS QUOTES"') + + self.assert_compile( + select([col]).alias().select(), + 'SELECT anon_1."NEEDS QUOTES" FROM ' + '(SELECT "NEEDS QUOTES") AS anon_1', + ) + def test_apply_labels_should_quote(self): # Not lower case names, should quote metadata = MetaData() diff --git a/test/sql/test_text.py b/test/sql/test_text.py index afc775598..f6b3b0519 100644 --- a/test/sql/test_text.py +++ b/test/sql/test_text.py @@ -19,6 +19,7 @@ from sqlalchemy import text from sqlalchemy import union from sqlalchemy import util from sqlalchemy.sql import column +from sqlalchemy.sql import quoted_name from sqlalchemy.sql import table from sqlalchemy.sql import util as sql_util from sqlalchemy.testing import assert_raises_message @@ -27,7 +28,6 @@ from sqlalchemy.testing import eq_ from sqlalchemy.testing import fixtures from sqlalchemy.types import NullType - table1 = table( "mytable", column("myid", Integer), @@ -136,7 +136,9 @@ class SelectCompositionTest(fixtures.TestBase, AssertsCompiledSQL): def test_select_composition_six(self): # test that "auto-labeling of subquery columns" # doesn't interfere with literal columns, - # exported columns don't get quoted + # exported columns don't get quoted. + # [ticket:4730] refines this but for the moment the behavior with + # no columns is being maintained. self.assert_compile( select( [ @@ -708,6 +710,44 @@ class OrderByLabelResolutionTest(fixtures.TestBase, AssertsCompiledSQL): "GROUP BY anon_1.myid", ) + def test_order_by_literal_col_quoting_one(self): + col = literal_column("SUM(ABC)").label("SUM(ABC)") + tbl = table("my_table") + query = select([col]).select_from(tbl).order_by(col) + self.assert_compile( + query, + 'SELECT SUM(ABC) AS "SUM(ABC)" FROM my_table ORDER BY "SUM(ABC)"', + ) + + def test_order_by_literal_col_quoting_two(self): + col = literal_column("SUM(ABC)").label("SUM(ABC)_") + tbl = table("my_table") + query = select([col]).select_from(tbl).order_by(col) + self.assert_compile( + query, + 'SELECT SUM(ABC) AS "SUM(ABC)_" FROM my_table ORDER BY ' + '"SUM(ABC)_"', + ) + + def test_order_by_literal_col_quoting_one_explict_quote(self): + col = literal_column("SUM(ABC)").label(quoted_name("SUM(ABC)", True)) + tbl = table("my_table") + query = select([col]).select_from(tbl).order_by(col) + self.assert_compile( + query, + 'SELECT SUM(ABC) AS "SUM(ABC)" FROM my_table ORDER BY "SUM(ABC)"', + ) + + def test_order_by_literal_col_quoting_two_explicit_quote(self): + col = literal_column("SUM(ABC)").label(quoted_name("SUM(ABC)_", True)) + tbl = table("my_table") + query = select([col]).select_from(tbl).order_by(col) + self.assert_compile( + query, + 'SELECT SUM(ABC) AS "SUM(ABC)_" FROM my_table ORDER BY ' + '"SUM(ABC)_"', + ) + def test_order_by_func_label_desc(self): stmt = select([func.foo("bar").label("fb"), table1]).order_by( desc("fb") |
