ソースを参照

Fixed #34558 -- Fixed QuerySet.bulk_create() crash with Now() on Oracle.

Mariusz Felisiak 1 年間 前
コミット
72a86ceb33

+ 5 - 0
django/db/models/functions/datetime.py

@@ -236,6 +236,11 @@ class Now(Func):
             **extra_context,
         )
 
+    def as_oracle(self, compiler, connection, **extra_context):
+        return self.as_sql(
+            compiler, connection, template="LOCALTIMESTAMP", **extra_context
+        )
+
 
 class TruncBase(TimezoneMixin, Transform):
     kind = None

+ 10 - 0
docs/ref/models/database-functions.txt

@@ -562,11 +562,21 @@ Usage example:
     ``Now()`` uses ``STATEMENT_TIMESTAMP`` instead. If you need the transaction
     timestamp, use :class:`django.contrib.postgres.functions.TransactionNow`.
 
+.. admonition:: Oracle
+
+    On Oracle, the SQL ``LOCALTIMESTAMP`` is used to avoid issues with casting
+    ``CURRENT_TIMESTAMP`` to ``DateTimeField``.
+
 .. versionchanged:: 4.2
 
     Support for microsecond precision on MySQL and millisecond precision on
     SQLite were added.
 
+.. versionchanged:: 5.0
+
+    In older versions, the SQL ``CURRENT_TIMESTAMP`` was used on Oracle instead
+    of ``LOCALTIMESTAMP``.
+
 ``Trunc``
 ---------
 

+ 3 - 0
docs/releases/5.0.txt

@@ -382,6 +382,9 @@ Miscellaneous
 * ``ImageField.update_dimension_fields()`` is no longer called on the
   ``post_init`` signal if ``width_field`` and ``height_field`` are not set.
 
+* :class:`~django.db.models.functions.Now` database function now uses
+  ``LOCALTIMESTAMP`` instead of ``CURRENT_TIMESTAMP`` on Oracle.
+
 .. _deprecated-features-5.0:
 
 Features deprecated in 5.0

+ 14 - 1
tests/bulk_create/tests.py

@@ -10,7 +10,7 @@ from django.db import (
     connection,
 )
 from django.db.models import FileField, Value
-from django.db.models.functions import Lower
+from django.db.models.functions import Lower, Now
 from django.test import (
     TestCase,
     override_settings,
@@ -300,6 +300,19 @@ class BulkCreateTests(TestCase):
         bbb = Restaurant.objects.filter(name="betty's beetroot bar")
         self.assertEqual(bbb.count(), 1)
 
+    @skipUnlessDBFeature("has_bulk_insert")
+    def test_bulk_insert_now(self):
+        NullableFields.objects.bulk_create(
+            [
+                NullableFields(datetime_field=Now()),
+                NullableFields(datetime_field=Now()),
+            ]
+        )
+        self.assertEqual(
+            NullableFields.objects.filter(datetime_field__isnull=False).count(),
+            2,
+        )
+
     @skipUnlessDBFeature("has_bulk_insert")
     def test_bulk_insert_nullable_fields(self):
         fk_to_auto_fields = {