From 72a86ceb33749d4fd17d3d2910e19b9d9ca1643b Mon Sep 17 00:00:00 2001 From: Mariusz Felisiak Date: Thu, 11 May 2023 18:22:55 +0200 Subject: [PATCH] Fixed #34558 -- Fixed QuerySet.bulk_create() crash with Now() on Oracle. --- django/db/models/functions/datetime.py | 5 +++++ docs/ref/models/database-functions.txt | 10 ++++++++++ docs/releases/5.0.txt | 3 +++ tests/bulk_create/tests.py | 15 ++++++++++++++- 4 files changed, 32 insertions(+), 1 deletion(-) diff --git a/django/db/models/functions/datetime.py b/django/db/models/functions/datetime.py index baed94227af..eb5332ecc0a 100644 --- a/django/db/models/functions/datetime.py +++ b/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 diff --git a/docs/ref/models/database-functions.txt b/docs/ref/models/database-functions.txt index 13b70d76cda..f22a7ae3862 100644 --- a/docs/ref/models/database-functions.txt +++ b/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`` --------- diff --git a/docs/releases/5.0.txt b/docs/releases/5.0.txt index b1e09dab467..f23f39b0144 100644 --- a/docs/releases/5.0.txt +++ b/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 diff --git a/tests/bulk_create/tests.py b/tests/bulk_create/tests.py index a5050c9b0bf..aee0cd99968 100644 --- a/tests/bulk_create/tests.py +++ b/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 = {