summaryrefslogtreecommitdiff
path: root/django/db
diff options
context:
space:
mode:
Diffstat (limited to 'django/db')
-rw-r--r--django/db/backends/oracle/operations.py18
-rw-r--r--django/db/backends/oracle/utils.py24
2 files changed, 37 insertions, 5 deletions
diff --git a/django/db/backends/oracle/operations.py b/django/db/backends/oracle/operations.py
index 7cc33af537..bf9834d1f8 100644
--- a/django/db/backends/oracle/operations.py
+++ b/django/db/backends/oracle/operations.py
@@ -9,7 +9,7 @@ from django.utils import timezone
from django.utils.encoding import force_bytes, force_text
from .base import Database
-from .utils import InsertIdVar, Oracle_datetime
+from .utils import BulkInsertMapper, InsertIdVar, Oracle_datetime
class DatabaseOperations(BaseDatabaseOperations):
@@ -523,10 +523,18 @@ WHEN (new.%(col_name)s IS NULL)
return truncate_name(trigger_name, name_length).upper()
def bulk_insert_sql(self, fields, placeholder_rows):
- return " UNION ALL ".join(
- "SELECT %s FROM DUAL" % ", ".join(row)
- for row in placeholder_rows
- )
+ query = []
+ for row in placeholder_rows:
+ select = []
+ for i, placeholder in enumerate(row):
+ # A model without any fields has fields=[None].
+ if not fields[i]:
+ select.append(placeholder)
+ else:
+ internal_type = getattr(fields[i], 'target_field', fields[i]).get_internal_type()
+ select.append(BulkInsertMapper.types.get(internal_type, '%s') % placeholder)
+ query.append('SELECT %s FROM DUAL' % ', '.join(select))
+ return ' UNION ALL '.join(query)
def subtract_temporals(self, internal_type, lhs, rhs):
if internal_type == 'DateField':
diff --git a/django/db/backends/oracle/utils.py b/django/db/backends/oracle/utils.py
index f958655f94..6c81d5cd7b 100644
--- a/django/db/backends/oracle/utils.py
+++ b/django/db/backends/oracle/utils.py
@@ -29,3 +29,27 @@ class Oracle_datetime(datetime.datetime):
dt.year, dt.month, dt.day,
dt.hour, dt.minute, dt.second, dt.microsecond,
)
+
+
+class BulkInsertMapper:
+ BLOB = 'TO_BLOB(%s)'
+ DATE = 'TO_DATE(%s)'
+ INTERVAL = 'CAST(%s as INTERVAL DAY(9) TO SECOND(6))'
+ NUMBER = 'TO_NUMBER(%s)'
+ TIMESTAMP = 'TO_TIMESTAMP(%s)'
+
+ types = {
+ 'BigIntegerField': NUMBER,
+ 'BinaryField': BLOB,
+ 'DateField': DATE,
+ 'DateTimeField': TIMESTAMP,
+ 'DecimalField': NUMBER,
+ 'DurationField': INTERVAL,
+ 'FloatField': NUMBER,
+ 'IntegerField': NUMBER,
+ 'NullBooleanField': NUMBER,
+ 'PositiveIntegerField': NUMBER,
+ 'PositiveSmallIntegerField': NUMBER,
+ 'SmallIntegerField': NUMBER,
+ 'TimeField': TIMESTAMP,
+ }