From: Alexander Ruehe Date: Tue, 1 Apr 2025 21:52:12 +0000 (-0400) Subject: ensure ON UPDATE test is case insensitive X-Git-Tag: rel_2_0_41~34 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ade87b49f5878ecceb1b4cc6f2f11013a6d268f2;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 (cherry picked from commit 6f8f4a7d620f19afce8b8d43c25ff5ca5a466038) --- 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 122a7cb2e5..50976310a7 100644 --- a/lib/sqlalchemy/dialects/mysql/base.py +++ b/lib/sqlalchemy/dialects/mysql/base.py @@ -1933,7 +1933,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 f9cfeba05b..4a799234d9 100644 --- a/test/dialect/mysql/test_compiler.py +++ b/test/dialect/mysql/test_compiler.py @@ -438,6 +438,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) @@ -449,7 +464,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: @@ -459,7 +477,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 96650dab56..a511193131 100644 --- a/test/dialect/mysql/test_query.py +++ b/test/dialect/mysql/test_query.py @@ -56,6 +56,9 @@ class IdiosyncrasyTest(fixtures.TestBase): class ServerDefaultCreateTest(fixtures.TestBase): + __only_on__ = "mysql", "mariadb" + __backend__ = True + @testing.combinations( (Integer, text("10")), (Integer, text("'10'")), @@ -70,6 +73,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(