]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- merge tip, 0.6.4 + 0.6.5
authorMike Bayer <mike_mp@zzzcomputing.com>
Tue, 14 Sep 2010 21:37:27 +0000 (17:37 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Tue, 14 Sep 2010 21:37:27 +0000 (17:37 -0400)
14 files changed:
1  2 
doc/build/core/event.rst
doc/build/core/interfaces.rst
doc/build/core/pooling.rst
lib/sqlalchemy/engine/base.py
lib/sqlalchemy/orm/attributes.py
lib/sqlalchemy/orm/dynamic.py
lib/sqlalchemy/orm/interfaces.py
lib/sqlalchemy/orm/mapper.py
lib/sqlalchemy/orm/state.py
lib/sqlalchemy/orm/strategies.py
lib/sqlalchemy/pool.py
lib/sqlalchemy/schema.py
lib/sqlalchemy/util.py
test/orm/test_unitofwork.py

index ec36ee5990d3bbcfdd30f622b18011c052ca13ad,0000000000000000000000000000000000000000..ec36ee5990d3bbcfdd30f622b18011c052ca13ad
mode 100644,000000..100644
--- /dev/null
index 0000000000000000000000000000000000000000,71dd8c12207177e4d3aa6760dd291fcd0554d234..c6254491a05b043977f242685d33953899a4cd81
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,30 +1,30 @@@
 -.. _interfaces_core_toplevel:
++. _interfaces_core_toplevel:
+ Core Event Interfaces
+ ======================
+ .. module:: sqlalchemy.interfaces
+ This section describes the various categories of events which can be intercepted
+ in SQLAlchemy core, including execution and connection pool events.
+ For ORM event documentation, see :ref:`interfaces_orm_toplevel`.
+ A new version of this API with a significantly more flexible and consistent
+ interface will be available in version 0.7.
+ Execution, Connection and Cursor Events
+ ---------------------------------------
+ .. autoclass:: ConnectionProxy
+    :members:
+    :undoc-members:
+ Connection Pool Events
+ ----------------------
+ .. autoclass:: PoolListener
+    :members:
+    :undoc-members:
index 0000000000000000000000000000000000000000,edb6a334e3b412f1a1b5367be04e277661c23c93..692a33f00914ce598c419bc2fddef84555094a66
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,226 +1,226 @@@
 -   :show-inheritance:
+ .. _pooling_toplevel:
+ Connection Pooling
+ ==================
+ .. module:: sqlalchemy.pool
+ The establishment of a
+ database connection is typically a somewhat expensive operation, and
+ applications need a way to get at database connections repeatedly
+ with minimal overhead.  Particularly for
+ server-side web applications, a connection pool is the standard way to
+ maintain a "pool" of active database connections in memory which are
+ reused across requests.
+ SQLAlchemy includes several connection pool implementations 
+ which integrate with the :class:`.Engine`.  They can also be used
+ directly for applications that want to add pooling to an otherwise
+ plain DBAPI approach.
+ Connection Pool Configuration
+ -----------------------------
+ The :class:`~sqlalchemy.engine.Engine` returned by the
+ :func:`~sqlalchemy.create_engine` function in most cases has a :class:`QueuePool`
+ integrated, pre-configured with reasonable pooling defaults.  If
+ you're reading this section to simply enable pooling- congratulations!
+ You're already done.
+ The most common :class:`QueuePool` tuning parameters can be passed
+ directly to :func:`~sqlalchemy.create_engine` as keyword arguments:
+ ``pool_size``, ``max_overflow``, ``pool_recycle`` and
+ ``pool_timeout``.  For example::
+   engine = create_engine('postgresql://me@localhost/mydb',
+                          pool_size=20, max_overflow=0)
+ In the case of SQLite, a :class:`SingletonThreadPool` is provided instead,
+ to provide compatibility with SQLite's restricted threading model, as well
+ as to provide a reasonable default behavior to SQLite "memory" databases,
+ which maintain their entire dataset within the scope of a single connection.
+ All SQLAlchemy pool implementations have in common
+ that none of them "pre create" connections - all implementations wait
+ until first use before creating a connection.   At that point, if
+ no additional concurrent checkout requests for more connections 
+ are made, no additional connections are created.   This is why it's perfectly
+ fine for :func:`.create_engine` to default to using a :class:`.QueuePool`
+ of size five without regard to whether or not the application really needs five connections
+ queued up - the pool would only grow to that size if the application
+ actually used five connections concurrently, in which case the usage of a 
+ small pool is an entirely appropriate default behavior.
+ Switching Pool Implementations
+ ------------------------------
+ The usual way to use a different kind of pool with :func:`.create_engine`
+ is to use the ``poolclass`` argument.   This argument accepts a class
+ imported from the ``sqlalchemy.pool`` module, and handles the details
+ of building the pool for you.   Common options include specifying
+ :class:`.QueuePool` with SQLite::
+     from sqlalchemy.pool import QueuePool
+     engine = create_engine('sqlite:///file.db', poolclass=QueuePool)
+ Disabling pooling using :class:`.NullPool`::
+     from sqlalchemy.pool import NullPool
+     engine = create_engine(
+               'postgresql+psycopg2://scott:tiger@localhost/test', 
+               poolclass=NullPool)
+ Using a Custom Connection Function
+ ----------------------------------
+ All :class:`.Pool` classes accept an argument ``creator`` which is 
+ a callable that creates a new connection.  :func:`.create_engine`
+ accepts this function to pass onto the pool via an argument of
+ the same name::
+     import sqlalchemy.pool as pool
+     import psycopg2
+     def getconn():
+         c = psycopg2.connect(username='ed', host='127.0.0.1', dbname='test')
+         # do things with 'c' to set up
+         return c
+     engine = create_engine('postgresql+psycopg2://', creator=getconn)
+ For most "initialize on connection" routines, it's more convenient
+ to use a :class:`.PoolListener`, so that the usual URL argument to
+ :func:`.create_engine` is still usable.  ``creator`` is there as
+ a total last resort for when a DBAPI has some form of ``connect``
+ that is not at all supported by SQLAlchemy.
+ Constructing a Pool
+ ------------------------
+ To use a :class:`.Pool` by itself, the ``creator`` function is
+ the only argument that's required and is passed first, followed
+ by any additional options::
+     import sqlalchemy.pool as pool
+     import psycopg2
+     def getconn():
+         c = psycopg2.connect(username='ed', host='127.0.0.1', dbname='test')
+         return c
+     mypool = pool.QueuePool(getconn, max_overflow=10, pool_size=5)
+ DBAPI connections can then be procured from the pool using the :meth:`.Pool.connect`
+ function.  The return value of this method is a DBAPI connection that's contained
+ within a transparent proxy::
+     # get a connection
+     conn = mypool.connect()
+     # use it
+     cursor = conn.cursor()
+     cursor.execute("select foo")
+ The purpose of the transparent proxy is to intercept the ``close()`` call,
+ such that instead of the DBAPI connection being closed, its returned to the 
+ pool::
+     # "close" the connection.  Returns
+     # it to the pool.
+     conn.close()
+ The proxy also returns its contained DBAPI connection to the pool 
+ when it is garbage collected,
+ though it's not deterministic in Python that this occurs immediately (though
+ it is typical with cPython).
+ A particular pre-created :class:`.Pool` can be shared with one or more
+ engines by passing it to the ``pool`` argument of :func:`.create_engine`::
+     e = create_engine('postgresql://', pool=mypool)
+ Pool Event Listeners
+ --------------------
+ Connection pools support an event interface that allows hooks to execute
+ upon first connect, upon each new connection, and upon checkout and 
+ checkin of connections.   See :class:`.PoolListener` for details.
+ Builtin Pool Implementations
+ ----------------------------
+ .. autoclass:: sqlalchemy.pool.Pool
+    .. automethod:: __init__
+    .. automethod:: connect
+    .. automethod:: dispose
+    .. automethod:: recreate
+ .. autoclass:: sqlalchemy.pool.QueuePool
+    :show-inheritance:
+    .. automethod:: __init__
+ .. autoclass:: SingletonThreadPool
+    :show-inheritance:
+    .. automethod:: __init__
+ .. autoclass:: AssertionPool
+    :show-inheritance:
+ .. autoclass:: NullPool
++  :show-inheritance:
+ .. autoclass:: StaticPool
+    :show-inheritance:
+ Pooling Plain DB-API Connections
+ --------------------------------
+ Any :pep:`249` DB-API module can be "proxied" through the connection
+ pool transparently.  Usage of the DB-API is exactly as before, except
+ the ``connect()`` method will consult the pool.  Below we illustrate
+ this with ``psycopg2``::
+     import sqlalchemy.pool as pool
+     import psycopg2 as psycopg
+     psycopg = pool.manage(psycopg)
+     # then connect normally
+     connection = psycopg.connect(database='test', username='scott',
+                                  password='tiger')
+ This produces a :class:`_DBProxy` object which supports the same
+ ``connect()`` function as the original DB-API module.  Upon
+ connection, a connection proxy object is returned, which delegates its
+ calls to a real DB-API connection object.  This connection object is
+ stored persistently within a connection pool (an instance of
+ :class:`Pool`) that corresponds to the exact connection arguments sent
+ to the ``connect()`` function.
+ The connection proxy supports all of the methods on the original
+ connection object, most of which are proxied via ``__getattr__()``.
+ The ``close()`` method will return the connection to the pool, and the
+ ``cursor()`` method will return a proxied cursor object.  Both the
+ connection proxy and the cursor proxy will also return the underlying
+ connection to the pool after they have both been garbage collected,
+ which is detected via weakref callbacks  (``__del__`` is not used).
+ Additionally, when connections are returned to the pool, a
+ ``rollback()`` is issued on the connection unconditionally.  This is
+ to release any locks still held by the connection that may have
+ resulted from normal activity.
+ By default, the ``connect()`` method will return the same connection
+ that is already checked out in the current thread.  This allows a
+ particular connection to be used in a given thread without needing to
+ pass it around between functions.  To disable this behavior, specify
+ ``use_threadlocal=False`` to the ``manage()`` function.
+ .. autofunction:: sqlalchemy.pool.manage
+ .. autofunction:: sqlalchemy.pool.clear_managers
Simple merge
index ddfdb8655a549d72f036a408f52d2126960eca62,b56de5f05dc93a07a0d8a106fd6450b697e27a43..7cc8d2161b1f838f81187c619b31c445c72cdf78
@@@ -512,10 -455,10 +519,10 @@@ class ScalarAttributeImpl(AttributeImpl
              self, state, dict_.get(self.key, NO_VALUE))
  
      def set(self, state, dict_, value, initiator, passive=PASSIVE_OFF):
