|
|
|
@@ -491,14 +491,23 @@ class Dialect(object):
|
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
|
|
|
|
|
def do_executemany(self, cursor, statement, parameters, context=None):
|
|
|
|
|
"""Provide an implementation of *cursor.executemany(statement,
|
|
|
|
|
parameters)*."""
|
|
|
|
|
"""Provide an implementation of ``cursor.executemany(statement,
|
|
|
|
|
parameters)``."""
|
|
|
|
|
|
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
|
|
|
|
|
def do_execute(self, cursor, statement, parameters, context=None):
|
|
|
|
|
"""Provide an implementation of *cursor.execute(statement,
|
|
|
|
|
parameters)*."""
|
|
|
|
|
"""Provide an implementation of ``cursor.execute(statement,
|
|
|
|
|
parameters)``."""
|
|
|
|
|
|
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
|
|
|
|
|
def do_execute_no_params(self, cursor, statement, parameters, context=None):
|
|
|
|
|
"""Provide an implementation of ``cursor.execute(statement)``.
|
|
|
|
|
|
|
|
|
|
The parameter collection should not be sent.
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
|
|
|
|
@@ -777,12 +786,12 @@ class Connectable(object):
|
|
|
|
|
|
|
|
|
|
def connect(self, **kwargs):
|
|
|
|
|
"""Return a :class:`.Connection` object.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Depending on context, this may be ``self`` if this object
|
|
|
|
|
is already an instance of :class:`.Connection`, or a newly
|
|
|
|
|
procured :class:`.Connection` if this object is an instance
|
|
|
|
|
of :class:`.Engine`.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
def contextual_connect(self):
|
|
|
|
@@ -793,7 +802,7 @@ class Connectable(object):
|
|
|
|
|
is already an instance of :class:`.Connection`, or a newly
|
|
|
|
|
procured :class:`.Connection` if this object is an instance
|
|
|
|
|
of :class:`.Engine`.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
raise NotImplementedError()
|
|
|
|
@@ -904,6 +913,12 @@ class Connection(Connectable):
|
|
|
|
|
c.__dict__ = self.__dict__.copy()
|
|
|
|
|
return c
|
|
|
|
|
|
|
|
|
|
def __enter__(self):
|
|
|
|
|
return self
|
|
|
|
|
|
|
|
|
|
def __exit__(self, type, value, traceback):
|
|
|
|
|
self.close()
|
|
|
|
|
|
|
|
|
|
def execution_options(self, **opt):
|
|
|
|
|
""" Set non-SQL options for the connection which take effect
|
|
|
|
|
during execution.
|
|
|
|
@@ -940,7 +955,7 @@ class Connection(Connectable):
|
|
|
|
|
:param compiled_cache: Available on: Connection.
|
|
|
|
|
A dictionary where :class:`.Compiled` objects
|
|
|
|
|
will be cached when the :class:`.Connection` compiles a clause
|
|
|
|
|
expression into a :class:`.Compiled` object.
|
|
|
|
|
expression into a :class:`.Compiled` object.
|
|
|
|
|
It is the user's responsibility to
|
|
|
|
|
manage the size of this dictionary, which will have keys
|
|
|
|
|
corresponding to the dialect, clause element, the column
|
|
|
|
@@ -953,7 +968,7 @@ class Connection(Connectable):
|
|
|
|
|
some operations, including flush operations. The caching
|
|
|
|
|
used by the ORM internally supersedes a cache dictionary
|
|
|
|
|
specified here.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
:param isolation_level: Available on: Connection.
|
|
|
|
|
Set the transaction isolation level for
|
|
|
|
|
the lifespan of this connection. Valid values include
|
|
|
|
@@ -962,7 +977,7 @@ class Connection(Connectable):
|
|
|
|
|
database specific, including those for :ref:`sqlite_toplevel`,
|
|
|
|
|
:ref:`postgresql_toplevel` - see those dialect's documentation
|
|
|
|
|
for further info.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Note that this option necessarily affects the underying
|
|
|
|
|
DBAPI connection for the lifespan of the originating
|
|
|
|
|
:class:`.Connection`, and is not per-execution. This
|
|
|
|
@@ -970,6 +985,18 @@ class Connection(Connectable):
|
|
|
|
|
is returned to the connection pool, i.e.
|
|
|
|
|
the :meth:`.Connection.close` method is called.
|
|
|
|
|
|
|
|
|
|
:param no_parameters: When ``True``, if the final parameter
|
|
|
|
|
list or dictionary is totally empty, will invoke the
|
|
|
|
|
statement on the cursor as ``cursor.execute(statement)``,
|
|
|
|
|
not passing the parameter collection at all.
|
|
|
|
|
Some DBAPIs such as psycopg2 and mysql-python consider
|
|
|
|
|
percent signs as significant only when parameters are
|
|
|
|
|
present; this option allows code to generate SQL
|
|
|
|
|
containing percent signs (and possibly other characters)
|
|
|
|
|
that is neutral regarding whether it's executed by the DBAPI
|
|
|
|
|
or piped into a script that's later invoked by
|
|
|
|
|
command line tools. New in 0.7.6.
|
|
|
|
|
|
|
|
|
|
:param stream_results: Available on: Connection, statement.
|
|
|
|
|
Indicate to the dialect that results should be
|
|
|
|
|
"streamed" and not pre-buffered, if possible. This is a limitation
|
|
|
|
@@ -1113,17 +1140,35 @@ class Connection(Connectable):
|
|
|
|
|
|
|
|
|
|
def begin(self):
|
|
|
|
|
"""Begin a transaction and return a transaction handle.
|
|
|
|
|
|
|
|
|
|
The returned object is an instance of :class:`.Transaction`.
|
|
|
|
|
|
|
|
|
|
Repeated calls to ``begin`` on the same Connection will create
|
|
|
|
|
a lightweight, emulated nested transaction. Only the
|
|
|
|
|
outermost transaction may ``commit``. Calls to ``commit`` on
|
|
|
|
|
inner transactions are ignored. Any transaction in the
|
|
|
|
|
hierarchy may ``rollback``, however.
|
|
|
|
|
The returned object is an instance of :class:`.Transaction`.
|
|
|
|
|
This object represents the "scope" of the transaction,
|
|
|
|
|
which completes when either the :meth:`.Transaction.rollback`
|
|
|
|
|
or :meth:`.Transaction.commit` method is called.
|
|
|
|
|
|
|
|
|
|
Nested calls to :meth:`.begin` on the same :class:`.Connection`
|
|
|
|
|
will return new :class:`.Transaction` objects that represent
|
|
|
|
|
an emulated transaction within the scope of the enclosing
|
|
|
|
|
transaction, that is::
|
|
|
|
|
|
|
|
|
|
See also :meth:`.Connection.begin_nested`,
|
|
|
|
|
:meth:`.Connection.begin_twophase`.
|
|
|
|
|
trans = conn.begin() # outermost transaction
|
|
|
|
|
trans2 = conn.begin() # "nested"
|
|
|
|
|
trans2.commit() # does nothing
|
|
|
|
|
trans.commit() # actually commits
|
|
|
|
|
|
|
|
|
|
Calls to :meth:`.Transaction.commit` only have an effect
|
|
|
|
|
when invoked via the outermost :class:`.Transaction` object, though the
|
|
|
|
|
:meth:`.Transaction.rollback` method of any of the
|
|
|
|
|
:class:`.Transaction` objects will roll back the
|
|
|
|
|
transaction.
|
|
|
|
|
|
|
|
|
|
See also:
|
|
|
|
|
|
|
|
|
|
:meth:`.Connection.begin_nested` - use a SAVEPOINT
|
|
|
|
|
|
|
|
|
|
:meth:`.Connection.begin_twophase` - use a two phase /XID transaction
|
|
|
|
|
|
|
|
|
|
:meth:`.Engine.begin` - context manager available from :class:`.Engine`.
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
@@ -1157,7 +1202,7 @@ class Connection(Connectable):
|
|
|
|
|
def begin_twophase(self, xid=None):
|
|
|
|
|
"""Begin a two-phase or XA transaction and return a transaction
|
|
|
|
|
handle.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The returned object is an instance of :class:`.TwoPhaseTransaction`,
|
|
|
|
|
which in addition to the methods provided by
|
|
|
|
|
:class:`.Transaction`, also provides a :meth:`~.TwoPhaseTransaction.prepare`
|
|
|
|
@@ -1302,7 +1347,7 @@ class Connection(Connectable):
|
|
|
|
|
|
|
|
|
|
def close(self):
|
|
|
|
|
"""Close this :class:`.Connection`.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
This results in a release of the underlying database
|
|
|
|
|
resources, that is, the DBAPI connection referenced
|
|
|
|
|
internally. The DBAPI connection is typically restored
|
|
|
|
@@ -1313,7 +1358,7 @@ class Connection(Connectable):
|
|
|
|
|
the DBAPI connection's ``rollback()`` method, regardless
|
|
|
|
|
of any :class:`.Transaction` object that may be
|
|
|
|
|
outstanding with regards to this :class:`.Connection`.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
After :meth:`~.Connection.close` is called, the
|
|
|
|
|
:class:`.Connection` is permanently in a closed state,
|
|
|
|
|
and will allow no further operations.
|
|
|
|
@@ -1354,24 +1399,24 @@ class Connection(Connectable):
|
|
|
|
|
* a :class:`.DDLElement` object
|
|
|
|
|
* a :class:`.DefaultGenerator` object
|
|
|
|
|
* a :class:`.Compiled` object
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
:param \*multiparams/\**params: represent bound parameter
|
|
|
|
|
values to be used in the execution. Typically,
|
|
|
|
|
the format is either a collection of one or more
|
|
|
|
|
dictionaries passed to \*multiparams::
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
conn.execute(
|
|
|
|
|
table.insert(),
|
|
|
|
|
{"id":1, "value":"v1"},
|
|
|
|
|
{"id":2, "value":"v2"}
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
...or individual key/values interpreted by \**params::
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
conn.execute(
|
|
|
|
|
table.insert(), id=1, value="v1"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
In the case that a plain SQL string is passed, and the underlying
|
|
|
|
|
DBAPI accepts positional bind parameters, a collection of tuples
|
|
|
|
|
or individual values in \*multiparams may be passed::
|
|
|
|
@@ -1380,21 +1425,21 @@ class Connection(Connectable):
|
|
|
|
|
"INSERT INTO table (id, value) VALUES (?, ?)",
|
|
|
|
|
(1, "v1"), (2, "v2")
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
conn.execute(
|
|
|
|
|
"INSERT INTO table (id, value) VALUES (?, ?)",
|
|
|
|
|
1, "v1"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Note above, the usage of a question mark "?" or other
|
|
|
|
|
symbol is contingent upon the "paramstyle" accepted by the DBAPI
|
|
|
|
|
in use, which may be any of "qmark", "named", "pyformat", "format",
|
|
|
|
|
"numeric". See `pep-249 <http://www.python.org/dev/peps/pep-0249/>`_
|
|
|
|
|
for details on paramstyle.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
To execute a textual SQL statement which uses bound parameters in a
|
|
|
|
|
DBAPI-agnostic way, use the :func:`~.expression.text` construct.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
for c in type(object).__mro__:
|
|
|
|
|
if c in Connection.executors:
|
|
|
|
@@ -1623,7 +1668,8 @@ class Connection(Connectable):
|
|
|
|
|
|
|
|
|
|
if self._echo:
|
|
|
|
|
self.engine.logger.info(statement)
|
|
|
|
|
self.engine.logger.info("%r", sql_util._repr_params(parameters, batches=10))
|
|
|
|
|
self.engine.logger.info("%r",
|
|
|
|
|
sql_util._repr_params(parameters, batches=10))
|
|
|
|
|
try:
|
|
|
|
|
if context.executemany:
|
|
|
|
|
self.dialect.do_executemany(
|
|
|
|
@@ -1631,6 +1677,11 @@ class Connection(Connectable):
|
|
|
|
|
statement,
|
|
|
|
|
parameters,
|
|
|
|
|
context)
|
|
|
|
|
elif not parameters and context.no_parameters:
|
|
|
|
|
self.dialect.do_execute_no_params(
|
|
|
|
|
cursor,
|
|
|
|
|
statement,
|
|
|
|
|
context)
|
|
|
|
|
else:
|
|
|
|
|
self.dialect.do_execute(
|
|
|
|
|
cursor,
|
|
|
|
@@ -1845,33 +1896,41 @@ class Connection(Connectable):
|
|
|
|
|
"""Execute the given function within a transaction boundary.
|
|
|
|
|
|
|
|
|
|
The function is passed this :class:`.Connection`
|
|
|
|
|
as the first argument, followed by the given \*args and \**kwargs.
|
|
|
|
|
|
|
|
|
|
This is a shortcut for explicitly invoking
|
|
|
|
|
:meth:`.Connection.begin`, calling :meth:`.Transaction.commit`
|
|
|
|
|
upon success or :meth:`.Transaction.rollback` upon an
|
|
|
|
|
exception raise::
|
|
|
|
|
as the first argument, followed by the given \*args and \**kwargs,
|
|
|
|
|
e.g.::
|
|
|
|
|
|
|
|
|
|
def do_something(conn, x, y):
|
|
|
|
|
conn.execute("some statement", {'x':x, 'y':y})
|
|
|
|
|
|
|
|
|
|
conn.transaction(do_something, 5, 10)
|
|
|
|
|
|
|
|
|
|
Note that context managers (i.e. the ``with`` statement)
|
|
|
|
|
present a more modern way of accomplishing the above,
|
|
|
|
|
using the :class:`.Transaction` object as a base::
|
|
|
|
|
|
|
|
|
|
with conn.begin():
|
|
|
|
|
conn.execute("some statement", {'x':5, 'y':10})
|
|
|
|
|
|
|
|
|
|
One advantage to the :meth:`.Connection.transaction`
|
|
|
|
|
method is that the same method is also available
|
|
|
|
|
on :class:`.Engine` as :meth:`.Engine.transaction` -
|
|
|
|
|
this method procures a :class:`.Connection` and then
|
|
|
|
|
performs the same operation, allowing equivalent
|
|
|
|
|
usage with either a :class:`.Connection` or :class:`.Engine`
|
|
|
|
|
without needing to know what kind of object
|
|
|
|
|
it is.
|
|
|
|
|
conn.transaction(do_something, 5, 10)
|
|
|
|
|
|
|
|
|
|
The operations inside the function are all invoked within the
|
|
|
|
|
context of a single :class:`.Transaction`.
|
|
|
|
|
Upon success, the transaction is committed. If an
|
|
|
|
|
exception is raised, the transaction is rolled back
|
|
|
|
|
before propagating the exception.
|
|
|
|
|
|
|
|
|
|
.. note::
|
|
|
|
|
|
|
|
|
|
The :meth:`.transaction` method is superseded by
|
|
|
|
|
the usage of the Python ``with:`` statement, which can
|
|
|
|
|
be used with :meth:`.Connection.begin`::
|
|
|
|
|
|
|
|
|
|
with conn.begin():
|
|
|
|
|
conn.execute("some statement", {'x':5, 'y':10})
|
|
|
|
|
|
|
|
|
|
As well as with :meth:`.Engine.begin`::
|
|
|
|
|
|
|
|
|
|
with engine.begin() as conn:
|
|
|
|
|
conn.execute("some statement", {'x':5, 'y':10})
|
|
|
|
|
|
|
|
|
|
See also:
|
|
|
|
|
|
|
|
|
|
:meth:`.Engine.begin` - engine-level transactional
|
|
|
|
|
context
|
|
|
|
|
|
|
|
|
|
:meth:`.Engine.transaction` - engine-level version of
|
|
|
|
|
:meth:`.Connection.transaction`
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
@@ -1887,15 +1946,15 @@ class Connection(Connectable):
|
|
|
|
|
def run_callable(self, callable_, *args, **kwargs):
|
|
|
|
|
"""Given a callable object or function, execute it, passing
|
|
|
|
|
a :class:`.Connection` as the first argument.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The given \*args and \**kwargs are passed subsequent
|
|
|
|
|
to the :class:`.Connection` argument.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
This function, along with :meth:`.Engine.run_callable`,
|
|
|
|
|
allows a function to be run with a :class:`.Connection`
|
|
|
|
|
or :class:`.Engine` object without the need to know
|
|
|
|
|
which one is being dealt with.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
return callable_(self, *args, **kwargs)
|
|
|
|
|
|
|
|
|
@@ -1906,11 +1965,11 @@ class Connection(Connectable):
|
|
|
|
|
|
|
|
|
|
class Transaction(object):
|
|
|
|
|
"""Represent a database transaction in progress.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The :class:`.Transaction` object is procured by
|
|
|
|
|
calling the :meth:`~.Connection.begin` method of
|
|
|
|
|
:class:`.Connection`::
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
from sqlalchemy import create_engine
|
|
|
|
|
engine = create_engine("postgresql://scott:tiger@localhost/test")
|
|
|
|
|
connection = engine.connect()
|
|
|
|
@@ -1923,7 +1982,7 @@ class Transaction(object):
|
|
|
|
|
also implements a context manager interface so that
|
|
|
|
|
the Python ``with`` statement can be used with the
|
|
|
|
|
:meth:`.Connection.begin` method::
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
with connection.begin():
|
|
|
|
|
connection.execute("insert into x (a, b) values (1, 2)")
|
|
|
|
|
|
|
|
|
@@ -1931,7 +1990,7 @@ class Transaction(object):
|
|
|
|
|
|
|
|
|
|
See also: :meth:`.Connection.begin`, :meth:`.Connection.begin_twophase`,
|
|
|
|
|
:meth:`.Connection.begin_nested`.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.. index::
|
|
|
|
|
single: thread safety; Transaction
|
|
|
|
|
"""
|
|
|
|
@@ -2012,9 +2071,9 @@ class NestedTransaction(Transaction):
|
|
|
|
|
|
|
|
|
|
A new :class:`.NestedTransaction` object may be procured
|
|
|
|
|
using the :meth:`.Connection.begin_nested` method.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The interface is the same as that of :class:`.Transaction`.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
def __init__(self, connection, parent):
|
|
|
|
|
super(NestedTransaction, self).__init__(connection, parent)
|
|
|
|
@@ -2033,13 +2092,13 @@ class NestedTransaction(Transaction):
|
|
|
|
|
|
|
|
|
|
class TwoPhaseTransaction(Transaction):
|
|
|
|
|
"""Represent a two-phase transaction.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
A new :class:`.TwoPhaseTransaction` object may be procured
|
|
|
|
|
using the :meth:`.Connection.begin_twophase` method.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The interface is the same as that of :class:`.Transaction`
|
|
|
|
|
with the addition of the :meth:`prepare` method.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
def __init__(self, connection, xid):
|
|
|
|
|
super(TwoPhaseTransaction, self).__init__(connection, None)
|
|
|
|
@@ -2049,9 +2108,9 @@ class TwoPhaseTransaction(Transaction):
|
|
|
|
|
|
|
|
|
|
def prepare(self):
|
|
|
|
|
"""Prepare this :class:`.TwoPhaseTransaction`.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
After a PREPARE, the transaction can be committed.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
if not self._parent.is_active:
|
|
|
|
|
raise exc.InvalidRequestError("This transaction is inactive")
|
|
|
|
@@ -2075,11 +2134,11 @@ class Engine(Connectable, log.Identified):
|
|
|
|
|
:func:`~sqlalchemy.create_engine` function.
|
|
|
|
|
|
|
|
|
|
See also:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
:ref:`engines_toplevel`
|
|
|
|
|
|
|
|
|
|
:ref:`connections_toplevel`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
_execution_options = util.immutabledict()
|
|
|
|
@@ -2115,13 +2174,13 @@ class Engine(Connectable, log.Identified):
|
|
|
|
|
def update_execution_options(self, **opt):
|
|
|
|
|
"""Update the default execution_options dictionary
|
|
|
|
|
of this :class:`.Engine`.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The given keys/values in \**opt are added to the
|
|
|
|
|
default execution options that will be used for
|
|
|
|
|
all connections. The initial contents of this dictionary
|
|
|
|
|
can be sent via the ``execution_options`` paramter
|
|
|
|
|
to :func:`.create_engine`.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
See :meth:`.Connection.execution_options` for more
|
|
|
|
|
details on execution options.
|
|
|
|
|
|
|
|
|
@@ -2236,19 +2295,96 @@ class Engine(Connectable, log.Identified):
|
|
|
|
|
if connection is None:
|
|
|
|
|
conn.close()
|
|
|
|
|
|
|
|
|
|
class _trans_ctx(object):
|
|
|
|
|
def __init__(self, conn, transaction, close_with_result):
|
|
|
|
|
self.conn = conn
|
|
|
|
|
self.transaction = transaction
|
|
|
|
|
self.close_with_result = close_with_result
|
|
|
|
|
|
|
|
|
|
def __enter__(self):
|
|
|
|
|
return self.conn
|
|
|
|
|
|
|
|
|
|
def __exit__(self, type, value, traceback):
|
|
|
|
|
if type is not None:
|
|
|
|
|
self.transaction.rollback()
|
|
|
|
|
else:
|
|
|
|
|
self.transaction.commit()
|
|
|
|
|
if not self.close_with_result:
|
|
|
|
|
self.conn.close()
|
|
|
|
|
|
|
|
|
|
def begin(self, close_with_result=False):
|
|
|
|
|
"""Return a context manager delivering a :class:`.Connection`
|
|
|
|
|
with a :class:`.Transaction` established.
|
|
|
|
|
|
|
|
|
|
E.g.::
|
|
|
|
|
|
|
|
|
|
with engine.begin() as conn:
|
|
|
|
|
conn.execute("insert into table (x, y, z) values (1, 2, 3)")
|
|
|
|
|
conn.execute("my_special_procedure(5)")
|
|
|
|
|
|
|
|
|
|
Upon successful operation, the :class:`.Transaction`
|
|
|
|
|
is committed. If an error is raised, the :class:`.Transaction`
|
|
|
|
|
is rolled back.
|
|
|
|
|
|
|
|
|
|
The ``close_with_result`` flag is normally ``False``, and indicates
|
|
|
|
|
that the :class:`.Connection` will be closed when the operation
|
|
|
|
|
is complete. When set to ``True``, it indicates the :class:`.Connection`
|
|
|
|
|
is in "single use" mode, where the :class:`.ResultProxy`
|
|
|
|
|
returned by the first call to :meth:`.Connection.execute` will
|
|
|
|
|
close the :class:`.Connection` when that :class:`.ResultProxy`
|
|
|
|
|
has exhausted all result rows.
|
|
|
|
|
|
|
|
|
|
New in 0.7.6.
|
|
|
|
|
|
|
|
|
|
See also:
|
|
|
|
|
|
|
|
|
|
:meth:`.Engine.connect` - procure a :class:`.Connection` from
|
|
|
|
|
an :class:`.Engine`.
|
|
|
|
|
|
|
|
|
|
:meth:`.Connection.begin` - start a :class:`.Transaction`
|
|
|
|
|
for a particular :class:`.Connection`.
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
conn = self.contextual_connect(close_with_result=close_with_result)
|
|
|
|
|
trans = conn.begin()
|
|
|
|
|
return Engine._trans_ctx(conn, trans, close_with_result)
|
|
|
|
|
|
|
|
|
|
def transaction(self, callable_, *args, **kwargs):
|
|
|
|
|
"""Execute the given function within a transaction boundary.
|
|
|
|
|
|
|
|
|
|
The function is passed a newly procured
|
|
|
|
|
:class:`.Connection` as the first argument, followed by
|
|
|
|
|
the given \*args and \**kwargs. The :class:`.Connection`
|
|
|
|
|
is then closed (returned to the pool) when the operation
|
|
|
|
|
is complete.
|
|
|
|
|
The function is passed a :class:`.Connection` newly procured
|
|
|
|
|
from :meth:`.Engine.contextual_connect` as the first argument,
|
|
|
|
|
followed by the given \*args and \**kwargs.
|
|
|
|
|
|
|
|
|
|
This method can be used interchangeably with
|
|
|
|
|
:meth:`.Connection.transaction`. See that method for
|
|
|
|
|
more details on usage as well as a modern alternative
|
|
|
|
|
using context managers (i.e. the ``with`` statement).
|
|
|
|
|
e.g.::
|
|
|
|
|
|
|
|
|
|
def do_something(conn, x, y):
|
|
|
|
|
conn.execute("some statement", {'x':x, 'y':y})
|
|
|
|
|
|
|
|
|
|
engine.transaction(do_something, 5, 10)
|
|
|
|
|
|
|
|
|
|
The operations inside the function are all invoked within the
|
|
|
|
|
context of a single :class:`.Transaction`.
|
|
|
|
|
Upon success, the transaction is committed. If an
|
|
|
|
|
exception is raised, the transaction is rolled back
|
|
|
|
|
before propagating the exception.
|
|
|
|
|
|
|
|
|
|
.. note::
|
|
|
|
|
|
|
|
|
|
The :meth:`.transaction` method is superseded by
|
|
|
|
|
the usage of the Python ``with:`` statement, which can
|
|
|
|
|
be used with :meth:`.Engine.begin`::
|
|
|
|
|
|
|
|
|
|
with engine.begin() as conn:
|
|
|
|
|
conn.execute("some statement", {'x':5, 'y':10})
|
|
|
|
|
|
|
|
|
|
See also:
|
|
|
|
|
|
|
|
|
|
:meth:`.Engine.begin` - engine-level transactional
|
|
|
|
|
context
|
|
|
|
|
|
|
|
|
|
:meth:`.Connection.transaction` - connection-level version of
|
|
|
|
|
:meth:`.Engine.transaction`
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
@@ -2261,15 +2397,15 @@ class Engine(Connectable, log.Identified):
|
|
|
|
|
def run_callable(self, callable_, *args, **kwargs):
|
|
|
|
|
"""Given a callable object or function, execute it, passing
|
|
|
|
|
a :class:`.Connection` as the first argument.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The given \*args and \**kwargs are passed subsequent
|
|
|
|
|
to the :class:`.Connection` argument.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
This function, along with :meth:`.Connection.run_callable`,
|
|
|
|
|
allows a function to be run with a :class:`.Connection`
|
|
|
|
|
or :class:`.Engine` object without the need to know
|
|
|
|
|
which one is being dealt with.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
conn = self.contextual_connect()
|
|
|
|
|
try:
|
|
|
|
@@ -2390,19 +2526,19 @@ class Engine(Connectable, log.Identified):
|
|
|
|
|
|
|
|
|
|
def raw_connection(self):
|
|
|
|
|
"""Return a "raw" DBAPI connection from the connection pool.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The returned object is a proxied version of the DBAPI
|
|
|
|
|
connection object used by the underlying driver in use.
|
|
|
|
|
The object will have all the same behavior as the real DBAPI
|
|
|
|
|
connection, except that its ``close()`` method will result in the
|
|
|
|
|
connection being returned to the pool, rather than being closed
|
|
|
|
|
for real.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
This method provides direct DBAPI connection access for
|
|
|
|
|
special situations. In most situations, the :class:`.Connection`
|
|
|
|
|
object should be used, which is procured using the
|
|
|
|
|
:meth:`.Engine.connect` method.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
return self.pool.unique_connection()
|
|
|
|
@@ -2487,7 +2623,6 @@ except ImportError:
|
|
|
|
|
|
|
|
|
|
def __getattr__(self, name):
|
|
|
|
|
try:
|
|
|
|
|
# TODO: no test coverage here
|
|
|
|
|
return self[name]
|
|
|
|
|
except KeyError, e:
|
|
|
|
|
raise AttributeError(e.args[0])
|
|
|
|
@@ -2575,6 +2710,10 @@ class ResultMetaData(object):
|
|
|
|
|
context = parent.context
|
|
|
|
|
dialect = context.dialect
|
|
|
|
|
typemap = dialect.dbapi_type_map
|
|
|
|
|
translate_colname = dialect._translate_colname
|
|
|
|
|
|
|
|
|
|
# high precedence key values.
|
|
|
|
|
primary_keymap = {}
|
|
|
|
|
|
|
|
|
|
for i, rec in enumerate(metadata):
|
|
|
|
|
colname = rec[0]
|
|
|
|
@@ -2583,6 +2722,9 @@ class ResultMetaData(object):
|
|
|
|
|
if dialect.description_encoding:
|
|
|
|
|
colname = dialect._description_decoder(colname)
|
|
|
|
|
|
|
|
|
|
if translate_colname:
|
|
|
|
|
colname, untranslated = translate_colname(colname)
|
|
|
|
|
|
|
|
|
|
if context.result_map:
|
|
|
|
|
try:
|
|
|
|
|
name, obj, type_ = context.result_map[colname.lower()]
|
|
|
|
@@ -2600,15 +2742,17 @@ class ResultMetaData(object):
|
|
|
|
|
|
|
|
|
|
# indexes as keys. This is only needed for the Python version of
|
|
|
|
|
# RowProxy (the C version uses a faster path for integer indexes).
|
|
|
|
|
keymap[i] = rec
|
|
|
|
|
primary_keymap[i] = rec
|
|
|
|
|
|
|
|
|
|
# Column names as keys
|
|
|
|
|
if keymap.setdefault(name.lower(), rec) is not rec:
|
|
|
|
|
# We do not raise an exception directly because several
|
|
|
|
|
# columns colliding by name is not a problem as long as the
|
|
|
|
|
# user does not try to access them (ie use an index directly,
|
|
|
|
|
# or the more precise ColumnElement)
|
|
|
|
|
keymap[name.lower()] = (processor, obj, None)
|
|
|
|
|
# populate primary keymap, looking for conflicts.
|
|
|
|
|
if primary_keymap.setdefault(name.lower(), rec) is not rec:
|
|
|
|
|
# place a record that doesn't have the "index" - this
|
|
|
|
|
# is interpreted later as an AmbiguousColumnError,
|
|
|
|
|
# but only when actually accessed. Columns
|
|
|
|
|
# colliding by name is not a problem if those names
|
|
|
|
|
# aren't used; integer and ColumnElement access is always
|
|
|
|
|
# unambiguous.
|
|
|
|
|
primary_keymap[name.lower()] = (processor, obj, None)
|
|
|
|
|
|
|
|
|
|
if dialect.requires_name_normalize:
|
|
|
|
|
colname = dialect.normalize_name(colname)
|
|
|
|
@@ -2618,10 +2762,20 @@ class ResultMetaData(object):
|
|
|
|
|
for o in obj:
|
|
|
|
|
keymap[o] = rec
|
|
|
|
|
|
|
|
|
|
if translate_colname and \
|
|
|
|
|
untranslated:
|
|
|
|
|
keymap[untranslated] = rec
|
|
|
|
|
|
|
|
|
|
# overwrite keymap values with those of the
|
|
|
|
|
# high precedence keymap.
|
|
|
|
|
keymap.update(primary_keymap)
|
|
|
|
|
|
|
|
|
|
if parent._echo:
|
|
|
|
|
context.engine.logger.debug(
|
|
|
|
|
"Col %r", tuple(x[0] for x in metadata))
|
|
|
|
|
|
|
|
|
|
@util.pending_deprecation("0.8", "sqlite dialect uses "
|
|
|
|
|
"_translate_colname() now")
|
|
|
|
|
def _set_keymap_synonym(self, name, origname):
|
|
|
|
|
"""Set a synonym for the given name.
|
|
|
|
|
|
|
|
|
@@ -2647,7 +2801,7 @@ class ResultMetaData(object):
|
|
|
|
|
if key._label and key._label.lower() in map:
|
|
|
|
|
result = map[key._label.lower()]
|
|
|
|
|
elif hasattr(key, 'name') and key.name.lower() in map:
|
|
|
|
|
# match is only on name.
|
|
|
|
|
# match is only on name.
|
|
|
|
|
result = map[key.name.lower()]
|
|
|
|
|
# search extra hard to make sure this
|
|
|
|
|
# isn't a column/label name overlap.
|
|
|
|
@@ -2800,7 +2954,7 @@ class ResultProxy(object):
|
|
|
|
|
@property
|
|
|
|
|
def returns_rows(self):
|
|
|
|
|
"""True if this :class:`.ResultProxy` returns rows.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
I.e. if it is legal to call the methods
|
|
|
|
|
:meth:`~.ResultProxy.fetchone`,
|
|
|
|
|
:meth:`~.ResultProxy.fetchmany`
|
|
|
|
@@ -2814,12 +2968,12 @@ class ResultProxy(object):
|
|
|
|
|
"""True if this :class:`.ResultProxy` is the result
|
|
|
|
|
of a executing an expression language compiled
|
|
|
|
|
:func:`.expression.insert` construct.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
When True, this implies that the
|
|
|
|
|
:attr:`inserted_primary_key` attribute is accessible,
|
|
|
|
|
assuming the statement did not include
|
|
|
|
|
a user defined "returning" construct.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
return self.context.isinsert
|
|
|
|
|
|
|
|
|
@@ -2867,7 +3021,7 @@ class ResultProxy(object):
|
|
|
|
|
@util.memoized_property
|
|
|
|
|
def inserted_primary_key(self):
|
|
|
|
|
"""Return the primary key for the row just inserted.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The return value is a list of scalar values
|
|
|
|
|
corresponding to the list of primary key columns
|
|
|
|
|
in the target table.
|
|
|
|
@@ -2875,7 +3029,7 @@ class ResultProxy(object):
|
|
|
|
|
This only applies to single row :func:`.insert`
|
|
|
|
|
constructs which did not explicitly specify
|
|
|
|
|
:meth:`.Insert.returning`.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Note that primary key columns which specify a
|
|
|
|
|
server_default clause,
|
|
|
|
|
or otherwise do not qualify as "autoincrement"
|
|
|
|
|