From: Georg Wicke-Arndt Date: Tue, 9 Jan 2024 13:04:33 +0000 (+0100) Subject: Parse NOT NULL for MySQL generated columns X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=77c6e85a3182c32e2cf97a9ed27c7173968b0f8f;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Parse NOT NULL for MySQL generated columns As per the MySQL CREATE TABLE specification (see https://dev.mysql.com/doc/refman/8.0/en/create-table.html), the location of the NULL/NOT NULL syntax is slightly different for generated vs. regular columns: in generated columns, the NULL/NOT NULL goes after the VIRTUAL/STORED instead of directly after the data type. Fixes #10850 --- diff --git a/lib/sqlalchemy/dialects/mysql/reflection.py b/lib/sqlalchemy/dialects/mysql/reflection.py index 74c60f07b5..c764e8ccc7 100644 --- a/lib/sqlalchemy/dialects/mysql/reflection.py +++ b/lib/sqlalchemy/dialects/mysql/reflection.py @@ -290,6 +290,9 @@ class MySQLTableDefinitionParser: # this can be "NULL" in the case of TIMESTAMP if spec.get("notnull", False) == "NOT NULL": col_kw["nullable"] = False + # For generated columns, the nullability is marked in a different place + if spec.get("notnull_generated", False) == "NOT NULL": + col_kw["nullable"] = False # AUTO_INCREMENT if spec.get("autoincr", False): @@ -452,7 +455,9 @@ class MySQLTableDefinitionParser: r"(?: +ON UPDATE [\-\w\.\(\)]+)?)" r"))?" r"(?: +(?:GENERATED ALWAYS)? ?AS +(?P\(" - r".*\))? ?(?PVIRTUAL|STORED)?)?" + r".*\))? ?(?PVIRTUAL|STORED)?" + r"(?: +(?P(?:NOT )?NULL))?" + r")?" r"(?: +(?PAUTO_INCREMENT))?" r"(?: +COMMENT +'(?P(?:''|[^'])*)')?" r"(?: +COLUMN_FORMAT +(?P\w+))?" diff --git a/test/dialect/mysql/test_reflection.py b/test/dialect/mysql/test_reflection.py index f3d1f34599..573fed45d8 100644 --- a/test/dialect/mysql/test_reflection.py +++ b/test/dialect/mysql/test_reflection.py @@ -792,6 +792,7 @@ class ReflectionTest(fixtures.TestBase, AssertsCompiledSQL): ["s TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP"], ["t TIMESTAMP"], ["u TIMESTAMP DEFAULT CURRENT_TIMESTAMP"], + ["v INTEGER GENERATED ALWAYS AS (4711) VIRTUAL NOT NULL"], ] ): Table("nn_t%d" % idx, meta) # to allow DROP @@ -859,6 +860,7 @@ class ReflectionTest(fixtures.TestBase, AssertsCompiledSQL): else False, "default": current_timestamp, }, + {"name": "v", "nullable": False, "default": None}, ], )