From: Mike Bayer Date: Thu, 3 Dec 2020 16:17:08 +0000 (-0500) Subject: Reflect decimal points in MariaDB non-quoted numeric defaults X-Git-Tag: rel_1_3_21~6^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=aabf16a14748a5746c97cce9c301ccb8ac05b418;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Reflect decimal points in MariaDB non-quoted numeric defaults Fixed issue where reflecting a server default on MariaDB only that contained a decimal point in the value would fail to be reflected correctly, leading towards a reflected table that lacked any server default. Fixes: #5744 Change-Id: Ifc5960928685a906558ba84ed6f59eecb3b1c358 (cherry picked from commit 7fb41cfc69c6521bebce229a56bddd6267f39955) --- diff --git a/doc/build/changelog/unreleased_13/5744.rst b/doc/build/changelog/unreleased_13/5744.rst new file mode 100644 index 0000000000..7325279e84 --- /dev/null +++ b/doc/build/changelog/unreleased_13/5744.rst @@ -0,0 +1,10 @@ +.. change:: + :tags: bug, mysql, reflection + :tickets: 5744 + :versions: 1.4.0b2 + + Fixed issue where reflecting a server default on MariaDB only that + contained a decimal point in the value would fail to be reflected + correctly, leading towards a reflected table that lacked any server + default. + diff --git a/lib/sqlalchemy/dialects/mysql/reflection.py b/lib/sqlalchemy/dialects/mysql/reflection.py index 2cb9b3a6db..00400c138e 100644 --- a/lib/sqlalchemy/dialects/mysql/reflection.py +++ b/lib/sqlalchemy/dialects/mysql/reflection.py @@ -381,8 +381,8 @@ class MySQLTableDefinitionParser(object): r"(?: +COLLATE +(?P[\w_]+))?" r"(?: +(?P(?:NOT )?NULL))?" r"(?: +DEFAULT +(?P" - r"(?:NULL|'(?:''|[^'])*'|[\w\(\)]+" - r"(?: +ON UPDATE [\w\(\)]+)?)" + r"(?:NULL|'(?:''|[^'])*'|[\w\.\(\)]+" + r"(?: +ON UPDATE [\w\.\(\)]+)?)" r"))?" r"(?: +(?:GENERATED ALWAYS)? ?AS +(?P\(" r".*\))? ?(?PVIRTUAL|STORED)?)?" diff --git a/test/dialect/mysql/test_reflection.py b/test/dialect/mysql/test_reflection.py index dfc7992d26..b11ecd4897 100644 --- a/test/dialect/mysql/test_reflection.py +++ b/test/dialect/mysql/test_reflection.py @@ -235,6 +235,9 @@ class ReflectionTest(fixtures.TestBase, AssertsCompiledSQL): def test_default_reflection(self): """Test reflection of column defaults.""" + # TODO: this test is a mess. should be broken into individual + # combinations + from sqlalchemy.dialects.mysql import VARCHAR def_table = Table( @@ -259,6 +262,8 @@ class ReflectionTest(fixtures.TestBase, AssertsCompiledSQL): ) ), ), + Column("c7", mysql.DOUBLE(), DefaultClause("0.0000")), + Column("c8", mysql.DOUBLE(22, 6), DefaultClause("0.0000")), ) def_table.create() try: @@ -278,6 +283,15 @@ class ReflectionTest(fixtures.TestBase, AssertsCompiledSQL): assert reflected.c.c5.default is None assert reflected.c.c5.server_default is None assert reflected.c.c6.default is None + assert str(reflected.c.c7.server_default.arg) in ("0", "'0'") + + # this is because the numeric is 6 decimal places, MySQL + # formats it to that many places. + assert str(reflected.c.c8.server_default.arg) in ( + "0.000000", + "'0.000000'", + ) + assert re.match( r"CURRENT_TIMESTAMP(\(\))? ON UPDATE CURRENT_TIMESTAMP(\(\))?", str(reflected.c.c6.server_default.arg).upper(), @@ -298,6 +312,11 @@ class ReflectionTest(fixtures.TestBase, AssertsCompiledSQL): assert reflected.c.c5.default is None assert reflected.c.c5.server_default is None assert reflected.c.c6.default is None + assert str(reflected.c.c7.server_default.arg) in ("0", "'0'") + assert str(reflected.c.c8.server_default.arg) in ( + "0.000000", + "'0.000000'", + ) assert re.match( r"CURRENT_TIMESTAMP(\(\))? ON UPDATE CURRENT_TIMESTAMP(\(\))?", str(reflected.c.c6.server_default.arg).upper(),