adjust MySQL view reflection for non-standard MySQL variants

Adjusted the regular expression used to match "CREATE VIEW" when
testing for views to work more flexibly, no longer requiring the
special keyword "ALGORITHM" in the middle, which was intended to be
optional but was not working correctly.  The change allows view reflection
to work more completely on MySQL-compatible variants such as StarRocks.
Pull request courtesy John Bodley.

Fixes: #8588
Closes: #8589
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/8589
Pull-request-sha: d85b2c5b51

Change-Id: I173137f0bf68639cad0d5c329055475b40ddb5e4
(cherry picked from commit 9829bc43d6)
This commit is contained in:
John Bodley
2022-09-29 21:58:58 -04:00
committed by Mike Bayer
parent f354465125
commit 322b9b4faa
4 changed files with 31 additions and 3 deletions
+10
View File
@@ -0,0 +1,10 @@
.. change::
:tags: bug, mysql
:tickets: 8588
Adjusted the regular expression used to match "CREATE VIEW" when
testing for views to work more flexibly, no longer requiring the
special keyword "ALGORITHM" in the middle, which was intended to be
optional but was not working correctly. The change allows view reflection
to work more completely on MySQL-compatible variants such as StarRocks.
Pull request courtesy John Bodley.
+1 -1
View File
@@ -3107,7 +3107,7 @@ class MySQLDialect(default.DefaultDialect):
sql = self._show_create_table(
connection, None, charset, full_name=full_name
)
if re.match(r"^CREATE (?:ALGORITHM)?.* VIEW", sql):
if parser._check_view(sql):
# Adapt views to something table-like.
columns = self._describe_table(
connection, None, charset, full_name=full_name
@@ -70,6 +70,9 @@ class MySQLTableDefinitionParser(object):
pass
return state
def _check_view(self, sql):
return bool(self._re_is_view.match(sql))
def _parse_constraints(self, line):
"""Parse a KEY or CONSTRAINT line.
@@ -349,6 +352,8 @@ class MySQLTableDefinitionParser(object):
self.preparer._unescape_identifier,
)
self._re_is_view = _re_compile(r"^CREATE(?! TABLE)(\s.*)?\sVIEW")
# `col`,`col2`(32),`col3`(15) DESC
#
self._re_keyexprs = _re_compile(
+15 -2
View File
@@ -1122,8 +1122,6 @@ class ReflectionTest(fixtures.TestBase, AssertsCompiledSQL):
class RawReflectionTest(fixtures.TestBase):
__backend__ = True
def setup_test(self):
dialect = mysql.dialect()
self.parser = _reflection.MySQLTableDefinitionParser(
@@ -1249,3 +1247,18 @@ class RawReflectionTest(fixtures.TestBase):
"SET NULL",
),
)
@testing.combinations(
(
"CREATE ALGORITHM=UNDEFINED DEFINER=`scott`@`%` "
"SQL SECURITY DEFINER VIEW `v1` AS SELECT",
True,
),
("CREATE VIEW `v1` AS SELECT", True),
("CREATE TABLE `v1`", False),
("CREATE TABLE `VIEW`", False),
("CREATE TABLE `VIEW_THINGS`", False),
("CREATE TABLE `A VIEW`", False),
)
def test_is_view(self, sql, expected):
is_(self.parser._check_view(sql), expected)