Ticket #14149: 14149.diff

File 14149.diff, 3.0 KB (added by ikelly, 5 years ago)
  • django/db/backends/oracle/base.py

     
    351351        return super(DatabaseOperations, self).combine_expression(connector, sub_expressions)
    352352
    353353
     354class _UninitializedOperatorsDescriptor(object):
     355
     356    def __get__(self, instance, owner):
     357        # If connection.operators is looked up before a connection has been
     358        # created, transparently initialize connection.operators to avert an
     359        # AttributeError.
     360        if instance is None:
     361            raise AttributeError("operators not available as class attribute")
     362        # Creating a cursor will initialize the operators.
     363        instance.cursor()
     364        return instance.operators
     365
     366
    354367class DatabaseWrapper(BaseDatabaseWrapper):
    355368    vendor = 'oracle'
    356     operators = {
     369    operators = _UninitializedOperatorsDescriptor()
     370
     371    _standard_operators = {
    357372        'exact': '= %s',
    358373        'iexact': '= UPPER(%s)',
    359374        'contains': "LIKE TRANSLATE(%s USING NCHAR_CS) ESCAPE TRANSLATE('\\' USING NCHAR_CS)",
     
    368383        'iendswith': "LIKE UPPER(TRANSLATE(%s USING NCHAR_CS)) ESCAPE TRANSLATE('\\' USING NCHAR_CS)",
    369384    }
    370385
     386    _likec_operators = _standard_operators.copy()
     387    _likec_operators.update({
     388        'contains': "LIKEC %s ESCAPE '\\'",
     389        'icontains': "LIKEC UPPER(%s) ESCAPE '\\'",
     390        'startswith': "LIKEC %s ESCAPE '\\'",
     391        'endswith': "LIKEC %s ESCAPE '\\'",
     392        'istartswith': "LIKEC UPPER(%s) ESCAPE '\\'",
     393        'iendswith': "LIKEC UPPER(%s) ESCAPE '\\'",
     394    })
     395
    371396    def __init__(self, *args, **kwargs):
    372397        super(DatabaseWrapper, self).__init__(*args, **kwargs)
    373398
     
    412437            cursor.execute("ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS' "
    413438                           "NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF' "
    414439                           "NLS_TERRITORY = 'AMERICA'")
     440
     441            if 'operators' not in self.__dict__:
     442                # Ticket #14149: Check whether our LIKE implementation will
     443                # work for this connection or we need to fall back on LIKEC.
     444                # This check is performed only once per DatabaseWrapper
     445                # instance per thread, since subsequent connections will use
     446                # the same settings.
     447                try:
     448                    cursor.execute("SELECT 1 FROM DUAL WHERE DUMMY %s"
     449                                   % self._standard_operators['contains'],
     450                                   ['X'])
     451                except utils.DatabaseError:
     452                    self.operators = self._likec_operators
     453                else:
     454                    self.operators = self._standard_operators
     455
    415456            try:
    416457                self.oracle_version = int(self.connection.version.split('.')[0])
    417458                # There's no way for the DatabaseOperations class to know the
Back to Top