Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1l7Koz-0005Cz-CJ for psycopg@arkaria.postgresql.org; Wed, 03 Feb 2021 16:16:01 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1l7Koy-0000MV-AQ for psycopg@arkaria.postgresql.org; Wed, 03 Feb 2021 16:16:00 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1l7Kox-0000Lx-Vm for psycopg@lists.postgresql.org; Wed, 03 Feb 2021 16:16:00 +0000 Received: from mail1.dalibo.net ([212.83.143.11] helo=mail.dalibo.com) by makus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1l7Kor-0003Ao-Cd for psycopg@postgresql.org; Wed, 03 Feb 2021 16:15:58 +0000 Received: from dalibo.com (lan31-5-82-234-69-236.fbx.proxad.net [82.234.69.236]) by mail.dalibo.com (Postfix) with ESMTPSA id 27337203B3; Wed, 3 Feb 2021 17:15:50 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=dalibo.com; s=a; t=1612368950; bh=B8ep6k8zoolL42zXRaN8BOH5vjlsdOm5ivB7YLagpGo=; h=Date:From:To:Subject:From; b=mi5+41VMSCmoCw6DOq/b9vtFATQUkjX6qwQSoTZiRQabtb5VYEVJc9lbkl9VacLoL WdBLSjhDDH2JxgyJ3I/v4+YsvGklQq4/ygKNrSVi2mqRmacUgay7EBHqtRjp3ekUnq 3HpS1LwrW6p5h5WvHGn04jGRoh4fk4lXkNrl5n3I= Date: Wed, 3 Feb 2021 17:15:48 +0100 From: Denis Laxalde To: psycopg@postgresql.org Subject: about client-side cursors Message-ID: <20210203161548.vkhu3qkpvmgvyhik@dalibo.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: NeoMutt/20180716 List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk Hi, I'd like to discuss about the concept of client-side cursor as defined in psycopg. This is a concept I've always been quite uncomfortable with; I'll try to explain why. First, from a practical point of view: cur = connection.cursor() cur.execute(...) result = cur.fetchxxx() This typical pattern seems awkward to me. Where do IO operations actually take place? (on execute()? on fetch()? on both?) Then, and besides the terminology, the fact that named cursors are very different from client-side cursors while being constructed by the same API is confusing. I understand that this may come from the DB-API: https://www.python.org/dev/peps/pep-0249/#cursor-objects > [Cursor] objects represent a database cursor. [...] But this does not seem quite right to me since a client-side cursor is actually not a PostgreSQL cursor. (The documention on psycopg2 is clear on the difference, though.) In asyncio context, while playing around with psycopg3, the situation is even worse because of the additional async/await keywords; for instance: conn = await psycopg3.AsyncConnection.connect() async with conn: cur = await conn.execute("SELECT * FROM test") r = await cur.fetchall() Why do we need two 'await' (i.e. two IO operations) on conn.execute() and cur.fetchall() if 'cur' is a client-side cursor? (Back to my first point about where IO happen, this appears to depend on whether the connection has 'autocommit' or not...) All in all, my main point is: (why) do we need client-side cursors? Thanks, Denis