From 6bb6df29431b606937637be5837cc671836b142b Mon Sep 17 00:00:00 2001 From: Shai Berger Date: Fri, 16 May 2014 20:04:26 +0300 Subject: [PATCH] Fix storing of binary fields and unicode textfields for Oracle/Python3 --- django/db/backends/oracle/base.py | 10 ++++++++-- tests/model_regress/tests.py | 11 +++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/django/db/backends/oracle/base.py b/django/db/backends/oracle/base.py index f945b26101..0184fa1cbe 100644 --- a/django/db/backends/oracle/base.py +++ b/django/db/backends/oracle/base.py @@ -748,6 +748,7 @@ class OracleParam(object): param = timezone.make_aware(param, default_timezone) param = Oracle_datetime.from_datetime(param.astimezone(timezone.utc)) + string_size = 0 # Oracle doesn't recognize True and False correctly in Python 3. # The conversion done below works both in 2 and 3. if param is True: @@ -756,15 +757,20 @@ class OracleParam(object): param = "0" if hasattr(param, 'bind_parameter'): self.force_bytes = param.bind_parameter(cursor) - elif isinstance(param, six.memoryview): + elif isinstance(param, Database.Binary): self.force_bytes = param else: + # To transmit to the database, we need Unicode if supported + # To get size right, we must consider bytes. self.force_bytes = convert_unicode(param, cursor.charset, strings_only) + if isinstance(self.force_bytes, six.string_types): + # We could optimize by only converting up to 4000 bytes here + string_size = len(force_bytes(param, cursor.charset, strings_only)) if hasattr(param, 'input_size'): # If parameter has `input_size` attribute, use that. self.input_size = param.input_size - elif isinstance(param, six.string_types) and len(param) > 4000: + elif string_size > 4000: # Mark any string param greater than 4000 characters as a CLOB. self.input_size = Database.CLOB else: diff --git a/tests/model_regress/tests.py b/tests/model_regress/tests.py index 952ba45aab..057798c785 100644 --- a/tests/model_regress/tests.py +++ b/tests/model_regress/tests.py @@ -66,6 +66,17 @@ class ModelTests(TestCase): a = Article.objects.get(pk=a.pk) self.assertEqual(len(a.article_text), 5000) + def test_long_unicode_textfield(self): + # TextFields can hold more than 4000 bytes also when they are + # less than 4000 characters + a = Article.objects.create( + headline="Really, really big", + pub_date=datetime.datetime.now(), + article_text='\u05d0\u05d1\u05d2' * 1000 + ) + a = Article.objects.get(pk=a.pk) + self.assertEqual(len(a.article_text), 3000) + def test_date_lookup(self): # Regression test for #659 Party.objects.create(when=datetime.datetime(1999, 12, 31))