From: Alexander Ruehe Date: Tue, 1 Apr 2025 21:52:12 +0000 (-0400) Subject: ensure ON UPDATE test is case insensitive X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6f8f4a7d620f19afce8b8d43c25ff5ca5a466038;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git ensure ON UPDATE test is case insensitive Fixed regression caused by the DEFAULT rendering changes in 2.0.40 :ticket:`12425` where using lowercase `on update` in a MySQL server default would incorrectly apply parenthesis, leading to errors when MySQL interpreted the rendered DDL. Pull request courtesy Alexander Ruehe. Fixes: #12488 Closes: #12489 Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/12489 Pull-request-sha: b9008f747d21bc06a4006c99a47fc6aa99407636 Change-Id: If5281c52415e4ddb6c2f8aee191d2335f6673b35 --- diff --git a/doc/build/changelog/unreleased_20/12488.rst b/doc/build/changelog/unreleased_20/12488.rst new file mode 100644 index 0000000000..d81d025bdd --- /dev/null +++ b/doc/build/changelog/unreleased_20/12488.rst @@ -0,0 +1,8 @@ +.. change:: + :tags: bug, mysql + :tickets: 12488 + + Fixed regression caused by the DEFAULT rendering changes in 2.0.40 + :ticket:`12425` where using lowercase `on update` in a MySQL server default + would incorrectly apply parenthesis, leading to errors when MySQL + interpreted the rendered DDL. Pull request courtesy Alexander Ruehe. diff --git a/lib/sqlalchemy/dialects/mysql/base.py b/lib/sqlalchemy/dialects/mysql/base.py index bff907d53b..c3bf5fee3b 100644 --- a/lib/sqlalchemy/dialects/mysql/base.py +++ b/lib/sqlalchemy/dialects/mysql/base.py @@ -1941,7 +1941,7 @@ class MySQLDDLCompiler(compiler.DDLCompiler): if ( self.dialect._support_default_function and not re.match(r"^\s*[\'\"\(]", default) - and "ON UPDATE" not in default + and not re.search(r"ON +UPDATE", default, re.I) and re.match(r".*\W.*", default) ): colspec.append(f"DEFAULT ({default})") diff --git a/test/dialect/mysql/test_compiler.py b/test/dialect/mysql/test_compiler.py index dc36973a9e..92e9bdd2b9 100644 --- a/test/dialect/mysql/test_compiler.py +++ b/test/dialect/mysql/test_compiler.py @@ -442,6 +442,21 @@ class CompileTest(ReservedWordFixture, fixtures.TestBase, AssertsCompiledSQL): "description", String(255), server_default=func.lower("hi") ), Column("data", JSON, server_default=func.json_object()), + Column( + "updated1", + DateTime, + server_default=text("now() on update now()"), + ), + Column( + "updated2", + DateTime, + server_default=text("now() On UpDate now()"), + ), + Column( + "updated3", + DateTime, + server_default=text("now() ON UPDATE now()"), + ), ) eq_(dialect._support_default_function, has_brackets) @@ -453,7 +468,10 @@ class CompileTest(ReservedWordFixture, fixtures.TestBase, AssertsCompiledSQL): "time DATETIME DEFAULT CURRENT_TIMESTAMP, " "name VARCHAR(255) DEFAULT 'some str', " "description VARCHAR(255) DEFAULT (lower('hi')), " - "data JSON DEFAULT (json_object()))", + "data JSON DEFAULT (json_object()), " + "updated1 DATETIME DEFAULT now() on update now(), " + "updated2 DATETIME DEFAULT now() On UpDate now(), " + "updated3 DATETIME DEFAULT now() ON UPDATE now())", dialect=dialect, ) else: @@ -463,7 +481,10 @@ class CompileTest(ReservedWordFixture, fixtures.TestBase, AssertsCompiledSQL): "time DATETIME DEFAULT CURRENT_TIMESTAMP, " "name VARCHAR(255) DEFAULT 'some str', " "description VARCHAR(255) DEFAULT lower('hi'), " - "data JSON DEFAULT json_object())", + "data JSON DEFAULT json_object(), " + "updated1 DATETIME DEFAULT now() on update now(), " + "updated2 DATETIME DEFAULT now() On UpDate now(), " + "updated3 DATETIME DEFAULT now() ON UPDATE now())", dialect=dialect, ) diff --git a/test/dialect/mysql/test_query.py b/test/dialect/mysql/test_query.py index cd1e9327d3..b15ee517aa 100644 --- a/test/dialect/mysql/test_query.py +++ b/test/dialect/mysql/test_query.py @@ -61,6 +61,9 @@ class IdiosyncrasyTest(fixtures.TestBase): class ServerDefaultCreateTest(fixtures.TestBase): + __only_on__ = "mysql", "mariadb" + __backend__ = True + @testing.combinations( (Integer, text("10")), (Integer, text("'10'")), @@ -75,6 +78,18 @@ class ServerDefaultCreateTest(fixtures.TestBase): literal_column("3") + literal_column("5"), testing.requires.mysql_expression_defaults, ), + ( + DateTime, + text("now() ON UPDATE now()"), + ), + ( + DateTime, + text("now() on update now()"), + ), + ( + DateTime, + text("now() ON UPDATE now()"), + ), argnames="datatype, default", ) def test_create_server_defaults(