summaryrefslogtreecommitdiff
path: root/test/sql
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2014-09-07 00:01:34 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2014-09-07 00:01:34 -0400
commit7950270cf2b12807acd7c330b11dae36e50c3a28 (patch)
treef1ec50aa6fc604d7a2dadf1b41aff73952a05dcc /test/sql
parente80c7cc5c103788a4c7e1c479af2c37cd9c958b3 (diff)
downloadsqlalchemy-7950270cf2b12807acd7c330b11dae36e50c3a28.tar.gz
- enhance ClauseAdapter / ColumnAdapter to have new behaviors with labels.
The "anonymize label" logic is now generalized to ClauseAdapter, and takes place when the anonymize_labels flag is sent, taking effect for all .columns lookups as well as within traverse() calls against the label directly. - traverse() will also memoize what it gets in columns, so that calling upon traverse() / .columns against the same Label will produce the same anonymized label. This is so that AliasedClass produces the same anonymized label when it is accessed per-column (e.g. SomeAlias.some_column) as well as when it is applied to a Query, and within column loader strategies (e.g. query(SomeAlias)); the former uses traverse() while the latter uses .columns - AliasedClass now calls onto ColumnAdapter - Query also makes sure to use that same ColumnAdapter from the AliasedClass in all cases - update the logic from 0.9 in #1068 to make use of the same _label_resolve_dict we use for #2992, simplifying how that works and adding support for new scenarios that were pretty broken (see #3148, #3188)
Diffstat (limited to 'test/sql')
-rw-r--r--test/sql/test_generative.py46
-rw-r--r--test/sql/test_text.py44
2 files changed, 85 insertions, 5 deletions
diff --git a/test/sql/test_generative.py b/test/sql/test_generative.py
index 2e3c4b1e8..1140a1180 100644
--- a/test/sql/test_generative.py
+++ b/test/sql/test_generative.py
@@ -1207,6 +1207,52 @@ class ClauseAdapterTest(fixtures.TestBase, AssertsCompiledSQL):
"WHERE c.bid = anon_1.b_aid"
)
+ t1 = table("table1",
+ column("col1"),
+ column("col2"),
+ column("col3"),
+ )
+ t2 = table("table2",
+ column("col1"),
+ column("col2"),
+ column("col3"),
+ )
+
+ def test_label_anonymize_one(self):
+ t1a = t1.alias()
+ adapter = sql_util.ClauseAdapter(t1a, anonymize_labels=True)
+
+ expr = select([t1.c.col2]).where(t1.c.col3 == 5).label('expr')
+ expr_adapted = adapter.traverse(expr)
+
+ stmt = select([expr, expr_adapted]).order_by(expr, expr_adapted)
+ self.assert_compile(
+ stmt,
+ "SELECT "
+ "(SELECT table1.col2 FROM table1 WHERE table1.col3 = :col3_1) "
+ "AS expr, "
+ "(SELECT table1_1.col2 FROM table1 AS table1_1 "
+ "WHERE table1_1.col3 = :col3_2) AS anon_1 "
+ "ORDER BY expr, anon_1"
+ )
+
+ def test_label_anonymize_two(self):
+ t1a = t1.alias()
+ adapter = sql_util.ClauseAdapter(t1a, anonymize_labels=True)
+
+ expr = select([t1.c.col2]).where(t1.c.col3 == 5).label(None)
+ expr_adapted = adapter.traverse(expr)
+
+ stmt = select([expr, expr_adapted]).order_by(expr, expr_adapted)
+ self.assert_compile(
+ stmt,
+ "SELECT "
+ "(SELECT table1.col2 FROM table1 WHERE table1.col3 = :col3_1) "
+ "AS anon_1, "
+ "(SELECT table1_1.col2 FROM table1 AS table1_1 "
+ "WHERE table1_1.col3 = :col3_2) AS anon_2 "
+ "ORDER BY anon_1, anon_2"
+ )
class SpliceJoinsTest(fixtures.TestBase, AssertsCompiledSQL):
__dialect__ = 'default'
diff --git a/test/sql/test_text.py b/test/sql/test_text.py
index 94627ae07..60d90196e 100644
--- a/test/sql/test_text.py
+++ b/test/sql/test_text.py
@@ -1,7 +1,7 @@
"""Test the TextClause and related constructs."""
from sqlalchemy.testing import fixtures, AssertsCompiledSQL, eq_, \
- assert_raises_message, expect_warnings
+ assert_raises_message, expect_warnings, assert_warnings
from sqlalchemy import text, select, Integer, String, Float, \
bindparam, and_, func, literal_column, exc, MetaData, Table, Column,\
asc, func, desc, union
@@ -680,7 +680,40 @@ class OrderByLabelResolutionTest(fixtures.TestBase, AssertsCompiledSQL):
"somelabel DESC"
)
- def test_anonymized_via_columnadapter(self):
+ def test_columnadapter_anonymized(self):
+ """test issue #3148
+
+ Testing the anonymization applied from the ColumnAdapter.columns
+ collection, typically as used in eager loading.
+
+ """
+ exprs = [
+ table1.c.myid,
+ table1.c.name.label('t1name'),
+ func.foo("hoho").label('x')]
+
+ ta = table1.alias()
+ adapter = sql_util.ColumnAdapter(ta, anonymize_labels=True)
+
+ s1 = select([adapter.columns[expr] for expr in exprs]).\
+ apply_labels().order_by("myid", "t1name", "x")
+
+ def go():
+ # the labels here are anonymized, so label naming
+ # can't catch these.
+ self.assert_compile(
+ s1,
+ "SELECT mytable_1.myid AS mytable_1_myid, "
+ "mytable_1.name AS name_1, foo(:foo_2) AS foo_1 "
+ "FROM mytable AS mytable_1 ORDER BY mytable_1.myid, t1name, x"
+ )
+
+ assert_warnings(
+ go,
+ ["Can't resolve label reference 't1name'",
+ "Can't resolve label reference 'x'"], regex=True)
+
+ def test_columnadapter_non_anonymized(self):
"""test issue #3148
Testing the anonymization applied from the ColumnAdapter.columns
@@ -698,10 +731,11 @@ class OrderByLabelResolutionTest(fixtures.TestBase, AssertsCompiledSQL):
s1 = select([adapter.columns[expr] for expr in exprs]).\
apply_labels().order_by("myid", "t1name", "x")
- # our "t1name" and "x" labels get modified
+ # labels are maintained
self.assert_compile(
s1,
"SELECT mytable_1.myid AS mytable_1_myid, "
- "mytable_1.name AS name_1, foo(:foo_2) AS foo_1 "
- "FROM mytable AS mytable_1 ORDER BY mytable_1.myid, name_1, foo_1"
+ "mytable_1.name AS t1name, foo(:foo_1) AS x "
+ "FROM mytable AS mytable_1 ORDER BY mytable_1.myid, t1name, x"
)
+