first commit based on psycopg2 2.9 version

This commit is contained in:
lishifu_db
2021-07-05 21:34:17 +08:00
parent d126b6ec53
commit 3553ed0e30
178 changed files with 51253 additions and 0 deletions

99
doc/src/Makefile Normal file
View File

@ -0,0 +1,99 @@
# Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = _build
# DSN for the doctest database
PSYCOPG2_DSN="user=postgres dbname=test"
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
clean:
-rm -rf $(BUILDDIR)/*
-rm -rf ./html/*
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text pages are in $(BUILDDIR)/text."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/psycopg.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/psycopg.qhc"
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
"run these through (pdf)latex."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
PSYCOPG2_DSN=$(PSYCOPG2_DSN) \
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."

136
doc/src/_static/psycopg.css Normal file
View File

@ -0,0 +1,136 @@
blockquote {
font-style: italic;
}
div.admonition-todo {
background-color: #ffa;
border: 1px solid #ee2;
}
div.dbapi-extension {
background-color: #eef;
border: 1px solid #aaf;
}
code.sql,
tt.sql {
font-size: 1em;
background-color: transparent;
}
a > code.sql,
a > tt.sql {
font-weight: normal;
}
a > code.sql:hover,
a > tt.sql:hover {
text-decoration: underline;
}
dl.faq dt {
font-weight: bold;
}
table.data-types div.line-block {
margin-bottom: 0;
}
/* better theme customisation */
body {
background-color: #216464;
}
header, .related, .document, footer {
background-color: white;
}
header h1 {
font-size: 150%;
margin-bottom: 0;
padding: 0.5rem 10px 0.5rem 10px;
}
h1, h2, h3 {
font-weight: normal;
}
.body h1, .body h2, .body h3 {
color: #074848;
}
h1 {
font-size: 200%;
}
h2 {
font-size: 160%;
}
h3 {
font-size: 140%;
}
footer#pagefooter {
margin-bottom: 1rem;
font-size: 85%;
color: #444;
}
#rellinks, #breadcrumbs {
padding-right: 10px;
padding-left: 10px;
}
.sphinxsidebar {
padding-left: 10px;
}
.bodywrapper {
padding-right: 10px;
}
div.body h1, div.body h2, div.body h3 {
background-color: #f2f2f2;
border-bottom: 1px solid #d0d0d0;
}
div.body p.rubric {
border-bottom: 1px solid #d0d0d0;
}
body .sphinxsidebar .search {
margin-top: 0;
}
html pre {
background-color: #efc;
border: 1px solid #ac9;
border-left: none;
border-right: none;
}
a, a:visited {
color: #0b6868;
}
th {
background-color: #ede;
}
code.xref, a code {
font-weight: bold;
}
code.descname {
font-weight: bold;
font-size: 120%;
}
@media (max-width: 820px) {
body {
background-color: white;
}
}

View File

