summaryrefslogtreecommitdiff
path: root/test/sql
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2019-06-15 18:06:50 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2019-06-15 20:38:39 -0400
commit009acc95b8804b5b62fbd43c6fdd61d6fd407ef7 (patch)
treeb6e8d799be87d73b3f981c7a876b8c22a18809d4 /test/sql
parentde08740d7c21fa9dcef453bfd07a3defa428e88f (diff)
downloadsqlalchemy-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.py102
-rw-r--r--test/sql/test_text.py44
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")