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:
d85b2c5b51e45cec543c9ae9d62d6d659b063354
Change-Id: I173137f0bf68639cad0d5c329055475b40ddb5e4
--- /dev/null
+.. 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.
\ No newline at end of file
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
pass
return state
+ def _check_view(self, sql: str) -> bool:
+ return bool(self._re_is_view.match(sql))
+
def _parse_constraints(self, line):
"""Parse a KEY or CONSTRAINT line.
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(
class RawReflectionTest(fixtures.TestBase):
- __backend__ = True
-
def setup_test(self):
dialect = mysql.dialect()
self.parser = _reflection.MySQLTableDefinitionParser(
"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: str, expected: bool) -> None:
+ is_(self.parser._check_view(sql), expected)