@ -0,0 +1,6 @@
{# Add a title over the search box #}
{%- if pagename != "search" %}
<h3>Quick search</h3>
{%- include "!searchbox.html" %}
{%- endif %}

599
doc/src/advanced.rst Normal file
View File

@ -0,0 +1,599 @@
More advanced topics
====================
.. sectionauthor:: Daniele Varrazzo <daniele.varrazzo@gmail.com>
.. testsetup:: *
import re
import select
cur.execute("CREATE TABLE atable (apoint point)")
conn.commit()
def wait(conn):
while True:
state = conn.poll()
if state == psycopg2.extensions.POLL_OK:
break
elif state == psycopg2.extensions.POLL_WRITE:
select.select([], [conn.fileno()], [])
elif state == psycopg2.extensions.POLL_READ:
select.select([conn.fileno()], [], [])
else:
raise psycopg2.OperationalError("poll() returned %s" % state)
aconn = psycopg2.connect(database='test', async=1)
wait(aconn)
acurs = aconn.cursor()
.. index::
double: Subclassing; Cursor
double: Subclassing; Connection
.. _subclassing-connection:
.. _subclassing-cursor:
Connection and cursor factories
-------------------------------
Psycopg exposes two new-style classes that can be sub-classed and expanded to
adapt them to the needs of the programmer: `psycopg2.extensions.cursor`
and `psycopg2.extensions.connection`. The `connection` class is
usually sub-classed only to provide an easy way to create customized cursors
but other uses are possible. `cursor` is much more interesting, because
it is the class where query building, execution and result type-casting into
Python variables happens.
The `~psycopg2.extras` module contains several examples of :ref:`connection
and cursor subclasses <cursor-subclasses>`.
.. note::
If you only need a customized cursor class, since Psycopg 2.5 you can use
the `~connection.cursor_factory` parameter of a regular connection instead
of creating a new `!connection` subclass.
.. index::
single: Example; Cursor subclass
An example of cursor subclass performing logging is::
import psycopg2
import psycopg2.extensions
import logging
class LoggingCursor(psycopg2.extensions.cursor):
def execute(self, sql, args=None):
logger = logging.getLogger('sql_debug')
logger.info(self.mogrify(sql, args))
try:
psycopg2.extensions.cursor.execute(self, sql, args)
except Exception, exc:
logger.error("%s: %s" % (exc.__class__.__name__, exc))
raise
conn = psycopg2.connect(DSN)
cur = conn.cursor(cursor_factory=LoggingCursor)
cur.execute("INSERT INTO mytable VALUES (%s, %s, %s);",
(10, 20, 30))
.. index::
single: Objects; Creating new adapters
single: Adaptation; Creating new adapters
single: Data types; Creating new adapters
.. _adapting-new-types:
Adapting new Python types to SQL syntax
---------------------------------------
Any Python class or type can be adapted to an SQL string. Adaptation mechanism
is similar to the Object Adaptation proposed in the :pep:`246` and is exposed
by the `psycopg2.extensions.adapt()` function.
The `~cursor.execute()` method adapts its arguments to the
`~psycopg2.extensions.ISQLQuote` protocol. Objects that conform to this
protocol expose a `!getquoted()` method returning the SQL representation
of the object as a string (the method must return `!bytes` in Python 3).
Optionally the conform object may expose a
`~psycopg2.extensions.ISQLQuote.prepare()` method.
There are two basic ways to have a Python object adapted to SQL:
- the object itself is conform, or knows how to make itself conform. Such
object must expose a `__conform__()` method that will be called with the
protocol object as argument. The object can check that the protocol is
`!ISQLQuote`, in which case it can return `!self` (if the object also
implements `!getquoted()`) or a suitable wrapper object. This option is
viable if you are the author of the object and if the object is specifically
designed for the database (i.e. having Psycopg as a dependency and polluting
its interface with the required methods doesn't bother you). For a simple
example you can take a look at the source code for the
`psycopg2.extras.Inet` object.
- If implementing the `!ISQLQuote` interface directly in the object is not an
option (maybe because the object to adapt comes from a third party library),
you can use an *adaptation function*, taking the object to be adapted as
argument and returning a conforming object. The adapter must be
registered via the `~psycopg2.extensions.register_adapter()` function. A
simple example wrapper is `!psycopg2.extras.UUID_adapter` used by the
`~psycopg2.extras.register_uuid()` function.
A convenient object to write adapters is the `~psycopg2.extensions.AsIs`
wrapper, whose `!getquoted()` result is simply the `!str()`\ ing conversion of
the wrapped object.
.. index::
single: Example; Types adaptation
Example: mapping of a `!Point` class into the |point|_ PostgreSQL
geometric type:
.. doctest::
>>> from psycopg2.extensions import adapt, register_adapter, AsIs
>>> class Point(object):
... def __init__(self, x, y):
... self.x = x
... self.y = y
>>> def adapt_point(point):
... x = adapt(point.x).getquoted()
... y = adapt(point.y).getquoted()
... return AsIs("'(%s, %s)'" % (x, y))
>>> register_adapter(Point, adapt_point)
>>> cur.execute("INSERT INTO atable (apoint) VALUES (%s)",
... (Point(1.23, 4.56),))
.. |point| replace:: :sql:`point`
.. _point: https://www.postgresql.org/docs/current/static/datatype-geometric.html#DATATYPE-GEOMETRIC
The above function call results in the SQL command::
INSERT INTO atable (apoint) VALUES ('(1.23, 4.56)');
.. index:: Type casting
.. _type-casting-from-sql-to-python:
Type casting of SQL types into Python objects
---------------------------------------------
PostgreSQL objects read from the database can be adapted to Python objects
through an user-defined adapting function. An adapter function takes two
arguments: the object string representation as returned by PostgreSQL and the
cursor currently being read, and should return a new Python object. For
example, the following function parses the PostgreSQL :sql:`point`
representation into the previously defined `!Point` class:
>>> def cast_point(value, cur):
... if value is None:
... return None
...
... # Convert from (f1, f2) syntax using a regular expression.
... m = re.match(r"\(([^)]+),([^)]+)\)", value)
... if m:
... return Point(float(m.group(1)), float(m.group(2)))
... else:
... raise InterfaceError("bad point representation: %r" % value)
In order to create a mapping from a PostgreSQL type (either standard or
user-defined), its OID must be known. It can be retrieved either by the second
column of the `cursor.description`:
>>> cur.execute("SELECT NULL::point")
>>> point_oid = cur.description[0][1]
>>> point_oid
600
or by querying the system catalog for the type name and namespace (the
namespace for system objects is :sql:`pg_catalog`):
>>> cur.execute("""
... SELECT pg_type.oid
... FROM pg_type JOIN pg_namespace
... ON typnamespace = pg_namespace.oid
... WHERE typname = %(typename)s
... AND nspname = %(namespace)s""",
... {'typename': 'point', 'namespace': 'pg_catalog'})
>>> point_oid = cur.fetchone()[0]
>>> point_oid
600
After you know the object OID, you can create and register the new type:
>>> POINT = psycopg2.extensions.new_type((point_oid,), "POINT", cast_point)
>>> psycopg2.extensions.register_type(POINT)
The `~psycopg2.extensions.new_type()` function binds the object OIDs
(more than one can be specified) to the adapter function.
`~psycopg2.extensions.register_type()` completes the spell. Conversion
is automatically performed when a column whose type is a registered OID is
read:
>>> cur.execute("SELECT '(10.2,20.3)'::point")
>>> point = cur.fetchone()[0]
>>> print type(point), point.x, point.y
<class 'Point'> 10.2 20.3
A typecaster created by `!new_type()` can be also used with
`~psycopg2.extensions.new_array_type()` to create a typecaster converting a
PostgreSQL array into a Python list.
.. index::
pair: Asynchronous; Notifications
pair: LISTEN; SQL command
pair: NOTIFY; SQL command
.. _async-notify:
Asynchronous notifications
--------------------------
Psycopg allows asynchronous interaction with other database sessions using the
facilities offered by PostgreSQL commands |LISTEN|_ and |NOTIFY|_. Please
refer to the PostgreSQL documentation for examples about how to use this form of
communication.
Notifications are instances of the `~psycopg2.extensions.Notify` object made
available upon reception in the `connection.notifies` list. Notifications can
be sent from Python code simply executing a :sql:`NOTIFY` command in an
`~cursor.execute()` call.
Because of the way sessions interact with notifications (see |NOTIFY|_
documentation), you should keep the connection in `~connection.autocommit`
mode if you wish to receive or send notifications in a timely manner.
.. |LISTEN| replace:: :sql:`LISTEN`
.. _LISTEN: https://www.postgresql.org/docs/current/static/sql-listen.html
.. |NOTIFY| replace:: :sql:`NOTIFY`
.. _NOTIFY: https://www.postgresql.org/docs/current/static/sql-notify.html
Notifications are received after every query execution. If the user is
interested in receiving notifications but not in performing any query, the
`~connection.poll()` method can be used to check for new messages without
wasting resources.
A simple application could poll the connection from time to time to check if
something new has arrived. A better strategy is to use some I/O completion
function such as :py:func:`~select.select` to sleep until awakened by the kernel when there is
some data to read on the connection, thereby using no CPU unless there is
something to read::
import select
import psycopg2
import psycopg2.extensions
conn = psycopg2.connect(DSN)
conn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
curs = conn.cursor()
curs.execute("LISTEN test;")
print "Waiting for notifications on channel 'test'"
while True:
if select.select([conn],[],[],5) == ([],[],[]):
print "Timeout"
else:
conn.poll()
while conn.notifies:
notify = conn.notifies.pop(0)
print "Got NOTIFY:", notify.pid, notify.channel, notify.payload
Running the script and executing a command such as :sql:`NOTIFY test, 'hello'`
in a separate :program:`psql` shell, the output may look similar to:
.. code-block:: none
Waiting for notifications on channel 'test'
Timeout
Timeout
Got NOTIFY: 6535 test hello
Timeout
...
Note that the payload is only available from PostgreSQL 9.0: notifications
received from a previous version server will have the
`~psycopg2.extensions.Notify.payload` attribute set to the empty string.
.. versionchanged:: 2.3
Added `~psycopg2.extensions.Notify` object and handling notification
payload.
.. versionchanged:: 2.7
The `~connection.notifies` attribute is writable: it is possible to
replace it with any object exposing an `!append()` method. An useful
example would be to use a `~collections.deque` object.
.. index::
double: Asynchronous; Connection
.. _async-support:
Asynchronous support
--------------------
.. versionadded:: 2.2
Psycopg can issue asynchronous queries to a PostgreSQL database. An asynchronous
communication style is established passing the parameter *async*\=1 to the
`~psycopg2.connect()` function: the returned connection will work in
*asynchronous mode*.
In asynchronous mode, a Psycopg connection will rely on the caller to poll the
socket file descriptor, checking if it is ready to accept data or if a query
result has been transferred and is ready to be read on the client. The caller
can use the method `~connection.fileno()` to get the connection file
descriptor and `~connection.poll()` to make communication proceed according to
the current connection state.
The following is an example loop using methods `!fileno()` and `!poll()`
together with the Python :py:func:`~select.select` function in order to carry on
asynchronous operations with Psycopg::
def wait(conn):
while True:
state = conn.poll()
if state == psycopg2.extensions.POLL_OK:
break
elif state == psycopg2.extensions.POLL_WRITE:
select.select([], [conn.fileno()], [])
elif state == psycopg2.extensions.POLL_READ:
select.select([conn.fileno()], [], [])
else:
raise psycopg2.OperationalError("poll() returned %s" % state)
The above loop of course would block an entire application: in a real
asynchronous framework, `!select()` would be called on many file descriptors
waiting for any of them to be ready. Nonetheless the function can be used to
connect to a PostgreSQL server only using nonblocking commands and the
connection obtained can be used to perform further nonblocking queries. After
`!poll()` has returned `~psycopg2.extensions.POLL_OK`, and thus `!wait()` has
returned, the connection can be safely used:
>>> aconn = psycopg2.connect(database='test', async=1)
>>> wait(aconn)
>>> acurs = aconn.cursor()
Note that there are a few other requirements to be met in order to have a
completely non-blocking connection attempt: see the libpq documentation for
|PQconnectStart|_.
.. |PQconnectStart| replace:: `!PQconnectStart()`
.. _PQconnectStart: https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-PQCONNECTSTARTPARAMS
The same loop should be also used to perform nonblocking queries: after
sending a query via `~cursor.execute()` or `~cursor.callproc()`, call
`!poll()` on the connection available from `cursor.connection` until it
returns `!POLL_OK`, at which point the query has been completely sent to the
server and, if it produced data, the results have been transferred to the
client and available using the regular cursor methods:
>>> acurs.execute("SELECT pg_sleep(5); SELECT 42;")
>>> wait(acurs.connection)
>>> acurs.fetchone()[0]
42
When an asynchronous query is being executed, `connection.isexecuting()` returns
`!True`. Two cursors can't execute concurrent queries on the same asynchronous
connection.
There are several limitations in using asynchronous connections: the
connection is always in `~connection.autocommit` mode and it is not
possible to change it. So a
transaction is not implicitly started at the first query and is not possible
to use methods `~connection.commit()` and `~connection.rollback()`: you can
manually control transactions using `~cursor.execute()` to send database
commands such as :sql:`BEGIN`, :sql:`COMMIT` and :sql:`ROLLBACK`. Similarly
`~connection.set_session()` can't be used but it is still possible to invoke the
:sql:`SET` command with the proper :sql:`default_transaction_...` parameter.
With asynchronous connections it is also not possible to use
`~connection.set_client_encoding()`, `~cursor.executemany()`, :ref:`large
objects <large-objects>`, :ref:`named cursors <server-side-cursors>`.
:ref:`COPY commands <copy>` are not supported either in asynchronous mode, but
this will be probably implemented in a future release.
.. index::
single: Greenlet
single: Coroutine
single: Eventlet
single: gevent
single: Wait callback
.. _green-support:
Support for coroutine libraries
-------------------------------
.. versionadded:: 2.2
Psycopg can be used together with coroutine_\-based libraries and participate
in cooperative multithreading.
Coroutine-based libraries (such as Eventlet_ or gevent_) can usually patch the
Python standard library in order to enable a coroutine switch in the presence of
blocking I/O: the process is usually referred as making the system *green*, in
reference to the `green threads`_.
Because Psycopg is a C extension module, it is not possible for coroutine
libraries to patch it: Psycopg instead enables cooperative multithreading by
allowing the registration of a *wait callback* using the
`psycopg2.extensions.set_wait_callback()` function. When a wait callback is
registered, Psycopg will use `libpq non-blocking calls`__ instead of the regular
blocking ones, and will delegate to the callback the responsibility to wait
for the socket to become readable or writable.
Working this way, the caller does not have the complete freedom to schedule the
socket check whenever they want as with an :ref:`asynchronous connection
<async-support>`, but has the advantage of maintaining a complete |DBAPI|
semantics: from the point of view of the end user, all Psycopg functions and
objects will work transparently in the coroutine environment (blocking the
calling green thread and giving other green threads the possibility to be
scheduled), allowing non modified code and third party libraries (such as
SQLAlchemy_) to be used in coroutine-based programs.
.. warning::
Psycopg connections are not *green thread safe* and can't be used
concurrently by different green threads. Trying to execute more than one
command at time using one cursor per thread will result in an error (or a
deadlock on versions before 2.4.2).
Therefore, programmers are advised to either avoid sharing connections
between coroutines or to use a library-friendly lock to synchronize shared
connections, e.g. for pooling.
Coroutine libraries authors should provide a callback implementation (and
possibly a method to register it) to make Psycopg as green as they want. An
example callback (using `!select()` to block) is provided as
`psycopg2.extras.wait_select()`: it boils down to something similar to::
def wait_select(conn):
while True:
state = conn.poll()
if state == extensions.POLL_OK:
break
elif state == extensions.POLL_READ:
select.select([conn.fileno()], [], [])
elif state == extensions.POLL_WRITE:
select.select([], [conn.fileno()], [])
else:
raise OperationalError("bad state from poll: %s" % state)
Providing callback functions for the single coroutine libraries is out of
psycopg2 scope, as the callback can be tied to the libraries' implementation
details. You can check the `psycogreen`_ project for further informations and
resources about the topic.
.. _coroutine: https://en.wikipedia.org/wiki/Coroutine
.. _greenlet: https://pypi.org/project/greenlet/
.. _green threads: https://en.wikipedia.org/wiki/Green_threads
.. _Eventlet: https://eventlet.net/
.. _gevent: http://www.gevent.org/
.. _SQLAlchemy: https://www.sqlalchemy.org/
.. _psycogreen: https://github.com/psycopg/psycogreen/
.. __: https://www.postgresql.org/docs/current/static/libpq-async.html
.. warning::
:ref:`COPY commands <copy>` are currently not supported when a wait callback
is registered, but they will be probably implemented in a future release.
:ref:`Large objects <large-objects>` are not supported either: they are
not compatible with asynchronous connections.
.. testcode::
:hide:
aconn.close()
conn.rollback()
cur.execute("DROP TABLE atable")
conn.commit()
cur.close()
conn.close()
.. index::
single: Replication
.. _replication-support:
Replication protocol support
----------------------------
.. versionadded:: 2.7
Modern PostgreSQL servers (version 9.0 and above) support replication. The
replication protocol is built on top of the client-server protocol and can be
operated using ``libpq``, as such it can be also operated by ``psycopg2``.
The replication protocol can be operated on both synchronous and
:ref:`asynchronous <async-support>` connections.
Server version 9.4 adds a new feature called *Logical Replication*.
.. seealso::
- PostgreSQL `Streaming Replication Protocol`__
.. __: https://www.postgresql.org/docs/current/static/protocol-replication.html
Logical replication Quick-Start
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
You must be using PostgreSQL server version 9.4 or above to run this quick
start.
Make sure that replication connections are permitted for user ``postgres`` in
``pg_hba.conf`` and reload the server configuration. You also need to set
``wal_level=logical`` and ``max_wal_senders``, ``max_replication_slots`` to
value greater than zero in ``postgresql.conf`` (these changes require a server
restart). Create a database ``psycopg2_test``.
Then run the following code to quickly try the replication support out. This
is not production code -- it's only intended as a simple demo of logical
replication::
from __future__ import print_function
import sys
import psycopg2
import psycopg2.extras
conn = psycopg2.connect('dbname=psycopg2_test user=postgres',
connection_factory=psycopg2.extras.LogicalReplicationConnection)
cur = conn.cursor()
try:
# test_decoding produces textual output
cur.start_replication(slot_name='pytest', decode=True)
except psycopg2.ProgrammingError:
cur.create_replication_slot('pytest', output_plugin='test_decoding')
cur.start_replication(slot_name='pytest', decode=True)
class DemoConsumer(object):
def __call__(self, msg):
print(msg.payload)
msg.cursor.send_feedback(flush_lsn=msg.data_start)
democonsumer = DemoConsumer()
print("Starting streaming, press Control-C to end...", file=sys.stderr)
try:
cur.consume_stream(democonsumer)
except KeyboardInterrupt:
cur.close()
conn.close()
print("The slot 'pytest' still exists. Drop it with "
"SELECT pg_drop_replication_slot('pytest'); if no longer needed.",
file=sys.stderr)
print("WARNING: Transaction logs will accumulate in pg_xlog "
"until the slot is dropped.", file=sys.stderr)
You can now make changes to the ``psycopg2_test`` database using a normal
psycopg2 session, ``psql``, etc. and see the logical decoding stream printed
by this demo client.
This will continue running until terminated with ``Control-C``.
For the details see :ref:`replication-objects`.

288
doc/src/conf.py Normal file
View File

@ -0,0 +1,288 @@
#
# Psycopg documentation build configuration file, created by
# sphinx-quickstart on Sun Feb 7 13:48:41 2010.
#
# This file is execfile()d with the current directory set to its containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import os
import sys
from better import better_theme_path
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
sys.path.append(os.path.abspath('tools/lib'))
# -- General configuration -----------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.todo',
'sphinx.ext.ifconfig',
'sphinx.ext.doctest',
'sphinx.ext.intersphinx',
]
# Specific extensions for Psycopg documentation.
extensions += ['dbapi_extension', 'sql_role', 'ticket_role']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix of source filenames.
source_suffix = '.rst'
# The encoding of source files.
# source_encoding = 'utf-8'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = 'Psycopg'
copyright = (
'2001-2021, Federico Di Gregorio, Daniele Varrazzo, The Psycopg Team'
)
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '2.0'
# The full version, including alpha/beta/rc tags.
try:
import psycopg2
except ImportError:
print("WARNING: couldn't import psycopg to read version.")
release = version
else:
release = psycopg2.__version__.split()[0]
version = '.'.join(release.split('.')[:2])
intersphinx_mapping = {'py': ('https://docs.python.org/3', None)}
# Pattern to generate links to the bug tracker
ticket_url = 'https://github.com/psycopg/psycopg2/issues/%s'
ticket_remap_until = 25
ticket_remap_offset = 230
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
# language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
# today = ''
# Else, today_fmt is used as the format for a strftime call.
# today_fmt = '%B %d, %Y'
# List of documents that shouldn't be included in the build.
# unused_docs = []
# List of directories, relative to source directory, that shouldn't be searched
# for source files.
exclude_trees = ['_build', 'html']
# The reST default role (used for this markup: `text`) to use for all documents.
default_role = 'obj'
# If true, '()' will be appended to :func: etc. cross-reference text.
# add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
# add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
# show_authors = False
# Using 'python' instead of the default gives warnings if parsing an example
# fails, instead of defaulting to none
highlight_language = 'python'
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
# modindex_common_prefix = []
# Include TODO items in the documentation
todo_include_todos = False
rst_epilog = """
.. |DBAPI| replace:: DB API 2.0
.. _DBAPI: https://www.python.org/dev/peps/pep-0249/
.. _transaction isolation level:
https://www.postgresql.org/docs/current/static/transaction-iso.html
.. |MVCC| replace:: :abbr:`MVCC (Multiversion concurrency control)`
"""
# -- Options for HTML output ---------------------------------------------------
# The theme to use for HTML and HTML Help pages. Major themes that come with
# Sphinx are currently 'default' and 'sphinxdoc'.
html_theme = 'better'
# The stylesheet to use with HTML output: this will include the original one
# adding a few classes.
# html_style = 'psycopg.css'
# Hide the sphinx footer
html_show_sphinx = False
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
html_theme_options = {
'linktotheme': False,
'cssfiles': ['_static/psycopg.css'],
}
# Add any paths that contain custom themes here, relative to this directory.
html_theme_path = [better_theme_path]
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
# html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
html_short_title = 'Home'
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
# html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
# html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
# html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
# html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
# no need for the prev/next topic link using better theme: they are on top
html_sidebars = {
'**': ['localtoc.html', 'searchbox.html'],
}
# Additional templates that should be rendered to pages, maps page names to
# template names.
# html_additional_pages = {}
# If false, no module index is generated.
# html_use_modindex = True
# If false, no index is generated.
# html_use_index = True
# If true, the index is split into individual pages for each letter.
# html_split_index = False
# If true, links to the reST sources are added to the pages.
# html_show_sourcelink = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
# html_use_opensearch = ''
# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
# html_file_suffix = ''
# Output file base name for HTML help builder.
htmlhelp_basename = 'psycopgdoc'
# -- Options for LaTeX output --------------------------------------------------
# The paper size ('letter' or 'a4').
# latex_paper_size = 'letter'
# The font size ('10pt', '11pt' or '12pt').
# latex_font_size = '10pt'
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
(
'index',
'psycopg.tex',
'Psycopg Documentation',
'Federico Di Gregorio',
'manual',
)
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
# latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
# latex_use_parts = False
# Additional stuff for the LaTeX preamble.
# latex_preamble = ''
# Documents to append as an appendix to all manuals.
# latex_appendices = []
# If false, no module index is generated.
# latex_use_modindex = True
doctest_global_setup = """
import os
import psycopg2
def test_connect():
try:
dsn = os.environ['PSYCOPG2_DSN']
except KeyError:
assert False, "You need to set the environment variable PSYCOPG2_DSN" \
" in order to test the documentation!"
return psycopg2.connect(dsn)
conn = test_connect()
cur = conn.cursor()
def drop_test_table(name):
cur.execute("SAVEPOINT drop_test_table;")
try:
cur.execute("DROP TABLE %s;" % name)
except:
cur.execute("ROLLBACK TO SAVEPOINT drop_test_table;")
conn.commit()
def create_test_table():
drop_test_table('test')
cur.execute("CREATE TABLE test (id SERIAL PRIMARY KEY, num INT, data TEXT)")
conn.commit()
"""

916
doc/src/connection.rst Normal file
View File

@ -0,0 +1,916 @@
The ``connection`` class
========================
.. sectionauthor:: Daniele Varrazzo <daniele.varrazzo@gmail.com>
.. testsetup::
from pprint import pprint
import psycopg2.extensions
drop_test_table('foo')
.. class:: connection
Handles the connection to a PostgreSQL database instance. It encapsulates
a database session.
Connections are created using the factory function
`~psycopg2.connect()`.
Connections are thread safe and can be shared among many threads. See
:ref:`thread-safety` for details.
Connections can be used as context managers. Note that a context wraps a
transaction: if the context exits with success the transaction is
committed, if it exits with an exception the transaction is rolled back.
Note that the connection is not closed by the context and it can be used
for several contexts.
.. code:: python
conn = psycopg2.connect(DSN)
with conn:
with conn.cursor() as curs:
curs.execute(SQL1)
with conn:
with conn.cursor() as curs:
curs.execute(SQL2)
# leaving contexts doesn't close the connection
conn.close()
.. method:: cursor(name=None, cursor_factory=None, scrollable=None, withhold=False)
Return a new `cursor` object using the connection.
If *name* is specified, the returned cursor will be a :ref:`server
side cursor <server-side-cursors>` (also known as *named cursor*).
Otherwise it will be a regular *client side* cursor. By default a
named cursor is declared without :sql:`SCROLL` option and
:sql:`WITHOUT HOLD`: set the argument or property `~cursor.scrollable`
to `!True`/`!False` and or `~cursor.withhold` to `!True` to change the
declaration.
The name can be a string not valid as a PostgreSQL identifier: for
example it may start with a digit and contain non-alphanumeric
characters and quotes.
.. versionchanged:: 2.4
previously only valid PostgreSQL identifiers were accepted as
cursor name.
The *cursor_factory* argument can be used to create non-standard
cursors. The class returned must be a subclass of
`psycopg2.extensions.cursor`. See :ref:`subclassing-cursor` for
details. A default factory for the connection can also be specified
using the `~connection.cursor_factory` attribute.
.. versionchanged:: 2.4.3 added the *withhold* argument.
.. versionchanged:: 2.5 added the *scrollable* argument.
.. extension::
All the function arguments are Psycopg extensions to the |DBAPI|.
.. index::
pair: Transaction; Commit
.. method:: commit()
Commit any pending transaction to the database.
By default, Psycopg opens a transaction before executing the first
command: if `!commit()` is not called, the effect of any data
manipulation will be lost.
The connection can be also set in "autocommit" mode: no transaction is
automatically open, commands have immediate effect. See
:ref:`transactions-control` for details.
.. versionchanged:: 2.5 if the connection is used in a ``with``
statement, the method is automatically called if no exception is
raised in the ``with`` block.
.. index::
pair: Transaction; Rollback
.. method:: rollback()
Roll back to the start of any pending transaction. Closing a
connection without committing the changes first will cause an implicit
rollback to be performed.
.. versionchanged:: 2.5 if the connection is used in a ``with``
statement, the method is automatically called if an exception is
raised in the ``with`` block.
.. method:: close()
Close the connection now (rather than whenever `del` is executed).
The connection will be unusable from this point forward; an
`~psycopg2.InterfaceError` will be raised if any operation is
attempted with the connection. The same applies to all cursor objects
trying to use the connection. Note that closing a connection without
committing the changes first will cause any pending change to be
discarded as if a :sql:`ROLLBACK` was performed (unless a different
isolation level has been selected: see
`~connection.set_isolation_level()`).
.. index::
single: PgBouncer; unclean server
.. versionchanged:: 2.2
previously an explicit :sql:`ROLLBACK` was issued by Psycopg on
`!close()`. The command could have been sent to the backend at an
inappropriate time, so Psycopg currently relies on the backend to
implicitly discard uncommitted changes. Some middleware are known
to behave incorrectly though when the connection is closed during
a transaction (when `~connection.status` is
`~psycopg2.extensions.STATUS_IN_TRANSACTION`), e.g. PgBouncer_
reports an ``unclean server`` and discards the connection. To
avoid this problem you can ensure to terminate the transaction
with a `~connection.commit()`/`~connection.rollback()` before
closing.
.. _PgBouncer: http://www.pgbouncer.org/
.. index::
single: Exceptions; In the connection class
.. rubric:: Exceptions as connection class attributes
The `!connection` also exposes as attributes the same exceptions
available in the `psycopg2` module. See :ref:`dbapi-exceptions`.
.. index::
single: Two-phase commit; methods
.. rubric:: Two-phase commit support methods
.. versionadded:: 2.3
.. seealso:: :ref:`tpc` for an introductory explanation of these methods.
Note that PostgreSQL supports two-phase commit since release 8.1: these
methods raise `~psycopg2.NotSupportedError` if used with an older version
server.
.. _tpc_methods:
.. method:: xid(format_id, gtrid, bqual)
Returns a `~psycopg2.extensions.Xid` instance to be passed to the
`!tpc_*()` methods of this connection. The argument types and
constraints are explained in :ref:`tpc`.
The values passed to the method will be available on the returned
object as the members `~psycopg2.extensions.Xid.format_id`,
`~psycopg2.extensions.Xid.gtrid`, `~psycopg2.extensions.Xid.bqual`.
The object also allows accessing to these members and unpacking as a
3-items tuple.
.. method:: tpc_begin(xid)
Begins a TPC transaction with the given transaction ID *xid*.
This method should be called outside of a transaction (i.e. nothing
may have executed since the last `~connection.commit()` or
`~connection.rollback()` and `connection.status` is
`~psycopg2.extensions.STATUS_READY`).
Furthermore, it is an error to call `!commit()` or `!rollback()`
within the TPC transaction: in this case a `~psycopg2.ProgrammingError`
is raised.
The *xid* may be either an object returned by the `~connection.xid()`
method or a plain string: the latter allows to create a transaction
using the provided string as PostgreSQL transaction id. See also
`~connection.tpc_recover()`.
.. index::
pair: Transaction; Prepare
.. method:: tpc_prepare()
Performs the first phase of a transaction started with
`~connection.tpc_begin()`. A `~psycopg2.ProgrammingError` is raised if
this method is used outside of a TPC transaction.
After calling `!tpc_prepare()`, no statements can be executed until
`~connection.tpc_commit()` or `~connection.tpc_rollback()` will be
called. The `~connection.reset()` method can be used to restore the
status of the connection to `~psycopg2.extensions.STATUS_READY`: the
transaction will remain prepared in the database and will be
possible to finish it with `!tpc_commit(xid)` and
`!tpc_rollback(xid)`.
.. seealso:: the |PREPARE TRANSACTION|_ PostgreSQL command.
.. |PREPARE TRANSACTION| replace:: :sql:`PREPARE TRANSACTION`
.. _PREPARE TRANSACTION: https://www.postgresql.org/docs/current/static/sql-prepare-transaction.html
.. index::
pair: Commit; Prepared
.. method:: tpc_commit([xid])
When called with no arguments, `!tpc_commit()` commits a TPC
transaction previously prepared with `~connection.tpc_prepare()`.
If `!tpc_commit()` is called prior to `!tpc_prepare()`, a single phase
commit is performed. A transaction manager may choose to do this if
only a single resource is participating in the global transaction.
When called with a transaction ID *xid*, the database commits
the given transaction. If an invalid transaction ID is
provided, a `~psycopg2.ProgrammingError` will be raised. This form
should be called outside of a transaction, and is intended for use in
recovery.
On return, the TPC transaction is ended.
.. seealso:: the |COMMIT PREPARED|_ PostgreSQL command.
.. |COMMIT PREPARED| replace:: :sql:`COMMIT PREPARED`
.. _COMMIT PREPARED: https://www.postgresql.org/docs/current/static/sql-commit-prepared.html
.. index::
pair: Rollback; Prepared
.. method:: tpc_rollback([xid])
When called with no arguments, `!tpc_rollback()` rolls back a TPC
transaction. It may be called before or after
`~connection.tpc_prepare()`.
When called with a transaction ID *xid*, it rolls back the given
transaction. If an invalid transaction ID is provided, a
`~psycopg2.ProgrammingError` is raised. This form should be called
outside of a transaction, and is intended for use in recovery.
On return, the TPC transaction is ended.
.. seealso:: the |ROLLBACK PREPARED|_ PostgreSQL command.
.. |ROLLBACK PREPARED| replace:: :sql:`ROLLBACK PREPARED`
.. _ROLLBACK PREPARED: https://www.postgresql.org/docs/current/static/sql-rollback-prepared.html
.. index::
pair: Transaction; Recover
.. method:: tpc_recover()
Returns a list of `~psycopg2.extensions.Xid` representing pending
transactions, suitable for use with `tpc_commit()` or
`tpc_rollback()`.
If a transaction was not initiated by Psycopg, the returned Xids will
have attributes `~psycopg2.extensions.Xid.format_id` and
`~psycopg2.extensions.Xid.bqual` set to `!None` and the
`~psycopg2.extensions.Xid.gtrid` set to the PostgreSQL transaction ID: such Xids are still
usable for recovery. Psycopg uses the same algorithm of the
`PostgreSQL JDBC driver`__ to encode a XA triple in a string, so
transactions initiated by a program using such driver should be
unpacked correctly.
.. __: https://jdbc.postgresql.org/
Xids returned by `!tpc_recover()` also have extra attributes
`~psycopg2.extensions.Xid.prepared`, `~psycopg2.extensions.Xid.owner`,
`~psycopg2.extensions.Xid.database` populated with the values read
from the server.
.. seealso:: the |pg_prepared_xacts|_ system view.
.. |pg_prepared_xacts| replace:: `pg_prepared_xacts`
.. _pg_prepared_xacts: https://www.postgresql.org/docs/current/static/view-pg-prepared-xacts.html
.. extension::
The above methods are the only ones defined by the |DBAPI| protocol.
The Psycopg connection objects exports the following additional
methods and attributes.
.. attribute:: closed
Read-only integer attribute: 0 if the connection is open, nonzero if
it is closed or broken.
.. method:: cancel
Cancel the current database operation.
The method interrupts the processing of the current operation. If no
query is being executed, it does nothing. You can call this function
from a different thread than the one currently executing a database
operation, for instance if you want to cancel a long running query if a
button is pushed in the UI. Interrupting query execution will cause the
cancelled method to raise a
`~psycopg2.extensions.QueryCanceledError`. Note that the termination
of the query is not guaranteed to succeed: see the documentation for
|PQcancel|_.
.. |PQcancel| replace:: `!PQcancel()`
.. _PQcancel: https://www.postgresql.org/docs/current/static/libpq-cancel.html#LIBPQ-PQCANCEL
.. versionadded:: 2.3
.. method:: reset
Reset the connection to the default.
The method rolls back an eventual pending transaction and executes the
PostgreSQL |RESET|_ and |SET SESSION AUTHORIZATION|__ to revert the
session to the default values. A two-phase commit transaction prepared
using `~connection.tpc_prepare()` will remain in the database
available for recover.
.. |RESET| replace:: :sql:`RESET`
.. _RESET: https://www.postgresql.org/docs/current/static/sql-reset.html
.. |SET SESSION AUTHORIZATION| replace:: :sql:`SET SESSION AUTHORIZATION`
.. __: https://www.postgresql.org/docs/current/static/sql-set-session-authorization.html
.. versionadded:: 2.0.12
.. attribute:: dsn
Read-only string containing the connection string used by the
connection.
If a password was specified in the connection string it will be
obscured.
.. rubric:: Transaction control methods and attributes.
.. index::
pair: Transaction; Autocommit
pair: Transaction; Isolation level
.. method:: set_session(isolation_level=None, readonly=None, deferrable=None, autocommit=None)
Set one or more parameters for the next transactions or statements in
the current session.
:param isolation_level: set the `isolation level`_ for the next
transactions/statements. The value can be one of the literal
values ``READ UNCOMMITTED``, ``READ COMMITTED``, ``REPEATABLE
READ``, ``SERIALIZABLE`` or the equivalent :ref:`constant
<isolation-level-constants>` defined in the `~psycopg2.extensions`
module.
:param readonly: if `!True`, set the connection to read only;
read/write if `!False`.
:param deferrable: if `!True`, set the connection to deferrable;
non deferrable if `!False`. Only available from PostgreSQL 9.1.
:param autocommit: switch the connection to autocommit mode: not a
PostgreSQL session setting but an alias for setting the
`autocommit` attribute.
.. _isolation level:
https://www.postgresql.org/docs/current/static/transaction-iso.html
Arguments set to `!None` (the default for all) will not be changed.
The parameters *isolation_level*, *readonly* and *deferrable* also
accept the string ``DEFAULT`` as a value: the effect is to reset the
parameter to the server default. Defaults are defined by the server
configuration: see values for |default_transaction_isolation|__,
|default_transaction_read_only|__, |default_transaction_deferrable|__.
.. |default_transaction_isolation| replace:: :sql:`default_transaction_isolation`
.. __: https://www.postgresql.org/docs/current/static/runtime-config-client.html#GUC-DEFAULT-TRANSACTION-ISOLATION
.. |default_transaction_read_only| replace:: :sql:`default_transaction_read_only`
.. __: https://www.postgresql.org/docs/current/static/runtime-config-client.html#GUC-DEFAULT-TRANSACTION-READ-ONLY
.. |default_transaction_deferrable| replace:: :sql:`default_transaction_deferrable`
.. __: https://www.postgresql.org/docs/current/static/runtime-config-client.html#GUC-DEFAULT-TRANSACTION-DEFERRABLE
The function must be invoked with no transaction in progress.
.. seealso:: |SET TRANSACTION|_ for further details about the behaviour
of the transaction parameters in the server.
.. |SET TRANSACTION| replace:: :sql:`SET TRANSACTION`
.. _SET TRANSACTION: https://www.postgresql.org/docs/current/static/sql-set-transaction.html
.. versionadded:: 2.4.2
.. versionchanged:: 2.7
Before this version, the function would have set
:sql:`default_transaction_*` attribute in the current session;
this implementation has the problem of not playing well with
external connection pooling working at transaction level and not
resetting the state of the session: changing the default
transaction would pollute the connections in the pool and create
problems to other applications using the same pool.
Starting from 2.7, if the connection is not autocommit, the
transaction characteristics are issued together with :sql:`BEGIN`
and will leave the :sql:`default_transaction_*` settings untouched.
For example::
conn.set_session(readonly=True)
will not change :sql:`default_transaction_read_only`, but
following transaction will start with a :sql:`BEGIN READ ONLY`.
Conversely, using::
conn.set_session(readonly=True, autocommit=True)
will set :sql:`default_transaction_read_only` to :sql:`on` and
rely on the server to apply the read only state to whatever
transaction, implicit or explicit, is executed in the connection.
.. attribute:: autocommit
Read/write attribute: if `!True`, no transaction is handled by the
driver and every statement sent to the backend has immediate effect;
if `!False` a new transaction is started at the first command
execution: the methods `commit()` or `rollback()` must be manually
invoked to terminate the transaction.
The autocommit mode is useful to execute commands requiring to be run
outside a transaction, such as :sql:`CREATE DATABASE` or
:sql:`VACUUM`.
The default is `!False` (manual commit) as per DBAPI specification.
.. warning::
By default, any query execution, including a simple :sql:`SELECT`
will start a transaction: for long-running programs, if no further
action is taken, the session will remain "idle in transaction", an
undesirable condition for several reasons (locks are held by
the session, tables bloat...). For long lived scripts, either
ensure to terminate a transaction as soon as possible or use an
autocommit connection.
.. versionadded:: 2.4.2
.. attribute:: isolation_level
Return or set the `transaction isolation level`_ for the current
session. The value is one of the :ref:`isolation-level-constants`
defined in the `psycopg2.extensions` module. On set it is also
possible to use one of the literal values ``READ UNCOMMITTED``, ``READ
COMMITTED``, ``REPEATABLE READ``, ``SERIALIZABLE``, ``DEFAULT``.
.. versionchanged:: 2.7
the property is writable.
.. versionchanged:: 2.7
the default value for `!isolation_level` is
`~psycopg2.extensions.ISOLATION_LEVEL_DEFAULT`; previously the
property would have queried the server and returned the real value
applied. To know this value you can run a query such as :sql:`show
transaction_isolation`. Usually the default value is `READ
COMMITTED`, but this may be changed in the server configuration.
This value is now entirely separate from the `autocommit`
property: in previous version, if `!autocommit` was set to `!True`
this property would have returned
`~psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT`; it will now
return the server isolation level.
.. attribute:: readonly
Return or set the read-only status for the current session. Available
values are `!True` (new transactions will be in read-only mode),
`!False` (new transactions will be writable), `!None` (use the default
configured for the server by :sql:`default_transaction_read_only`).
.. versionadded:: 2.7
.. attribute:: deferrable
Return or set the `deferrable status`__ for the current session.
Available values are `!True` (new transactions will be in deferrable
mode), `!False` (new transactions will be in non deferrable mode),
`!None` (use the default configured for the server by
:sql:`default_transaction_deferrable`).
.. __: `SET TRANSACTION`_
.. versionadded:: 2.7
.. method:: set_isolation_level(level)
.. note::
This is a legacy method mixing `~conn.isolation_level` and
`~conn.autocommit`. Using the respective properties is a better
option.
Set the `transaction isolation level`_ for the current session.
The level defines the different phenomena that can happen in the
database between concurrent transactions.
The value set is an integer: symbolic constants are defined in
the module `psycopg2.extensions`: see
:ref:`isolation-level-constants` for the available values.
The default level is `~psycopg2.extensions.ISOLATION_LEVEL_DEFAULT`:
at this level a transaction is automatically started the first time a
database command is executed. If you want an *autocommit* mode,
switch to `~psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT` before
executing any command::
>>> conn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
See also :ref:`transactions-control`.
.. index::
pair: Client; Encoding
.. attribute:: encoding
.. method:: set_client_encoding(enc)
Read or set the client encoding for the current session. The default
is the encoding defined by the database. It should be one of the
`characters set supported by PostgreSQL`__
.. __: https://www.postgresql.org/docs/current/static/multibyte.html
.. index::
pair: Client; Logging
.. attribute:: notices
A list containing all the database messages sent to the client during
the session.
.. doctest::
:options: +NORMALIZE_WHITESPACE
>>> cur.execute("CREATE TABLE foo (id serial PRIMARY KEY);")
>>> pprint(conn.notices)
['NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "foo_pkey" for table "foo"\n',
'NOTICE: CREATE TABLE will create implicit sequence "foo_id_seq" for serial column "foo.id"\n']
.. versionchanged:: 2.7
The `!notices` attribute is writable: the user may replace it
with any Python object exposing an `!append()` method. If
appending raises an exception the notice is silently
dropped.
To avoid a leak in case excessive notices are generated, only the last
50 messages are kept. This check is only in place if the `!notices`
attribute is a list: if any other object is used it will be up to the
user to guard from leakage.
You can configure what messages to receive using `PostgreSQL logging
configuration parameters`__ such as ``log_statement``,
``client_min_messages``, ``log_min_duration_statement`` etc.
.. __: https://www.postgresql.org/docs/current/static/runtime-config-logging.html
.. attribute:: notifies
List of `~psycopg2.extensions.Notify` objects containing asynchronous
notifications received by the session.
For other details see :ref:`async-notify`.
.. versionchanged:: 2.3
Notifications are instances of the `!Notify` object. Previously the
list was composed by 2 items tuples :samp:`({pid},{channel})` and
the payload was not accessible. To keep backward compatibility,
`!Notify` objects can still be accessed as 2 items tuples.
.. versionchanged:: 2.7
The `!notifies` attribute is writable: the user may replace it
with any Python object exposing an `!append()` method. If
appending raises an exception the notification is silently
dropped.
.. attribute:: cursor_factory
The default cursor factory used by `~connection.cursor()` if the
parameter is not specified.
.. versionadded:: 2.5
.. index::
pair: Connection; Info
.. attribute:: info
A `~psycopg2.extensions.ConnectionInfo` object exposing information
about the native libpq connection.
.. versionadded:: 2.8
.. index::
pair: Connection; Status
.. attribute:: status
A read-only integer representing the status of the connection.
Symbolic constants for the values are defined in the module
`psycopg2.extensions`: see :ref:`connection-status-constants`
for the available values.
The status is undefined for `closed` connections.
.. method:: lobject([oid [, mode [, new_oid [, new_file [, lobject_factory]]]]])
Return a new database large object as a `~psycopg2.extensions.lobject`
instance.
See :ref:`large-objects` for an overview.
:param oid: The OID of the object to read or write. 0 to create
a new large object and and have its OID assigned automatically.
:param mode: Access mode to the object, see below.
:param new_oid: Create a new object using the specified OID. The
function raises `~psycopg2.OperationalError` if the OID is already
in use. Default is 0, meaning assign a new one automatically.
:param new_file: The name of a file to be imported in the database
(using the |lo_import|_ function)
:param lobject_factory: Subclass of
`~psycopg2.extensions.lobject` to be instantiated.
.. |lo_import| replace:: `!lo_import()`
.. _lo_import: https://www.postgresql.org/docs/current/static/lo-interfaces.html#LO-IMPORT
Available values for *mode* are:
======= =========
*mode* meaning
======= =========
``r`` Open for read only
``w`` Open for write only
``rw`` Open for read/write
``n`` Don't open the file
``b`` Don't decode read data (return data as `!str` in Python 2 or `!bytes` in Python 3)
``t`` Decode read data according to `connection.encoding` (return data as `!unicode` in Python 2 or `!str` in Python 3)
======= =========
``b`` and ``t`` can be specified together with a read/write mode. If
neither ``b`` nor ``t`` is specified, the default is ``b`` in Python 2
and ``t`` in Python 3.
.. versionadded:: 2.0.8
.. versionchanged:: 2.4 added ``b`` and ``t`` mode and unicode
support.
.. rubric:: Methods related to asynchronous support
.. versionadded:: 2.2
.. seealso:: :ref:`async-support` and :ref:`green-support`.
.. attribute:: async
async_
Read only attribute: 1 if the connection is asynchronous, 0 otherwise.
.. versionchanged:: 2.7 added the `!async_` alias for Python versions
where `!async` is a keyword.
.. method:: poll()
Used during an asynchronous connection attempt, or when a cursor is
executing a query on an asynchronous connection, make communication
proceed if it wouldn't block.
Return one of the constants defined in :ref:`poll-constants`. If it
returns `~psycopg2.extensions.POLL_OK` then the connection has been
established or the query results are available on the client.
Otherwise wait until the file descriptor returned by `fileno()` is
ready to read or to write, as explained in :ref:`async-support`.
`poll()` should be also used by the function installed by
`~psycopg2.extensions.set_wait_callback()` as explained in
:ref:`green-support`.
`poll()` is also used to receive asynchronous notifications from the
database: see :ref:`async-notify` from further details.
.. method:: fileno()
Return the file descriptor underlying the connection: useful to read
its status during asynchronous communication.
.. method:: isexecuting()
Return `!True` if the connection is executing an asynchronous operation.
.. rubric:: Interoperation with other C API modules
.. attribute:: pgconn_ptr
Return the internal `!PGconn*` as integer. Useful to pass the libpq
raw connection structure to C functions, e.g. via `ctypes`::
>>> import ctypes
>>> import ctypes.util
>>> libpq = ctypes.pydll.LoadLibrary(ctypes.util.find_library('pq'))
>>> libpq.PQserverVersion.argtypes = [ctypes.c_void_p]
>>> libpq.PQserverVersion.restype = ctypes.c_int
>>> libpq.PQserverVersion(conn.pgconn_ptr)
90611
.. versionadded:: 2.8
.. method:: get_native_connection()
Return the internal `!PGconn*` wrapped in a PyCapsule object. This is
only useful for passing the `libpq` raw connection associated to this
connection object to other C-level modules that may have a use for it.
.. seealso:: Python C API `Capsules`__ docs.
.. __: https://docs.python.org/3.1/c-api/capsule.html
.. versionadded:: 2.8
.. rubric:: informative methods of the native connection
.. note::
These methods are better accessed using the `~connection.info`
attributes and may be dropped in future versions.
.. index::
pair: Transaction; Status
.. method:: get_transaction_status()
Also available as `~connection.info`\ `!.`\
`~psycopg2.extensions.ConnectionInfo.transaction_status`.
Return the current session transaction status as an integer. Symbolic
constants for the values are defined in the module
`psycopg2.extensions`: see :ref:`transaction-status-constants`
for the available values.
.. seealso:: libpq docs for `PQtransactionStatus()`__ for details.
.. __: https://www.postgresql.org/docs/current/static/libpq-status.html#LIBPQ-PQTRANSACTIONSTATUS
.. index::
pair: Protocol; Version
.. attribute:: protocol_version
Also available as `~connection.info`\ `!.`\
`~psycopg2.extensions.ConnectionInfo.protocol_version`.
A read-only integer representing frontend/backend protocol being used.
Currently Psycopg supports only protocol 3, which allows connection
to PostgreSQL server from version 7.4. Psycopg versions previous than
2.3 support both protocols 2 and 3.
.. seealso:: libpq docs for `PQprotocolVersion()`__ for details.
.. __: https://www.postgresql.org/docs/current/static/libpq-status.html#LIBPQ-PQPROTOCOLVERSION
.. versionadded:: 2.0.12
.. index::
pair: Server; Version
.. attribute:: server_version
Also available as `~connection.info`\ `!.`\
`~psycopg2.extensions.ConnectionInfo.server_version`.
A read-only integer representing the backend version.
The number is formed by converting the major, minor, and revision
numbers into two-decimal-digit numbers and appending them together.
For example, version 8.1.5 will be returned as ``80105``.
.. seealso:: libpq docs for `PQserverVersion()`__ for details.
.. __: https://www.postgresql.org/docs/current/static/libpq-status.html#LIBPQ-PQSERVERVERSION
.. versionadded:: 2.0.12
.. index::
pair: Backend; PID
.. method:: get_backend_pid()
Also available as `~connection.info`\ `!.`\
`~psycopg2.extensions.ConnectionInfo.backend_pid`.
Returns the process ID (PID) of the backend server process *you
connected to*. Note that if you use a connection pool service such as
PgBouncer_ this value will not be updated if your connection is
switched to a different backend.
Note that the PID belongs to a process executing on the database
server host, not the local host!
.. seealso:: libpq docs for `PQbackendPID()`__ for details.
.. __: https://www.postgresql.org/docs/current/static/libpq-status.html#LIBPQ-PQBACKENDPID
.. versionadded:: 2.0.8
.. index::
pair: Server; Parameters
.. method:: get_parameter_status(parameter)
Also available as `~connection.info`\ `!.`\
`~psycopg2.extensions.ConnectionInfo.parameter_status()`.
Look up a current parameter setting of the server.
Potential values for ``parameter`` are: ``server_version``,
``server_encoding``, ``client_encoding``, ``is_superuser``,
``session_authorization``, ``DateStyle``, ``TimeZone``,
``integer_datetimes``, and ``standard_conforming_strings``.
If server did not report requested parameter, return `!None`.
.. seealso:: libpq docs for `PQparameterStatus()`__ for details.
.. __: https://www.postgresql.org/docs/current/static/libpq-status.html#LIBPQ-PQPARAMETERSTATUS
.. versionadded:: 2.0.12
.. index::
pair: Connection; Parameters
.. method:: get_dsn_parameters()
Also available as `~connection.info`\ `!.`\
`~psycopg2.extensions.ConnectionInfo.dsn_parameters`.
Get the effective dsn parameters for the connection as a dictionary.
The *password* parameter is removed from the result.
Example::
>>> conn.get_dsn_parameters()
{'dbname': 'test', 'user': 'postgres', 'port': '5432', 'sslmode': 'prefer'}
Requires libpq >= 9.3.
.. seealso:: libpq docs for `PQconninfo()`__ for details.
.. __: https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-PQCONNINFO
.. versionadded:: 2.7
.. testcode::
:hide:
conn.rollback()

668
doc/src/cursor.rst Normal file
View File

@ -0,0 +1,668 @@
The ``cursor`` class
====================
.. sectionauthor:: Daniele Varrazzo <daniele.varrazzo@gmail.com>
.. testsetup:: *
from StringIO import StringIO
import sys
create_test_table()
# initial data
cur.executemany("INSERT INTO test (num, data) VALUES (%s, %s)",
[(100, "abc'def"), (None, 'dada'), (42, 'bar')])
conn.commit()
.. class:: cursor
Allows Python code to execute PostgreSQL command in a database session.
Cursors are created by the `connection.cursor()` method: they are
bound to the connection for the entire lifetime and all the commands are
executed in the context of the database session wrapped by the connection.
Cursors created from the same connection are not isolated, i.e., any
changes done to the database by a cursor are immediately visible by the
other cursors. Cursors created from different connections can or can not
be isolated, depending on the connections' :ref:`isolation level
<transactions-control>`. See also `~connection.rollback()` and
`~connection.commit()` methods.
Cursors are *not* thread safe: a multithread application can create
many cursors from the same connection and should use each cursor from
a single thread. See :ref:`thread-safety` for details.
Cursors can be used as context managers: leaving the context will close
the cursor.
.. code:: python
with conn.cursor() as curs:
curs.execute(SQL)
# the cursor is now closed
.. attribute:: description
Read-only attribute describing the result of a query. It is a
sequence of `~psycopg2.extensions.Column` instances, each one
describing one result column in order. The attribute is `!None` for
operations that do not return rows or if the cursor has not had an
operation invoked via the |execute*|_ methods yet.
For compatibility with the DB-API, every object can be unpacked as a
7-items sequence: the attributes retuned this way are the following.
For further details and other attributes available check the
`~psycopg2.extensions.Column` documentation.
0. `~psycopg2.extensions.Column.name`: the name of the column returned.
1. `~psycopg2.extensions.Column.type_code`: the PostgreSQL OID of the
column.
2. `~psycopg2.extensions.Column.display_size`: the actual length of
the column in bytes.
3. `~psycopg2.extensions.Column.internal_size`: the size in bytes of
the column associated to this column on the server.
4. `~psycopg2.extensions.Column.precision`: total number of
significant digits in columns of type |NUMERIC|. `!None`
for other types.
5. `~psycopg2.extensions.Column.scale`: count of decimal digits in
the fractional part in columns of type |NUMERIC|. `!None`
for other types.
6. `~psycopg2.extensions.Column.null_ok`: always `!None` as not easy
to retrieve from the libpq.
.. versionchanged:: 2.4
if possible, columns descriptions are named tuple instead of
regular tuples.
.. versionchanged:: 2.8
columns descriptions are instances of `!Column`, exposing extra
attributes.
.. |NUMERIC| replace:: :sql:`NUMERIC`
.. method:: close()
Close the cursor now (rather than whenever `del` is executed).
The cursor will be unusable from this point forward; an
`~psycopg2.InterfaceError` will be raised if any operation is
attempted with the cursor.
.. versionchanged:: 2.5 if the cursor is used in a ``with`` statement,
the method is automatically called at the end of the ``with``
block.
.. attribute:: closed
Read-only boolean attribute: specifies if the cursor is closed
(`!True`) or not (`!False`).
.. extension::
The `closed` attribute is a Psycopg extension to the
|DBAPI|.
.. versionadded:: 2.0.7
.. attribute:: connection
Read-only attribute returning a reference to the `connection`
object on which the cursor was created.
.. attribute:: name
Read-only attribute containing the name of the cursor if it was
created as named cursor by `connection.cursor()`, or `!None` if
it is a client side cursor. See :ref:`server-side-cursors`.
.. extension::
The `name` attribute is a Psycopg extension to the |DBAPI|.
.. attribute:: scrollable
Read/write attribute: specifies if a named cursor is declared
:sql:`SCROLL`, hence is capable to scroll backwards (using
`~cursor.scroll()`). If `!True`, the cursor can be scrolled backwards,
if `!False` it is never scrollable. If `!None` (default) the cursor
scroll option is not specified, usually but not always meaning no
backward scroll (see the |declare-notes|__).
.. |declare-notes| replace:: :sql:`DECLARE` notes
.. __: https://www.postgresql.org/docs/current/static/sql-declare.html#SQL-DECLARE-NOTES
.. note::
set the value before calling `~cursor.execute()` or use the
`connection.cursor()` *scrollable* parameter, otherwise the value
will have no effect.
.. versionadded:: 2.5
.. extension::
The `scrollable` attribute is a Psycopg extension to the |DBAPI|.
.. attribute:: withhold
Read/write attribute: specifies if a named cursor lifetime should
extend outside of the current transaction, i.e., it is possible to
fetch from the cursor even after a `connection.commit()` (but not after
a `connection.rollback()`). See :ref:`server-side-cursors`
.. note::
set the value before calling `~cursor.execute()` or use the
`connection.cursor()` *withhold* parameter, otherwise the value
will have no effect.
.. versionadded:: 2.4.3
.. extension::
The `withhold` attribute is a Psycopg extension to the |DBAPI|.
.. |execute*| replace:: `execute*()`
.. _execute*:
.. rubric:: Commands execution methods
.. method:: execute(query, vars=None)
Execute a database operation (query or command).
Parameters may be provided as sequence or mapping and will be bound to
variables in the operation. Variables are specified either with
positional (``%s``) or named (:samp:`%({name})s`) placeholders. See
:ref:`query-parameters`.
The method returns `!None`. If a query was executed, the returned
values can be retrieved using |fetch*|_ methods.
.. method:: executemany(query, vars_list)
Execute a database operation (query or command) against all parameter
tuples or mappings found in the sequence *vars_list*.
The function is mostly useful for commands that update the database:
any result set returned by the query is discarded.
Parameters are bounded to the query using the same rules described in
the `~cursor.execute()` method.
.. warning::
In its current implementation this method is not faster than
executing `~cursor.execute()` in a loop. For better performance
you can use the functions described in :ref:`fast-exec`.
.. method:: callproc(procname [, parameters])
Call a stored database procedure with the given name. The sequence of
parameters must contain one entry for each argument that the procedure
expects. Overloaded procedures are supported. Named parameters can be
used by supplying the parameters as a dictionary.
This function is, at present, not DBAPI-compliant. The return value is
supposed to consist of the sequence of parameters with modified output
and input/output parameters. In future versions, the DBAPI-compliant
return value may be implemented, but for now the function returns None.
The procedure may provide a result set as output. This is then made
available through the standard |fetch*|_ methods.
.. versionchanged:: 2.7
added support for named arguments.
.. method:: mogrify(operation [, parameters])
Return a query string after arguments binding. The string returned is
exactly the one that would be sent to the database running the
`~cursor.execute()` method or similar.
The returned string is always a bytes string.
>>> cur.mogrify("INSERT INTO test (num, data) VALUES (%s, %s)", (42, 'bar'))
"INSERT INTO test (num, data) VALUES (42, E'bar')"
.. extension::
The `mogrify()` method is a Psycopg extension to the |DBAPI|.
.. method:: setinputsizes(sizes)
This method is exposed in compliance with the |DBAPI|. It currently
does nothing but it is safe to call it.
.. |fetch*| replace:: `!fetch*()`
.. _fetch*:
.. rubric:: Results retrieval methods
The following methods are used to read data from the database after an
`~cursor.execute()` call.
.. _cursor-iterable:
.. note::
`cursor` objects are iterable, so, instead of calling
explicitly `~cursor.fetchone()` in a loop, the object itself can
be used:
>>> cur.execute("SELECT * FROM test;")
>>> for record in cur:
... print record
...
(1, 100, "abc'def")
(2, None, 'dada')
(3, 42, 'bar')
.. versionchanged:: 2.4
iterating over a :ref:`named cursor <server-side-cursors>`
fetches `~cursor.itersize` records at time from the backend.
Previously only one record was fetched per roundtrip, resulting
in a large overhead.
.. method:: fetchone()
Fetch the next row of a query result set, returning a single tuple,
or `!None` when no more data is available:
>>> cur.execute("SELECT * FROM test WHERE id = %s", (3,))
>>> cur.fetchone()
(3, 42, 'bar')
A `~psycopg2.ProgrammingError` is raised if the previous call
to |execute*|_ did not produce any result set or no call was issued
yet.
.. method:: fetchmany([size=cursor.arraysize])
Fetch the next set of rows of a query result, returning a list of
tuples. An empty list is returned when no more rows are available.
The number of rows to fetch per call is specified by the parameter.
If it is not given, the cursor's `~cursor.arraysize` determines
the number of rows to be fetched. The method should try to fetch as
many rows as indicated by the size parameter. If this is not possible
due to the specified number of rows not being available, fewer rows
may be returned:
>>> cur.execute("SELECT * FROM test;")
>>> cur.fetchmany(2)
[(1, 100, "abc'def"), (2, None, 'dada')]
>>> cur.fetchmany(2)
[(3, 42, 'bar')]
>>> cur.fetchmany(2)
[]
A `~psycopg2.ProgrammingError` is raised if the previous call to
|execute*|_ did not produce any result set or no call was issued yet.
Note there are performance considerations involved with the size
parameter. For optimal performance, it is usually best to use the
`~cursor.arraysize` attribute. If the size parameter is used,
then it is best for it to retain the same value from one
`fetchmany()` call to the next.
.. method:: fetchall()
Fetch all (remaining) rows of a query result, returning them as a list
of tuples. An empty list is returned if there is no more record to
fetch.
>>> cur.execute("SELECT * FROM test;")
>>> cur.fetchall()
[(1, 100, "abc'def"), (2, None, 'dada'), (3, 42, 'bar')]
A `~psycopg2.ProgrammingError` is raised if the previous call to
|execute*|_ did not produce any result set or no call was issued yet.
.. method:: scroll(value [, mode='relative'])
Scroll the cursor in the result set to a new position according
to mode.
If `mode` is ``relative`` (default), value is taken as offset to
the current position in the result set, if set to ``absolute``,
value states an absolute target position.
If the scroll operation would leave the result set, a
`~psycopg2.ProgrammingError` is raised and the cursor position is
not changed.
.. note::
According to the |DBAPI|_, the exception raised for a cursor out
of bound should have been `!IndexError`. The best option is
probably to catch both exceptions in your code::
try:
cur.scroll(1000 * 1000)
except (ProgrammingError, IndexError), exc:
deal_with_it(exc)
The method can be used both for client-side cursors and
:ref:`server-side cursors <server-side-cursors>`. Server-side cursors
can usually scroll backwards only if declared `~cursor.scrollable`.
Moving out-of-bound in a server-side cursor doesn't result in an
exception, if the backend doesn't raise any (Postgres doesn't tell us
in a reliable way if we went out of bound).
.. attribute:: arraysize
This read/write attribute specifies the number of rows to fetch at a
time with `~cursor.fetchmany()`. It defaults to 1 meaning to fetch
a single row at a time.
.. attribute:: itersize
Read/write attribute specifying the number of rows to fetch from the
backend at each network roundtrip during :ref:`iteration
<cursor-iterable>` on a :ref:`named cursor <server-side-cursors>`. The
default is 2000.
.. versionadded:: 2.4
.. extension::
The `itersize` attribute is a Psycopg extension to the |DBAPI|.
.. attribute:: rowcount
This read-only attribute specifies the number of rows that the last
|execute*|_ produced (for :abbr:`DQL (Data Query Language)` statements
like :sql:`SELECT`) or affected (for
:abbr:`DML (Data Manipulation Language)` statements like :sql:`UPDATE`
or :sql:`INSERT`).
The attribute is -1 in case no |execute*| has been performed on
the cursor or the row count of the last operation if it can't be
determined by the interface.
.. note::
The |DBAPI|_ interface reserves to redefine the latter case to
have the object return `!None` instead of -1 in future versions
of the specification.
.. attribute:: rownumber
This read-only attribute provides the current 0-based index of the
cursor in the result set or `!None` if the index cannot be
determined.
The index can be seen as index of the cursor in a sequence (the result
set). The next fetch operation will fetch the row indexed by
`rownumber` in that sequence.
.. index:: oid
.. attribute:: lastrowid
This read-only attribute provides the OID of the last row inserted
by the cursor. If the table wasn't created with OID support or the
last operation is not a single record insert, the attribute is set to
`!None`.
.. note::
PostgreSQL currently advices to not create OIDs on the tables and
the default for |CREATE-TABLE|__ is to not support them. The
|INSERT-RETURNING|__ syntax available from PostgreSQL 8.3 allows
more flexibility.
.. |CREATE-TABLE| replace:: :sql:`CREATE TABLE`
.. __: https://www.postgresql.org/docs/current/static/sql-createtable.html
.. |INSERT-RETURNING| replace:: :sql:`INSERT ... RETURNING`
.. __: https://www.postgresql.org/docs/current/static/sql-insert.html
.. attribute:: query
Read-only attribute containing the body of the last query sent to the
backend (including bound arguments) as bytes string. `!None` if no
query has been executed yet:
>>> cur.execute("INSERT INTO test (num, data) VALUES (%s, %s)", (42, 'bar'))
>>> cur.query
"INSERT INTO test (num, data) VALUES (42, E'bar')"
.. extension::
The `query` attribute is a Psycopg extension to the |DBAPI|.
.. attribute:: statusmessage
Read-only attribute containing the message returned by the last
command:
>>> cur.execute("INSERT INTO test (num, data) VALUES (%s, %s)", (42, 'bar'))
>>> cur.statusmessage
'INSERT 0 1'
.. extension::
The `statusmessage` attribute is a Psycopg extension to the
|DBAPI|.
.. method:: cast(oid, s)
Convert a value from the PostgreSQL string representation to a Python
object.
Use the most specific of the typecasters registered by
`~psycopg2.extensions.register_type()`.
.. versionadded:: 2.4
.. extension::
The `cast()` method is a Psycopg extension to the |DBAPI|.
.. attribute:: tzinfo_factory
The time zone factory used to handle data types such as
:sql:`TIMESTAMP WITH TIME ZONE`. It should be a `~datetime.tzinfo`
object. Default is `datetime.timezone`.
.. versionchanged:: 2.9
previosly the default factory was `psycopg2.tz.FixedOffsetTimezone`.
.. method:: nextset()
This method is not supported (PostgreSQL does not have multiple data
sets) and will raise a `~psycopg2.NotSupportedError` exception.
.. method:: setoutputsize(size [, column])
This method is exposed in compliance with the |DBAPI|. It currently
does nothing but it is safe to call it.
.. rubric:: COPY-related methods
Efficiently copy data from file-like objects to the database and back. See
:ref:`copy` for an overview.
.. extension::
The :sql:`COPY` command is a PostgreSQL extension to the SQL standard.
As such, its support is a Psycopg extension to the |DBAPI|.
.. method:: copy_from(file, table, sep='\\t', null='\\\\N', size=8192, columns=None)
Read data *from* the file-like object *file* appending them to
the table named *table*.
:param file: file-like object to read data from. It must have both
`!read()` and `!readline()` methods.
:param table: name of the table to copy data into.
:param sep: columns separator expected in the file. Defaults to a tab.
:param null: textual representation of :sql:`NULL` in the file.
The default is the two characters string ``\N``.
:param size: size of the buffer used to read from the file.
:param columns: iterable with name of the columns to import.
The length and types should match the content of the file to read.
If not specified, it is assumed that the entire table matches the
file structure.
Example::
>>> f = StringIO("42\tfoo\n74\tbar\n")
>>> cur.copy_from(f, 'test', columns=('num', 'data'))
>>> cur.execute("select * from test where id > 5;")
>>> cur.fetchall()
[(6, 42, 'foo'), (7, 74, 'bar')]
.. note:: the name of the table is not quoted: if the table name
contains uppercase letters or special characters it must be quoted
with double quotes::
cur.copy_from(f, '"TABLE"')
.. versionchanged:: 2.0.6
added the *columns* parameter.
.. versionchanged:: 2.4
data read from files implementing the `io.TextIOBase` interface
are encoded in the connection `~connection.encoding` when sent to
the backend.
.. method:: copy_to(file, table, sep='\\t', null='\\\\N', columns=None)
Write the content of the table named *table* *to* the file-like
object *file*. See :ref:`copy` for an overview.
:param file: file-like object to write data into. It must have a
`!write()` method.
:param table: name of the table to copy data from.
:param sep: columns separator expected in the file. Defaults to a tab.
:param null: textual representation of :sql:`NULL` in the file.
The default is the two characters string ``\N``.
:param columns: iterable with name of the columns to export.
If not specified, export all the columns.
Example::
>>> cur.copy_to(sys.stdout, 'test', sep="|")
1|100|abc'def
2|\N|dada
...
.. note:: the name of the table is not quoted: if the table name
contains uppercase letters or special characters it must be quoted
with double quotes::
cur.copy_to(f, '"TABLE"')
.. versionchanged:: 2.0.6
added the *columns* parameter.
.. versionchanged:: 2.4
data sent to files implementing the `io.TextIOBase` interface
are decoded in the connection `~connection.encoding` when read
from the backend.
.. method:: copy_expert(sql, file, size=8192)
Submit a user-composed :sql:`COPY` statement. The method is useful to
handle all the parameters that PostgreSQL makes available (see
|COPY|__ command documentation).
:param sql: the :sql:`COPY` statement to execute.
:param file: a file-like object to read or write (according to *sql*).
:param size: size of the read buffer to be used in :sql:`COPY FROM`.
The *sql* statement should be in the form :samp:`COPY {table} TO
STDOUT` to export :samp:`{table}` to the *file* object passed as
argument or :samp:`COPY {table} FROM STDIN` to import the content of
the *file* object into :samp:`{table}`. If you need to compose a
:sql:`COPY` statement dynamically (because table, fields, or query
parameters are in Python variables) you may use the objects provided
by the `psycopg2.sql` module.
*file* must be a readable file-like object (as required by
`~cursor.copy_from()`) for *sql* statement :sql:`COPY ... FROM STDIN`
or a writable one (as required by `~cursor.copy_to()`) for :sql:`COPY
... TO STDOUT`.
Example:
>>> cur.copy_expert("COPY test TO STDOUT WITH CSV HEADER", sys.stdout)
id,num,data
1,100,abc'def
2,,dada
...
.. |COPY| replace:: :sql:`COPY`
.. __: https://www.postgresql.org/docs/current/static/sql-copy.html
.. versionadded:: 2.0.6
.. versionchanged:: 2.4
files implementing the `io.TextIOBase` interface are dealt with
using Unicode data instead of bytes.
.. rubric:: Interoperation with other C API modules
.. attribute:: pgresult_ptr
Return the cursor's internal `!PGresult*` as integer. Useful to pass
the libpq raw result structure to C functions, e.g. via `ctypes`::
>>> import ctypes
>>> libpq = ctypes.pydll.LoadLibrary(ctypes.util.find_library('pq'))
>>> libpq.PQcmdStatus.argtypes = [ctypes.c_void_p]
>>> libpq.PQcmdStatus.restype = ctypes.c_char_p
>>> curs.execute("select 'x'")
>>> libpq.PQcmdStatus(curs.pgresult_ptr)
b'SELECT 1'
.. versionadded:: 2.8
.. testcode::
:hide:
conn.rollback()

76
doc/src/errorcodes.rst Normal file
View File

@ -0,0 +1,76 @@
`psycopg2.errorcodes` -- Error codes defined by PostgreSQL
===============================================================
.. sectionauthor:: Daniele Varrazzo <daniele.varrazzo@gmail.com>
.. index::
single: Error; Codes
.. module:: psycopg2.errorcodes
.. testsetup:: *
from psycopg2 import errorcodes
.. versionadded:: 2.0.6
This module contains symbolic names for all PostgreSQL error codes and error
classes codes. Subclasses of `~psycopg2.Error` make the PostgreSQL error
code available in the `~psycopg2.Error.pgcode` attribute.
From PostgreSQL documentation:
All messages emitted by the PostgreSQL server are assigned five-character
error codes that follow the SQL standard's conventions for :sql:`SQLSTATE`
codes. Applications that need to know which error condition has occurred
should usually test the error code, rather than looking at the textual
error message. The error codes are less likely to change across
PostgreSQL releases, and also are not subject to change due to
localization of error messages. Note that some, but not all, of the error
codes produced by PostgreSQL are defined by the SQL standard; some
additional error codes for conditions not defined by the standard have
been invented or borrowed from other databases.
According to the standard, the first two characters of an error code
denote a class of errors, while the last three characters indicate a
specific condition within that class. Thus, an application that does not
recognize the specific error code can still be able to infer what to do
from the error class.
.. seealso:: `PostgreSQL Error Codes table`__
.. __: https://www.postgresql.org/docs/current/static/errcodes-appendix.html#ERRCODES-TABLE
An example of the available constants defined in the module:
>>> errorcodes.CLASS_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION
'42'
>>> errorcodes.UNDEFINED_TABLE
'42P01'
Constants representing all the error values defined by PostgreSQL versions
between 8.1 and 13 are included in the module.
.. autofunction:: lookup(code)
.. doctest::
>>> try:
... cur.execute("SELECT ouch FROM aargh;")
... except Exception as e:
... pass
...
>>> errorcodes.lookup(e.pgcode[:2])
'CLASS_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION'
>>> errorcodes.lookup(e.pgcode)
'UNDEFINED_TABLE'
.. versionadded:: 2.0.14
.. testcode::
:hide:
conn.rollback()

83
doc/src/errors.rst Normal file
View File

@ -0,0 +1,83 @@
`psycopg2.errors` -- Exception classes mapping PostgreSQL errors
================================================================
.. sectionauthor:: Daniele Varrazzo <daniele.varrazzo@gmail.com>
.. index::
single: Error; Class
.. module:: psycopg2.errors
.. versionadded:: 2.8
.. versionchanged:: 2.8.4 added errors introduced in PostgreSQL 12
.. versionchanged:: 2.8.6 added errors introduced in PostgreSQL 13
This module exposes the classes psycopg raises upon receiving an error from
the database with a :sql:`SQLSTATE` value attached (available in the
`~psycopg2.Error.pgcode` attribute). The content of the module is generated
from the PostgreSQL source code and includes classes for every error defined
by PostgreSQL in versions between 9.1 and 13.
Every class in the module is named after what referred as "condition name" `in
the documentation`__, converted to CamelCase: e.g. the error 22012,
``division_by_zero`` is exposed by this module as the class `!DivisionByZero`.
.. __: https://www.postgresql.org/docs/current/static/errcodes-appendix.html#ERRCODES-TABLE
Every exception class is a subclass of one of the :ref:`standard DB-API
exception <dbapi-exceptions>` and expose the `~psycopg2.Error` interface.
Each class' superclass is what used to be raised by psycopg in versions before
the introduction of this module, so everything should be compatible with
previously written code catching one the DB-API class: if your code used to
catch `!IntegrityError` to detect a duplicate entry, it will keep on working
even if a more specialised subclass such as `UniqueViolation` is raised.
The new classes allow a more idiomatic way to check and process a specific
error among the many the database may return. For instance, in order to check
that a table is locked, the following code could have been used previously:
.. code-block:: python
try:
cur.execute("LOCK TABLE mytable IN ACCESS EXCLUSIVE MODE NOWAIT")
except psycopg2.OperationalError as e:
if e.pgcode == psycopg2.errorcodes.LOCK_NOT_AVAILABLE:
locked = True
else:
raise
While this method is still available, the specialised class allows for a more
idiomatic error handler:
.. code-block:: python
try:
cur.execute("LOCK TABLE mytable IN ACCESS EXCLUSIVE MODE NOWAIT")
except psycopg2.errors.LockNotAvailable:
locked = True
.. autofunction:: lookup
.. code-block:: python
try:
cur.execute("LOCK TABLE mytable IN ACCESS EXCLUSIVE MODE NOWAIT")
except psycopg2.errors.lookup("55P03"):
locked = True
SQLSTATE exception classes
--------------------------
The following table contains the list of all the SQLSTATE classes exposed by
the module.
Note that, for completeness, the module also exposes all the
:ref:`DB-API-defined exceptions <dbapi-exceptions>` and :ref:`a few
psycopg-specific ones <extension-exceptions>` exposed by the `!extensions`
module, which are not listed here.
.. include:: sqlstate_errors.rst

1010
doc/src/extensions.rst Normal file

File diff suppressed because it is too large Load Diff

1085
doc/src/extras.rst Normal file

File diff suppressed because it is too large Load Diff

382
doc/src/faq.rst Normal file
View File

@ -0,0 +1,382 @@
Frequently Asked Questions
==========================
.. sectionauthor:: Daniele Varrazzo <daniele.varrazzo@gmail.com>
Here are a few gotchas you may encounter using `psycopg2`. Feel free to
suggest new entries!
Meta
----
.. _faq-question:
.. cssclass:: faq
How do I ask a question?
- Have you first checked if your question is answered already in the
documentation?
- If your question is about installing psycopg, have you checked the
:ref:`install FAQ <faq-compile>` and the :ref:`install docs
<installation>`?
- Have you googled for your error message?
- If you haven't found an answer yet, please write to the `Mailing List`_.
- If you haven't found a bug, DO NOT write to the bug tracker to ask
questions. You will only get piro grumpy.
.. _mailing list: https://www.postgresql.org/list/psycopg/
.. _faq-transactions:
Problems with transactions handling
-----------------------------------
.. _faq-idle-in-transaction:
.. cssclass:: faq
Why does `!psycopg2` leave database sessions "idle in transaction"?
Psycopg normally starts a new transaction the first time a query is
executed, e.g. calling `cursor.execute()`, even if the command is a
:sql:`SELECT`. The transaction is not closed until an explicit
`~connection.commit()` or `~connection.rollback()`.
If you are writing a long-living program, you should probably make sure to
call one of the transaction closing methods before leaving the connection
unused for a long time (which may also be a few seconds, depending on the
concurrency level in your database). Alternatively you can use a
connection in `~connection.autocommit` mode to avoid a new transaction to
be started at the first command.
.. _faq-transaction-aborted:
.. cssclass:: faq
I receive the error *current transaction is aborted, commands ignored until end of transaction block* and can't do anything else!
There was a problem *in the previous* command to the database, which
resulted in an error. The database will not recover automatically from
this condition: you must run a `~connection.rollback()` before sending
new commands to the session (if this seems too harsh, remember that
PostgreSQL supports nested transactions using the |SAVEPOINT|_ command).
.. |SAVEPOINT| replace:: :sql:`SAVEPOINT`
.. _SAVEPOINT: https://www.postgresql.org/docs/current/static/sql-savepoint.html
.. _faq-transaction-aborted-multiprocess:
.. cssclass:: faq
Why do I get the error *current transaction is aborted, commands ignored until end of transaction block* when I use `!multiprocessing` (or any other forking system) and not when use `!threading`?
Psycopg's connections can't be shared across processes (but are thread
safe). If you are forking the Python process make sure to create a new
connection in each forked child. See :ref:`thread-safety` for further
informations.
.. _faq-types:
Problems with type conversions
------------------------------
.. _faq-cant-adapt:
.. cssclass:: faq
Why does `!cursor.execute()` raise the exception *can't adapt*?
Psycopg converts Python objects in a SQL string representation by looking
at the object class. The exception is raised when you are trying to pass
as query parameter an object for which there is no adapter registered for
its class. See :ref:`adapting-new-types` for informations.
.. _faq-number-required:
.. cssclass:: faq
I can't pass an integer or a float parameter to my query: it says *a number is required*, but *it is* a number!
In your query string, you always have to use ``%s`` placeholders,
even when passing a number. All Python objects are converted by Psycopg
in their SQL representation, so they get passed to the query as strings.
See :ref:`query-parameters`. ::
>>> cur.execute("INSERT INTO numbers VALUES (%d)", (42,)) # WRONG
>>> cur.execute("INSERT INTO numbers VALUES (%s)", (42,)) # correct
.. _faq-not-all-arguments-converted:
.. cssclass:: faq
I try to execute a query but it fails with the error *not all arguments converted during string formatting* (or *object does not support indexing*). Why?
Psycopg always require positional arguments to be passed as a sequence, even
when the query takes a single parameter. And remember that to make a
single item tuple in Python you need a comma! See :ref:`query-parameters`.
::
>>> cur.execute("INSERT INTO foo VALUES (%s)", "bar") # WRONG
>>> cur.execute("INSERT INTO foo VALUES (%s)", ("bar")) # WRONG
>>> cur.execute("INSERT INTO foo VALUES (%s)", ("bar",)) # correct
>>> cur.execute("INSERT INTO foo VALUES (%s)", ["bar"]) # correct
.. _faq-unicode:
.. cssclass:: faq
My database is Unicode, but I receive all the strings as UTF-8 `!str`. Can I receive `!unicode` objects instead?
The following magic formula will do the trick::
psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
psycopg2.extensions.register_type(psycopg2.extensions.UNICODEARRAY)
See :ref:`unicode-handling` for the gory details.
.. _faq-bytes:
.. cssclass:: faq
My database is in mixed encoding. My program was working on Python 2 but Python 3 fails decoding the strings. How do I avoid decoding?
From psycopg 2.8 you can use the following adapters to always return bytes
from strings::
psycopg2.extensions.register_type(psycopg2.extensions.BYTES)
psycopg2.extensions.register_type(psycopg2.extensions.BYTESARRAY)
See :ref:`unicode-handling` for an example.
.. _faq-float:
.. cssclass:: faq
Psycopg converts :sql:`decimal`\/\ :sql:`numeric` database types into Python `!Decimal` objects. Can I have `!float` instead?
You can register a customized adapter for PostgreSQL decimal type::
DEC2FLOAT = psycopg2.extensions.new_type(
psycopg2.extensions.DECIMAL.values,
'DEC2FLOAT',
lambda value, curs: float(value) if value is not None else None)
psycopg2.extensions.register_type(DEC2FLOAT)
See :ref:`type-casting-from-sql-to-python` to read the relevant
documentation. If you find `!psycopg2.extensions.DECIMAL` not available, use
`!psycopg2._psycopg.DECIMAL` instead.
.. _faq-json-adapt:
.. cssclass:: faq
Psycopg automatically converts PostgreSQL :sql:`json` data into Python objects. How can I receive strings instead?
The easiest way to avoid JSON parsing is to register a no-op function with
`~psycopg2.extras.register_default_json()`::
psycopg2.extras.register_default_json(loads=lambda x: x)
See :ref:`adapt-json` for further details.
.. _faq-jsonb-adapt:
.. cssclass:: faq
Psycopg converts :sql:`json` values into Python objects but :sql:`jsonb` values are returned as strings. Can :sql:`jsonb` be converted automatically?
Automatic conversion of :sql:`jsonb` values is supported from Psycopg
release 2.5.4. For previous versions you can register the :sql:`json`
typecaster on the :sql:`jsonb` oids (which are known and not supposed to
change in future PostgreSQL versions)::
psycopg2.extras.register_json(oid=3802, array_oid=3807, globally=True)
See :ref:`adapt-json` for further details.
.. _faq-identifier:
.. cssclass:: faq
How can I pass field/table names to a query?
The arguments in the `~cursor.execute()` methods can only represent data
to pass to the query: they cannot represent a table or field name::
# This doesn't work
cur.execute("insert into %s values (%s)", ["my_table", 42])
If you want to build a query dynamically you can use the objects exposed
by the `psycopg2.sql` module::
cur.execute(
sql.SQL("insert into %s values (%%s)") % [sql.Identifier("my_table")],
[42])
.. _faq-bytea-9.0:
.. cssclass:: faq
Transferring binary data from PostgreSQL 9.0 doesn't work.
PostgreSQL 9.0 uses by default `the "hex" format`__ to transfer
:sql:`bytea` data: the format can't be parsed by the libpq 8.4 and
earlier. The problem is solved in Psycopg 2.4.1, that uses its own parser
for the :sql:`bytea` format. For previous Psycopg releases, three options
to solve the problem are:
- set the bytea_output__ parameter to ``escape`` in the server;
- execute the database command ``SET bytea_output TO escape;`` in the
session before reading binary data;
- upgrade the libpq library on the client to at least 9.0.
.. __: https://www.postgresql.org/docs/current/static/datatype-binary.html
.. __: https://www.postgresql.org/docs/current/static/runtime-config-client.html#GUC-BYTEA-OUTPUT
.. _faq-array:
.. cssclass:: faq
Arrays of *TYPE* are not casted to list.
Arrays are only casted to list when their oid is known, and an array
typecaster is registered for them. If there is no typecaster, the array is
returned unparsed from PostgreSQL (e.g. ``{a,b,c}``). It is easy to create
a generic arrays typecaster, returning a list of array: an example is
provided in the `~psycopg2.extensions.new_array_type()` documentation.
.. _faq-best-practices:
Best practices
--------------
.. _faq-reuse-cursors:
.. cssclass:: faq
When should I save and re-use a cursor as opposed to creating a new one as needed?
Cursors are lightweight objects and creating lots of them should not pose
any kind of problem. But note that cursors used to fetch result sets will
cache the data and use memory in proportion to the result set size. Our
suggestion is to almost always create a new cursor and dispose old ones as
soon as the data is not required anymore (call `~cursor.close()` on
them.) The only exception are tight loops where one usually use the same
cursor for a whole bunch of :sql:`INSERT`\s or :sql:`UPDATE`\s.
.. _faq-reuse-connections:
.. cssclass:: faq
When should I save and re-use a connection as opposed to creating a new one as needed?
Creating a connection can be slow (think of SSL over TCP) so the best
practice is to create a single connection and keep it open as long as
required. It is also good practice to rollback or commit frequently (even
after a single :sql:`SELECT` statement) to make sure the backend is never
left "idle in transaction". See also `psycopg2.pool` for lightweight
connection pooling.
.. _faq-named-cursors:
.. cssclass:: faq
What are the advantages or disadvantages of using named cursors?
The only disadvantages is that they use up resources on the server and
that there is a little overhead because at least two queries (one to
create the cursor and one to fetch the initial result set) are issued to
the backend. The advantage is that data is fetched one chunk at a time:
using small `~cursor.fetchmany()` values it is possible to use very
little memory on the client and to skip or discard parts of the result set.
.. _faq-interrupt-query:
.. cssclass:: faq
How do I interrupt a long-running query in an interactive shell?
Normally the interactive shell becomes unresponsive to :kbd:`Ctrl-C` when
running a query. Using a connection in green mode allows Python to
receive and handle the interrupt, although it may leave the connection
broken, if the async callback doesn't handle the `!KeyboardInterrupt`
correctly.
Starting from psycopg 2.6.2, the `~psycopg2.extras.wait_select` callback
can handle a :kbd:`Ctrl-C` correctly. For previous versions, you can use
`this implementation`__.
.. __: https://www.psycopg.org/articles/2014/07/20/cancelling-postgresql-statements-python/
.. code-block:: pycon
>>> psycopg2.extensions.set_wait_callback(psycopg2.extras.wait_select)
>>> cnn = psycopg2.connect('')
>>> cur = cnn.cursor()
>>> cur.execute("select pg_sleep(10)")
^C
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
QueryCanceledError: canceling statement due to user request
>>> cnn.rollback()
>>> # You can use the connection and cursor again from here
.. _faq-compile:
Problems compiling and installing psycopg2
------------------------------------------
.. _faq-wheels:
.. cssclass:: faq
Psycopg 2.8 fails to install, Psycopg 2.7 was working fine.
With Psycopg 2.7 you were installing binary packages, but they have proven
unreliable so now you have to install them explicitly using the
``psycopg2-binary`` package. See :ref:`binary-packages` for all the
details.
.. _faq-python-h:
.. cssclass:: faq
I can't compile `!psycopg2`: the compiler says *error: Python.h: No such file or directory*. What am I missing?
You need to install a Python development package: it is usually called
``python-dev`` or ``python3-dev`` according to your Python version.
.. _faq-libpq-fe-h:
.. cssclass:: faq
I can't compile `!psycopg2`: the compiler says *error: libpq-fe.h: No such file or directory*. What am I missing?
You need to install the development version of the libpq: the package is
usually called ``libpq-dev``.
.. _faq-lo_truncate:
.. cssclass:: faq
`!psycopg2` raises `!ImportError` with message *_psycopg.so: undefined symbol: lo_truncate* when imported.
This means that Psycopg was compiled with |lo_truncate|_ support (*i.e.*
the libpq used at compile time was version >= 8.3) but at runtime an older
libpq dynamic library is found.
Fast-forward several years, if the message reports *undefined symbol:
lo_truncate64* it means that Psycopg was built with large objects 64 bits
API support (*i.e.* the libpq used at compile time was at least 9.3) but
at runtime an older libpq dynamic library is found.
You can use:
.. code-block:: shell
$ ldd /path/to/packages/psycopg2/_psycopg.so | grep libpq
to find what is the libpq dynamic library used at runtime.
You can avoid the problem by using the same version of the
:program:`pg_config` at install time and the libpq at runtime.
.. |lo_truncate| replace:: `!lo_truncate()`
.. _lo_truncate: https://www.postgresql.org/docs/current/static/lo-interfaces.html#LO-TRUNCATE
.. _faq-import-mod_wsgi:
.. cssclass:: faq
Psycopg raises *ImportError: cannot import name tz* on import in mod_wsgi / ASP, but it works fine otherwise.
If `!psycopg2` is installed in an egg_ (e.g. because installed by
:program:`easy_install`), the user running the program may be unable to
write in the `eggs cache`__. Set the env variable
:envvar:`PYTHON_EGG_CACHE` to a writable directory. With modwsgi you can
use the WSGIPythonEggs__ directive.
.. _egg: http://peak.telecommunity.com/DevCenter/PythonEggs
.. __: https://stackoverflow.com/questions/2192323/what-is-the-python-egg-cache-python-egg-cache
.. __: https://modwsgi.readthedocs.io/en/develop/configuration-directives/WSGIPythonEggs.html

70
doc/src/index.rst Normal file
View File

@ -0,0 +1,70 @@
=================================================
Psycopg -- PostgreSQL database adapter for Python
=================================================
.. sectionauthor:: Daniele Varrazzo <daniele.varrazzo@gmail.com>
Psycopg_ is the most popular PostgreSQL_ database adapter for the Python_
programming language. Its main features are the complete implementation of
the Python |DBAPI|_ specification and the thread safety (several threads can
share the same connection). It was designed for heavily multi-threaded
applications that create and destroy lots of cursors and make a large number
of concurrent :sql:`INSERT`\s or :sql:`UPDATE`\s.
Psycopg 2 is mostly implemented in C as a libpq_ wrapper, resulting in being
both efficient and secure. It features client-side and :ref:`server-side
<server-side-cursors>` cursors, :ref:`asynchronous communication
<async-support>` and :ref:`notifications <async-notify>`, :ref:`COPY <copy>`
support. Many Python types are supported out-of-the-box and :ref:`adapted to
matching PostgreSQL data types <python-types-adaptation>`; adaptation can be
extended and customized thanks to a flexible :ref:`objects adaptation system
<adapting-new-types>`.
Psycopg 2 is both Unicode and Python 3 friendly.
.. _Psycopg: https://psycopg.org/
.. _PostgreSQL: https://www.postgresql.org/
.. _Python: https://www.python.org/
.. _libpq: https://www.postgresql.org/docs/current/static/libpq.html
.. rubric:: Contents
.. toctree::
:maxdepth: 2
install
usage
module
connection
cursor
advanced
extensions
extras
errors
sql
tz
pool
errorcodes
faq
news
license
.. ifconfig:: builder != 'text'
.. rubric:: Indices and tables
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
.. ifconfig:: todo_include_todos
.. note::
**To Do items in the documentation**
.. todolist::

357
doc/src/install.rst Normal file
View File

@ -0,0 +1,357 @@
.. _installation:
Installation
============
.. sectionauthor:: Daniele Varrazzo <daniele.varrazzo@gmail.com>
Psycopg is a PostgreSQL_ adapter for the Python_ programming language. It is a
wrapper for the libpq_, the official PostgreSQL client library.
.. _PostgreSQL: https://www.postgresql.org/
.. _Python: https://www.python.org/
.. index::
single: Install; from PyPI
single: Install; wheel
single: Wheel
.. _binary-packages:
Quick Install
-------------
For most operating systems, the quickest way to install Psycopg is using the
wheel_ package available on PyPI_:
.. code-block:: console
$ pip install psycopg2-binary
This will install a pre-compiled binary version of the module which does not
require the build or runtime prerequisites described below. Make sure to use
an up-date-date version of :program:`pip` (you can upgrade it using something
like ``pip install -U pip``).
You may then import the ``psycopg2`` package, as usual:
.. code-block:: python
import psycopg2
# Connect to your postgres DB
conn = psycopg2.connect("dbname=test user=postgres")
# Open a cursor to perform database operations
cur = conn.cursor()
# Execute a query
cur.execute("SELECT * FROM my_data")
# Retrieve query results
records = cur.fetchall()
.. _PyPI: https://pypi.org/project/psycopg2-binary/
.. _wheel: https://pythonwheels.com/
psycopg vs psycopg-binary
^^^^^^^^^^^^^^^^^^^^^^^^^
The ``psycopg2-binary`` package is meant for beginners to start playing
with Python and PostgreSQL without the need to meet the build
requirements.
If you are the maintainer of a published package depending on `!psycopg2`
you shouldn't use ``psycopg2-binary`` as a module dependency. **For
production use you are advised to use the source distribution.**
The binary packages come with their own versions of a few C libraries,
among which ``libpq`` and ``libssl``, which will be used regardless of other
libraries available on the client: upgrading the system libraries will not
upgrade the libraries used by `!psycopg2`. Please build `!psycopg2` from
source if you want to maintain binary upgradeability.
.. warning::
The `!psycopg2` wheel package comes packaged, among the others, with its
own ``libssl`` binary. This may create conflicts with other extension
modules binding with ``libssl`` as well, for instance with the Python
`ssl` module: in some cases, under concurrency, the interaction between
the two libraries may result in a segfault. In case of doubts you are
advised to use a package built from source.
.. index::
single: Install; disable wheel
single: Wheel; disable
.. _disable-wheel:
Change in binary packages between Psycopg 2.7 and 2.8
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In version 2.7.x, :command:`pip install psycopg2` would have tried to install
automatically the binary package of Psycopg. Because of concurrency problems
binary packages have displayed, ``psycopg2-binary`` has become a separate
package, and from 2.8 it has become the only way to install the binary
package.
If you are using Psycopg 2.7 and you want to disable the use of wheel binary
packages, relying on the system libraries available on your client, you
can use the :command:`pip` |--no-binary option|__, e.g.:
.. code-block:: console
$ pip install --no-binary :all: psycopg2
.. |--no-binary option| replace:: ``--no-binary`` option
.. __: https://pip.pypa.io/en/stable/reference/pip_install/#install-no-binary
which can be specified in your :file:`requirements.txt` files too, e.g. use:
.. code-block:: none
psycopg2>=2.7,<2.8 --no-binary psycopg2
to use the last bugfix release of the `!psycopg2` 2.7 package, specifying to
always compile it from source. Of course in this case you will have to meet
the :ref:`build prerequisites <build-prerequisites>`.
.. index::
single: Prerequisites
Prerequisites
-------------
The current `!psycopg2` implementation supports:
..
NOTE: keep consistent with setup.py and the /features/ page.
- Python versions from 3.6 to 3.9
- PostgreSQL server versions from 7.4 to 13
- PostgreSQL client library version from 9.1
.. _build-prerequisites:
Build prerequisites
^^^^^^^^^^^^^^^^^^^
The build prerequisites are to be met in order to install Psycopg from source
code, from a source distribution package, GitHub_ or from PyPI.
.. _GitHub: https://github.com/psycopg/psycopg2
Psycopg is a C wrapper around the libpq_ PostgreSQL client library. To install
it from sources you will need:
- A C compiler.
- The Python header files. They are usually installed in a package such as
**python-dev** or **python3-dev**. A message such as *error: Python.h: No
such file or directory* is an indication that the Python headers are
missing.
- The libpq header files. They are usually installed in a package such as
**libpq-dev**. If you get an *error: libpq-fe.h: No such file or directory*
you are missing them.
- The :program:`pg_config` program: it is usually installed by the
**libpq-dev** package but sometimes it is not in a :envvar:`PATH` directory.
Having it in the :envvar:`PATH` greatly streamlines the installation, so try
running ``pg_config --version``: if it returns an error or an unexpected
version number then locate the directory containing the :program:`pg_config`
shipped with the right libpq version (usually
``/usr/lib/postgresql/X.Y/bin/``) and add it to the :envvar:`PATH`:
.. code-block:: console
$ export PATH=/usr/lib/postgresql/X.Y/bin/:$PATH
You only need :program:`pg_config` to compile `!psycopg2`, not for its
regular usage.
Once everything is in place it's just a matter of running the standard:
.. code-block:: console
$ pip install psycopg2
or, from the directory containing the source code:
.. code-block:: console
$ python setup.py build
$ python setup.py install
Runtime requirements
^^^^^^^^^^^^^^^^^^^^
Unless you compile `!psycopg2` as a static library, or you install it from a
self-contained wheel package, it will need the libpq_ library at runtime
(usually distributed in a ``libpq.so`` or ``libpq.dll`` file). `!psycopg2`
relies on the host OS to find the library if the library is installed in a
standard location there is usually no problem; if the library is in a
non-standard location you will have to tell somehow Psycopg how to find it,
which is OS-dependent (for instance setting a suitable
:envvar:`LD_LIBRARY_PATH` on Linux).
.. note::
The libpq header files used to compile `!psycopg2` should match the
version of the library linked at runtime. If you get errors about missing
or mismatching libraries when importing `!psycopg2` check (e.g. using
:program:`ldd`) if the module ``psycopg2/_psycopg.so`` is linked to the
right ``libpq.so``.
.. note::
Whatever version of libpq `!psycopg2` is compiled with, it will be
possible to connect to PostgreSQL servers of any supported version: just
install the most recent libpq version or the most practical, without
trying to match it to the version of the PostgreSQL server you will have
to connect to.
.. index::
single: setup.py
single: setup.cfg
Non-standard builds
-------------------
If you have less standard requirements such as:
- creating a :ref:`debug build <debug-build>`,
- using :program:`pg_config` not in the :envvar:`PATH`,
then take a look at the ``setup.cfg`` file.
Some of the options available in ``setup.cfg`` are also available as command
line arguments of the ``build_ext`` sub-command. For instance you can specify
an alternate :program:`pg_config` location using:
.. code-block:: console
$ python setup.py build_ext --pg-config /path/to/pg_config build
Use ``python setup.py build_ext --help`` to get a list of the options
supported.
.. index::
single: debug
single: PSYCOPG_DEBUG
.. _debug-build:
Creating a debug build
^^^^^^^^^^^^^^^^^^^^^^
In case of problems, Psycopg can be configured to emit detailed debug
messages, which can be very useful for diagnostics and to report a bug. In
order to create a debug package:
- `Download`__ and unpack the Psycopg *source package* (the ``.tar.gz``
package).
- Edit the ``setup.cfg`` file adding the ``PSYCOPG_DEBUG`` flag to the
``define`` option.
- :ref:`Compile and install <build-prerequisites>` the package.
- Set the :envvar:`PSYCOPG_DEBUG` environment variable:
.. code-block:: console
$ export PSYCOPG_DEBUG=1
- Run your program (making sure that the `!psycopg2` package imported is the
one you just compiled and not e.g. the system one): you will have a copious
stream of informations printed on stderr.
.. __: https://pypi.org/project/psycopg2/#files
Non-standard Python Implementation
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The `psycopg2` package is the current mature implementation of the adapter: it
is a C extension and as such it is only compatible with CPython_. If you want
to use Psycopg on a different Python implementation (PyPy, Jython, IronPython)
there is a couple of alternative:
- a `Ctypes port`__, but it is not as mature as the C implementation yet
and it is not as feature-complete;
- a `CFFI port`__ which is currently more used and reported more efficient on
PyPy, but please be careful of its version numbers because they are not
aligned to the official psycopg2 ones and some features may differ.
.. _PostgreSQL: https://www.postgresql.org/
.. _Python: https://www.python.org/
.. _libpq: https://www.postgresql.org/docs/current/static/libpq.html
.. _CPython: https://en.wikipedia.org/wiki/CPython
.. _Ctypes: https://docs.python.org/library/ctypes.html
.. __: https://github.com/mvantellingen/psycopg2-ctypes
.. __: https://github.com/chtd/psycopg2cffi
.. index::
single: tests
.. _test-suite:
Running the test suite
----------------------
Once `!psycopg2` is installed you can run the test suite to verify it is
working correctly. From the source directory, you can run:
.. code-block:: console
$ python -c "import tests; tests.unittest.main(defaultTest='tests.test_suite')" --verbose
The tests run against a database called ``psycopg2_test`` on UNIX socket and
the standard port. You can configure a different database to run the test by
setting the environment variables:
- :envvar:`PSYCOPG2_TESTDB`
- :envvar:`PSYCOPG2_TESTDB_HOST`
- :envvar:`PSYCOPG2_TESTDB_PORT`
- :envvar:`PSYCOPG2_TESTDB_USER`
The database should already exist before running the tests.
.. _other-problems:
If you still have problems
--------------------------
Try the following. *In order:*
- Read again the :ref:`build-prerequisites`.
- Read the :ref:`FAQ <faq-compile>`.
- Google for `!psycopg2` *your error message*. Especially useful the week
after the release of a new OS X version.
- Write to the `Mailing List`_.
- If you think that you have discovered a bug, test failure or missing feature
please raise a ticket in the `bug tracker`_.
- Complain on your blog or on Twitter that `!psycopg2` is the worst package
ever and about the quality time you have wasted figuring out the correct
:envvar:`ARCHFLAGS`. Especially useful from the Starbucks near you.
.. _mailing list: https://www.postgresql.org/list/psycopg/
.. _bug tracker: https://github.com/psycopg/psycopg2/issues

7
doc/src/license.rst Normal file
View File

@ -0,0 +1,7 @@
.. index::
single: License
License
=======
.. include:: ../../LICENSE

388
doc/src/module.rst Normal file
View File

@ -0,0 +1,388 @@
The `psycopg2` module content
==================================
.. sectionauthor:: Daniele Varrazzo <daniele.varrazzo@gmail.com>
.. module:: psycopg2
The module interface respects the standard defined in the |DBAPI|_.
.. index::
single: Connection string
double: Connection; Parameters
single: Username; Connection
single: Password; Connection
single: Host; Connection
single: Port; Connection
single: DSN (Database Source Name)
.. function::
connect(dsn=None, connection_factory=None, cursor_factory=None, async=False, \*\*kwargs)
Create a new database session and return a new `connection` object.
The connection parameters can be specified as a `libpq connection
string`__ using the *dsn* parameter::
conn = psycopg2.connect("dbname=test user=postgres password=secret")
or using a set of keyword arguments::
conn = psycopg2.connect(dbname="test", user="postgres", password="secret")
or using a mix of both: if the same parameter name is specified in both
sources, the *kwargs* value will have precedence over the *dsn* value.
Note that either the *dsn* or at least one connection-related keyword
argument is required.
The basic connection parameters are:
- `!dbname` -- the database name (`!database` is a deprecated alias)
- `!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)
Any other connection parameter supported by the client library/server can
be passed either in the connection string or as a keyword. The PostgreSQL
documentation contains the complete list of the `supported parameters`__.
Also note that the same parameters can be passed to the client library
using `environment variables`__.
.. __:
.. _connstring: https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING
.. __:
.. _connparams: https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-PARAMKEYWORDS
.. __:
.. _connenvvars: https://www.postgresql.org/docs/current/static/libpq-envars.html
Using the *connection_factory* parameter a different class or
connections factory can be specified. It should be a callable object
taking a *dsn* string argument. See :ref:`subclassing-connection` for
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.
Using *async*\=\ `!True` an asynchronous connection will be created: see
:ref:`async-support` to know about advantages and limitations. *async_* is
a valid alias for the Python version where ``async`` is a keyword.
.. versionchanged:: 2.4.3
any keyword argument is passed to the connection. Previously only the
basic parameters (plus `!sslmode`) were supported as keywords.
.. versionchanged:: 2.5
added the *cursor_factory* parameter.
.. versionchanged:: 2.7
both *dsn* and keyword arguments can be specified.
.. versionchanged:: 2.7
added *async_* alias.
.. seealso::
- `~psycopg2.extensions.parse_dsn`
- libpq `connection string syntax`__
- libpq supported `connection parameters`__
- libpq supported `environment variables`__
.. __: connstring_
.. __: connparams_
.. __: connenvvars_
.. extension::
The non-connection-related keyword parameters are Psycopg extensions
to the |DBAPI|_.
.. data:: apilevel
String constant stating the supported DB API level. For `psycopg2` is
``2.0``.
.. data:: threadsafety
Integer constant stating the level of thread safety the interface
supports. For `psycopg2` is ``2``, i.e. threads can share the module
and the connection. See :ref:`thread-safety` for details.
.. data:: paramstyle
String constant stating the type of parameter marker formatting expected
by the interface. For `psycopg2` is ``pyformat``. See also
:ref:`query-parameters`.
.. data:: __libpq_version__
Integer constant reporting the version of the ``libpq`` library this
``psycopg2`` module was compiled with (in the same format of
`~psycopg2.extensions.ConnectionInfo.server_version`). If this value is
greater or equal than ``90100`` then you may query the version of the
actually loaded library using the `~psycopg2.extensions.libpq_version()`
function.
.. index::
single: Exceptions; DB API
.. _dbapi-exceptions:
Exceptions
----------
In compliance with the |DBAPI|_, the module makes informations about errors
available through the following exceptions:
.. exception:: Warning
Exception raised for important warnings like data truncations while
inserting, etc. It is a subclass of the Python `StandardError`
(`Exception` on Python 3).
.. exception:: Error
Exception that is the base class of all other error exceptions. You can
use this to catch all errors with one single `!except` statement. Warnings
are not considered errors and thus not use this class as base. It
is a subclass of the Python `StandardError` (`Exception` on Python 3).
.. attribute:: pgerror
String representing the error message returned by the backend,
`!None` if not available.
.. attribute:: pgcode
String representing the error code returned by the backend, `!None`
if not available. The `~psycopg2.errorcodes` module contains
symbolic constants representing PostgreSQL error codes.
.. doctest::
:options: +NORMALIZE_WHITESPACE
>>> try:
... cur.execute("SELECT * FROM barf")
... except psycopg2.Error as e:
... pass
>>> e.pgcode
'42P01'
>>> print e.pgerror
ERROR: relation "barf" does not exist
LINE 1: SELECT * FROM barf
^
.. attribute:: cursor
The cursor the exception was raised from; `None` if not applicable.
.. attribute:: diag
A `~psycopg2.extensions.Diagnostics` object containing further
information about the error. ::
>>> try:
... cur.execute("SELECT * FROM barf")
... except psycopg2.Error, e:
... pass
>>> e.diag.severity
'ERROR'
>>> e.diag.message_primary
'relation "barf" does not exist'
.. versionadded:: 2.5
.. extension::
The `~Error.pgerror`, `~Error.pgcode`, `~Error.cursor`, and
`~Error.diag` attributes are Psycopg extensions.
.. exception:: InterfaceError
Exception raised for errors that are related to the database interface
rather than the database itself. It is a subclass of `Error`.
.. exception:: DatabaseError
Exception raised for errors that are related to the database. It is a
subclass of `Error`.
.. exception:: DataError
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
subclass of `DatabaseError`.
.. exception:: OperationalError
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
during processing, etc. It is a subclass of `DatabaseError`.
.. exception:: IntegrityError
Exception raised when the relational integrity of the database is
affected, e.g. a foreign key check fails. It is a subclass of
`DatabaseError`.
.. exception:: InternalError
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
subclass of `DatabaseError`.
.. exception:: ProgrammingError
Exception raised for programming errors, e.g. table not found or already
exists, syntax error in the SQL statement, wrong number of parameters
specified, etc. It is a subclass of `DatabaseError`.
.. exception:: NotSupportedError
Exception raised in case a method or database API was used which is not
supported by the database, e.g. requesting a `!rollback()` on a
connection that does not support transaction or has transactions turned
off. It is a subclass of `DatabaseError`.
.. extension::
Psycopg actually raises a different exception for each :sql:`SQLSTATE`
error returned by the database: the classes are available in the
`psycopg2.errors` module. Every exception class is a subclass of one of
the exception classes defined here though, so they don't need to be
trapped specifically: trapping `!Error` or `!DatabaseError` is usually
what needed to write a generic error handler; trapping a specific error
such as `!NotNullViolation` can be useful to write specific exception
handlers.
This is the exception inheritance layout:
.. parsed-literal::
`!StandardError`
\|__ `Warning`
\|__ `Error`
\|__ `InterfaceError`
\|__ `DatabaseError`
\|__ `DataError`
\|__ `OperationalError`
\|__ `IntegrityError`
\|__ `InternalError`
\|__ `ProgrammingError`
\|__ `NotSupportedError`
.. _type-objects-and-constructors:
Type Objects and Constructors
-----------------------------
.. note::
This section is mostly copied verbatim from the |DBAPI|_
specification. While these objects are exposed in compliance to the
DB API, Psycopg offers very accurate tools to convert data between Python
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:
.. function:: Date(year,month,day)
This function constructs an object holding a date value.
.. function:: Time(hour,minute,second)
This function constructs an object holding a time value.
.. 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)
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).
.. 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)
This function constructs an object capable of holding a binary (long)
string value.
.. 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.
.. 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).
.. data:: NUMBER
This type object is used to describe numeric columns in a database.
.. data:: DATETIME
This type object is used to describe date/time columns in a database.
.. data:: ROWID
This type object is used to describe the "Row ID" column in a database.
.. testcode::
:hide:
conn.rollback()