-         if initiator is self:
+         if initiator and initiator.parent_token is self.parent_token:
              return
  
 -        if self.active_history:
 +        if self.dispatch.active_history:
              old = self.get(state, dict_)
          else:
              old = dict_.get(self.key, NO_VALUE)
@@@ -591,10 -534,10 +598,10 @@@ class MutableScalarAttributeImpl(Scalar
          state.mutable_dict.pop(self.key)
  
      def set(self, state, dict_, value, initiator, passive=PASSIVE_OFF):
-         if initiator is self:
+         if initiator and initiator.parent_token is self.parent_token:
              return
  
 -        if self.extensions:
 +        if self.dispatch.on_set:
              old = self.get(state, dict_)
              value = self.fire_replace_event(state, dict_, 
                                              value, old, initiator)
@@@ -653,14 -596,14 +660,14 @@@ class ScalarObjectAttributeImpl(ScalarA
          setter operation.
  
          """
-         if initiator is self:
+         if initiator and initiator.parent_token is self.parent_token:
              return
  
 -        if self.active_history:
 +        if self.dispatch.active_history:
-             old = self.get(state, dict_)
+             old = self.get(state, dict_, passive=PASSIVE_ONLY_PERSISTENT)
          else:
              old = self.get(state, dict_, passive=PASSIVE_NO_FETCH)
-              
+         
          value = self.fire_replace_event(state, dict_, value, old, initiator)
          dict_[self.key] = value
  
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 5d14c178984c10344ac39d56f49c2201cb5d868c,c70a41069f90f4228747f1449d281bd402e3cf21..9ed5c806707047a3ad5fe2155f48668d863340b2
@@@ -209,20 -131,15 +209,28 @@@ class Pool(log.Identified)
              for l in listeners:
                  self.add_listener(l)
  
 +    dispatch = event.dispatcher(PoolEvents)
 +        
 +    @util.deprecated(2.7, "Pool.add_listener is deprecated.  Use event.listen()")
 +    def add_listener(self, listener):
 +        """Add a :class:`.PoolListener`-like object to this pool.
 +        
 +        ``listener`` may be an object that implements some or all of
 +        PoolListener, or a dictionary of callables containing implementations
 +        of some or all of the named methods in PoolListener.
 +
 +        """
 +        interfaces.PoolListener._adapt_listener(self, listener)
 +    
      def unique_connection(self):
+         """Produce a DBAPI connection that is not referenced by any
+         thread-local context.
+         
+         This method is different from :meth:`.Pool.connect` only if the
+         ``use_threadlocal`` flag has been set to ``True``.
+         
+         """
+         
          return _ConnectionFairy(self).checkout()
  
      def create_connection(self):
Simple merge
Simple merge
Simple merge