Opened 12 years ago
Closed 12 years ago
#22670 closed Bug (duplicate)
bulk_create with empty model fields fails on oracle
| Reported by: | Owned by: | nobody | |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | 1.6 |
| Severity: | Normal | Keywords: | |
| Cc: | Triage Stage: | Unreviewed | |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
I did the minimal example for reproducing this bug. Model looks very simple:
class ProbaModel(models.Model): num = models.IntegerField(null=True, blank=True)
When i tried to run the following test code:
class ProbaTestCase(TestCase): def test_bulk_create(self): ProbaModel.objects.bulk_create( [ ProbaModel(num=1), ProbaModel() ] )
I got an
Traceback (most recent call last):
File "/home/sns/devel/proba/proba/app1/tests.py", line 10, in test_bulk_create
ProbaModel()
File "/home/sns/devel/proba/local/lib/python2.7/site-packages/django/db/models/manager.py", line 160, in bulk_create
return self.get_queryset().bulk_create(*args, **kwargs)
File "/home/sns/devel/proba/local/lib/python2.7/site-packages/django/db/models/query.py", line 359, in bulk_create
self._batched_insert(objs_without_pk, fields, batch_size)
File "/home/sns/devel/proba/local/lib/python2.7/site-packages/django/db/models/query.py", line 838, in _batched_insert
using=self.db)
File "/home/sns/devel/proba/local/lib/python2.7/site-packages/django/db/models/manager.py", line 232, in _insert
return insert_query(self.model, objs, fields, **kwargs)
File "/home/sns/devel/proba/local/lib/python2.7/site-packages/django/db/models/query.py", line 1514, in insert_query
return query.get_compiler(using=using).execute_sql(return_id)
File "/home/sns/devel/proba/local/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 903, in execute_sql
cursor.execute(sql, params)
File "/home/sns/devel/proba/local/lib/python2.7/site-packages/django/db/backends/util.py", line 53, in execute
return self.cursor.execute(sql, params)
File "/home/sns/devel/proba/local/lib/python2.7/site-packages/django/db/utils.py", line 99, in __exit__
six.reraise(dj_exc_type, dj_exc_value, traceback)
File "/home/sns/devel/proba/local/lib/python2.7/site-packages/django/db/backends/util.py", line 53, in execute
return self.cursor.execute(sql, params)
File "/home/sns/devel/proba/local/lib/python2.7/site-packages/django/db/backends/oracle/base.py", line 816, in execute
return self.cursor.execute(query, self._param_generator(params))
DatabaseError: ORA-01790: expression must have same datatype as corresponding expression
This bug confirmed on Oracle 11.2.0.4 and 12. Complete project located on my GitHub: https://github.com/nsadovskiy/bulk_create_fail
Solution that works fo me is patch on django/db/backends/oracle/base.py:
*** base.py 2014-05-20 18:37:07.000000000 +0700
--- base.py 2014-05-20 18:41:45.000000000 +0700
***************
*** 467,509 ****
return '%s_TR' % util.truncate_name(table, name_length).upper()
def bulk_insert_sql(self, fields, num_values):
! MAPPER = {
! 'CharField': 'to_nchar(%s)',
! 'CommaSeparatedIntegerField': 'to_nchar(%s)',
! 'EmailField': 'to_nchar(%s)',
! 'FileField': 'to_nchar(%s)',
! 'FilePathField': 'to_nchar(%s)',
! 'ImageField': 'to_nchar(%s)',
! 'SlugField': 'to_nchar(%s)',
! 'URLField': 'to_nchar(%s)',
!
! 'IPAddressField': 'to_char(%s)',
! 'GenericIPAddressField': 'to_char(%s)',
!
! 'AutoField': 'to_number(%s)',
! 'BigIntegerField': 'to_number(%s)',
! 'BooleanField': 'to_number(%s)',
! 'DecimalField': 'to_number(%s)',
! 'FloatField': 'to_number(%s)',
! 'IntegerField': 'to_number(%s)',
! 'NullBooleanField': 'to_number(%s)',
! 'PositiveIntegerField': 'to_number(%s)',
! 'PositiveSmallIntegerField': 'to_number(%s)',
! 'SmallIntegerField': 'to_number(%s)',
! 'ForeignKey': 'to_number(%s)',
! 'ManyToManyField': 'to_number(%s)',
! 'OneToOneField': 'to_number(%s)',
!
! 'DateField': 'to_date(%s)',
!
! 'DateTimeField': 'to_timestamp(%s)',
! 'TimeField': 'to_timestamp(%s)',
!
! 'BinaryField': 'to_blob(%s)',
!
! 'TextField': 'to_nclob(%s)'
! }
! items_sql = "SELECT %s FROM DUAL" % ", ".join([MAPPER.get(field.get_internal_type(), '%s') for field in fields])
return " UNION ALL ".join([items_sql] * num_values)
--- 467,473 ----
return '%s_TR' % util.truncate_name(table, name_length).upper()
def bulk_insert_sql(self, fields, num_values):
! items_sql = "SELECT %s FROM DUAL" % ", ".join(["%s"] * len(fields))
return " UNION ALL ".join([items_sql] * num_values)
Note:
See TracTickets
for help on using tickets.
Double post of #22669.