summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaveł Tyślacki <pavel.tyslacki@gmail.com>2019-02-28 00:44:45 +0300
committerTim Graham <timograham@gmail.com>2019-03-15 19:44:49 -0400
commitd8252025bc85b23e8f9d774f46dc2773750deebf (patch)
tree1ab1270b8052cafc25e509cfc58301ccd2217f72
parentaaf45d542245c2d209ca63f97295f5f746a41997 (diff)
[2.2.x] Refs #30183 -- Moved SQLite table constraint parsing to a method.
Backport of 4492be348ad6fb24957068e63448142399629d18 from master.
-rw-r--r--django/db/backends/sqlite3/introspection.py88
1 files changed, 47 insertions, 41 deletions
diff --git a/django/db/backends/sqlite3/introspection.py b/django/db/backends/sqlite3/introspection.py
index fd8accb04e..aa141ea089 100644
--- a/django/db/backends/sqlite3/introspection.py
+++ b/django/db/backends/sqlite3/introspection.py
@@ -234,6 +234,52 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
}
return constraints
+ def _parse_table_constraints(self, sql):
+ # Check constraint parsing is based of SQLite syntax diagram.
+ # https://www.sqlite.org/syntaxdiagrams.html#table-constraint
+ def next_ttype(ttype):
+ for token in tokens:
+ if token.ttype == ttype:
+ return token
+
+ statement = sqlparse.parse(sql)[0]
+ constraints = {}
+ tokens = statement.flatten()
+ for token in tokens:
+ name = None
+ if token.match(sqlparse.tokens.Keyword, 'CONSTRAINT'):
+ # Table constraint
+ name_token = next_ttype(sqlparse.tokens.Literal.String.Symbol)
+ name = name_token.value[1:-1]
+ token = next_ttype(sqlparse.tokens.Keyword)
+ if token.match(sqlparse.tokens.Keyword, 'UNIQUE'):
+ constraints[name] = {
+ 'unique': True,
+ 'columns': [],
+ 'primary_key': False,
+ 'foreign_key': None,
+ 'check': False,
+ 'index': False,
+ }
+ if token.match(sqlparse.tokens.Keyword, 'CHECK'):
+ # Column check constraint
+ if name is None:
+ column_token = next_ttype(sqlparse.tokens.Literal.String.Symbol)
+ column = column_token.value[1:-1]
+ name = '__check__%s' % column
+ columns = [column]
+ else:
+ columns = []
+ constraints[name] = {
+ 'check': True,
+ 'columns': columns,
+ 'primary_key': False,
+ 'unique': False,
+ 'foreign_key': None,
+ 'index': False,
+ }
+ return constraints
+
def get_constraints(self, cursor, table_name):
"""
Retrieve any constraints or keys (unique, pk, fk, check, index) across
@@ -251,48 +297,8 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
# table_name is a view.
pass
else:
- # Check constraint parsing is based of SQLite syntax diagram.
- # https://www.sqlite.org/syntaxdiagrams.html#table-constraint
- def next_ttype(ttype):
- for token in tokens:
- if token.ttype == ttype:
- return token
+ constraints.update(self._parse_table_constraints(table_schema))
- statement = sqlparse.parse(table_schema)[0]
- tokens = statement.flatten()
- for token in tokens:
- name = None
- if token.match(sqlparse.tokens.Keyword, 'CONSTRAINT'):
- # Table constraint
- name_token = next_ttype(sqlparse.tokens.Literal.String.Symbol)
- name = name_token.value[1:-1]
- token = next_ttype(sqlparse.tokens.Keyword)
- if token.match(sqlparse.tokens.Keyword, 'UNIQUE'):
- constraints[name] = {
- 'unique': True,
- 'columns': [],
- 'primary_key': False,
- 'foreign_key': None,
- 'check': False,
- 'index': False,
- }
- if token.match(sqlparse.tokens.Keyword, 'CHECK'):
- # Column check constraint
- if name is None:
- column_token = next_ttype(sqlparse.tokens.Literal.String.Symbol)
- column = column_token.value[1:-1]
- name = '__check__%s' % column
- columns = [column]
- else:
- columns = []
- constraints[name] = {
- 'check': True,
- 'columns': columns,
- 'primary_key': False,
- 'unique': False,
- 'foreign_key': None,
- 'index': False,
- }
# Get the index info
cursor.execute("PRAGMA index_list(%s)" % self.connection.ops.quote_name(table_name))
for row in cursor.fetchall():