~launchpad-pqm/launchpad/devel

« back to all changes in this revision

Viewing changes to lib/canonical/database/sqlbase.py

  • Committer: Jelmer Vernooij
  • Date: 2011-09-21 14:28:02 UTC
  • mfrom: (14006 devel)
  • mto: This revision was merged to the branch mainline in revision 14010.
  • Revision ID: jelmer@canonical.com-20110921142802-7ggkc204igsy532w
MergeĀ lp:launchpad

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
 
4
4
__metaclass__ = type
5
5
__all__ = [
6
 
    'alreadyInstalledMsg',
7
 
    'begin',
8
6
    'block_implicit_flushes',
9
7
    'clear_current_connection_cache',
10
8
    'commit',
11
 
    'ConflictingTransactionManagerError',
12
9
    'connect',
13
10
    'convert_storm_clause_to_string',
14
11
    'cursor',
15
 
    'expire_from_cache',
16
12
    'flush_database_caches',
17
13
    'flush_database_updates',
18
14
    'get_transaction_timestamp',
25
21
    'quoteIdentifier',
26
22
    'quote_identifier',
27
23
    'reset_store',
28
 
    'rollback',
29
24
    'session_store',
30
25
    'SQLBase',
31
26
    'sqlvalues',
35
30
 
36
31
 
37
32
from datetime import datetime
38
 
from textwrap import dedent
39
 
import warnings
40
33
 
41
34
from lazr.restful.interfaces import IRepresentationCache
42
35
import psycopg2
64
57
from zope.interface import implements
65
58
from zope.security.proxy import removeSecurityProxy
66
59
 
67
 
from canonical.config import (
68
 
    config,
69
 
    dbconfig,
70
 
    )
 
60
from canonical.config import dbconfig
71
61
from canonical.database.interfaces import ISQLBase
72
62
from lp.services.propertycache import clear_property_cache
73
63
 
272
262
        clear_property_cache(self)
273
263
 
274
264
 
275
 
alreadyInstalledMsg = ("A ZopelessTransactionManager with these settings is "
276
 
"already installed.  This is probably caused by calling initZopeless twice.")
277
 
 
278
 
 
279
 
class ConflictingTransactionManagerError(Exception):
280
 
    pass
281
 
 
282
 
 
283
265
class ZopelessTransactionManager(object):
284
266
    """Compatibility shim for initZopeless()"""
285
267
 
286
268
    _installed = None
287
 
    _CONFIG_OVERLAY_NAME = 'initZopeless config overlay'
288
269
 
289
270
    def __init__(self):
290
271
        raise AssertionError("ZopelessTransactionManager should not be "
302
283
            ISOLATION_LEVEL_READ_COMMITTED: 'read_committed',
303
284
            ISOLATION_LEVEL_SERIALIZABLE: 'serializable'}[isolation]
304
285
 
305
 
        # Construct a config fragment:
306
 
        overlay = dedent("""\
307
 
            [database]
308
 
            isolation_level: %(isolation_level)s
309
 
 
310
 
            [launchpad]
311
 
            dbuser: %(dbuser)s
312
 
            """ % dict(
313
 
                isolation_level=isolation_level,
314
 
                dbuser=dbuser))
315
 
 
316
 
        if cls._installed is not None:
317
 
            if cls._config_overlay != overlay:
318
 
                raise ConflictingTransactionManagerError(
319
 
                        "A ZopelessTransactionManager with different "
320
 
                        "settings is already installed")
321
 
            # There's an identical ZopelessTransactionManager already
322
 
            # installed, so return that one, but also emit a warning.
323
 
            warnings.warn(alreadyInstalledMsg, stacklevel=3)
324
 
        else:
325
 
            config.push(cls._CONFIG_OVERLAY_NAME, overlay)
326
 
            cls._config_overlay = overlay
327
 
            cls._dbuser = dbuser
328
 
            cls._isolation = isolation
329
 
            cls._reset_stores()
330
 
            cls._installed = cls
331
 
        return cls._installed
 
286
        dbconfig.override(dbuser=dbuser, isolation_level=isolation_level)
 
287
 
 
288
        cls._dbuser = dbuser
 
289
        cls._isolation = isolation
 
290
        cls._reset_stores()
 
291
        cls._installed = cls
332
292
 
333
293
    @staticmethod
334
294
    def _reset_stores():
366
326
        """
367
327
        assert cls._installed is not None, (
368
328
            "ZopelessTransactionManager not installed")
369
 
        config.pop(cls._CONFIG_OVERLAY_NAME)
 
329
        dbconfig.override(dbuser=None, isolation_level=None)
370
330
        cls._reset_stores()
371
331
        cls._installed = None
372
332
 
373
 
    @classmethod
374
 
    def set_isolation_level(cls, isolation):
375
 
        """Set the transaction isolation level.
376
 
 
377
 
        Level can be one of ISOLATION_LEVEL_AUTOCOMMIT,
378
 
        ISOLATION_LEVEL_READ_COMMITTED or
379
 
        ISOLATION_LEVEL_SERIALIZABLE. As changing the isolation level
380
 
        must be done before any other queries are issued in the
381
 
        current transaction, this method automatically issues a
382
 
        rollback to ensure this is the case.
383
 
        """
384
 
        assert cls._installed is not None, (
385
 
            "ZopelessTransactionManager not installed")
386
 
        cls.uninstall()
387
 
        cls.initZopeless(cls._dbuser, isolation)
388
 
 
389
 
    @staticmethod
390
 
    def conn():
391
 
        store = _get_sqlobject_store()
392
 
        # Use of the raw connection will not be coherent with Storm's
393
 
        # cache.
394
 
        connection = store._connection
395
 
        connection._ensure_connected()
396
 
        return connection._raw_connection
397
 
 
398
 
    @staticmethod
399
 
    def begin():
400
 
        """Begin a transaction."""
401
 
        transaction.begin()
402
 
 
403
 
    @staticmethod
404
 
    def commit():
405
 
        """Commit the current transaction."""
406
 
        transaction.commit()
407
 
 
408
 
    @staticmethod
409
 
    def abort():
410
 
        """Abort the current transaction."""
411
 
        transaction.abort()
412
 
 
413
 
    @staticmethod
414
 
    def registerSynch(synch):
415
 
        """Register an ISynchronizer."""
416
 
        transaction.manager.registerSynch(synch)
417
 
 
418
 
    @staticmethod
419
 
    def unregisterSynch(synch):
420
 
        """Unregister an ISynchronizer."""
421
 
        transaction.manager.unregisterSynch(synch)
422
 
 
423
333
 
424
334
def clear_current_connection_cache():
425
335
    """Clear SQLObject's object cache. SQLObject compatibility - DEPRECATED.
427
337
    _get_sqlobject_store().invalidate()
428
338
 
429
339
 
430
 
def expire_from_cache(obj):
431
 
    """Expires a single object from the SQLObject cache.
432
 
    SQLObject compatibility - DEPRECATED."""
433
 
    _get_sqlobject_store().invalidate(obj)
434
 
 
435
 
 
436
340
def get_transaction_timestamp():
437
341
    """Get the timestamp for the current transaction on the MAIN DEFAULT
438
342
    store. DEPRECATED - if needed it should become a method on the store.
730
634
    return mergeFunctionMetadata(func, reset_store_decorator)
731
635
 
732
636
 
733
 
# Some helpers intended for use with initZopeless.  These allow you to avoid
734
 
# passing the transaction manager all through your code.
735
 
 
736
 
def begin():
737
 
    """Begins a transaction."""
738
 
    transaction.begin()
739
 
 
740
 
 
741
 
def rollback():
742
 
    transaction.abort()
743
 
 
744
 
 
 
637
# DEPRECATED -- use transaction.commit() directly.
745
638
def commit():
746
639
    transaction.commit()
747
640