You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							414 lines
						
					
					
						
							16 KiB
						
					
					
				
			
		
		
	
	
							414 lines
						
					
					
						
							16 KiB
						
					
					
				from .. import util
 | 
						|
from ..engine import Connection as _LegacyConnection
 | 
						|
from ..engine import create_engine as _create_engine
 | 
						|
from ..engine import Engine as _LegacyEngine
 | 
						|
from ..engine.base import OptionEngineMixin
 | 
						|
 | 
						|
NO_OPTIONS = util.immutabledict()
 | 
						|
 | 
						|
 | 
						|
def create_engine(*arg, **kw):
 | 
						|
    """Create a new :class:`_future.Engine` instance.
 | 
						|
 | 
						|
    Arguments passed to :func:`_future.create_engine` are mostly identical
 | 
						|
    to those passed to the 1.x :func:`_sa.create_engine` function.
 | 
						|
    The difference is that the object returned is the :class:`._future.Engine`
 | 
						|
    which has the 2.0 version of the API.
 | 
						|
 | 
						|
    """
 | 
						|
 | 
						|
    kw["_future_engine_class"] = Engine
 | 
						|
    return _create_engine(*arg, **kw)
 | 
						|
 | 
						|
 | 
						|
class Connection(_LegacyConnection):
 | 
						|
    """Provides high-level functionality for a wrapped DB-API connection.
 | 
						|
 | 
						|
    The :class:`_future.Connection` object is procured by calling
 | 
						|
    the :meth:`_future.Engine.connect` method of the :class:`_future.Engine`
 | 
						|
    object, and provides services for execution of SQL statements as well
 | 
						|
    as transaction control.
 | 
						|
 | 
						|
    **This is the SQLAlchemy 2.0 version** of the :class:`_engine.Connection`
 | 
						|
    class.   The API and behavior of this object is largely the same, with the
 | 
						|
    following differences in behavior:
 | 
						|
 | 
						|
    * The result object returned for results is the
 | 
						|
      :class:`_engine.CursorResult`
 | 
						|
      object, which is a subclass of the :class:`_engine.Result`.
 | 
						|
      This object has a slightly different API and behavior than the
 | 
						|
      :class:`_engine.LegacyCursorResult` returned for 1.x style usage.
 | 
						|
 | 
						|
    * The object has :meth:`_future.Connection.commit` and
 | 
						|
      :meth:`_future.Connection.rollback` methods which commit or roll back
 | 
						|
      the current transaction in progress, if any.
 | 
						|
 | 
						|
    * The object features "autobegin" behavior, such that any call to
 | 
						|
      :meth:`_future.Connection.execute` will
 | 
						|
      unconditionally start a
 | 
						|
      transaction which can be controlled using the above mentioned
 | 
						|
      :meth:`_future.Connection.commit` and
 | 
						|
      :meth:`_future.Connection.rollback` methods.
 | 
						|
 | 
						|
    * The object does not have any "autocommit" functionality.  Any SQL
 | 
						|
      statement or DDL statement will not be followed by any COMMIT until
 | 
						|
      the transaction is explicitly committed, either via the
 | 
						|
      :meth:`_future.Connection.commit` method, or if the connection is
 | 
						|
      being used in a context manager that commits such as the one
 | 
						|
      returned by :meth:`_future.Engine.begin`.
 | 
						|
 | 
						|
    * The SAVEPOINT method :meth:`_future.Connection.begin_nested` returns
 | 
						|
      a :class:`_engine.NestedTransaction` as was always the case, and the
 | 
						|
      savepoint can be controlled by invoking
 | 
						|
      :meth:`_engine.NestedTransaction.commit` or
 | 
						|
      :meth:`_engine.NestedTransaction.rollback` as was the case before.
 | 
						|
      However, this savepoint "transaction" is not associated with the
 | 
						|
      transaction that is controlled by the connection itself; the overall
 | 
						|
      transaction can be committed or rolled back directly which will not emit
 | 
						|
      any special instructions for the SAVEPOINT (this will typically have the
 | 
						|
      effect that one desires).
 | 
						|
 | 
						|
    * The :class:`_future.Connection` object does not support "branching",
 | 
						|
      which was a pattern by which a sub "connection" would be used that
 | 
						|
      refers to this connection as a parent.
 | 
						|
 | 
						|
 | 
						|
 | 
						|
    """
 | 
						|
 | 
						|
    _is_future = True
 | 
						|
 | 
						|
    def _branch(self):
 | 
						|
        raise NotImplementedError(
 | 
						|
            "sqlalchemy.future.Connection does not support "
 | 
						|
            "'branching' of new connections."
 | 
						|
        )
 | 
						|
 | 
						|
    def begin(self):
 | 
						|
        """Begin a transaction prior to autobegin occurring.
 | 
						|
 | 
						|
        The returned object is an instance of :class:`_engine.RootTransaction`.
 | 
						|
        This object represents the "scope" of the transaction,
 | 
						|
        which completes when either the :meth:`_engine.Transaction.rollback`
 | 
						|
        or :meth:`_engine.Transaction.commit` method is called.
 | 
						|
 | 
						|
        The :meth:`_future.Connection.begin` method in SQLAlchemy 2.0 begins a
 | 
						|
        transaction that normally will be begun in any case when the connection
 | 
						|
        is first used to execute a statement.  The reason this method might be
 | 
						|
        used would be to invoke the :meth:`_events.ConnectionEvents.begin`
 | 
						|
        event at a specific time, or to organize code within the scope of a
 | 
						|
        connection checkout in terms of context managed blocks, such as::
 | 
						|
 | 
						|
            with engine.connect() as conn:
 | 
						|
                with conn.begin():
 | 
						|
                    conn.execute(...)
 | 
						|
                    conn.execute(...)
 | 
						|
 | 
						|
                with conn.begin():
 | 
						|
                    conn.execute(...)
 | 
						|
                    conn.execute(...)
 | 
						|
 | 
						|
        The above code is not  fundamentally any different in its behavior than
 | 
						|
        the following code  which does not use
 | 
						|
        :meth:`_future.Connection.begin`; the below style is referred towards
 | 
						|
        as "commit as you go" style::
 | 
						|
 | 
						|
            with engine.connect() as conn:
 | 
						|
                conn.execute(...)
 | 
						|
                conn.execute(...)
 | 
						|
                conn.commit()
 | 
						|
 | 
						|
                conn.execute(...)
 | 
						|
                conn.execute(...)
 | 
						|
                conn.commit()
 | 
						|
 | 
						|
        From a database point of view, the :meth:`_future.Connection.begin`
 | 
						|
        method does not emit any SQL or change the state of the underlying
 | 
						|
        DBAPI connection in any way; the Python DBAPI does not have any
 | 
						|
        concept of explicit transaction begin.
 | 
						|
 | 
						|
        .. seealso::
 | 
						|
 | 
						|
            :ref:`tutorial_working_with_transactions` - in the
 | 
						|
            :ref:`unified_tutorial`
 | 
						|
 | 
						|
            :meth:`_future.Connection.begin_nested` - use a SAVEPOINT
 | 
						|
 | 
						|
            :meth:`_engine.Connection.begin_twophase` -
 | 
						|
            use a two phase /XID transaction
 | 
						|
 | 
						|
            :meth:`_future.Engine.begin` - context manager available from
 | 
						|
            :class:`_future.Engine`
 | 
						|
 | 
						|
        """
 | 
						|
        return super(Connection, self).begin()
 | 
						|
 | 
						|
    def begin_nested(self):
 | 
						|
        """Begin a nested transaction (i.e. SAVEPOINT) and return a transaction
 | 
						|
        handle.
 | 
						|
 | 
						|
        The returned object is an instance of
 | 
						|
        :class:`_engine.NestedTransaction`.
 | 
						|
 | 
						|
        Nested transactions require SAVEPOINT support in the
 | 
						|
        underlying database.  Any transaction in the hierarchy may
 | 
						|
        ``commit`` and ``rollback``, however the outermost transaction
 | 
						|
        still controls the overall ``commit`` or ``rollback`` of the
 | 
						|
        transaction of a whole.
 | 
						|
 | 
						|
        If an outer :class:`.RootTransaction` is not present on this
 | 
						|
        :class:`_future.Connection`, a new one is created using "autobegin".
 | 
						|
        This outer transaction may be completed using "commit-as-you-go" style
 | 
						|
        usage, by calling upon :meth:`_future.Connection.commit` or
 | 
						|
        :meth:`_future.Connection.rollback`.
 | 
						|
 | 
						|
        .. tip::
 | 
						|
 | 
						|
            The "autobegin" behavior of :meth:`_future.Connection.begin_nested`
 | 
						|
            is specific to :term:`2.0 style` use; for legacy behaviors, see
 | 
						|
            :meth:`_engine.Connection.begin_nested`.
 | 
						|
 | 
						|
        The :class:`_engine.NestedTransaction` remains independent of the
 | 
						|
        :class:`_future.Connection` object itself. Calling the
 | 
						|
        :meth:`_future.Connection.commit` or
 | 
						|
        :meth:`_future.Connection.rollback` will always affect the actual
 | 
						|
        containing database transaction itself, and not the SAVEPOINT itself.
 | 
						|
        When a database transaction is committed, any SAVEPOINTs that have been
 | 
						|
        established are cleared and the data changes within their scope is also
 | 
						|
        committed.
 | 
						|
 | 
						|
        .. seealso::
 | 
						|
 | 
						|
            :meth:`_future.Connection.begin`
 | 
						|
 | 
						|
 | 
						|
        """
 | 
						|
        return super(Connection, self).begin_nested()
 | 
						|
 | 
						|
    def commit(self):
 | 
						|
        """Commit the transaction that is currently in progress.
 | 
						|
 | 
						|
        This method commits the current transaction if one has been started.
 | 
						|
        If no transaction was started, the method has no effect, assuming
 | 
						|
        the connection is in a non-invalidated state.
 | 
						|
 | 
						|
        A transaction is begun on a :class:`_future.Connection` automatically
 | 
						|
        whenever a statement is first executed, or when the
 | 
						|
        :meth:`_future.Connection.begin` method is called.
 | 
						|
 | 
						|
        .. note:: The :meth:`_future.Connection.commit` method only acts upon
 | 
						|
          the primary database transaction that is linked to the
 | 
						|
          :class:`_future.Connection` object.  It does not operate upon a
 | 
						|
          SAVEPOINT that would have been invoked from the
 | 
						|
          :meth:`_future.Connection.begin_nested` method; for control of a
 | 
						|
          SAVEPOINT, call :meth:`_engine.NestedTransaction.commit` on the
 | 
						|
          :class:`_engine.NestedTransaction` that is returned by the
 | 
						|
          :meth:`_future.Connection.begin_nested` method itself.
 | 
						|
 | 
						|
 | 
						|
        """
 | 
						|
        if self._transaction:
 | 
						|
            self._transaction.commit()
 | 
						|
 | 
						|
    def rollback(self):
 | 
						|
        """Roll back the transaction that is currently in progress.
 | 
						|
 | 
						|
        This method rolls back the current transaction if one has been started.
 | 
						|
        If no transaction was started, the method has no effect.  If a
 | 
						|
        transaction was started and the connection is in an invalidated state,
 | 
						|
        the transaction is cleared using this method.
 | 
						|
 | 
						|
        A transaction is begun on a :class:`_future.Connection` automatically
 | 
						|
        whenever a statement is first executed, or when the
 | 
						|
        :meth:`_future.Connection.begin` method is called.
 | 
						|
 | 
						|
        .. note:: The :meth:`_future.Connection.rollback` method only acts
 | 
						|
          upon the primary database transaction that is linked to the
 | 
						|
          :class:`_future.Connection` object.  It does not operate upon a
 | 
						|
          SAVEPOINT that would have been invoked from the
 | 
						|
          :meth:`_future.Connection.begin_nested` method; for control of a
 | 
						|
          SAVEPOINT, call :meth:`_engine.NestedTransaction.rollback` on the
 | 
						|
          :class:`_engine.NestedTransaction` that is returned by the
 | 
						|
          :meth:`_future.Connection.begin_nested` method itself.
 | 
						|
 | 
						|
 | 
						|
        """
 | 
						|
        if self._transaction:
 | 
						|
            self._transaction.rollback()
 | 
						|
 | 
						|
    def close(self):
 | 
						|
        """Close this :class:`_future.Connection`.
 | 
						|
 | 
						|
        This has the effect of also calling :meth:`_future.Connection.rollback`
 | 
						|
        if any transaction is in place.
 | 
						|
 | 
						|
        """
 | 
						|
        super(Connection, self).close()
 | 
						|
 | 
						|
    def execute(self, statement, parameters=None, execution_options=None):
 | 
						|
        r"""Executes a SQL statement construct and returns a
 | 
						|
        :class:`_engine.Result`.
 | 
						|
 | 
						|
        :param statement: The statement to be executed.  This is always
 | 
						|
         an object that is in both the :class:`_expression.ClauseElement` and
 | 
						|
         :class:`_expression.Executable` hierarchies, including:
 | 
						|
 | 
						|
         * :class:`_expression.Select`
 | 
						|
         * :class:`_expression.Insert`, :class:`_expression.Update`,
 | 
						|
           :class:`_expression.Delete`
 | 
						|
         * :class:`_expression.TextClause` and
 | 
						|
           :class:`_expression.TextualSelect`
 | 
						|
         * :class:`_schema.DDL` and objects which inherit from
 | 
						|
           :class:`_schema.DDLElement`
 | 
						|
 | 
						|
        :param parameters: parameters which will be bound into the statement.
 | 
						|
         This may be either a dictionary of parameter names to values,
 | 
						|
         or a mutable sequence (e.g. a list) of dictionaries.  When a
 | 
						|
         list of dictionaries is passed, the underlying statement execution
 | 
						|
         will make use of the DBAPI ``cursor.executemany()`` method.
 | 
						|
         When a single dictionary is passed, the DBAPI ``cursor.execute()``
 | 
						|
         method will be used.
 | 
						|
 | 
						|
        :param execution_options: optional dictionary of execution options,
 | 
						|
         which will be associated with the statement execution.  This
 | 
						|
         dictionary can provide a subset of the options that are accepted
 | 
						|
         by :meth:`_future.Connection.execution_options`.
 | 
						|
 | 
						|
        :return: a :class:`_engine.Result` object.
 | 
						|
 | 
						|
        """
 | 
						|
        return self._execute_20(
 | 
						|
            statement, parameters, execution_options or NO_OPTIONS
 | 
						|
        )
 | 
						|
 | 
						|
    def scalar(self, statement, parameters=None, execution_options=None):
 | 
						|
        r"""Executes a SQL statement construct and returns a scalar object.
 | 
						|
 | 
						|
        This method is shorthand for invoking the
 | 
						|
        :meth:`_engine.Result.scalar` method after invoking the
 | 
						|
        :meth:`_future.Connection.execute` method.  Parameters are equivalent.
 | 
						|
 | 
						|
        :return: a scalar Python value representing the first column of the
 | 
						|
         first row returned.
 | 
						|
 | 
						|
        """
 | 
						|
        return self.execute(statement, parameters, execution_options).scalar()
 | 
						|
 | 
						|
 | 
						|
