From: Daniele Varrazzo Date: Sun, 15 May 2022 09:57:22 +0000 (+0200) Subject: docs: Subtly suggest to use the psycopg.sql module rather than ClientCursor X-Git-Tag: 3.1~99^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F302%2Fhead;p=thirdparty%2Fpsycopg.git docs: Subtly suggest to use the psycopg.sql module rather than ClientCursor --- diff --git a/docs/advanced/cursors.rst b/docs/advanced/cursors.rst index 938b6a935..8a86ab4f0 100644 --- a/docs/advanced/cursors.rst +++ b/docs/advanced/cursors.rst @@ -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 ` and don't support :ref:`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 diff --git a/docs/basic/from_pg2.rst b/docs/basic/from_pg2.rst index e2b22a307..8a2bf269b 100644 --- a/docs/basic/from_pg2.rst +++ b/docs/basic/from_pg2.rst @@ -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 -` 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 ` +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::