]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Reworked SQLiteDialect's check constraint reflection regex as verbose.
authorJeff Horemans <jeff.horemans@vortex-financials.be>
Thu, 8 Aug 2024 16:18:16 +0000 (18:18 +0200)
committerJeff Horemans <jeff.horemans@vortex-financials.be>
Thu, 8 Aug 2024 16:18:16 +0000 (18:18 +0200)
lib/sqlalchemy/dialects/sqlite/base.py

index b088ff935213f40680a93cd43bb56231c5dbaa67..1db4f49d1587a34f634c464278fefd2a271122e2 100644 (file)
@@ -2640,9 +2640,52 @@ class SQLiteDialect(default.DefaultDialect):
         #   non-capturing and non-consuming group, allowing the next one
         #   to match, or the end of the table definition
         #   e.g. newline and closing ')'.
-        CHECK_PATTERN = r"(?:CONSTRAINT ((?:(?! PRIMARY | FOREIGN KEY| UNIQUE | CHECK ).)+) )?CHECK \((.+?)\)(?:, *\n\t?(?=CONSTRAINT|CHECK)|\n\))"
+        CHECK_PATTERN = r"""
+        # Non-capturing group for the name part of named check constraints.
+        # This group is optional as unnamed check constraints can exist.
+        (?:
+        # Match beginning of constraint definition seperated by whitespace.
+        CONSTRAINT\s
+
+        # First capturing group that matches the actual name of the constraint.
+        # Any characters is allowed, as long as none of the reserved table
+        # constraint keywords are encountered using a negative lookahead.
+        ((?:(?!\sPRIMARY\s|\sFOREIGN\sKEY|\sUNIQUE\s|\sCHECK\s).)+)
+
+        # End of optional non-capturing name group seperated by whitespace.
+        \s)?
+
+        # Match beginning of the check expression with starting parenthesis
+        # and optional whitespace.
+        CHECK\s?\(
+
+        # Match actual expression, which can be any character.
+        (.+?)
+
+        # End parenthesis of the check expression.
+        \)
+
+        # Non-capturing group that helps denote the end of the check
+        # expression part.
+        # This can either be (1) the beginning of the next constraint,
+        # or (2) the end of the table definition.
+        (?:
+
+        # (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)
+        # OR operator, seperating (1) & (2)
+        |
+        # (2) Matches end parenthesis of table definition, seperated by
+        # newline.
+        \n\)
+        # End of non-capturing group.
+        )
+        """
         cks = []
-        for match in re.finditer(CHECK_PATTERN, table_data or "", re.I | re.S):
+        for match in re.finditer(CHECK_PATTERN, table_data or "",
+                                 re.I | re.S | re.VERBOSE):
             name = match.group(1)
 
             if name: