Fixed #31301 -- Fixed crash of QuerySet.bulk_create() with mixed empty and set ForeignKeys to AutoFields on Oracle.
This commit is contained in:
parent
8b30360322
commit
a21f7b91db
|
@ -62,6 +62,8 @@ class BulkInsertMapper:
|
||||||
TIMESTAMP = 'TO_TIMESTAMP(%s)'
|
TIMESTAMP = 'TO_TIMESTAMP(%s)'
|
||||||
|
|
||||||
types = {
|
types = {
|
||||||
|
'AutoField': NUMBER,
|
||||||
|
'BigAutoField': NUMBER,
|
||||||
'BigIntegerField': NUMBER,
|
'BigIntegerField': NUMBER,
|
||||||
'BinaryField': BLOB,
|
'BinaryField': BLOB,
|
||||||
'BooleanField': NUMBER,
|
'BooleanField': NUMBER,
|
||||||
|
@ -75,6 +77,7 @@ class BulkInsertMapper:
|
||||||
'PositiveBigIntegerField': NUMBER,
|
'PositiveBigIntegerField': NUMBER,
|
||||||
'PositiveIntegerField': NUMBER,
|
'PositiveIntegerField': NUMBER,
|
||||||
'PositiveSmallIntegerField': NUMBER,
|
'PositiveSmallIntegerField': NUMBER,
|
||||||
|
'SmallAutoField': NUMBER,
|
||||||
'SmallIntegerField': NUMBER,
|
'SmallIntegerField': NUMBER,
|
||||||
'TextField': CLOB,
|
'TextField': CLOB,
|
||||||
'TimeField': TIMESTAMP,
|
'TimeField': TIMESTAMP,
|
||||||
|
|
|
@ -64,6 +64,14 @@ class NoFields(models.Model):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class SmallAutoFieldModel(models.Model):
|
||||||
|
id = models.SmallAutoField(primary_key=True)
|
||||||
|
|
||||||
|
|
||||||
|
class BigAutoFieldModel(models.Model):
|
||||||
|
id = models.BigAutoField(primary_key=True)
|
||||||
|
|
||||||
|
|
||||||
class NullableFields(models.Model):
|
class NullableFields(models.Model):
|
||||||
# Fields in db.backends.oracle.BulkInsertMapper
|
# Fields in db.backends.oracle.BulkInsertMapper
|
||||||
big_int_filed = models.BigIntegerField(null=True, default=1)
|
big_int_filed = models.BigIntegerField(null=True, default=1)
|
||||||
|
@ -81,6 +89,9 @@ class NullableFields(models.Model):
|
||||||
positive_small_integer_field = models.PositiveSmallIntegerField(null=True, default=4)
|
positive_small_integer_field = models.PositiveSmallIntegerField(null=True, default=4)
|
||||||
small_integer_field = models.SmallIntegerField(null=True, default=5)
|
small_integer_field = models.SmallIntegerField(null=True, default=5)
|
||||||
time_field = models.TimeField(null=True, default=timezone.now)
|
time_field = models.TimeField(null=True, default=timezone.now)
|
||||||
|
auto_field = models.ForeignKey(NoFields, on_delete=models.CASCADE, null=True)
|
||||||
|
small_auto_field = models.ForeignKey(SmallAutoFieldModel, on_delete=models.CASCADE, null=True)
|
||||||
|
big_auto_field = models.ForeignKey(BigAutoFieldModel, on_delete=models.CASCADE, null=True)
|
||||||
# Fields not required in BulkInsertMapper
|
# Fields not required in BulkInsertMapper
|
||||||
char_field = models.CharField(null=True, max_length=4, default='char')
|
char_field = models.CharField(null=True, max_length=4, default='char')
|
||||||
email_field = models.EmailField(null=True, default='user@example.com')
|
email_field = models.EmailField(null=True, default='user@example.com')
|
||||||
|
|
|
@ -9,9 +9,9 @@ from django.test import (
|
||||||
)
|
)
|
||||||
|
|
||||||
from .models import (
|
from .models import (
|
||||||
Country, NoFields, NullableFields, Pizzeria, ProxyCountry,
|
BigAutoFieldModel, Country, NoFields, NullableFields, Pizzeria,
|
||||||
ProxyMultiCountry, ProxyMultiProxyCountry, ProxyProxyCountry, Restaurant,
|
ProxyCountry, ProxyMultiCountry, ProxyMultiProxyCountry, ProxyProxyCountry,
|
||||||
State, TwoFields,
|
Restaurant, SmallAutoFieldModel, State, TwoFields,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -234,10 +234,16 @@ class BulkCreateTests(TestCase):
|
||||||
|
|
||||||
@skipUnlessDBFeature('has_bulk_insert')
|
@skipUnlessDBFeature('has_bulk_insert')
|
||||||
def test_bulk_insert_nullable_fields(self):
|
def test_bulk_insert_nullable_fields(self):
|
||||||
|
fk_to_auto_fields = {
|
||||||
|
'auto_field': NoFields.objects.create(),
|
||||||
|
'small_auto_field': SmallAutoFieldModel.objects.create(),
|
||||||
|
'big_auto_field': BigAutoFieldModel.objects.create(),
|
||||||
|
}
|
||||||
# NULL can be mixed with other values in nullable fields
|
# NULL can be mixed with other values in nullable fields
|
||||||
nullable_fields = [field for field in NullableFields._meta.get_fields() if field.name != 'id']
|
nullable_fields = [field for field in NullableFields._meta.get_fields() if field.name != 'id']
|
||||||
NullableFields.objects.bulk_create([
|
NullableFields.objects.bulk_create([
|
||||||
NullableFields(**{field.name: None}) for field in nullable_fields
|
NullableFields(**{**fk_to_auto_fields, field.name: None})
|
||||||
|
for field in nullable_fields
|
||||||
])
|
])
|
||||||
self.assertEqual(NullableFields.objects.count(), len(nullable_fields))
|
self.assertEqual(NullableFields.objects.count(), len(nullable_fields))
|
||||||
for field in nullable_fields:
|
for field in nullable_fields:
|
||||||
|
|
Loading…
Reference in New Issue