summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2013-10-12 20:04:55 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2013-10-12 20:04:55 -0400
commit9bc9d5c1068be878118202259add3c2e1bcec0cb (patch)
tree9e611c162b83debad6c70b5436c61630546c2872
parenteabf41b392ac042228765c9b95138522e44365e7 (diff)
downloadsqlalchemy-9bc9d5c1068be878118202259add3c2e1bcec0cb.tar.gz
- Fixed bug in default compiler plus those of postgresql, mysql, and
mssql to ensure that any literal SQL expression values are rendered directly as literals, instead of as bound parameters, within a CREATE INDEX statement. [ticket:2742] - don't need expression_as_ddl(); literal_binds and include_table take care of this functionality.
-rw-r--r--doc/build/changelog/changelog_08.rst10
-rw-r--r--lib/sqlalchemy/dialects/mssql/base.py2
-rw-r--r--lib/sqlalchemy/dialects/mysql/base.py3
-rw-r--r--lib/sqlalchemy/dialects/postgresql/base.py17
-rw-r--r--lib/sqlalchemy/sql/compiler.py7
-rw-r--r--lib/sqlalchemy/sql/util.py20
-rw-r--r--test/dialect/mssql/test_compiler.py10
-rw-r--r--test/dialect/mysql/test_compiler.py10
-rw-r--r--test/dialect/postgresql/test_compiler.py10
-rw-r--r--test/dialect/test_oracle.py11
-rw-r--r--test/sql/test_constraints.py21
11 files changed, 87 insertions, 34 deletions
diff --git a/doc/build/changelog/changelog_08.rst b/doc/build/changelog/changelog_08.rst
index 6731fe19a..8de572b20 100644
--- a/doc/build/changelog/changelog_08.rst
+++ b/doc/build/changelog/changelog_08.rst
@@ -12,6 +12,16 @@
.. change::
:tags: bug, sql
+ :tickets: 2742
+ :versions: 0.9.0
+
+ Fixed bug in default compiler plus those of postgresql, mysql, and
+ mssql to ensure that any literal SQL expression values are
+ rendered directly as literals, instead of as bound parameters,
+ within a CREATE INDEX statement.
+
+ .. change::
+ :tags: bug, sql
:tickets: 2815
:versions: 0.9.0
diff --git a/lib/sqlalchemy/dialects/mssql/base.py b/lib/sqlalchemy/dialects/mssql/base.py
index b1b168035..06570b032 100644
--- a/lib/sqlalchemy/dialects/mssql/base.py
+++ b/lib/sqlalchemy/dialects/mssql/base.py
@@ -1001,7 +1001,7 @@ class MSDDLCompiler(compiler.DDLCompiler):
preparer.format_table(index.table),
', '.join(
self.sql_compiler.process(expr,
- include_table=False) for
+ include_table=False, literal_binds=True) for
expr in index.expressions)
)
diff --git a/lib/sqlalchemy/dialects/mysql/base.py b/lib/sqlalchemy/dialects/mysql/base.py
index fd6a47a10..3bbd88d52 100644
--- a/lib/sqlalchemy/dialects/mysql/base.py
+++ b/lib/sqlalchemy/dialects/mysql/base.py
@@ -1523,7 +1523,8 @@ class MySQLDDLCompiler(compiler.DDLCompiler):
self._verify_index_table(index)
preparer = self.preparer
table = preparer.format_table(index.table)
- columns = [self.sql_compiler.process(expr, include_table=False)
+ columns = [self.sql_compiler.process(expr, include_table=False,
+ literal_binds=True)
for expr in index.expressions]
name = self._prepared_index_name(index)
diff --git a/lib/sqlalchemy/dialects/postgresql/base.py b/lib/sqlalchemy/dialects/postgresql/base.py
index ecbbf1674..83ad1d46f 100644
--- a/lib/sqlalchemy/dialects/postgresql/base.py
+++ b/lib/sqlalchemy/dialects/postgresql/base.py
@@ -1100,12 +1100,9 @@ class PGDDLCompiler(compiler.DDLCompiler):
text += "(%s)" \
% (
', '.join([
- self.sql_compiler.process(expr, include_table=False) +
-
-
+ self.sql_compiler.process(
+ expr, include_table=False, literal_binds=True) +
(c.key in ops and (' ' + ops[c.key]) or '')
-
-
for expr, c in zip(index.expressions, index.columns)])
)
@@ -1115,8 +1112,9 @@ class PGDDLCompiler(compiler.DDLCompiler):
whereclause = None
if whereclause is not None:
- whereclause = sql_util.expression_as_ddl(whereclause)
- where_compiled = self.sql_compiler.process(whereclause)
+ where_compiled = self.sql_compiler.process(
+ whereclause, include_table=False,
+ literal_binds=True)
text += " WHERE " + where_compiled
return text
@@ -1131,8 +1129,9 @@ class PGDDLCompiler(compiler.DDLCompiler):
elements.append(self.preparer.quote(c.name) + ' WITH '+op)
text += "EXCLUDE USING %s (%s)" % (constraint.using, ', '.join(elements))
if constraint.where is not None:
- sqltext = sql_util.expression_as_ddl(constraint.where)
- text += ' WHERE (%s)' % self.sql_compiler.process(sqltext)
+ text += ' WHERE (%s)' % self.sql_compiler.process(
+ constraint.where,
+ literal_binds=True)
text += self.define_constraint_deferrability(constraint)
return text
diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py
index f81886240..9f2abd6f5 100644
--- a/lib/sqlalchemy/sql/compiler.py
+++ b/lib/sqlalchemy/sql/compiler.py
@@ -2305,7 +2305,7 @@ class DDLCompiler(Compiled):
use_schema=include_table_schema),
', '.join(
self.sql_compiler.process(expr,
- include_table=False) for
+ include_table=False, literal_binds=True) for
expr in index.expressions)
)
return text
@@ -2392,8 +2392,9 @@ class DDLCompiler(Compiled):
if constraint.name is not None:
text += "CONSTRAINT %s " % \
self.preparer.format_constraint(constraint)
- sqltext = sql_util.expression_as_ddl(constraint.sqltext)
- text += "CHECK (%s)" % self.sql_compiler.process(sqltext)
+ text += "CHECK (%s)" % self.sql_compiler.process(constraint.sqltext,
+ include_table=False,
+ literal_binds=True)
text += self.define_constraint_deferrability(constraint)
return text
diff --git a/lib/sqlalchemy/sql/util.py b/lib/sqlalchemy/sql/util.py
index 2a5c2e277..bf07716c8 100644
--- a/lib/sqlalchemy/sql/util.py
+++ b/lib/sqlalchemy/sql/util.py
@@ -254,26 +254,6 @@ class _repr_params(object):
return repr(self.params)
-def expression_as_ddl(clause):
- """Given a SQL expression, convert for usage in DDL, such as
- CREATE INDEX and CHECK CONSTRAINT.
-
- Converts bind params into quoted literals, column identifiers
- into detached column constructs so that the parent table
- identifier is not included.
-
- """
- def repl(element):
- if isinstance(element, BindParameter):
- return literal_column(_quote_ddl_expr(element.value))
- elif isinstance(element, ColumnClause) and \
- element.table is not None:
- col = ColumnClause(element.name)
- return col
- else:
- return None
-
- return visitors.replacement_traverse(clause, {}, repl)
def adapt_criterion_to_null(crit, nulls):
diff --git a/test/dialect/mssql/test_compiler.py b/test/dialect/mssql/test_compiler.py
index 87037c6a4..f218d9d0e 100644
--- a/test/dialect/mssql/test_compiler.py
+++ b/test/dialect/mssql/test_compiler.py
@@ -528,6 +528,16 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL):
"CREATE INDEX foo ON test (x DESC, y)"
)
+ def test_create_index_expr(self):
+ m = MetaData()
+ t1 = Table('foo', m,
+ Column('x', Integer)
+ )
+ self.assert_compile(
+ schema.CreateIndex(Index("bar", t1.c.x > 5)),
+ "CREATE INDEX bar ON foo (x > 5)"
+ )
+
def test_index_extra_include_1(self):
metadata = MetaData()
tbl = Table('test', metadata,
diff --git a/test/dialect/mysql/test_compiler.py b/test/dialect/mysql/test_compiler.py
index a77a25cc4..d1488ed33 100644
--- a/test/dialect/mysql/test_compiler.py
+++ b/test/dialect/mysql/test_compiler.py
@@ -94,6 +94,16 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL):
"CREATE TABLE testtbl (data VARCHAR(255), "
"PRIMARY KEY (data) USING btree)")
+ def test_create_index_expr(self):
+ m = MetaData()
+ t1 = Table('foo', m,
+ Column('x', Integer)
+ )
+ self.assert_compile(
+ schema.CreateIndex(Index("bar", t1.c.x > 5)),
+ "CREATE INDEX bar ON foo (x > 5)"
+ )
+
def test_skip_deferrable_kw(self):
m = MetaData()
t1 = Table('t1', m, Column('id', Integer, primary_key=True))
diff --git a/test/dialect/postgresql/test_compiler.py b/test/dialect/postgresql/test_compiler.py
index 11661b11f..858f3e763 100644
--- a/test/dialect/postgresql/test_compiler.py
+++ b/test/dialect/postgresql/test_compiler.py
@@ -173,6 +173,16 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL):
'USING hash (data)',
dialect=postgresql.dialect())
+ def test_create_index_literals(self):
+ m = MetaData()
+ tbl = Table('testtbl', m, Column('data', Integer))
+
+ idx1 = Index('test_idx1', tbl.c.data + 5)
+ self.assert_compile(
+ schema.CreateIndex(idx1),
+ "CREATE INDEX test_idx1 ON testtbl (data + 5)"
+ )
+
def test_exclude_constraint_min(self):
m = MetaData()
tbl = Table('testtbl', m,
diff --git a/test/dialect/test_oracle.py b/test/dialect/test_oracle.py
index 71b2d96cb..1fde1c198 100644
--- a/test/dialect/test_oracle.py
+++ b/test/dialect/test_oracle.py
@@ -587,6 +587,17 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL):
schema.CreateIndex(Index("bar", t1.c.x)),
"CREATE INDEX alt_schema.bar ON alt_schema.foo (x)"
)
+
+ def test_create_index_expr(self):
+ m = MetaData()
+ t1 = Table('foo', m,
+ Column('x', Integer)
+ )
+ self.assert_compile(
+ schema.CreateIndex(Index("bar", t1.c.x > 5)),
+ "CREATE INDEX bar ON foo (x > 5)"
+ )
+
class CompatFlagsTest(fixtures.TestBase, AssertsCompiledSQL):
__only_on__ = 'oracle'
diff --git a/test/sql/test_constraints.py b/test/sql/test_constraints.py
index b44a65190..393bcd448 100644
--- a/test/sql/test_constraints.py
+++ b/test/sql/test_constraints.py
@@ -726,6 +726,27 @@ class ConstraintCompilationTest(fixtures.TestBase, AssertsCompiledSQL):
"ALTER TABLE tbl ADD PRIMARY KEY (a)"
)
+ def test_render_check_constraint_sql_literal(self):
+ t, t2 = self._constraint_create_fixture()
+
+ constraint = CheckConstraint(t.c.a > 5)
+
+ self.assert_compile(
+ schema.AddConstraint(constraint),
+ "ALTER TABLE tbl ADD CHECK (a > 5)"
+ )
+
+ def test_render_index_sql_literal(self):
+ t, t2 = self._constraint_create_fixture()
+
+ constraint = Index('name', t.c.a + 5)
+
+ self.assert_compile(
+ schema.CreateIndex(constraint),
+ "CREATE INDEX name ON tbl (a + 5)"
+ )
+
+
class ConstraintAPITest(fixtures.TestBase):
def test_double_fk_usage_raises(self):
f = ForeignKey('b.id')