diff options
author | Daniele Varrazzo <daniele.varrazzo@gmail.com> | 2010-02-14 16:11:01 +0000 |
---|---|---|
committer | Daniele Varrazzo <daniele.varrazzo@gmail.com> | 2010-02-14 16:45:36 +0000 |
commit | b744c92f58ab3dfc65d51dfe61acc11427a192dd (patch) | |
tree | 04d4f89e839fde6384371589dabb6aae01e773d8 /doc/src | |
parent | 620f77cb77304e1b03d311204e5f942109b1a5f4 (diff) | |
download | psycopg2-b744c92f58ab3dfc65d51dfe61acc11427a192dd.tar.gz |
Documentation dir reordered.
Diffstat (limited to 'doc/src')
-rw-r--r-- | doc/src/Makefile | 99 | ||||
-rw-r--r-- | doc/src/_static/psycopg.css | 21 | ||||
-rw-r--r-- | doc/src/advanced.rst | 340 | ||||
-rw-r--r-- | doc/src/conf.py | 257 | ||||
-rw-r--r-- | doc/src/connection.rst | 305 | ||||
-rw-r--r-- | doc/src/cursor.rst | 509 | ||||
-rw-r--r-- | doc/src/errorcodes.rst | 41 | ||||
-rw-r--r-- | doc/src/extensions.rst | 410 | ||||
-rw-r--r-- | doc/src/extras.rst | 149 | ||||
-rw-r--r-- | doc/src/index.rst | 59 | ||||
-rw-r--r-- | doc/src/module.rst | 308 | ||||
-rwxr-xr-x | doc/src/tools/lib/dbapi_extension.py | 52 | ||||
-rw-r--r-- | doc/src/tools/lib/sql_role.py | 21 | ||||
-rwxr-xr-x | doc/src/tools/stitch_text.py | 56 | ||||
-rw-r--r-- | doc/src/tz.rst | 18 | ||||
-rw-r--r-- | doc/src/usage.rst | 482 |
16 files changed, 3127 insertions, 0 deletions
diff --git a/doc/src/Makefile b/doc/src/Makefile new file mode 100644 index 0000000..53d0680 --- /dev/null +++ b/doc/src/Makefile @@ -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." diff --git a/doc/src/_static/psycopg.css b/doc/src/_static/psycopg.css new file mode 100644 index 0000000..df52b32 --- /dev/null +++ b/doc/src/_static/psycopg.css @@ -0,0 +1,21 @@ +@import url("default.css"); + +div.admonition-todo { + background-color: #ffa; + border: 1px solid #ee2; +} + +div.dbapi-extension { + background-color: #eef; + border: 1px solid #aaf; +} + +tt.sql { + font-size: 1em; + background-color: transparent; +} + +a > tt.sql:hover { + text-decoration: underline; +} + diff --git a/doc/src/advanced.rst b/doc/src/advanced.rst new file mode 100644 index 0000000..64aa704 --- /dev/null +++ b/doc/src/advanced.rst @@ -0,0 +1,340 @@ +More advanced topics +==================== + +.. sectionauthor:: Daniele Varrazzo <daniele.varrazzo@gmail.com> + +.. testsetup:: * + + import re + + cur.execute("CREATE TABLE atable (apoint point)") + conn.commit() + +.. 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: :class:`psycopg2.extensions.cursor` +and :class:`psycopg2.extensions.connection`. The :class:`connection` class is +usually sub-classed only to provide an easy way to create customized cursors +but other uses are possible. :class:`cursor` is much more interesting, because +it is the class where query building, execution and result type-casting into +Python variables happens. + +.. 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 :func:`psycopg2.extensions.adapt` function. + +The :meth:`~cursor.execute` method adapts its arguments to the +:class:`~psycopg2.extensions.ISQLQuote` protocol. Objects that conform to this +protocol expose a :meth:`!getquoted` method returning the SQL representation +of the object as a string. + +The easiest way to adapt an object to an SQL string is to register an adapter +function via the :func:`~psycopg2.extensions.register_adapter` function. The +adapter function must take the value to be adapted as argument and return a +conform object. A convenient object is the :class:`~psycopg2.extensions.AsIs` +wrapper, whose :meth:`!getquoted` result is simply the :meth:`!str`\ ing +conversion of the wrapped object. + +.. index:: + single: Example; Types adaptation + +Example: mapping of a :class:`!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): + ... return AsIs("'(%s, %s)'" % (adapt(point.x), adapt(point.y))) + + >>> register_adapter(Point, adapt_point) + + >>> cur.execute("INSERT INTO atable (apoint) VALUES (%s)", + ... (Point(1.23, 4.56),)) + + +.. |point| replace:: :sql:`point` +.. _point: http://www.postgresql.org/docs/8.4/static/datatype-geometric.html#AEN6084 + +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 :class:`!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 :attr:`cursor.description`: + + >>> cur.execute("SELECT NULL::point") + >>> point_oid = cur.description[0][1] + >>> point_oid + 600 + +or by querying the system catalogs 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 must can and register the new type: + + >>> POINT = psycopg2.extensions.new_type((point_oid,), "POINT", cast_point) + >>> psycopg2.extensions.register_type(POINT) + +The :func:`~psycopg2.extensions.new_type` function binds the object OIDs +(more than one can be specified) to the adapter function. +:func:`~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 + + + +.. 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 of how to use this form of +communications. + +Notifications received are made available in the :attr:`connection.notifies` +list. Notifications can be sent from Python code simply using a :sql:`NOTIFY` +command in an :meth:`~cursor.execute` call. + +Because of the way sessions interact with notifications (see |NOTIFY|_ +documentation), you should keep the connection in :ref:`autocommit +<autocommit>` mode while sending and receiveng notification. + +.. |LISTEN| replace:: :sql:`LISTEN` +.. _LISTEN: http://www.postgresql.org/docs/8.4/static/sql-listen.html +.. |NOTIFY| replace:: :sql:`NOTIFY` +.. _NOTIFY: http://www.postgresql.org/docs/8.4/static/sql-notify.html + +.. index:: + single: Example; Asynchronous notification + +Example:: + + import sys + 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 'NOTIFY test'" + while 1: + if select.select([curs],[],[],5)==([],[],[]): + print "Timeout" + else: + if curs.isready(): + print "Got NOTIFY:", curs.connection.notifies.pop() + +Running the script and executing the command :sql:`NOTIFY test` in a separate +:program:`psql` shell, the output may look similar to:: + + Waiting for 'NOTIFY test' + Timeout + Timeout + Got NOTIFY: (6535, 'test') + Timeout + ... + + + +.. index:: + double: Asynchronous; Query + +.. _asynchronous-queries: + +Asynchronous queries +-------------------- + +.. warning:: + + Psycopg support for asynchronous queries is still experimental and the + informations reported here may be out of date. + + Discussion, testing and suggestions are welcome. + +Program code can initiate an asynchronous query by passing an ``async=1`` flag +to the :meth:`~cursor.execute` or :meth:`~cursor.callproc` cursor methods. A +very simple example, from the connection to the query:: + + conn = psycopg2.connect(database='test') + curs = conn.cursor() + curs.execute("SELECT * from test WHERE fielda > %s", (1971,), async=1) + +From then on any query on other cursors derived from the same connection is +doomed to fail (and raise an exception) until the original cursor (the one +executing the query) complete the asynchronous operation. This can happen in +a number of different ways: + +1) one of the :meth:`!fetch*` methods is called, effectively blocking until + data has been sent from the backend to the client, terminating the query. + +2) :meth:`connection.cancel` is called. This method tries to abort the + current query and will block until the query is aborted or fully executed. + The return value is ``True`` if the query was successfully aborted or + ``False`` if it was executed. Query result are discarded in both cases. + +3) :meth:`~cursor.execute` is called again on the same cursor + (:meth:`!execute` on a different cursor will simply raise an exception). + This waits for the complete execution of the current query, discard any + data and execute the new one. + +Note that calling :meth:`!execute` two times in a row will not abort the +former query and will temporarily go to synchronous mode until the first of +the two queries is executed. + +Cursors now have some extra methods that make them useful during +asynchronous queries: + +:meth:`~cursor.fileno` + Returns the file descriptor associated with the current connection and + make possible to use a cursor in a context where a file object would be + expected (like in a :func:`select` call). + +:meth:`~cursor.isready` + Returns ``False`` if the backend is still processing the query or ``True`` + if data is ready to be fetched (by one of the :meth:`!fetch*` methods). + +.. index:: + single: Example; Asynchronous query + +A code snippet that shows how to use the cursor object in a :func:`!select` +call:: + + import psycopg2 + import select + + conn = psycopg2.connect(database='test') + curs = conn.cursor() + curs.execute("SELECT * from test WHERE fielda > %s", (1971,), async=1) + + # wait for input with a maximum timeout of 5 seconds + query_ended = False + while not query_ended: + rread, rwrite, rspec = select([curs, another_file], [], [], 5) + + if curs.isready(): + query_ended = True + + # manage input from other sources like other_file, etc. + + print "Query Results:" + for row in curs: + print row + + +.. testcode:: + :hide: + + conn.rollback() + cur.execute("DROP TABLE atable") + conn.commit() + cur.close() + conn.close() diff --git a/doc/src/conf.py b/doc/src/conf.py new file mode 100644 index 0000000..f7f370b --- /dev/null +++ b/doc/src/conf.py @@ -0,0 +1,257 @@ +# -*- coding: utf-8 -*- +# +# 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 sys, os + +# 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'] + +# Specific extensions for Psycopg documentation. +extensions += [ 'dbapi_extension', 'sql_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 = u'Psycopg' +copyright = u'2001-2010, Federico Di Gregorio. Documentation by Daniele Varrazzo' + +# 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 + release = psycopg2.__version__.split()[0] +except ImportError: + print "WARNING: couldn't import psycopg to read version." + release = version + +# 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 = None + +# 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 + +# 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 = True + +rst_epilog = """ +.. |DBAPI| replace:: DB API 2.0 + +.. _DBAPI: http://www.python.org/dev/peps/pep-0249/ + +.. _transaction isolation level: + http://www.postgresql.org/docs/8.4/static/transaction-iso.html + +.. _serializable isolation level: + http://www.postgresql.org/docs/8.4/static/transaction-iso.html#XACT-SERIALIZABLE + +.. _mx.DateTime: http://www.egenix.com/products/python/mxBase/mxDateTime/ + +.. |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 = 'default' + +# The stylesheet to use with HTML output: this will include the original one +# adding a few classes. +html_style = 'psycopg.css' + +# 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 = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_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 = None + +# 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. +#html_sidebars = {} + +# 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', u'Psycopg Documentation', + u'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() + +""" diff --git a/doc/src/connection.rst b/doc/src/connection.rst new file mode 100644 index 0000000..c7da5f1 --- /dev/null +++ b/doc/src/connection.rst @@ -0,0 +1,305 @@ +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 + :func:`~psycopg2.connect`. + + Connections are thread safe and can be shared among many thread. See + :ref:`thread-safety` for details. + + .. method:: cursor([name] [, cursor_factory]) + + Return a new :class:`cursor` object using the connection. + + If :obj:`!name` is specified, the returned cursor will be a *server + side* (or *named*) cursor. Otherwise the cursor will be *client side*. + See :ref:`server-side-cursors` for further details. + + The :obj:`!cursor_factory` argument can be used to create non-standard + cursors. The class returned should be a subclass of + :class:`psycopg2.extensions.cursor`. See :ref:`subclassing-cursor` for + details. + + .. extension:: + + The :obj:`!name` and :obj:`!cursor_factory` parameters are Psycopg + extensions to the |DBAPI|. + + + .. index:: + pair: Transaction; Commit + + .. method:: commit() + + Commit any pending transaction to the database. Psycopg can be set to + perform automatic commits at each operation, see + :meth:`~connection.set_isolation_level`. + + + .. 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. + + + .. method:: close() + + Close the connection now (rather than whenever :meth:`__del__` is + called). The connection will be unusable from this point forward; an + :exc:`~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 an implicit rollback to be + performed (unless a different isolation level has been selected: see + :meth:`~connection.set_isolation_level`). + + + .. index:: + single: Exceptions; In the connection class + + .. rubric:: Excetptions as connection class attributes + + The :class:`!connection` also exposes as attributes the same exceptions + available in the :mod:`psycopg2` module. See :ref:`dbapi-exceptions`. + + + .. 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 attribute reporting whether the database connection is open + (0) or closed (1). + + + .. 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. + + .. |RESET| replace:: :sql:`RESET` + .. _RESET: http://www.postgresql.org/docs/8.4/static/sql-reset.html + + .. |SET SESSION AUTHORIZATION| replace:: :sql:`SET SESSION AUTHORIZATION` + .. __: http://www.postgresql.org/docs/8.4/static/sql-set-session-authorization.html + + .. versionadded:: 2.0.12 + + + .. attribute:: dsn + + Read-only string containing the connection string used by the + connection. + + + .. index:: + pair: Transaction; Autocommit + pair: Transaction; Isolation level + + .. _autocommit: + + .. attribute:: isolation_level + .. method:: set_isolation_level(level) + + Read or 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 or read is an integer: symbolic constants are defined in + the module :mod:`psycopg2.extensions`: see + :ref:`isolation-level-constants` for the available values. + + The default level is :sql:`READ COMMITTED`: in this level a transaction + is automatically started every time a database command is executed. If + you want an *autocommit* mode, switch to + :obj:`~psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT` + before executing any command:: + + >>> conn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT) + + + .. 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`__ + + .. __: http://www.postgresql.org/docs/8.4/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'] + + To avoid a leak in case excessive notices are generated, only the last + 50 messages are kept. + + You can configure what messages to receive using `PostgreSQL logging + configuration parameters`__ such as ``log_statement``, + ``client_min_messages``, ``log_min_duration_statement`` etc. + + .. __: http://www.postgresql.org/docs/8.4/static/runtime-config-logging.html + + + .. attribute:: notifies + + List containing asynchronous notifications received by the session. + + Received notifications have the form of a 2 items tuple + :samp:`({pid},{name})`, where :samp:`{pid}` is the PID of the backend + that sent the notification and :samp:`{name}` is the signal name + specified in the :sql:`NOTIFY` command. + + For other details see :ref:`async-notify`. + + .. index:: + pair: Backend; PID + + .. method:: get_backend_pid() + + Returns the process ID (PID) of the backend server process handling + this connection. + + 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. + + .. __: http://www.postgresql.org/docs/8.4/static/libpq-status.html#AEN33590 + + .. versionadded:: 2.0.8 + + + .. index:: + pair: Server; Parameters + + .. method:: get_parameter_status(parameter) + + 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. + + .. __: http://www.postgresql.org/docs/8.4/static/libpq-status.html#AEN33499 + + .. versionadded:: 2.0.12 + + + .. index:: + pair: Transaction; Status + + .. method:: get_transaction_status() + + Return the current session transaction status as an integer. Symbolic + constants for the values are defined in the module + :mod:`psycopg2.extensions`: see :ref:`transaction-status-constants` + for the available values. + + .. seealso:: libpq docs for `PQtransactionStatus()`__ for details. + + .. __: http://www.postgresql.org/docs/8.4/static/libpq-status.html#AEN33480 + + + .. index:: + pair: Protocol; Version + + .. attribute:: protocol_version + + A read-only integer representing frontend/backend protocol being used. + It can be 2 or 3. + + .. seealso:: libpq docs for `PQprotocolVersion()`__ for details. + + .. __: http://www.postgresql.org/docs/8.4/static/libpq-status.html#AEN33546 + + .. versionadded:: 2.0.12 + + + .. index:: + pair: Server; Version + + .. attribute:: 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. + + .. __: http://www.postgresql.org/docs/8.4/static/libpq-status.html#AEN33556 + + .. versionadded:: 2.0.12 + + + .. 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 + :mod:`psycopg2.extensions`: see :ref:`connection-status-constants` + for the available values. + + + .. method:: lobject([oid [, mode [, new_oid [, new_file [, lobject_factory]]]]]) + + Return a new database large object. + + The ``lobject_factory`` argument can be used to create non-standard + lobjects by passing a class different from the default. Note that the + new class *should* be a sub-class of + :class:`psycopg2.extensions.lobject`. + + .. todo:: conn.lobject details + + .. versionadded:: 2.0.8 diff --git a/doc/src/cursor.rst b/doc/src/cursor.rst new file mode 100644 index 0000000..b46f129 --- /dev/null +++ b/doc/src/cursor.rst @@ -0,0 +1,509 @@ +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 :meth:`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 :meth:`~connection.rollback` and + :meth:`~connection.commit` methods. + + Cursors are *not* thread safe: a multithread application can create + many cursors from the same same connection and should use each cursor from + a single thread. See :ref:`thread-safety` for details. + + + .. attribute:: description + + This read-only attribute is a sequence of 7-item sequences. + + Each of these sequences contains information describing one result + column: + + - ``name`` + - ``type_code`` + - ``display_size`` + - ``internal_size`` + - ``precision`` + - ``scale`` + - ``null_ok`` + + The first two items (``name`` and ``type_code``) are always specified, + the other five are optional and are set to ``None`` if no meaningful + values can be provided. + + This attribute will be ``None`` for operations that do not return rows + or if the cursor has not had an operation invoked via the + |execute*|_ methods yet. + + The ``type_code`` can be interpreted by comparing it to the Type + Objects specified in the section :ref:`type-objects-and-constructors`. + It is also used to register typecasters to convert PostgreSQL types to + Python objects: see :ref:`type-casting-from-sql-to-python`. + + + .. method:: close() + + Close the cursor now (rather than whenever :meth:`!__del__` is + called). The cursor will be unusable from this point forward; an + :exc:`~psycopg2.InterfaceError` will be raised if any operation is + attempted with the cursor. + + .. attribute:: closed + + Read-only boolean attribute: specifies if the cursor is closed + (``True``) or not (``False``). + + .. extension:: + + The :attr:`closed` attribute is a Psycopg extension to the + |DBAPI|. + + .. versionadded:: 2.0.7 + + + .. attribute:: connection + + Read-only attribute returning a reference to the :class:`connection` + object on which the cursor was created. + + + .. attribute:: name + + Read-only attribute containing the name of the cursor if it was + creates as named cursor by :meth:`connection.cursor`, or ``None`` if + it is a client side cursor. See :ref:`server-side-cursors`. + + .. extension:: + + The :attr:`name` attribute is a Psycopg extension to the |DBAPI|. + + + + .. |execute*| replace:: :meth:`execute*` + + .. _execute*: + + .. rubric:: Commands execution methods + + + .. method:: execute(operation [, parameters] [, async]) + + Prepare and 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. + + If :obj:`!async` is ``True``, query execution will be asynchronous: + the function returns immediately while the query is executed by the + backend. Use the :meth:`~cursor.isready` method to see if the data is + ready for return via |fetch*|_ methods. See + :ref:`asynchronous-queries`. + + .. extension:: + + The :obj:`async` parameter is a Psycopg extension to the |DBAPI|. + + + .. 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 + :meth:`~cursor.execute` method or similar. + + >>> cur.mogrify("INSERT INTO test (num, data) VALUES (%s, %s)", (42, 'bar')) + "INSERT INTO test (num, data) VALUES (42, E'bar')" + + .. extension:: + + The :meth:`mogrify` method is a Psycopg extension to the |DBAPI|. + + + .. method:: executemany(operation, seq_of_parameters) + + Prepare a database operation (query or command) and then execute it + against all parameter tuples or mappings found in the sequence + :obj:`!seq_of_parameters`. + + 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 :meth:`~cursor.execute` method. + + + .. method:: callproc(procname [, parameters] [, async]) + + Call a stored database procedure with the given name. The sequence of + parameters must contain one entry for each argument that the procedure + expects. The result of the call is returned as modified copy of the + input sequence. Input parameters are left untouched, output and + input/output parameters replaced with possibly new values. + + The procedure may also provide a result set as output. This must then + be made available through the standard |fetch*|_ methods. + + If :obj:`!async` is ``True``, procedure execution will be asynchronous: + the function returns immediately while the procedure is executed by + the backend. Use the :meth:`~cursor.isready` method to see if the + data is ready for return via |fetch*|_ methods. See + :ref:`asynchronous-queries`. + + .. extension:: + + The :obj:`async` parameter 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:: :meth:`!fetch*` + + .. _fetch*: + + .. rubric:: Results retrieval methods + + + The following methods are used to read data from the database after an + :meth:`~cursor.execute` call. + + .. note:: + + :class:`cursor` objects are iterable, so, instead of calling + explicitly :meth:`~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') + + + .. 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 :exc:`~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 :attr:`~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 :exc:`~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 + :attr:`~cursor.arraysize` attribute. If the size parameter is used, + then it is best for it to retain the same value from one + :meth:`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 :exc:`~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 :obj:`!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 + :exc:`~psycopg2.ProgrammingError` is raised and the cursor position is + not changed. + + The method can be used both for client-side cursors and + :ref:`server-side cursors <server-side-cursors>`. + + .. note:: + + According to the |DBAPI|_, the exception raised for a cursor out + of bound should have been :exc:`!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) + + + .. attribute:: arraysize + + This read/write attribute specifies the number of rows to fetch at a + time with :meth:`~cursor.fetchmany`. It defaults to 1 meaning to fetch + a single row at a time. + + + .. 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 + :attr:`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``. + + 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` + .. __: http://www.postgresql.org/docs/8.4/static/sql-createtable.html + + .. |INSERT-RETURNING| replace:: :sql:`INSERT ... RETURNING` + .. __: http://www.postgresql.org/docs/8.4/static/sql-insert.html + + + .. method:: nextset() + + This method is not supported (PostgreSQL does not have multiple data + sets) and will raise a :exc:`~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. + + + .. attribute:: query + + Read-only attribute containing the body of the last query sent to the + backend (including bound arguments). ``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 :attr:`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 :attr:`statusmessage` attribute is a Psycopg extension to the + |DBAPI|. + + + .. method:: isready() + + Return ``False`` if the backend is still processing an asynchronous + query or ``True`` if data is ready to be fetched by one of the + |fetch*|_ methods. See :ref:`asynchronous-queries`. + + .. extension:: + + The :meth:`isready` method is a Psycopg extension to the |DBAPI|. + + + .. method:: fileno() + + Return the file descriptor associated with the current connection and + make possible to use a cursor in a context where a file object would + be expected (like in a :func:`select` call). See + :ref:`asynchronous-queries`. + + .. extension:: + + The :meth:`fileno` method is a Psycopg extension to the |DBAPI|. + + + + .. rubric:: COPY-related methods + + .. 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', columns=None) + + Read data *from* the file-like object :obj:`!file` appending them to + the table named :obj:`!table`. :obj:`!file` must have both + :meth:`!read` and :meth:`!readline` method. See :ref:`copy` for an + overview. + + The optional argument :obj:`!sep` is the columns separator and + :obj:`!null` represents :sql:`NULL` values in the file. + + The :obj:`!columns` argument is a sequence containing the name of the + fields where the read data will be entered. Its length and column + type should match the content of the read file. If not specifies, it + is assumed that the entire table matches the file structure. + + >>> 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')] + + .. versionchanged:: 2.0.6 + added the :obj:`columns` parameter. + + + .. method:: copy_to(file, table, sep='\\t', null='\\N', columns=None) + + Write the content of the table named :obj:`!table` *to* the file-like + object :obj:`!file`. :obj:`!file` must have a :meth:`!write` method. + See :ref:`copy` for an overview. + + The optional argument :obj:`!sep` is the columns separator and + :obj:`!null` represents :sql:`NULL` values in the file. + + The :obj:`!columns` argument is a sequence of field names: if not + ``None`` only the specified fields will be included in the dump. + + >>> cur.copy_to(sys.stdout, 'test', sep="|") + 1|100|abc'def + 2|\N|dada + ... + + .. versionchanged:: 2.0.6 + added the :obj:`columns` parameter. + + + .. method:: copy_expert(sql, file [, size]) + + Submit a user-composed :sql:`COPY` statement. The method is useful to + handle all the parameters that PostgreSQL makes available (see + |COPY|__ command documentation). + + :obj:`!file` must be an open, readable file for :sql:`COPY FROM` or an + open, writeable file for :sql:`COPY TO`. The optional :obj:`!size` + argument, when specified for a :sql:`COPY FROM` statement, will be + passed to :obj:`!file`\ 's read method to control the read buffer + size. + + >>> 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` + .. __: http://www.postgresql.org/docs/8.4/static/sql-copy.html + + .. versionadded:: 2.0.6 + + + .. attribute:: tzinfo_factory + + The time zone factory used to handle data types such as + :sql:`TIMESTAMP WITH TIME ZONE`. It should be a |tzinfo|_ object. + See also the :mod:`psycopg2.tz` module. + + .. |tzinfo| replace:: :class:`!tzinfo` + .. _tzinfo: http://docs.python.org/library/datetime.html#tzinfo-objects diff --git a/doc/src/errorcodes.rst b/doc/src/errorcodes.rst new file mode 100644 index 0000000..e1c76c0 --- /dev/null +++ b/doc/src/errorcodes.rst @@ -0,0 +1,41 @@ +:mod:`psycopg2.errorcodes` -- Error codes defined by PostgreSQL +=============================================================== + +.. sectionauthor:: Daniele Varrazzo <daniele.varrazzo@gmail.com> + +.. module:: psycopg2.errorcodes + +.. versionadded:: 2.0.6 + +This module contains symbolic names for all PostgreSQL error codes. +Subclasses of :exc:`~psycopg2.Error` make the PostgreSQL error code available +in the :attr:`~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`__ + + .. __: http://www.postgresql.org/docs/8.4/static/errcodes-appendix.html#ERRCODES-TABLE + + +.. todo:: errors table + + diff --git a/doc/src/extensions.rst b/doc/src/extensions.rst new file mode 100644 index 0000000..59bbc6e --- /dev/null +++ b/doc/src/extensions.rst @@ -0,0 +1,410 @@ +:mod:`psycopg2.extensions` -- Extensions to the DB API +====================================================== + +.. sectionauthor:: Daniele Varrazzo <daniele.varrazzo@gmail.com> + +.. module:: psycopg2.extensions + +.. testsetup:: * + + from psycopg2.extensions import AsIs, QuotedString, ISOLATION_LEVEL_AUTOCOMMIT + from psycopg2._psycopg import Binary + +The module contains a few objects and function extending the minimum set of +functionalities defined by the |DBAPI|_. + + +.. class:: connection + + Is the class usually returned by the :func:`~psycopg2.connect` function. + It is exposed by the :mod:`extensions` module in order to allow + subclassing to extend its behaviour: the subclass should be passed to the + :func:`!connect` function using the :obj:`!connection_factory` parameter. + See also :ref:`subclassing-connection`. + + For a complete description of the class, see :class:`connection`. + +.. class:: cursor + + It is the class usually returnded by the :meth:`connection.cursor` + method. It is exposed by the :mod:`extensions` module in order to allow + subclassing to extend its behaviour: the subclass should be passed to the + :meth:`!cursor` method using the :obj:`!cursor_factory` parameter. See + also :ref:`subclassing-cursor`. + + For a complete description of the class, see :class:`cursor`. + +.. class:: lobject + + .. todo:: class lobject + + .. versionadded:: 2.0.8 + + +.. _sql-adaptation-objects: + +SQL adaptation protocol objects +------------------------------- + +Psycopg provides a flexible system to adapt Python objects to the SQL syntax +(inspired to the :pep:`246`), allowing serialization in PostgreSQL. See +:ref:`adapting-new-types` for a detailed description. The following objects +deal with Python objects adaptation: + +.. function:: adapt(obj) + + Return the SQL representation of :obj:`obj` as a string. Raise a + :exc:`~psycopg2.ProgrammingError` if how to adapt the object is unknown. + In order to allow new objects to be adapted, register a new adapter for it + using the :func:`register_adapter` function. + + The function is the entry point of the adaptation mechanism: it can be + used to write adapters for complex objects by recursively calling + :func:`!adapt` on its components. + +.. function:: register_adapter(class, adapter) + + Register a new adapter for the objects of class :data:`class`. + + :data:`adapter` should be a function taking a single argument (the object + to adapt) and returning an object conforming the :class:`ISQLQuote` + protocol (e.g. exposing a :meth:`!getquoted` method). The :class:`AsIs` is + often useful for this task. + + Once an object is registered, it can be safely used in SQL queries and by + the :func:`adapt` function. + +.. class:: ISQLQuote(wrapped_object) + + Represents the SQL adaptation protocol. Objects conforming this protocol + should implement a :meth:`!getquoted` method. + + Adapters may subclass :class:`!ISQLQuote`, but is not necessary: it is + enough to expose a :meth:`!getquoted` method to be conforming. + + .. attribute:: _wrapped + + The wrapped object passes to the constructor + + .. method:: getquoted() + + Subclasses or other conforming objects should return a valid SQL + string representing the wrapped object. The :class:`!ISQLQuote` + implementation does nothing. + +.. class:: AsIs + + Adapter conform to the :class:`ISQLQuote` protocol useful for objects + whose string representation is already valid as SQL representation. + + .. method:: getquoted() + + Return the :meth:`str` conversion of the wrapped object. + + >>> AsIs(42).getquoted() + '42' + +.. class:: QuotedString + + Adapter conform to the :class:`ISQLQuote` protocol for string-like + objects. + + .. method:: getquoted() + + Return the string enclosed in single quotes. Any single quote + appearing in the the string is escaped by doubling it according to SQL + string constants syntax. Backslashes are escaped too. + + >>> QuotedString(r"O'Reilly").getquoted() + "'O''Reilly'" + +.. class:: Binary + + Adapter conform to the :class:`ISQLQuote` protocol for binary objects. + + .. method:: getquoted() + + Return the string enclosed in single quotes. It performs the same + escaping of the :class:`QuotedString` adapter, plus it knows how to + escape non-printable chars. + + >>> Binary("\x00\x08\x0F").getquoted() + "'\\\\000\\\\010\\\\017'" + + .. versionchanged:: 2.0.14(ish) + previously the adapter was not exposed by the :mod:`extensions` + module. In older version it can be imported from the implementation + module :mod:`!psycopg2._psycopg`. + + + +.. class:: Boolean + Float + SQL_IN + + Specialized adapters for builtin objects. + +.. class:: DateFromPy + TimeFromPy + TimestampFromPy + IntervalFromPy + + Specialized adapters for Python datetime objects. + +.. class:: DateFromMx + TimeFromMx + TimestampFromMx + IntervalFromMx + + Specialized adapters for `mx.DateTime`_ objects. + +.. data:: adapters + + Dictionary of the currently registered object adapters. Use + :func:`register_adapter` to add an adapter for a new type. + + + +Database types casting functions +-------------------------------- + +These functions are used to manipulate type casters to convert from PostgreSQL +types to Python objects. See :ref:`type-casting-from-sql-to-python` for +details. + +.. function:: new_type(oids, name, adapter) + + Create a new type caster to convert from a PostgreSQL type to a Python + object. The created object must be registered using + :func:`register_type` to be used. + + :param oids: tuple of OIDs of the PostgreSQL type to convert. + :param name: the name of the new type adapter. + :param adapter: the adaptation function. + + The object OID can be read from the :data:`cursor.description` attribute + or by querying from the PostgreSQL catalog. + + :data:`adapter` should have signature :samp:`fun({value}, {cur})` where + :samp:`{value}` is the string representation returned by PostgreSQL and + :samp:`{cur}` is the cursor from which data are read. In case of + :sql:`NULL`, :samp:`{value}` is ``None``. The adapter should return the + converted object. + + See :ref:`type-casting-from-sql-to-python` for an usage example. + +.. function:: register_type(obj [, scope]) + + Register a type caster created using :func:`new_type`. + + If :obj:`!scope` is specified, it should be a :class:`connection` or a + :class:`cursor`: the type caster will be effective only limited to the + specified object. Otherwise it will be globally registered. + + +.. data:: string_types + + The global register of type casters. + + +.. index:: + single: Encoding; Mapping + +.. data:: encodings + + Mapping from `PostgreSQL encoding`__ names to `Python codec`__ names. + Used by Psycopg when adapting or casting unicode strings. See + :ref:`unicode-handling`. + + .. __: http://www.postgresql.org/docs/8.4/static/multibyte.html + .. __: http://docs.python.org/library/codecs.html#standard-encodings + + + +.. index:: + single: Exceptions; Additional + +Additional exceptions +--------------------- + +The module exports a few exceptions in addition to the :ref:`standard ones +<dbapi-exceptions>` defined by the |DBAPI|_. + +.. exception:: QueryCanceledError + + (subclasses :exc:`~psycopg2.OperationalError`) + + Error related to SQL query cancelation. It can be trapped specifically to + detect a timeout. + + .. versionadded:: 2.0.7 + + +.. exception:: TransactionRollbackError + + (subclasses :exc:`~psycopg2.OperationalError`) + + Error causing transaction rollback (deadlocks, serialisation failures, + etc). It can be trapped specifically to detect a deadlock. + + .. versionadded:: 2.0.7 + + + +.. index:: + pair: Isolation level; Constants + +.. _isolation-level-constants: + +Isolation level constants +------------------------- + +Psycopg2 :class:`connection` objects hold informations about the PostgreSQL +`transaction isolation level`_. The current transaction level can be read +from the :attr:`~connection.isolation_level` attribute. The default isolation +level is :sql:`READ COMMITTED`. A different isolation level con be set +through the :meth:`~connection.set_isolation_level` method. The level can be +set to one of the following constants: + +.. data:: ISOLATION_LEVEL_AUTOCOMMIT + + No transaction is started when command are issued and no + :meth:`~connection.commit` or :meth:`~connection.rollback` is required. + Some PostgreSQL command such as :sql:`CREATE DATABASE` can't run into a + transaction: to run such command use:: + + >>> conn.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT) + +.. data:: ISOLATION_LEVEL_READ_UNCOMMITTED + + The :sql:`READ UNCOMMITTED` isolation level is defined in the SQL standard but not available in + the |MVCC| model of PostgreSQL: it is replaced by the stricter :sql:`READ + COMMITTED`. + +.. data:: ISOLATION_LEVEL_READ_COMMITTED + + This is the default value. A new transaction is started at the first + :meth:`~cursor.execute` command on a cursor and at each new + :meth:`!execute` after a :meth:`~connection.commit` or a + :meth:`~connection.rollback`. The transaction runs in the PostgreSQL + :sql:`READ COMMITTED` isolation level. + +.. data:: ISOLATION_LEVEL_REPEATABLE_READ + + The :sql:`REPEATABLE READ` isolation level is defined in the SQL standard + but not available in the |MVCC| model of PostgreSQL: it is replaced by the + stricter :sql:`SERIALIZABLE`. + +.. data:: ISOLATION_LEVEL_SERIALIZABLE + + Transactions are run at a :sql:`SERIALIZABLE` isolation level. This is the + strictest transactions isolation level, equivalent to having the + transactions executed serially rather than concurrently. However + applications using this level must be prepared to retry reansactions due + to serialization failures. See `serializable isolation level`_ in + PostgreSQL documentation. + + + +.. index:: + pair: Transaction status; Constants + +.. _transaction-status-constants: + +Transaction status constants +---------------------------- + +These values represent the possible status of a transaction: the current value +can be read using the :meth:`connection.get_transaction_status` method. + +.. data:: TRANSACTION_STATUS_IDLE + + The session is idle and there is no current transaction. + +.. data:: TRANSACTION_STATUS_ACTIVE + + A command is currently in progress. + +.. data:: TRANSACTION_STATUS_INTRANS + + The session is idle in a valid transaction block. + +.. data:: TRANSACTION_STATUS_INERROR + + The session is idle in a failed transaction block. + +.. data:: TRANSACTION_STATUS_UNKNOWN + + Reported if the connection with the server is bad. + + + +.. index:: + pair: Connection status; Constants + +.. _connection-status-constants: + +Connection status constants +--------------------------- + +These values represent the possible status of a connection: the current value +can be read from the :data:`~connection.status` attribute. + +.. data:: STATUS_SETUP + + Used internally. + +.. data:: STATUS_READY + + Connection established. + +.. data:: STATUS_BEGIN + + Connection established. A transaction is in progress. + +.. data:: STATUS_IN_TRANSACTION + + An alias for :data:`STATUS_BEGIN` + +.. data:: STATUS_SYNC + + Used internally. + +.. data:: STATUS_ASYNC + + Used internally. + + + +Additional database types +------------------------- + +The :mod:`!extensions` module includes typecasters for many standard +PostgreSQL types. These objects allow the conversion of returned data into +Python objects. All the typecasters are automatically registered, except +:data:`UNICODE` and :data:`UNICODEARRAY`: you can register them using +:func:`register_type` in order to receive Unicode objects instead of strings +from the database. See :ref:`unicode-handling` for details. + +.. data:: BINARYARRAY + BOOLEAN + BOOLEANARRAY + DATE + DATEARRAY + DATETIMEARRAY + DECIMALARRAY + FLOAT + FLOATARRAY + INTEGER + INTEGERARRAY + INTERVAL + INTERVALARRAY + LONGINTEGER + LONGINTEGERARRAY + ROWIDARRAY + STRINGARRAY + TIME + TIMEARRAY + UNICODE + UNICODEARRAY + diff --git a/doc/src/extras.rst b/doc/src/extras.rst new file mode 100644 index 0000000..dd7ed39 --- /dev/null +++ b/doc/src/extras.rst @@ -0,0 +1,149 @@ +:mod:`psycopg2.extras` -- Miscellaneous goodies for Psycopg 2 +============================================================= + +.. sectionauthor:: Daniele Varrazzo <daniele.varrazzo@gmail.com> + +.. module:: psycopg2.extras + +.. testsetup:: + + import psycopg2.extras + + create_test_table() + +This module is a generic place used to hold little helper functions and +classes until a better place in the distribution is found. + + +.. index:: + pair: Cursor; Dictionary + +.. _dict-cursor: + +Dictionary-like cursor +---------------------- + +The dict cursors allow to access to the retrieved records using an iterface +similar to the Python dictionaries instead of the tuples. You can use it +either passing :class:`DictConnection` as :obj:`!connection_factory` argument +to the :func:`~psycopg2.connect` function or passing :class:`DictCursor` as +the :class:`!cursor_factory` argument to the :meth:`~connection.cursor` method +of a regular :class:`connection`. + + >>> dict_cur = conn.cursor(cursor_factory=psycopg2.extras.DictCursor) + >>> dict_cur.execute("INSERT INTO test (num, data) VALUES(%s, %s)", + ... (100, "abc'def")) + >>> dict_cur.execute("SELECT * FROM test") + >>> rec = dict_cur.fetchone() + >>> rec['id'] + 1 + >>> rec['num'] + 100 + >>> rec['data'] + "abc'def" + +The records still support indexing as the original tuple: + + >>> rec[2] + "abc'def" + + +.. autoclass:: DictCursor + +.. autoclass:: DictConnection + +.. autoclass:: DictRow + + +Real dictionary cursor +^^^^^^^^^^^^^^^^^^^^^^ + +.. autoclass:: RealDictCursor + +.. autoclass:: RealDictConnection + +.. autoclass:: RealDictRow + + + +.. index:: + pair: Cursor; Logging + +Logging cursor +-------------- + +.. autoclass:: LoggingConnection + :members: initialize,filter + +.. autoclass:: LoggingCursor + + +.. autoclass:: MinTimeLoggingConnection + :members: initialize,filter + +.. autoclass:: MinTimeLoggingCursor + + + +.. index:: + pair: UUID; Data types + +UUID data type +-------------- + +.. versionadded:: 2.0.9 +.. versionchanged:: 2.0.13 added UUID array support. + +.. doctest:: + + >>> psycopg2.extras.register_uuid() + <psycopg2._psycopg.type object at 0x...> + + >>> # Python UUID can be used in SQL queries + >>> import uuid + >>> my_uuid = uuid.UUID('{12345678-1234-5678-1234-567812345678}') + >>> psycopg2.extensions.adapt(my_uuid).getquoted() + "'12345678-1234-5678-1234-567812345678'::uuid" + + >>> # PostgreSQL UUID are transformed into Python UUID objects. + >>> cur.execute("SELECT 'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'::uuid") + >>> cur.fetchone()[0] + UUID('a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11') + + +.. autofunction:: register_uuid + +.. autoclass:: UUID_adapter + + + +.. index:: + pair: INET; Data types + +INET data type +-------------- + + >>> psycopg2.extras.register_inet() + <psycopg2._psycopg.type object at 0x...> + >>> cur.execute("SELECT '192.168.0.1'::inet") + >>> cur.fetchone()[0].addr + '192.168.0.1' + +.. autofunction:: register_inet() + +.. autoclass:: Inet + +.. todo:: Adapter non registered: how to register it? + + + +.. index:: + single: Time zones; Fractional + +Fractional time zones +--------------------- + +.. autofunction:: register_tstz_w_secs + + .. versionadded:: 2.0.9 + diff --git a/doc/src/index.rst b/doc/src/index.rst new file mode 100644 index 0000000..4b32069 --- /dev/null +++ b/doc/src/index.rst @@ -0,0 +1,59 @@ +================================================= +Psycopg -- PostgreSQL database adapter for Python +================================================= + +.. sectionauthor:: Daniele Varrazzo <daniele.varrazzo@gmail.com> + +Psycopg is a PostgreSQL_ database adapter for the Python_ programming +language. Its main advantages are that it supports the full Python |DBAPI|_ +and it is thread safe (threads can share the connections). It was designed for +heavily multi-threaded applications that create and destroy lots of cursors and +make a conspicuous number of concurrent :sql:`INSERT`\ s or :sql:`UPDATE`\ s. +The psycopg distribution includes ZPsycopgDA, a Zope_ Database Adapter. + +Psycopg 2 is an almost complete rewrite of the Psycopg 1.1.x branch. Psycopg 2 +features complete libpq_ v3 protocol, |COPY-TO-FROM|__ and full :ref:`object +adaptation <python-types-adaptation>` for all basic Python types: strings (including unicode), ints, +longs, floats, buffers (binary objects), booleans, `mx.DateTime`_ and builtin +datetime types. It also supports unicode queries and Python lists mapped to +PostgreSQL arrays. + +.. _PostgreSQL: http://www.postgresql.org/ +.. _Python: http://www.python.org/ +.. _Zope: http://www.zope.org/ +.. _libpq: http://www.postgresql.org/docs/8.4/static/libpq.html +.. |COPY-TO-FROM| replace:: :sql:`COPY TO/COPY FROM` +.. __: http://www.postgresql.org/docs/8.4/static/sql-copy.html + +Contents: + +.. toctree:: + :maxdepth: 2 + + usage + module + connection + cursor + advanced + extensions + tz + extras + errorcodes + + +.. ifconfig:: builder != 'text' + + .. rubric:: Indices and tables + + * :ref:`genindex` + * :ref:`search` + + +.. ifconfig:: todo_include_todos + + .. note:: + + **To Do items in the documentation** + + .. todolist:: + diff --git a/doc/src/module.rst b/doc/src/module.rst new file mode 100644 index 0000000..3bb7559 --- /dev/null +++ b/doc/src/module.rst @@ -0,0 +1,308 @@ +The :mod:`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 or params[, connection_factory]) + + Create a new database session and return a new :class:`connection` object. + + You can specify the connection parameters either as a string:: + + conn = psycopg2.connect("dbname=test user=postgres password=secret") + + or using a set of keyword arguments:: + + conn = psycopg2.connect(database="test", user="postgres", password="secret") + + The full list of available parameters is: + + - :obj:`!dbname` -- the database name (only in dsn string) + - :obj:`!database` -- the database name (only as keyword argument) + - :obj:`!user` -- user name used to authenticate + - :obj:`!password` -- password used to authenticate + - :obj:`!host` -- database host address (defaults to UNIX socket if not provided) + - :obj:`!port` -- connection port number (defaults to 5432 if not provided) + - :obj:`!sslmode` -- `SSL TCP/IP negotiation`__ mode + + .. __: http://www.postgresql.org/docs/8.4/static/libpq-ssl.html#LIBPQ-SSL-SSLMODE-STATEMENTS + + Using the :obj:`!connection_factory` parameter a different class or + connections factory can be specified. It should be a callable object + taking a :obj:`!dsn` argument. See :ref:`subclassing-connection` for + details. + + .. extension:: + + The :obj:`connection_factory` parameter is a Psycopg extension to the + |DBAPI|. + + +.. data:: apilevel + + String constant stating the supported DB API level. For :mod:`psycopg2` is + ``2.0``. + +.. data:: threadsafety + + Integer constant stating the level of thread safety the interface + supports. For :mod:`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 :mod:`psycopg2` is ``pyformat``. See also + :ref:`query-parameters`. + + + +.. 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:: 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 should not use this class as base. It + is a subclass of the Python |StandardError|_. + + .. 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 :mod:`~psycopg2.errorcodes` module contains + symbolic constants representing PostgreSQL error codes. + + .. extension:: + + The :attr:`~Error.pgerror` and :attr:`~Error.pgcode` attributes are + Psycopg extensions. + + .. doctest:: + :options: +NORMALIZE_WHITESPACE + + >>> try: + ... cur.execute("SELECT * FROM barf") + ... except Exception, e: + ... pass + + >>> e.pgcode + '42P01' + >>> print e.pgerror + ERROR: relation "barf" does not exist + LINE 1: SELECT * FROM barf + ^ + + .. versionchanged:: 2.0.7 added :attr:`Error.pgerror` and + :attr:`Error.pgcode` attributes. + + + +.. exception:: InterfaceError + + Exception raised for errors that are related to the database interface + rather than the database itself. It is a subclass of :exc:`Error`. + +.. exception:: DatabaseError + + Exception raised for errors that are related to the database. It is a + subclass of :exc:`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 :exc:`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 :exc:`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 + :exc:`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 :exc:`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 :exc:`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 :meth:`!rollback` on a + connection that does not support transaction or has transactions turned + off. It is a subclass of :exc:`DatabaseError`. + + +.. extension:: + + Psycopg may raise a few other, more specialized, exceptions: currently + :exc:`~psycopg2.extensions.QueryCanceledError` and + :exc:`~psycopg2.extensions.TransactionRollbackError` are defined. These + exceptions are not exposed by the main :mod:`!psycopg2` module but are + made available by the :mod:`~psycopg2.extensions` module. All the + additional exceptions are subclasses of standard |DBAPI| exceptions, so + trapping them specifically is not required. + + +This is the exception inheritance layout: + +.. parsed-literal:: + + |StandardError| + \|__ :exc:`Warning` + \|__ :exc:`Error` + \|__ :exc:`InterfaceError` + \|__ :exc:`DatabaseError` + \|__ :exc:`DataError` + \|__ :exc:`OperationalError` + \| \|__ :exc:`psycopg2.extensions.QueryCanceledError` + \| \|__ :exc:`psycopg2.extensions.TransactionRollbackError` + \|__ :exc:`IntegrityError` + \|__ :exc:`InternalError` + \|__ :exc:`ProgrammingError` + \|__ :exc:`NotSupportedError` + + +.. |StandardError| replace:: :exc:`!StandardError` +.. _StandardError: http://docs.python.org/library/exceptions.html#exceptions.StandardError + + +.. _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. + + +.. 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. + diff --git a/doc/src/tools/lib/dbapi_extension.py b/doc/src/tools/lib/dbapi_extension.py new file mode 100755 index 0000000..583c752 --- /dev/null +++ b/doc/src/tools/lib/dbapi_extension.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +""" + 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.util.compat import Directive, make_admonition + +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): + nodes = make_admonition(extension_node, + self.name, [_('DB API extension')], self.options, + self.content, self.lineno, self.content_offset, + self.block_text, self.state, self.state_machine) + nodes[0]['classes'].append('dbapi-extension') + return nodes + + +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) + diff --git a/doc/src/tools/lib/sql_role.py b/doc/src/tools/lib/sql_role.py new file mode 100644 index 0000000..8fb8ab8 --- /dev/null +++ b/doc/src/tools/lib/sql_role.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +""" + 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) + diff --git a/doc/src/tools/stitch_text.py b/doc/src/tools/stitch_text.py new file mode 100755 index 0000000..c54f4b1 --- /dev/null +++ b/doc/src/tools/stitch_text.py @@ -0,0 +1,56 @@ +#! /usr/bin/env python +"""A script to stitch together the generated text files in the correct order. +""" + +import os +import sys + +def main(): + if len(sys.argv) != 3: + print >>sys.stderr, "usage: %s index.rst text-dir" + return 2 + + _, index, txt_dir = sys.argv + + for fb in iter_file_base(index): + emit(fb, txt_dir) + + return 0 + +def iter_file_base(fn): + have_line = iter(open(fn)).next + + while not have_line().startswith('.. toctree'): + pass + while have_line().strip().startswith(':'): + pass + + yield os.path.splitext(os.path.basename(fn))[0] + + n = 0 + while 1: + line = have_line() + if line.isspace(): + continue + if line.startswith(".."): + break + n += 1 + yield line.strip() + + if n < 5: + # maybe format changed? + raise Exception("Not enough files found. Format change in index.rst?") + +def emit(basename, txt_dir): + for line in open(os.path.join(txt_dir, basename + ".txt")): + line = line.replace("``", "'") + sys.stdout.write(line) + + # some space between sections + print + print + + +if __name__ == '__main__': + sys.exit(main()) + diff --git a/doc/src/tz.rst b/doc/src/tz.rst new file mode 100644 index 0000000..3cac88c --- /dev/null +++ b/doc/src/tz.rst @@ -0,0 +1,18 @@ +:mod:`psycopg2.tz` -- ``tzinfo`` implementations for Psycopg 2 +=============================================================== + +.. sectionauthor:: Daniele Varrazzo <daniele.varrazzo@gmail.com> + +.. module:: psycopg2.tz + +This module holds two different tzinfo implementations that can be used as the +:obj:`tzinfo` argument to datetime constructors, directly passed to Psycopg +functions or used to set the :attr:`cursor.tzinfo_factory` attribute in +cursors. + +.. todo:: should say something more about tz handling + +.. autoclass:: psycopg2.tz.FixedOffsetTimezone + +.. autoclass:: psycopg2.tz.LocalTimezone + diff --git a/doc/src/usage.rst b/doc/src/usage.rst new file mode 100644 index 0000000..9d86d6e --- /dev/null +++ b/doc/src/usage.rst @@ -0,0 +1,482 @@ +Basic module usage +================== + +.. sectionauthor:: Daniele Varrazzo <daniele.varrazzo@gmail.com> + +.. index:: + pair: Example; Usage + +The basic Psycopg usage is common to all the database adapters implementing +the |DBAPI|_ protocol. Here is an interactive session showing some of the +basic commands:: + + >>> import psycopg2 + + # Connect to an existing database + >>> conn = psycopg2.connect("dbname=test user=postgres") + + # Open a cursor to perform database operations + >>> cur = conn.cursor() + + # Execute a command: this creates a new table + >>> cur.execute("CREATE TABLE test (id serial PRIMARY KEY, num integer, data varchar);") + + # Pass data to fill a query placeholders and let Psycopg perform + # the correct conversion (no more SQL injections!) + >>> cur.execute("INSERT INTO test (num, data) VALUES (%s, %s)", + ... (100, "abc'def")) + + # Query the database and obtain data as Python objects + >>> cur.execute("SELECT * FROM test;") + >>> cur.fetchone() + (1, 100, "abc'def") + + # Make the changes to the database persistent + >>> conn.commit() + + # Close communication with the database + >>> cur.close() + >>> conn.close() + + +The main entry point of Psycopg are: + +- The function :func:`~psycopg2.connect` creates a new database session and + returns a new :class:`connection` instance. + +- The class :class:`connection` encapsulates a database session. It allows to: + + - create new :class:`cursor`\s using the :meth:`~connection.cursor` method to + execute database commands and queries, + + - terminate the session using the methods :meth:`~connection.commit` or + :meth:`~connection.rollback`. + +- The class :class:`cursor` allows interaction with the database: + + - send commands to the database using methods such as :meth:`~cursor.execute` + and :meth:`~cursor.executemany`, + + - retrieve data from the database using methods such as + :meth:`~cursor.fetchone`, :meth:`~cursor.fetchmany`, + :meth:`~cursor.fetchall`. + + + +.. index:: Transaction, Begin, Commit, Rollback, Autocommit + +.. _transactions-control: + +Transactions control +-------------------- + +In Psycopg transactions are handled by the :class:`connection` class. By +default, every time a command is sent to the database (using one of the +:class:`cursor`\ s created by the connection), a new transaction is created. +The following database commands will be executed in the context of the same +transaction -- not only the commands issued by the first cursor, but the ones +issued by all the cursors created by the same connection. Should any command +fail, the transaction will be aborted and no further command will be executed +until a call to the :meth:`connection.rollback` method. + +The connection is responsible to terminate its transaction, calling either the +:meth:`~connection.commit` or :meth:`~connection.rollback` method. Committed +changes are immediately made persistent into the database. Closing the +connection using the :meth:`~connection.close` method or destroying the +connection object (calling :meth:`!__del__` or letting it fall out of scope) +will result in an implicit :meth:`!rollback` call. + +It is possible to set the connection in *autocommit* mode: this way all the +commands executed will be immediately committed and no rollback is possible. A +few commands (e.g. :sql:`CREATE DATABASE`) require to be run outside any +transaction: in order to be able to run these commands from Psycopg, the +session must be in autocommit mode. Read the documentation for +:meth:`connection.set_isolation_level` to know how to change the commit mode. + + +.. index:: + pair: Query; Parameters + +.. _query-parameters: + +Passing parameters to SQL queries +--------------------------------- + +Psycopg casts Python variables to SQL literals by type. Many standard Python types +are already `adapted to the correct SQL representation`__. + +.. __: python-types-adaptation_ + +Example: the Python function call:: + + >>> cur.execute( + ... """INSERT INTO some_table (an_int, a_date, a_string) + ... VALUES (%s, %s, %s);""", + ... (10, datetime.date(2005, 11, 18), "O'Reilly")) + +is converted into the SQL command:: + + INSERT INTO some_table (an_int, a_date, a_string) + VALUES (10, '2005-11-18', 'O''Reilly'); + +Named arguments are supported too using :samp:`%({name})s` placeholders. +Using named arguments the values can be passed to the query in any order and +many placeholder can use the same values:: + + >>> cur.execute( + ... """INSERT INTO some_table (an_int, a_date, another_date, a_string) + ... VALUES (%(int)s, %(date)s, %(date)s, %(str)s);""", + ... {'int': 10, 'str': "O'Reilly", 'date': datetime.date(2005, 11, 18)}) + +While the mechanism resembles regular Python strings manipulation, there are a +few subtle differences you should care about when passing parameters to a +query: + +- The Python string operator ``%`` is not used: the :meth:`~cursor.execute` + method accepts a tuple or dictionary of values as second parameter. + |sql-warn|__. + + .. |sql-warn| replace:: **Never** use ``%`` or ``+`` to merge values + into queries + + .. __: sql-injection_ + +- The variables placeholder must *always be a* ``%s``, even if a different + placeholder (such as a ``%d`` for integers or ``%f`` for floats) may look + more appropriate:: + + >>> cur.execute("INSERT INTO numbers VALUES (%d)", (42,)) # WRONG + >>> cur.execute("INSERT INTO numbers VALUES (%s)", (42,)) # correct + +- For positional variables binding, *the second argument must always be a + tuple*, even if it contains a single variable:: + + >>> cur.execute("INSERT INTO foo VALUES (%s)", "bar") # WRONG + >>> cur.execute("INSERT INTO foo VALUES (%s)", ("bar",)) # correct + +- Only variable values should be bound via this method: it shouldn't be used + to set table or field names. For these elements, ordinary string formatting + should be used before running :meth:`~cursor.execute`. + + + +.. index:: Security, SQL injection + +.. _sql-injection: + +The problem with the query parameters +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The SQL representation for many data types is often not the same of the Python +string representation. The classic example is with single quotes in +strings: SQL uses them as string constants bounds and requires them to be +escaped, whereas in Python single quotes can be left unescaped in strings +bounded by double quotes. For this reason a naïve approach to the composition +of query strings, e.g. using string concatenation, is a recipe for terrible +problems:: + + >>> SQL = "INSERT INTO authors (name) VALUES ('%s');" # NEVER DO THIS + >>> data = ("O'Reilly", ) + >>> cur.execute(SQL % data) # THIS WILL FAIL MISERABLY + ProgrammingError: syntax error at or near "Reilly" + LINE 1: INSERT INTO authors (name) VALUES ('O'Reilly') + ^ + +If the variable containing the data to be sent to the database comes from an +untrusted source (e.g. a form published on a web site) an attacker could +easily craft a malformed string, either gaining access to unauthorized data or +performing destructive operations on the database. This form of attack is +called `SQL injection`_ and is known to be one of the most widespread forms of +attack to servers. Before continuing, please print `this page`__ as a memo and +hang it onto your desk. + +.. _SQL injection: http://en.wikipedia.org/wiki/SQL_injection +.. __: http://xkcd.com/327/ + +Psycopg can `convert automatically Python objects into and from SQL +literals`__: using this feature your code will result more robust and +reliable. It is really the case to stress this point: + +.. __: python-types-adaptation_ + +.. warning:: + + Never, **never**, **NEVER** use Python string concatenation (``+``) or + string parameters interpolation (``%``) to pass variables to a SQL query + string. Not even at gunpoint. + +The correct way to pass variables in a SQL command is using the second +argument of the :meth:`~cursor.execute` method:: + + >>> SQL = "INSERT INTO authors (name) VALUES (%s);" # Notice: no quotes + >>> data = ("O'Reilly", ) + >>> cur.execute(SQL, data) # Notice: no % operator + + + +.. index:: + pair: Objects; Adaptation + single: Data types; Adaptation + +.. _python-types-adaptation: + +Adaptation of Python values to SQL types +---------------------------------------- + +Many standards Python types are adapted into SQL and returned as Python +objects when a query is executed. + +If you need to convert other Python types to and from PostgreSQL data types, +see :ref:`adapting-new-types` and :ref:`type-casting-from-sql-to-python`. You +can also find a few other specialized adapters in the :mod:`psycopg2.extras` +module. + +In the following examples the method :meth:`~cursor.mogrify` is used to show +the SQL string that would be sent to the database. + +.. index:: + single: None; Adaptation + single: NULL; Adaptation + single: Boolean; Adaptation + +- Python ``None`` and boolean values are converted into the proper SQL + literals:: + + >>> cur.mogrify("SELECT %s, %s, %s;", (None, True, False)) + >>> 'SELECT NULL, true, false;' + +.. index:: + single: Integer; Adaptation + single: Float; Adaptation + single: Decimal; Adaptation + +- Numeric objects: :class:`!int`, :class:`!long`, :class:`!float`, + :class:`!Decimal` are converted in the PostgreSQL numerical representation:: + + >>> cur.mogrify("SELECT %s, %s, %s, %s;", (10, 10L, 10.0, Decimal("10.00"))) + >>> 'SELECT 10, 10, 10.0, 10.00;' + +.. index:: + single: Strings; Adaptation + single: Unicode; Adaptation + single: Buffer; Adaptation + single: bytea; Adaptation + single: Binary string + +- String types: :class:`!str`, :class:`!unicode` are converted in SQL string + syntax. :class:`!buffer` is converted in PostgreSQL binary string syntax, + suitable for :sql:`bytea` fields. When reading textual fields, either + :class:`!str` or :class:`!unicode` can be received: see + :ref:`unicode-handling`. + +.. index:: + single: Date objects; Adaptation + single: Time objects; Adaptation + single: Interval objects; Adaptation + single: mx.DateTime; Adaptation + +- Date and time objects: builtin :class:`!datetime`, :class:`!date`, + :class:`!time`. :class:`!timedelta` are converted into PostgreSQL's + :sql:`timestamp`, :sql:`date`, :sql:`time`, :sql:`interval` data types. + Time zones are supported too. The Egenix `mx.DateTime`_ objects are adapted + the same way:: + + >>> dt = datetime.datetime.now() + >>> dt + datetime.datetime(2010, 2, 8, 1, 40, 27, 425337) + + >>> cur.mogrify("SELECT %s, %s, %s;", (dt, dt.date(), dt.time())) + "SELECT '2010-02-08T01:40:27.425337', '2010-02-08', '01:40:27.425337';" + + >>> cur.mogrify("SELECT %s;", (dt - datetime.datetime(2010,1,1),)) + "SELECT '38 days 6027.425337 seconds';" + +.. index:: + single: Array; Adaptation + single: Lists; Adaptation + +- Python lists are converted into PostgreSQL :sql:`ARRAY`\ s:: + + >>> cur.mogrify("SELECT %s;", ([10, 20, 30], )) + 'SELECT ARRAY[10, 20, 30];' + +.. index:: + single: Tuple; Adaptation + single: IN operator + +- Python tuples are converted in a syntax suitable for the SQL :sql:`IN` + operator:: + + >>> cur.mogrify("SELECT %s IN %s;", (10, (10, 20, 30))) + 'SELECT 10 IN (10, 20, 30);' + + .. note:: + + SQL doesn't allow an empty list in the IN operator, so your code should + guard against empty tuples. + + .. note:: + + The IN adapter is automatically registered when the + :mod:`~psycopg2.extensions` module is imported. This behaviour may change + in the future and the adapter will probably be always active. + + .. versionadded:: 2.0.6 + the tuple :sql:`IN` adaptation. + + +.. index:: + single: Unicode + +.. _unicode-handling: + +Unicode handling +^^^^^^^^^^^^^^^^ + +Psycopg can exchange Unicode data with a PostgreSQL database. Python +:class:`!unicode` objects are automatically *encoded* in the client encoding +defined on the database connection (the `PostgreSQL encoding`__, available in +:attr:`connection.encoding`, is translated into a `Python codec`__ using an +:data:`~psycopg2.extensions.encodings` mapping):: + + >>> print u, type(u) + àèìòù€ <type 'unicode'> + + >>> cur.execute("INSERT INTO test (num, data) VALUES (%s,%s);", (74, u)) + +.. __: http://www.postgresql.org/docs/8.4/static/multibyte.html +.. __: http://docs.python.org/library/codecs.html#standard-encodings + +When reading data from the database, the strings returned are usually 8 bit +:class:`!str` objects encoded in the database client encoding:: + + >>> print conn.encoding + UTF8 + + >>> cur.execute("SELECT data FROM test WHERE num = 74") + >>> x = cur.fetchone()[0] + >>> print x, type(x), repr(x) + àèìòù€ <type 'str'> '\xc3\xa0\xc3\xa8\xc3\xac\xc3\xb2\xc3\xb9\xe2\x82\xac' + + >>> conn.set_client_encoding('LATIN9') + + >>> cur.execute("SELECT data FROM test WHERE num = 74") + >>> x = cur.fetchone()[0] + >>> print type(x), repr(x) + <type 'str'> '\xe0\xe8\xec\xf2\xf9\xa4' + +In order to obtain :class:`!unicode` objects instead, it is possible to +register a typecaster so that PostgreSQL textual types are automatically +*decoded* using the current client encoding:: + + >>> psycopg2.extensions.register_type(psycopg2.extensions.UNICODE, cur) + + >>> cur.execute("SELECT data FROM test WHERE num = 74") + >>> x = cur.fetchone()[0] + >>> print x, type(x), repr(x) + àèìòù€ <type 'unicode'> u'\xe0\xe8\xec\xf2\xf9\u20ac' + +In the above example, the :data:`~psycopg2.extensions.UNICODE` typecaster is +registered only on the cursor. It is also possible to register typecasters on +the connection or globally: see the function +:func:`~psycopg2.extensions.register_type` and +:ref:`type-casting-from-sql-to-python` for details. + +.. note:: + + If you want to receive uniformly all your database input in Unicode, you + can register the related typecasters globally as soon as Psycopg is + imported:: + + import psycopg2 + import psycopg2.extensions + psycopg2.extensions.register_type(psycopg2.extensions.UNICODE) + psycopg2.extensions.register_type(psycopg2.extensions.UNICODEARRAY) + + and then forget about this story. + + + +.. index:: + pair: Server side; Cursor + pair: Named; Cursor + pair: DECLARE; SQL command + pair: FETCH; SQL command + pair: MOVE; SQL command + +.. _server-side-cursors: + +Server side cursors +------------------- + +When a database query is executed, the Psycopg :class:`cursor` usually fetches +all the records returned by the backend, transferring them to the client +process. If the query returned an huge amount of data, a proportionally large +amount of memory will be allocated by the client. + +If the dataset is too large to be practically handled on the client side, it is +possible to create a *server side* cursor. Using this kind of cursor it is +possible to transfer to the client only a controlled amount of data, so that a +large dataset can be examined without keeping it entirely in memory. + +Server side cursor are created in PostgreSQL using the |DECLARE|_ command and +subsequently handled using :sql:`MOVE`, :sql:`FETCH` and :sql:`CLOSE` commands. + +Psycopg wraps the database server side cursor in *named cursors*. A named +cursor is created using the :meth:`~connection.cursor` method specifying the +:obj:`!name` parameter. Such cursor will behave mostly like a regular cursor, +allowing the user to move in the dataset using the :meth:`~cursor.scroll` +methog and to read the data using :meth:`~cursor.fetchone` and +:meth:`~cursor.fetchmany` methods. + +.. |DECLARE| replace:: :sql:`DECLARE` +.. _DECLARE: http://www.postgresql.org/docs/8.4/static/sql-declare.html + + + +.. index:: Thread safety, Multithread + +.. _thread-safety: + +Thread safety +------------- + +The Psycopg module is *thread-safe*: threads can access the same database +using separate session (by creating a :class:`connection` per thread) or using +the same session (accessing to the same connection and creating separate +:class:`cursor`\ s). In |DBAPI|_ parlance, Psycopg is *level 2 thread safe*. + + + +.. index:: + pair: COPY; SQL command + +.. _copy: + +Using COPY TO and COPY FROM +--------------------------- + +Psycopg :class:`cursor` objects provide an interface to the efficient +PostgreSQL |COPY|__ command to move data from files to tables and back. +The methods exposed are: + +:meth:`~cursor.copy_from` + Reads data *from* a file-like object appending them to a database table + (:sql:`COPY table FROM file` syntax). The source file must have both + :meth:`!read` and :meth:`!readline` method. + +:meth:`~cursor.copy_to` + Writes the content of a table *to* a file-like object (:sql:`COPY table TO + file` syntax). The target file must have a :meth:`write` method. + +:meth:`~cursor.copy_expert` + Allows to handle more specific cases and to use all the :sql:`COPY` + features available in PostgreSQL. + +Please refer to the documentation of the single methods for details and +examples. + +.. |COPY| replace:: :sql:`COPY` +.. __: http://www.postgresql.org/docs/8.4/static/sql-copy.html + + |