Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vQrBp-001NXF-2c for pgsql-performance@arkaria.postgresql.org; Wed, 03 Dec 2025 18:02:58 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vQrBo-00FAZ6-30 for pgsql-performance@arkaria.postgresql.org; Wed, 03 Dec 2025 18:02:57 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vQrBo-00FAYw-22 for pgsql-performance@lists.postgresql.org; Wed, 03 Dec 2025 18:02:56 +0000 Received: from mail-lf1-x12c.google.com ([2a00:1450:4864:20::12c]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1vQrBn-002xee-0b for pgsql-performance@lists.postgresql.org; Wed, 03 Dec 2025 18:02:56 +0000 Received: by mail-lf1-x12c.google.com with SMTP id 2adb3069b0e04-5942a631c2dso11023028e87.2 for ; Wed, 03 Dec 2025 10:02:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1764784974; x=1765389774; darn=lists.postgresql.org; h=to:subject:message-id:date:from:mime-version:from:to:cc:subject :date:message-id:reply-to; bh=/S6A6mt9oeiUbXcuBxGkSeGcKNp78VP9AkYa4Ozad5s=; b=hTtKRWdIlEXLCrjN64lmUhvV4XOA3TyXm11Ot4Z2nbUho5/OSE2OElr8hXLN5ub8PQ 9o4fSFQkEI9IurQvtzG3kxW9uFUwvzn+6GqakqJy5wIyaDASdYWsPqMYHzfxWkv7sFzT klHIQ+VYpR8lbZn2RVIaI7xDFJaFqY0eQAYg9KoDNBq28glRy8/a1hM1CAktRvyArhAO rA43Cs3Y7CZgYKzxxJoPjO2DiC6Mpij33ABTGV4SCZSM54HXWXZ18iS2q5RPjIAZGWh0 8Tq6TxZA4IuoCRewS+rQCgn6QeXlY/4auCyVkcbVN0wCSgAbZ+oAggFJD/Vvd7O6Pnhl lX/w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764784974; x=1765389774; h=to:subject:message-id:date:from:mime-version:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=/S6A6mt9oeiUbXcuBxGkSeGcKNp78VP9AkYa4Ozad5s=; b=n7bJl3hBIQDsxzHL0BhOKXJatIASpCkeUglMt1jtCQYFZPXf4U3Bt7rw0lO8Yeh2W/ cenWxsq3duj0E4JjL20+cH+QMor68htBuMYk798n94sdTorTLX2Ppa529lZ/fZhhO9dd G23kD1Pq+MUEkA9v3S8BtGUyne9k4UL+XE98Hc+6nevGbk5FguNvKlhcZjXfxN4Y9gX8 FNExzPF764qDWyXod9Uf5kobmXWwo8U3hv+So3myhiefLMd4vUTQPreivE2+s+IK320S QRrcwLikjWdBHv04/pNRkhUOh3W8/z7a3cVIs2t6YnryanRy3MtYHIGu76B7t4NhhwYX KCPA== X-Gm-Message-State: AOJu0YxCwasdtTPr8doAGkYCE+HnkxCFFAHyk4DGA3o/wC1fTLTdEY9G fF0gxuoUgrl1dGJMM3I+u57VZZmOtwHiz/75jXsX6YX16hPQRhZnxFCzbZZWjoEj3gnb3NT0Qhs kDCUtDdoBIk34z2vKJD3xX0R2rlVhoclwEaOSuu4= X-Gm-Gg: ASbGncu0gFQdy9FUehEqvImzNj+B8CRxZDZlH5MECWw/kH0oLiOq3B2CrB4YL0zvQfe orp93NGmCWpkEh2B9n679FSiYDd8YhsWq6zj1yllmgEvub1mrjViovwnBg9hS6jugVTKhnPNlR9 2oEPnHx92Fql2bJw48uQcWUkPgZ+29C617dZStWwHoGoH7URpkLiXZ5OXuk3ZqA9yag/VpKGLCu DS8Xg6j/WQA5lXnLh2qkgyb3wZsiXmGK0vGWq1K+ZrtiZVZ4fzdGkUOXMaud8navjNW0Iu+kXb0 app8UqDDc/8= X-Google-Smtp-Source: AGHT+IFxtccGuUqhwqKkQUb4Cw+kiYq0uYWmutaAGDQcxWFFDVJOBhMPSG3l593Qbtl4egAFKgbGJiD8f0YoSyvjXOA= X-Received: by 2002:a05:6512:2313:b0:595:81e7:3daa with SMTP id 2adb3069b0e04-597d3f7bcefmr1390835e87.27.1764784973046; Wed, 03 Dec 2025 10:02:53 -0800 (PST) MIME-Version: 1.0 From: Tim Fors Date: Wed, 3 Dec 2025 13:02:40 -0500 X-Gm-Features: AWmQ_bmy0fIIiq4OtGXzJS-pSwdtoq3b692kNSdg9F0yh-d4hZ3KAl2_uy_1Yn4 Message-ID: Subject: Client-server communication for FETCH To: pgsql-performance@lists.postgresql.org Content-Type: multipart/alternative; boundary="0000000000006c67c706451005cc" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --0000000000006c67c706451005cc Content-Type: text/plain; charset="UTF-8" Hello community, I have a simple C program using libpq V18 to FETCH one row at a time (see below). Does the server send multiple rows to the client where they are cached for satisfying the FETCH statements, or does it just send one row at a time since that's all that each FETCH statement is asking for? If it's sending multiple rows at a time, is there some way that I can observe this e.g. some kind of trace info that would show it? Or where in the libpq source would I look to see how the client is retrieving rows from the server? I have done extensive searching to try and find the definitive answer to this. The searches indicate that libpq supports the concept of a client-side cursor, where it has a cache of rows sent by the server and uses that cache to perform each FETCH, but I'd like to be able to verify whether this is true or not. Thanks, Tim res = PQexec(conn, "DECLARE cur CURSOR FOR select * from table1"); if (PQresultStatus(res) != PGRES_COMMAND_OK) { printf("DECLARE CURSOR failed: %s", PQerrorMessage(conn)); PQclear(res); exit(1); } PQclear(res); res = PQexec(conn, "FETCH in cur"); if (PQresultStatus(res) != PGRES_TUPLES_OK) { printf("FETCH failed: %s", PQerrorMessage(conn)); PQclear(res); exit(1); } PQclear(res); res = PQexec(conn, "FETCH in cur"); if (PQresultStatus(res) != PGRES_TUPLES_OK) { printf("FETCH failed: %s", PQerrorMessage(conn)); PQclear(res); exit(1); } --0000000000006c67c706451005cc Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Hello community,

I have a simple C prog= ram using libpq V18 to FETCH one row at a time (see below). Does the server= send multiple rows to the client where they are cached for satisfying the = FETCH statements, or does it just send one row at a time since that's a= ll that each FETCH statement is asking for? If it's sending multiple ro= ws at a time, is there some way that I can observe this e.g. some kind of t= race info that would show=C2=A0it? Or where in the libpq source would I loo= k to see how the client is retrieving rows from the server?

<= /div>
I have done extensive=C2=A0searching to try and find the definiti= ve answer=C2=A0to this. The searches indicate that libpq supports the conce= pt of a client-side cursor, where it has a cache of rows sent by the server= and uses that cache to perform each FETCH, but I'd like to be able to = verify whether this is true or not.=C2=A0

Thanks,<= /div>

Tim

=C2=A0 res =3D PQexec= (conn, "DECLARE cur CURSOR FOR select * from table1");
=C2=A0 = if (PQresultStatus(res) !=3D PGRES_COMMAND_OK)
=C2=A0 {
=C2=A0 =C2=A0= printf("DECLARE CURSOR failed: %s", PQerrorMessage(conn));
= =C2=A0 =C2=A0 PQclear(res);
=C2=A0 =C2=A0 exit(1);
=C2=A0 }
=C2=A0= PQclear(res);

=C2=A0 res =3D PQexec(conn, "FETCH in cur")= ;
=C2=A0 if (PQresultStatus(res) !=3D PGRES_TUPLES_OK)
=C2=A0 {
= =C2=A0 =C2=A0 printf("FETCH failed: %s", PQerrorMessage(conn));=C2=A0 =C2=A0 PQclear(res);
=C2=A0 =C2=A0 exit(1);
=C2=A0 }
=C2= =A0 PQclear(res);

=C2=A0 res =3D PQexec(conn, "FETCH in cur&quo= t;);
=C2=A0 if (PQresultStatus(res) !=3D PGRES_TUPLES_OK)
=C2=A0 {=C2=A0 =C2=A0 printf("FETCH failed: %s", PQerrorMessage(conn));<= br>=C2=A0 =C2=A0 PQclear(res);
=C2=A0 =C2=A0 exit(1);
=C2=A0 }
--0000000000006c67c706451005cc--