Edgewall Software

Changes between Version 18 and Version 19 of TracDev/DatabaseApi


Ignore:
Timestamp:
Jan 6, 2011, 1:52:47 PM (13 years ago)
Author:
Christian Boos
Comment:

#PooledConnections: what changed with context managers…

Legend:

Unmodified
Added
Removed
Modified
  • TracDev/DatabaseApi

    v18 v19  
    133133=== Pooled Connections ===
    134134
    135 The {{{Environment}}} method {{{get_db_cnx()}}} returns a connection from the pool of connections.  This connection needs to be returned, and Trac is written so that the return will happen automatically by the garbage collector if the code is written to follow a simple rule.  When the garbage collector determines the pooled database connection is no longer being used, its `__del__` method will return the pooled connection to the pool for reuse.  If you have set a lexical variable in the function's body to the pooled connection, this typically occurs when the function is returning.  In the example above of {{{myFunc}}} it occurs at the return statement since {{{db}}} is a variable local to {{{myFunc}}}
     135Trac used to operate the following way:
     136 The {{{Environment}}} method {{{get_db_cnx()}}} returns a connection from the pool of connections.  This connection needs to be returned, and Trac is written so that the return will happen automatically by the garbage collector if the code is written to follow a simple rule.  When the garbage collector determines the pooled database connection is no longer being used, its `__del__` method will return the pooled connection to the pool for reuse.  If you have set a lexical variable in the function's body to the pooled connection, this typically occurs when the function is returning.  In the example above of {{{myFunc}}} it occurs at the return statement since {{{db}}} is a variable local to {{{myFunc}}}
     137
     138With the context managers introduced in Trac 0.13, we're able to return this Connection to the pool in a much more robust and direct way:
     139 When the control flow exits a context manager (either `Environment.db_query` or `Environment.db_transaction`), and if that context manager is the "outermost" one in case multiple contexts where nested, then the `Connection` is immediately returned to the pool, regardless of the behavior of the garbage collector.
     140
     141This means that even if a variable still contains a reference to the `Connection`, it won't be possible to use it outside of the context:
     142{{{#!pycon
     143>>> from trac.env import open_environment
     144>>> env = open_environment('...-trac')
     145>>> with env.db_query as db:
     146...     print db("SELECT count(*) FROM wiki")
     147...
     148[(563,)]
     149>>> db
     150<trac.db.util.ConnectionWrapper object at 0x026146E8>
     151>>> print db("SELECT count(*) FROM wiki")
     152Traceback (most recent call last):
     153  File "<stdin>", line 1, in <module>
     154  File "trac\db\util.py", line 123, in __call__
     155    cursor = self.cnx.cursor()
     156  File "trac\db\util.py", line 108, in __getattr__
     157    return getattr(self.cnx, name)
     158AttributeError: 'NoneType' object has no attribute 'cursor'
     159}}}
     160
     161... which is a good thing!
     162
    136163
    137164== Rules for DB API Usage ==