From 9b9a21adb80fb20525925a10c23381fe6f3983ba Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Mon, 30 Jun 2014 11:08:05 -0400 Subject: [PATCH] - add new section Working with Raw DBAPI Connections, fixes #2218. --- doc/build/core/connections.rst | 65 +++++++++++++++++++++++++++++++++ lib/sqlalchemy/sql/functions.py | 9 +++++ 2 files changed, 74 insertions(+) diff --git a/doc/build/core/connections.rst b/doc/build/core/connections.rst index c05bf18d09..ca584f0120 100644 --- a/doc/build/core/connections.rst +++ b/doc/build/core/connections.rst @@ -445,6 +445,71 @@ Calling :meth:`~.Connection.close` on the "contextual" connection does not :term its resources until all other usages of that resource are closed as well, including that any ongoing transactions are rolled back or committed. +.. _dbapi_connections: + +Working with Raw DBAPI Connections +================================== + +There are some cases where SQLAlchemy does not provide a genericized way +at accessing some :term:`DBAPI` functions, such as calling stored procedures as well +as dealing with multiple result sets. In these cases, it's just as expedient +to deal with the raw DBAPI connection directly. This is accessible from +a :class:`.Engine` using the :meth:`.Engine.raw_connection` method:: + + dbapi_conn = engine.raw_connection() + +The instance returned is a "wrapped" form of DBAPI connection. When its +``.close()`` method is called, the connection is :term:`released` back to the +engine's connection pool:: + + dbapi_conn.close() + +While SQLAlchemy may in the future add built-in patterns for more DBAPI +use cases, there are diminishing returns as these cases tend to be rarely +needed and they also vary highly dependent on the type of DBAPI in use, +so in any case the direct DBAPI calling pattern is always there for those +cases where it is needed. + +Some recipes for DBAPI connection use follow. + +.. _stored_procedures: + +Calling Stored Procedures +------------------------- + +For stored procedures with special syntactical or parameter concerns, +DBAPI-level `callproc `_ +may be used:: + + connection = engine.raw_connection() + try: + cursor = connection.cursor() + cursor.callproc("my_procedure", ['x', 'y', 'z']) + results = list(cursor.fetchall()) + cursor.close() + connection.commit() + finally: + connection.close() + +Multiple Result Sets +-------------------- + +Multiple result set support is available from a raw DBAPI cursor using the +`nextset `_ method:: + + connection = engine.raw_connection() + try: + cursor = connection.cursor() + cursor.execute("select * from table1; select * from table2") + results_one = cursor.fetchall() + cursor.nextset() + results_two = cursor.fetchall() + cursor.close() + finally: + connection.close() + + + Registering New Dialects ======================== diff --git a/lib/sqlalchemy/sql/functions.py b/lib/sqlalchemy/sql/functions.py index 1def809e05..4ed7d853d9 100644 --- a/lib/sqlalchemy/sql/functions.py +++ b/lib/sqlalchemy/sql/functions.py @@ -267,6 +267,15 @@ func = _FunctionGenerator() calculate their return type automatically. For a listing of known generic functions, see :ref:`generic_functions`. + .. note:: + + The :data:`.func` construct has only limited support for calling + standalone "stored procedures", especially those with special parameterization + concerns. + + See the section :ref:`stored_procedures` for details on how to use + the DBAPI-level ``callproc()`` method for fully traditional stored procedures. + """ modifier = _FunctionGenerator(group=False) -- 2.47.3