8
doc/src/news.rst Normal file
View File

@ -0,0 +1,8 @@
.. index::
single: Release notes
single: News
Release notes
=============
.. include:: ../../NEWS

60
doc/src/pool.rst Normal file
View File

@ -0,0 +1,60 @@
`psycopg2.pool` -- Connections pooling
======================================
.. sectionauthor:: Daniele Varrazzo <daniele.varrazzo@gmail.com>
.. index::
pair: Connection; Pooling
.. module:: psycopg2.pool
Creating new PostgreSQL connections can be an expensive operation. This
module offers a few pure Python classes implementing simple connection pooling
directly in the client application.
.. class:: AbstractConnectionPool(minconn, maxconn, \*args, \*\*kwargs)
Base class implementing generic key-based pooling code.
New *minconn* connections are created automatically. The pool will support
a maximum of about *maxconn* connections. *\*args* and *\*\*kwargs* are
passed to the `~psycopg2.connect()` function.
The following methods are expected to be implemented by subclasses:
.. method:: getconn(key=None)
Get a free connection from the pool.
The *key* parameter is optional: if used, the connection will be
associated to the key and calling `!getconn()` with the same key again
will return the same connection.
.. method:: putconn(conn, key=None, close=False)
Put away a connection.
If *close* is `!True`, discard the connection from the pool.
*key* should be used consistently with `getconn()`.
.. method:: closeall
Close all the connections handled by the pool.
Note that all the connections are closed, including ones
eventually in use by the application.
The following classes are `AbstractConnectionPool` subclasses ready to
be used.
.. autoclass:: SimpleConnectionPool
.. note:: This pool class is useful only for single-threaded applications.
.. index:: Multithread; Connection pooling
.. autoclass:: ThreadedConnectionPool
.. note:: This pool class can be safely used in multi-threaded applications.

