Django

Code

Ticket #7732: oracle_pool.5.diff

File oracle_pool.5.diff, 7.4 kB (added by mboersma, 10 months ago)

Modified patch against trunk [10832] that passes the Django test suite

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

    old new  
    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) 
     
    284287        self.introspection = DatabaseIntrospection(self) 
    285288        self.validation = BaseDatabaseValidation() 
    286289 
     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') 
     334 
     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 
    303     def _cursor(self): 
    304         cursor = None 
    305         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) 
     353    def _init_oracle_settings(self, connection): 
     354        cursor = FormatStylePlaceholderCursor(connection) 
    309355            # Set oracle date to ansi date format.  This only needs to execute 
    310356            # once when we create a new connection. We also set the Territory 
    311357            # to 'AMERICA' which forces Sunday to evaluate to a '1' in TO_CHAR(). 
     
    313359                           "NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF' " 
    314360                           "NLS_TERRITORY = 'AMERICA'") 
    315361            try: 
    316                 self.oracle_version = int(self.connection.version.split('.')[0]) 
     362            self.oracle_version = int(connection.version.split('.')[0]) 
    317363                # There's no way for the DatabaseOperations class to know the 
    318364                # currently active Oracle version, so we do some setups here. 
    319365                # TODO: Multi-db support will need a better solution (a way to 
     
    324370                    self.ops.regex_lookup = self.ops.regex_lookup_10 
    325371            except ValueError: 
    326372                pass 
     373        return cursor 
     374 
     375    def _cursor(self): 
     376        cursor = None 
     377        if not self._valid_connection(): 
     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) 
    327384            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 
  • django/db/backends/oracle/creation.py

    old new  
    111111        settings.TEST_DATABASE_USER = settings.DATABASE_USER = self.connection.settings_dict["DATABASE_USER"] = TEST_DATABASE_USER 
    112112        settings.DATABASE_PASSWORD = self.connection.settings_dict["DATABASE_PASSWORD"] = TEST_DATABASE_PASSWD 
    113113 
     114        if hasattr(self.connection, '_pool'): 
     115            self.connection.close() 
     116            del self.connection.__class__._pool 
     117 
    114118        return settings.DATABASE_NAME 
    115119 
    116120    def _destroy_test_db(self, test_database_name, verbosity=1): 
     
    118122        Destroy a test database, prompting the user for confirmation if the 
    119123        database already exists. Returns the name of the test database created. 
    120124        """ 
     125 
     126        if hasattr(self.connection, '_pool'): 
     127            self.connection.close() 
     128            del self.connection.__class__._pool 
     129 
    121130        TEST_DATABASE_NAME = self._test_database_name(settings) 
    122131        TEST_DATABASE_USER = self._test_database_user(settings) 
    123132        TEST_DATABASE_PASSWD = self._test_database_passwd(settings)