]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
Document row factories
authorDenis Laxalde <denis.laxalde@dalibo.com>
Fri, 12 Feb 2021 14:55:14 +0000 (15:55 +0100)
committerDenis Laxalde <denis.laxalde@dalibo.com>
Tue, 23 Feb 2021 17:04:36 +0000 (18:04 +0100)
We document the row_factory argument of *Connection.execute() as well as
the row_factory attribute on Connection.

We add a new page in advanced section explaining the concepts of row
factories, providing examples and documenting built-in row factories.

docs/advanced/index.rst
docs/connection.rst
docs/row-factories.rst [new file with mode: 0644]

index 0bd6d587a11a3fe558d7c6cef1957986b1af4a84..31e3916922d7bfbcaeb49362c33f3b2e40548ec9 100644 (file)
@@ -5,6 +5,7 @@ Advanced topics
     :maxdepth: 1
     :caption: Contents:
 
+    ../row-factories
     ../adaptation
     ../prepared
     ../copy
index 04a7842a767a6ede78e980dfacb240329b0d3ed8..6981831067dae133bcbd40cba9f4c3a7926137d6 100644 (file)
@@ -65,7 +65,7 @@ The `!Connection` class
         .. note:: You can use :ref:`with conn.cursor(): ...<usage>`
             to close the cursor automatically when the block is exited.
 
-    .. automethod:: execute(query, params=None, prepare=None) -> Cursor
+    .. automethod:: execute(query, params=None, prepare=None, row_factory=None) -> Cursor
 
         :param query: The query to execute.
         :type query: `!str`, `!bytes`, or `sql.Composable`
@@ -74,7 +74,9 @@ The `!Connection` class
         :param prepare: Force (`!True`) or disallow (`!False`) preparation of
             the query. By default (`!None`) prepare automatically. See
             :ref:`prepared-statements`.
-        :type prepare: `!bool`
+        :param row_factory: Optional row factory to form result's row. See
+            :ref:`row-factories` for details.
+        :type row_factory: `Callable[[Cursor], Callable[[Sequence[Any]], Any]]`
 
         The cursor is what returned calling `cursor()` without parameters. The
         parameters are passed to its `~Cursor.execute()` and the cursor is
@@ -83,6 +85,12 @@ The `!Connection` class
         See :ref:`query-parameters` for all the details about executing
         queries.
 
+    .. autoattribute:: row_factory
+        :annotation: RowFactory
+
+        Writable attribute to control how result's rows are formed.
+        See :ref:`row-factories` for details.
+
     .. rubric:: Transaction management methods
 
     For details see :ref:`transactions`.
@@ -203,7 +211,7 @@ The `!AsyncConnection` class
         .. note:: You can use ``async with conn.cursor() as cur: ...`` to
             close the cursor automatically when the block is exited.
 
-    .. automethod:: execute(query, params=None, prepare=None) -> AsyncCursor
+    .. automethod:: execute(query, params=None, prepare=None, row_factory=None) -> AsyncCursor
     .. automethod:: commit
     .. automethod:: rollback
 
diff --git a/docs/row-factories.rst b/docs/row-factories.rst
new file mode 100644 (file)
index 0000000..eae335b
--- /dev/null
@@ -0,0 +1,60 @@
+.. currentmodule:: psycopg3
+
+.. index:: row factories
+
+.. _row-factories:
+
+Row factories
+=============
+
+Cursor's `fetch*` methods return tuples of column values by default. This can
+be changed to adapt the needs of the programmer by using custom row factories.
+
+A row factory is a callable that accepts a cursor object and returns another
+callable accepting a `values` tuple and returning a row in the desired form.
+This can be implemented as a class, for instance:
+
+.. code:: python
+
+   class DictRowFactory:
+       def __init__(self, cursor):
+           self.cursor = cursor
+
+       def __call__(self, values):
+           fields = (c.name for c in self.cursor.description)
+           return dict(zip(fields, values))
+
+or as a plain function:
+
+.. code:: python
+
+   def dict_row_factory(cursor):
+       def make_row(values):
+           fields = (c.name for c in cursor.description)
+           return dict(zip(fields, values))
+
+       return make_row
+
+These can then be used by specifying a `row_factory` argument in
+`Connection.connect()`, `Connection.cursor()`, `Cursor.execute()` and
+`Connection.execute()` or by writting to `Connection.row_factory` attribute.
+
+.. code:: python
+
+    conn = psycopg3.connect(row_factory=DictRowFactory)
+    cur = conn.execute("SELECT first_name, last_name, age FROM persons")
+    person = cur.fetchone()
+    print(f"{person['first_name']} {person['last_name']}")
+
+Later usages of `row_factory` override earlier definitions; for instance,
+the `row_factory` specified at `Connection.connect()` can be overridden by
+passing another value at `Connection.cursor()`.
+
+Available row factories
+-----------------------
+
+Module `psycopg3.rows` contains available row factories:
+
+.. currentmodule:: psycopg3.rows
+
+.. autofunction:: dict_row