147
doc/src/sql.rst Normal file
View File

@ -0,0 +1,147 @@
`psycopg2.sql` -- SQL string composition
========================================
.. sectionauthor:: Daniele Varrazzo <daniele.varrazzo@gmail.com>
.. module:: psycopg2.sql
.. versionadded:: 2.7
The module contains objects and functions useful to generate SQL dynamically,
in a convenient and safe way. SQL identifiers (e.g. names of tables and
fields) cannot be passed to the `~cursor.execute()` method like query
arguments::
# This will not work
table_name = 'my_table'
cur.execute("insert into %s values (%s, %s)", [table_name, 10, 20])
The SQL query should be composed before the arguments are merged, for
instance::
# This works, but it is not optimal
table_name = 'my_table'
cur.execute(
"insert into %s values (%%s, %%s)" % table_name,
[10, 20])
This sort of works, but it is an accident waiting to happen: the table name
may be an invalid SQL literal and need quoting; even more serious is the
security problem in case the table name comes from an untrusted source. The
name should be escaped using `~psycopg2.extensions.quote_ident()`::
# This works, but it is not optimal
table_name = 'my_table'
cur.execute(
"insert into %s values (%%s, %%s)" % ext.quote_ident(table_name),
[10, 20])
This is now safe, but it somewhat ad-hoc. In case, for some reason, it is
necessary to include a value in the query string (as opposite as in a value)
the merging rule is still different (`~psycopg2.extensions.adapt()` should be
used...). It is also still relatively dangerous: if `!quote_ident()` is
forgotten somewhere, the program will usually work, but will eventually crash
in the presence of a table or field name with containing characters to escape,
or will present a potentially exploitable weakness.
The objects exposed by the `!psycopg2.sql` module allow generating SQL
statements on the fly, separating clearly the variable parts of the statement
from the query parameters::
from psycopg2 import sql
cur.execute(
sql.SQL("insert into {} values (%s, %s)")
.format(sql.Identifier('my_table')),
[10, 20])
Module usage
------------
Usually you should express the template of your query as an `SQL` instance
with `{}`\-style placeholders and use `~SQL.format()` to merge the variable
parts into them, all of which must be `Composable` subclasses. You can still
have `%s`\ -style placeholders in your query and pass values to
`~cursor.execute()`: such value placeholders will be untouched by
`!format()`::
query = sql.SQL("select {field} from {table} where {pkey} = %s").format(
field=sql.Identifier('my_name'),
table=sql.Identifier('some_table'),
pkey=sql.Identifier('id'))
The resulting object is meant to be passed directly to cursor methods such as
`~cursor.execute()`, `~cursor.executemany()`, `~cursor.copy_expert()`, but can
also be used to compose a query as a Python string, using the
`~Composable.as_string()` method::
cur.execute(query, (42,))
If part of your query is a variable sequence of arguments, such as a
comma-separated list of field names, you can use the `SQL.join()` method to
pass them to the query::
query = sql.SQL("select {fields} from {table}").format(
fields=sql.SQL(',').join([
sql.Identifier('field1'),
sql.Identifier('field2'),
sql.Identifier('field3'),
]),
table=sql.Identifier('some_table'))
`!sql` objects
--------------
The `!sql` objects are in the following inheritance hierarchy:
| `Composable`: the base class exposing the common interface
| ``|__`` `SQL`: a literal snippet of an SQL query
| ``|__`` `Identifier`: a PostgreSQL identifier or dot-separated sequence of identifiers
| ``|__`` `Literal`: a value hardcoded into a query
| ``|__`` `Placeholder`: a `%s`\ -style placeholder whose value will be added later e.g. by `~cursor.execute()`
| ``|__`` `Composed`: a sequence of `!Composable` instances.
.. autoclass:: Composable
.. automethod:: as_string
.. autoclass:: SQL
.. autoattribute:: string
.. automethod:: format
.. automethod:: join
.. autoclass:: Identifier
.. versionchanged:: 2.8
added support for multiple strings.
.. autoattribute:: strings
.. versionadded:: 2.8
previous verions only had a `!string` attribute. The attribute
still exists but is deprecate and will only work if the
`!Identifier` wraps a single string.
.. autoclass:: Literal
.. autoattribute:: wrapped
.. autoclass:: Placeholder
.. autoattribute:: name
.. autoclass:: Composed
.. autoattribute:: seq
.. automethod:: join

