Ticket #7732: oracle_pool.4.diff

File oracle_pool.4.diff, 7.3 KB (added by dbergstr@…, 6 years ago)

Patch against revision 10578 (1.1beta). Use settings.DATABASE_OPTIONS, general code cleanup.

  • django/db/backends/oracle/base.py

     
    273273        'iendswith': "LIKEC UPPER(%s) ESCAPE '\\'",
    274274    }
    275275    oracle_version = None
     276    _pool_defaults = {'SESSION_POOL_MIN': 1,
     277                      'SESSION_POOL_MAX': 3,
     278                      'SESSION_POOL_INCREMENT': 1,}
    276279
    277280    def __init__(self, *args, **kwargs):
    278281        super(DatabaseWrapper, self).__init__(*args, **kwargs)
     
    283286        self.creation = DatabaseCreation(self)
    284287        self.introspection = DatabaseIntrospection(self)
    285288        self.validation = BaseDatabaseValidation()
     289       
     290        # Fetch connection pool settings
     291        opts = self.settings_dict['DATABASE_OPTIONS']
     292        if not isinstance(opts, dict):
     293            # Insurance against foolish users...
     294            opts = {}
     295        if opts.get('SESSION_POOL', False):
     296            self._use_pool = True
     297            self._pool_settings = dict(self._pool_defaults)
     298            self._pool_settings.update(opts)
     299        else:
     300            self._use_pool = False
     301   
     302    def _get_pool (self):
     303        if not hasattr (self.__class__, '_pool'):
     304            settings_dict = self.settings_dict
     305            Database.OPT_Threading = 1
     306            if len(settings_dict['DATABASE_HOST'].strip()) == 0:
     307                settings_dict['DATABASE_HOST'] = 'localhost'
     308            if len(settings_dict['DATABASE_PORT'].strip()) != 0:
     309                dsn = Database.makedsn(settings_dict['DATABASE_HOST'],
     310                                       int(settings_dict['DATABASE_PORT']),
     311                                       settings_dict['DATABASE_NAME'])
     312                p = Database.SessionPool(settings_dict['DATABASE_USER'],
     313                                         settings_dict['DATABASE_PASSWORD'],
     314                                         dsn,
     315                                         self._pool_settings['SESSION_POOL_MIN'],
     316                                         self._pool_settings['SESSION_POOL_MAX'],
     317                                         self._pool_settings['SESSION_POOL_INCREMENT'],
     318                                         threaded = True)
     319            else:
     320                p = Database.SessionPool(settings_dict['DATABASE_USER'],
     321                                         settings_dict['DATABASE_PASSWORD'],
     322                                         settings_dict['DATABASE_NAME'],
     323                                         self._pool_settings['SESSION_POOL_MIN'],
     324                                         self._pool_settings['SESSION_POOL_MAX'],
     325                                         self._pool_settings['SESSION_POOL_INCREMENT'],
     326                                         threaded = True)
     327            setattr(self.__class__, '_pool', p)
     328            # TODO I think the init stuff only needs to happen once per pool,
     329            # but it may be once per connection...
     330            conn = p.acquire()
     331            self._init_oracle_settings(conn)
     332            p.release(conn)
     333        return getattr(self.__class__, '_pool')
    286334
     335    pool = property (_get_pool)
     336
    287337    def _valid_connection(self):
    288338        return self.connection is not None
    289339
     
    300350        return "%s/%s@%s" % (settings_dict['DATABASE_USER'],
    301351                             settings_dict['DATABASE_PASSWORD'], dsn)
    302352
     353    def _init_oracle_settings(self, connection):
     354        cursor = FormatStylePlaceholderCursor(connection)
     355        # Set oracle date to ansi date format.  This only needs to execute
     356        # once when we create a new connection. We also set the Territory
     357        # to 'AMERICA' which forces Sunday to evaluate to a '1' in TO_CHAR().
     358        cursor.execute("ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS' "
     359                       "NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF' "
     360                       "NLS_TERRITORY = 'AMERICA'")
     361        try:
     362            self.oracle_version = int(connection.version.split('.')[0])
     363            # There's no way for the DatabaseOperations class to know the
     364            # currently active Oracle version, so we do some setups here.
     365            # TODO: Multi-db support will need a better solution (a way to
     366            # communicate the current version).
     367            if self.oracle_version <= 9:
     368                self.ops.regex_lookup = self.ops.regex_lookup_9
     369            else:
     370                self.ops.regex_lookup = self.ops.regex_lookup_10
     371        except ValueError:
     372            pass
     373        return cursor
     374
    303375    def _cursor(self):
    304376        cursor = None
    305377        if not self._valid_connection():
    306             conn_string = self._connect_string()
    307             self.connection = Database.connect(conn_string, **self.settings_dict['DATABASE_OPTIONS'])
    308             cursor = FormatStylePlaceholderCursor(self.connection)
    309             # Set oracle date to ansi date format.  This only needs to execute
    310             # once when we create a new connection. We also set the Territory
    311             # to 'AMERICA' which forces Sunday to evaluate to a '1' in TO_CHAR().
    312             cursor.execute("ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS' "
    313                            "NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF' "
    314                            "NLS_TERRITORY = 'AMERICA'")
     378            if self._use_pool and self.pool is not None:
     379                self.connection = self.pool.acquire()
     380            else:
     381                    self.connection = Database.connect(self._connect_string()
     382                        **self.settings_dict['DATABASE_OPTIONS'])
     383                    cursor = self._init_oracle_settings(self.connection)
    315384            try:
    316                 self.oracle_version = int(self.connection.version.split('.')[0])
    317                 # There's no way for the DatabaseOperations class to know the
    318                 # currently active Oracle version, so we do some setups here.
    319                 # TODO: Multi-db support will need a better solution (a way to
    320                 # communicate the current version).
    321                 if self.oracle_version <= 9:
    322                     self.ops.regex_lookup = self.ops.regex_lookup_9
    323                 else:
    324                     self.ops.regex_lookup = self.ops.regex_lookup_10
    325             except ValueError:
    326                 pass
    327             try:
    328385                self.connection.stmtcachesize = 20
    329386            except:
    330387                # Django docs specify cx_Oracle version 4.3.1 or higher, but
    331388                # stmtcachesize is available only in 4.3.2 and up.
    332389                pass
     390            # TODO Does pulling a connection from the pool count as "creation"?
    333391            connection_created.send(sender=self.__class__)
    334392        if not cursor:
    335393            cursor = FormatStylePlaceholderCursor(self.connection)
    336394        return cursor
    337395
     396    def close(self):
     397       from django.conf import settings
     398       if self._use_pool:
     399           if self.connection is not None:
     400               self.pool.release(self.connection)
     401               self.connection = None
     402       else:
     403           if self.connection is not None:
     404               self.connection.close()
     405               self.connection = None
     406
    338407    # Oracle doesn't support savepoint commits.  Ignore them.
    339408    def _savepoint_commit(self, sid):
    340409        pass
Back to Top