diff --git a/django/db/models/functions.py b/django/db/models/functions.py index f2252000cd..f16cf10b15 100644 --- a/django/db/models/functions.py +++ b/django/db/models/functions.py @@ -16,6 +16,18 @@ class Coalesce(Func): raise ValueError('Coalesce must take at least two expressions') super(Coalesce, self).__init__(*expressions, **extra) + def as_oracle(self, compiler, connection): + # we can't mix TextField (NCLOB) and CharField (NVARCHAR), so convert + # all fields to NCLOB when we expect NCLOB + if self.output_field.get_internal_type() == 'TextField': + class ToNCLOB(Func): + function = 'TO_NCLOB' + + expressions = [ + ToNCLOB(expression) for expression in self.get_source_expressions()] + self.set_source_expressions(expressions) + return super(Coalesce, self).as_sql(compiler, connection) + class ConcatPair(Func): """ diff --git a/tests/db_functions/tests.py b/tests/db_functions/tests.py index 089fd11a8a..2ab18b61e0 100644 --- a/tests/db_functions/tests.py +++ b/tests/db_functions/tests.py @@ -56,6 +56,18 @@ class FunctionTests(TestCase): lambda a: a.headline ) + # mixed Text and Char wrapped + article = Article.objects.annotate( + headline=Coalesce(Lower('summary'), Lower('text'), output_field=TextField()), + ) + + self.assertQuerysetEqual( + article.order_by('title'), [ + lorem_ipsum.lower(), + ], + lambda a: a.headline + ) + def test_concat(self): Author.objects.create(name='Jayden') Author.objects.create(name='John Smith', alias='smithj', goes_by='John')