summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnssi Kääriäinen <akaariai@gmail.com>2012-10-27 19:05:41 +0300
committerAnssi Kääriäinen <akaariai@gmail.com>2012-10-27 19:05:46 +0300
commit908efca81723af7a3f4fb5b586e530ed7cd3952b (patch)
tree5f6b470ea41df19168bbaac82c8154438ecd8b9c
parent373df56d36891b9ab1f88519bf9e8f3c0b3bb108 (diff)
parentb55de81b9e4d820a223c066022050a0df0ee1dd0 (diff)
Fixed #19198 -- merged 4 different Oracle fixes
-rw-r--r--django/contrib/gis/tests/utils.py2
-rw-r--r--django/db/backends/oracle/base.py4
-rw-r--r--django/db/models/query.py11
-rw-r--r--tests/regressiontests/backends/tests.py8
-rw-r--r--tests/regressiontests/inspectdb/tests.py11
-rw-r--r--tests/regressiontests/introspection/tests.py15
6 files changed, 42 insertions, 9 deletions
diff --git a/django/contrib/gis/tests/utils.py b/django/contrib/gis/tests/utils.py
index a83ba8a93f..8355b27fd7 100644
--- a/django/contrib/gis/tests/utils.py
+++ b/django/contrib/gis/tests/utils.py
@@ -26,7 +26,7 @@ mysql = _default_db == 'mysql'
spatialite = _default_db == 'spatialite'
HAS_SPATIALREFSYS = True
-if oracle:
+if oracle and 'gis' in settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE']:
from django.contrib.gis.db.backends.oracle.models import SpatialRefSys
elif postgis:
from django.contrib.gis.db.backends.postgis.models import SpatialRefSys
diff --git a/django/db/backends/oracle/base.py b/django/db/backends/oracle/base.py
index 6bf2e815a7..aad52992dd 100644
--- a/django/db/backends/oracle/base.py
+++ b/django/db/backends/oracle/base.py
@@ -256,6 +256,10 @@ WHEN (new.%(col_name)s IS NULL)
if not name.startswith('"') and not name.endswith('"'):
name = '"%s"' % util.truncate_name(name.upper(),
self.max_name_length())
+ # Oracle puts the query text into a (query % args) construct, so % signs
+ # in names need to be escaped. The '%%' will be collapsed back to '%' at
+ # that stage so we aren't really making the name longer here.
+ name = name.replace('%','%%')
return name.upper()
def random_function_sql(self):
diff --git a/django/db/models/query.py b/django/db/models/query.py
index dc1ddf1606..da4c69f362 100644
--- a/django/db/models/query.py
+++ b/django/db/models/query.py
@@ -1418,8 +1418,15 @@ def get_cached_row(row, index_start, using, klass_info, offset=0):
fields = row[index_start : index_start + field_count]
# If all the select_related columns are None, then the related
# object must be non-existent - set the relation to None.
- # Otherwise, construct the related object.
- if fields == (None,) * field_count:
+ # Otherwise, construct the related object. Also, some backends treat ''
+ # and None equivalently for char fields, so we have to be prepared for
+ # '' values.
+ if connections[using].features.interprets_empty_strings_as_nulls:
+ vals = tuple([None if f == '' else f for f in fields])
+ else:
+ vals = fields
+
+ if vals == (None,) * field_count:
obj = None
else:
if field_names:
diff --git a/tests/regressiontests/backends/tests.py b/tests/regressiontests/backends/tests.py
index d284cfaac8..4766dcf44e 100644
--- a/tests/regressiontests/backends/tests.py
+++ b/tests/regressiontests/backends/tests.py
@@ -26,6 +26,14 @@ from . import models
class OracleChecks(unittest.TestCase):
@unittest.skipUnless(connection.vendor == 'oracle',
+ "No need to check Oracle quote_name semantics")
+ def test_quote_name(self):
+ # Check that '%' chars are escaped for query execution.
+ name = '"SOME%NAME"'
+ quoted_name = connection.ops.quote_name(name)
+ self.assertEquals(quoted_name % (), name)
+
+ @unittest.skipUnless(connection.vendor == 'oracle',
"No need to check Oracle cursor semantics")
def test_dbms_session(self):
# If the backend is Oracle, test that we can call a standard
diff --git a/tests/regressiontests/inspectdb/tests.py b/tests/regressiontests/inspectdb/tests.py
index 484e7f4060..028d263337 100644
--- a/tests/regressiontests/inspectdb/tests.py
+++ b/tests/regressiontests/inspectdb/tests.py
@@ -1,6 +1,7 @@
from __future__ import unicode_literals
from django.core.management import call_command
+from django.db import connection
from django.test import TestCase, skipUnlessDBFeature
from django.utils.six import StringIO
@@ -60,14 +61,16 @@ class InspectDBTestCase(TestCase):
self.assertIn("number_45extra = models.CharField", output)
def test_special_column_name_introspection(self):
- """Introspection of column names containing special characters,
- unsuitable for Python identifiers
+ """
+ Introspection of column names containing special characters,
+ unsuitable for Python identifiers
"""
out = StringIO()
call_command('inspectdb', stdout=out)
output = out.getvalue()
+ base_name = 'Field' if connection.vendor != 'oracle' else 'field'
self.assertIn("field = models.IntegerField()", output)
- self.assertIn("field_field = models.IntegerField(db_column='Field_')", output)
- self.assertIn("field_field_0 = models.IntegerField(db_column='Field__')", output)
+ self.assertIn("field_field = models.IntegerField(db_column='%s_')" % base_name, output)
+ self.assertIn("field_field_0 = models.IntegerField(db_column='%s__')" % base_name, output)
self.assertIn("field_field_1 = models.IntegerField(db_column='__field')", output)
self.assertIn("prc_x = models.IntegerField(db_column='prc(%) x')", output)
diff --git a/tests/regressiontests/introspection/tests.py b/tests/regressiontests/introspection/tests.py
index a54e0c670b..4b8a3277e2 100644
--- a/tests/regressiontests/introspection/tests.py
+++ b/tests/regressiontests/introspection/tests.py
@@ -4,10 +4,15 @@ from functools import update_wrapper
from django.db import connection
from django.test import TestCase, skipUnlessDBFeature, skipIfDBFeature
-from django.utils import six
+from django.utils import six, unittest
from .models import Reporter, Article
+if connection.vendor == 'oracle':
+ expectedFailureOnOracle = unittest.expectedFailure
+else:
+ expectedFailureOnOracle = lambda f: f
+
#
# The introspection module is optional, so methods tested here might raise
# NotImplementedError. This is perfectly acceptable behavior for the backend
@@ -89,7 +94,13 @@ class IntrospectionTests(six.with_metaclass(IgnoreNotimplementedError, TestCase)
[datatype(r[1], r) for r in desc],
['IntegerField', 'CharField', 'CharField', 'CharField', 'BigIntegerField']
)
- # Check also length of CharFields
+
+ # The following test fails on Oracle due to #17202 (can't correctly
+ # inspect the length of character columns).
+ @expectedFailureOnOracle
+ def test_get_table_description_col_lengths(self):
+ cursor = connection.cursor()
+ desc = connection.introspection.get_table_description(cursor, Reporter._meta.db_table)
self.assertEqual(
[r[3] for r in desc if datatype(r[1], r) == 'CharField'],
[30, 30, 75]