Bläddra i källkod

Fixed #28596 -- Fixed QuerySet.bulk_create() and cascade deletion crash on Oracle when using more than 65535 parameters.

Thanks Tim Graham for the review.
Mariusz Felisiak 7 år sedan
förälder
incheckning
1b823b8f18

+ 1 - 0
django/db/backends/oracle/features.py

@@ -55,3 +55,4 @@ class DatabaseFeatures(BaseDatabaseFeatures):
     """
     supports_callproc_kwargs = True
     supports_over_clause = True
+    max_query_params = 2**16 - 1

+ 6 - 0
django/db/backends/oracle/operations.py

@@ -556,3 +556,9 @@ END;
             rhs_sql, rhs_params = rhs
             return "NUMTODSINTERVAL(%s - %s, 'DAY')" % (lhs_sql, rhs_sql), lhs_params + rhs_params
         return super().subtract_temporals(internal_type, lhs, rhs)
+
+    def bulk_batch_size(self, fields, objs):
+        """Oracle restricts the number of parameters in a query."""
+        if fields:
+            return self.connection.features.max_query_params // len(fields)
+        return len(objs)

+ 14 - 0
tests/backends/oracle/test_operations.py

@@ -9,3 +9,17 @@ class OperationsTests(unittest.TestCase):
     def test_sequence_name_truncation(self):
         seq_name = connection.ops._get_no_autofield_sequence_name('schema_authorwithevenlongee869')
         self.assertEqual(seq_name, 'SCHEMA_AUTHORWITHEVENLOB0B8_SQ')
+
+    def test_bulk_batch_size(self):
+        # Oracle restricts the number of parameters in a query.
+        objects = range(2**16)
+        self.assertEqual(connection.ops.bulk_batch_size([], objects), len(objects))
+        # Each field is a parameter for each object.
+        self.assertEqual(
+            connection.ops.bulk_batch_size(['id'], objects),
+            connection.features.max_query_params,
+        )
+        self.assertEqual(
+            connection.ops.bulk_batch_size(['id', 'other'], objects),
+            connection.features.max_query_params // 2,
+        )