View File

@ -0,0 +1,50 @@
"""
extension
~~~~~~~~~
A directive to create a box warning that a certain bit of Psycopg is an
extension to the DBAPI 2.0.
:copyright: Copyright 2010 by Daniele Varrazzo.
"""
from docutils import nodes
from sphinx.locale import _
from docutils.parsers.rst import Directive
class extension_node(nodes.Admonition, nodes.Element): pass
class Extension(Directive):
"""
An extension entry, displayed as an admonition.
"""
has_content = True
required_arguments = 0
optional_arguments = 0
final_argument_whitespace = False
option_spec = {}
def run(self):
node = extension_node('\n'.join(self.content))
node += nodes.title(_('DB API extension'), _('DB API extension'))
self.state.nested_parse(self.content, self.content_offset, node)
node['classes'].append('dbapi-extension')
return [node]
def visit_extension_node(self, node):
self.visit_admonition(node)
def depart_extension_node(self, node):
self.depart_admonition(node)
def setup(app):
app.add_node(extension_node,
html=(visit_extension_node, depart_extension_node),
latex=(visit_extension_node, depart_extension_node),
text=(visit_extension_node, depart_extension_node))
app.add_directive('extension', Extension)

View File

@ -0,0 +1,19 @@
"""
sql role
~~~~~~~~
An interpreted text role to style SQL syntax in Psycopg documentation.
:copyright: Copyright 2010 by Daniele Varrazzo.
"""
from docutils import nodes, utils
from docutils.parsers.rst import roles
def sql_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
text = utils.unescape(text)
options['classes'] = ['sql']
return [nodes.literal(rawtext, text, **options)], []
def setup(app):
roles.register_local_role('sql', sql_role)

