2010-02-26 03:17:52 +03:00
|
|
|
The `psycopg2` module content
|
2010-02-09 07:58:28 +03:00
|
|
|
==================================
|
|
|
|
|
|
|
|
.. sectionauthor:: Daniele Varrazzo <daniele.varrazzo@gmail.com>
|
|
|
|
|
|
|
|
.. module:: psycopg2
|
|
|
|
|
2010-02-10 00:31:40 +03:00
|
|
|
The module interface respects the standard defined in the |DBAPI|_.
|
2010-02-09 07:58:28 +03:00
|
|
|
|
2013-01-09 16:56:06 +04:00
|
|
|
.. index::
|
2010-02-09 07:58:28 +03:00
|
|
|
single: Connection string
|
|
|
|
double: Connection; Parameters
|
|
|
|
single: Username; Connection
|
|
|
|
single: Password; Connection
|
|
|
|
single: Host; Connection
|
|
|
|
single: Port; Connection
|
|
|
|
single: DSN (Database Source Name)
|
|
|
|
|
2013-01-09 16:56:06 +04:00
|
|
|
.. function::
|
2013-04-07 05:30:12 +04:00
|
|
|
connect(dsn, connection_factory=None, cursor_factory=None, async=False)
|
|
|
|
connect(\*\*kwargs, connection_factory=None, cursor_factory=None, async=False)
|
2010-02-09 07:58:28 +03:00
|
|
|
|
2010-02-26 03:17:52 +03:00
|
|
|
Create a new database session and return a new `connection` object.
|
2010-02-09 07:58:28 +03:00
|
|
|
|
2013-01-09 16:56:06 +04:00
|
|
|
The connection parameters can be specified either as a `libpq connection
|
|
|
|
string`__ using the *dsn* parameter::
|
2010-02-09 07:58:28 +03:00
|
|
|
|
|
|
|
conn = psycopg2.connect("dbname=test user=postgres password=secret")
|
|
|
|
|
|
|
|
or using a set of keyword arguments::
|
|
|
|
|
|
|
|
conn = psycopg2.connect(database="test", user="postgres", password="secret")
|
|
|
|
|
2013-01-09 16:56:06 +04:00
|
|
|
The two call styles are mutually exclusive: you cannot specify connection
|
|
|
|
parameters as keyword arguments together with a connection string; only
|
2013-04-07 05:30:12 +04:00
|
|
|
the parameters not needed for the database connection (*i.e.*
|
|
|
|
*connection_factory*, *cursor_factory*, and *async*) are supported
|
|
|
|
together with the *dsn* argument.
|
2013-01-09 16:56:06 +04:00
|
|
|
|
2011-11-17 05:51:25 +04:00
|
|
|
The basic connection parameters are:
|
|
|
|
|
2013-01-09 16:56:06 +04:00
|
|
|
- `!dbname` -- the database name (only in the *dsn* string)
|
2011-02-19 19:16:28 +03:00
|
|
|
- `!database` -- the database name (only as keyword argument)
|
|
|
|
- `!user` -- user name used to authenticate
|
|
|
|
- `!password` -- password used to authenticate
|
|
|
|
- `!host` -- database host address (defaults to UNIX socket if not provided)
|
|
|
|
- `!port` -- connection port number (defaults to 5432 if not provided)
|
2010-02-09 07:58:28 +03:00
|
|
|
|
2011-11-17 05:51:25 +04:00
|
|
|
Any other connection parameter supported by the client library/server can
|
2013-01-09 16:56:06 +04:00
|
|
|
be passed either in the connection string or as keywords. The PostgreSQL
|
|
|
|
documentation contains the complete list of the `supported parameters`__.
|
2011-11-17 05:51:25 +04:00
|
|
|
Also note that the same parameters can be passed to the client library
|
|
|
|
using `environment variables`__.
|
|
|
|
|
2013-01-09 16:56:06 +04:00
|
|
|
.. __:
|
|
|
|
.. _connstring: http://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING
|
|
|
|
.. __:
|
|
|
|
.. _connparams: http://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-PARAMKEYWORDS
|
|
|
|
.. __:
|
|
|
|
.. _connenvvars: http://www.postgresql.org/docs/current/static/libpq-envars.html
|
2010-02-09 07:58:28 +03:00
|
|
|
|
2010-04-08 16:22:55 +04:00
|
|
|
Using the *connection_factory* parameter a different class or
|
2010-02-09 07:58:28 +03:00
|
|
|
connections factory can be specified. It should be a callable object
|
2013-01-09 16:56:06 +04:00
|
|
|
taking a *dsn* string argument. See :ref:`subclassing-connection` for
|
2013-04-07 05:30:12 +04:00
|
|
|
details. If a *cursor_factory* is specified, the connection's
|
|
|
|
`~connection.cursor_factory` is set to it. If you only need customized
|
|
|
|
cursors you can use this parameter instead of subclassing a connection.
|
2010-02-09 07:58:28 +03:00
|
|
|
|
2013-01-09 16:56:06 +04:00
|
|
|
Using *async*\=\ `!True` an asynchronous connection will be created: see
|
2010-04-08 16:22:55 +04:00
|
|
|
:ref:`async-support` to know about advantages and limitations.
|
|
|
|
|
2011-11-17 05:51:25 +04:00
|
|
|
.. versionchanged:: 2.4.3
|
|
|
|
any keyword argument is passed to the connection. Previously only the
|
|
|
|
basic parameters (plus `!sslmode`) were supported as keywords.
|
|
|
|
|
2013-04-07 05:30:12 +04:00
|
|
|
.. versionchanged:: 2.5
|
|
|
|
added the *cursor_factory* parameter.
|
|
|
|
|
2013-01-09 16:56:06 +04:00
|
|
|
.. seealso::
|
|
|
|
|
|
|
|
- libpq `connection string syntax`__
|
|
|
|
- libpq supported `connection parameters`__
|
|
|
|
- libpq supported `environment variables`__
|
|
|
|
|
|
|
|
.. __: connstring_
|
|
|
|
.. __: connparams_
|
|
|
|
.. __: connenvvars_
|
|
|
|
|
2010-02-10 02:09:48 +03:00
|
|
|
.. extension::
|
|
|
|
|
2010-04-08 16:22:55 +04:00
|
|
|
The parameters *connection_factory* and *async* are Psycopg extensions
|
|
|
|
to the |DBAPI|.
|
2010-02-10 02:09:48 +03:00
|
|
|
|
|
|
|
|
2010-02-09 07:58:28 +03:00
|
|
|
.. data:: apilevel
|
|
|
|
|
2010-02-26 03:17:52 +03:00
|
|
|
String constant stating the supported DB API level. For `psycopg2` is
|
2010-02-09 07:58:28 +03:00
|
|
|
``2.0``.
|
|
|
|
|
|
|
|
.. data:: threadsafety
|
|
|
|
|
|
|
|
Integer constant stating the level of thread safety the interface
|
2010-02-26 03:17:52 +03:00
|
|
|
supports. For `psycopg2` is ``2``, i.e. threads can share the module
|
2010-02-09 07:58:28 +03:00
|
|
|
and the connection. See :ref:`thread-safety` for details.
|
|
|
|
|
|
|
|
.. data:: paramstyle
|
|
|
|
|
|
|
|
String constant stating the type of parameter marker formatting expected
|
2010-02-26 03:17:52 +03:00
|
|
|
by the interface. For `psycopg2` is ``pyformat``. See also
|
2010-02-09 07:58:28 +03:00
|
|
|
:ref:`query-parameters`.
|
|
|
|
|
2015-06-01 19:05:11 +03:00
|
|
|
.. data:: __libpq_version__
|
|
|
|
|
|
|
|
Integer contant containing the version of ``libpq`` this `psycopg2`
|
|
|
|
module was compiled with. If this value is ``>= 90100`` then you
|
|
|
|
may query for the actually loaded version of libpq using
|
|
|
|
`~psycopg2.extensions.libpq_version()`.
|
2010-02-09 07:58:28 +03:00
|
|
|
|
2010-02-11 06:15:14 +03:00
|
|
|
|
2014-08-24 17:57:26 +04:00
|
|
|
.. index::
|
2010-02-11 06:15:14 +03:00
|
|
|
single: Exceptions; DB API
|
|
|
|
|
|
|
|
.. _dbapi-exceptions:
|
2010-02-09 07:58:28 +03:00
|
|
|
|
|
|
|
Exceptions
|
|
|
|
----------
|
|
|
|
|
2010-02-11 06:15:14 +03:00
|
|
|
In compliance with the |DBAPI|_, the module makes informations about errors
|
2010-02-09 07:58:28 +03:00
|
|
|
available through the following exceptions:
|
|
|
|
|
2014-08-24 17:57:26 +04:00
|
|
|
.. exception:: Warning
|
|
|
|
|
2010-02-09 07:58:28 +03:00
|
|
|
Exception raised for important warnings like data truncations while
|
2011-02-19 19:16:28 +03:00
|
|
|
inserting, etc. It is a subclass of the Python `~exceptions.StandardError`.
|
2014-08-24 17:57:26 +04:00
|
|
|
|
|
|
|
.. exception:: Error
|
2010-02-09 07:58:28 +03:00
|
|
|
|
|
|
|
Exception that is the base class of all other error exceptions. You can
|
2011-02-19 19:16:28 +03:00
|
|
|
use this to catch all errors with one single `!except` statement. Warnings
|
2010-03-03 20:43:24 +03:00
|
|
|
are not considered errors and thus not use this class as base. It
|
2011-02-19 19:16:28 +03:00
|
|
|
is a subclass of the Python `!StandardError`.
|
2010-02-13 08:44:49 +03:00
|
|
|
|
|
|
|
.. attribute:: pgerror
|
|
|
|
|
|
|
|
String representing the error message returned by the backend,
|
2011-02-19 19:16:28 +03:00
|
|
|
`!None` if not available.
|
2010-02-13 08:44:49 +03:00
|
|
|
|
|
|
|
.. attribute:: pgcode
|
|
|
|
|
2011-02-19 19:16:28 +03:00
|
|
|
String representing the error code returned by the backend, `!None`
|
2010-02-26 03:17:52 +03:00
|
|
|
if not available. The `~psycopg2.errorcodes` module contains
|
2010-02-13 08:44:49 +03:00
|
|
|
symbolic constants representing PostgreSQL error codes.
|
|
|
|
|
2012-01-19 05:30:46 +04:00
|
|
|
.. doctest::
|
|
|
|
:options: +NORMALIZE_WHITESPACE
|
2010-02-13 08:44:49 +03:00
|
|
|
|
2012-01-19 05:30:46 +04:00
|
|
|
>>> try:
|
|
|
|
... cur.execute("SELECT * FROM barf")
|
2014-08-24 17:57:26 +04:00
|
|
|
... except psycopg2.Error as e:
|
2012-01-19 05:30:46 +04:00
|
|
|
... pass
|
2010-02-13 19:06:39 +03:00
|
|
|
|
2012-01-19 05:30:46 +04:00
|
|
|
>>> e.pgcode
|
|
|
|
'42P01'
|
|
|
|
>>> print e.pgerror
|
|
|
|
ERROR: relation "barf" does not exist
|
|
|
|
LINE 1: SELECT * FROM barf
|
|
|
|
^
|
2014-08-24 17:57:26 +04:00
|
|
|
|
2012-01-19 05:30:46 +04:00
|
|
|
.. attribute:: cursor
|
2010-02-13 08:44:49 +03:00
|
|
|
|
2012-01-19 05:30:46 +04:00
|
|
|
The cursor the exception was raised from; `None` if not applicable.
|
2010-02-13 08:44:49 +03:00
|
|
|
|
2013-03-18 05:33:23 +04:00
|
|
|
.. attribute:: diag
|
|
|
|
|
|
|
|
A `~psycopg2.extensions.Diagnostics` object containing further
|
|
|
|
information about the error. ::
|
|
|
|
|
|
|
|
>>> try:
|
|
|
|
... cur.execute("SELECT * FROM barf")
|
2014-08-24 17:57:26 +04:00
|
|
|
... except psycopg2.Error, e:
|
2013-03-18 05:33:23 +04:00
|
|
|
... pass
|
|
|
|
|
|
|
|
>>> e.diag.severity
|
|
|
|
'ERROR'
|
|
|
|
>>> e.diag.message_primary
|
|
|
|
'relation "barf" does not exist'
|
|
|
|
|
|
|
|
.. versionadded:: 2.5
|
|
|
|
|
2012-01-19 05:30:46 +04:00
|
|
|
.. extension::
|
2010-02-13 08:44:49 +03:00
|
|
|
|
2013-03-18 05:33:23 +04:00
|
|
|
The `~Error.pgerror`, `~Error.pgcode`, `~Error.cursor`, and
|
|
|
|
`~Error.diag` attributes are Psycopg extensions.
|
2010-02-13 08:44:49 +03:00
|
|
|
|
|
|
|
|
2010-02-09 07:58:28 +03:00
|
|
|
.. exception:: InterfaceError
|
|
|
|
|
|
|
|
Exception raised for errors that are related to the database interface
|
2010-02-26 03:17:52 +03:00
|
|
|
rather than the database itself. It is a subclass of `Error`.
|
2010-02-09 07:58:28 +03:00
|
|
|
|
|
|
|
.. exception:: DatabaseError
|
|
|
|
|
|
|
|
Exception raised for errors that are related to the database. It is a
|
2010-02-26 03:17:52 +03:00
|
|
|
subclass of `Error`.
|
2014-08-24 17:57:26 +04:00
|
|
|
|
2010-02-09 07:58:28 +03:00
|
|
|
.. exception:: DataError
|
2014-08-24 17:57:26 +04:00
|
|
|
|
2010-02-09 07:58:28 +03:00
|
|
|
Exception raised for errors that are due to problems with the processed
|
|
|
|
data like division by zero, numeric value out of range, etc. It is a
|
2010-02-26 03:17:52 +03:00
|
|
|
subclass of `DatabaseError`.
|
2014-08-24 17:57:26 +04:00
|
|
|
|
2010-02-09 07:58:28 +03:00
|
|
|
.. exception:: OperationalError
|
2014-08-24 17:57:26 +04:00
|
|
|
|
2010-02-09 07:58:28 +03:00
|
|
|
Exception raised for errors that are related to the database's operation
|
|
|
|
and not necessarily under the control of the programmer, e.g. an
|
|
|
|
unexpected disconnect occurs, the data source name is not found, a
|
|
|
|
transaction could not be processed, a memory allocation error occurred
|
2010-02-26 03:17:52 +03:00
|
|
|
during processing, etc. It is a subclass of `DatabaseError`.
|
2014-08-24 17:57:26 +04:00
|
|
|
|
|
|
|
.. exception:: IntegrityError
|
|
|
|
|
2010-02-09 07:58:28 +03:00
|
|
|
Exception raised when the relational integrity of the database is
|
|
|
|
affected, e.g. a foreign key check fails. It is a subclass of
|
2010-02-26 03:17:52 +03:00
|
|
|
`DatabaseError`.
|
2014-08-24 17:57:26 +04:00
|
|
|
|
|
|
|
.. exception:: InternalError
|
|
|
|
|
2010-02-09 07:58:28 +03:00
|
|
|
Exception raised when the database encounters an internal error, e.g. the
|
|
|
|
cursor is not valid anymore, the transaction is out of sync, etc. It is a
|
2010-02-26 03:17:52 +03:00
|
|
|
subclass of `DatabaseError`.
|
2014-08-24 17:57:26 +04:00
|
|
|
|
2010-02-09 07:58:28 +03:00
|
|
|
.. exception:: ProgrammingError
|
2014-08-24 17:57:26 +04:00
|
|
|
|
2010-02-09 07:58:28 +03:00
|
|
|
Exception raised for programming errors, e.g. table not found or already
|
|
|
|
exists, syntax error in the SQL statement, wrong number of parameters
|
2010-02-26 03:17:52 +03:00
|
|
|
specified, etc. It is a subclass of `DatabaseError`.
|
2014-08-24 17:57:26 +04:00
|
|
|
|
2010-02-09 07:58:28 +03:00
|
|
|
.. exception:: NotSupportedError
|
2014-08-24 17:57:26 +04:00
|
|
|
|
2010-02-09 07:58:28 +03:00
|
|
|
Exception raised in case a method or database API was used which is not
|
2010-02-26 03:17:52 +03:00
|
|
|
supported by the database, e.g. requesting a `!rollback()` on a
|
2010-02-11 06:15:14 +03:00
|
|
|
connection that does not support transaction or has transactions turned
|
2010-02-26 03:17:52 +03:00
|
|
|
off. It is a subclass of `DatabaseError`.
|
2010-02-09 07:58:28 +03:00
|
|
|
|
|
|
|
|
2010-02-11 06:15:14 +03:00
|
|
|
.. extension::
|
|
|
|
|
2010-02-11 06:40:28 +03:00
|
|
|
Psycopg may raise a few other, more specialized, exceptions: currently
|
2010-02-26 03:17:52 +03:00
|
|
|
`~psycopg2.extensions.QueryCanceledError` and
|
|
|
|
`~psycopg2.extensions.TransactionRollbackError` are defined. These
|
|
|
|
exceptions are not exposed by the main `!psycopg2` module but are
|
|
|
|
made available by the `~psycopg2.extensions` module. All the
|
2010-02-11 06:40:28 +03:00
|
|
|
additional exceptions are subclasses of standard |DBAPI| exceptions, so
|
|
|
|
trapping them specifically is not required.
|
2010-02-09 07:58:28 +03:00
|
|
|
|
|
|
|
|
2010-02-11 06:15:14 +03:00
|
|
|
This is the exception inheritance layout:
|
2010-02-09 07:58:28 +03:00
|
|
|
|
2010-02-11 06:15:14 +03:00
|
|
|
.. parsed-literal::
|
2010-02-09 07:58:28 +03:00
|
|
|
|
2011-02-19 19:16:28 +03:00
|
|
|
`!StandardError`
|
2010-02-26 03:17:52 +03:00
|
|
|
\|__ `Warning`
|
|
|
|
\|__ `Error`
|
|
|
|
\|__ `InterfaceError`
|
|
|
|
\|__ `DatabaseError`
|
|
|
|
\|__ `DataError`
|
|
|
|
\|__ `OperationalError`
|
|
|
|
\| \|__ `psycopg2.extensions.QueryCanceledError`
|
|
|
|
\| \|__ `psycopg2.extensions.TransactionRollbackError`
|
|
|
|
\|__ `IntegrityError`
|
|
|
|
\|__ `InternalError`
|
|
|
|
\|__ `ProgrammingError`
|
|
|
|
\|__ `NotSupportedError`
|
|
|
|
|
|
|
|
|
2010-02-09 07:58:28 +03:00
|
|
|
|
2010-02-09 16:33:31 +03:00
|
|
|
.. _type-objects-and-constructors:
|
2010-02-09 07:58:28 +03:00
|
|
|
|
|
|
|
Type Objects and Constructors
|
|
|
|
-----------------------------
|
|
|
|
|
2011-09-22 18:50:50 +04:00
|
|
|
.. note::
|
|
|
|
|
|
|
|
This section is mostly copied verbatim from the |DBAPI|_
|
2010-02-09 07:58:28 +03:00
|
|
|
specification. While these objects are exposed in compliance to the
|
2010-02-10 00:31:40 +03:00
|
|
|
DB API, Psycopg offers very accurate tools to convert data between Python
|
2010-02-09 07:58:28 +03:00
|
|
|
and PostgreSQL formats. See :ref:`adapting-new-types` and
|
|
|
|
:ref:`type-casting-from-sql-to-python`
|
|
|
|
|
|
|
|
Many databases need to have the input in a particular format for
|
|
|
|
binding to an operation's input parameters. For example, if an
|
|
|
|
input is destined for a DATE column, then it must be bound to the
|
|
|
|
database in a particular string format. Similar problems exist
|
|
|
|
for "Row ID" columns or large binary items (e.g. blobs or RAW
|
|
|
|
columns). This presents problems for Python since the parameters
|
|
|
|
to the .execute*() method are untyped. When the database module
|
|
|
|
sees a Python string object, it doesn't know if it should be bound
|
|
|
|
as a simple CHAR column, as a raw BINARY item, or as a DATE.
|
|
|
|
|
|
|
|
To overcome this problem, a module must provide the constructors
|
|
|
|
defined below to create objects that can hold special values.
|
|
|
|
When passed to the cursor methods, the module can then detect the
|
|
|
|
proper type of the input parameter and bind it accordingly.
|
|
|
|
|
|
|
|
A Cursor Object's description attribute returns information about
|
|
|
|
each of the result columns of a query. The type_code must compare
|
|
|
|
equal to one of Type Objects defined below. Type Objects may be
|
|
|
|
equal to more than one type code (e.g. DATETIME could be equal to
|
|
|
|
the type codes for date, time and timestamp columns; see the
|
|
|
|
Implementation Hints below for details).
|
|
|
|
|
|
|
|
The module exports the following constructors and singletons:
|
2012-10-28 01:24:48 +04:00
|
|
|
|
2010-02-09 07:58:28 +03:00
|
|
|
.. function:: Date(year,month,day)
|
|
|
|
|
|
|
|
This function constructs an object holding a date value.
|
2012-10-28 01:24:48 +04:00
|
|
|
|
2010-02-09 07:58:28 +03:00
|
|
|
.. function:: Time(hour,minute,second)
|
|
|
|
|
|
|
|
This function constructs an object holding a time value.
|
2012-10-28 01:24:48 +04:00
|
|
|
|
2010-02-09 07:58:28 +03:00
|
|
|
.. function:: Timestamp(year,month,day,hour,minute,second)
|
|
|
|
|
|
|
|
This function constructs an object holding a time stamp value.
|
|
|
|
|
|
|
|
.. function:: DateFromTicks(ticks)
|
|
|
|
|
|
|
|
This function constructs an object holding a date value from the given
|
|
|
|
ticks value (number of seconds since the epoch; see the documentation of
|
|
|
|
the standard Python time module for details).
|
|
|
|
|
|
|
|
.. function:: TimeFromTicks(ticks)
|
2012-10-28 01:24:48 +04:00
|
|
|
|
2010-02-09 07:58:28 +03:00
|
|
|
This function constructs an object holding a time value from the given
|
|
|
|
ticks value (number of seconds since the epoch; see the documentation of
|
|
|
|
the standard Python time module for details).
|
2012-10-28 01:24:48 +04:00
|
|
|
|
2010-02-09 07:58:28 +03:00
|
|
|
.. function:: TimestampFromTicks(ticks)
|
|
|
|
|
|
|
|
This function constructs an object holding a time stamp value from the
|
|
|
|
given ticks value (number of seconds since the epoch; see the
|
|
|
|
documentation of the standard Python time module for details).
|
|
|
|
|
|
|
|
.. function:: Binary(string)
|
2012-10-28 01:24:48 +04:00
|
|
|
|
2010-02-09 07:58:28 +03:00
|
|
|
This function constructs an object capable of holding a binary (long)
|
|
|
|
string value.
|
2012-10-28 01:24:48 +04:00
|
|
|
|
|
|
|
.. note::
|
|
|
|
|
|
|
|
All the adapters returned by the module level factories (`!Binary`,
|
|
|
|
`!Date`, `!Time`, `!Timestamp` and the `!*FromTicks` variants) expose the
|
|
|
|
wrapped object (a regular Python object such as `!datetime`) in an
|
|
|
|
`!adapted` attribute.
|
2010-02-09 07:58:28 +03:00
|
|
|
|
|
|
|
.. data:: STRING
|
|
|
|
|
|
|
|
This type object is used to describe columns in a database that are
|
|
|
|
string-based (e.g. CHAR).
|
|
|
|
|
|
|
|
.. data:: BINARY
|
|
|
|
|
|
|
|
This type object is used to describe (long) binary columns in a database
|
|
|
|
(e.g. LONG, RAW, BLOBs).
|
2012-10-28 01:24:48 +04:00
|
|
|
|
2010-02-09 07:58:28 +03:00
|
|
|
.. data:: NUMBER
|
|
|
|
|
|
|
|
This type object is used to describe numeric columns in a database.
|
|
|
|
|
|
|
|
.. data:: DATETIME
|
2012-10-28 01:24:48 +04:00
|
|
|
|
2010-02-09 07:58:28 +03:00
|
|
|
This type object is used to describe date/time columns in a database.
|
2012-10-28 01:24:48 +04:00
|
|
|
|
2010-02-09 07:58:28 +03:00
|
|
|
.. data:: ROWID
|
2012-10-28 01:24:48 +04:00
|
|
|
|
2010-02-09 07:58:28 +03:00
|
|
|
This type object is used to describe the "Row ID" column in a database.
|
|
|
|
|
2010-04-20 02:51:42 +04:00
|
|
|
|
|
|
|
.. testcode::
|
|
|
|
:hide:
|
|
|
|
|
|
|
|
conn.rollback()
|