Fixed #31751 -- Fixed database introspection with cx_Oracle 8.

This commit is contained in:
Mariusz Felisiak 2020-06-30 09:50:15 +02:00 committed by GitHub
parent a93425a37f
commit 615e32162f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 48 additions and 18 deletions

View File

@ -1,14 +1,19 @@
import cx_Oracle import cx_Oracle
from django.db.backends.oracle.introspection import DatabaseIntrospection from django.db.backends.oracle.introspection import DatabaseIntrospection
from django.utils.functional import cached_property
class OracleIntrospection(DatabaseIntrospection): class OracleIntrospection(DatabaseIntrospection):
# Associating any OBJECTVAR instances with GeometryField. This won't work # Associating any OBJECTVAR instances with GeometryField. This won't work
# right on Oracle objects that aren't MDSYS.SDO_GEOMETRY, but it is the # right on Oracle objects that aren't MDSYS.SDO_GEOMETRY, but it is the
# only object type supported within Django anyways. # only object type supported within Django anyways.
data_types_reverse = DatabaseIntrospection.data_types_reverse.copy() @cached_property
data_types_reverse[cx_Oracle.OBJECT] = 'GeometryField' def data_types_reverse(self):
return {
**super().data_types_reverse,
cx_Oracle.OBJECT: 'GeometryField',
}
def get_geometry_type(self, table_name, description): def get_geometry_type(self, table_name, description):
with self.connection.cursor() as cursor: with self.connection.cursor() as cursor:

View File

@ -323,6 +323,10 @@ class DatabaseWrapper(BaseDatabaseWrapper):
else: else:
return True return True
@cached_property
def cx_oracle_version(self):
return tuple(int(x) for x in Database.version.split('.'))
@cached_property @cached_property
def oracle_version(self): def oracle_version(self):
with self.temporary_connection(): with self.temporary_connection():

View File

@ -6,29 +6,48 @@ from django.db import models
from django.db.backends.base.introspection import ( from django.db.backends.base.introspection import (
BaseDatabaseIntrospection, FieldInfo as BaseFieldInfo, TableInfo, BaseDatabaseIntrospection, FieldInfo as BaseFieldInfo, TableInfo,
) )
from django.utils.functional import cached_property
FieldInfo = namedtuple('FieldInfo', BaseFieldInfo._fields + ('is_autofield', 'is_json')) FieldInfo = namedtuple('FieldInfo', BaseFieldInfo._fields + ('is_autofield', 'is_json'))
class DatabaseIntrospection(BaseDatabaseIntrospection): class DatabaseIntrospection(BaseDatabaseIntrospection):
# Maps type objects to Django Field types.
data_types_reverse = {
cx_Oracle.BLOB: 'BinaryField',
cx_Oracle.CLOB: 'TextField',
cx_Oracle.DATETIME: 'DateField',
cx_Oracle.FIXED_CHAR: 'CharField',
cx_Oracle.FIXED_NCHAR: 'CharField',
cx_Oracle.INTERVAL: 'DurationField',
cx_Oracle.NATIVE_FLOAT: 'FloatField',
cx_Oracle.NCHAR: 'CharField',
cx_Oracle.NCLOB: 'TextField',
cx_Oracle.NUMBER: 'DecimalField',
cx_Oracle.STRING: 'CharField',
cx_Oracle.TIMESTAMP: 'DateTimeField',
}
cache_bust_counter = 1 cache_bust_counter = 1
# Maps type objects to Django Field types.
@cached_property
def data_types_reverse(self):
if self.connection.cx_oracle_version < (8,):
return {
cx_Oracle.BLOB: 'BinaryField',
cx_Oracle.CLOB: 'TextField',
cx_Oracle.DATETIME: 'DateField',
cx_Oracle.FIXED_CHAR: 'CharField',
cx_Oracle.FIXED_NCHAR: 'CharField',
cx_Oracle.INTERVAL: 'DurationField',
cx_Oracle.NATIVE_FLOAT: 'FloatField',
cx_Oracle.NCHAR: 'CharField',
cx_Oracle.NCLOB: 'TextField',
cx_Oracle.NUMBER: 'DecimalField',
cx_Oracle.STRING: 'CharField',
cx_Oracle.TIMESTAMP: 'DateTimeField',
}
else:
return {
cx_Oracle.DB_TYPE_DATE: 'DateField',
cx_Oracle.DB_TYPE_BINARY_DOUBLE: 'FloatField',
cx_Oracle.DB_TYPE_BLOB: 'BinaryField',
cx_Oracle.DB_TYPE_CHAR: 'CharField',
cx_Oracle.DB_TYPE_CLOB: 'TextField',
cx_Oracle.DB_TYPE_INTERVAL_DS: 'DurationField',
cx_Oracle.DB_TYPE_NCHAR: 'CharField',
cx_Oracle.DB_TYPE_NCLOB: 'TextField',
cx_Oracle.DB_TYPE_NVARCHAR: 'CharField',
cx_Oracle.DB_TYPE_NUMBER: 'DecimalField',
cx_Oracle.DB_TYPE_TIMESTAMP: 'DateTimeField',
cx_Oracle.DB_TYPE_VARCHAR: 'CharField',
}
def get_field_type(self, data_type, description): def get_field_type(self, data_type, description):
if data_type == cx_Oracle.NUMBER: if data_type == cx_Oracle.NUMBER:
precision, scale = description[4:6] precision, scale = description[4:6]

View File

@ -22,3 +22,5 @@ Bugfixes
* Fixed a regression in Django 3.0.2 that caused a migration crash on * Fixed a regression in Django 3.0.2 that caused a migration crash on
PostgreSQL when adding a foreign key to a model with a namespaced PostgreSQL when adding a foreign key to a model with a namespaced
``db_table`` (:ticket:`31735`). ``db_table`` (:ticket:`31735`).
* Added compatibility for ``cx_Oracle`` 8 (:ticket:`31751`).