From ed5eca598e6e0fced2262dafa052d5db1661d83a Mon Sep 17 00:00:00 2001 From: Ian Kelly Date: Tue, 11 Dec 2007 02:22:40 +0000 Subject: [PATCH] Fixed ORA-01461 error when trying to store more than 4000 bytes in a TextField under Oracle git-svn-id: http://code.djangoproject.com/svn/django/trunk@6905 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/db/backends/oracle/base.py | 19 +++++++++++++++++++ tests/regressiontests/model_regress/models.py | 10 ++++++++++ 2 files changed, 29 insertions(+) diff --git a/django/db/backends/oracle/base.py b/django/db/backends/oracle/base.py index 24fda78427..cd830413fc 100644 --- a/django/db/backends/oracle/base.py +++ b/django/db/backends/oracle/base.py @@ -455,6 +455,23 @@ class FormatStylePlaceholderCursor(Database.Cursor): else: return tuple([smart_str(p, self.charset, True) for p in params]) + def _guess_input_sizes(self, params_list): + # Mark any string parameter greater than 4000 characters as an NCLOB. + if isinstance(params_list[0], dict): + sizes = {} + iterators = [params.iteritems() for params in params_list] + else: + sizes = [None] * len(params_list[0]) + iterators = [enumerate(params) for params in params_list] + for iterator in iterators: + for key, value in iterator: + if isinstance(value, basestring) and len(value) > 4000: + sizes[key] = Database.NCLOB + if isinstance(sizes, dict): + self.setinputsizes(**sizes) + else: + self.setinputsizes(*sizes) + def execute(self, query, params=None): if params is None: params = [] @@ -468,6 +485,7 @@ class FormatStylePlaceholderCursor(Database.Cursor): if query.endswith(';') or query.endswith('/'): query = query[:-1] query = smart_str(query, self.charset) % tuple(args) + self._guess_input_sizes([params]) return Database.Cursor.execute(self, query, params) def executemany(self, query, params=None): @@ -484,6 +502,7 @@ class FormatStylePlaceholderCursor(Database.Cursor): query = query[:-1] query = smart_str(query, self.charset) % tuple(args) new_param_list = [self._format_params(i) for i in params] + self._guess_input_sizes(new_param_list) return Database.Cursor.executemany(self, query, new_param_list) def fetchone(self): diff --git a/tests/regressiontests/model_regress/models.py b/tests/regressiontests/model_regress/models.py index 00c3bc96f0..02e73a5aa9 100644 --- a/tests/regressiontests/model_regress/models.py +++ b/tests/regressiontests/model_regress/models.py @@ -11,6 +11,7 @@ class Article(models.Model): pub_date = models.DateTimeField() status = models.IntegerField(blank=True, null=True, choices=CHOICES) misc_data = models.CharField(max_length=100, blank=True) + article_text = models.TextField() class Meta: ordering = ('pub_date','headline') @@ -41,5 +42,14 @@ Empty strings should be returned as Unicode >>> a2 = Article.objects.get(pk=a.id) >>> a2.misc_data u'' + +# TextFields can hold more than 4000 characters (this was broken in Oracle). +>>> a3 = Article(headline="Really, really big", pub_date=datetime.now()) +>>> a3.article_text = "ABCDE" * 1000 +>>> a3.save() +>>> a4 = Article.objects.get(pk=a3.id) +>>> len(a4.article_text) +5000 + """ }