mirror of
				https://github.com/psycopg/psycopg2.git
				synced 2025-10-31 15:57:31 +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