Fixed #32158 -- Fixed loaddata crash on SQLite when table/column names are SQL keywords.

This commit is contained in:
Chinmoy Chakraborty 2020-12-28 11:15:48 +05:30 committed by Mariusz Felisiak
parent 89fc144ded
commit 270072c4c2
3 changed files with 28 additions and 4 deletions

View File

@ -327,19 +327,24 @@ class DatabaseWrapper(BaseDatabaseWrapper):
violations = cursor.execute('PRAGMA foreign_key_check').fetchall() violations = cursor.execute('PRAGMA foreign_key_check').fetchall()
else: else:
violations = chain.from_iterable( violations = chain.from_iterable(
cursor.execute('PRAGMA foreign_key_check(%s)' % table_name).fetchall() cursor.execute(
'PRAGMA foreign_key_check(%s)'
% self.ops.quote_name(table_name)
).fetchall()
for table_name in table_names for table_name in table_names
) )
# See https://www.sqlite.org/pragma.html#pragma_foreign_key_check # See https://www.sqlite.org/pragma.html#pragma_foreign_key_check
for table_name, rowid, referenced_table_name, foreign_key_index in violations: for table_name, rowid, referenced_table_name, foreign_key_index in violations:
foreign_key = cursor.execute( foreign_key = cursor.execute(
'PRAGMA foreign_key_list(%s)' % table_name 'PRAGMA foreign_key_list(%s)' % self.ops.quote_name(table_name)
).fetchall()[foreign_key_index] ).fetchall()[foreign_key_index]
column_name, referenced_column_name = foreign_key[3:5] column_name, referenced_column_name = foreign_key[3:5]
primary_key_column_name = self.introspection.get_primary_key_column(cursor, table_name) primary_key_column_name = self.introspection.get_primary_key_column(cursor, table_name)
primary_key_value, bad_value = cursor.execute( primary_key_value, bad_value = cursor.execute(
'SELECT %s, %s FROM %s WHERE rowid = %%s' % ( 'SELECT %s, %s FROM %s WHERE rowid = %%s' % (
primary_key_column_name, column_name, table_name self.ops.quote_name(primary_key_column_name),
self.ops.quote_name(column_name),
self.ops.quote_name(table_name),
), ),
(rowid,), (rowid,),
).fetchone() ).fetchone()

View File

@ -140,3 +140,11 @@ class Author(models.Model):
class Book(models.Model): class Book(models.Model):
author = models.ForeignKey(Author, models.CASCADE, to_field='name') author = models.ForeignKey(Author, models.CASCADE, to_field='name')
class SQLKeywordsModel(models.Model):
id = models.AutoField(primary_key=True, db_column='select')
reporter = models.ForeignKey(Reporter, models.CASCADE, db_column='where')
class Meta:
db_table = 'order'

View File

@ -20,7 +20,7 @@ from django.test import (
from .models import ( from .models import (
Article, Object, ObjectReference, Person, Post, RawData, Reporter, Article, Object, ObjectReference, Person, Post, RawData, Reporter,
ReporterProxy, SchoolClass, Square, ReporterProxy, SchoolClass, SQLKeywordsModel, Square,
VeryLongModelNameZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ, VeryLongModelNameZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ,
) )
@ -625,6 +625,17 @@ class FkConstraintsTests(TransactionTestCase):
connection.check_constraints() connection.check_constraints()
transaction.set_rollback(True) transaction.set_rollback(True)
def test_check_constraints_sql_keywords(self):
with transaction.atomic():
obj = SQLKeywordsModel.objects.create(reporter=self.r)
obj.refresh_from_db()
obj.reporter_id = 30
with connection.constraint_checks_disabled():
obj.save()
with self.assertRaises(IntegrityError):
connection.check_constraints(table_names=['order'])
transaction.set_rollback(True)
class ThreadTests(TransactionTestCase): class ThreadTests(TransactionTestCase):