summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2020-12-26 11:16:51 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2020-12-26 11:16:51 -0500
commite81bc1f098ea40cf38ec4e4007c11c7f3ffc9712 (patch)
tree55f5d0663d3239182fc01605c2c144bb54657127
parent0cc8a08262f6b92746a280387282d55beb24fa9d (diff)
downloadsqlalchemy-e81bc1f098ea40cf38ec4e4007c11c7f3ffc9712.tar.gz
narrow the check for double-paren exprs in mysql create_index
Fixed regression from SQLAlchemy 1.3.20 caused by the fix for :ticket:`5462` which adds double-parenthesis for MySQL functional expressions in indexes, as is required by the backend, this inadvertently extended to include arbitrary :func:`_sql.text` expressions as well as Alembic's internal textual component, which are required by Alembic for arbitrary index expressions which don't imply double parenthesis. The check has been narrowed to include only binary/ unary/functional expressions directly. Fixes: #5800 Change-Id: I40f83c6f9dd04b984d0c86eba632a588570709a1
-rw-r--r--doc/build/changelog/unreleased_13/5800.rst12
-rw-r--r--lib/sqlalchemy/dialects/mysql/base.py10
-rw-r--r--test/dialect/mysql/test_compiler.py40
3 files changed, 58 insertions, 4 deletions
diff --git a/doc/build/changelog/unreleased_13/5800.rst b/doc/build/changelog/unreleased_13/5800.rst
new file mode 100644
index 000000000..11bb7309e
--- /dev/null
+++ b/doc/build/changelog/unreleased_13/5800.rst
@@ -0,0 +1,12 @@
+.. change::
+ :tags: bug, mysql
+ :tickets: 5800
+
+ Fixed regression from SQLAlchemy 1.3.20 caused by the fix for
+ :ticket:`5462` which adds double-parenthesis for MySQL functional
+ expressions in indexes, as is required by the backend, this inadvertently
+ extended to include arbitrary :func:`_sql.text` expressions as well as
+ Alembic's internal textual component, which are required by Alembic for
+ arbitrary index expressions which don't imply double parenthesis. The
+ check has been narrowed to include only binary/ unary/functional
+ expressions directly. \ No newline at end of file
diff --git a/lib/sqlalchemy/dialects/mysql/base.py b/lib/sqlalchemy/dialects/mysql/base.py
index f90d961d8..7a4d3261f 100644
--- a/lib/sqlalchemy/dialects/mysql/base.py
+++ b/lib/sqlalchemy/dialects/mysql/base.py
@@ -978,6 +978,7 @@ from ...engine import reflection
from ...sql import coercions
from ...sql import compiler
from ...sql import elements
+from ...sql import functions
from ...sql import operators
from ...sql import roles
from ...sql import util as sql_util
@@ -2027,12 +2028,13 @@ class MySQLDDLCompiler(compiler.DDLCompiler):
self.sql_compiler.process(
elements.Grouping(expr)
if (
- not isinstance(expr, elements.ColumnClause)
- and (
- not isinstance(expr, elements.UnaryExpression)
- or expr.modifier
+ isinstance(expr, elements.BinaryExpression)
+ or (
+ isinstance(expr, elements.UnaryExpression)
+ and expr.modifier
not in (operators.desc_op, operators.asc_op)
)
+ or isinstance(expr, functions.FunctionElement)
)
else expr,
include_table=False,
diff --git a/test/dialect/mysql/test_compiler.py b/test/dialect/mysql/test_compiler.py
index 7bddebd17..2993f96b8 100644
--- a/test/dialect/mysql/test_compiler.py
+++ b/test/dialect/mysql/test_compiler.py
@@ -40,6 +40,7 @@ from sqlalchemy import String
from sqlalchemy import Table
from sqlalchemy import testing
from sqlalchemy import TEXT
+from sqlalchemy import text
from sqlalchemy import TIME
from sqlalchemy import Time
from sqlalchemy import TIMESTAMP
@@ -99,6 +100,45 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL):
"CREATE FULLTEXT INDEX test_idx1 " "ON testtbl (data(10))",
)
+ def test_create_index_with_text(self):
+ m = MetaData()
+ tbl = Table("testtbl", m, Column("data", String(255)))
+ idx = Index("test_idx1", text("created_at desc"), _table=tbl)
+
+ self.assert_compile(
+ schema.CreateIndex(idx),
+ "CREATE INDEX test_idx1 ON testtbl (created_at desc)",
+ )
+
+ def test_create_index_with_arbitrary_column_element(self):
+ from sqlalchemy.ext.compiler import compiles
+
+ class _textual_index_element(sql.ColumnElement):
+ """alembic's wrapper"""
+
+ __visit_name__ = "_textual_idx_element"
+
+ def __init__(self, table, text):
+ self.table = table
+ self.text = text
+
+ @compiles(_textual_index_element)
+ def _render_textual_index_column(element, compiler, **kw):
+ return compiler.process(element.text, **kw)
+
+ m = MetaData()
+ tbl = Table("testtbl", m, Column("data", String(255)))
+ idx = Index(
+ "test_idx1",
+ _textual_index_element(tbl, text("created_at desc")),
+ _table=tbl,
+ )
+
+ self.assert_compile(
+ schema.CreateIndex(idx),
+ "CREATE INDEX test_idx1 ON testtbl (created_at desc)",
+ )
+
def test_create_index_with_parser(self):
m = MetaData()
tbl = Table("testtbl", m, Column("data", String(255)))