From: Mike Bayer Date: Sun, 13 Oct 2013 00:04:55 +0000 (-0400) Subject: - Fixed bug in default compiler plus those of postgresql, mysql, and X-Git-Tag: rel_0_8_3~17 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d8c17e2a6f41d0aad331678e916f1aa4f07e4f7b;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - 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. Conflicts: lib/sqlalchemy/sql/util.py --- diff --git a/doc/build/changelog/changelog_08.rst b/doc/build/changelog/changelog_08.rst index 0937aaad57..3d2179f5a7 100644 --- a/doc/build/changelog/changelog_08.rst +++ b/doc/build/changelog/changelog_08.rst @@ -10,6 +10,16 @@ .. changelog:: :version: 0.8.3 + .. 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 diff --git a/lib/sqlalchemy/dialects/mssql/base.py b/lib/sqlalchemy/dialects/mssql/base.py index fc952f4b59..fa6db3453c 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 0fe4595030..8ead8f148a 100644 --- a/lib/sqlalchemy/dialects/mysql/base.py +++ b/lib/sqlalchemy/dialects/mysql/base.py @@ -1532,7 +1532,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 1c8a71fbd1..2cbe7c8300 100644 --- a/lib/sqlalchemy/dialects/postgresql/base.py +++ b/lib/sqlalchemy/dialects/postgresql/base.py @@ -1101,12 +1101,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)]) ) @@ -1116,8 +1113,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 @@ -1132,8 +1130,9 @@ class PGDDLCompiler(compiler.DDLCompiler): elements.append(self.preparer.quote(c.name, c.quote)+' 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 13bf47c0b1..0a1fcdfab1 100644 --- a/lib/sqlalchemy/sql/compiler.py +++ b/lib/sqlalchemy/sql/compiler.py @@ -2031,7 +2031,7 @@ class DDLCompiler(engine.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 @@ -2121,8 +2121,9 @@ class DDLCompiler(engine.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 fdc5bb3725..ecb26e2ea9 100644 --- a/lib/sqlalchemy/sql/util.py +++ b/lib/sqlalchemy/sql/util.py @@ -270,6 +270,8 @@ def expression_as_ddl(clause): into detached column constructs so that the parent table identifier is not included. + .. deprecated:: this function is removed in 0.9.0. + """ def repl(element): if isinstance(element, expression.BindParameter): diff --git a/test/dialect/mssql/test_compiler.py b/test/dialect/mssql/test_compiler.py index 87037c6a4e..f218d9d0ed 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 a77a25cc4a..d1488ed330 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 11661b11f5..858f3e7636 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 def4654f02..e3d35e3945 100644 --- a/test/dialect/test_oracle.py +++ b/test/dialect/test_oracle.py @@ -552,6 +552,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 b44a651904..393bcd4480 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')