Contact: fumanchu@aminus.org

Log in as guest/geniusql to create tickets

Changeset 175

Show
Ignore:
Timestamp:
09/24/07 11:13:01
Author:
fumanchu
Message:

Better error handling for pypgsql DDL, plus a new connection test.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/geniusql/providers/pypgsql.py

    r174 r175  
    2828            return libpq.PQconnectdb(connstr) 
    2929        except libpq.DatabaseError, x: 
    30             if x.args[0].startswith('could not connect'): 
    31                 raise errors.OutOfConnectionsError() 
     30            if (x.args[0].startswith('could not connect') or 
     31                x.args[0].startswith('timeout expired')): 
     32                    raise errors.OutOfConnectionsError() 
    3233            raise 
    3334     
    3435    def _del_conn(self, conn): 
    35         conn.finish() 
     36        try: 
     37            conn.finish() 
     38        except libpq.InterfaceError, exc: 
     39            if exc.args == ('PgConnection object is closed',): 
     40                pass 
     41            else: 
     42                raise 
     43     
     44    def _simulate_unreachable(self, callback): 
     45        oldconnect = self.Connect 
     46        oldretry = self._factory.retry 
     47        try: 
     48            connstr = "connect_timeout=1 " 
     49            for atom in self.Connect.split(" "): 
     50                k, v = atom.split("=", 1) 
     51                if k == 'host': 
     52                    v = 'www.example.com' 
     53                connstr += "%s=%s " % (k, v) 
     54            self.Connect = connstr 
     55             
     56            self._factory.retry = [0] 
     57             
     58            callback() 
     59        finally: 
     60            self.Connect = oldconnect 
     61            self._factory.retry = oldretry 
    3662 
    3763 
     
    6086                raise 
    6187        return dbinfo 
     88     
     89    def execute_ddl(self, sql, conn=None): 
     90        """Return a native response for the given DDL statement. 
     91         
     92        In general, DDL statements should lock out other statements 
     93        (especially those isolated in other transactions). Use this 
     94        method to perform a locked DDL statement. 
     95        """ 
     96        try: 
     97            postgres.PgDatabase.execute_ddl(self, sql, conn) 
     98        except libpq.OperationalError, x: 
     99            if x.args: 
     100                msg = x.args[0] 
     101                if "already exists" in msg or "does not exist" in msg: 
     102                    raise errors.MappingError(*x.args) 
     103            raise 
    62104     
    63105    def fetch(self, sql, conn=None): 
  • trunk/geniusql/test/zoo_fixture.py

    r174 r175  
    13121312 
    13131313 
     1314class ConnectionTests(unittest.TestCase): 
     1315     
     1316    def test_ConnClose(self): 
     1317        Animal = schema['Animal'] 
     1318         
     1319        # Start a sticky transaction so we use the same conn. 
     1320        connmgr = db.connections 
     1321        connmgr.start() 
     1322        # Test a normal query. 
     1323        self.assertEqual(len(Animal.select_all(lambda x: x.Legs == 4)), 4) 
     1324         
     1325        # Take the connection down on our side. 
     1326        txkey = connmgr.id() 
     1327        conn = connmgr.transactions[txkey] 
     1328        connmgr._del_conn(conn) 
     1329         
     1330        # Try another query. 
     1331        try: 
     1332            fourlegs = len(Animal.select_all(lambda x: x.Legs == 4)) 
     1333            self.assertEqual(fourlegs, 4) 
     1334        except: 
     1335            del connmgr.transactions[txkey] 
     1336        else: 
     1337            raise AssertionError("Connection did not fail.") 
     1338     
     1339    def test_ConnUnreachable(self): 
     1340        Animal = schema['Animal'] 
     1341         
     1342        # Simulate an unreachable host during the grabbing of a connection. 
     1343        # This is easy to simulate by just munging the hostname for the conn. 
     1344        def callback(): 
     1345            fourlegs = len(Animal.select_all(lambda x: x.Legs == 4)) 
     1346            self.assertEqual(fourlegs, 4) 
     1347         
     1348        db.connections.shutdown() 
     1349        db.connections._simulate_unreachable(callback) 
     1350 
     1351 
    13141352##class ZooSchema(dejavu.Schema): 
    13151353##     
     
    14011439                tools.TestRunner.run(loader(ConcurrencyTests)) 
    14021440             
     1441            if 'connection' not in skiptests: 
     1442                tools.TestRunner.run(loader(ConnectionTests)) 
     1443             
    14031444            # Each thread opens a new SQLite :memory: database, 
    14041445            # so the concept of "isolation" is pretty meaningless.