class Engine(_LegacyEngine):
 | 
						|
    """Connects a :class:`_pool.Pool` and
 | 
						|
    :class:`_engine.Dialect` together to provide a
 | 
						|
    source of database connectivity and behavior.
 | 
						|
 | 
						|
    **This is the SQLAlchemy 2.0 version** of the :class:`~.engine.Engine`.
 | 
						|
 | 
						|
    An :class:`.future.Engine` object is instantiated publicly using the
 | 
						|
    :func:`~sqlalchemy.future.create_engine` function.
 | 
						|
 | 
						|
    .. seealso::
 | 
						|
 | 
						|
        :doc:`/core/engines`
 | 
						|
 | 
						|
        :ref:`connections_toplevel`
 | 
						|
 | 
						|
    """
 | 
						|
 | 
						|
    _connection_cls = Connection
 | 
						|
    _is_future = True
 | 
						|
 | 
						|
    def _not_implemented(self, *arg, **kw):
 | 
						|
        raise NotImplementedError(
 | 
						|
            "This method is not implemented for SQLAlchemy 2.0."
 | 
						|
        )
 | 
						|
 | 
						|
    transaction = (
 | 
						|
        run_callable
 | 
						|
    ) = (
 | 
						|
        execute
 | 
						|
    ) = (
 | 
						|
        scalar
 | 
						|
    ) = (
 | 
						|
        _execute_clauseelement
 | 
						|
    ) = _execute_compiled = table_names = has_table = _not_implemented
 | 
						|
 | 
						|
    def _run_ddl_visitor(self, visitorcallable, element, **kwargs):
 | 
						|
        # TODO: this is for create_all support etc.   not clear if we
 | 
						|
        # want to provide this in 2.0, that is, a way to execute SQL where
 | 
						|
        # they aren't calling "engine.begin()" explicitly, however, DDL
 | 
						|
        # may be a special case for which we want to continue doing it this
 | 
						|
        # way.  A big win here is that the full DDL sequence is inside of a
 | 
						|
        # single transaction rather than COMMIT for each statement.
 | 
						|
        with self.begin() as conn:
 | 
						|
            conn._run_ddl_visitor(visitorcallable, element, **kwargs)
 | 
						|
 | 
						|
    @classmethod
 | 
						|
    def _future_facade(self, legacy_engine):
 | 
						|
        return Engine(
 | 
						|
            legacy_engine.pool,
 | 
						|
            legacy_engine.dialect,
 | 
						|
            legacy_engine.url,
 | 
						|
            logging_name=legacy_engine.logging_name,
 | 
						|
            echo=legacy_engine.echo,
 | 
						|
            hide_parameters=legacy_engine.hide_parameters,
 | 
						|
            execution_options=legacy_engine._execution_options,
 | 
						|
        )
 | 
						|
 | 
						|
    @util.contextmanager
 | 
						|
    def begin(self):
 | 
						|
        """Return a :class:`_future.Connection` object with a transaction
 | 
						|
        begun.
 | 
						|
 | 
						|
        Use of this method is similar to that of
 | 
						|
        :meth:`_future.Engine.connect`, typically as a context manager, which
 | 
						|
        will automatically maintain the state of the transaction when the block
 | 
						|
        ends, either by calling :meth:`_future.Connection.commit` when the
 | 
						|
        block succeeds normally, or :meth:`_future.Connection.rollback` when an
 | 
						|
        exception is raised, before propagating the exception outwards::
 | 
						|
 | 
						|
            with engine.begin() as connection:
 | 
						|
                connection.execute(text("insert into table values ('foo')"))
 | 
						|
 | 
						|
 | 
						|
        .. seealso::
 | 
						|
 | 
						|
            :meth:`_future.Engine.connect`
 | 
						|
 | 
						|
            :meth:`_future.Connection.begin`
 | 
						|
 | 
						|
        """
 | 
						|
        with self.connect() as conn:
 | 
						|
            with conn.begin():
 | 
						|
                yield conn
 | 
						|
 | 
						|
    def connect(self):
 | 
						|
        """Return a new :class:`_future.Connection` object.
 | 
						|
 | 
						|
        The :class:`_future.Connection` acts as a Python context manager, so
 | 
						|
        the typical use of this method looks like::
 | 
						|
 | 
						|
            with engine.connect() as connection:
 | 
						|
                connection.execute(text("insert into table values ('foo')"))
 | 
						|
                connection.commit()
 | 
						|
 | 
						|
        Where above, after the block is completed, the connection is "closed"
 | 
						|
        and its underlying DBAPI resources are returned to the connection pool.
 | 
						|
        This also has the effect of rolling back any transaction that
 | 
						|
        was explicitly begun or was begun via autobegin, and will
 | 
						|
        emit the :meth:`_events.ConnectionEvents.rollback` event if one was
 | 
						|
        started and is still in progress.
 | 
						|
 | 
						|
        .. seealso::
 | 
						|
 | 
						|
            :meth:`_future.Engine.begin`
 | 
						|
 | 
						|
 | 
						|
        """
 | 
						|
        return super(Engine, self).connect()
 | 
						|
 | 
						|
 | 
						|
class OptionEngine(OptionEngineMixin, Engine):
 | 
						|
    pass
 | 
						|
 | 
						|
 | 
						|
Engine._option_cls = OptionEngine
 |