Code

Ticket #17291: ora_version.diff

File ora_version.diff, 6.1 KB (added by akaariai, 2 years ago)
Line 
1diff --git a/django/db/backends/__init__.py b/django/db/backends/__init__.py
2index dd24878..c89dcd9 100644
3--- a/django/db/backends/__init__.py
4+++ b/django/db/backends/__init__.py
5@@ -340,6 +340,9 @@ class BaseDatabaseFeatures(object):
6     # Do time/datetime fields have microsecond precision?
7     supports_microsecond_precision = True
8 
9+    # Is there support for __regex lookups?
10+    supports_regex = True
11+
12     # Does the __regex lookup support backreferencing and grouping?
13     supports_regex_backreferencing = True
14 
15diff --git a/django/db/backends/oracle/base.py b/django/db/backends/oracle/base.py
16index c197422..6cfd608 100644
17--- a/django/db/backends/oracle/base.py
18+++ b/django/db/backends/oracle/base.py
19@@ -83,6 +83,14 @@ class DatabaseFeatures(BaseDatabaseFeatures):
20     has_bulk_insert = True
21     supports_tablespaces = True
22 
23+    def _supports_regex(self):
24+        if self.connection.oracle_version > 9:
25+            return True
26+        else:
27+            return False
28+    supports_regex = property(_supports_regex)
29+    supports_regex_backreferencing = supports_regex
30+
31 class DatabaseOperations(BaseDatabaseOperations):
32     compiler_module = "django.db.backends.oracle.compiler"
33 
34@@ -249,21 +257,15 @@ WHEN (new.%(col_name)s IS NULL)
35     def random_function_sql(self):
36         return "DBMS_RANDOM.RANDOM"
37 
38-    def regex_lookup_9(self, lookup_type):
39-        raise NotImplementedError("Regexes are not supported in Oracle before version 10g.")
40-
41-    def regex_lookup_10(self, lookup_type):
42-        if lookup_type == 'regex':
43-            match_option = "'c'"
44-        else:
45-            match_option = "'i'"
46-        return 'REGEXP_LIKE(%%s, %%s, %s)' % match_option
47-
48     def regex_lookup(self, lookup_type):
49-        # If regex_lookup is called before it's been initialized, then create
50-        # a cursor to initialize it and recur.
51-        self.connection.cursor()
52-        return self.connection.ops.regex_lookup(lookup_type)
53+        if self.connection.oracle_version > 9:
54+            if lookup_type == 'regex':
55+                match_option = "'c'"
56+            else:
57+                match_option = "'i'"
58+            return 'REGEXP_LIKE(%%s, %%s, %s)' % match_option
59+        else:
60+            raise NotImplementedError("Regexes are not supported in Oracle before version 10g.")
61 
62     def return_insert_id(self):
63         return "RETURNING %s INTO %%s", (InsertIdVar(),)
64@@ -434,7 +436,7 @@ class DatabaseWrapper(BaseDatabaseWrapper):
65     def __init__(self, *args, **kwargs):
66         super(DatabaseWrapper, self).__init__(*args, **kwargs)
67 
68-        self.oracle_version = None
69+        self._oracle_version = None
70         self.features = DatabaseFeatures(self)
71         use_returning_into = self.settings_dict["OPTIONS"].get('use_returning_into', True)
72         self.features.can_return_id_from_insert = use_returning_into
73@@ -444,6 +446,15 @@ class DatabaseWrapper(BaseDatabaseWrapper):
74         self.introspection = DatabaseIntrospection(self)
75         self.validation = BaseDatabaseValidation(self)
76 
77+    def _get_ora_version(self):
78+        if self._oracle_version is None:
79+            # To check the server version, we need a connection
80+            if self.connection is None:
81+                self._cursor().close()
82+            self._oracle_version = int(self.connection.version.split('.')[0])
83+        return self._oracle_version
84+    oracle_version = property(_get_ora_version)
85+
86     def check_constraints(self, table_names=None):
87         """
88         To check constraints, we set constraints to immediate. Then, when, we're done we must ensure they
89@@ -517,19 +528,6 @@ class DatabaseWrapper(BaseDatabaseWrapper):
90                     self.operators = self._likec_operators
91                 else:
92                     self.operators = self._standard_operators
93-
94-            try:
95-                self.oracle_version = int(self.connection.version.split('.')[0])
96-                # There's no way for the DatabaseOperations class to know the
97-                # currently active Oracle version, so we do some setups here.
98-                # TODO: Multi-db support will need a better solution (a way to
99-                # communicate the current version).
100-                if self.oracle_version <= 9:
101-                    self.ops.regex_lookup = self.ops.regex_lookup_9
102-                else:
103-                    self.ops.regex_lookup = self.ops.regex_lookup_10
104-            except ValueError:
105-                pass
106             try:
107                 self.connection.stmtcachesize = 20
108             except:
109@@ -650,7 +648,7 @@ class FormatStylePlaceholderCursor(object):
110         self.cursor.arraysize = 100
111 
112     def _format_params(self, params):
113-        return tuple([OracleParam(p, self, True) for p in params])
114+        return tuple(OracleParam(p, self, True) for p in params)
115 
116     def _guess_input_sizes(self, params_list):
117         sizes = [None] * len(params_list[0])
118@@ -722,12 +720,12 @@ class FormatStylePlaceholderCursor(object):
119     def fetchmany(self, size=None):
120         if size is None:
121             size = self.arraysize
122-        return tuple([_rowfactory(r, self.cursor)
123-                      for r in self.cursor.fetchmany(size)])
124+        return tuple(_rowfactory(r, self.cursor)
125+                     for r in self.cursor.fetchmany(size))
126 
127     def fetchall(self):
128-        return tuple([_rowfactory(r, self.cursor)
129-                      for r in self.cursor.fetchall()])
130+        return tuple(_rowfactory(r, self.cursor)
131+                     for r in self.cursor.fetchall())
132 
133     def var(self, *args):
134         return VariableWrapper(self.cursor.var(*args))
135diff --git a/tests/modeltests/lookup/tests.py b/tests/modeltests/lookup/tests.py
136index 9c2b0c6..068b5f7 100644
137--- a/tests/modeltests/lookup/tests.py
138+++ b/tests/modeltests/lookup/tests.py
139@@ -479,6 +479,7 @@ class LookupTests(TestCase):
140             self.assertEqual(str(ex), "Join on field 'headline' not permitted. "
141                              "Did you misspell 'starts' for the lookup type?")
142 
143+    @skipUnlessDBFeature('supports_regex')
144     def test_regex(self):
145         # Create some articles with a bit more interesting headlines for testing field lookups:
146         for a in Article.objects.all():