View File

@ -0,0 +1,57 @@
"""
ticket role
~~~~~~~~~~~
An interpreted text role to link docs to tickets issues.
:copyright: Copyright 2013 by Daniele Varrazzo.
"""
import re
from docutils import nodes, utils
from docutils.parsers.rst import roles
def ticket_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
cfg = inliner.document.settings.env.app.config
if cfg.ticket_url is None:
msg = inliner.reporter.warning(
"ticket not configured: please configure ticket_url in conf.py")
prb = inliner.problematic(rawtext, rawtext, msg)
return [prb], [msg]
rv = [nodes.Text(name + ' ')]
tokens = re.findall(r'(#?\d+)|([^\d#]+)', text)
for ticket, noise in tokens:
if ticket:
num = int(ticket.replace('#', ''))
# Push numbers of the oldel tickets ahead.
# We moved the tickets from a different tracker to GitHub and the
# latter already had a few ticket numbers taken (as merge
# requests).
remap_until = cfg.ticket_remap_until
remap_offset = cfg.ticket_remap_offset
if remap_until and remap_offset:
if num <= remap_until:
num += remap_offset
url = cfg.ticket_url % num
roles.set_classes(options)
node = nodes.reference(ticket, utils.unescape(ticket),
refuri=url, **options)
rv.append(node)
else:
assert noise
rv.append(nodes.Text(noise))
return rv, []
def setup(app):
app.add_config_value('ticket_url', None, 'env')
app.add_config_value('ticket_remap_until', None, 'env')
app.add_config_value('ticket_remap_offset', None, 'env')
app.add_role('ticket', ticket_role)
app.add_role('tickets', ticket_role)

