mirror of
https://github.com/psycopg/psycopg2.git
synced 2025-02-07 12:50:32 +03:00
Added documentation to type casting objects.
This commit is contained in:
parent
74403ff5a8
commit
5491dd8db0
|
@ -49,7 +49,7 @@ An example of cursor subclass performing logging is::
|
|||
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
|
||||
|
@ -61,34 +61,38 @@ 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 ``getquoted()`` method returning the SQL representation of
|
||||
the object as a string.
|
||||
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 :func:`psycopg2.extensions.AsIs`
|
||||
wrapper, whose ``getquoted()`` result is simply the ``str()``\ ingification of
|
||||
the wrapped object.
|
||||
wrapper, whose :meth:`getquoted()` result is simply the ``str()``\ ing
|
||||
conversion of the wrapped object.
|
||||
|
||||
Example: mapping of a ``Point`` class into the ``point`` PostgreSQL geometric
|
||||
type::
|
||||
Example: mapping of a :data:`Point` class into the |point|_ PostgreSQL
|
||||
geometric type::
|
||||
|
||||
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)
|
||||
|
||||
curs.execute("INSERT INTO atable (apoint) VALUES (%s)",
|
||||
|
||||
curs.execute("INSERT INTO atable (apoint) VALUES (%s)",
|
||||
(Point(1.23, 4.56),))
|
||||
|
||||
|
||||
.. |point| replace:: ``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));
|
||||
|
@ -99,8 +103,8 @@ The above function call results in the SQL command::
|
|||
|
||||
.. _type-casting-from-sql-to-python:
|
||||
|
||||
Type casting of SQL types into Python values
|
||||
--------------------------------------------
|
||||
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
|
||||
|
@ -111,13 +115,13 @@ previously defined ``Point`` class::
|
|||
|
||||
def cast_point(value, curs):
|
||||
if value is not None:
|
||||
# Convert from (f1, f2) syntax using a regular expression.
|
||||
m = re.match("\((.*),(.*)\)", value)
|
||||
# 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)))
|
||||
|
||||
|
||||
To create a mapping from the PostgreSQL type (either standard or user-defined),
|
||||
its ``oid`` must be known. It can be retrieved either by the second column of
|
||||
its OID must be known. It can be retrieved either by the second column of
|
||||
the cursor description::
|
||||
|
||||
curs.execute("SELECT NULL::point")
|
||||
|
@ -132,11 +136,11 @@ namespace for system objects is ``pg_catalog``)::
|
|||
ON typnamespace = pg_namespace.oid
|
||||
WHERE typname = %(typename)s
|
||||
AND nspname = %(namespace)s""",
|
||||
{'typename': 'point', 'namespace': 'pg_catalog'})
|
||||
|
||||
{'typename': 'point', 'namespace': 'pg_catalog'})
|
||||
|
||||
point_oid = curs.fetchone()[0]
|
||||
|
||||
After you know the object ``oid``, you must can and register the new type::
|
||||
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)
|
||||
|
@ -144,7 +148,7 @@ After you know the object ``oid``, you must can and register the new type::
|
|||
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
|
||||
is automatically performed when a column whose type is a registered OID is
|
||||
read::
|
||||
|
||||
>>> curs.execute("SELECT '(10.2,20.3)'::point")
|
||||
|
@ -217,7 +221,7 @@ Running the script and executing the command ``NOTIFY test`` in a separate
|
|||
|
||||
.. index::
|
||||
double: Asynchronous; Query
|
||||
|
||||
|
||||
.. _asynchronous-queries:
|
||||
|
||||
Asynchronous queries
|
||||
|
@ -237,7 +241,7 @@ 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
|
||||
|
@ -245,12 +249,12 @@ a number of different ways:
|
|||
|
||||
1) one of the :obj:`.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
|
||||
(:obj:`.execute()` on a different cursor will simply raise an exception).
|
||||
This waits for the complete execution of the current query, discard any
|
||||
|
@ -271,13 +275,13 @@ asynchronous queries:
|
|||
: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 :obj:`.fetch*()` methods).
|
||||
|
||||
|
||||
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)
|
||||
|
|
|
@ -36,7 +36,167 @@ functionalities defined by the |DBAPI|.
|
|||
.. todo:: class lobject
|
||||
|
||||
|
||||
.. todo:: finish module extensions
|
||||
|
||||
.. _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:`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
|
||||
|
||||
Represents the SQL adaptation protocol. Objects conforming this protocol
|
||||
should implement a :meth:`getquoted` method.
|
||||
|
||||
.. todo:: has Psycopg user ever to explicitely use this object?
|
||||
|
||||
.. todo::
|
||||
what the ISQLQuote methods are for? In my understanding the
|
||||
class is only used as symbol to dispatch adaptation and not to be
|
||||
instantiated.
|
||||
|
||||
.. 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 ``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'"
|
||||
|
||||
.. todo::
|
||||
|
||||
this class is actually not importd in module extensions: I'd say this
|
||||
is a bug.
|
||||
|
||||
|
||||
.. data:: Boolean
|
||||
.. data:: Float
|
||||
|
||||
Specialized adapters for builtin objects.
|
||||
|
||||
.. data:: DateFromPy
|
||||
.. data:: TimeFromPy
|
||||
.. data:: TimestampFromPy
|
||||
.. data:: IntervalFromPy
|
||||
|
||||
Specialized adapters for Python datetime objects.
|
||||
|
||||
.. data:: DateFromMx
|
||||
.. data:: TimeFromMx
|
||||
.. data:: TimestampFromMx
|
||||
.. data:: 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` or directly
|
||||
from the PostgreSQL catalog.
|
||||
|
||||
:data:`adapter` should have signature ``fun(value, cur)`` where
|
||||
``value`` is the string representation returned by PostgreSQL and ``cur``
|
||||
is the cursor from which data are read. In case of ``NULL``, ``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.
|
||||
|
||||
.. todo:: Please confirm the above behaviour.
|
||||
|
||||
.. data:: string_types
|
||||
|
||||
The global register of type casters.
|
||||
|
||||
.. data:: binary_types
|
||||
|
||||
.. todo:: is this used?
|
||||
|
||||
|
||||
|
||||
|
@ -60,9 +220,9 @@ one of the following constants:
|
|||
No transaction is started when command are issued and no ``commit()`` or
|
||||
``rollback()`` is required. Some PostgreSQL command such as ``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
|
||||
|
||||
This isolation level is defined in the SQL standard but not available in
|
||||
|
@ -75,13 +235,13 @@ one of the following constants:
|
|||
:meth:`cursor.execute()` command on a cursor and at each new ``execute()``
|
||||
after a :meth:`connection.commit()` or a :meth:`connection.rollback()`.
|
||||
The transaction runs in the PostgreSQL ``READ COMMITTED`` isolation level.
|
||||
|
||||
|
||||
.. data:: ISOLATION_LEVEL_REPEATABLE_READ
|
||||
|
||||
This isolation level is defined in the SQL standard but not available in
|
||||
the MVCC model of PostgreSQL: it is replaced by the stricter
|
||||
``SERIALIZABLE``.
|
||||
|
||||
|
||||
.. data:: ISOLATION_LEVEL_SERIALIZABLE
|
||||
|
||||
Transactions are run at a ``SERIALIZABLE`` isolation level. This is the
|
||||
|
|
|
@ -23,7 +23,7 @@ basic commands::
|
|||
|
||||
# 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)",
|
||||
>>> cur.execute("INSERT INTO test (num, data) VALUES (%s, %s)",
|
||||
... (100, "abc'def"))
|
||||
|
||||
# Query the database and obtain data as Python objects
|
||||
|
@ -46,7 +46,7 @@ The main entry point of Psycopg are:
|
|||
|
||||
- The class :class:`connection` encapsulates a database session. It allows to:
|
||||
|
||||
- terminate the session using the methods :meth:`connection.commit()` and
|
||||
- terminate the session using the methods :meth:`connection.commit()` and
|
||||
:meth:`connection.rollback()`,
|
||||
|
||||
- create new :class:`cursor`\ s to execute database commands and queries
|
||||
|
@ -59,7 +59,7 @@ The main entry point of Psycopg are:
|
|||
|
||||
- retrieve data using the methods :meth:`cursor.fetchone()`,
|
||||
:meth:`cursor.fetchmany()`, :meth:`cursor.fetchall()`.
|
||||
|
||||
|
||||
|
||||
|
||||
.. index:: Transaction, Begin, Commit, Rollback, Autocommit
|
||||
|
@ -154,7 +154,7 @@ Passing parameters to SQL queries
|
|||
---------------------------------
|
||||
|
||||
Psycopg casts Python variables to SQL literals by type. `Standard Python types
|
||||
are already adapted to the proper SQL literal`__.
|
||||
are already adapted to the proper SQL literal`__.
|
||||
|
||||
.. __: python-types-adaptation_
|
||||
|
||||
|
@ -184,7 +184,7 @@ Notice that:
|
|||
- 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
|
||||
|
||||
|
@ -218,7 +218,7 @@ 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.
|
||||
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`.
|
||||
|
@ -301,12 +301,19 @@ the SQL string that would be sent to the database.
|
|||
>>> cur.mogrify("SELECT %s IN %s;", (10, (10, 20, 30)))
|
||||
'SELECT 10 IN (10, 20, 30);'
|
||||
|
||||
.. note::
|
||||
.. note::
|
||||
|
||||
SQL doesn't allow an empty list in the IN operator, so your code should
|
||||
guard against empty tuples.
|
||||
|
||||
.. note::
|
||||
|
||||
In order to use the tuple adapter, your application must import the module
|
||||
:mod:`psycopg2.extensions`.
|
||||
|
||||
.. todo:: is this a bug or a feature?
|
||||
|
||||
.. versionadded:: 2.0.6
|
||||
|
||||
.. index::
|
||||
pair: Server side; Cursor
|
||||
|
@ -359,7 +366,7 @@ the same session (accessing to the same connection and creating separate
|
|||
|
||||
|
||||
|
||||
.. index::
|
||||
.. index::
|
||||
pair: COPY; SQL command
|
||||
|
||||
.. _copy:
|
||||
|
|
Loading…
Reference in New Issue
Block a user