summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2015-01-16 18:03:45 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2015-01-16 18:03:45 -0500
commit79fa69f1f37fdbc0dfec6bdea1e07f52bfe18f7b (patch)
tree02fba7faed7318101abc98c17ce3fdc50ea8110e
parent41307cd7339a2a2aee0a3dd9c8b994df99d7eedb (diff)
downloadsqlalchemy-79fa69f1f37fdbc0dfec6bdea1e07f52bfe18f7b.tar.gz
- Fixed bug where Postgresql dialect would fail to render an
expression in an :class:`.Index` that did not correspond directly to a table-bound column; typically when a :func:`.text` construct was one of the expressions within the index; or could misinterpret the list of expressions if one or more of them were such an expression. fixes #3174
-rw-r--r--doc/build/changelog/changelog_09.rst11
-rw-r--r--lib/sqlalchemy/dialects/postgresql/base.py9
-rw-r--r--test/dialect/postgresql/test_compiler.py54
3 files changed, 71 insertions, 3 deletions
diff --git a/doc/build/changelog/changelog_09.rst b/doc/build/changelog/changelog_09.rst
index acead3011..d9cbd5032 100644
--- a/doc/build/changelog/changelog_09.rst
+++ b/doc/build/changelog/changelog_09.rst
@@ -15,6 +15,17 @@
:version: 0.9.9
.. change::
+ :tags: bug, postgresql
+ :versions: 1.0.0
+ :tickets: 3174
+
+ Fixed bug where Postgresql dialect would fail to render an
+ expression in an :class:`.Index` that did not correspond directly
+ to a table-bound column; typically when a :func:`.text` construct
+ was one of the expressions within the index; or could misinterpret the
+ list of expressions if one or more of them were such an expression.
+
+ .. change::
:tags: bug, orm
:versions: 1.0.0
:tickets: 3287
diff --git a/lib/sqlalchemy/dialects/postgresql/base.py b/lib/sqlalchemy/dialects/postgresql/base.py
index fa9a2cfd0..0817fe837 100644
--- a/lib/sqlalchemy/dialects/postgresql/base.py
+++ b/lib/sqlalchemy/dialects/postgresql/base.py
@@ -1477,8 +1477,13 @@ class PGDDLCompiler(compiler.DDLCompiler):
if not isinstance(expr, expression.ColumnClause)
else 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)])
+ (
+ (' ' + ops[expr.key])
+ if hasattr(expr, 'key')
+ and expr.key in ops else ''
+ )
+ for expr in index.expressions
+ ])
)
whereclause = index.dialect_options["postgresql"]["where"]
diff --git a/test/dialect/postgresql/test_compiler.py b/test/dialect/postgresql/test_compiler.py
index 6c4f3c8cc..5717df9f7 100644
--- a/test/dialect/postgresql/test_compiler.py
+++ b/test/dialect/postgresql/test_compiler.py
@@ -5,7 +5,7 @@ from sqlalchemy.testing.assertions import AssertsCompiledSQL, is_, \
from sqlalchemy.testing import engines, fixtures
from sqlalchemy import testing
from sqlalchemy import Sequence, Table, Column, Integer, update, String,\
- insert, func, MetaData, Enum, Index, and_, delete, select, cast
+ insert, func, MetaData, Enum, Index, and_, delete, select, cast, text
from sqlalchemy.dialects.postgresql import ExcludeConstraint, array
from sqlalchemy import exc, schema
from sqlalchemy.dialects.postgresql import base as postgresql
@@ -296,6 +296,58 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL):
'(data text_pattern_ops, data2 int4_ops)',
dialect=postgresql.dialect())
+ def test_create_index_with_text_or_composite(self):
+ m = MetaData()
+ tbl = Table('testtbl', m,
+ Column('d1', String),
+ Column('d2', Integer))
+
+ idx = Index('test_idx1', text('x'))
+ tbl.append_constraint(idx)
+
+ idx2 = Index('test_idx2', text('y'), tbl.c.d2)
+
+ idx3 = Index(
+ 'test_idx2', tbl.c.d1, text('y'), tbl.c.d2,
+ postgresql_ops={'d1': 'x1', 'd2': 'x2'}
+ )
+
+ idx4 = Index(
+ 'test_idx2', tbl.c.d1, tbl.c.d2 > 5, text('q'),
+ postgresql_ops={'d1': 'x1', 'd2': 'x2'}
+ )
+
+ idx5 = Index(
+ 'test_idx2', tbl.c.d1, (tbl.c.d2 > 5).label('g'), text('q'),
+ postgresql_ops={'d1': 'x1', 'g': 'x2'}
+ )
+
+ self.assert_compile(
+ schema.CreateIndex(idx),
+ "CREATE INDEX test_idx1 ON testtbl (x)"
+ )
+ self.assert_compile(
+ schema.CreateIndex(idx2),
+ "CREATE INDEX test_idx2 ON testtbl (y, d2)"
+ )
+ self.assert_compile(
+ schema.CreateIndex(idx3),
+ "CREATE INDEX test_idx2 ON testtbl (d1 x1, y, d2 x2)"
+ )
+
+ # note that at the moment we do not expect the 'd2' op to
+ # pick up on the "d2 > 5" expression
+ self.assert_compile(
+ schema.CreateIndex(idx4),
+ "CREATE INDEX test_idx2 ON testtbl (d1 x1, (d2 > 5), q)"
+ )
+
+ # however it does work if we label!
+ self.assert_compile(
+ schema.CreateIndex(idx5),
+ "CREATE INDEX test_idx2 ON testtbl (d1 x1, (d2 > 5) x2, q)"
+ )
+
def test_create_index_with_using(self):
m = MetaData()
tbl = Table('testtbl', m, Column('data', String))