View File

@ -0,0 +1,57 @@
#!/usr/bin/env python
"""Create the docs table of the sqlstate errors.
"""
import re
import sys
from collections import namedtuple
from psycopg2._psycopg import sqlstate_errors
def main():
sqlclasses = {}
clsfile = sys.argv[1]
with open(clsfile) as f:
for l in f:
m = re.match(r'/\* Class (..) - (.+) \*/', l)
if m is not None:
sqlclasses[m.group(1)] = m.group(2)
Line = namedtuple('Line', 'colstate colexc colbase sqlstate')
lines = [Line('SQLSTATE', 'Exception', 'Base exception', None)]
for k in sorted(sqlstate_errors):
exc = sqlstate_errors[k]
lines.append(Line(
f"``{k}``", f"`!{exc.__name__}`",
f"`!{get_base_exception(exc).__name__}`", k))
widths = [max(len(l[c]) for l in lines) for c in range(3)]
h = Line(*(['=' * w for w in widths] + [None]))
lines.insert(0, h)
lines.insert(2, h)
lines.append(h)
h1 = '-' * (sum(widths) + len(widths) - 1)
sqlclass = None
for l in lines:
cls = l.sqlstate[:2] if l.sqlstate else None
if cls and cls != sqlclass:
print(f"**Class {cls}**: {sqlclasses[cls]}")
print(h1)
sqlclass = cls
print("%-*s %-*s %-*s" % (
widths[0], l.colstate, widths[1], l.colexc, widths[2], l.colbase))
def get_base_exception(exc):
for cls in exc.__mro__:
if cls.__module__ == 'psycopg2':
return cls
if __name__ == '__main__':
sys.exit(main())

19
doc/src/tz.rst Normal file
View File

@ -0,0 +1,19 @@
`psycopg2.tz` -- ``tzinfo`` implementations for Psycopg 2
===============================================================
.. sectionauthor:: Daniele Varrazzo <daniele.varrazzo@gmail.com>
.. module:: psycopg2.tz
.. deprecated:: 2.9
The module will be dropped in psycopg 2.10. Use `datetime.timezone`
instead.
This module holds two different tzinfo implementations that can be used as the
`tzinfo` argument to `~datetime.datetime` constructors, directly passed to
Psycopg functions or used to set the `cursor.tzinfo_factory` attribute in
cursors.
.. autoclass:: psycopg2.tz.FixedOffsetTimezone
.. autoclass:: psycopg2.tz.LocalTimezone

1106
doc/src/usage.rst Normal file

File diff suppressed because it is too large Load Diff