]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
docs: Subtly suggest to use the psycopg.sql module rather than ClientCursor 302/head
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Sun, 15 May 2022 09:57:22 +0000 (11:57 +0200)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Sun, 15 May 2022 09:59:14 +0000 (11:59 +0200)
docs/advanced/cursors.rst
docs/basic/from_pg2.rst

index 938b6a935b880303bb1f8cc186cfae4a8a0a196c..8a86ab4f01572bd88550ed81c403aafcfba60282 100644 (file)
@@ -68,7 +68,7 @@ allow for greater flexibility (for instance to parametrize a table name too,
 not only values); however, for simple cases, a `!ClientCursor` could be the
 right object.
 
-In order to obtain `!ClientCursor` from a connection, you can its
+In order to obtain `!ClientCursor` from a connection, you can set its
 `~Connection.cursor_factory` (at init time or changing its attribute
 afterwards):
 
@@ -89,6 +89,22 @@ as argument.
     conn = psycopg.connect(DSN)
     cur = psycopg.ClientCursor(conn)
 
+.. warning::
+
+    Client-side cursors don't support :ref:`binary parameters and return
+    values <binary-data>` and don't support :ref:`prepared statements
+    <prepared-statements>`.
+
+.. tip::
+
+    The best use for client-side binding cursors is probably to port large
+    Psycopg 2 code to Psycopg 3, especially for programs making wide use of
+    Data Definition Language statements.
+
+    The `psycopg.sql` module allows for more generic client-side query
+    composition, to mix client- and server-side parameters binding, and allows
+    to parametrize tables and fields names too, or entirely generic SQL
+    snippets.
 
 .. index::
     double: Cursor; Server-side
@@ -100,7 +116,7 @@ as argument.
 Server-side cursors
 -------------------
 
-PostgreSQL also has its own concept of *cursor* (sometimes also called
+PostgreSQL has its own concept of *cursor* too (sometimes also called
 *portal*). When a database cursor is created, the query is not necessarily
 completely processed: the server might be able to produce results only as they
 are needed. Only the results requested are transmitted to the client: if the
index e2b22a3077703701068ea819e2288414b5ab591f..8a2bf269b37f9f8d2846128b0da37eea857f05a2 100644 (file)
@@ -66,19 +66,25 @@ function can be used instead of :sql:`NOTIFY`::
     #id-1.9.3.157.7.5
 
 If this is not possible, you must merge the query and the parameter on the
-client side. You can do so using a :ref:`client-side binding cursor
-<client-side-binding-cursors>` such as `ClientCursor`::
+client side. You can do so using the `psycopg.sql` objects::
+
+    >>> from psycopg import sql
+
+    >>> cur.execute(sql.SQL("CREATE TABLE foo (id int DEFAULT {})").format(42)
+
+or creating a :ref:`client-side binding cursor <client-side-binding-cursors>`
+such as `ClientCursor`::
 
     >>> cur = ClientCursor(conn)
     >>> cur.execute("CREATE TABLE foo (id int DEFAULT %s)", [42])
 
-if you need `!ClientCursor` often you can set the `Connection.cursor_factory`
+if you need `!ClientCursor` often, you can set the `Connection.cursor_factory`
 to have them created by default by `Connection.cursor()`. This way, Psycopg 3
 will behave largely the same way of Psycopg 2.
 
-Note that, using parameters, you can only specify values. If you need to
-parametrize different parts of a statement (aka *the ones that don't go in
-single quotes*) you can use the objects from the `psycopg.sql` module::
+Note that, using `!ClientCursor` parameters, you can only specify query values
+(aka *the string that go in single quotes*). If you need to parametrize
+different parts of a statement, you must use the `!psycopg.sql` module::
 
     >>> from psycopg import sql
 
@@ -113,16 +119,16 @@ the `psycopg.sql` objects to compose a multiple query on the client side and
 run them in the same `!execute()` call::
 
 
-    >>> cur = psycopg.ClientCursor(conn)
-    >>> cur.execute(
-    ...     "INSERT INTO foo VALUES (%s); INSERT INTO foo VALUES (%s)",
-    ...     (10, 20))
-
     >>> from psycopg import sql
     >>> conn.execute(
     ...     sql.SQL("INSERT INTO foo VALUES ({}); INSERT INTO foo values ({})"
     ...     .format(10, 20))
 
+    >>> psycopg.ClientCursor(conn)
+    >>> cur.execute(
+    ...     "INSERT INTO foo VALUES (%s); INSERT INTO foo VALUES (%s)",
+    ...     (10, 20))
+
 Note that statements that must be run outside a transaction (such as
 :sql:`CREATE DATABASE`) can never be executed in batch with other statements,
 even if the connection is in autocommit mode::