Ticket #14204: 14204-sqlite-fk-constraints.diff
File 14204-sqlite-fk-constraints.diff, 5.0 KB (added by , 14 years ago) |
---|
-
django/db/backends/sqlite3/base.py
diff --git a/django/db/backends/sqlite3/base.py b/django/db/backends/sqlite3/base.py
a b 24 24 except ImportError, e1: 25 25 from sqlite3 import dbapi2 as Database 26 26 except ImportError, exc: 27 import sys28 27 from django.core.exceptions import ImproperlyConfigured 29 28 if sys.version_info < (2, 5, 0): 30 29 module = 'pysqlite2 module' … … 62 61 can_use_chunked_reads = False 63 62 64 63 class DatabaseOperations(BaseDatabaseOperations): 64 def __init__(self, connection): 65 super(DatabaseOperations, self).__init__() 66 self.connection = connection 67 65 68 def date_extract_sql(self, lookup_type, field_name): 66 69 # sqlite doesn't support extract, so we fake it with the user-defined 67 70 # function django_extract that's registered in connect(). Note that … … 128 131 # No field, or the field isn't known to be a decimal or integer 129 132 return value 130 133 134 def deferrable_sql(self): 135 """ 136 Returns the SQL necessary to make a constraint "initially deferred" 137 during a CREATE TABLE statement. 138 """ 139 if self.connection.supports_fk_constraints: 140 return " ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED" 141 return '' 142 131 143 class DatabaseWrapper(BaseDatabaseWrapper): 132 144 133 145 # SQLite requires LIKE statements to include an ESCAPE clause if the value … … 154 166 super(DatabaseWrapper, self).__init__(*args, **kwargs) 155 167 156 168 self.features = DatabaseFeatures() 157 self.ops = DatabaseOperations( )169 self.ops = DatabaseOperations(self) 158 170 self.client = DatabaseClient(self) 159 171 self.creation = DatabaseCreation(self) 160 172 self.introspection = DatabaseIntrospection(self) 161 173 self.validation = BaseDatabaseValidation(self) 174 self.supports_fk_constraints = False 162 175 163 176 def _cursor(self): 177 new_connection = False 164 178 if self.connection is None: 179 new_connection = True 165 180 settings_dict = self.settings_dict 166 181 if not settings_dict['NAME']: 167 182 from django.core.exceptions import ImproperlyConfigured … … 177 192 self.connection.create_function("django_date_trunc", 2, _sqlite_date_trunc) 178 193 self.connection.create_function("regexp", 2, _sqlite_regexp) 179 194 connection_created.send(sender=self.__class__, connection=self) 180 return self.connection.cursor(factory=SQLiteCursorWrapper) 195 cursor = self.connection.cursor(factory=SQLiteCursorWrapper) 196 if new_connection: 197 self.supports_fk_constraints = self._check_fk_constraint_support(cursor) 198 if self.supports_fk_constraints: 199 cursor.execute("PRAGMA foreign_keys = ON") 200 return cursor 181 201 182 202 def close(self): 183 203 # If database is in memory, closing the connection destroys the … … 186 206 if self.settings_dict['NAME'] != ":memory:": 187 207 BaseDatabaseWrapper.close(self) 188 208 209 def _check_fk_constraint_support(self, cursor): 210 cursor.execute("PRAGMA foreign_keys") 211 v = cursor.fetchone() 212 if v is None: 213 return False 214 return True 215 189 216 FORMAT_QMARK_REGEX = re.compile(r'(?![^%])%s') 190 217 191 218 class SQLiteCursorWrapper(Database.Cursor): -
django/db/backends/sqlite3/creation.py
diff --git a/django/db/backends/sqlite3/creation.py b/django/db/backends/sqlite3/creation.py
a b 64 64 if test_database_name and test_database_name != ":memory:": 65 65 # Remove the SQLite database file 66 66 os.remove(test_database_name) 67 68 def sql_for_inline_foreign_key_references(self, field, known_models, style): 69 "Return the SQL snippet defining the foreign key reference for a field" 70 if self.connection.supports_fk_constraints: 71 qn = self.connection.ops.quote_name 72 output = [style.SQL_KEYWORD('REFERENCES') + ' ' + \ 73 style.SQL_TABLE(qn(field.rel.to._meta.db_table)) + ' (' + \ 74 style.SQL_FIELD(qn(field.rel.to._meta.get_field(field.rel.field_name).column)) + ')' + 75 self.connection.ops.deferrable_sql() 76 ] 77 return output, False 78 return super(DatabaseCreation, self).sql_for_inline_foreign_key_references(field, known_models, style) 79 80 def sql_destroy_model(self, model, references_to_delete, style): 81 "Return the DROP TABLE and restraint dropping statements for a single model" 82 if self.connection.supports_fk_constraints: 83 if not model._meta.managed or model._meta.proxy: 84 return [] 85 # Drop the table now 86 qn = self.connection.ops.quote_name 87 output = ['%s %s;' % (style.SQL_KEYWORD('DROP TABLE'), 88 style.SQL_TABLE(qn(model._meta.db_table)))] 89 return output 90 return super(DatabaseCreation, self).sql_destroy_model(model, references_to_delete, style)