From 44be2ef4484345298825f547e21d2881cc4921a9 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Wed, 4 Sep 2024 08:45:52 -0400 Subject: [PATCH] Fix regular expression for `SQLiteDialect.get_check_constraints` Fixed regression in SQLite reflection caused by :ticket:`11677` which interfered with reflection for CHECK constraints that were followed by other kinds of constraints within the same table definition. Pull request courtesy Harutaka Kawamura. Fixes: #11832 Closes: #11834 Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/11834 Pull-request-sha: a10fcef45ccfad6ebf17ec94fc48d0965f0d4123 Change-Id: I50bcc7aa727f73be235895d154cd859f19adda09 --- doc/build/changelog/unreleased_20/11832.rst | 9 ++++++++ lib/sqlalchemy/dialects/sqlite/base.py | 2 +- test/dialect/test_sqlite.py | 25 ++++++++++++++++++++- 3 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 doc/build/changelog/unreleased_20/11832.rst diff --git a/doc/build/changelog/unreleased_20/11832.rst b/doc/build/changelog/unreleased_20/11832.rst new file mode 100644 index 0000000000..9c1a79df18 --- /dev/null +++ b/doc/build/changelog/unreleased_20/11832.rst @@ -0,0 +1,9 @@ +.. change:: + :tags: bug, sqlite + :tickets: 11832 + + Fixed regression in SQLite reflection caused by :ticket:`11677` which + interfered with reflection for CHECK constraints that were followed + by other kinds of constraints within the same table definition. Pull + request courtesy Harutaka Kawamura. + diff --git a/lib/sqlalchemy/dialects/sqlite/base.py b/lib/sqlalchemy/dialects/sqlite/base.py index cf8f16966b..5e32e2fbb0 100644 --- a/lib/sqlalchemy/dialects/sqlite/base.py +++ b/lib/sqlalchemy/dialects/sqlite/base.py @@ -2674,7 +2674,7 @@ class SQLiteDialect(default.DefaultDialect): # (1) Matches end of check constraint with trailing comma, # optional whitespace (including newline), and the beginning # of the next constraint (either named or unnamed). - ,[\s\n]*(?=CONSTRAINT|CHECK) + ,[\s\n]*(?=CONSTRAINT|CHECK|UNIQUE|FOREIGN|PRIMARY) # OR operator, seperating (1) & (2) | # (2) Matches end parenthesis of table definition, seperated by diff --git a/test/dialect/test_sqlite.py b/test/dialect/test_sqlite.py index 8afa800530..ebd5312177 100644 --- a/test/dialect/test_sqlite.py +++ b/test/dialect/test_sqlite.py @@ -1823,16 +1823,18 @@ class ConstraintReflectionTest(fixtures.TestBase): Column("id", Integer), Column("value", Integer), Column("prefix", String), - PrimaryKeyConstraint("id"), CheckConstraint("id > 0"), + UniqueConstraint("prefix", name="prefix_named"), # Constraint definition with newline and tab characters CheckConstraint( """((value > 0) AND \n\t(value < 100) AND \n\t (value != 50))""", name="ck_r_value_multiline", ), + UniqueConstraint("value"), # Constraint name with special chars and 'check' in the name CheckConstraint("value IS NOT NULL", name="^check-r* #\n\t"), + PrimaryKeyConstraint("id", name="pk_name"), # Constraint definition with special characters. CheckConstraint("prefix NOT GLOB '*[^-. /#,]*'"), ) @@ -2448,6 +2450,27 @@ class ConstraintReflectionTest(fixtures.TestBase): [{"column_names": ["x"], "name": None}], ) + def test_unique_constraint_mixed_into_ck(self, connection): + """test #11832""" + + inspector = inspect(connection) + eq_( + inspector.get_unique_constraints("r"), + [ + {"name": "prefix_named", "column_names": ["prefix"]}, + {"name": None, "column_names": ["value"]}, + ], + ) + + def test_primary_key_constraint_mixed_into_ck(self, connection): + """test #11832""" + + inspector = inspect(connection) + eq_( + inspector.get_pk_constraint("r"), + {"constrained_columns": ["id"], "name": "pk_name"}, + ) + def test_primary_key_constraint_named(self): inspector = inspect(testing.db) eq_( -- 2.47.2