($INBOX_DIR/description missing)  
help / color / mirror / Atom feed
Multiple-output-file make rules: We're Doing It Wrong
29+ messages / 4 participants
[nested] [flat]

* Multiple-output-file make rules: We're Doing It Wrong
@ 2018-03-21 21:36  Tom Lane <[email protected]>
  0 siblings, 1 reply; 29+ messages in thread

From: Tom Lane @ 2018-03-21 21:36 UTC (permalink / raw)
  To: [email protected]

In https://postgr.es/m/[email protected]
I griped about a weird make failure I was having with VPATH builds.
I did not push the patch I suggested at the time, because I didn't
understand why it seemed to resolve the issue, and because neither
I nor anyone else could reproduce the issue on other machines.

Well, I've had an epiphany after fooling with John Naylor's bootstrap
patch, and I now understand what must have been happening and how
to reproduce it.  Specifically, I can reproduce the issue as stated
if I force sql_help.h to be newer than sql_help.c.  Typically they'd
have the same file mod times, to within the filesystem's resolution;
but create_help.pl does close the .c file first, so with a bit of
bad luck the .h file might be recorded as 1 second newer.  (It's
probably easier to reproduce the problem on newer filesystems with
sub-second timestamp resolution.)

Given that state of affairs, make thinks it needs to rebuild sql_help.c,
which it does by executing the stated rule:

sql_help.c: sql_help.h ;

and of course nothing happens.  So in a plain build, we've just wasted
a few cycles in make.  But in a VPATH build, make believes that the
execution of this rule should have produced a sql_help.c file *in the
build directory*, and then when it goes to compile that file, we get
the sql_help.c-doesn't-exist failure I observed.

My first thought about fixing this was to switch the order of the file
close steps in create_help.pl.  But that's just a hack, which I'd
already considered and rejected for genbki.pl in the case of the
bootstrap data patch.  We cannot hope to control the order in which
bison writes gram.c and gram.h, for instance, so we need some other
solution if we want to prevent the same sort of thing from sometimes
happening in VPATH builds from distribution tarballs.

I propose that the right solution is that these dummy rules should
look like

sql_help.c: sql_help.h
	touch $@

Although the dependent file is actually made by the same process that
made the referenced file, the "touch" makes certain that its file
timestamp is >= the referenced file's timestamp, so that we won't
think we need to re-make it again later, and in particular a VPATH
build will consider that sql_help.c is up to date.

Now, to make this work, we need to make sure that distprep steps
request building of sql_help.c not only sql_help.h, or else the
tarball build run won't execute the touch step and we're back to
a state of uncertainty about the file timestamps.  In the attached
proposed patch, I made sure that any command asking to make the
depended-on file also asked for the dependent file.  This is kind
of annoying, but it avoids assuming anything about which way the
dependency runs, which after all is a basically-arbitrary choice
in the responsible Makefile.

I looked for rules with this bug by looking for comments that
mention parser/Makefile.  There may well be some more, but I have
no good idea how to find them --- any thoughts?  (Note that I
intentionally didn't touch the instance in backend/catalog/Makefile,
as that will be fixed by the bootstrap data patch, and there's no
need to create a merge failure in advance of that.)

Anyway, I think we need to apply and back-patch the attached,
or something much like it.

			regards, tom lane



Attachments:

  [text/x-diff] fix-make-rules-with-multiple-outputs.patch (5.1K, ../../[email protected]/2-fix-make-rules-with-multiple-outputs.patch)
  download | inline diff:
diff --git a/src/backend/Makefile b/src/backend/Makefile
index 4a28267..d0f99a6 100644
--- a/src/backend/Makefile
+++ b/src/backend/Makefile
@@ -131,19 +131,20 @@ postgres.o: $(OBJS)
 # match the dependencies shown in the subdirectory makefiles!
 
 parser/gram.h: parser/gram.y
-	$(MAKE) -C parser gram.h
+	$(MAKE) -C parser gram.h gram.c
 
 storage/lmgr/lwlocknames.h: storage/lmgr/generate-lwlocknames.pl storage/lmgr/lwlocknames.txt
-	$(MAKE) -C storage/lmgr lwlocknames.h
+	$(MAKE) -C storage/lmgr lwlocknames.h lwlocknames.c
 
 utils/errcodes.h: utils/generate-errcodes.pl utils/errcodes.txt
 	$(MAKE) -C utils errcodes.h
 
 # see explanation in parser/Makefile
-utils/fmgrprotos.h: utils/fmgroids.h ;
+utils/fmgrprotos.h: utils/fmgroids.h
+	touch $@
 
 utils/fmgroids.h: utils/Gen_fmgrtab.pl catalog/Catalog.pm $(top_srcdir)/src/include/catalog/pg_proc.h
-	$(MAKE) -C utils $(notdir $@)
+	$(MAKE) -C utils fmgroids.h fmgrprotos.h
 
 utils/probes.h: utils/probes.d
 	$(MAKE) -C utils probes.h
@@ -218,7 +219,7 @@ distprep:
 	$(MAKE) -C bootstrap	bootparse.c bootscanner.c
 	$(MAKE) -C catalog	schemapg.h postgres.bki postgres.description postgres.shdescription
 	$(MAKE) -C replication	repl_gram.c repl_scanner.c syncrep_gram.c syncrep_scanner.c
-	$(MAKE) -C storage/lmgr	lwlocknames.h
+	$(MAKE) -C storage/lmgr	lwlocknames.h lwlocknames.c
 	$(MAKE) -C utils	fmgrtab.c fmgroids.h fmgrprotos.h errcodes.h
 	$(MAKE) -C utils/misc	guc-file.c
 	$(MAKE) -C utils/sort	qsort_tuple.c
diff --git a/src/backend/parser/Makefile b/src/backend/parser/Makefile
index 4b97f83..304f90e 100644
--- a/src/backend/parser/Makefile
+++ b/src/backend/parser/Makefile
@@ -24,11 +24,14 @@ include $(top_srcdir)/src/backend/common.mk
 # There is no correct way to write a rule that generates two files.
 # Rules with two targets don't have that meaning, they are merely
 # shorthand for two otherwise separate rules.  To be safe for parallel
-# make, we must chain the dependencies like this.  The semicolon is
-# important, otherwise make will choose the built-in rule for
-# gram.y=>gram.c.
-
-gram.h: gram.c ;
+# make, we must chain the dependencies like this.  Furthermore, the
+# "touch" step is essential, because it ensures that gram.h is seen as
+# newer than (or at least no older than) gram.c.  Without that, make is
+# likely to try to rebuild both files at inopportune times, causing
+# havoc in parallel or VPATH builds.
+
+gram.h: gram.c
+	touch $@
 
 gram.c: BISONFLAGS += -d
 gram.c: BISON_CHECK_CMD = $(PERL) $(srcdir)/check_keywords.pl $< $(top_srcdir)/src/include/parser/kwlist.h
diff --git a/src/backend/storage/lmgr/Makefile b/src/backend/storage/lmgr/Makefile
index e1b787e..d97f672 100644
--- a/src/backend/storage/lmgr/Makefile
+++ b/src/backend/storage/lmgr/Makefile
@@ -26,7 +26,8 @@ s_lock_test: s_lock.c $(top_builddir)/src/port/libpgport.a
 		$(TASPATH) -L $(top_builddir)/src/port -lpgport -o s_lock_test
 
 # see explanation in ../../parser/Makefile
-lwlocknames.c: lwlocknames.h ;
+lwlocknames.c: lwlocknames.h
+	touch $@
 
 lwlocknames.h: $(top_srcdir)/src/backend/storage/lmgr/lwlocknames.txt generate-lwlocknames.pl
 	$(PERL) $(srcdir)/generate-lwlocknames.pl $<
diff --git a/src/backend/utils/Makefile b/src/backend/utils/Makefile
index efb8b53..0809cd8 100644
--- a/src/backend/utils/Makefile
+++ b/src/backend/utils/Makefile
@@ -21,8 +21,11 @@ all: errcodes.h fmgroids.h fmgrprotos.h probes.h
 $(SUBDIRS:%=%-recursive): fmgroids.h fmgrprotos.h
 
 # see explanation in ../parser/Makefile
-fmgrprotos.h: fmgroids.h ;
-fmgroids.h: fmgrtab.c ;
+fmgrprotos.h: fmgroids.h
+	touch $@
+
+fmgroids.h: fmgrtab.c
+	touch $@
 
 fmgrtab.c: Gen_fmgrtab.pl $(catalogdir)/Catalog.pm $(top_srcdir)/src/include/catalog/pg_proc.h
 	$(PERL) -I $(catalogdir) $< -I $(top_srcdir)/src/include/ $(top_srcdir)/src/include/catalog/pg_proc.h
diff --git a/src/bin/psql/Makefile b/src/bin/psql/Makefile
index c8eb2f9..58f7aa8 100644
--- a/src/bin/psql/Makefile
+++ b/src/bin/psql/Makefile
@@ -35,7 +35,11 @@ psql: $(OBJS) | submake-libpq submake-libpgport submake-libpgfeutils
 
 help.o: sql_help.h
 
-sql_help.c: sql_help.h ;
+# sql_help.c is built by create_help.pl, but make sure it's newer than
+# sql_help.h (see comments in src/backend/parser/Makefile)
+sql_help.c: sql_help.h
+	touch $@
+
 sql_help.h: create_help.pl $(wildcard $(REFDOCDIR)/*.sgml)
 	$(PERL) $< $(REFDOCDIR) $*
 
@@ -43,7 +47,7 @@ psqlscanslash.c: FLEXFLAGS = -Cfe -p -p
 psqlscanslash.c: FLEX_NO_BACKUP=yes
 psqlscanslash.c: FLEX_FIX_WARNING=yes
 
-distprep: sql_help.h psqlscanslash.c
+distprep: sql_help.h sql_help.c psqlscanslash.c
 
 install: all installdirs
 	$(INSTALL_PROGRAM) psql$(X) '$(DESTDIR)$(bindir)/psql$(X)'
diff --git a/src/pl/plpgsql/src/Makefile b/src/pl/plpgsql/src/Makefile
index fc60618..dd17092 100644
--- a/src/pl/plpgsql/src/Makefile
+++ b/src/pl/plpgsql/src/Makefile
@@ -63,7 +63,9 @@ uninstall-headers:
 pl_gram.o pl_handler.o pl_comp.o pl_exec.o pl_funcs.o pl_scanner.o: plpgsql.h pl_gram.h plerrcodes.h
 
 # See notes in src/backend/parser/Makefile about the following two rules
-pl_gram.h: pl_gram.c ;
+pl_gram.h: pl_gram.c
+	touch $@
+
 pl_gram.c: BISONFLAGS += -d
 
 # generate plerrcodes.h from src/backend/utils/errcodes.txt


^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: Multiple-output-file make rules: We're Doing It Wrong
@ 2018-03-22 03:16  Tom Lane <[email protected]>
  parent: Tom Lane <[email protected]>
  0 siblings, 0 replies; 29+ messages in thread

From: Tom Lane @ 2018-03-22 03:16 UTC (permalink / raw)
  To: [email protected]

I wrote:
> I looked for rules with this bug by looking for comments that
> mention parser/Makefile.  There may well be some more, but I have
> no good idea how to find them --- any thoughts?

I realized that grepping for line-ending semicolons in makefiles
would be a pretty efficient way to check this.  Doing so reveals
these additional trouble spots:

src/Makefile.shlib:324:$(stlib): $(shlib) ;
src/Makefile.shlib:361:$(stlib): $(shlib) ;
src/backend/Makefile:79:libpostgres.a: postgres ;
src/backend/Makefile:89:libpostgres.a: postgres ;
src/test/isolation/Makefile:46:specparse.h: specparse.c ;
src/interfaces/ecpg/preproc/Makefile:42:preproc.h: preproc.c ;

I'm not too excited about the libpostgres.a cases, but the last
two are definitely hazards for VPATH builds, and the two cases in
Makefile.shlib might be worth fixing too.

Also, I trolled the archives for possible reports of actual problems
of this ilk.  I found this:

https://www.postgresql.org/message-id/569C22C0.70404%40lucee.org

which certainly looks exactly like the sort of behavior I'd expect,
if there'd been a timestamp problem in the 9.5.0 tarball.  But the
rules around *dll.def files don't look like there's any such bug.

			regards, tom lane




^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* [PATCH 2/2] doc review
@ 2021-03-03 22:36  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 29+ messages in thread

From: Justin Pryzby @ 2021-03-03 22:36 UTC (permalink / raw)

---
 doc/src/sgml/libpq.sgml                | 67 +++++++++++++-------------
 src/interfaces/libpq/fe-exec.c         |  2 +-
 src/test/modules/test_libpq/pipeline.c |  6 +--
 3 files changed, 38 insertions(+), 37 deletions(-)

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index a34ecbb144..e2865a218b 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -3130,8 +3130,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_SYNC</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a point in a
-            pipeline where a synchronization point has been established.
+            The <structname>PGresult</structname> represents a
+            synchronization point in pipeline mode, requested by 
+            <xref linkend="libpq-PQsendPipeline"/>.
             This status occurs only when pipeline mode has been selected.
            </para>
           </listitem>
@@ -3141,9 +3142,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_ABORTED</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a pipeline that's
+            The <structname>PGresult</structname> represents a pipeline that has
             received an error from the server.  <function>PQgetResult</function>
-            must be called repeatedly, and it will return this status code,
+            must be called repeatedly, and each time it will return this status code
             until the end of the current pipeline, at which point it will return
             <literal>PGRES_PIPELINE_SYNC</literal> and normal processing can
             resume.
@@ -4953,7 +4954,7 @@ int PQflush(PGconn *conn);
    <title>Using Pipeline Mode</title>
 
    <para>
-    To issue pipelines the application must switch a connection into pipeline mode.
+    To issue pipelines, the application must switch a connection into pipeline mode.
     Enter pipeline mode with <xref linkend="libpq-PQenterPipelineMode"/>
     or test whether pipeline mode is active with
     <xref linkend="libpq-PQpipelineStatus"/>.
@@ -4975,7 +4976,7 @@ int PQflush(PGconn *conn);
         server will block trying to send results to the client from queries
         it has already processed. This only occurs when the client sends
         enough queries to fill both its output buffer and the server's receive
-        buffer before switching to processing input from the server,
+        buffer before it switches to processing input from the server,
         but it's hard to predict exactly when that will happen.
        </para>
       </footnote>
@@ -5025,7 +5026,7 @@ int PQflush(PGconn *conn);
     <title>Processing Results</title>
 
     <para>
-     To process the result of one pipeline query, the application calls
+     To process the result of one query in a pipeline, the application calls
      <function>PQgetResult</function> repeatedly and handles each result
      until <function>PQgetResult</function> returns null.
      The result from the next query in the pipeline may then be retrieved using
@@ -5057,10 +5058,10 @@ int PQflush(PGconn *conn);
      <type>PGresult</type> types <literal>PGRES_PIPELINE_SYNC</literal>
      and <literal>PGRES_PIPELINE_ABORTED</literal>.
      <literal>PGRES_PIPELINE_SYNC</literal> is reported exactly once for each
-     <function>PQsendPipeline</function> call at the corresponding point in
-     the result stream.
+     <function>PQsendPipeline</function> after retrieving results for all
+     queries in the pipeline.
      <literal>PGRES_PIPELINE_ABORTED</literal> is emitted in place of a normal
-     result stream result for the first error and all subsequent results
+     stream result for the first error and all subsequent results
      except <literal>PGRES_PIPELINE_SYNC</literal> and null;
      see <xref linkend="libpq-pipeline-errors"/>.
     </para>
@@ -5075,7 +5076,8 @@ int PQflush(PGconn *conn);
      application about the query currently being processed (except that
      <function>PQgetResult</function> returns null to indicate that we start
      returning the results of next query). The application must keep track
-     of the order in which it sent queries and the expected results.
+     of the order in which it sent queries, to associate them with their
+     corresponding results.
      Applications will typically use a state machine or a FIFO queue for this.
     </para>
 
@@ -5091,10 +5093,10 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     From the client perspective, after the client gets a
-     <literal>PGRES_FATAL_ERROR</literal> return from
-     <function>PQresultStatus</function> the pipeline is flagged as aborted.
-     <application>libpq</application> will report
+     From the client perspective, after <function>PQresultStatus</function>
+     returns <literal>PGRES_FATAL_ERROR</literal>,
+     the pipeline is flagged as aborted.
+     <function>PQresultStatus</function>, will report a
      <literal>PGRES_PIPELINE_ABORTED</literal> result for each remaining queued
      operation in an aborted pipeline. The result for
      <function>PQsendPipeline</function> is reported as
@@ -5108,8 +5110,8 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     If the pipeline used an implicit transaction then operations that have
-     already executed are rolled back and operations that were queued for after
+     If the pipeline used an implicit transaction, then operations that have
+     already executed are rolled back and operations that were queued to follow
      the failed operation are skipped entirely. The same behaviour holds if the
      pipeline starts and commits a single explicit transaction (i.e. the first
      statement is <literal>BEGIN</literal> and the last is
@@ -5145,11 +5147,11 @@ int PQflush(PGconn *conn);
 
     <para>
      The client application should generally maintain a queue of work
-     still to be dispatched and a queue of work that has been dispatched
+     remaining to be dispatched and a queue of work that has been dispatched
      but not yet had its results processed. When the socket is writable
      it should dispatch more work. When the socket is readable it should
      read results and process them, matching them up to the next entry in
-     its expected results queue.  Based on available memory, results from
+     its expected results queue.  Based on available memory, results from the
      socket should be read frequently: there's no need to wait until the
      pipeline end to read the results.  Pipelines should be scoped to logical
      units of work, usually (but not necessarily) one transaction per pipeline.
@@ -5191,8 +5193,8 @@ int PQflush(PGconn *conn);
 
      <listitem>
       <para>
-      Returns current pipeline mode status of the <application>libpq</application>
-      connection.
+      Returns the current pipeline mode status of the
+      <application>libpq</application> connection.
 <synopsis>
 PGpipelineStatus PQpipelineStatus(const PGconn *conn);
 </synopsis>
@@ -5233,11 +5235,10 @@ PGpipelineStatus PQpipelineStatus(const PGconn *conn);
          <listitem>
           <para>
            The <application>libpq</application> connection is in pipeline
-           mode and an error has occurred while processing the current
-           pipeline.
-           The aborted flag is cleared as soon as the result
-           of the <function>PQsendPipeline</function> at the end of the aborted
-           pipeline is processed. Clients don't usually need this function to
+           mode and an error occurred while processing the current pipeline.
+           The aborted flag is cleared when <function>PQresultStatus</function>
+           returns PGRES_PIPELINE_SYNC at the end of the pipeline.
+           Clients don't usually need this function to
            verify aborted status, as they can tell that the pipeline is aborted
            from the <literal>PGRES_PIPELINE_ABORTED</literal> result code.
           </para>
@@ -5328,7 +5329,7 @@ int PQsendPipeline(PGconn *conn);
        Returns 1 for success. Returns 0 if the connection is not in
        pipeline mode or sending a
        <link linkend="protocol-flow-ext-query">sync message</link>
-       is failed.
+       failed.
       </para>
      </listitem>
     </varlistentry>
@@ -5349,7 +5350,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is most useful when the server is distant, i.e., network latency
     (<quote>ping time</quote>) is high, and also when many small operations
-    are being performed in rapid sequence.  There is usually less benefit
+    are being performed in rapid succession.  There is usually less benefit
     in using pipelined commands when each query takes many multiples of the client/server
     round-trip time to execute.  A 100-statement operation run on a server
     300ms round-trip-time away would take 30 seconds in network latency alone
@@ -5367,7 +5368,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is not useful when information from one operation is required by
     the client to produce the next operation. In such cases, the client
-    must introduce a synchronization point and wait for a full client/server
+    would have to introduce a synchronization point and wait for a full client/server
     round-trip to get the results it needs. However, it's often possible to
     adjust the client design to exchange the required information server-side.
     Read-modify-write cycles are especially good candidates; for example:
@@ -5392,10 +5393,10 @@ UPDATE mytable SET x = x + 1 WHERE id = 42;
 
    <note>
     <para>
-     The pipeline API was introduced in PostgreSQL 14, but clients using
-     the PostgreSQL 14 version of <application>libpq</application> can use
-     pipelines on server versions 7.4 and newer. Pipeline mode works on any server
-     that supports the v3 extended query protocol.
+     The pipeline API was introduced in <productname>PostgreSQL</productname> 14.
+     Pipeline mode is a client-side feature which doesn't require server
+     support, and works on any server that supports the v3 extended query
+     protocol.
     </para>
    </note>
   </sect2>
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index 7ae7c14948..d7b036a35c 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -3803,7 +3803,7 @@ pqPipelineFlush(PGconn *conn)
 {
 	if ((conn->pipelineStatus == PQ_PIPELINE_OFF) ||
 		(conn->outCount >= OUTBUFFER_THRESHOLD))
-		return (pqFlush(conn));
+		return pqFlush(conn);
 	return 0;
 }
 
diff --git a/src/test/modules/test_libpq/pipeline.c b/src/test/modules/test_libpq/pipeline.c
index f4a2bdec57..01d5a9a8ff 100644
--- a/src/test/modules/test_libpq/pipeline.c
+++ b/src/test/modules/test_libpq/pipeline.c
@@ -126,7 +126,7 @@ test_simple_pipeline(PGconn *conn)
 	 * process the results of as they come in.
 	 *
 	 * For a simple case we should be able to do this without interim
-	 * processing of results since our out buffer will give us enough slush to
+	 * processing of results since our output buffer will give us enough slush to
 	 * work with and we won't block on sending. So blocking mode is fine.
 	 */
 	if (PQisnonblocking(conn))
@@ -603,7 +603,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 
 	/*
 	 * Now we start inserting. We'll be sending enough data that we could fill
-	 * our out buffer, so to avoid deadlocking we need to enter nonblocking
+	 * our output buffer, so to avoid deadlocking we need to enter nonblocking
 	 * mode and consume input while we send more output. As results of each
 	 * query are processed we should pop them to allow processing of the next
 	 * query. There's no need to finish the pipeline before processing
@@ -635,7 +635,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 		}
 
 		/*
-		 * Process any results, so we keep the server's out buffer free
+		 * Process any results, so we keep the server's output buffer free
 		 * flowing and it can continue to process input
 		 */
 		if (FD_ISSET(sock, &input_mask))
-- 
2.17.0


--oC1+HKm2/end4ao3--





^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* [PATCH 2/2] doc review
@ 2021-03-03 22:36  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 29+ messages in thread

From: Justin Pryzby @ 2021-03-03 22:36 UTC (permalink / raw)

---
 doc/src/sgml/libpq.sgml                | 67 +++++++++++++-------------
 src/interfaces/libpq/fe-exec.c         |  2 +-
 src/test/modules/test_libpq/pipeline.c |  6 +--
 3 files changed, 38 insertions(+), 37 deletions(-)

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index a34ecbb144..e2865a218b 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -3130,8 +3130,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_SYNC</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a point in a
-            pipeline where a synchronization point has been established.
+            The <structname>PGresult</structname> represents a
+            synchronization point in pipeline mode, requested by 
+            <xref linkend="libpq-PQsendPipeline"/>.
             This status occurs only when pipeline mode has been selected.
            </para>
           </listitem>
@@ -3141,9 +3142,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_ABORTED</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a pipeline that's
+            The <structname>PGresult</structname> represents a pipeline that has
             received an error from the server.  <function>PQgetResult</function>
-            must be called repeatedly, and it will return this status code,
+            must be called repeatedly, and each time it will return this status code
             until the end of the current pipeline, at which point it will return
             <literal>PGRES_PIPELINE_SYNC</literal> and normal processing can
             resume.
@@ -4953,7 +4954,7 @@ int PQflush(PGconn *conn);
    <title>Using Pipeline Mode</title>
 
    <para>
-    To issue pipelines the application must switch a connection into pipeline mode.
+    To issue pipelines, the application must switch a connection into pipeline mode.
     Enter pipeline mode with <xref linkend="libpq-PQenterPipelineMode"/>
     or test whether pipeline mode is active with
     <xref linkend="libpq-PQpipelineStatus"/>.
@@ -4975,7 +4976,7 @@ int PQflush(PGconn *conn);
         server will block trying to send results to the client from queries
         it has already processed. This only occurs when the client sends
         enough queries to fill both its output buffer and the server's receive
-        buffer before switching to processing input from the server,
+        buffer before it switches to processing input from the server,
         but it's hard to predict exactly when that will happen.
        </para>
       </footnote>
@@ -5025,7 +5026,7 @@ int PQflush(PGconn *conn);
     <title>Processing Results</title>
 
     <para>
-     To process the result of one pipeline query, the application calls
+     To process the result of one query in a pipeline, the application calls
      <function>PQgetResult</function> repeatedly and handles each result
      until <function>PQgetResult</function> returns null.
      The result from the next query in the pipeline may then be retrieved using
@@ -5057,10 +5058,10 @@ int PQflush(PGconn *conn);
      <type>PGresult</type> types <literal>PGRES_PIPELINE_SYNC</literal>
      and <literal>PGRES_PIPELINE_ABORTED</literal>.
      <literal>PGRES_PIPELINE_SYNC</literal> is reported exactly once for each
-     <function>PQsendPipeline</function> call at the corresponding point in
-     the result stream.
+     <function>PQsendPipeline</function> after retrieving results for all
+     queries in the pipeline.
      <literal>PGRES_PIPELINE_ABORTED</literal> is emitted in place of a normal
-     result stream result for the first error and all subsequent results
+     stream result for the first error and all subsequent results
      except <literal>PGRES_PIPELINE_SYNC</literal> and null;
      see <xref linkend="libpq-pipeline-errors"/>.
     </para>
@@ -5075,7 +5076,8 @@ int PQflush(PGconn *conn);
      application about the query currently being processed (except that
      <function>PQgetResult</function> returns null to indicate that we start
      returning the results of next query). The application must keep track
-     of the order in which it sent queries and the expected results.
+     of the order in which it sent queries, to associate them with their
+     corresponding results.
      Applications will typically use a state machine or a FIFO queue for this.
     </para>
 
@@ -5091,10 +5093,10 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     From the client perspective, after the client gets a
-     <literal>PGRES_FATAL_ERROR</literal> return from
-     <function>PQresultStatus</function> the pipeline is flagged as aborted.
-     <application>libpq</application> will report
+     From the client perspective, after <function>PQresultStatus</function>
+     returns <literal>PGRES_FATAL_ERROR</literal>,
+     the pipeline is flagged as aborted.
+     <function>PQresultStatus</function>, will report a
      <literal>PGRES_PIPELINE_ABORTED</literal> result for each remaining queued
      operation in an aborted pipeline. The result for
      <function>PQsendPipeline</function> is reported as
@@ -5108,8 +5110,8 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     If the pipeline used an implicit transaction then operations that have
-     already executed are rolled back and operations that were queued for after
+     If the pipeline used an implicit transaction, then operations that have
+     already executed are rolled back and operations that were queued to follow
      the failed operation are skipped entirely. The same behaviour holds if the
      pipeline starts and commits a single explicit transaction (i.e. the first
      statement is <literal>BEGIN</literal> and the last is
@@ -5145,11 +5147,11 @@ int PQflush(PGconn *conn);
 
     <para>
      The client application should generally maintain a queue of work
-     still to be dispatched and a queue of work that has been dispatched
+     remaining to be dispatched and a queue of work that has been dispatched
      but not yet had its results processed. When the socket is writable
      it should dispatch more work. When the socket is readable it should
      read results and process them, matching them up to the next entry in
-     its expected results queue.  Based on available memory, results from
+     its expected results queue.  Based on available memory, results from the
      socket should be read frequently: there's no need to wait until the
      pipeline end to read the results.  Pipelines should be scoped to logical
      units of work, usually (but not necessarily) one transaction per pipeline.
@@ -5191,8 +5193,8 @@ int PQflush(PGconn *conn);
 
      <listitem>
       <para>
-      Returns current pipeline mode status of the <application>libpq</application>
-      connection.
+      Returns the current pipeline mode status of the
+      <application>libpq</application> connection.
 <synopsis>
 PGpipelineStatus PQpipelineStatus(const PGconn *conn);
 </synopsis>
@@ -5233,11 +5235,10 @@ PGpipelineStatus PQpipelineStatus(const PGconn *conn);
          <listitem>
           <para>
            The <application>libpq</application> connection is in pipeline
-           mode and an error has occurred while processing the current
-           pipeline.
-           The aborted flag is cleared as soon as the result
-           of the <function>PQsendPipeline</function> at the end of the aborted
-           pipeline is processed. Clients don't usually need this function to
+           mode and an error occurred while processing the current pipeline.
+           The aborted flag is cleared when <function>PQresultStatus</function>
+           returns PGRES_PIPELINE_SYNC at the end of the pipeline.
+           Clients don't usually need this function to
            verify aborted status, as they can tell that the pipeline is aborted
            from the <literal>PGRES_PIPELINE_ABORTED</literal> result code.
           </para>
@@ -5328,7 +5329,7 @@ int PQsendPipeline(PGconn *conn);
        Returns 1 for success. Returns 0 if the connection is not in
        pipeline mode or sending a
        <link linkend="protocol-flow-ext-query">sync message</link>
-       is failed.
+       failed.
       </para>
      </listitem>
     </varlistentry>
@@ -5349,7 +5350,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is most useful when the server is distant, i.e., network latency
     (<quote>ping time</quote>) is high, and also when many small operations
-    are being performed in rapid sequence.  There is usually less benefit
+    are being performed in rapid succession.  There is usually less benefit
     in using pipelined commands when each query takes many multiples of the client/server
     round-trip time to execute.  A 100-statement operation run on a server
     300ms round-trip-time away would take 30 seconds in network latency alone
@@ -5367,7 +5368,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is not useful when information from one operation is required by
     the client to produce the next operation. In such cases, the client
-    must introduce a synchronization point and wait for a full client/server
+    would have to introduce a synchronization point and wait for a full client/server
     round-trip to get the results it needs. However, it's often possible to
     adjust the client design to exchange the required information server-side.
     Read-modify-write cycles are especially good candidates; for example:
@@ -5392,10 +5393,10 @@ UPDATE mytable SET x = x + 1 WHERE id = 42;
 
    <note>
     <para>
-     The pipeline API was introduced in PostgreSQL 14, but clients using
-     the PostgreSQL 14 version of <application>libpq</application> can use
-     pipelines on server versions 7.4 and newer. Pipeline mode works on any server
-     that supports the v3 extended query protocol.
+     The pipeline API was introduced in <productname>PostgreSQL</productname> 14.
+     Pipeline mode is a client-side feature which doesn't require server
+     support, and works on any server that supports the v3 extended query
+     protocol.
     </para>
    </note>
   </sect2>
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index 7ae7c14948..d7b036a35c 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -3803,7 +3803,7 @@ pqPipelineFlush(PGconn *conn)
 {
 	if ((conn->pipelineStatus == PQ_PIPELINE_OFF) ||
 		(conn->outCount >= OUTBUFFER_THRESHOLD))
-		return (pqFlush(conn));
+		return pqFlush(conn);
 	return 0;
 }
 
diff --git a/src/test/modules/test_libpq/pipeline.c b/src/test/modules/test_libpq/pipeline.c
index f4a2bdec57..01d5a9a8ff 100644
--- a/src/test/modules/test_libpq/pipeline.c
+++ b/src/test/modules/test_libpq/pipeline.c
@@ -126,7 +126,7 @@ test_simple_pipeline(PGconn *conn)
 	 * process the results of as they come in.
 	 *
 	 * For a simple case we should be able to do this without interim
-	 * processing of results since our out buffer will give us enough slush to
+	 * processing of results since our output buffer will give us enough slush to
 	 * work with and we won't block on sending. So blocking mode is fine.
 	 */
 	if (PQisnonblocking(conn))
@@ -603,7 +603,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 
 	/*
 	 * Now we start inserting. We'll be sending enough data that we could fill
-	 * our out buffer, so to avoid deadlocking we need to enter nonblocking
+	 * our output buffer, so to avoid deadlocking we need to enter nonblocking
 	 * mode and consume input while we send more output. As results of each
 	 * query are processed we should pop them to allow processing of the next
 	 * query. There's no need to finish the pipeline before processing
@@ -635,7 +635,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 		}
 
 		/*
-		 * Process any results, so we keep the server's out buffer free
+		 * Process any results, so we keep the server's output buffer free
 		 * flowing and it can continue to process input
 		 */
 		if (FD_ISSET(sock, &input_mask))
-- 
2.17.0


--oC1+HKm2/end4ao3--





^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* [PATCH 2/2] doc review
@ 2021-03-03 22:36  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 29+ messages in thread

From: Justin Pryzby @ 2021-03-03 22:36 UTC (permalink / raw)

---
 doc/src/sgml/libpq.sgml                | 67 +++++++++++++-------------
 src/interfaces/libpq/fe-exec.c         |  2 +-
 src/test/modules/test_libpq/pipeline.c |  6 +--
 3 files changed, 38 insertions(+), 37 deletions(-)

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index a34ecbb144..e2865a218b 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -3130,8 +3130,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_SYNC</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a point in a
-            pipeline where a synchronization point has been established.
+            The <structname>PGresult</structname> represents a
+            synchronization point in pipeline mode, requested by 
+            <xref linkend="libpq-PQsendPipeline"/>.
             This status occurs only when pipeline mode has been selected.
            </para>
           </listitem>
@@ -3141,9 +3142,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_ABORTED</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a pipeline that's
+            The <structname>PGresult</structname> represents a pipeline that has
             received an error from the server.  <function>PQgetResult</function>
-            must be called repeatedly, and it will return this status code,
+            must be called repeatedly, and each time it will return this status code
             until the end of the current pipeline, at which point it will return
             <literal>PGRES_PIPELINE_SYNC</literal> and normal processing can
             resume.
@@ -4953,7 +4954,7 @@ int PQflush(PGconn *conn);
    <title>Using Pipeline Mode</title>
 
    <para>
-    To issue pipelines the application must switch a connection into pipeline mode.
+    To issue pipelines, the application must switch a connection into pipeline mode.
     Enter pipeline mode with <xref linkend="libpq-PQenterPipelineMode"/>
     or test whether pipeline mode is active with
     <xref linkend="libpq-PQpipelineStatus"/>.
@@ -4975,7 +4976,7 @@ int PQflush(PGconn *conn);
         server will block trying to send results to the client from queries
         it has already processed. This only occurs when the client sends
         enough queries to fill both its output buffer and the server's receive
-        buffer before switching to processing input from the server,
+        buffer before it switches to processing input from the server,
         but it's hard to predict exactly when that will happen.
        </para>
       </footnote>
@@ -5025,7 +5026,7 @@ int PQflush(PGconn *conn);
     <title>Processing Results</title>
 
     <para>
-     To process the result of one pipeline query, the application calls
+     To process the result of one query in a pipeline, the application calls
      <function>PQgetResult</function> repeatedly and handles each result
      until <function>PQgetResult</function> returns null.
      The result from the next query in the pipeline may then be retrieved using
@@ -5057,10 +5058,10 @@ int PQflush(PGconn *conn);
      <type>PGresult</type> types <literal>PGRES_PIPELINE_SYNC</literal>
      and <literal>PGRES_PIPELINE_ABORTED</literal>.
      <literal>PGRES_PIPELINE_SYNC</literal> is reported exactly once for each
-     <function>PQsendPipeline</function> call at the corresponding point in
-     the result stream.
+     <function>PQsendPipeline</function> after retrieving results for all
+     queries in the pipeline.
      <literal>PGRES_PIPELINE_ABORTED</literal> is emitted in place of a normal
-     result stream result for the first error and all subsequent results
+     stream result for the first error and all subsequent results
      except <literal>PGRES_PIPELINE_SYNC</literal> and null;
      see <xref linkend="libpq-pipeline-errors"/>.
     </para>
@@ -5075,7 +5076,8 @@ int PQflush(PGconn *conn);
      application about the query currently being processed (except that
      <function>PQgetResult</function> returns null to indicate that we start
      returning the results of next query). The application must keep track
-     of the order in which it sent queries and the expected results.
+     of the order in which it sent queries, to associate them with their
+     corresponding results.
      Applications will typically use a state machine or a FIFO queue for this.
     </para>
 
@@ -5091,10 +5093,10 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     From the client perspective, after the client gets a
-     <literal>PGRES_FATAL_ERROR</literal> return from
-     <function>PQresultStatus</function> the pipeline is flagged as aborted.
-     <application>libpq</application> will report
+     From the client perspective, after <function>PQresultStatus</function>
+     returns <literal>PGRES_FATAL_ERROR</literal>,
+     the pipeline is flagged as aborted.
+     <function>PQresultStatus</function>, will report a
      <literal>PGRES_PIPELINE_ABORTED</literal> result for each remaining queued
      operation in an aborted pipeline. The result for
      <function>PQsendPipeline</function> is reported as
@@ -5108,8 +5110,8 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     If the pipeline used an implicit transaction then operations that have
-     already executed are rolled back and operations that were queued for after
+     If the pipeline used an implicit transaction, then operations that have
+     already executed are rolled back and operations that were queued to follow
      the failed operation are skipped entirely. The same behaviour holds if the
      pipeline starts and commits a single explicit transaction (i.e. the first
      statement is <literal>BEGIN</literal> and the last is
@@ -5145,11 +5147,11 @@ int PQflush(PGconn *conn);
 
     <para>
      The client application should generally maintain a queue of work
-     still to be dispatched and a queue of work that has been dispatched
+     remaining to be dispatched and a queue of work that has been dispatched
      but not yet had its results processed. When the socket is writable
      it should dispatch more work. When the socket is readable it should
      read results and process them, matching them up to the next entry in
-     its expected results queue.  Based on available memory, results from
+     its expected results queue.  Based on available memory, results from the
      socket should be read frequently: there's no need to wait until the
      pipeline end to read the results.  Pipelines should be scoped to logical
      units of work, usually (but not necessarily) one transaction per pipeline.
@@ -5191,8 +5193,8 @@ int PQflush(PGconn *conn);
 
      <listitem>
       <para>
-      Returns current pipeline mode status of the <application>libpq</application>
-      connection.
+      Returns the current pipeline mode status of the
+      <application>libpq</application> connection.
 <synopsis>
 PGpipelineStatus PQpipelineStatus(const PGconn *conn);
 </synopsis>
@@ -5233,11 +5235,10 @@ PGpipelineStatus PQpipelineStatus(const PGconn *conn);
          <listitem>
           <para>
            The <application>libpq</application> connection is in pipeline
-           mode and an error has occurred while processing the current
-           pipeline.
-           The aborted flag is cleared as soon as the result
-           of the <function>PQsendPipeline</function> at the end of the aborted
-           pipeline is processed. Clients don't usually need this function to
+           mode and an error occurred while processing the current pipeline.
+           The aborted flag is cleared when <function>PQresultStatus</function>
+           returns PGRES_PIPELINE_SYNC at the end of the pipeline.
+           Clients don't usually need this function to
            verify aborted status, as they can tell that the pipeline is aborted
            from the <literal>PGRES_PIPELINE_ABORTED</literal> result code.
           </para>
@@ -5328,7 +5329,7 @@ int PQsendPipeline(PGconn *conn);
        Returns 1 for success. Returns 0 if the connection is not in
        pipeline mode or sending a
        <link linkend="protocol-flow-ext-query">sync message</link>
-       is failed.
+       failed.
       </para>
      </listitem>
     </varlistentry>
@@ -5349,7 +5350,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is most useful when the server is distant, i.e., network latency
     (<quote>ping time</quote>) is high, and also when many small operations
-    are being performed in rapid sequence.  There is usually less benefit
+    are being performed in rapid succession.  There is usually less benefit
     in using pipelined commands when each query takes many multiples of the client/server
     round-trip time to execute.  A 100-statement operation run on a server
     300ms round-trip-time away would take 30 seconds in network latency alone
@@ -5367,7 +5368,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is not useful when information from one operation is required by
     the client to produce the next operation. In such cases, the client
-    must introduce a synchronization point and wait for a full client/server
+    would have to introduce a synchronization point and wait for a full client/server
     round-trip to get the results it needs. However, it's often possible to
     adjust the client design to exchange the required information server-side.
     Read-modify-write cycles are especially good candidates; for example:
@@ -5392,10 +5393,10 @@ UPDATE mytable SET x = x + 1 WHERE id = 42;
 
    <note>
     <para>
-     The pipeline API was introduced in PostgreSQL 14, but clients using
-     the PostgreSQL 14 version of <application>libpq</application> can use
-     pipelines on server versions 7.4 and newer. Pipeline mode works on any server
-     that supports the v3 extended query protocol.
+     The pipeline API was introduced in <productname>PostgreSQL</productname> 14.
+     Pipeline mode is a client-side feature which doesn't require server
+     support, and works on any server that supports the v3 extended query
+     protocol.
     </para>
    </note>
   </sect2>
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index 7ae7c14948..d7b036a35c 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -3803,7 +3803,7 @@ pqPipelineFlush(PGconn *conn)
 {
 	if ((conn->pipelineStatus == PQ_PIPELINE_OFF) ||
 		(conn->outCount >= OUTBUFFER_THRESHOLD))
-		return (pqFlush(conn));
+		return pqFlush(conn);
 	return 0;
 }
 
diff --git a/src/test/modules/test_libpq/pipeline.c b/src/test/modules/test_libpq/pipeline.c
index f4a2bdec57..01d5a9a8ff 100644
--- a/src/test/modules/test_libpq/pipeline.c
+++ b/src/test/modules/test_libpq/pipeline.c
@@ -126,7 +126,7 @@ test_simple_pipeline(PGconn *conn)
 	 * process the results of as they come in.
 	 *
 	 * For a simple case we should be able to do this without interim
-	 * processing of results since our out buffer will give us enough slush to
+	 * processing of results since our output buffer will give us enough slush to
 	 * work with and we won't block on sending. So blocking mode is fine.
 	 */
 	if (PQisnonblocking(conn))
@@ -603,7 +603,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 
 	/*
 	 * Now we start inserting. We'll be sending enough data that we could fill
-	 * our out buffer, so to avoid deadlocking we need to enter nonblocking
+	 * our output buffer, so to avoid deadlocking we need to enter nonblocking
 	 * mode and consume input while we send more output. As results of each
 	 * query are processed we should pop them to allow processing of the next
 	 * query. There's no need to finish the pipeline before processing
@@ -635,7 +635,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 		}
 
 		/*
-		 * Process any results, so we keep the server's out buffer free
+		 * Process any results, so we keep the server's output buffer free
 		 * flowing and it can continue to process input
 		 */
 		if (FD_ISSET(sock, &input_mask))
-- 
2.17.0


--oC1+HKm2/end4ao3--





^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* [PATCH 2/2] doc review
@ 2021-03-03 22:36  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 29+ messages in thread

From: Justin Pryzby @ 2021-03-03 22:36 UTC (permalink / raw)

---
 doc/src/sgml/libpq.sgml                | 67 +++++++++++++-------------
 src/interfaces/libpq/fe-exec.c         |  2 +-
 src/test/modules/test_libpq/pipeline.c |  6 +--
 3 files changed, 38 insertions(+), 37 deletions(-)

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index a34ecbb144..e2865a218b 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -3130,8 +3130,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_SYNC</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a point in a
-            pipeline where a synchronization point has been established.
+            The <structname>PGresult</structname> represents a
+            synchronization point in pipeline mode, requested by 
+            <xref linkend="libpq-PQsendPipeline"/>.
             This status occurs only when pipeline mode has been selected.
            </para>
           </listitem>
@@ -3141,9 +3142,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_ABORTED</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a pipeline that's
+            The <structname>PGresult</structname> represents a pipeline that has
             received an error from the server.  <function>PQgetResult</function>
-            must be called repeatedly, and it will return this status code,
+            must be called repeatedly, and each time it will return this status code
             until the end of the current pipeline, at which point it will return
             <literal>PGRES_PIPELINE_SYNC</literal> and normal processing can
             resume.
@@ -4953,7 +4954,7 @@ int PQflush(PGconn *conn);
    <title>Using Pipeline Mode</title>
 
    <para>
-    To issue pipelines the application must switch a connection into pipeline mode.
+    To issue pipelines, the application must switch a connection into pipeline mode.
     Enter pipeline mode with <xref linkend="libpq-PQenterPipelineMode"/>
     or test whether pipeline mode is active with
     <xref linkend="libpq-PQpipelineStatus"/>.
@@ -4975,7 +4976,7 @@ int PQflush(PGconn *conn);
         server will block trying to send results to the client from queries
         it has already processed. This only occurs when the client sends
         enough queries to fill both its output buffer and the server's receive
-        buffer before switching to processing input from the server,
+        buffer before it switches to processing input from the server,
         but it's hard to predict exactly when that will happen.
        </para>
       </footnote>
@@ -5025,7 +5026,7 @@ int PQflush(PGconn *conn);
     <title>Processing Results</title>
 
     <para>
-     To process the result of one pipeline query, the application calls
+     To process the result of one query in a pipeline, the application calls
      <function>PQgetResult</function> repeatedly and handles each result
      until <function>PQgetResult</function> returns null.
      The result from the next query in the pipeline may then be retrieved using
@@ -5057,10 +5058,10 @@ int PQflush(PGconn *conn);
      <type>PGresult</type> types <literal>PGRES_PIPELINE_SYNC</literal>
      and <literal>PGRES_PIPELINE_ABORTED</literal>.
      <literal>PGRES_PIPELINE_SYNC</literal> is reported exactly once for each
-     <function>PQsendPipeline</function> call at the corresponding point in
-     the result stream.
+     <function>PQsendPipeline</function> after retrieving results for all
+     queries in the pipeline.
      <literal>PGRES_PIPELINE_ABORTED</literal> is emitted in place of a normal
-     result stream result for the first error and all subsequent results
+     stream result for the first error and all subsequent results
      except <literal>PGRES_PIPELINE_SYNC</literal> and null;
      see <xref linkend="libpq-pipeline-errors"/>.
     </para>
@@ -5075,7 +5076,8 @@ int PQflush(PGconn *conn);
      application about the query currently being processed (except that
      <function>PQgetResult</function> returns null to indicate that we start
      returning the results of next query). The application must keep track
-     of the order in which it sent queries and the expected results.
+     of the order in which it sent queries, to associate them with their
+     corresponding results.
      Applications will typically use a state machine or a FIFO queue for this.
     </para>
 
@@ -5091,10 +5093,10 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     From the client perspective, after the client gets a
-     <literal>PGRES_FATAL_ERROR</literal> return from
-     <function>PQresultStatus</function> the pipeline is flagged as aborted.
-     <application>libpq</application> will report
+     From the client perspective, after <function>PQresultStatus</function>
+     returns <literal>PGRES_FATAL_ERROR</literal>,
+     the pipeline is flagged as aborted.
+     <function>PQresultStatus</function>, will report a
      <literal>PGRES_PIPELINE_ABORTED</literal> result for each remaining queued
      operation in an aborted pipeline. The result for
      <function>PQsendPipeline</function> is reported as
@@ -5108,8 +5110,8 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     If the pipeline used an implicit transaction then operations that have
-     already executed are rolled back and operations that were queued for after
+     If the pipeline used an implicit transaction, then operations that have
+     already executed are rolled back and operations that were queued to follow
      the failed operation are skipped entirely. The same behaviour holds if the
      pipeline starts and commits a single explicit transaction (i.e. the first
      statement is <literal>BEGIN</literal> and the last is
@@ -5145,11 +5147,11 @@ int PQflush(PGconn *conn);
 
     <para>
      The client application should generally maintain a queue of work
-     still to be dispatched and a queue of work that has been dispatched
+     remaining to be dispatched and a queue of work that has been dispatched
      but not yet had its results processed. When the socket is writable
      it should dispatch more work. When the socket is readable it should
      read results and process them, matching them up to the next entry in
-     its expected results queue.  Based on available memory, results from
+     its expected results queue.  Based on available memory, results from the
      socket should be read frequently: there's no need to wait until the
      pipeline end to read the results.  Pipelines should be scoped to logical
      units of work, usually (but not necessarily) one transaction per pipeline.
@@ -5191,8 +5193,8 @@ int PQflush(PGconn *conn);
 
      <listitem>
       <para>
-      Returns current pipeline mode status of the <application>libpq</application>
-      connection.
+      Returns the current pipeline mode status of the
+      <application>libpq</application> connection.
 <synopsis>
 PGpipelineStatus PQpipelineStatus(const PGconn *conn);
 </synopsis>
@@ -5233,11 +5235,10 @@ PGpipelineStatus PQpipelineStatus(const PGconn *conn);
          <listitem>
           <para>
            The <application>libpq</application> connection is in pipeline
-           mode and an error has occurred while processing the current
-           pipeline.
-           The aborted flag is cleared as soon as the result
-           of the <function>PQsendPipeline</function> at the end of the aborted
-           pipeline is processed. Clients don't usually need this function to
+           mode and an error occurred while processing the current pipeline.
+           The aborted flag is cleared when <function>PQresultStatus</function>
+           returns PGRES_PIPELINE_SYNC at the end of the pipeline.
+           Clients don't usually need this function to
            verify aborted status, as they can tell that the pipeline is aborted
            from the <literal>PGRES_PIPELINE_ABORTED</literal> result code.
           </para>
@@ -5328,7 +5329,7 @@ int PQsendPipeline(PGconn *conn);
        Returns 1 for success. Returns 0 if the connection is not in
        pipeline mode or sending a
        <link linkend="protocol-flow-ext-query">sync message</link>
-       is failed.
+       failed.
       </para>
      </listitem>
     </varlistentry>
@@ -5349,7 +5350,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is most useful when the server is distant, i.e., network latency
     (<quote>ping time</quote>) is high, and also when many small operations
-    are being performed in rapid sequence.  There is usually less benefit
+    are being performed in rapid succession.  There is usually less benefit
     in using pipelined commands when each query takes many multiples of the client/server
     round-trip time to execute.  A 100-statement operation run on a server
     300ms round-trip-time away would take 30 seconds in network latency alone
@@ -5367,7 +5368,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is not useful when information from one operation is required by
     the client to produce the next operation. In such cases, the client
-    must introduce a synchronization point and wait for a full client/server
+    would have to introduce a synchronization point and wait for a full client/server
     round-trip to get the results it needs. However, it's often possible to
     adjust the client design to exchange the required information server-side.
     Read-modify-write cycles are especially good candidates; for example:
@@ -5392,10 +5393,10 @@ UPDATE mytable SET x = x + 1 WHERE id = 42;
 
    <note>
     <para>
-     The pipeline API was introduced in PostgreSQL 14, but clients using
-     the PostgreSQL 14 version of <application>libpq</application> can use
-     pipelines on server versions 7.4 and newer. Pipeline mode works on any server
-     that supports the v3 extended query protocol.
+     The pipeline API was introduced in <productname>PostgreSQL</productname> 14.
+     Pipeline mode is a client-side feature which doesn't require server
+     support, and works on any server that supports the v3 extended query
+     protocol.
     </para>
    </note>
   </sect2>
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index 7ae7c14948..d7b036a35c 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -3803,7 +3803,7 @@ pqPipelineFlush(PGconn *conn)
 {
 	if ((conn->pipelineStatus == PQ_PIPELINE_OFF) ||
 		(conn->outCount >= OUTBUFFER_THRESHOLD))
-		return (pqFlush(conn));
+		return pqFlush(conn);
 	return 0;
 }
 
diff --git a/src/test/modules/test_libpq/pipeline.c b/src/test/modules/test_libpq/pipeline.c
index f4a2bdec57..01d5a9a8ff 100644
--- a/src/test/modules/test_libpq/pipeline.c
+++ b/src/test/modules/test_libpq/pipeline.c
@@ -126,7 +126,7 @@ test_simple_pipeline(PGconn *conn)
 	 * process the results of as they come in.
 	 *
 	 * For a simple case we should be able to do this without interim
-	 * processing of results since our out buffer will give us enough slush to
+	 * processing of results since our output buffer will give us enough slush to
 	 * work with and we won't block on sending. So blocking mode is fine.
 	 */
 	if (PQisnonblocking(conn))
@@ -603,7 +603,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 
 	/*
 	 * Now we start inserting. We'll be sending enough data that we could fill
-	 * our out buffer, so to avoid deadlocking we need to enter nonblocking
+	 * our output buffer, so to avoid deadlocking we need to enter nonblocking
 	 * mode and consume input while we send more output. As results of each
 	 * query are processed we should pop them to allow processing of the next
 	 * query. There's no need to finish the pipeline before processing
@@ -635,7 +635,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 		}
 
 		/*
-		 * Process any results, so we keep the server's out buffer free
+		 * Process any results, so we keep the server's output buffer free
 		 * flowing and it can continue to process input
 		 */
 		if (FD_ISSET(sock, &input_mask))
-- 
2.17.0


--oC1+HKm2/end4ao3--





^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* [PATCH 2/2] doc review
@ 2021-03-03 22:36  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 29+ messages in thread

From: Justin Pryzby @ 2021-03-03 22:36 UTC (permalink / raw)

---
 doc/src/sgml/libpq.sgml                | 67 +++++++++++++-------------
 src/interfaces/libpq/fe-exec.c         |  2 +-
 src/test/modules/test_libpq/pipeline.c |  6 +--
 3 files changed, 38 insertions(+), 37 deletions(-)

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index a34ecbb144..e2865a218b 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -3130,8 +3130,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_SYNC</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a point in a
-            pipeline where a synchronization point has been established.
+            The <structname>PGresult</structname> represents a
+            synchronization point in pipeline mode, requested by 
+            <xref linkend="libpq-PQsendPipeline"/>.
             This status occurs only when pipeline mode has been selected.
            </para>
           </listitem>
@@ -3141,9 +3142,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_ABORTED</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a pipeline that's
+            The <structname>PGresult</structname> represents a pipeline that has
             received an error from the server.  <function>PQgetResult</function>
-            must be called repeatedly, and it will return this status code,
+            must be called repeatedly, and each time it will return this status code
             until the end of the current pipeline, at which point it will return
             <literal>PGRES_PIPELINE_SYNC</literal> and normal processing can
             resume.
@@ -4953,7 +4954,7 @@ int PQflush(PGconn *conn);
    <title>Using Pipeline Mode</title>
 
    <para>
-    To issue pipelines the application must switch a connection into pipeline mode.
+    To issue pipelines, the application must switch a connection into pipeline mode.
     Enter pipeline mode with <xref linkend="libpq-PQenterPipelineMode"/>
     or test whether pipeline mode is active with
     <xref linkend="libpq-PQpipelineStatus"/>.
@@ -4975,7 +4976,7 @@ int PQflush(PGconn *conn);
         server will block trying to send results to the client from queries
         it has already processed. This only occurs when the client sends
         enough queries to fill both its output buffer and the server's receive
-        buffer before switching to processing input from the server,
+        buffer before it switches to processing input from the server,
         but it's hard to predict exactly when that will happen.
        </para>
       </footnote>
@@ -5025,7 +5026,7 @@ int PQflush(PGconn *conn);
     <title>Processing Results</title>
 
     <para>
-     To process the result of one pipeline query, the application calls
+     To process the result of one query in a pipeline, the application calls
      <function>PQgetResult</function> repeatedly and handles each result
      until <function>PQgetResult</function> returns null.
      The result from the next query in the pipeline may then be retrieved using
@@ -5057,10 +5058,10 @@ int PQflush(PGconn *conn);
      <type>PGresult</type> types <literal>PGRES_PIPELINE_SYNC</literal>
      and <literal>PGRES_PIPELINE_ABORTED</literal>.
      <literal>PGRES_PIPELINE_SYNC</literal> is reported exactly once for each
-     <function>PQsendPipeline</function> call at the corresponding point in
-     the result stream.
+     <function>PQsendPipeline</function> after retrieving results for all
+     queries in the pipeline.
      <literal>PGRES_PIPELINE_ABORTED</literal> is emitted in place of a normal
-     result stream result for the first error and all subsequent results
+     stream result for the first error and all subsequent results
      except <literal>PGRES_PIPELINE_SYNC</literal> and null;
      see <xref linkend="libpq-pipeline-errors"/>.
     </para>
@@ -5075,7 +5076,8 @@ int PQflush(PGconn *conn);
      application about the query currently being processed (except that
      <function>PQgetResult</function> returns null to indicate that we start
      returning the results of next query). The application must keep track
-     of the order in which it sent queries and the expected results.
+     of the order in which it sent queries, to associate them with their
+     corresponding results.
      Applications will typically use a state machine or a FIFO queue for this.
     </para>
 
@@ -5091,10 +5093,10 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     From the client perspective, after the client gets a
-     <literal>PGRES_FATAL_ERROR</literal> return from
-     <function>PQresultStatus</function> the pipeline is flagged as aborted.
-     <application>libpq</application> will report
+     From the client perspective, after <function>PQresultStatus</function>
+     returns <literal>PGRES_FATAL_ERROR</literal>,
+     the pipeline is flagged as aborted.
+     <function>PQresultStatus</function>, will report a
      <literal>PGRES_PIPELINE_ABORTED</literal> result for each remaining queued
      operation in an aborted pipeline. The result for
      <function>PQsendPipeline</function> is reported as
@@ -5108,8 +5110,8 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     If the pipeline used an implicit transaction then operations that have
-     already executed are rolled back and operations that were queued for after
+     If the pipeline used an implicit transaction, then operations that have
+     already executed are rolled back and operations that were queued to follow
      the failed operation are skipped entirely. The same behaviour holds if the
      pipeline starts and commits a single explicit transaction (i.e. the first
      statement is <literal>BEGIN</literal> and the last is
@@ -5145,11 +5147,11 @@ int PQflush(PGconn *conn);
 
     <para>
      The client application should generally maintain a queue of work
-     still to be dispatched and a queue of work that has been dispatched
+     remaining to be dispatched and a queue of work that has been dispatched
      but not yet had its results processed. When the socket is writable
      it should dispatch more work. When the socket is readable it should
      read results and process them, matching them up to the next entry in
-     its expected results queue.  Based on available memory, results from
+     its expected results queue.  Based on available memory, results from the
      socket should be read frequently: there's no need to wait until the
      pipeline end to read the results.  Pipelines should be scoped to logical
      units of work, usually (but not necessarily) one transaction per pipeline.
@@ -5191,8 +5193,8 @@ int PQflush(PGconn *conn);
 
      <listitem>
       <para>
-      Returns current pipeline mode status of the <application>libpq</application>
-      connection.
+      Returns the current pipeline mode status of the
+      <application>libpq</application> connection.
 <synopsis>
 PGpipelineStatus PQpipelineStatus(const PGconn *conn);
 </synopsis>
@@ -5233,11 +5235,10 @@ PGpipelineStatus PQpipelineStatus(const PGconn *conn);
          <listitem>
           <para>
            The <application>libpq</application> connection is in pipeline
-           mode and an error has occurred while processing the current
-           pipeline.
-           The aborted flag is cleared as soon as the result
-           of the <function>PQsendPipeline</function> at the end of the aborted
-           pipeline is processed. Clients don't usually need this function to
+           mode and an error occurred while processing the current pipeline.
+           The aborted flag is cleared when <function>PQresultStatus</function>
+           returns PGRES_PIPELINE_SYNC at the end of the pipeline.
+           Clients don't usually need this function to
            verify aborted status, as they can tell that the pipeline is aborted
            from the <literal>PGRES_PIPELINE_ABORTED</literal> result code.
           </para>
@@ -5328,7 +5329,7 @@ int PQsendPipeline(PGconn *conn);
        Returns 1 for success. Returns 0 if the connection is not in
        pipeline mode or sending a
        <link linkend="protocol-flow-ext-query">sync message</link>
-       is failed.
+       failed.
       </para>
      </listitem>
     </varlistentry>
@@ -5349,7 +5350,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is most useful when the server is distant, i.e., network latency
     (<quote>ping time</quote>) is high, and also when many small operations
-    are being performed in rapid sequence.  There is usually less benefit
+    are being performed in rapid succession.  There is usually less benefit
     in using pipelined commands when each query takes many multiples of the client/server
     round-trip time to execute.  A 100-statement operation run on a server
     300ms round-trip-time away would take 30 seconds in network latency alone
@@ -5367,7 +5368,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is not useful when information from one operation is required by
     the client to produce the next operation. In such cases, the client
-    must introduce a synchronization point and wait for a full client/server
+    would have to introduce a synchronization point and wait for a full client/server
     round-trip to get the results it needs. However, it's often possible to
     adjust the client design to exchange the required information server-side.
     Read-modify-write cycles are especially good candidates; for example:
@@ -5392,10 +5393,10 @@ UPDATE mytable SET x = x + 1 WHERE id = 42;
 
    <note>
     <para>
-     The pipeline API was introduced in PostgreSQL 14, but clients using
-     the PostgreSQL 14 version of <application>libpq</application> can use
-     pipelines on server versions 7.4 and newer. Pipeline mode works on any server
-     that supports the v3 extended query protocol.
+     The pipeline API was introduced in <productname>PostgreSQL</productname> 14.
+     Pipeline mode is a client-side feature which doesn't require server
+     support, and works on any server that supports the v3 extended query
+     protocol.
     </para>
    </note>
   </sect2>
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index 7ae7c14948..d7b036a35c 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -3803,7 +3803,7 @@ pqPipelineFlush(PGconn *conn)
 {
 	if ((conn->pipelineStatus == PQ_PIPELINE_OFF) ||
 		(conn->outCount >= OUTBUFFER_THRESHOLD))
-		return (pqFlush(conn));
+		return pqFlush(conn);
 	return 0;
 }
 
diff --git a/src/test/modules/test_libpq/pipeline.c b/src/test/modules/test_libpq/pipeline.c
index f4a2bdec57..01d5a9a8ff 100644
--- a/src/test/modules/test_libpq/pipeline.c
+++ b/src/test/modules/test_libpq/pipeline.c
@@ -126,7 +126,7 @@ test_simple_pipeline(PGconn *conn)
 	 * process the results of as they come in.
 	 *
 	 * For a simple case we should be able to do this without interim
-	 * processing of results since our out buffer will give us enough slush to
+	 * processing of results since our output buffer will give us enough slush to
 	 * work with and we won't block on sending. So blocking mode is fine.
 	 */
 	if (PQisnonblocking(conn))
@@ -603,7 +603,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 
 	/*
 	 * Now we start inserting. We'll be sending enough data that we could fill
-	 * our out buffer, so to avoid deadlocking we need to enter nonblocking
+	 * our output buffer, so to avoid deadlocking we need to enter nonblocking
 	 * mode and consume input while we send more output. As results of each
 	 * query are processed we should pop them to allow processing of the next
 	 * query. There's no need to finish the pipeline before processing
@@ -635,7 +635,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 		}
 
 		/*
-		 * Process any results, so we keep the server's out buffer free
+		 * Process any results, so we keep the server's output buffer free
 		 * flowing and it can continue to process input
 		 */
 		if (FD_ISSET(sock, &input_mask))
-- 
2.17.0


--oC1+HKm2/end4ao3--





^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* [PATCH 2/2] doc review
@ 2021-03-03 22:36  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 29+ messages in thread

From: Justin Pryzby @ 2021-03-03 22:36 UTC (permalink / raw)

---
 doc/src/sgml/libpq.sgml                | 67 +++++++++++++-------------
 src/interfaces/libpq/fe-exec.c         |  2 +-
 src/test/modules/test_libpq/pipeline.c |  6 +--
 3 files changed, 38 insertions(+), 37 deletions(-)

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index a34ecbb144..e2865a218b 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -3130,8 +3130,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_SYNC</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a point in a
-            pipeline where a synchronization point has been established.
+            The <structname>PGresult</structname> represents a
+            synchronization point in pipeline mode, requested by 
+            <xref linkend="libpq-PQsendPipeline"/>.
             This status occurs only when pipeline mode has been selected.
            </para>
           </listitem>
@@ -3141,9 +3142,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_ABORTED</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a pipeline that's
+            The <structname>PGresult</structname> represents a pipeline that has
             received an error from the server.  <function>PQgetResult</function>
-            must be called repeatedly, and it will return this status code,
+            must be called repeatedly, and each time it will return this status code
             until the end of the current pipeline, at which point it will return
             <literal>PGRES_PIPELINE_SYNC</literal> and normal processing can
             resume.
@@ -4953,7 +4954,7 @@ int PQflush(PGconn *conn);
    <title>Using Pipeline Mode</title>
 
    <para>
-    To issue pipelines the application must switch a connection into pipeline mode.
+    To issue pipelines, the application must switch a connection into pipeline mode.
     Enter pipeline mode with <xref linkend="libpq-PQenterPipelineMode"/>
     or test whether pipeline mode is active with
     <xref linkend="libpq-PQpipelineStatus"/>.
@@ -4975,7 +4976,7 @@ int PQflush(PGconn *conn);
         server will block trying to send results to the client from queries
         it has already processed. This only occurs when the client sends
         enough queries to fill both its output buffer and the server's receive
-        buffer before switching to processing input from the server,
+        buffer before it switches to processing input from the server,
         but it's hard to predict exactly when that will happen.
        </para>
       </footnote>
@@ -5025,7 +5026,7 @@ int PQflush(PGconn *conn);
     <title>Processing Results</title>
 
     <para>
-     To process the result of one pipeline query, the application calls
+     To process the result of one query in a pipeline, the application calls
      <function>PQgetResult</function> repeatedly and handles each result
      until <function>PQgetResult</function> returns null.
      The result from the next query in the pipeline may then be retrieved using
@@ -5057,10 +5058,10 @@ int PQflush(PGconn *conn);
      <type>PGresult</type> types <literal>PGRES_PIPELINE_SYNC</literal>
      and <literal>PGRES_PIPELINE_ABORTED</literal>.
      <literal>PGRES_PIPELINE_SYNC</literal> is reported exactly once for each
-     <function>PQsendPipeline</function> call at the corresponding point in
-     the result stream.
+     <function>PQsendPipeline</function> after retrieving results for all
+     queries in the pipeline.
      <literal>PGRES_PIPELINE_ABORTED</literal> is emitted in place of a normal
-     result stream result for the first error and all subsequent results
+     stream result for the first error and all subsequent results
      except <literal>PGRES_PIPELINE_SYNC</literal> and null;
      see <xref linkend="libpq-pipeline-errors"/>.
     </para>
@@ -5075,7 +5076,8 @@ int PQflush(PGconn *conn);
      application about the query currently being processed (except that
      <function>PQgetResult</function> returns null to indicate that we start
      returning the results of next query). The application must keep track
-     of the order in which it sent queries and the expected results.
+     of the order in which it sent queries, to associate them with their
+     corresponding results.
      Applications will typically use a state machine or a FIFO queue for this.
     </para>
 
@@ -5091,10 +5093,10 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     From the client perspective, after the client gets a
-     <literal>PGRES_FATAL_ERROR</literal> return from
-     <function>PQresultStatus</function> the pipeline is flagged as aborted.
-     <application>libpq</application> will report
+     From the client perspective, after <function>PQresultStatus</function>
+     returns <literal>PGRES_FATAL_ERROR</literal>,
+     the pipeline is flagged as aborted.
+     <function>PQresultStatus</function>, will report a
      <literal>PGRES_PIPELINE_ABORTED</literal> result for each remaining queued
      operation in an aborted pipeline. The result for
      <function>PQsendPipeline</function> is reported as
@@ -5108,8 +5110,8 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     If the pipeline used an implicit transaction then operations that have
-     already executed are rolled back and operations that were queued for after
+     If the pipeline used an implicit transaction, then operations that have
+     already executed are rolled back and operations that were queued to follow
      the failed operation are skipped entirely. The same behaviour holds if the
      pipeline starts and commits a single explicit transaction (i.e. the first
      statement is <literal>BEGIN</literal> and the last is
@@ -5145,11 +5147,11 @@ int PQflush(PGconn *conn);
 
     <para>
      The client application should generally maintain a queue of work
-     still to be dispatched and a queue of work that has been dispatched
+     remaining to be dispatched and a queue of work that has been dispatched
      but not yet had its results processed. When the socket is writable
      it should dispatch more work. When the socket is readable it should
      read results and process them, matching them up to the next entry in
-     its expected results queue.  Based on available memory, results from
+     its expected results queue.  Based on available memory, results from the
      socket should be read frequently: there's no need to wait until the
      pipeline end to read the results.  Pipelines should be scoped to logical
      units of work, usually (but not necessarily) one transaction per pipeline.
@@ -5191,8 +5193,8 @@ int PQflush(PGconn *conn);
 
      <listitem>
       <para>
-      Returns current pipeline mode status of the <application>libpq</application>
-      connection.
+      Returns the current pipeline mode status of the
+      <application>libpq</application> connection.
 <synopsis>
 PGpipelineStatus PQpipelineStatus(const PGconn *conn);
 </synopsis>
@@ -5233,11 +5235,10 @@ PGpipelineStatus PQpipelineStatus(const PGconn *conn);
          <listitem>
           <para>
            The <application>libpq</application> connection is in pipeline
-           mode and an error has occurred while processing the current
-           pipeline.
-           The aborted flag is cleared as soon as the result
-           of the <function>PQsendPipeline</function> at the end of the aborted
-           pipeline is processed. Clients don't usually need this function to
+           mode and an error occurred while processing the current pipeline.
+           The aborted flag is cleared when <function>PQresultStatus</function>
+           returns PGRES_PIPELINE_SYNC at the end of the pipeline.
+           Clients don't usually need this function to
            verify aborted status, as they can tell that the pipeline is aborted
            from the <literal>PGRES_PIPELINE_ABORTED</literal> result code.
           </para>
@@ -5328,7 +5329,7 @@ int PQsendPipeline(PGconn *conn);
        Returns 1 for success. Returns 0 if the connection is not in
        pipeline mode or sending a
        <link linkend="protocol-flow-ext-query">sync message</link>
-       is failed.
+       failed.
       </para>
      </listitem>
     </varlistentry>
@@ -5349,7 +5350,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is most useful when the server is distant, i.e., network latency
     (<quote>ping time</quote>) is high, and also when many small operations
-    are being performed in rapid sequence.  There is usually less benefit
+    are being performed in rapid succession.  There is usually less benefit
     in using pipelined commands when each query takes many multiples of the client/server
     round-trip time to execute.  A 100-statement operation run on a server
     300ms round-trip-time away would take 30 seconds in network latency alone
@@ -5367,7 +5368,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is not useful when information from one operation is required by
     the client to produce the next operation. In such cases, the client
-    must introduce a synchronization point and wait for a full client/server
+    would have to introduce a synchronization point and wait for a full client/server
     round-trip to get the results it needs. However, it's often possible to
     adjust the client design to exchange the required information server-side.
     Read-modify-write cycles are especially good candidates; for example:
@@ -5392,10 +5393,10 @@ UPDATE mytable SET x = x + 1 WHERE id = 42;
 
    <note>
     <para>
-     The pipeline API was introduced in PostgreSQL 14, but clients using
-     the PostgreSQL 14 version of <application>libpq</application> can use
-     pipelines on server versions 7.4 and newer. Pipeline mode works on any server
-     that supports the v3 extended query protocol.
+     The pipeline API was introduced in <productname>PostgreSQL</productname> 14.
+     Pipeline mode is a client-side feature which doesn't require server
+     support, and works on any server that supports the v3 extended query
+     protocol.
     </para>
    </note>
   </sect2>
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index 7ae7c14948..d7b036a35c 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -3803,7 +3803,7 @@ pqPipelineFlush(PGconn *conn)
 {
 	if ((conn->pipelineStatus == PQ_PIPELINE_OFF) ||
 		(conn->outCount >= OUTBUFFER_THRESHOLD))
-		return (pqFlush(conn));
+		return pqFlush(conn);
 	return 0;
 }
 
diff --git a/src/test/modules/test_libpq/pipeline.c b/src/test/modules/test_libpq/pipeline.c
index f4a2bdec57..01d5a9a8ff 100644
--- a/src/test/modules/test_libpq/pipeline.c
+++ b/src/test/modules/test_libpq/pipeline.c
@@ -126,7 +126,7 @@ test_simple_pipeline(PGconn *conn)
 	 * process the results of as they come in.
 	 *
 	 * For a simple case we should be able to do this without interim
-	 * processing of results since our out buffer will give us enough slush to
+	 * processing of results since our output buffer will give us enough slush to
 	 * work with and we won't block on sending. So blocking mode is fine.
 	 */
 	if (PQisnonblocking(conn))
@@ -603,7 +603,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 
 	/*
 	 * Now we start inserting. We'll be sending enough data that we could fill
-	 * our out buffer, so to avoid deadlocking we need to enter nonblocking
+	 * our output buffer, so to avoid deadlocking we need to enter nonblocking
 	 * mode and consume input while we send more output. As results of each
 	 * query are processed we should pop them to allow processing of the next
 	 * query. There's no need to finish the pipeline before processing
@@ -635,7 +635,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 		}
 
 		/*
-		 * Process any results, so we keep the server's out buffer free
+		 * Process any results, so we keep the server's output buffer free
 		 * flowing and it can continue to process input
 		 */
 		if (FD_ISSET(sock, &input_mask))
-- 
2.17.0


--oC1+HKm2/end4ao3--





^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* [PATCH 2/2] doc review
@ 2021-03-03 22:36  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 29+ messages in thread

From: Justin Pryzby @ 2021-03-03 22:36 UTC (permalink / raw)

---
 doc/src/sgml/libpq.sgml                | 67 +++++++++++++-------------
 src/interfaces/libpq/fe-exec.c         |  2 +-
 src/test/modules/test_libpq/pipeline.c |  6 +--
 3 files changed, 38 insertions(+), 37 deletions(-)

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index a34ecbb144..e2865a218b 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -3130,8 +3130,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_SYNC</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a point in a
-            pipeline where a synchronization point has been established.
+            The <structname>PGresult</structname> represents a
+            synchronization point in pipeline mode, requested by 
+            <xref linkend="libpq-PQsendPipeline"/>.
             This status occurs only when pipeline mode has been selected.
            </para>
           </listitem>
@@ -3141,9 +3142,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_ABORTED</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a pipeline that's
+            The <structname>PGresult</structname> represents a pipeline that has
             received an error from the server.  <function>PQgetResult</function>
-            must be called repeatedly, and it will return this status code,
+            must be called repeatedly, and each time it will return this status code
             until the end of the current pipeline, at which point it will return
             <literal>PGRES_PIPELINE_SYNC</literal> and normal processing can
             resume.
@@ -4953,7 +4954,7 @@ int PQflush(PGconn *conn);
    <title>Using Pipeline Mode</title>
 
    <para>
-    To issue pipelines the application must switch a connection into pipeline mode.
+    To issue pipelines, the application must switch a connection into pipeline mode.
     Enter pipeline mode with <xref linkend="libpq-PQenterPipelineMode"/>
     or test whether pipeline mode is active with
     <xref linkend="libpq-PQpipelineStatus"/>.
@@ -4975,7 +4976,7 @@ int PQflush(PGconn *conn);
         server will block trying to send results to the client from queries
         it has already processed. This only occurs when the client sends
         enough queries to fill both its output buffer and the server's receive
-        buffer before switching to processing input from the server,
+        buffer before it switches to processing input from the server,
         but it's hard to predict exactly when that will happen.
        </para>
       </footnote>
@@ -5025,7 +5026,7 @@ int PQflush(PGconn *conn);
     <title>Processing Results</title>
 
     <para>
-     To process the result of one pipeline query, the application calls
+     To process the result of one query in a pipeline, the application calls
      <function>PQgetResult</function> repeatedly and handles each result
      until <function>PQgetResult</function> returns null.
      The result from the next query in the pipeline may then be retrieved using
@@ -5057,10 +5058,10 @@ int PQflush(PGconn *conn);
      <type>PGresult</type> types <literal>PGRES_PIPELINE_SYNC</literal>
      and <literal>PGRES_PIPELINE_ABORTED</literal>.
      <literal>PGRES_PIPELINE_SYNC</literal> is reported exactly once for each
-     <function>PQsendPipeline</function> call at the corresponding point in
-     the result stream.
+     <function>PQsendPipeline</function> after retrieving results for all
+     queries in the pipeline.
      <literal>PGRES_PIPELINE_ABORTED</literal> is emitted in place of a normal
-     result stream result for the first error and all subsequent results
+     stream result for the first error and all subsequent results
      except <literal>PGRES_PIPELINE_SYNC</literal> and null;
      see <xref linkend="libpq-pipeline-errors"/>.
     </para>
@@ -5075,7 +5076,8 @@ int PQflush(PGconn *conn);
      application about the query currently being processed (except that
      <function>PQgetResult</function> returns null to indicate that we start
      returning the results of next query). The application must keep track
-     of the order in which it sent queries and the expected results.
+     of the order in which it sent queries, to associate them with their
+     corresponding results.
      Applications will typically use a state machine or a FIFO queue for this.
     </para>
 
@@ -5091,10 +5093,10 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     From the client perspective, after the client gets a
-     <literal>PGRES_FATAL_ERROR</literal> return from
-     <function>PQresultStatus</function> the pipeline is flagged as aborted.
-     <application>libpq</application> will report
+     From the client perspective, after <function>PQresultStatus</function>
+     returns <literal>PGRES_FATAL_ERROR</literal>,
+     the pipeline is flagged as aborted.
+     <function>PQresultStatus</function>, will report a
      <literal>PGRES_PIPELINE_ABORTED</literal> result for each remaining queued
      operation in an aborted pipeline. The result for
      <function>PQsendPipeline</function> is reported as
@@ -5108,8 +5110,8 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     If the pipeline used an implicit transaction then operations that have
-     already executed are rolled back and operations that were queued for after
+     If the pipeline used an implicit transaction, then operations that have
+     already executed are rolled back and operations that were queued to follow
      the failed operation are skipped entirely. The same behaviour holds if the
      pipeline starts and commits a single explicit transaction (i.e. the first
      statement is <literal>BEGIN</literal> and the last is
@@ -5145,11 +5147,11 @@ int PQflush(PGconn *conn);
 
     <para>
      The client application should generally maintain a queue of work
-     still to be dispatched and a queue of work that has been dispatched
+     remaining to be dispatched and a queue of work that has been dispatched
      but not yet had its results processed. When the socket is writable
      it should dispatch more work. When the socket is readable it should
      read results and process them, matching them up to the next entry in
-     its expected results queue.  Based on available memory, results from
+     its expected results queue.  Based on available memory, results from the
      socket should be read frequently: there's no need to wait until the
      pipeline end to read the results.  Pipelines should be scoped to logical
      units of work, usually (but not necessarily) one transaction per pipeline.
@@ -5191,8 +5193,8 @@ int PQflush(PGconn *conn);
 
      <listitem>
       <para>
-      Returns current pipeline mode status of the <application>libpq</application>
-      connection.
+      Returns the current pipeline mode status of the
+      <application>libpq</application> connection.
 <synopsis>
 PGpipelineStatus PQpipelineStatus(const PGconn *conn);
 </synopsis>
@@ -5233,11 +5235,10 @@ PGpipelineStatus PQpipelineStatus(const PGconn *conn);
          <listitem>
           <para>
            The <application>libpq</application> connection is in pipeline
-           mode and an error has occurred while processing the current
-           pipeline.
-           The aborted flag is cleared as soon as the result
-           of the <function>PQsendPipeline</function> at the end of the aborted
-           pipeline is processed. Clients don't usually need this function to
+           mode and an error occurred while processing the current pipeline.
+           The aborted flag is cleared when <function>PQresultStatus</function>
+           returns PGRES_PIPELINE_SYNC at the end of the pipeline.
+           Clients don't usually need this function to
            verify aborted status, as they can tell that the pipeline is aborted
            from the <literal>PGRES_PIPELINE_ABORTED</literal> result code.
           </para>
@@ -5328,7 +5329,7 @@ int PQsendPipeline(PGconn *conn);
        Returns 1 for success. Returns 0 if the connection is not in
        pipeline mode or sending a
        <link linkend="protocol-flow-ext-query">sync message</link>
-       is failed.
+       failed.
       </para>
      </listitem>
     </varlistentry>
@@ -5349,7 +5350,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is most useful when the server is distant, i.e., network latency
     (<quote>ping time</quote>) is high, and also when many small operations
-    are being performed in rapid sequence.  There is usually less benefit
+    are being performed in rapid succession.  There is usually less benefit
     in using pipelined commands when each query takes many multiples of the client/server
     round-trip time to execute.  A 100-statement operation run on a server
     300ms round-trip-time away would take 30 seconds in network latency alone
@@ -5367,7 +5368,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is not useful when information from one operation is required by
     the client to produce the next operation. In such cases, the client
-    must introduce a synchronization point and wait for a full client/server
+    would have to introduce a synchronization point and wait for a full client/server
     round-trip to get the results it needs. However, it's often possible to
     adjust the client design to exchange the required information server-side.
     Read-modify-write cycles are especially good candidates; for example:
@@ -5392,10 +5393,10 @@ UPDATE mytable SET x = x + 1 WHERE id = 42;
 
    <note>
     <para>
-     The pipeline API was introduced in PostgreSQL 14, but clients using
-     the PostgreSQL 14 version of <application>libpq</application> can use
-     pipelines on server versions 7.4 and newer. Pipeline mode works on any server
-     that supports the v3 extended query protocol.
+     The pipeline API was introduced in <productname>PostgreSQL</productname> 14.
+     Pipeline mode is a client-side feature which doesn't require server
+     support, and works on any server that supports the v3 extended query
+     protocol.
     </para>
    </note>
   </sect2>
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index 7ae7c14948..d7b036a35c 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -3803,7 +3803,7 @@ pqPipelineFlush(PGconn *conn)
 {
 	if ((conn->pipelineStatus == PQ_PIPELINE_OFF) ||
 		(conn->outCount >= OUTBUFFER_THRESHOLD))
-		return (pqFlush(conn));
+		return pqFlush(conn);
 	return 0;
 }
 
diff --git a/src/test/modules/test_libpq/pipeline.c b/src/test/modules/test_libpq/pipeline.c
index f4a2bdec57..01d5a9a8ff 100644
--- a/src/test/modules/test_libpq/pipeline.c
+++ b/src/test/modules/test_libpq/pipeline.c
@@ -126,7 +126,7 @@ test_simple_pipeline(PGconn *conn)
 	 * process the results of as they come in.
 	 *
 	 * For a simple case we should be able to do this without interim
-	 * processing of results since our out buffer will give us enough slush to
+	 * processing of results since our output buffer will give us enough slush to
 	 * work with and we won't block on sending. So blocking mode is fine.
 	 */
 	if (PQisnonblocking(conn))
@@ -603,7 +603,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 
 	/*
 	 * Now we start inserting. We'll be sending enough data that we could fill
-	 * our out buffer, so to avoid deadlocking we need to enter nonblocking
+	 * our output buffer, so to avoid deadlocking we need to enter nonblocking
 	 * mode and consume input while we send more output. As results of each
 	 * query are processed we should pop them to allow processing of the next
 	 * query. There's no need to finish the pipeline before processing
@@ -635,7 +635,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 		}
 
 		/*
-		 * Process any results, so we keep the server's out buffer free
+		 * Process any results, so we keep the server's output buffer free
 		 * flowing and it can continue to process input
 		 */
 		if (FD_ISSET(sock, &input_mask))
-- 
2.17.0


--oC1+HKm2/end4ao3--





^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* [PATCH 2/2] doc review
@ 2021-03-03 22:36  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 29+ messages in thread

From: Justin Pryzby @ 2021-03-03 22:36 UTC (permalink / raw)

---
 doc/src/sgml/libpq.sgml                | 67 +++++++++++++-------------
 src/interfaces/libpq/fe-exec.c         |  2 +-
 src/test/modules/test_libpq/pipeline.c |  6 +--
 3 files changed, 38 insertions(+), 37 deletions(-)

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index a34ecbb144..e2865a218b 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -3130,8 +3130,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_SYNC</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a point in a
-            pipeline where a synchronization point has been established.
+            The <structname>PGresult</structname> represents a
+            synchronization point in pipeline mode, requested by 
+            <xref linkend="libpq-PQsendPipeline"/>.
             This status occurs only when pipeline mode has been selected.
            </para>
           </listitem>
@@ -3141,9 +3142,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_ABORTED</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a pipeline that's
+            The <structname>PGresult</structname> represents a pipeline that has
             received an error from the server.  <function>PQgetResult</function>
-            must be called repeatedly, and it will return this status code,
+            must be called repeatedly, and each time it will return this status code
             until the end of the current pipeline, at which point it will return
             <literal>PGRES_PIPELINE_SYNC</literal> and normal processing can
             resume.
@@ -4953,7 +4954,7 @@ int PQflush(PGconn *conn);
    <title>Using Pipeline Mode</title>
 
    <para>
-    To issue pipelines the application must switch a connection into pipeline mode.
+    To issue pipelines, the application must switch a connection into pipeline mode.
     Enter pipeline mode with <xref linkend="libpq-PQenterPipelineMode"/>
     or test whether pipeline mode is active with
     <xref linkend="libpq-PQpipelineStatus"/>.
@@ -4975,7 +4976,7 @@ int PQflush(PGconn *conn);
         server will block trying to send results to the client from queries
         it has already processed. This only occurs when the client sends
         enough queries to fill both its output buffer and the server's receive
-        buffer before switching to processing input from the server,
+        buffer before it switches to processing input from the server,
         but it's hard to predict exactly when that will happen.
        </para>
       </footnote>
@@ -5025,7 +5026,7 @@ int PQflush(PGconn *conn);
     <title>Processing Results</title>
 
     <para>
-     To process the result of one pipeline query, the application calls
+     To process the result of one query in a pipeline, the application calls
      <function>PQgetResult</function> repeatedly and handles each result
      until <function>PQgetResult</function> returns null.
      The result from the next query in the pipeline may then be retrieved using
@@ -5057,10 +5058,10 @@ int PQflush(PGconn *conn);
      <type>PGresult</type> types <literal>PGRES_PIPELINE_SYNC</literal>
      and <literal>PGRES_PIPELINE_ABORTED</literal>.
      <literal>PGRES_PIPELINE_SYNC</literal> is reported exactly once for each
-     <function>PQsendPipeline</function> call at the corresponding point in
-     the result stream.
+     <function>PQsendPipeline</function> after retrieving results for all
+     queries in the pipeline.
      <literal>PGRES_PIPELINE_ABORTED</literal> is emitted in place of a normal
-     result stream result for the first error and all subsequent results
+     stream result for the first error and all subsequent results
      except <literal>PGRES_PIPELINE_SYNC</literal> and null;
      see <xref linkend="libpq-pipeline-errors"/>.
     </para>
@@ -5075,7 +5076,8 @@ int PQflush(PGconn *conn);
      application about the query currently being processed (except that
      <function>PQgetResult</function> returns null to indicate that we start
      returning the results of next query). The application must keep track
-     of the order in which it sent queries and the expected results.
+     of the order in which it sent queries, to associate them with their
+     corresponding results.
      Applications will typically use a state machine or a FIFO queue for this.
     </para>
 
@@ -5091,10 +5093,10 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     From the client perspective, after the client gets a
-     <literal>PGRES_FATAL_ERROR</literal> return from
-     <function>PQresultStatus</function> the pipeline is flagged as aborted.
-     <application>libpq</application> will report
+     From the client perspective, after <function>PQresultStatus</function>
+     returns <literal>PGRES_FATAL_ERROR</literal>,
+     the pipeline is flagged as aborted.
+     <function>PQresultStatus</function>, will report a
      <literal>PGRES_PIPELINE_ABORTED</literal> result for each remaining queued
      operation in an aborted pipeline. The result for
      <function>PQsendPipeline</function> is reported as
@@ -5108,8 +5110,8 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     If the pipeline used an implicit transaction then operations that have
-     already executed are rolled back and operations that were queued for after
+     If the pipeline used an implicit transaction, then operations that have
+     already executed are rolled back and operations that were queued to follow
      the failed operation are skipped entirely. The same behaviour holds if the
      pipeline starts and commits a single explicit transaction (i.e. the first
      statement is <literal>BEGIN</literal> and the last is
@@ -5145,11 +5147,11 @@ int PQflush(PGconn *conn);
 
     <para>
      The client application should generally maintain a queue of work
-     still to be dispatched and a queue of work that has been dispatched
+     remaining to be dispatched and a queue of work that has been dispatched
      but not yet had its results processed. When the socket is writable
      it should dispatch more work. When the socket is readable it should
      read results and process them, matching them up to the next entry in
-     its expected results queue.  Based on available memory, results from
+     its expected results queue.  Based on available memory, results from the
      socket should be read frequently: there's no need to wait until the
      pipeline end to read the results.  Pipelines should be scoped to logical
      units of work, usually (but not necessarily) one transaction per pipeline.
@@ -5191,8 +5193,8 @@ int PQflush(PGconn *conn);
 
      <listitem>
       <para>
-      Returns current pipeline mode status of the <application>libpq</application>
-      connection.
+      Returns the current pipeline mode status of the
+      <application>libpq</application> connection.
 <synopsis>
 PGpipelineStatus PQpipelineStatus(const PGconn *conn);
 </synopsis>
@@ -5233,11 +5235,10 @@ PGpipelineStatus PQpipelineStatus(const PGconn *conn);
          <listitem>
           <para>
            The <application>libpq</application> connection is in pipeline
-           mode and an error has occurred while processing the current
-           pipeline.
-           The aborted flag is cleared as soon as the result
-           of the <function>PQsendPipeline</function> at the end of the aborted
-           pipeline is processed. Clients don't usually need this function to
+           mode and an error occurred while processing the current pipeline.
+           The aborted flag is cleared when <function>PQresultStatus</function>
+           returns PGRES_PIPELINE_SYNC at the end of the pipeline.
+           Clients don't usually need this function to
            verify aborted status, as they can tell that the pipeline is aborted
            from the <literal>PGRES_PIPELINE_ABORTED</literal> result code.
           </para>
@@ -5328,7 +5329,7 @@ int PQsendPipeline(PGconn *conn);
        Returns 1 for success. Returns 0 if the connection is not in
        pipeline mode or sending a
        <link linkend="protocol-flow-ext-query">sync message</link>
-       is failed.
+       failed.
       </para>
      </listitem>
     </varlistentry>
@@ -5349,7 +5350,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is most useful when the server is distant, i.e., network latency
     (<quote>ping time</quote>) is high, and also when many small operations
-    are being performed in rapid sequence.  There is usually less benefit
+    are being performed in rapid succession.  There is usually less benefit
     in using pipelined commands when each query takes many multiples of the client/server
     round-trip time to execute.  A 100-statement operation run on a server
     300ms round-trip-time away would take 30 seconds in network latency alone
@@ -5367,7 +5368,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is not useful when information from one operation is required by
     the client to produce the next operation. In such cases, the client
-    must introduce a synchronization point and wait for a full client/server
+    would have to introduce a synchronization point and wait for a full client/server
     round-trip to get the results it needs. However, it's often possible to
     adjust the client design to exchange the required information server-side.
     Read-modify-write cycles are especially good candidates; for example:
@@ -5392,10 +5393,10 @@ UPDATE mytable SET x = x + 1 WHERE id = 42;
 
    <note>
     <para>
-     The pipeline API was introduced in PostgreSQL 14, but clients using
-     the PostgreSQL 14 version of <application>libpq</application> can use
-     pipelines on server versions 7.4 and newer. Pipeline mode works on any server
-     that supports the v3 extended query protocol.
+     The pipeline API was introduced in <productname>PostgreSQL</productname> 14.
+     Pipeline mode is a client-side feature which doesn't require server
+     support, and works on any server that supports the v3 extended query
+     protocol.
     </para>
    </note>
   </sect2>
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index 7ae7c14948..d7b036a35c 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -3803,7 +3803,7 @@ pqPipelineFlush(PGconn *conn)
 {
 	if ((conn->pipelineStatus == PQ_PIPELINE_OFF) ||
 		(conn->outCount >= OUTBUFFER_THRESHOLD))
-		return (pqFlush(conn));
+		return pqFlush(conn);
 	return 0;
 }
 
diff --git a/src/test/modules/test_libpq/pipeline.c b/src/test/modules/test_libpq/pipeline.c
index f4a2bdec57..01d5a9a8ff 100644
--- a/src/test/modules/test_libpq/pipeline.c
+++ b/src/test/modules/test_libpq/pipeline.c
@@ -126,7 +126,7 @@ test_simple_pipeline(PGconn *conn)
 	 * process the results of as they come in.
 	 *
 	 * For a simple case we should be able to do this without interim
-	 * processing of results since our out buffer will give us enough slush to
+	 * processing of results since our output buffer will give us enough slush to
 	 * work with and we won't block on sending. So blocking mode is fine.
 	 */
 	if (PQisnonblocking(conn))
@@ -603,7 +603,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 
 	/*
 	 * Now we start inserting. We'll be sending enough data that we could fill
-	 * our out buffer, so to avoid deadlocking we need to enter nonblocking
+	 * our output buffer, so to avoid deadlocking we need to enter nonblocking
 	 * mode and consume input while we send more output. As results of each
 	 * query are processed we should pop them to allow processing of the next
 	 * query. There's no need to finish the pipeline before processing
@@ -635,7 +635,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 		}
 
 		/*
-		 * Process any results, so we keep the server's out buffer free
+		 * Process any results, so we keep the server's output buffer free
 		 * flowing and it can continue to process input
 		 */
 		if (FD_ISSET(sock, &input_mask))
-- 
2.17.0


--oC1+HKm2/end4ao3--





^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* [PATCH 2/2] doc review
@ 2021-03-03 22:36  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 29+ messages in thread

From: Justin Pryzby @ 2021-03-03 22:36 UTC (permalink / raw)

---
 doc/src/sgml/libpq.sgml                | 67 +++++++++++++-------------
 src/interfaces/libpq/fe-exec.c         |  2 +-
 src/test/modules/test_libpq/pipeline.c |  6 +--
 3 files changed, 38 insertions(+), 37 deletions(-)

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index a34ecbb144..e2865a218b 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -3130,8 +3130,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_SYNC</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a point in a
-            pipeline where a synchronization point has been established.
+            The <structname>PGresult</structname> represents a
+            synchronization point in pipeline mode, requested by 
+            <xref linkend="libpq-PQsendPipeline"/>.
             This status occurs only when pipeline mode has been selected.
            </para>
           </listitem>
@@ -3141,9 +3142,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_ABORTED</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a pipeline that's
+            The <structname>PGresult</structname> represents a pipeline that has
             received an error from the server.  <function>PQgetResult</function>
-            must be called repeatedly, and it will return this status code,
+            must be called repeatedly, and each time it will return this status code
             until the end of the current pipeline, at which point it will return
             <literal>PGRES_PIPELINE_SYNC</literal> and normal processing can
             resume.
@@ -4953,7 +4954,7 @@ int PQflush(PGconn *conn);
    <title>Using Pipeline Mode</title>
 
    <para>
-    To issue pipelines the application must switch a connection into pipeline mode.
+    To issue pipelines, the application must switch a connection into pipeline mode.
     Enter pipeline mode with <xref linkend="libpq-PQenterPipelineMode"/>
     or test whether pipeline mode is active with
     <xref linkend="libpq-PQpipelineStatus"/>.
@@ -4975,7 +4976,7 @@ int PQflush(PGconn *conn);
         server will block trying to send results to the client from queries
         it has already processed. This only occurs when the client sends
         enough queries to fill both its output buffer and the server's receive
-        buffer before switching to processing input from the server,
+        buffer before it switches to processing input from the server,
         but it's hard to predict exactly when that will happen.
        </para>
       </footnote>
@@ -5025,7 +5026,7 @@ int PQflush(PGconn *conn);
     <title>Processing Results</title>
 
     <para>
-     To process the result of one pipeline query, the application calls
+     To process the result of one query in a pipeline, the application calls
      <function>PQgetResult</function> repeatedly and handles each result
      until <function>PQgetResult</function> returns null.
      The result from the next query in the pipeline may then be retrieved using
@@ -5057,10 +5058,10 @@ int PQflush(PGconn *conn);
      <type>PGresult</type> types <literal>PGRES_PIPELINE_SYNC</literal>
      and <literal>PGRES_PIPELINE_ABORTED</literal>.
      <literal>PGRES_PIPELINE_SYNC</literal> is reported exactly once for each
-     <function>PQsendPipeline</function> call at the corresponding point in
-     the result stream.
+     <function>PQsendPipeline</function> after retrieving results for all
+     queries in the pipeline.
      <literal>PGRES_PIPELINE_ABORTED</literal> is emitted in place of a normal
-     result stream result for the first error and all subsequent results
+     stream result for the first error and all subsequent results
      except <literal>PGRES_PIPELINE_SYNC</literal> and null;
      see <xref linkend="libpq-pipeline-errors"/>.
     </para>
@@ -5075,7 +5076,8 @@ int PQflush(PGconn *conn);
      application about the query currently being processed (except that
      <function>PQgetResult</function> returns null to indicate that we start
      returning the results of next query). The application must keep track
-     of the order in which it sent queries and the expected results.
+     of the order in which it sent queries, to associate them with their
+     corresponding results.
      Applications will typically use a state machine or a FIFO queue for this.
     </para>
 
@@ -5091,10 +5093,10 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     From the client perspective, after the client gets a
-     <literal>PGRES_FATAL_ERROR</literal> return from
-     <function>PQresultStatus</function> the pipeline is flagged as aborted.
-     <application>libpq</application> will report
+     From the client perspective, after <function>PQresultStatus</function>
+     returns <literal>PGRES_FATAL_ERROR</literal>,
+     the pipeline is flagged as aborted.
+     <function>PQresultStatus</function>, will report a
      <literal>PGRES_PIPELINE_ABORTED</literal> result for each remaining queued
      operation in an aborted pipeline. The result for
      <function>PQsendPipeline</function> is reported as
@@ -5108,8 +5110,8 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     If the pipeline used an implicit transaction then operations that have
-     already executed are rolled back and operations that were queued for after
+     If the pipeline used an implicit transaction, then operations that have
+     already executed are rolled back and operations that were queued to follow
      the failed operation are skipped entirely. The same behaviour holds if the
      pipeline starts and commits a single explicit transaction (i.e. the first
      statement is <literal>BEGIN</literal> and the last is
@@ -5145,11 +5147,11 @@ int PQflush(PGconn *conn);
 
     <para>
      The client application should generally maintain a queue of work
-     still to be dispatched and a queue of work that has been dispatched
+     remaining to be dispatched and a queue of work that has been dispatched
      but not yet had its results processed. When the socket is writable
      it should dispatch more work. When the socket is readable it should
      read results and process them, matching them up to the next entry in
-     its expected results queue.  Based on available memory, results from
+     its expected results queue.  Based on available memory, results from the
      socket should be read frequently: there's no need to wait until the
      pipeline end to read the results.  Pipelines should be scoped to logical
      units of work, usually (but not necessarily) one transaction per pipeline.
@@ -5191,8 +5193,8 @@ int PQflush(PGconn *conn);
 
      <listitem>
       <para>
-      Returns current pipeline mode status of the <application>libpq</application>
-      connection.
+      Returns the current pipeline mode status of the
+      <application>libpq</application> connection.
 <synopsis>
 PGpipelineStatus PQpipelineStatus(const PGconn *conn);
 </synopsis>
@@ -5233,11 +5235,10 @@ PGpipelineStatus PQpipelineStatus(const PGconn *conn);
          <listitem>
           <para>
            The <application>libpq</application> connection is in pipeline
-           mode and an error has occurred while processing the current
-           pipeline.
-           The aborted flag is cleared as soon as the result
-           of the <function>PQsendPipeline</function> at the end of the aborted
-           pipeline is processed. Clients don't usually need this function to
+           mode and an error occurred while processing the current pipeline.
+           The aborted flag is cleared when <function>PQresultStatus</function>
+           returns PGRES_PIPELINE_SYNC at the end of the pipeline.
+           Clients don't usually need this function to
            verify aborted status, as they can tell that the pipeline is aborted
            from the <literal>PGRES_PIPELINE_ABORTED</literal> result code.
           </para>
@@ -5328,7 +5329,7 @@ int PQsendPipeline(PGconn *conn);
        Returns 1 for success. Returns 0 if the connection is not in
        pipeline mode or sending a
        <link linkend="protocol-flow-ext-query">sync message</link>
-       is failed.
+       failed.
       </para>
      </listitem>
     </varlistentry>
@@ -5349,7 +5350,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is most useful when the server is distant, i.e., network latency
     (<quote>ping time</quote>) is high, and also when many small operations
-    are being performed in rapid sequence.  There is usually less benefit
+    are being performed in rapid succession.  There is usually less benefit
     in using pipelined commands when each query takes many multiples of the client/server
     round-trip time to execute.  A 100-statement operation run on a server
     300ms round-trip-time away would take 30 seconds in network latency alone
@@ -5367,7 +5368,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is not useful when information from one operation is required by
     the client to produce the next operation. In such cases, the client
-    must introduce a synchronization point and wait for a full client/server
+    would have to introduce a synchronization point and wait for a full client/server
     round-trip to get the results it needs. However, it's often possible to
     adjust the client design to exchange the required information server-side.
     Read-modify-write cycles are especially good candidates; for example:
@@ -5392,10 +5393,10 @@ UPDATE mytable SET x = x + 1 WHERE id = 42;
 
    <note>
     <para>
-     The pipeline API was introduced in PostgreSQL 14, but clients using
-     the PostgreSQL 14 version of <application>libpq</application> can use
-     pipelines on server versions 7.4 and newer. Pipeline mode works on any server
-     that supports the v3 extended query protocol.
+     The pipeline API was introduced in <productname>PostgreSQL</productname> 14.
+     Pipeline mode is a client-side feature which doesn't require server
+     support, and works on any server that supports the v3 extended query
+     protocol.
     </para>
    </note>
   </sect2>
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index 7ae7c14948..d7b036a35c 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -3803,7 +3803,7 @@ pqPipelineFlush(PGconn *conn)
 {
 	if ((conn->pipelineStatus == PQ_PIPELINE_OFF) ||
 		(conn->outCount >= OUTBUFFER_THRESHOLD))
-		return (pqFlush(conn));
+		return pqFlush(conn);
 	return 0;
 }
 
diff --git a/src/test/modules/test_libpq/pipeline.c b/src/test/modules/test_libpq/pipeline.c
index f4a2bdec57..01d5a9a8ff 100644
--- a/src/test/modules/test_libpq/pipeline.c
+++ b/src/test/modules/test_libpq/pipeline.c
@@ -126,7 +126,7 @@ test_simple_pipeline(PGconn *conn)
 	 * process the results of as they come in.
 	 *
 	 * For a simple case we should be able to do this without interim
-	 * processing of results since our out buffer will give us enough slush to
+	 * processing of results since our output buffer will give us enough slush to
 	 * work with and we won't block on sending. So blocking mode is fine.
 	 */
 	if (PQisnonblocking(conn))
@@ -603,7 +603,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 
 	/*
 	 * Now we start inserting. We'll be sending enough data that we could fill
-	 * our out buffer, so to avoid deadlocking we need to enter nonblocking
+	 * our output buffer, so to avoid deadlocking we need to enter nonblocking
 	 * mode and consume input while we send more output. As results of each
 	 * query are processed we should pop them to allow processing of the next
 	 * query. There's no need to finish the pipeline before processing
@@ -635,7 +635,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 		}
 
 		/*
-		 * Process any results, so we keep the server's out buffer free
+		 * Process any results, so we keep the server's output buffer free
 		 * flowing and it can continue to process input
 		 */
 		if (FD_ISSET(sock, &input_mask))
-- 
2.17.0


--oC1+HKm2/end4ao3--





^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* [PATCH 2/2] doc review
@ 2021-03-03 22:36  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 29+ messages in thread

From: Justin Pryzby @ 2021-03-03 22:36 UTC (permalink / raw)

---
 doc/src/sgml/libpq.sgml                | 67 +++++++++++++-------------
 src/interfaces/libpq/fe-exec.c         |  2 +-
 src/test/modules/test_libpq/pipeline.c |  6 +--
 3 files changed, 38 insertions(+), 37 deletions(-)

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index a34ecbb144..e2865a218b 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -3130,8 +3130,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_SYNC</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a point in a
-            pipeline where a synchronization point has been established.
+            The <structname>PGresult</structname> represents a
+            synchronization point in pipeline mode, requested by 
+            <xref linkend="libpq-PQsendPipeline"/>.
             This status occurs only when pipeline mode has been selected.
            </para>
           </listitem>
@@ -3141,9 +3142,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_ABORTED</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a pipeline that's
+            The <structname>PGresult</structname> represents a pipeline that has
             received an error from the server.  <function>PQgetResult</function>
-            must be called repeatedly, and it will return this status code,
+            must be called repeatedly, and each time it will return this status code
             until the end of the current pipeline, at which point it will return
             <literal>PGRES_PIPELINE_SYNC</literal> and normal processing can
             resume.
@@ -4953,7 +4954,7 @@ int PQflush(PGconn *conn);
    <title>Using Pipeline Mode</title>
 
    <para>
-    To issue pipelines the application must switch a connection into pipeline mode.
+    To issue pipelines, the application must switch a connection into pipeline mode.
     Enter pipeline mode with <xref linkend="libpq-PQenterPipelineMode"/>
     or test whether pipeline mode is active with
     <xref linkend="libpq-PQpipelineStatus"/>.
@@ -4975,7 +4976,7 @@ int PQflush(PGconn *conn);
         server will block trying to send results to the client from queries
         it has already processed. This only occurs when the client sends
         enough queries to fill both its output buffer and the server's receive
-        buffer before switching to processing input from the server,
+        buffer before it switches to processing input from the server,
         but it's hard to predict exactly when that will happen.
        </para>
       </footnote>
@@ -5025,7 +5026,7 @@ int PQflush(PGconn *conn);
     <title>Processing Results</title>
 
     <para>
-     To process the result of one pipeline query, the application calls
+     To process the result of one query in a pipeline, the application calls
      <function>PQgetResult</function> repeatedly and handles each result
      until <function>PQgetResult</function> returns null.
      The result from the next query in the pipeline may then be retrieved using
@@ -5057,10 +5058,10 @@ int PQflush(PGconn *conn);
      <type>PGresult</type> types <literal>PGRES_PIPELINE_SYNC</literal>
      and <literal>PGRES_PIPELINE_ABORTED</literal>.
      <literal>PGRES_PIPELINE_SYNC</literal> is reported exactly once for each
-     <function>PQsendPipeline</function> call at the corresponding point in
-     the result stream.
+     <function>PQsendPipeline</function> after retrieving results for all
+     queries in the pipeline.
      <literal>PGRES_PIPELINE_ABORTED</literal> is emitted in place of a normal
-     result stream result for the first error and all subsequent results
+     stream result for the first error and all subsequent results
      except <literal>PGRES_PIPELINE_SYNC</literal> and null;
      see <xref linkend="libpq-pipeline-errors"/>.
     </para>
@@ -5075,7 +5076,8 @@ int PQflush(PGconn *conn);
      application about the query currently being processed (except that
      <function>PQgetResult</function> returns null to indicate that we start
      returning the results of next query). The application must keep track
-     of the order in which it sent queries and the expected results.
+     of the order in which it sent queries, to associate them with their
+     corresponding results.
      Applications will typically use a state machine or a FIFO queue for this.
     </para>
 
@@ -5091,10 +5093,10 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     From the client perspective, after the client gets a
-     <literal>PGRES_FATAL_ERROR</literal> return from
-     <function>PQresultStatus</function> the pipeline is flagged as aborted.
-     <application>libpq</application> will report
+     From the client perspective, after <function>PQresultStatus</function>
+     returns <literal>PGRES_FATAL_ERROR</literal>,
+     the pipeline is flagged as aborted.
+     <function>PQresultStatus</function>, will report a
      <literal>PGRES_PIPELINE_ABORTED</literal> result for each remaining queued
      operation in an aborted pipeline. The result for
      <function>PQsendPipeline</function> is reported as
@@ -5108,8 +5110,8 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     If the pipeline used an implicit transaction then operations that have
-     already executed are rolled back and operations that were queued for after
+     If the pipeline used an implicit transaction, then operations that have
+     already executed are rolled back and operations that were queued to follow
      the failed operation are skipped entirely. The same behaviour holds if the
      pipeline starts and commits a single explicit transaction (i.e. the first
      statement is <literal>BEGIN</literal> and the last is
@@ -5145,11 +5147,11 @@ int PQflush(PGconn *conn);
 
     <para>
      The client application should generally maintain a queue of work
-     still to be dispatched and a queue of work that has been dispatched
+     remaining to be dispatched and a queue of work that has been dispatched
      but not yet had its results processed. When the socket is writable
      it should dispatch more work. When the socket is readable it should
      read results and process them, matching them up to the next entry in
-     its expected results queue.  Based on available memory, results from
+     its expected results queue.  Based on available memory, results from the
      socket should be read frequently: there's no need to wait until the
      pipeline end to read the results.  Pipelines should be scoped to logical
      units of work, usually (but not necessarily) one transaction per pipeline.
@@ -5191,8 +5193,8 @@ int PQflush(PGconn *conn);
 
      <listitem>
       <para>
-      Returns current pipeline mode status of the <application>libpq</application>
-      connection.
+      Returns the current pipeline mode status of the
+      <application>libpq</application> connection.
 <synopsis>
 PGpipelineStatus PQpipelineStatus(const PGconn *conn);
 </synopsis>
@@ -5233,11 +5235,10 @@ PGpipelineStatus PQpipelineStatus(const PGconn *conn);
          <listitem>
           <para>
            The <application>libpq</application> connection is in pipeline
-           mode and an error has occurred while processing the current
-           pipeline.
-           The aborted flag is cleared as soon as the result
-           of the <function>PQsendPipeline</function> at the end of the aborted
-           pipeline is processed. Clients don't usually need this function to
+           mode and an error occurred while processing the current pipeline.
+           The aborted flag is cleared when <function>PQresultStatus</function>
+           returns PGRES_PIPELINE_SYNC at the end of the pipeline.
+           Clients don't usually need this function to
            verify aborted status, as they can tell that the pipeline is aborted
            from the <literal>PGRES_PIPELINE_ABORTED</literal> result code.
           </para>
@@ -5328,7 +5329,7 @@ int PQsendPipeline(PGconn *conn);
        Returns 1 for success. Returns 0 if the connection is not in
        pipeline mode or sending a
        <link linkend="protocol-flow-ext-query">sync message</link>
-       is failed.
+       failed.
       </para>
      </listitem>
     </varlistentry>
@@ -5349,7 +5350,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is most useful when the server is distant, i.e., network latency
     (<quote>ping time</quote>) is high, and also when many small operations
-    are being performed in rapid sequence.  There is usually less benefit
+    are being performed in rapid succession.  There is usually less benefit
     in using pipelined commands when each query takes many multiples of the client/server
     round-trip time to execute.  A 100-statement operation run on a server
     300ms round-trip-time away would take 30 seconds in network latency alone
@@ -5367,7 +5368,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is not useful when information from one operation is required by
     the client to produce the next operation. In such cases, the client
-    must introduce a synchronization point and wait for a full client/server
+    would have to introduce a synchronization point and wait for a full client/server
     round-trip to get the results it needs. However, it's often possible to
     adjust the client design to exchange the required information server-side.
     Read-modify-write cycles are especially good candidates; for example:
@@ -5392,10 +5393,10 @@ UPDATE mytable SET x = x + 1 WHERE id = 42;
 
    <note>
     <para>
-     The pipeline API was introduced in PostgreSQL 14, but clients using
-     the PostgreSQL 14 version of <application>libpq</application> can use
-     pipelines on server versions 7.4 and newer. Pipeline mode works on any server
-     that supports the v3 extended query protocol.
+     The pipeline API was introduced in <productname>PostgreSQL</productname> 14.
+     Pipeline mode is a client-side feature which doesn't require server
+     support, and works on any server that supports the v3 extended query
+     protocol.
     </para>
    </note>
   </sect2>
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index 7ae7c14948..d7b036a35c 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -3803,7 +3803,7 @@ pqPipelineFlush(PGconn *conn)
 {
 	if ((conn->pipelineStatus == PQ_PIPELINE_OFF) ||
 		(conn->outCount >= OUTBUFFER_THRESHOLD))
-		return (pqFlush(conn));
+		return pqFlush(conn);
 	return 0;
 }
 
diff --git a/src/test/modules/test_libpq/pipeline.c b/src/test/modules/test_libpq/pipeline.c
index f4a2bdec57..01d5a9a8ff 100644
--- a/src/test/modules/test_libpq/pipeline.c
+++ b/src/test/modules/test_libpq/pipeline.c
@@ -126,7 +126,7 @@ test_simple_pipeline(PGconn *conn)
 	 * process the results of as they come in.
 	 *
 	 * For a simple case we should be able to do this without interim
-	 * processing of results since our out buffer will give us enough slush to
+	 * processing of results since our output buffer will give us enough slush to
 	 * work with and we won't block on sending. So blocking mode is fine.
 	 */
 	if (PQisnonblocking(conn))
@@ -603,7 +603,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 
 	/*
 	 * Now we start inserting. We'll be sending enough data that we could fill
-	 * our out buffer, so to avoid deadlocking we need to enter nonblocking
+	 * our output buffer, so to avoid deadlocking we need to enter nonblocking
 	 * mode and consume input while we send more output. As results of each
 	 * query are processed we should pop them to allow processing of the next
 	 * query. There's no need to finish the pipeline before processing
@@ -635,7 +635,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 		}
 
 		/*
-		 * Process any results, so we keep the server's out buffer free
+		 * Process any results, so we keep the server's output buffer free
 		 * flowing and it can continue to process input
 		 */
 		if (FD_ISSET(sock, &input_mask))
-- 
2.17.0


--oC1+HKm2/end4ao3--





^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* [PATCH 2/2] doc review
@ 2021-03-03 22:36  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 29+ messages in thread

From: Justin Pryzby @ 2021-03-03 22:36 UTC (permalink / raw)

---
 doc/src/sgml/libpq.sgml                | 67 +++++++++++++-------------
 src/interfaces/libpq/fe-exec.c         |  2 +-
 src/test/modules/test_libpq/pipeline.c |  6 +--
 3 files changed, 38 insertions(+), 37 deletions(-)

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index a34ecbb144..e2865a218b 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -3130,8 +3130,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_SYNC</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a point in a
-            pipeline where a synchronization point has been established.
+            The <structname>PGresult</structname> represents a
+            synchronization point in pipeline mode, requested by 
+            <xref linkend="libpq-PQsendPipeline"/>.
             This status occurs only when pipeline mode has been selected.
            </para>
           </listitem>
@@ -3141,9 +3142,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_ABORTED</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a pipeline that's
+            The <structname>PGresult</structname> represents a pipeline that has
             received an error from the server.  <function>PQgetResult</function>
-            must be called repeatedly, and it will return this status code,
+            must be called repeatedly, and each time it will return this status code
             until the end of the current pipeline, at which point it will return
             <literal>PGRES_PIPELINE_SYNC</literal> and normal processing can
             resume.
@@ -4953,7 +4954,7 @@ int PQflush(PGconn *conn);
    <title>Using Pipeline Mode</title>
 
    <para>
-    To issue pipelines the application must switch a connection into pipeline mode.
+    To issue pipelines, the application must switch a connection into pipeline mode.
     Enter pipeline mode with <xref linkend="libpq-PQenterPipelineMode"/>
     or test whether pipeline mode is active with
     <xref linkend="libpq-PQpipelineStatus"/>.
@@ -4975,7 +4976,7 @@ int PQflush(PGconn *conn);
         server will block trying to send results to the client from queries
         it has already processed. This only occurs when the client sends
         enough queries to fill both its output buffer and the server's receive
-        buffer before switching to processing input from the server,
+        buffer before it switches to processing input from the server,
         but it's hard to predict exactly when that will happen.
        </para>
       </footnote>
@@ -5025,7 +5026,7 @@ int PQflush(PGconn *conn);
     <title>Processing Results</title>
 
     <para>
-     To process the result of one pipeline query, the application calls
+     To process the result of one query in a pipeline, the application calls
      <function>PQgetResult</function> repeatedly and handles each result
      until <function>PQgetResult</function> returns null.
      The result from the next query in the pipeline may then be retrieved using
@@ -5057,10 +5058,10 @@ int PQflush(PGconn *conn);
      <type>PGresult</type> types <literal>PGRES_PIPELINE_SYNC</literal>
      and <literal>PGRES_PIPELINE_ABORTED</literal>.
      <literal>PGRES_PIPELINE_SYNC</literal> is reported exactly once for each
-     <function>PQsendPipeline</function> call at the corresponding point in
-     the result stream.
+     <function>PQsendPipeline</function> after retrieving results for all
+     queries in the pipeline.
      <literal>PGRES_PIPELINE_ABORTED</literal> is emitted in place of a normal
-     result stream result for the first error and all subsequent results
+     stream result for the first error and all subsequent results
      except <literal>PGRES_PIPELINE_SYNC</literal> and null;
      see <xref linkend="libpq-pipeline-errors"/>.
     </para>
@@ -5075,7 +5076,8 @@ int PQflush(PGconn *conn);
      application about the query currently being processed (except that
      <function>PQgetResult</function> returns null to indicate that we start
      returning the results of next query). The application must keep track
-     of the order in which it sent queries and the expected results.
+     of the order in which it sent queries, to associate them with their
+     corresponding results.
      Applications will typically use a state machine or a FIFO queue for this.
     </para>
 
@@ -5091,10 +5093,10 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     From the client perspective, after the client gets a
-     <literal>PGRES_FATAL_ERROR</literal> return from
-     <function>PQresultStatus</function> the pipeline is flagged as aborted.
-     <application>libpq</application> will report
+     From the client perspective, after <function>PQresultStatus</function>
+     returns <literal>PGRES_FATAL_ERROR</literal>,
+     the pipeline is flagged as aborted.
+     <function>PQresultStatus</function>, will report a
      <literal>PGRES_PIPELINE_ABORTED</literal> result for each remaining queued
      operation in an aborted pipeline. The result for
      <function>PQsendPipeline</function> is reported as
@@ -5108,8 +5110,8 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     If the pipeline used an implicit transaction then operations that have
-     already executed are rolled back and operations that were queued for after
+     If the pipeline used an implicit transaction, then operations that have
+     already executed are rolled back and operations that were queued to follow
      the failed operation are skipped entirely. The same behaviour holds if the
      pipeline starts and commits a single explicit transaction (i.e. the first
      statement is <literal>BEGIN</literal> and the last is
@@ -5145,11 +5147,11 @@ int PQflush(PGconn *conn);
 
     <para>
      The client application should generally maintain a queue of work
-     still to be dispatched and a queue of work that has been dispatched
+     remaining to be dispatched and a queue of work that has been dispatched
      but not yet had its results processed. When the socket is writable
      it should dispatch more work. When the socket is readable it should
      read results and process them, matching them up to the next entry in
-     its expected results queue.  Based on available memory, results from
+     its expected results queue.  Based on available memory, results from the
      socket should be read frequently: there's no need to wait until the
      pipeline end to read the results.  Pipelines should be scoped to logical
      units of work, usually (but not necessarily) one transaction per pipeline.
@@ -5191,8 +5193,8 @@ int PQflush(PGconn *conn);
 
      <listitem>
       <para>
-      Returns current pipeline mode status of the <application>libpq</application>
-      connection.
+      Returns the current pipeline mode status of the
+      <application>libpq</application> connection.
 <synopsis>
 PGpipelineStatus PQpipelineStatus(const PGconn *conn);
 </synopsis>
@@ -5233,11 +5235,10 @@ PGpipelineStatus PQpipelineStatus(const PGconn *conn);
          <listitem>
           <para>
            The <application>libpq</application> connection is in pipeline
-           mode and an error has occurred while processing the current
-           pipeline.
-           The aborted flag is cleared as soon as the result
-           of the <function>PQsendPipeline</function> at the end of the aborted
-           pipeline is processed. Clients don't usually need this function to
+           mode and an error occurred while processing the current pipeline.
+           The aborted flag is cleared when <function>PQresultStatus</function>
+           returns PGRES_PIPELINE_SYNC at the end of the pipeline.
+           Clients don't usually need this function to
            verify aborted status, as they can tell that the pipeline is aborted
            from the <literal>PGRES_PIPELINE_ABORTED</literal> result code.
           </para>
@@ -5328,7 +5329,7 @@ int PQsendPipeline(PGconn *conn);
        Returns 1 for success. Returns 0 if the connection is not in
        pipeline mode or sending a
        <link linkend="protocol-flow-ext-query">sync message</link>
-       is failed.
+       failed.
       </para>
      </listitem>
     </varlistentry>
@@ -5349,7 +5350,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is most useful when the server is distant, i.e., network latency
     (<quote>ping time</quote>) is high, and also when many small operations
-    are being performed in rapid sequence.  There is usually less benefit
+    are being performed in rapid succession.  There is usually less benefit
     in using pipelined commands when each query takes many multiples of the client/server
     round-trip time to execute.  A 100-statement operation run on a server
     300ms round-trip-time away would take 30 seconds in network latency alone
@@ -5367,7 +5368,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is not useful when information from one operation is required by
     the client to produce the next operation. In such cases, the client
-    must introduce a synchronization point and wait for a full client/server
+    would have to introduce a synchronization point and wait for a full client/server
     round-trip to get the results it needs. However, it's often possible to
     adjust the client design to exchange the required information server-side.
     Read-modify-write cycles are especially good candidates; for example:
@@ -5392,10 +5393,10 @@ UPDATE mytable SET x = x + 1 WHERE id = 42;
 
    <note>
     <para>
-     The pipeline API was introduced in PostgreSQL 14, but clients using
-     the PostgreSQL 14 version of <application>libpq</application> can use
-     pipelines on server versions 7.4 and newer. Pipeline mode works on any server
-     that supports the v3 extended query protocol.
+     The pipeline API was introduced in <productname>PostgreSQL</productname> 14.
+     Pipeline mode is a client-side feature which doesn't require server
+     support, and works on any server that supports the v3 extended query
+     protocol.
     </para>
    </note>
   </sect2>
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index 7ae7c14948..d7b036a35c 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -3803,7 +3803,7 @@ pqPipelineFlush(PGconn *conn)
 {
 	if ((conn->pipelineStatus == PQ_PIPELINE_OFF) ||
 		(conn->outCount >= OUTBUFFER_THRESHOLD))
-		return (pqFlush(conn));
+		return pqFlush(conn);
 	return 0;
 }
 
diff --git a/src/test/modules/test_libpq/pipeline.c b/src/test/modules/test_libpq/pipeline.c
index f4a2bdec57..01d5a9a8ff 100644
--- a/src/test/modules/test_libpq/pipeline.c
+++ b/src/test/modules/test_libpq/pipeline.c
@@ -126,7 +126,7 @@ test_simple_pipeline(PGconn *conn)
 	 * process the results of as they come in.
 	 *
 	 * For a simple case we should be able to do this without interim
-	 * processing of results since our out buffer will give us enough slush to
+	 * processing of results since our output buffer will give us enough slush to
 	 * work with and we won't block on sending. So blocking mode is fine.
 	 */
 	if (PQisnonblocking(conn))
@@ -603,7 +603,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 
 	/*
 	 * Now we start inserting. We'll be sending enough data that we could fill
-	 * our out buffer, so to avoid deadlocking we need to enter nonblocking
+	 * our output buffer, so to avoid deadlocking we need to enter nonblocking
 	 * mode and consume input while we send more output. As results of each
 	 * query are processed we should pop them to allow processing of the next
 	 * query. There's no need to finish the pipeline before processing
@@ -635,7 +635,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 		}
 
 		/*
-		 * Process any results, so we keep the server's out buffer free
+		 * Process any results, so we keep the server's output buffer free
 		 * flowing and it can continue to process input
 		 */
 		if (FD_ISSET(sock, &input_mask))
-- 
2.17.0


--oC1+HKm2/end4ao3--





^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* [PATCH 2/2] doc review
@ 2021-03-03 22:36  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 29+ messages in thread

From: Justin Pryzby @ 2021-03-03 22:36 UTC (permalink / raw)

---
 doc/src/sgml/libpq.sgml                | 67 +++++++++++++-------------
 src/interfaces/libpq/fe-exec.c         |  2 +-
 src/test/modules/test_libpq/pipeline.c |  6 +--
 3 files changed, 38 insertions(+), 37 deletions(-)

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index a34ecbb144..e2865a218b 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -3130,8 +3130,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_SYNC</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a point in a
-            pipeline where a synchronization point has been established.
+            The <structname>PGresult</structname> represents a
+            synchronization point in pipeline mode, requested by 
+            <xref linkend="libpq-PQsendPipeline"/>.
             This status occurs only when pipeline mode has been selected.
            </para>
           </listitem>
@@ -3141,9 +3142,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_ABORTED</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a pipeline that's
+            The <structname>PGresult</structname> represents a pipeline that has
             received an error from the server.  <function>PQgetResult</function>
-            must be called repeatedly, and it will return this status code,
+            must be called repeatedly, and each time it will return this status code
             until the end of the current pipeline, at which point it will return
             <literal>PGRES_PIPELINE_SYNC</literal> and normal processing can
             resume.
@@ -4953,7 +4954,7 @@ int PQflush(PGconn *conn);
    <title>Using Pipeline Mode</title>
 
    <para>
-    To issue pipelines the application must switch a connection into pipeline mode.
+    To issue pipelines, the application must switch a connection into pipeline mode.
     Enter pipeline mode with <xref linkend="libpq-PQenterPipelineMode"/>
     or test whether pipeline mode is active with
     <xref linkend="libpq-PQpipelineStatus"/>.
@@ -4975,7 +4976,7 @@ int PQflush(PGconn *conn);
         server will block trying to send results to the client from queries
         it has already processed. This only occurs when the client sends
         enough queries to fill both its output buffer and the server's receive
-        buffer before switching to processing input from the server,
+        buffer before it switches to processing input from the server,
         but it's hard to predict exactly when that will happen.
        </para>
       </footnote>
@@ -5025,7 +5026,7 @@ int PQflush(PGconn *conn);
     <title>Processing Results</title>
 
     <para>
-     To process the result of one pipeline query, the application calls
+     To process the result of one query in a pipeline, the application calls
      <function>PQgetResult</function> repeatedly and handles each result
      until <function>PQgetResult</function> returns null.
      The result from the next query in the pipeline may then be retrieved using
@@ -5057,10 +5058,10 @@ int PQflush(PGconn *conn);
      <type>PGresult</type> types <literal>PGRES_PIPELINE_SYNC</literal>
      and <literal>PGRES_PIPELINE_ABORTED</literal>.
      <literal>PGRES_PIPELINE_SYNC</literal> is reported exactly once for each
-     <function>PQsendPipeline</function> call at the corresponding point in
-     the result stream.
+     <function>PQsendPipeline</function> after retrieving results for all
+     queries in the pipeline.
      <literal>PGRES_PIPELINE_ABORTED</literal> is emitted in place of a normal
-     result stream result for the first error and all subsequent results
+     stream result for the first error and all subsequent results
      except <literal>PGRES_PIPELINE_SYNC</literal> and null;
      see <xref linkend="libpq-pipeline-errors"/>.
     </para>
@@ -5075,7 +5076,8 @@ int PQflush(PGconn *conn);
      application about the query currently being processed (except that
      <function>PQgetResult</function> returns null to indicate that we start
      returning the results of next query). The application must keep track
-     of the order in which it sent queries and the expected results.
+     of the order in which it sent queries, to associate them with their
+     corresponding results.
      Applications will typically use a state machine or a FIFO queue for this.
     </para>
 
@@ -5091,10 +5093,10 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     From the client perspective, after the client gets a
-     <literal>PGRES_FATAL_ERROR</literal> return from
-     <function>PQresultStatus</function> the pipeline is flagged as aborted.
-     <application>libpq</application> will report
+     From the client perspective, after <function>PQresultStatus</function>
+     returns <literal>PGRES_FATAL_ERROR</literal>,
+     the pipeline is flagged as aborted.
+     <function>PQresultStatus</function>, will report a
      <literal>PGRES_PIPELINE_ABORTED</literal> result for each remaining queued
      operation in an aborted pipeline. The result for
      <function>PQsendPipeline</function> is reported as
@@ -5108,8 +5110,8 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     If the pipeline used an implicit transaction then operations that have
-     already executed are rolled back and operations that were queued for after
+     If the pipeline used an implicit transaction, then operations that have
+     already executed are rolled back and operations that were queued to follow
      the failed operation are skipped entirely. The same behaviour holds if the
      pipeline starts and commits a single explicit transaction (i.e. the first
      statement is <literal>BEGIN</literal> and the last is
@@ -5145,11 +5147,11 @@ int PQflush(PGconn *conn);
 
     <para>
      The client application should generally maintain a queue of work
-     still to be dispatched and a queue of work that has been dispatched
+     remaining to be dispatched and a queue of work that has been dispatched
      but not yet had its results processed. When the socket is writable
      it should dispatch more work. When the socket is readable it should
      read results and process them, matching them up to the next entry in
-     its expected results queue.  Based on available memory, results from
+     its expected results queue.  Based on available memory, results from the
      socket should be read frequently: there's no need to wait until the
      pipeline end to read the results.  Pipelines should be scoped to logical
      units of work, usually (but not necessarily) one transaction per pipeline.
@@ -5191,8 +5193,8 @@ int PQflush(PGconn *conn);
 
      <listitem>
       <para>
-      Returns current pipeline mode status of the <application>libpq</application>
-      connection.
+      Returns the current pipeline mode status of the
+      <application>libpq</application> connection.
 <synopsis>
 PGpipelineStatus PQpipelineStatus(const PGconn *conn);
 </synopsis>
@@ -5233,11 +5235,10 @@ PGpipelineStatus PQpipelineStatus(const PGconn *conn);
          <listitem>
           <para>
            The <application>libpq</application> connection is in pipeline
-           mode and an error has occurred while processing the current
-           pipeline.
-           The aborted flag is cleared as soon as the result
-           of the <function>PQsendPipeline</function> at the end of the aborted
-           pipeline is processed. Clients don't usually need this function to
+           mode and an error occurred while processing the current pipeline.
+           The aborted flag is cleared when <function>PQresultStatus</function>
+           returns PGRES_PIPELINE_SYNC at the end of the pipeline.
+           Clients don't usually need this function to
            verify aborted status, as they can tell that the pipeline is aborted
            from the <literal>PGRES_PIPELINE_ABORTED</literal> result code.
           </para>
@@ -5328,7 +5329,7 @@ int PQsendPipeline(PGconn *conn);
        Returns 1 for success. Returns 0 if the connection is not in
        pipeline mode or sending a
        <link linkend="protocol-flow-ext-query">sync message</link>
-       is failed.
+       failed.
       </para>
      </listitem>
     </varlistentry>
@@ -5349,7 +5350,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is most useful when the server is distant, i.e., network latency
     (<quote>ping time</quote>) is high, and also when many small operations
-    are being performed in rapid sequence.  There is usually less benefit
+    are being performed in rapid succession.  There is usually less benefit
     in using pipelined commands when each query takes many multiples of the client/server
     round-trip time to execute.  A 100-statement operation run on a server
     300ms round-trip-time away would take 30 seconds in network latency alone
@@ -5367,7 +5368,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is not useful when information from one operation is required by
     the client to produce the next operation. In such cases, the client
-    must introduce a synchronization point and wait for a full client/server
+    would have to introduce a synchronization point and wait for a full client/server
     round-trip to get the results it needs. However, it's often possible to
     adjust the client design to exchange the required information server-side.
     Read-modify-write cycles are especially good candidates; for example:
@@ -5392,10 +5393,10 @@ UPDATE mytable SET x = x + 1 WHERE id = 42;
 
    <note>
     <para>
-     The pipeline API was introduced in PostgreSQL 14, but clients using
-     the PostgreSQL 14 version of <application>libpq</application> can use
-     pipelines on server versions 7.4 and newer. Pipeline mode works on any server
-     that supports the v3 extended query protocol.
+     The pipeline API was introduced in <productname>PostgreSQL</productname> 14.
+     Pipeline mode is a client-side feature which doesn't require server
+     support, and works on any server that supports the v3 extended query
+     protocol.
     </para>
    </note>
   </sect2>
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index 7ae7c14948..d7b036a35c 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -3803,7 +3803,7 @@ pqPipelineFlush(PGconn *conn)
 {
 	if ((conn->pipelineStatus == PQ_PIPELINE_OFF) ||
 		(conn->outCount >= OUTBUFFER_THRESHOLD))
-		return (pqFlush(conn));
+		return pqFlush(conn);
 	return 0;
 }
 
diff --git a/src/test/modules/test_libpq/pipeline.c b/src/test/modules/test_libpq/pipeline.c
index f4a2bdec57..01d5a9a8ff 100644
--- a/src/test/modules/test_libpq/pipeline.c
+++ b/src/test/modules/test_libpq/pipeline.c
@@ -126,7 +126,7 @@ test_simple_pipeline(PGconn *conn)
 	 * process the results of as they come in.
 	 *
 	 * For a simple case we should be able to do this without interim
-	 * processing of results since our out buffer will give us enough slush to
+	 * processing of results since our output buffer will give us enough slush to
 	 * work with and we won't block on sending. So blocking mode is fine.
 	 */
 	if (PQisnonblocking(conn))
@@ -603,7 +603,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 
 	/*
 	 * Now we start inserting. We'll be sending enough data that we could fill
-	 * our out buffer, so to avoid deadlocking we need to enter nonblocking
+	 * our output buffer, so to avoid deadlocking we need to enter nonblocking
 	 * mode and consume input while we send more output. As results of each
 	 * query are processed we should pop them to allow processing of the next
 	 * query. There's no need to finish the pipeline before processing
@@ -635,7 +635,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 		}
 
 		/*
-		 * Process any results, so we keep the server's out buffer free
+		 * Process any results, so we keep the server's output buffer free
 		 * flowing and it can continue to process input
 		 */
 		if (FD_ISSET(sock, &input_mask))
-- 
2.17.0


--oC1+HKm2/end4ao3--





^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* [PATCH 2/2] doc review
@ 2021-03-03 22:36  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 29+ messages in thread

From: Justin Pryzby @ 2021-03-03 22:36 UTC (permalink / raw)

---
 doc/src/sgml/libpq.sgml                | 67 +++++++++++++-------------
 src/interfaces/libpq/fe-exec.c         |  2 +-
 src/test/modules/test_libpq/pipeline.c |  6 +--
 3 files changed, 38 insertions(+), 37 deletions(-)

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index a34ecbb144..e2865a218b 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -3130,8 +3130,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_SYNC</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a point in a
-            pipeline where a synchronization point has been established.
+            The <structname>PGresult</structname> represents a
+            synchronization point in pipeline mode, requested by 
+            <xref linkend="libpq-PQsendPipeline"/>.
             This status occurs only when pipeline mode has been selected.
            </para>
           </listitem>
@@ -3141,9 +3142,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_ABORTED</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a pipeline that's
+            The <structname>PGresult</structname> represents a pipeline that has
             received an error from the server.  <function>PQgetResult</function>
-            must be called repeatedly, and it will return this status code,
+            must be called repeatedly, and each time it will return this status code
             until the end of the current pipeline, at which point it will return
             <literal>PGRES_PIPELINE_SYNC</literal> and normal processing can
             resume.
@@ -4953,7 +4954,7 @@ int PQflush(PGconn *conn);
    <title>Using Pipeline Mode</title>
 
    <para>
-    To issue pipelines the application must switch a connection into pipeline mode.
+    To issue pipelines, the application must switch a connection into pipeline mode.
     Enter pipeline mode with <xref linkend="libpq-PQenterPipelineMode"/>
     or test whether pipeline mode is active with
     <xref linkend="libpq-PQpipelineStatus"/>.
@@ -4975,7 +4976,7 @@ int PQflush(PGconn *conn);
         server will block trying to send results to the client from queries
         it has already processed. This only occurs when the client sends
         enough queries to fill both its output buffer and the server's receive
-        buffer before switching to processing input from the server,
+        buffer before it switches to processing input from the server,
         but it's hard to predict exactly when that will happen.
        </para>
       </footnote>
@@ -5025,7 +5026,7 @@ int PQflush(PGconn *conn);
     <title>Processing Results</title>
 
     <para>
-     To process the result of one pipeline query, the application calls
+     To process the result of one query in a pipeline, the application calls
      <function>PQgetResult</function> repeatedly and handles each result
      until <function>PQgetResult</function> returns null.
      The result from the next query in the pipeline may then be retrieved using
@@ -5057,10 +5058,10 @@ int PQflush(PGconn *conn);
      <type>PGresult</type> types <literal>PGRES_PIPELINE_SYNC</literal>
      and <literal>PGRES_PIPELINE_ABORTED</literal>.
      <literal>PGRES_PIPELINE_SYNC</literal> is reported exactly once for each
-     <function>PQsendPipeline</function> call at the corresponding point in
-     the result stream.
+     <function>PQsendPipeline</function> after retrieving results for all
+     queries in the pipeline.
      <literal>PGRES_PIPELINE_ABORTED</literal> is emitted in place of a normal
-     result stream result for the first error and all subsequent results
+     stream result for the first error and all subsequent results
      except <literal>PGRES_PIPELINE_SYNC</literal> and null;
      see <xref linkend="libpq-pipeline-errors"/>.
     </para>
@@ -5075,7 +5076,8 @@ int PQflush(PGconn *conn);
      application about the query currently being processed (except that
      <function>PQgetResult</function> returns null to indicate that we start
      returning the results of next query). The application must keep track
-     of the order in which it sent queries and the expected results.
+     of the order in which it sent queries, to associate them with their
+     corresponding results.
      Applications will typically use a state machine or a FIFO queue for this.
     </para>
 
@@ -5091,10 +5093,10 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     From the client perspective, after the client gets a
-     <literal>PGRES_FATAL_ERROR</literal> return from
-     <function>PQresultStatus</function> the pipeline is flagged as aborted.
-     <application>libpq</application> will report
+     From the client perspective, after <function>PQresultStatus</function>
+     returns <literal>PGRES_FATAL_ERROR</literal>,
+     the pipeline is flagged as aborted.
+     <function>PQresultStatus</function>, will report a
      <literal>PGRES_PIPELINE_ABORTED</literal> result for each remaining queued
      operation in an aborted pipeline. The result for
      <function>PQsendPipeline</function> is reported as
@@ -5108,8 +5110,8 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     If the pipeline used an implicit transaction then operations that have
-     already executed are rolled back and operations that were queued for after
+     If the pipeline used an implicit transaction, then operations that have
+     already executed are rolled back and operations that were queued to follow
      the failed operation are skipped entirely. The same behaviour holds if the
      pipeline starts and commits a single explicit transaction (i.e. the first
      statement is <literal>BEGIN</literal> and the last is
@@ -5145,11 +5147,11 @@ int PQflush(PGconn *conn);
 
     <para>
      The client application should generally maintain a queue of work
-     still to be dispatched and a queue of work that has been dispatched
+     remaining to be dispatched and a queue of work that has been dispatched
      but not yet had its results processed. When the socket is writable
      it should dispatch more work. When the socket is readable it should
      read results and process them, matching them up to the next entry in
-     its expected results queue.  Based on available memory, results from
+     its expected results queue.  Based on available memory, results from the
      socket should be read frequently: there's no need to wait until the
      pipeline end to read the results.  Pipelines should be scoped to logical
      units of work, usually (but not necessarily) one transaction per pipeline.
@@ -5191,8 +5193,8 @@ int PQflush(PGconn *conn);
 
      <listitem>
       <para>
-      Returns current pipeline mode status of the <application>libpq</application>
-      connection.
+      Returns the current pipeline mode status of the
+      <application>libpq</application> connection.
 <synopsis>
 PGpipelineStatus PQpipelineStatus(const PGconn *conn);
 </synopsis>
@@ -5233,11 +5235,10 @@ PGpipelineStatus PQpipelineStatus(const PGconn *conn);
          <listitem>
           <para>
            The <application>libpq</application> connection is in pipeline
-           mode and an error has occurred while processing the current
-           pipeline.
-           The aborted flag is cleared as soon as the result
-           of the <function>PQsendPipeline</function> at the end of the aborted
-           pipeline is processed. Clients don't usually need this function to
+           mode and an error occurred while processing the current pipeline.
+           The aborted flag is cleared when <function>PQresultStatus</function>
+           returns PGRES_PIPELINE_SYNC at the end of the pipeline.
+           Clients don't usually need this function to
            verify aborted status, as they can tell that the pipeline is aborted
            from the <literal>PGRES_PIPELINE_ABORTED</literal> result code.
           </para>
@@ -5328,7 +5329,7 @@ int PQsendPipeline(PGconn *conn);
        Returns 1 for success. Returns 0 if the connection is not in
        pipeline mode or sending a
        <link linkend="protocol-flow-ext-query">sync message</link>
-       is failed.
+       failed.
       </para>
      </listitem>
     </varlistentry>
@@ -5349,7 +5350,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is most useful when the server is distant, i.e., network latency
     (<quote>ping time</quote>) is high, and also when many small operations
-    are being performed in rapid sequence.  There is usually less benefit
+    are being performed in rapid succession.  There is usually less benefit
     in using pipelined commands when each query takes many multiples of the client/server
     round-trip time to execute.  A 100-statement operation run on a server
     300ms round-trip-time away would take 30 seconds in network latency alone
@@ -5367,7 +5368,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is not useful when information from one operation is required by
     the client to produce the next operation. In such cases, the client
-    must introduce a synchronization point and wait for a full client/server
+    would have to introduce a synchronization point and wait for a full client/server
     round-trip to get the results it needs. However, it's often possible to
     adjust the client design to exchange the required information server-side.
     Read-modify-write cycles are especially good candidates; for example:
@@ -5392,10 +5393,10 @@ UPDATE mytable SET x = x + 1 WHERE id = 42;
 
    <note>
     <para>
-     The pipeline API was introduced in PostgreSQL 14, but clients using
-     the PostgreSQL 14 version of <application>libpq</application> can use
-     pipelines on server versions 7.4 and newer. Pipeline mode works on any server
-     that supports the v3 extended query protocol.
+     The pipeline API was introduced in <productname>PostgreSQL</productname> 14.
+     Pipeline mode is a client-side feature which doesn't require server
+     support, and works on any server that supports the v3 extended query
+     protocol.
     </para>
    </note>
   </sect2>
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index 7ae7c14948..d7b036a35c 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -3803,7 +3803,7 @@ pqPipelineFlush(PGconn *conn)
 {
 	if ((conn->pipelineStatus == PQ_PIPELINE_OFF) ||
 		(conn->outCount >= OUTBUFFER_THRESHOLD))
-		return (pqFlush(conn));
+		return pqFlush(conn);
 	return 0;
 }
 
diff --git a/src/test/modules/test_libpq/pipeline.c b/src/test/modules/test_libpq/pipeline.c
index f4a2bdec57..01d5a9a8ff 100644
--- a/src/test/modules/test_libpq/pipeline.c
+++ b/src/test/modules/test_libpq/pipeline.c
@@ -126,7 +126,7 @@ test_simple_pipeline(PGconn *conn)
 	 * process the results of as they come in.
 	 *
 	 * For a simple case we should be able to do this without interim
-	 * processing of results since our out buffer will give us enough slush to
+	 * processing of results since our output buffer will give us enough slush to
 	 * work with and we won't block on sending. So blocking mode is fine.
 	 */
 	if (PQisnonblocking(conn))
@@ -603,7 +603,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 
 	/*
 	 * Now we start inserting. We'll be sending enough data that we could fill
-	 * our out buffer, so to avoid deadlocking we need to enter nonblocking
+	 * our output buffer, so to avoid deadlocking we need to enter nonblocking
 	 * mode and consume input while we send more output. As results of each
 	 * query are processed we should pop them to allow processing of the next
 	 * query. There's no need to finish the pipeline before processing
@@ -635,7 +635,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 		}
 
 		/*
-		 * Process any results, so we keep the server's out buffer free
+		 * Process any results, so we keep the server's output buffer free
 		 * flowing and it can continue to process input
 		 */
 		if (FD_ISSET(sock, &input_mask))
-- 
2.17.0


--oC1+HKm2/end4ao3--





^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* [PATCH 2/2] doc review
@ 2021-03-03 22:36  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 29+ messages in thread

From: Justin Pryzby @ 2021-03-03 22:36 UTC (permalink / raw)

---
 doc/src/sgml/libpq.sgml                | 67 +++++++++++++-------------
 src/interfaces/libpq/fe-exec.c         |  2 +-
 src/test/modules/test_libpq/pipeline.c |  6 +--
 3 files changed, 38 insertions(+), 37 deletions(-)

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index a34ecbb144..e2865a218b 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -3130,8 +3130,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_SYNC</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a point in a
-            pipeline where a synchronization point has been established.
+            The <structname>PGresult</structname> represents a
+            synchronization point in pipeline mode, requested by 
+            <xref linkend="libpq-PQsendPipeline"/>.
             This status occurs only when pipeline mode has been selected.
            </para>
           </listitem>
@@ -3141,9 +3142,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_ABORTED</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a pipeline that's
+            The <structname>PGresult</structname> represents a pipeline that has
             received an error from the server.  <function>PQgetResult</function>
-            must be called repeatedly, and it will return this status code,
+            must be called repeatedly, and each time it will return this status code
             until the end of the current pipeline, at which point it will return
             <literal>PGRES_PIPELINE_SYNC</literal> and normal processing can
             resume.
@@ -4953,7 +4954,7 @@ int PQflush(PGconn *conn);
    <title>Using Pipeline Mode</title>
 
    <para>
-    To issue pipelines the application must switch a connection into pipeline mode.
+    To issue pipelines, the application must switch a connection into pipeline mode.
     Enter pipeline mode with <xref linkend="libpq-PQenterPipelineMode"/>
     or test whether pipeline mode is active with
     <xref linkend="libpq-PQpipelineStatus"/>.
@@ -4975,7 +4976,7 @@ int PQflush(PGconn *conn);
         server will block trying to send results to the client from queries
         it has already processed. This only occurs when the client sends
         enough queries to fill both its output buffer and the server's receive
-        buffer before switching to processing input from the server,
+        buffer before it switches to processing input from the server,
         but it's hard to predict exactly when that will happen.
        </para>
       </footnote>
@@ -5025,7 +5026,7 @@ int PQflush(PGconn *conn);
     <title>Processing Results</title>
 
     <para>
-     To process the result of one pipeline query, the application calls
+     To process the result of one query in a pipeline, the application calls
      <function>PQgetResult</function> repeatedly and handles each result
      until <function>PQgetResult</function> returns null.
      The result from the next query in the pipeline may then be retrieved using
@@ -5057,10 +5058,10 @@ int PQflush(PGconn *conn);
      <type>PGresult</type> types <literal>PGRES_PIPELINE_SYNC</literal>
      and <literal>PGRES_PIPELINE_ABORTED</literal>.
      <literal>PGRES_PIPELINE_SYNC</literal> is reported exactly once for each
-     <function>PQsendPipeline</function> call at the corresponding point in
-     the result stream.
+     <function>PQsendPipeline</function> after retrieving results for all
+     queries in the pipeline.
      <literal>PGRES_PIPELINE_ABORTED</literal> is emitted in place of a normal
-     result stream result for the first error and all subsequent results
+     stream result for the first error and all subsequent results
      except <literal>PGRES_PIPELINE_SYNC</literal> and null;
      see <xref linkend="libpq-pipeline-errors"/>.
     </para>
@@ -5075,7 +5076,8 @@ int PQflush(PGconn *conn);
      application about the query currently being processed (except that
      <function>PQgetResult</function> returns null to indicate that we start
      returning the results of next query). The application must keep track
-     of the order in which it sent queries and the expected results.
+     of the order in which it sent queries, to associate them with their
+     corresponding results.
      Applications will typically use a state machine or a FIFO queue for this.
     </para>
 
@@ -5091,10 +5093,10 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     From the client perspective, after the client gets a
-     <literal>PGRES_FATAL_ERROR</literal> return from
-     <function>PQresultStatus</function> the pipeline is flagged as aborted.
-     <application>libpq</application> will report
+     From the client perspective, after <function>PQresultStatus</function>
+     returns <literal>PGRES_FATAL_ERROR</literal>,
+     the pipeline is flagged as aborted.
+     <function>PQresultStatus</function>, will report a
      <literal>PGRES_PIPELINE_ABORTED</literal> result for each remaining queued
      operation in an aborted pipeline. The result for
      <function>PQsendPipeline</function> is reported as
@@ -5108,8 +5110,8 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     If the pipeline used an implicit transaction then operations that have
-     already executed are rolled back and operations that were queued for after
+     If the pipeline used an implicit transaction, then operations that have
+     already executed are rolled back and operations that were queued to follow
      the failed operation are skipped entirely. The same behaviour holds if the
      pipeline starts and commits a single explicit transaction (i.e. the first
      statement is <literal>BEGIN</literal> and the last is
@@ -5145,11 +5147,11 @@ int PQflush(PGconn *conn);
 
     <para>
      The client application should generally maintain a queue of work
-     still to be dispatched and a queue of work that has been dispatched
+     remaining to be dispatched and a queue of work that has been dispatched
      but not yet had its results processed. When the socket is writable
      it should dispatch more work. When the socket is readable it should
      read results and process them, matching them up to the next entry in
-     its expected results queue.  Based on available memory, results from
+     its expected results queue.  Based on available memory, results from the
      socket should be read frequently: there's no need to wait until the
      pipeline end to read the results.  Pipelines should be scoped to logical
      units of work, usually (but not necessarily) one transaction per pipeline.
@@ -5191,8 +5193,8 @@ int PQflush(PGconn *conn);
 
      <listitem>
       <para>
-      Returns current pipeline mode status of the <application>libpq</application>
-      connection.
+      Returns the current pipeline mode status of the
+      <application>libpq</application> connection.
 <synopsis>
 PGpipelineStatus PQpipelineStatus(const PGconn *conn);
 </synopsis>
@@ -5233,11 +5235,10 @@ PGpipelineStatus PQpipelineStatus(const PGconn *conn);
          <listitem>
           <para>
            The <application>libpq</application> connection is in pipeline
-           mode and an error has occurred while processing the current
-           pipeline.
-           The aborted flag is cleared as soon as the result
-           of the <function>PQsendPipeline</function> at the end of the aborted
-           pipeline is processed. Clients don't usually need this function to
+           mode and an error occurred while processing the current pipeline.
+           The aborted flag is cleared when <function>PQresultStatus</function>
+           returns PGRES_PIPELINE_SYNC at the end of the pipeline.
+           Clients don't usually need this function to
            verify aborted status, as they can tell that the pipeline is aborted
            from the <literal>PGRES_PIPELINE_ABORTED</literal> result code.
           </para>
@@ -5328,7 +5329,7 @@ int PQsendPipeline(PGconn *conn);
        Returns 1 for success. Returns 0 if the connection is not in
        pipeline mode or sending a
        <link linkend="protocol-flow-ext-query">sync message</link>
-       is failed.
+       failed.
       </para>
      </listitem>
     </varlistentry>
@@ -5349,7 +5350,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is most useful when the server is distant, i.e., network latency
     (<quote>ping time</quote>) is high, and also when many small operations
-    are being performed in rapid sequence.  There is usually less benefit
+    are being performed in rapid succession.  There is usually less benefit
     in using pipelined commands when each query takes many multiples of the client/server
     round-trip time to execute.  A 100-statement operation run on a server
     300ms round-trip-time away would take 30 seconds in network latency alone
@@ -5367,7 +5368,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is not useful when information from one operation is required by
     the client to produce the next operation. In such cases, the client
-    must introduce a synchronization point and wait for a full client/server
+    would have to introduce a synchronization point and wait for a full client/server
     round-trip to get the results it needs. However, it's often possible to
     adjust the client design to exchange the required information server-side.
     Read-modify-write cycles are especially good candidates; for example:
@@ -5392,10 +5393,10 @@ UPDATE mytable SET x = x + 1 WHERE id = 42;
 
    <note>
     <para>
-     The pipeline API was introduced in PostgreSQL 14, but clients using
-     the PostgreSQL 14 version of <application>libpq</application> can use
-     pipelines on server versions 7.4 and newer. Pipeline mode works on any server
-     that supports the v3 extended query protocol.
+     The pipeline API was introduced in <productname>PostgreSQL</productname> 14.
+     Pipeline mode is a client-side feature which doesn't require server
+     support, and works on any server that supports the v3 extended query
+     protocol.
     </para>
    </note>
   </sect2>
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index 7ae7c14948..d7b036a35c 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -3803,7 +3803,7 @@ pqPipelineFlush(PGconn *conn)
 {
 	if ((conn->pipelineStatus == PQ_PIPELINE_OFF) ||
 		(conn->outCount >= OUTBUFFER_THRESHOLD))
-		return (pqFlush(conn));
+		return pqFlush(conn);
 	return 0;
 }
 
diff --git a/src/test/modules/test_libpq/pipeline.c b/src/test/modules/test_libpq/pipeline.c
index f4a2bdec57..01d5a9a8ff 100644
--- a/src/test/modules/test_libpq/pipeline.c
+++ b/src/test/modules/test_libpq/pipeline.c
@@ -126,7 +126,7 @@ test_simple_pipeline(PGconn *conn)
 	 * process the results of as they come in.
 	 *
 	 * For a simple case we should be able to do this without interim
-	 * processing of results since our out buffer will give us enough slush to
+	 * processing of results since our output buffer will give us enough slush to
 	 * work with and we won't block on sending. So blocking mode is fine.
 	 */
 	if (PQisnonblocking(conn))
@@ -603,7 +603,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 
 	/*
 	 * Now we start inserting. We'll be sending enough data that we could fill
-	 * our out buffer, so to avoid deadlocking we need to enter nonblocking
+	 * our output buffer, so to avoid deadlocking we need to enter nonblocking
 	 * mode and consume input while we send more output. As results of each
 	 * query are processed we should pop them to allow processing of the next
 	 * query. There's no need to finish the pipeline before processing
@@ -635,7 +635,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 		}
 
 		/*
-		 * Process any results, so we keep the server's out buffer free
+		 * Process any results, so we keep the server's output buffer free
 		 * flowing and it can continue to process input
 		 */
 		if (FD_ISSET(sock, &input_mask))
-- 
2.17.0


--oC1+HKm2/end4ao3--





^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* [PATCH 2/2] doc review
@ 2021-03-03 22:36  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 29+ messages in thread

From: Justin Pryzby @ 2021-03-03 22:36 UTC (permalink / raw)

---
 doc/src/sgml/libpq.sgml                | 67 +++++++++++++-------------
 src/interfaces/libpq/fe-exec.c         |  2 +-
 src/test/modules/test_libpq/pipeline.c |  6 +--
 3 files changed, 38 insertions(+), 37 deletions(-)

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index a34ecbb144..e2865a218b 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -3130,8 +3130,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_SYNC</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a point in a
-            pipeline where a synchronization point has been established.
+            The <structname>PGresult</structname> represents a
+            synchronization point in pipeline mode, requested by 
+            <xref linkend="libpq-PQsendPipeline"/>.
             This status occurs only when pipeline mode has been selected.
            </para>
           </listitem>
@@ -3141,9 +3142,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_ABORTED</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a pipeline that's
+            The <structname>PGresult</structname> represents a pipeline that has
             received an error from the server.  <function>PQgetResult</function>
-            must be called repeatedly, and it will return this status code,
+            must be called repeatedly, and each time it will return this status code
             until the end of the current pipeline, at which point it will return
             <literal>PGRES_PIPELINE_SYNC</literal> and normal processing can
             resume.
@@ -4953,7 +4954,7 @@ int PQflush(PGconn *conn);
    <title>Using Pipeline Mode</title>
 
    <para>
-    To issue pipelines the application must switch a connection into pipeline mode.
+    To issue pipelines, the application must switch a connection into pipeline mode.
     Enter pipeline mode with <xref linkend="libpq-PQenterPipelineMode"/>
     or test whether pipeline mode is active with
     <xref linkend="libpq-PQpipelineStatus"/>.
@@ -4975,7 +4976,7 @@ int PQflush(PGconn *conn);
         server will block trying to send results to the client from queries
         it has already processed. This only occurs when the client sends
         enough queries to fill both its output buffer and the server's receive
-        buffer before switching to processing input from the server,
+        buffer before it switches to processing input from the server,
         but it's hard to predict exactly when that will happen.
        </para>
       </footnote>
@@ -5025,7 +5026,7 @@ int PQflush(PGconn *conn);
     <title>Processing Results</title>
 
     <para>
-     To process the result of one pipeline query, the application calls
+     To process the result of one query in a pipeline, the application calls
      <function>PQgetResult</function> repeatedly and handles each result
      until <function>PQgetResult</function> returns null.
      The result from the next query in the pipeline may then be retrieved using
@@ -5057,10 +5058,10 @@ int PQflush(PGconn *conn);
      <type>PGresult</type> types <literal>PGRES_PIPELINE_SYNC</literal>
      and <literal>PGRES_PIPELINE_ABORTED</literal>.
      <literal>PGRES_PIPELINE_SYNC</literal> is reported exactly once for each
-     <function>PQsendPipeline</function> call at the corresponding point in
-     the result stream.
+     <function>PQsendPipeline</function> after retrieving results for all
+     queries in the pipeline.
      <literal>PGRES_PIPELINE_ABORTED</literal> is emitted in place of a normal
-     result stream result for the first error and all subsequent results
+     stream result for the first error and all subsequent results
      except <literal>PGRES_PIPELINE_SYNC</literal> and null;
      see <xref linkend="libpq-pipeline-errors"/>.
     </para>
@@ -5075,7 +5076,8 @@ int PQflush(PGconn *conn);
      application about the query currently being processed (except that
      <function>PQgetResult</function> returns null to indicate that we start
      returning the results of next query). The application must keep track
-     of the order in which it sent queries and the expected results.
+     of the order in which it sent queries, to associate them with their
+     corresponding results.
      Applications will typically use a state machine or a FIFO queue for this.
     </para>
 
@@ -5091,10 +5093,10 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     From the client perspective, after the client gets a
-     <literal>PGRES_FATAL_ERROR</literal> return from
-     <function>PQresultStatus</function> the pipeline is flagged as aborted.
-     <application>libpq</application> will report
+     From the client perspective, after <function>PQresultStatus</function>
+     returns <literal>PGRES_FATAL_ERROR</literal>,
+     the pipeline is flagged as aborted.
+     <function>PQresultStatus</function>, will report a
      <literal>PGRES_PIPELINE_ABORTED</literal> result for each remaining queued
      operation in an aborted pipeline. The result for
      <function>PQsendPipeline</function> is reported as
@@ -5108,8 +5110,8 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     If the pipeline used an implicit transaction then operations that have
-     already executed are rolled back and operations that were queued for after
+     If the pipeline used an implicit transaction, then operations that have
+     already executed are rolled back and operations that were queued to follow
      the failed operation are skipped entirely. The same behaviour holds if the
      pipeline starts and commits a single explicit transaction (i.e. the first
      statement is <literal>BEGIN</literal> and the last is
@@ -5145,11 +5147,11 @@ int PQflush(PGconn *conn);
 
     <para>
      The client application should generally maintain a queue of work
-     still to be dispatched and a queue of work that has been dispatched
+     remaining to be dispatched and a queue of work that has been dispatched
      but not yet had its results processed. When the socket is writable
      it should dispatch more work. When the socket is readable it should
      read results and process them, matching them up to the next entry in
-     its expected results queue.  Based on available memory, results from
+     its expected results queue.  Based on available memory, results from the
      socket should be read frequently: there's no need to wait until the
      pipeline end to read the results.  Pipelines should be scoped to logical
      units of work, usually (but not necessarily) one transaction per pipeline.
@@ -5191,8 +5193,8 @@ int PQflush(PGconn *conn);
 
      <listitem>
       <para>
-      Returns current pipeline mode status of the <application>libpq</application>
-      connection.
+      Returns the current pipeline mode status of the
+      <application>libpq</application> connection.
 <synopsis>
 PGpipelineStatus PQpipelineStatus(const PGconn *conn);
 </synopsis>
@@ -5233,11 +5235,10 @@ PGpipelineStatus PQpipelineStatus(const PGconn *conn);
          <listitem>
           <para>
            The <application>libpq</application> connection is in pipeline
-           mode and an error has occurred while processing the current
-           pipeline.
-           The aborted flag is cleared as soon as the result
-           of the <function>PQsendPipeline</function> at the end of the aborted
-           pipeline is processed. Clients don't usually need this function to
+           mode and an error occurred while processing the current pipeline.
+           The aborted flag is cleared when <function>PQresultStatus</function>
+           returns PGRES_PIPELINE_SYNC at the end of the pipeline.
+           Clients don't usually need this function to
            verify aborted status, as they can tell that the pipeline is aborted
            from the <literal>PGRES_PIPELINE_ABORTED</literal> result code.
           </para>
@@ -5328,7 +5329,7 @@ int PQsendPipeline(PGconn *conn);
        Returns 1 for success. Returns 0 if the connection is not in
        pipeline mode or sending a
        <link linkend="protocol-flow-ext-query">sync message</link>
-       is failed.
+       failed.
       </para>
      </listitem>
     </varlistentry>
@@ -5349,7 +5350,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is most useful when the server is distant, i.e., network latency
     (<quote>ping time</quote>) is high, and also when many small operations
-    are being performed in rapid sequence.  There is usually less benefit
+    are being performed in rapid succession.  There is usually less benefit
     in using pipelined commands when each query takes many multiples of the client/server
     round-trip time to execute.  A 100-statement operation run on a server
     300ms round-trip-time away would take 30 seconds in network latency alone
@@ -5367,7 +5368,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is not useful when information from one operation is required by
     the client to produce the next operation. In such cases, the client
-    must introduce a synchronization point and wait for a full client/server
+    would have to introduce a synchronization point and wait for a full client/server
     round-trip to get the results it needs. However, it's often possible to
     adjust the client design to exchange the required information server-side.
     Read-modify-write cycles are especially good candidates; for example:
@@ -5392,10 +5393,10 @@ UPDATE mytable SET x = x + 1 WHERE id = 42;
 
    <note>
     <para>
-     The pipeline API was introduced in PostgreSQL 14, but clients using
-     the PostgreSQL 14 version of <application>libpq</application> can use
-     pipelines on server versions 7.4 and newer. Pipeline mode works on any server
-     that supports the v3 extended query protocol.
+     The pipeline API was introduced in <productname>PostgreSQL</productname> 14.
+     Pipeline mode is a client-side feature which doesn't require server
+     support, and works on any server that supports the v3 extended query
+     protocol.
     </para>
    </note>
   </sect2>
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index 7ae7c14948..d7b036a35c 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -3803,7 +3803,7 @@ pqPipelineFlush(PGconn *conn)
 {
 	if ((conn->pipelineStatus == PQ_PIPELINE_OFF) ||
 		(conn->outCount >= OUTBUFFER_THRESHOLD))
-		return (pqFlush(conn));
+		return pqFlush(conn);
 	return 0;
 }
 
diff --git a/src/test/modules/test_libpq/pipeline.c b/src/test/modules/test_libpq/pipeline.c
index f4a2bdec57..01d5a9a8ff 100644
--- a/src/test/modules/test_libpq/pipeline.c
+++ b/src/test/modules/test_libpq/pipeline.c
@@ -126,7 +126,7 @@ test_simple_pipeline(PGconn *conn)
 	 * process the results of as they come in.
 	 *
 	 * For a simple case we should be able to do this without interim
-	 * processing of results since our out buffer will give us enough slush to
+	 * processing of results since our output buffer will give us enough slush to
 	 * work with and we won't block on sending. So blocking mode is fine.
 	 */
 	if (PQisnonblocking(conn))
@@ -603,7 +603,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 
 	/*
 	 * Now we start inserting. We'll be sending enough data that we could fill
-	 * our out buffer, so to avoid deadlocking we need to enter nonblocking
+	 * our output buffer, so to avoid deadlocking we need to enter nonblocking
 	 * mode and consume input while we send more output. As results of each
 	 * query are processed we should pop them to allow processing of the next
 	 * query. There's no need to finish the pipeline before processing
@@ -635,7 +635,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 		}
 
 		/*
-		 * Process any results, so we keep the server's out buffer free
+		 * Process any results, so we keep the server's output buffer free
 		 * flowing and it can continue to process input
 		 */
 		if (FD_ISSET(sock, &input_mask))
-- 
2.17.0


--oC1+HKm2/end4ao3--





^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* [PATCH 2/2] doc review
@ 2021-03-03 22:36  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 29+ messages in thread

From: Justin Pryzby @ 2021-03-03 22:36 UTC (permalink / raw)

---
 doc/src/sgml/libpq.sgml                | 67 +++++++++++++-------------
 src/interfaces/libpq/fe-exec.c         |  2 +-
 src/test/modules/test_libpq/pipeline.c |  6 +--
 3 files changed, 38 insertions(+), 37 deletions(-)

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index a34ecbb144..e2865a218b 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -3130,8 +3130,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_SYNC</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a point in a
-            pipeline where a synchronization point has been established.
+            The <structname>PGresult</structname> represents a
+            synchronization point in pipeline mode, requested by 
+            <xref linkend="libpq-PQsendPipeline"/>.
             This status occurs only when pipeline mode has been selected.
            </para>
           </listitem>
@@ -3141,9 +3142,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_ABORTED</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a pipeline that's
+            The <structname>PGresult</structname> represents a pipeline that has
             received an error from the server.  <function>PQgetResult</function>
-            must be called repeatedly, and it will return this status code,
+            must be called repeatedly, and each time it will return this status code
             until the end of the current pipeline, at which point it will return
             <literal>PGRES_PIPELINE_SYNC</literal> and normal processing can
             resume.
@@ -4953,7 +4954,7 @@ int PQflush(PGconn *conn);
    <title>Using Pipeline Mode</title>
 
    <para>
-    To issue pipelines the application must switch a connection into pipeline mode.
+    To issue pipelines, the application must switch a connection into pipeline mode.
     Enter pipeline mode with <xref linkend="libpq-PQenterPipelineMode"/>
     or test whether pipeline mode is active with
     <xref linkend="libpq-PQpipelineStatus"/>.
@@ -4975,7 +4976,7 @@ int PQflush(PGconn *conn);
         server will block trying to send results to the client from queries
         it has already processed. This only occurs when the client sends
         enough queries to fill both its output buffer and the server's receive
-        buffer before switching to processing input from the server,
+        buffer before it switches to processing input from the server,
         but it's hard to predict exactly when that will happen.
        </para>
       </footnote>
@@ -5025,7 +5026,7 @@ int PQflush(PGconn *conn);
     <title>Processing Results</title>
 
     <para>
-     To process the result of one pipeline query, the application calls
+     To process the result of one query in a pipeline, the application calls
      <function>PQgetResult</function> repeatedly and handles each result
      until <function>PQgetResult</function> returns null.
      The result from the next query in the pipeline may then be retrieved using
@@ -5057,10 +5058,10 @@ int PQflush(PGconn *conn);
      <type>PGresult</type> types <literal>PGRES_PIPELINE_SYNC</literal>
      and <literal>PGRES_PIPELINE_ABORTED</literal>.
      <literal>PGRES_PIPELINE_SYNC</literal> is reported exactly once for each
-     <function>PQsendPipeline</function> call at the corresponding point in
-     the result stream.
+     <function>PQsendPipeline</function> after retrieving results for all
+     queries in the pipeline.
      <literal>PGRES_PIPELINE_ABORTED</literal> is emitted in place of a normal
-     result stream result for the first error and all subsequent results
+     stream result for the first error and all subsequent results
      except <literal>PGRES_PIPELINE_SYNC</literal> and null;
      see <xref linkend="libpq-pipeline-errors"/>.
     </para>
@@ -5075,7 +5076,8 @@ int PQflush(PGconn *conn);
      application about the query currently being processed (except that
      <function>PQgetResult</function> returns null to indicate that we start
      returning the results of next query). The application must keep track
-     of the order in which it sent queries and the expected results.
+     of the order in which it sent queries, to associate them with their
+     corresponding results.
      Applications will typically use a state machine or a FIFO queue for this.
     </para>
 
@@ -5091,10 +5093,10 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     From the client perspective, after the client gets a
-     <literal>PGRES_FATAL_ERROR</literal> return from
-     <function>PQresultStatus</function> the pipeline is flagged as aborted.
-     <application>libpq</application> will report
+     From the client perspective, after <function>PQresultStatus</function>
+     returns <literal>PGRES_FATAL_ERROR</literal>,
+     the pipeline is flagged as aborted.
+     <function>PQresultStatus</function>, will report a
      <literal>PGRES_PIPELINE_ABORTED</literal> result for each remaining queued
      operation in an aborted pipeline. The result for
      <function>PQsendPipeline</function> is reported as
@@ -5108,8 +5110,8 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     If the pipeline used an implicit transaction then operations that have
-     already executed are rolled back and operations that were queued for after
+     If the pipeline used an implicit transaction, then operations that have
+     already executed are rolled back and operations that were queued to follow
      the failed operation are skipped entirely. The same behaviour holds if the
      pipeline starts and commits a single explicit transaction (i.e. the first
      statement is <literal>BEGIN</literal> and the last is
@@ -5145,11 +5147,11 @@ int PQflush(PGconn *conn);
 
     <para>
      The client application should generally maintain a queue of work
-     still to be dispatched and a queue of work that has been dispatched
+     remaining to be dispatched and a queue of work that has been dispatched
      but not yet had its results processed. When the socket is writable
      it should dispatch more work. When the socket is readable it should
      read results and process them, matching them up to the next entry in
-     its expected results queue.  Based on available memory, results from
+     its expected results queue.  Based on available memory, results from the
      socket should be read frequently: there's no need to wait until the
      pipeline end to read the results.  Pipelines should be scoped to logical
      units of work, usually (but not necessarily) one transaction per pipeline.
@@ -5191,8 +5193,8 @@ int PQflush(PGconn *conn);
 
      <listitem>
       <para>
-      Returns current pipeline mode status of the <application>libpq</application>
-      connection.
+      Returns the current pipeline mode status of the
+      <application>libpq</application> connection.
 <synopsis>
 PGpipelineStatus PQpipelineStatus(const PGconn *conn);
 </synopsis>
@@ -5233,11 +5235,10 @@ PGpipelineStatus PQpipelineStatus(const PGconn *conn);
          <listitem>
           <para>
            The <application>libpq</application> connection is in pipeline
-           mode and an error has occurred while processing the current
-           pipeline.
-           The aborted flag is cleared as soon as the result
-           of the <function>PQsendPipeline</function> at the end of the aborted
-           pipeline is processed. Clients don't usually need this function to
+           mode and an error occurred while processing the current pipeline.
+           The aborted flag is cleared when <function>PQresultStatus</function>
+           returns PGRES_PIPELINE_SYNC at the end of the pipeline.
+           Clients don't usually need this function to
            verify aborted status, as they can tell that the pipeline is aborted
            from the <literal>PGRES_PIPELINE_ABORTED</literal> result code.
           </para>
@@ -5328,7 +5329,7 @@ int PQsendPipeline(PGconn *conn);
        Returns 1 for success. Returns 0 if the connection is not in
        pipeline mode or sending a
        <link linkend="protocol-flow-ext-query">sync message</link>
-       is failed.
+       failed.
       </para>
      </listitem>
     </varlistentry>
@@ -5349,7 +5350,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is most useful when the server is distant, i.e., network latency
     (<quote>ping time</quote>) is high, and also when many small operations
-    are being performed in rapid sequence.  There is usually less benefit
+    are being performed in rapid succession.  There is usually less benefit
     in using pipelined commands when each query takes many multiples of the client/server
     round-trip time to execute.  A 100-statement operation run on a server
     300ms round-trip-time away would take 30 seconds in network latency alone
@@ -5367,7 +5368,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is not useful when information from one operation is required by
     the client to produce the next operation. In such cases, the client
-    must introduce a synchronization point and wait for a full client/server
+    would have to introduce a synchronization point and wait for a full client/server
     round-trip to get the results it needs. However, it's often possible to
     adjust the client design to exchange the required information server-side.
     Read-modify-write cycles are especially good candidates; for example:
@@ -5392,10 +5393,10 @@ UPDATE mytable SET x = x + 1 WHERE id = 42;
 
    <note>
     <para>
-     The pipeline API was introduced in PostgreSQL 14, but clients using
-     the PostgreSQL 14 version of <application>libpq</application> can use
-     pipelines on server versions 7.4 and newer. Pipeline mode works on any server
-     that supports the v3 extended query protocol.
+     The pipeline API was introduced in <productname>PostgreSQL</productname> 14.
+     Pipeline mode is a client-side feature which doesn't require server
+     support, and works on any server that supports the v3 extended query
+     protocol.
     </para>
    </note>
   </sect2>
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index 7ae7c14948..d7b036a35c 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -3803,7 +3803,7 @@ pqPipelineFlush(PGconn *conn)
 {
 	if ((conn->pipelineStatus == PQ_PIPELINE_OFF) ||
 		(conn->outCount >= OUTBUFFER_THRESHOLD))
-		return (pqFlush(conn));
+		return pqFlush(conn);
 	return 0;
 }
 
diff --git a/src/test/modules/test_libpq/pipeline.c b/src/test/modules/test_libpq/pipeline.c
index f4a2bdec57..01d5a9a8ff 100644
--- a/src/test/modules/test_libpq/pipeline.c
+++ b/src/test/modules/test_libpq/pipeline.c
@@ -126,7 +126,7 @@ test_simple_pipeline(PGconn *conn)
 	 * process the results of as they come in.
 	 *
 	 * For a simple case we should be able to do this without interim
-	 * processing of results since our out buffer will give us enough slush to
+	 * processing of results since our output buffer will give us enough slush to
 	 * work with and we won't block on sending. So blocking mode is fine.
 	 */
 	if (PQisnonblocking(conn))
@@ -603,7 +603,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 
 	/*
 	 * Now we start inserting. We'll be sending enough data that we could fill
-	 * our out buffer, so to avoid deadlocking we need to enter nonblocking
+	 * our output buffer, so to avoid deadlocking we need to enter nonblocking
 	 * mode and consume input while we send more output. As results of each
 	 * query are processed we should pop them to allow processing of the next
 	 * query. There's no need to finish the pipeline before processing
@@ -635,7 +635,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 		}
 
 		/*
-		 * Process any results, so we keep the server's out buffer free
+		 * Process any results, so we keep the server's output buffer free
 		 * flowing and it can continue to process input
 		 */
 		if (FD_ISSET(sock, &input_mask))
-- 
2.17.0


--oC1+HKm2/end4ao3--





^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* [PATCH 2/2] doc review
@ 2021-03-03 22:36  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 29+ messages in thread

From: Justin Pryzby @ 2021-03-03 22:36 UTC (permalink / raw)

---
 doc/src/sgml/libpq.sgml                | 67 +++++++++++++-------------
 src/interfaces/libpq/fe-exec.c         |  2 +-
 src/test/modules/test_libpq/pipeline.c |  6 +--
 3 files changed, 38 insertions(+), 37 deletions(-)

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index a34ecbb144..e2865a218b 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -3130,8 +3130,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_SYNC</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a point in a
-            pipeline where a synchronization point has been established.
+            The <structname>PGresult</structname> represents a
+            synchronization point in pipeline mode, requested by 
+            <xref linkend="libpq-PQsendPipeline"/>.
             This status occurs only when pipeline mode has been selected.
            </para>
           </listitem>
@@ -3141,9 +3142,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_ABORTED</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a pipeline that's
+            The <structname>PGresult</structname> represents a pipeline that has
             received an error from the server.  <function>PQgetResult</function>
-            must be called repeatedly, and it will return this status code,
+            must be called repeatedly, and each time it will return this status code
             until the end of the current pipeline, at which point it will return
             <literal>PGRES_PIPELINE_SYNC</literal> and normal processing can
             resume.
@@ -4953,7 +4954,7 @@ int PQflush(PGconn *conn);
    <title>Using Pipeline Mode</title>
 
    <para>
-    To issue pipelines the application must switch a connection into pipeline mode.
+    To issue pipelines, the application must switch a connection into pipeline mode.
     Enter pipeline mode with <xref linkend="libpq-PQenterPipelineMode"/>
     or test whether pipeline mode is active with
     <xref linkend="libpq-PQpipelineStatus"/>.
@@ -4975,7 +4976,7 @@ int PQflush(PGconn *conn);
         server will block trying to send results to the client from queries
         it has already processed. This only occurs when the client sends
         enough queries to fill both its output buffer and the server's receive
-        buffer before switching to processing input from the server,
+        buffer before it switches to processing input from the server,
         but it's hard to predict exactly when that will happen.
        </para>
       </footnote>
@@ -5025,7 +5026,7 @@ int PQflush(PGconn *conn);
     <title>Processing Results</title>
 
     <para>
-     To process the result of one pipeline query, the application calls
+     To process the result of one query in a pipeline, the application calls
      <function>PQgetResult</function> repeatedly and handles each result
      until <function>PQgetResult</function> returns null.
      The result from the next query in the pipeline may then be retrieved using
@@ -5057,10 +5058,10 @@ int PQflush(PGconn *conn);
      <type>PGresult</type> types <literal>PGRES_PIPELINE_SYNC</literal>
      and <literal>PGRES_PIPELINE_ABORTED</literal>.
      <literal>PGRES_PIPELINE_SYNC</literal> is reported exactly once for each
-     <function>PQsendPipeline</function> call at the corresponding point in
-     the result stream.
+     <function>PQsendPipeline</function> after retrieving results for all
+     queries in the pipeline.
      <literal>PGRES_PIPELINE_ABORTED</literal> is emitted in place of a normal
-     result stream result for the first error and all subsequent results
+     stream result for the first error and all subsequent results
      except <literal>PGRES_PIPELINE_SYNC</literal> and null;
      see <xref linkend="libpq-pipeline-errors"/>.
     </para>
@@ -5075,7 +5076,8 @@ int PQflush(PGconn *conn);
      application about the query currently being processed (except that
      <function>PQgetResult</function> returns null to indicate that we start
      returning the results of next query). The application must keep track
-     of the order in which it sent queries and the expected results.
+     of the order in which it sent queries, to associate them with their
+     corresponding results.
      Applications will typically use a state machine or a FIFO queue for this.
     </para>
 
@@ -5091,10 +5093,10 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     From the client perspective, after the client gets a
-     <literal>PGRES_FATAL_ERROR</literal> return from
-     <function>PQresultStatus</function> the pipeline is flagged as aborted.
-     <application>libpq</application> will report
+     From the client perspective, after <function>PQresultStatus</function>
+     returns <literal>PGRES_FATAL_ERROR</literal>,
+     the pipeline is flagged as aborted.
+     <function>PQresultStatus</function>, will report a
      <literal>PGRES_PIPELINE_ABORTED</literal> result for each remaining queued
      operation in an aborted pipeline. The result for
      <function>PQsendPipeline</function> is reported as
@@ -5108,8 +5110,8 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     If the pipeline used an implicit transaction then operations that have
-     already executed are rolled back and operations that were queued for after
+     If the pipeline used an implicit transaction, then operations that have
+     already executed are rolled back and operations that were queued to follow
      the failed operation are skipped entirely. The same behaviour holds if the
      pipeline starts and commits a single explicit transaction (i.e. the first
      statement is <literal>BEGIN</literal> and the last is
@@ -5145,11 +5147,11 @@ int PQflush(PGconn *conn);
 
     <para>
      The client application should generally maintain a queue of work
-     still to be dispatched and a queue of work that has been dispatched
+     remaining to be dispatched and a queue of work that has been dispatched
      but not yet had its results processed. When the socket is writable
      it should dispatch more work. When the socket is readable it should
      read results and process them, matching them up to the next entry in
-     its expected results queue.  Based on available memory, results from
+     its expected results queue.  Based on available memory, results from the
      socket should be read frequently: there's no need to wait until the
      pipeline end to read the results.  Pipelines should be scoped to logical
      units of work, usually (but not necessarily) one transaction per pipeline.
@@ -5191,8 +5193,8 @@ int PQflush(PGconn *conn);
 
      <listitem>
       <para>
-      Returns current pipeline mode status of the <application>libpq</application>
-      connection.
+      Returns the current pipeline mode status of the
+      <application>libpq</application> connection.
 <synopsis>
 PGpipelineStatus PQpipelineStatus(const PGconn *conn);
 </synopsis>
@@ -5233,11 +5235,10 @@ PGpipelineStatus PQpipelineStatus(const PGconn *conn);
          <listitem>
           <para>
            The <application>libpq</application> connection is in pipeline
-           mode and an error has occurred while processing the current
-           pipeline.
-           The aborted flag is cleared as soon as the result
-           of the <function>PQsendPipeline</function> at the end of the aborted
-           pipeline is processed. Clients don't usually need this function to
+           mode and an error occurred while processing the current pipeline.
+           The aborted flag is cleared when <function>PQresultStatus</function>
+           returns PGRES_PIPELINE_SYNC at the end of the pipeline.
+           Clients don't usually need this function to
            verify aborted status, as they can tell that the pipeline is aborted
            from the <literal>PGRES_PIPELINE_ABORTED</literal> result code.
           </para>
@@ -5328,7 +5329,7 @@ int PQsendPipeline(PGconn *conn);
        Returns 1 for success. Returns 0 if the connection is not in
        pipeline mode or sending a
        <link linkend="protocol-flow-ext-query">sync message</link>
-       is failed.
+       failed.
       </para>
      </listitem>
     </varlistentry>
@@ -5349,7 +5350,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is most useful when the server is distant, i.e., network latency
     (<quote>ping time</quote>) is high, and also when many small operations
-    are being performed in rapid sequence.  There is usually less benefit
+    are being performed in rapid succession.  There is usually less benefit
     in using pipelined commands when each query takes many multiples of the client/server
     round-trip time to execute.  A 100-statement operation run on a server
     300ms round-trip-time away would take 30 seconds in network latency alone
@@ -5367,7 +5368,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is not useful when information from one operation is required by
     the client to produce the next operation. In such cases, the client
-    must introduce a synchronization point and wait for a full client/server
+    would have to introduce a synchronization point and wait for a full client/server
     round-trip to get the results it needs. However, it's often possible to
     adjust the client design to exchange the required information server-side.
     Read-modify-write cycles are especially good candidates; for example:
@@ -5392,10 +5393,10 @@ UPDATE mytable SET x = x + 1 WHERE id = 42;
 
    <note>
     <para>
-     The pipeline API was introduced in PostgreSQL 14, but clients using
-     the PostgreSQL 14 version of <application>libpq</application> can use
-     pipelines on server versions 7.4 and newer. Pipeline mode works on any server
-     that supports the v3 extended query protocol.
+     The pipeline API was introduced in <productname>PostgreSQL</productname> 14.
+     Pipeline mode is a client-side feature which doesn't require server
+     support, and works on any server that supports the v3 extended query
+     protocol.
     </para>
    </note>
   </sect2>
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index 7ae7c14948..d7b036a35c 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -3803,7 +3803,7 @@ pqPipelineFlush(PGconn *conn)
 {
 	if ((conn->pipelineStatus == PQ_PIPELINE_OFF) ||
 		(conn->outCount >= OUTBUFFER_THRESHOLD))
-		return (pqFlush(conn));
+		return pqFlush(conn);
 	return 0;
 }
 
diff --git a/src/test/modules/test_libpq/pipeline.c b/src/test/modules/test_libpq/pipeline.c
index f4a2bdec57..01d5a9a8ff 100644
--- a/src/test/modules/test_libpq/pipeline.c
+++ b/src/test/modules/test_libpq/pipeline.c
@@ -126,7 +126,7 @@ test_simple_pipeline(PGconn *conn)
 	 * process the results of as they come in.
 	 *
 	 * For a simple case we should be able to do this without interim
-	 * processing of results since our out buffer will give us enough slush to
+	 * processing of results since our output buffer will give us enough slush to
 	 * work with and we won't block on sending. So blocking mode is fine.
 	 */
 	if (PQisnonblocking(conn))
@@ -603,7 +603,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 
 	/*
 	 * Now we start inserting. We'll be sending enough data that we could fill
-	 * our out buffer, so to avoid deadlocking we need to enter nonblocking
+	 * our output buffer, so to avoid deadlocking we need to enter nonblocking
 	 * mode and consume input while we send more output. As results of each
 	 * query are processed we should pop them to allow processing of the next
 	 * query. There's no need to finish the pipeline before processing
@@ -635,7 +635,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 		}
 
 		/*
-		 * Process any results, so we keep the server's out buffer free
+		 * Process any results, so we keep the server's output buffer free
 		 * flowing and it can continue to process input
 		 */
 		if (FD_ISSET(sock, &input_mask))
-- 
2.17.0


--oC1+HKm2/end4ao3--





^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* [PATCH 2/2] doc review
@ 2021-03-03 22:36  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 29+ messages in thread

From: Justin Pryzby @ 2021-03-03 22:36 UTC (permalink / raw)

---
 doc/src/sgml/libpq.sgml                | 67 +++++++++++++-------------
 src/interfaces/libpq/fe-exec.c         |  2 +-
 src/test/modules/test_libpq/pipeline.c |  6 +--
 3 files changed, 38 insertions(+), 37 deletions(-)

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index a34ecbb144..e2865a218b 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -3130,8 +3130,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_SYNC</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a point in a
-            pipeline where a synchronization point has been established.
+            The <structname>PGresult</structname> represents a
+            synchronization point in pipeline mode, requested by 
+            <xref linkend="libpq-PQsendPipeline"/>.
             This status occurs only when pipeline mode has been selected.
            </para>
           </listitem>
@@ -3141,9 +3142,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_ABORTED</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a pipeline that's
+            The <structname>PGresult</structname> represents a pipeline that has
             received an error from the server.  <function>PQgetResult</function>
-            must be called repeatedly, and it will return this status code,
+            must be called repeatedly, and each time it will return this status code
             until the end of the current pipeline, at which point it will return
             <literal>PGRES_PIPELINE_SYNC</literal> and normal processing can
             resume.
@@ -4953,7 +4954,7 @@ int PQflush(PGconn *conn);
    <title>Using Pipeline Mode</title>
 
    <para>
-    To issue pipelines the application must switch a connection into pipeline mode.
+    To issue pipelines, the application must switch a connection into pipeline mode.
     Enter pipeline mode with <xref linkend="libpq-PQenterPipelineMode"/>
     or test whether pipeline mode is active with
     <xref linkend="libpq-PQpipelineStatus"/>.
@@ -4975,7 +4976,7 @@ int PQflush(PGconn *conn);
         server will block trying to send results to the client from queries
         it has already processed. This only occurs when the client sends
         enough queries to fill both its output buffer and the server's receive
-        buffer before switching to processing input from the server,
+        buffer before it switches to processing input from the server,
         but it's hard to predict exactly when that will happen.
        </para>
       </footnote>
@@ -5025,7 +5026,7 @@ int PQflush(PGconn *conn);
     <title>Processing Results</title>
 
     <para>
-     To process the result of one pipeline query, the application calls
+     To process the result of one query in a pipeline, the application calls
      <function>PQgetResult</function> repeatedly and handles each result
      until <function>PQgetResult</function> returns null.
      The result from the next query in the pipeline may then be retrieved using
@@ -5057,10 +5058,10 @@ int PQflush(PGconn *conn);
      <type>PGresult</type> types <literal>PGRES_PIPELINE_SYNC</literal>
      and <literal>PGRES_PIPELINE_ABORTED</literal>.
      <literal>PGRES_PIPELINE_SYNC</literal> is reported exactly once for each
-     <function>PQsendPipeline</function> call at the corresponding point in
-     the result stream.
+     <function>PQsendPipeline</function> after retrieving results for all
+     queries in the pipeline.
      <literal>PGRES_PIPELINE_ABORTED</literal> is emitted in place of a normal
-     result stream result for the first error and all subsequent results
+     stream result for the first error and all subsequent results
      except <literal>PGRES_PIPELINE_SYNC</literal> and null;
      see <xref linkend="libpq-pipeline-errors"/>.
     </para>
@@ -5075,7 +5076,8 @@ int PQflush(PGconn *conn);
      application about the query currently being processed (except that
      <function>PQgetResult</function> returns null to indicate that we start
      returning the results of next query). The application must keep track
-     of the order in which it sent queries and the expected results.
+     of the order in which it sent queries, to associate them with their
+     corresponding results.
      Applications will typically use a state machine or a FIFO queue for this.
     </para>
 
@@ -5091,10 +5093,10 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     From the client perspective, after the client gets a
-     <literal>PGRES_FATAL_ERROR</literal> return from
-     <function>PQresultStatus</function> the pipeline is flagged as aborted.
-     <application>libpq</application> will report
+     From the client perspective, after <function>PQresultStatus</function>
+     returns <literal>PGRES_FATAL_ERROR</literal>,
+     the pipeline is flagged as aborted.
+     <function>PQresultStatus</function>, will report a
      <literal>PGRES_PIPELINE_ABORTED</literal> result for each remaining queued
      operation in an aborted pipeline. The result for
      <function>PQsendPipeline</function> is reported as
@@ -5108,8 +5110,8 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     If the pipeline used an implicit transaction then operations that have
-     already executed are rolled back and operations that were queued for after
+     If the pipeline used an implicit transaction, then operations that have
+     already executed are rolled back and operations that were queued to follow
      the failed operation are skipped entirely. The same behaviour holds if the
      pipeline starts and commits a single explicit transaction (i.e. the first
      statement is <literal>BEGIN</literal> and the last is
@@ -5145,11 +5147,11 @@ int PQflush(PGconn *conn);
 
     <para>
      The client application should generally maintain a queue of work
-     still to be dispatched and a queue of work that has been dispatched
+     remaining to be dispatched and a queue of work that has been dispatched
      but not yet had its results processed. When the socket is writable
      it should dispatch more work. When the socket is readable it should
      read results and process them, matching them up to the next entry in
-     its expected results queue.  Based on available memory, results from
+     its expected results queue.  Based on available memory, results from the
      socket should be read frequently: there's no need to wait until the
      pipeline end to read the results.  Pipelines should be scoped to logical
      units of work, usually (but not necessarily) one transaction per pipeline.
@@ -5191,8 +5193,8 @@ int PQflush(PGconn *conn);
 
      <listitem>
       <para>
-      Returns current pipeline mode status of the <application>libpq</application>
-      connection.
+      Returns the current pipeline mode status of the
+      <application>libpq</application> connection.
 <synopsis>
 PGpipelineStatus PQpipelineStatus(const PGconn *conn);
 </synopsis>
@@ -5233,11 +5235,10 @@ PGpipelineStatus PQpipelineStatus(const PGconn *conn);
          <listitem>
           <para>
            The <application>libpq</application> connection is in pipeline
-           mode and an error has occurred while processing the current
-           pipeline.
-           The aborted flag is cleared as soon as the result
-           of the <function>PQsendPipeline</function> at the end of the aborted
-           pipeline is processed. Clients don't usually need this function to
+           mode and an error occurred while processing the current pipeline.
+           The aborted flag is cleared when <function>PQresultStatus</function>
+           returns PGRES_PIPELINE_SYNC at the end of the pipeline.
+           Clients don't usually need this function to
            verify aborted status, as they can tell that the pipeline is aborted
            from the <literal>PGRES_PIPELINE_ABORTED</literal> result code.
           </para>
@@ -5328,7 +5329,7 @@ int PQsendPipeline(PGconn *conn);
        Returns 1 for success. Returns 0 if the connection is not in
        pipeline mode or sending a
        <link linkend="protocol-flow-ext-query">sync message</link>
-       is failed.
+       failed.
       </para>
      </listitem>
     </varlistentry>
@@ -5349,7 +5350,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is most useful when the server is distant, i.e., network latency
     (<quote>ping time</quote>) is high, and also when many small operations
-    are being performed in rapid sequence.  There is usually less benefit
+    are being performed in rapid succession.  There is usually less benefit
     in using pipelined commands when each query takes many multiples of the client/server
     round-trip time to execute.  A 100-statement operation run on a server
     300ms round-trip-time away would take 30 seconds in network latency alone
@@ -5367,7 +5368,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is not useful when information from one operation is required by
     the client to produce the next operation. In such cases, the client
-    must introduce a synchronization point and wait for a full client/server
+    would have to introduce a synchronization point and wait for a full client/server
     round-trip to get the results it needs. However, it's often possible to
     adjust the client design to exchange the required information server-side.
     Read-modify-write cycles are especially good candidates; for example:
@@ -5392,10 +5393,10 @@ UPDATE mytable SET x = x + 1 WHERE id = 42;
 
    <note>
     <para>
-     The pipeline API was introduced in PostgreSQL 14, but clients using
-     the PostgreSQL 14 version of <application>libpq</application> can use
-     pipelines on server versions 7.4 and newer. Pipeline mode works on any server
-     that supports the v3 extended query protocol.
+     The pipeline API was introduced in <productname>PostgreSQL</productname> 14.
+     Pipeline mode is a client-side feature which doesn't require server
+     support, and works on any server that supports the v3 extended query
+     protocol.
     </para>
    </note>
   </sect2>
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index 7ae7c14948..d7b036a35c 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -3803,7 +3803,7 @@ pqPipelineFlush(PGconn *conn)
 {
 	if ((conn->pipelineStatus == PQ_PIPELINE_OFF) ||
 		(conn->outCount >= OUTBUFFER_THRESHOLD))
-		return (pqFlush(conn));
+		return pqFlush(conn);
 	return 0;
 }
 
diff --git a/src/test/modules/test_libpq/pipeline.c b/src/test/modules/test_libpq/pipeline.c
index f4a2bdec57..01d5a9a8ff 100644
--- a/src/test/modules/test_libpq/pipeline.c
+++ b/src/test/modules/test_libpq/pipeline.c
@@ -126,7 +126,7 @@ test_simple_pipeline(PGconn *conn)
 	 * process the results of as they come in.
 	 *
 	 * For a simple case we should be able to do this without interim
-	 * processing of results since our out buffer will give us enough slush to
+	 * processing of results since our output buffer will give us enough slush to
 	 * work with and we won't block on sending. So blocking mode is fine.
 	 */
 	if (PQisnonblocking(conn))
@@ -603,7 +603,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 
 	/*
 	 * Now we start inserting. We'll be sending enough data that we could fill
-	 * our out buffer, so to avoid deadlocking we need to enter nonblocking
+	 * our output buffer, so to avoid deadlocking we need to enter nonblocking
 	 * mode and consume input while we send more output. As results of each
 	 * query are processed we should pop them to allow processing of the next
 	 * query. There's no need to finish the pipeline before processing
@@ -635,7 +635,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 		}
 
 		/*
-		 * Process any results, so we keep the server's out buffer free
+		 * Process any results, so we keep the server's output buffer free
 		 * flowing and it can continue to process input
 		 */
 		if (FD_ISSET(sock, &input_mask))
-- 
2.17.0


--oC1+HKm2/end4ao3--





^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* [PATCH 2/2] doc review
@ 2021-03-03 22:36  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 29+ messages in thread

From: Justin Pryzby @ 2021-03-03 22:36 UTC (permalink / raw)

---
 doc/src/sgml/libpq.sgml                | 67 +++++++++++++-------------
 src/interfaces/libpq/fe-exec.c         |  2 +-
 src/test/modules/test_libpq/pipeline.c |  6 +--
 3 files changed, 38 insertions(+), 37 deletions(-)

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index a34ecbb144..e2865a218b 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -3130,8 +3130,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_SYNC</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a point in a
-            pipeline where a synchronization point has been established.
+            The <structname>PGresult</structname> represents a
+            synchronization point in pipeline mode, requested by 
+            <xref linkend="libpq-PQsendPipeline"/>.
             This status occurs only when pipeline mode has been selected.
            </para>
           </listitem>
@@ -3141,9 +3142,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_ABORTED</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a pipeline that's
+            The <structname>PGresult</structname> represents a pipeline that has
             received an error from the server.  <function>PQgetResult</function>
-            must be called repeatedly, and it will return this status code,
+            must be called repeatedly, and each time it will return this status code
             until the end of the current pipeline, at which point it will return
             <literal>PGRES_PIPELINE_SYNC</literal> and normal processing can
             resume.
@@ -4953,7 +4954,7 @@ int PQflush(PGconn *conn);
    <title>Using Pipeline Mode</title>
 
    <para>
-    To issue pipelines the application must switch a connection into pipeline mode.
+    To issue pipelines, the application must switch a connection into pipeline mode.
     Enter pipeline mode with <xref linkend="libpq-PQenterPipelineMode"/>
     or test whether pipeline mode is active with
     <xref linkend="libpq-PQpipelineStatus"/>.
@@ -4975,7 +4976,7 @@ int PQflush(PGconn *conn);
         server will block trying to send results to the client from queries
         it has already processed. This only occurs when the client sends
         enough queries to fill both its output buffer and the server's receive
-        buffer before switching to processing input from the server,
+        buffer before it switches to processing input from the server,
         but it's hard to predict exactly when that will happen.
        </para>
       </footnote>
@@ -5025,7 +5026,7 @@ int PQflush(PGconn *conn);
     <title>Processing Results</title>
 
     <para>
-     To process the result of one pipeline query, the application calls
+     To process the result of one query in a pipeline, the application calls
      <function>PQgetResult</function> repeatedly and handles each result
      until <function>PQgetResult</function> returns null.
      The result from the next query in the pipeline may then be retrieved using
@@ -5057,10 +5058,10 @@ int PQflush(PGconn *conn);
      <type>PGresult</type> types <literal>PGRES_PIPELINE_SYNC</literal>
      and <literal>PGRES_PIPELINE_ABORTED</literal>.
      <literal>PGRES_PIPELINE_SYNC</literal> is reported exactly once for each
-     <function>PQsendPipeline</function> call at the corresponding point in
-     the result stream.
+     <function>PQsendPipeline</function> after retrieving results for all
+     queries in the pipeline.
      <literal>PGRES_PIPELINE_ABORTED</literal> is emitted in place of a normal
-     result stream result for the first error and all subsequent results
+     stream result for the first error and all subsequent results
      except <literal>PGRES_PIPELINE_SYNC</literal> and null;
      see <xref linkend="libpq-pipeline-errors"/>.
     </para>
@@ -5075,7 +5076,8 @@ int PQflush(PGconn *conn);
      application about the query currently being processed (except that
      <function>PQgetResult</function> returns null to indicate that we start
      returning the results of next query). The application must keep track
-     of the order in which it sent queries and the expected results.
+     of the order in which it sent queries, to associate them with their
+     corresponding results.
      Applications will typically use a state machine or a FIFO queue for this.
     </para>
 
@@ -5091,10 +5093,10 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     From the client perspective, after the client gets a
-     <literal>PGRES_FATAL_ERROR</literal> return from
-     <function>PQresultStatus</function> the pipeline is flagged as aborted.
-     <application>libpq</application> will report
+     From the client perspective, after <function>PQresultStatus</function>
+     returns <literal>PGRES_FATAL_ERROR</literal>,
+     the pipeline is flagged as aborted.
+     <function>PQresultStatus</function>, will report a
      <literal>PGRES_PIPELINE_ABORTED</literal> result for each remaining queued
      operation in an aborted pipeline. The result for
      <function>PQsendPipeline</function> is reported as
@@ -5108,8 +5110,8 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     If the pipeline used an implicit transaction then operations that have
-     already executed are rolled back and operations that were queued for after
+     If the pipeline used an implicit transaction, then operations that have
+     already executed are rolled back and operations that were queued to follow
      the failed operation are skipped entirely. The same behaviour holds if the
      pipeline starts and commits a single explicit transaction (i.e. the first
      statement is <literal>BEGIN</literal> and the last is
@@ -5145,11 +5147,11 @@ int PQflush(PGconn *conn);
 
     <para>
      The client application should generally maintain a queue of work
-     still to be dispatched and a queue of work that has been dispatched
+     remaining to be dispatched and a queue of work that has been dispatched
      but not yet had its results processed. When the socket is writable
      it should dispatch more work. When the socket is readable it should
      read results and process them, matching them up to the next entry in
-     its expected results queue.  Based on available memory, results from
+     its expected results queue.  Based on available memory, results from the
      socket should be read frequently: there's no need to wait until the
      pipeline end to read the results.  Pipelines should be scoped to logical
      units of work, usually (but not necessarily) one transaction per pipeline.
@@ -5191,8 +5193,8 @@ int PQflush(PGconn *conn);
 
      <listitem>
       <para>
-      Returns current pipeline mode status of the <application>libpq</application>
-      connection.
+      Returns the current pipeline mode status of the
+      <application>libpq</application> connection.
 <synopsis>
 PGpipelineStatus PQpipelineStatus(const PGconn *conn);
 </synopsis>
@@ -5233,11 +5235,10 @@ PGpipelineStatus PQpipelineStatus(const PGconn *conn);
          <listitem>
           <para>
            The <application>libpq</application> connection is in pipeline
-           mode and an error has occurred while processing the current
-           pipeline.
-           The aborted flag is cleared as soon as the result
-           of the <function>PQsendPipeline</function> at the end of the aborted
-           pipeline is processed. Clients don't usually need this function to
+           mode and an error occurred while processing the current pipeline.
+           The aborted flag is cleared when <function>PQresultStatus</function>
+           returns PGRES_PIPELINE_SYNC at the end of the pipeline.
+           Clients don't usually need this function to
            verify aborted status, as they can tell that the pipeline is aborted
            from the <literal>PGRES_PIPELINE_ABORTED</literal> result code.
           </para>
@@ -5328,7 +5329,7 @@ int PQsendPipeline(PGconn *conn);
        Returns 1 for success. Returns 0 if the connection is not in
        pipeline mode or sending a
        <link linkend="protocol-flow-ext-query">sync message</link>
-       is failed.
+       failed.
       </para>
      </listitem>
     </varlistentry>
@@ -5349,7 +5350,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is most useful when the server is distant, i.e., network latency
     (<quote>ping time</quote>) is high, and also when many small operations
-    are being performed in rapid sequence.  There is usually less benefit
+    are being performed in rapid succession.  There is usually less benefit
     in using pipelined commands when each query takes many multiples of the client/server
     round-trip time to execute.  A 100-statement operation run on a server
     300ms round-trip-time away would take 30 seconds in network latency alone
@@ -5367,7 +5368,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is not useful when information from one operation is required by
     the client to produce the next operation. In such cases, the client
-    must introduce a synchronization point and wait for a full client/server
+    would have to introduce a synchronization point and wait for a full client/server
     round-trip to get the results it needs. However, it's often possible to
     adjust the client design to exchange the required information server-side.
     Read-modify-write cycles are especially good candidates; for example:
@@ -5392,10 +5393,10 @@ UPDATE mytable SET x = x + 1 WHERE id = 42;
 
    <note>
     <para>
-     The pipeline API was introduced in PostgreSQL 14, but clients using
-     the PostgreSQL 14 version of <application>libpq</application> can use
-     pipelines on server versions 7.4 and newer. Pipeline mode works on any server
-     that supports the v3 extended query protocol.
+     The pipeline API was introduced in <productname>PostgreSQL</productname> 14.
+     Pipeline mode is a client-side feature which doesn't require server
+     support, and works on any server that supports the v3 extended query
+     protocol.
     </para>
    </note>
   </sect2>
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index 7ae7c14948..d7b036a35c 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -3803,7 +3803,7 @@ pqPipelineFlush(PGconn *conn)
 {
 	if ((conn->pipelineStatus == PQ_PIPELINE_OFF) ||
 		(conn->outCount >= OUTBUFFER_THRESHOLD))
-		return (pqFlush(conn));
+		return pqFlush(conn);
 	return 0;
 }
 
diff --git a/src/test/modules/test_libpq/pipeline.c b/src/test/modules/test_libpq/pipeline.c
index f4a2bdec57..01d5a9a8ff 100644
--- a/src/test/modules/test_libpq/pipeline.c
+++ b/src/test/modules/test_libpq/pipeline.c
@@ -126,7 +126,7 @@ test_simple_pipeline(PGconn *conn)
 	 * process the results of as they come in.
 	 *
 	 * For a simple case we should be able to do this without interim
-	 * processing of results since our out buffer will give us enough slush to
+	 * processing of results since our output buffer will give us enough slush to
 	 * work with and we won't block on sending. So blocking mode is fine.
 	 */
 	if (PQisnonblocking(conn))
@@ -603,7 +603,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 
 	/*
 	 * Now we start inserting. We'll be sending enough data that we could fill
-	 * our out buffer, so to avoid deadlocking we need to enter nonblocking
+	 * our output buffer, so to avoid deadlocking we need to enter nonblocking
 	 * mode and consume input while we send more output. As results of each
 	 * query are processed we should pop them to allow processing of the next
 	 * query. There's no need to finish the pipeline before processing
@@ -635,7 +635,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 		}
 
 		/*
-		 * Process any results, so we keep the server's out buffer free
+		 * Process any results, so we keep the server's output buffer free
 		 * flowing and it can continue to process input
 		 */
 		if (FD_ISSET(sock, &input_mask))
-- 
2.17.0


--oC1+HKm2/end4ao3--





^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* [PATCH 2/2] doc review
@ 2021-03-03 22:36  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 29+ messages in thread

From: Justin Pryzby @ 2021-03-03 22:36 UTC (permalink / raw)

---
 doc/src/sgml/libpq.sgml                | 67 +++++++++++++-------------
 src/interfaces/libpq/fe-exec.c         |  2 +-
 src/test/modules/test_libpq/pipeline.c |  6 +--
 3 files changed, 38 insertions(+), 37 deletions(-)

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index a34ecbb144..e2865a218b 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -3130,8 +3130,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_SYNC</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a point in a
-            pipeline where a synchronization point has been established.
+            The <structname>PGresult</structname> represents a
+            synchronization point in pipeline mode, requested by 
+            <xref linkend="libpq-PQsendPipeline"/>.
             This status occurs only when pipeline mode has been selected.
            </para>
           </listitem>
@@ -3141,9 +3142,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_ABORTED</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a pipeline that's
+            The <structname>PGresult</structname> represents a pipeline that has
             received an error from the server.  <function>PQgetResult</function>
-            must be called repeatedly, and it will return this status code,
+            must be called repeatedly, and each time it will return this status code
             until the end of the current pipeline, at which point it will return
             <literal>PGRES_PIPELINE_SYNC</literal> and normal processing can
             resume.
@@ -4953,7 +4954,7 @@ int PQflush(PGconn *conn);
    <title>Using Pipeline Mode</title>
 
    <para>
-    To issue pipelines the application must switch a connection into pipeline mode.
+    To issue pipelines, the application must switch a connection into pipeline mode.
     Enter pipeline mode with <xref linkend="libpq-PQenterPipelineMode"/>
     or test whether pipeline mode is active with
     <xref linkend="libpq-PQpipelineStatus"/>.
@@ -4975,7 +4976,7 @@ int PQflush(PGconn *conn);
         server will block trying to send results to the client from queries
         it has already processed. This only occurs when the client sends
         enough queries to fill both its output buffer and the server's receive
-        buffer before switching to processing input from the server,
+        buffer before it switches to processing input from the server,
         but it's hard to predict exactly when that will happen.
        </para>
       </footnote>
@@ -5025,7 +5026,7 @@ int PQflush(PGconn *conn);
     <title>Processing Results</title>
 
     <para>
-     To process the result of one pipeline query, the application calls
+     To process the result of one query in a pipeline, the application calls
      <function>PQgetResult</function> repeatedly and handles each result
      until <function>PQgetResult</function> returns null.
      The result from the next query in the pipeline may then be retrieved using
@@ -5057,10 +5058,10 @@ int PQflush(PGconn *conn);
      <type>PGresult</type> types <literal>PGRES_PIPELINE_SYNC</literal>
      and <literal>PGRES_PIPELINE_ABORTED</literal>.
      <literal>PGRES_PIPELINE_SYNC</literal> is reported exactly once for each
-     <function>PQsendPipeline</function> call at the corresponding point in
-     the result stream.
+     <function>PQsendPipeline</function> after retrieving results for all
+     queries in the pipeline.
      <literal>PGRES_PIPELINE_ABORTED</literal> is emitted in place of a normal
-     result stream result for the first error and all subsequent results
+     stream result for the first error and all subsequent results
      except <literal>PGRES_PIPELINE_SYNC</literal> and null;
      see <xref linkend="libpq-pipeline-errors"/>.
     </para>
@@ -5075,7 +5076,8 @@ int PQflush(PGconn *conn);
      application about the query currently being processed (except that
      <function>PQgetResult</function> returns null to indicate that we start
      returning the results of next query). The application must keep track
-     of the order in which it sent queries and the expected results.
+     of the order in which it sent queries, to associate them with their
+     corresponding results.
      Applications will typically use a state machine or a FIFO queue for this.
     </para>
 
@@ -5091,10 +5093,10 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     From the client perspective, after the client gets a
-     <literal>PGRES_FATAL_ERROR</literal> return from
-     <function>PQresultStatus</function> the pipeline is flagged as aborted.
-     <application>libpq</application> will report
+     From the client perspective, after <function>PQresultStatus</function>
+     returns <literal>PGRES_FATAL_ERROR</literal>,
+     the pipeline is flagged as aborted.
+     <function>PQresultStatus</function>, will report a
      <literal>PGRES_PIPELINE_ABORTED</literal> result for each remaining queued
      operation in an aborted pipeline. The result for
      <function>PQsendPipeline</function> is reported as
@@ -5108,8 +5110,8 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     If the pipeline used an implicit transaction then operations that have
-     already executed are rolled back and operations that were queued for after
+     If the pipeline used an implicit transaction, then operations that have
+     already executed are rolled back and operations that were queued to follow
      the failed operation are skipped entirely. The same behaviour holds if the
      pipeline starts and commits a single explicit transaction (i.e. the first
      statement is <literal>BEGIN</literal> and the last is
@@ -5145,11 +5147,11 @@ int PQflush(PGconn *conn);
 
     <para>
      The client application should generally maintain a queue of work
-     still to be dispatched and a queue of work that has been dispatched
+     remaining to be dispatched and a queue of work that has been dispatched
      but not yet had its results processed. When the socket is writable
      it should dispatch more work. When the socket is readable it should
      read results and process them, matching them up to the next entry in
-     its expected results queue.  Based on available memory, results from
+     its expected results queue.  Based on available memory, results from the
      socket should be read frequently: there's no need to wait until the
      pipeline end to read the results.  Pipelines should be scoped to logical
      units of work, usually (but not necessarily) one transaction per pipeline.
@@ -5191,8 +5193,8 @@ int PQflush(PGconn *conn);
 
      <listitem>
       <para>
-      Returns current pipeline mode status of the <application>libpq</application>
-      connection.
+      Returns the current pipeline mode status of the
+      <application>libpq</application> connection.
 <synopsis>
 PGpipelineStatus PQpipelineStatus(const PGconn *conn);
 </synopsis>
@@ -5233,11 +5235,10 @@ PGpipelineStatus PQpipelineStatus(const PGconn *conn);
          <listitem>
           <para>
            The <application>libpq</application> connection is in pipeline
-           mode and an error has occurred while processing the current
-           pipeline.
-           The aborted flag is cleared as soon as the result
-           of the <function>PQsendPipeline</function> at the end of the aborted
-           pipeline is processed. Clients don't usually need this function to
+           mode and an error occurred while processing the current pipeline.
+           The aborted flag is cleared when <function>PQresultStatus</function>
+           returns PGRES_PIPELINE_SYNC at the end of the pipeline.
+           Clients don't usually need this function to
            verify aborted status, as they can tell that the pipeline is aborted
            from the <literal>PGRES_PIPELINE_ABORTED</literal> result code.
           </para>
@@ -5328,7 +5329,7 @@ int PQsendPipeline(PGconn *conn);
        Returns 1 for success. Returns 0 if the connection is not in
        pipeline mode or sending a
        <link linkend="protocol-flow-ext-query">sync message</link>
-       is failed.
+       failed.
       </para>
      </listitem>
     </varlistentry>
@@ -5349,7 +5350,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is most useful when the server is distant, i.e., network latency
     (<quote>ping time</quote>) is high, and also when many small operations
-    are being performed in rapid sequence.  There is usually less benefit
+    are being performed in rapid succession.  There is usually less benefit
     in using pipelined commands when each query takes many multiples of the client/server
     round-trip time to execute.  A 100-statement operation run on a server
     300ms round-trip-time away would take 30 seconds in network latency alone
@@ -5367,7 +5368,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is not useful when information from one operation is required by
     the client to produce the next operation. In such cases, the client
-    must introduce a synchronization point and wait for a full client/server
+    would have to introduce a synchronization point and wait for a full client/server
     round-trip to get the results it needs. However, it's often possible to
     adjust the client design to exchange the required information server-side.
     Read-modify-write cycles are especially good candidates; for example:
@@ -5392,10 +5393,10 @@ UPDATE mytable SET x = x + 1 WHERE id = 42;
 
    <note>
     <para>
-     The pipeline API was introduced in PostgreSQL 14, but clients using
-     the PostgreSQL 14 version of <application>libpq</application> can use
-     pipelines on server versions 7.4 and newer. Pipeline mode works on any server
-     that supports the v3 extended query protocol.
+     The pipeline API was introduced in <productname>PostgreSQL</productname> 14.
+     Pipeline mode is a client-side feature which doesn't require server
+     support, and works on any server that supports the v3 extended query
+     protocol.
     </para>
    </note>
   </sect2>
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index 7ae7c14948..d7b036a35c 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -3803,7 +3803,7 @@ pqPipelineFlush(PGconn *conn)
 {
 	if ((conn->pipelineStatus == PQ_PIPELINE_OFF) ||
 		(conn->outCount >= OUTBUFFER_THRESHOLD))
-		return (pqFlush(conn));
+		return pqFlush(conn);
 	return 0;
 }
 
diff --git a/src/test/modules/test_libpq/pipeline.c b/src/test/modules/test_libpq/pipeline.c
index f4a2bdec57..01d5a9a8ff 100644
--- a/src/test/modules/test_libpq/pipeline.c
+++ b/src/test/modules/test_libpq/pipeline.c
@@ -126,7 +126,7 @@ test_simple_pipeline(PGconn *conn)
 	 * process the results of as they come in.
 	 *
 	 * For a simple case we should be able to do this without interim
-	 * processing of results since our out buffer will give us enough slush to
+	 * processing of results since our output buffer will give us enough slush to
 	 * work with and we won't block on sending. So blocking mode is fine.
 	 */
 	if (PQisnonblocking(conn))
@@ -603,7 +603,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 
 	/*
 	 * Now we start inserting. We'll be sending enough data that we could fill
-	 * our out buffer, so to avoid deadlocking we need to enter nonblocking
+	 * our output buffer, so to avoid deadlocking we need to enter nonblocking
 	 * mode and consume input while we send more output. As results of each
 	 * query are processed we should pop them to allow processing of the next
 	 * query. There's no need to finish the pipeline before processing
@@ -635,7 +635,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 		}
 
 		/*
-		 * Process any results, so we keep the server's out buffer free
+		 * Process any results, so we keep the server's output buffer free
 		 * flowing and it can continue to process input
 		 */
 		if (FD_ISSET(sock, &input_mask))
-- 
2.17.0


--oC1+HKm2/end4ao3--





^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* [PATCH 2/2] doc review
@ 2021-03-03 22:36  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 29+ messages in thread

From: Justin Pryzby @ 2021-03-03 22:36 UTC (permalink / raw)

---
 doc/src/sgml/libpq.sgml                | 67 +++++++++++++-------------
 src/interfaces/libpq/fe-exec.c         |  2 +-
 src/test/modules/test_libpq/pipeline.c |  6 +--
 3 files changed, 38 insertions(+), 37 deletions(-)

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index a34ecbb144..e2865a218b 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -3130,8 +3130,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_SYNC</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a point in a
-            pipeline where a synchronization point has been established.
+            The <structname>PGresult</structname> represents a
+            synchronization point in pipeline mode, requested by 
+            <xref linkend="libpq-PQsendPipeline"/>.
             This status occurs only when pipeline mode has been selected.
            </para>
           </listitem>
@@ -3141,9 +3142,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_ABORTED</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a pipeline that's
+            The <structname>PGresult</structname> represents a pipeline that has
             received an error from the server.  <function>PQgetResult</function>
-            must be called repeatedly, and it will return this status code,
+            must be called repeatedly, and each time it will return this status code
             until the end of the current pipeline, at which point it will return
             <literal>PGRES_PIPELINE_SYNC</literal> and normal processing can
             resume.
@@ -4953,7 +4954,7 @@ int PQflush(PGconn *conn);
    <title>Using Pipeline Mode</title>
 
    <para>
-    To issue pipelines the application must switch a connection into pipeline mode.
+    To issue pipelines, the application must switch a connection into pipeline mode.
     Enter pipeline mode with <xref linkend="libpq-PQenterPipelineMode"/>
     or test whether pipeline mode is active with
     <xref linkend="libpq-PQpipelineStatus"/>.
@@ -4975,7 +4976,7 @@ int PQflush(PGconn *conn);
         server will block trying to send results to the client from queries
         it has already processed. This only occurs when the client sends
         enough queries to fill both its output buffer and the server's receive
-        buffer before switching to processing input from the server,
+        buffer before it switches to processing input from the server,
         but it's hard to predict exactly when that will happen.
        </para>
       </footnote>
@@ -5025,7 +5026,7 @@ int PQflush(PGconn *conn);
     <title>Processing Results</title>
 
     <para>
-     To process the result of one pipeline query, the application calls
+     To process the result of one query in a pipeline, the application calls
      <function>PQgetResult</function> repeatedly and handles each result
      until <function>PQgetResult</function> returns null.
      The result from the next query in the pipeline may then be retrieved using
@@ -5057,10 +5058,10 @@ int PQflush(PGconn *conn);
      <type>PGresult</type> types <literal>PGRES_PIPELINE_SYNC</literal>
      and <literal>PGRES_PIPELINE_ABORTED</literal>.
      <literal>PGRES_PIPELINE_SYNC</literal> is reported exactly once for each
-     <function>PQsendPipeline</function> call at the corresponding point in
-     the result stream.
+     <function>PQsendPipeline</function> after retrieving results for all
+     queries in the pipeline.
      <literal>PGRES_PIPELINE_ABORTED</literal> is emitted in place of a normal
-     result stream result for the first error and all subsequent results
+     stream result for the first error and all subsequent results
      except <literal>PGRES_PIPELINE_SYNC</literal> and null;
      see <xref linkend="libpq-pipeline-errors"/>.
     </para>
@@ -5075,7 +5076,8 @@ int PQflush(PGconn *conn);
      application about the query currently being processed (except that
      <function>PQgetResult</function> returns null to indicate that we start
      returning the results of next query). The application must keep track
-     of the order in which it sent queries and the expected results.
+     of the order in which it sent queries, to associate them with their
+     corresponding results.
      Applications will typically use a state machine or a FIFO queue for this.
     </para>
 
@@ -5091,10 +5093,10 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     From the client perspective, after the client gets a
-     <literal>PGRES_FATAL_ERROR</literal> return from
-     <function>PQresultStatus</function> the pipeline is flagged as aborted.
-     <application>libpq</application> will report
+     From the client perspective, after <function>PQresultStatus</function>
+     returns <literal>PGRES_FATAL_ERROR</literal>,
+     the pipeline is flagged as aborted.
+     <function>PQresultStatus</function>, will report a
      <literal>PGRES_PIPELINE_ABORTED</literal> result for each remaining queued
      operation in an aborted pipeline. The result for
      <function>PQsendPipeline</function> is reported as
@@ -5108,8 +5110,8 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     If the pipeline used an implicit transaction then operations that have
-     already executed are rolled back and operations that were queued for after
+     If the pipeline used an implicit transaction, then operations that have
+     already executed are rolled back and operations that were queued to follow
      the failed operation are skipped entirely. The same behaviour holds if the
      pipeline starts and commits a single explicit transaction (i.e. the first
      statement is <literal>BEGIN</literal> and the last is
@@ -5145,11 +5147,11 @@ int PQflush(PGconn *conn);
 
     <para>
      The client application should generally maintain a queue of work
-     still to be dispatched and a queue of work that has been dispatched
+     remaining to be dispatched and a queue of work that has been dispatched
      but not yet had its results processed. When the socket is writable
      it should dispatch more work. When the socket is readable it should
      read results and process them, matching them up to the next entry in
-     its expected results queue.  Based on available memory, results from
+     its expected results queue.  Based on available memory, results from the
      socket should be read frequently: there's no need to wait until the
      pipeline end to read the results.  Pipelines should be scoped to logical
      units of work, usually (but not necessarily) one transaction per pipeline.
@@ -5191,8 +5193,8 @@ int PQflush(PGconn *conn);
 
      <listitem>
       <para>
-      Returns current pipeline mode status of the <application>libpq</application>
-      connection.
+      Returns the current pipeline mode status of the
+      <application>libpq</application> connection.
 <synopsis>
 PGpipelineStatus PQpipelineStatus(const PGconn *conn);
 </synopsis>
@@ -5233,11 +5235,10 @@ PGpipelineStatus PQpipelineStatus(const PGconn *conn);
          <listitem>
           <para>
            The <application>libpq</application> connection is in pipeline
-           mode and an error has occurred while processing the current
-           pipeline.
-           The aborted flag is cleared as soon as the result
-           of the <function>PQsendPipeline</function> at the end of the aborted
-           pipeline is processed. Clients don't usually need this function to
+           mode and an error occurred while processing the current pipeline.
+           The aborted flag is cleared when <function>PQresultStatus</function>
+           returns PGRES_PIPELINE_SYNC at the end of the pipeline.
+           Clients don't usually need this function to
            verify aborted status, as they can tell that the pipeline is aborted
            from the <literal>PGRES_PIPELINE_ABORTED</literal> result code.
           </para>
@@ -5328,7 +5329,7 @@ int PQsendPipeline(PGconn *conn);
        Returns 1 for success. Returns 0 if the connection is not in
        pipeline mode or sending a
        <link linkend="protocol-flow-ext-query">sync message</link>
-       is failed.
+       failed.
       </para>
      </listitem>
     </varlistentry>
@@ -5349,7 +5350,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is most useful when the server is distant, i.e., network latency
     (<quote>ping time</quote>) is high, and also when many small operations
-    are being performed in rapid sequence.  There is usually less benefit
+    are being performed in rapid succession.  There is usually less benefit
     in using pipelined commands when each query takes many multiples of the client/server
     round-trip time to execute.  A 100-statement operation run on a server
     300ms round-trip-time away would take 30 seconds in network latency alone
@@ -5367,7 +5368,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is not useful when information from one operation is required by
     the client to produce the next operation. In such cases, the client
-    must introduce a synchronization point and wait for a full client/server
+    would have to introduce a synchronization point and wait for a full client/server
     round-trip to get the results it needs. However, it's often possible to
     adjust the client design to exchange the required information server-side.
     Read-modify-write cycles are especially good candidates; for example:
@@ -5392,10 +5393,10 @@ UPDATE mytable SET x = x + 1 WHERE id = 42;
 
    <note>
     <para>
-     The pipeline API was introduced in PostgreSQL 14, but clients using
-     the PostgreSQL 14 version of <application>libpq</application> can use
-     pipelines on server versions 7.4 and newer. Pipeline mode works on any server
-     that supports the v3 extended query protocol.
+     The pipeline API was introduced in <productname>PostgreSQL</productname> 14.
+     Pipeline mode is a client-side feature which doesn't require server
+     support, and works on any server that supports the v3 extended query
+     protocol.
     </para>
    </note>
   </sect2>
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index 7ae7c14948..d7b036a35c 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -3803,7 +3803,7 @@ pqPipelineFlush(PGconn *conn)
 {
 	if ((conn->pipelineStatus == PQ_PIPELINE_OFF) ||
 		(conn->outCount >= OUTBUFFER_THRESHOLD))
-		return (pqFlush(conn));
+		return pqFlush(conn);
 	return 0;
 }
 
diff --git a/src/test/modules/test_libpq/pipeline.c b/src/test/modules/test_libpq/pipeline.c
index f4a2bdec57..01d5a9a8ff 100644
--- a/src/test/modules/test_libpq/pipeline.c
+++ b/src/test/modules/test_libpq/pipeline.c
@@ -126,7 +126,7 @@ test_simple_pipeline(PGconn *conn)
 	 * process the results of as they come in.
 	 *
 	 * For a simple case we should be able to do this without interim
-	 * processing of results since our out buffer will give us enough slush to
+	 * processing of results since our output buffer will give us enough slush to
 	 * work with and we won't block on sending. So blocking mode is fine.
 	 */
 	if (PQisnonblocking(conn))
@@ -603,7 +603,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 
 	/*
 	 * Now we start inserting. We'll be sending enough data that we could fill
-	 * our out buffer, so to avoid deadlocking we need to enter nonblocking
+	 * our output buffer, so to avoid deadlocking we need to enter nonblocking
 	 * mode and consume input while we send more output. As results of each
 	 * query are processed we should pop them to allow processing of the next
 	 * query. There's no need to finish the pipeline before processing
@@ -635,7 +635,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 		}
 
 		/*
-		 * Process any results, so we keep the server's out buffer free
+		 * Process any results, so we keep the server's output buffer free
 		 * flowing and it can continue to process input
 		 */
 		if (FD_ISSET(sock, &input_mask))
-- 
2.17.0


--oC1+HKm2/end4ao3--





^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* [PATCH 2/2] doc review
@ 2021-03-03 22:36  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 29+ messages in thread

From: Justin Pryzby @ 2021-03-03 22:36 UTC (permalink / raw)

---
 doc/src/sgml/libpq.sgml                | 67 +++++++++++++-------------
 src/interfaces/libpq/fe-exec.c         |  2 +-
 src/test/modules/test_libpq/pipeline.c |  6 +--
 3 files changed, 38 insertions(+), 37 deletions(-)

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index a34ecbb144..e2865a218b 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -3130,8 +3130,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_SYNC</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a point in a
-            pipeline where a synchronization point has been established.
+            The <structname>PGresult</structname> represents a
+            synchronization point in pipeline mode, requested by 
+            <xref linkend="libpq-PQsendPipeline"/>.
             This status occurs only when pipeline mode has been selected.
            </para>
           </listitem>
@@ -3141,9 +3142,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_ABORTED</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a pipeline that's
+            The <structname>PGresult</structname> represents a pipeline that has
             received an error from the server.  <function>PQgetResult</function>
-            must be called repeatedly, and it will return this status code,
+            must be called repeatedly, and each time it will return this status code
             until the end of the current pipeline, at which point it will return
             <literal>PGRES_PIPELINE_SYNC</literal> and normal processing can
             resume.
@@ -4953,7 +4954,7 @@ int PQflush(PGconn *conn);
    <title>Using Pipeline Mode</title>
 
    <para>
-    To issue pipelines the application must switch a connection into pipeline mode.
+    To issue pipelines, the application must switch a connection into pipeline mode.
     Enter pipeline mode with <xref linkend="libpq-PQenterPipelineMode"/>
     or test whether pipeline mode is active with
     <xref linkend="libpq-PQpipelineStatus"/>.
@@ -4975,7 +4976,7 @@ int PQflush(PGconn *conn);
         server will block trying to send results to the client from queries
         it has already processed. This only occurs when the client sends
         enough queries to fill both its output buffer and the server's receive
-        buffer before switching to processing input from the server,
+        buffer before it switches to processing input from the server,
         but it's hard to predict exactly when that will happen.
        </para>
       </footnote>
@@ -5025,7 +5026,7 @@ int PQflush(PGconn *conn);
     <title>Processing Results</title>
 
     <para>
-     To process the result of one pipeline query, the application calls
+     To process the result of one query in a pipeline, the application calls
      <function>PQgetResult</function> repeatedly and handles each result
      until <function>PQgetResult</function> returns null.
      The result from the next query in the pipeline may then be retrieved using
@@ -5057,10 +5058,10 @@ int PQflush(PGconn *conn);
      <type>PGresult</type> types <literal>PGRES_PIPELINE_SYNC</literal>
      and <literal>PGRES_PIPELINE_ABORTED</literal>.
      <literal>PGRES_PIPELINE_SYNC</literal> is reported exactly once for each
-     <function>PQsendPipeline</function> call at the corresponding point in
-     the result stream.
+     <function>PQsendPipeline</function> after retrieving results for all
+     queries in the pipeline.
      <literal>PGRES_PIPELINE_ABORTED</literal> is emitted in place of a normal
-     result stream result for the first error and all subsequent results
+     stream result for the first error and all subsequent results
      except <literal>PGRES_PIPELINE_SYNC</literal> and null;
      see <xref linkend="libpq-pipeline-errors"/>.
     </para>
@@ -5075,7 +5076,8 @@ int PQflush(PGconn *conn);
      application about the query currently being processed (except that
      <function>PQgetResult</function> returns null to indicate that we start
      returning the results of next query). The application must keep track
-     of the order in which it sent queries and the expected results.
+     of the order in which it sent queries, to associate them with their
+     corresponding results.
      Applications will typically use a state machine or a FIFO queue for this.
     </para>
 
@@ -5091,10 +5093,10 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     From the client perspective, after the client gets a
-     <literal>PGRES_FATAL_ERROR</literal> return from
-     <function>PQresultStatus</function> the pipeline is flagged as aborted.
-     <application>libpq</application> will report
+     From the client perspective, after <function>PQresultStatus</function>
+     returns <literal>PGRES_FATAL_ERROR</literal>,
+     the pipeline is flagged as aborted.
+     <function>PQresultStatus</function>, will report a
      <literal>PGRES_PIPELINE_ABORTED</literal> result for each remaining queued
      operation in an aborted pipeline. The result for
      <function>PQsendPipeline</function> is reported as
@@ -5108,8 +5110,8 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     If the pipeline used an implicit transaction then operations that have
-     already executed are rolled back and operations that were queued for after
+     If the pipeline used an implicit transaction, then operations that have
+     already executed are rolled back and operations that were queued to follow
      the failed operation are skipped entirely. The same behaviour holds if the
      pipeline starts and commits a single explicit transaction (i.e. the first
      statement is <literal>BEGIN</literal> and the last is
@@ -5145,11 +5147,11 @@ int PQflush(PGconn *conn);
 
     <para>
      The client application should generally maintain a queue of work
-     still to be dispatched and a queue of work that has been dispatched
+     remaining to be dispatched and a queue of work that has been dispatched
      but not yet had its results processed. When the socket is writable
      it should dispatch more work. When the socket is readable it should
      read results and process them, matching them up to the next entry in
-     its expected results queue.  Based on available memory, results from
+     its expected results queue.  Based on available memory, results from the
      socket should be read frequently: there's no need to wait until the
      pipeline end to read the results.  Pipelines should be scoped to logical
      units of work, usually (but not necessarily) one transaction per pipeline.
@@ -5191,8 +5193,8 @@ int PQflush(PGconn *conn);
 
      <listitem>
       <para>
-      Returns current pipeline mode status of the <application>libpq</application>
-      connection.
+      Returns the current pipeline mode status of the
+      <application>libpq</application> connection.
 <synopsis>
 PGpipelineStatus PQpipelineStatus(const PGconn *conn);
 </synopsis>
@@ -5233,11 +5235,10 @@ PGpipelineStatus PQpipelineStatus(const PGconn *conn);
          <listitem>
           <para>
            The <application>libpq</application> connection is in pipeline
-           mode and an error has occurred while processing the current
-           pipeline.
-           The aborted flag is cleared as soon as the result
-           of the <function>PQsendPipeline</function> at the end of the aborted
-           pipeline is processed. Clients don't usually need this function to
+           mode and an error occurred while processing the current pipeline.
+           The aborted flag is cleared when <function>PQresultStatus</function>
+           returns PGRES_PIPELINE_SYNC at the end of the pipeline.
+           Clients don't usually need this function to
            verify aborted status, as they can tell that the pipeline is aborted
            from the <literal>PGRES_PIPELINE_ABORTED</literal> result code.
           </para>
@@ -5328,7 +5329,7 @@ int PQsendPipeline(PGconn *conn);
        Returns 1 for success. Returns 0 if the connection is not in
        pipeline mode or sending a
        <link linkend="protocol-flow-ext-query">sync message</link>
-       is failed.
+       failed.
       </para>
      </listitem>
     </varlistentry>
@@ -5349,7 +5350,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is most useful when the server is distant, i.e., network latency
     (<quote>ping time</quote>) is high, and also when many small operations
-    are being performed in rapid sequence.  There is usually less benefit
+    are being performed in rapid succession.  There is usually less benefit
     in using pipelined commands when each query takes many multiples of the client/server
     round-trip time to execute.  A 100-statement operation run on a server
     300ms round-trip-time away would take 30 seconds in network latency alone
@@ -5367,7 +5368,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is not useful when information from one operation is required by
     the client to produce the next operation. In such cases, the client
-    must introduce a synchronization point and wait for a full client/server
+    would have to introduce a synchronization point and wait for a full client/server
     round-trip to get the results it needs. However, it's often possible to
     adjust the client design to exchange the required information server-side.
     Read-modify-write cycles are especially good candidates; for example:
@@ -5392,10 +5393,10 @@ UPDATE mytable SET x = x + 1 WHERE id = 42;
 
    <note>
     <para>
-     The pipeline API was introduced in PostgreSQL 14, but clients using
-     the PostgreSQL 14 version of <application>libpq</application> can use
-     pipelines on server versions 7.4 and newer. Pipeline mode works on any server
-     that supports the v3 extended query protocol.
+     The pipeline API was introduced in <productname>PostgreSQL</productname> 14.
+     Pipeline mode is a client-side feature which doesn't require server
+     support, and works on any server that supports the v3 extended query
+     protocol.
     </para>
    </note>
   </sect2>
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index 7ae7c14948..d7b036a35c 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -3803,7 +3803,7 @@ pqPipelineFlush(PGconn *conn)
 {
 	if ((conn->pipelineStatus == PQ_PIPELINE_OFF) ||
 		(conn->outCount >= OUTBUFFER_THRESHOLD))
-		return (pqFlush(conn));
+		return pqFlush(conn);
 	return 0;
 }
 
diff --git a/src/test/modules/test_libpq/pipeline.c b/src/test/modules/test_libpq/pipeline.c
index f4a2bdec57..01d5a9a8ff 100644
--- a/src/test/modules/test_libpq/pipeline.c
+++ b/src/test/modules/test_libpq/pipeline.c
@@ -126,7 +126,7 @@ test_simple_pipeline(PGconn *conn)
 	 * process the results of as they come in.
 	 *
 	 * For a simple case we should be able to do this without interim
-	 * processing of results since our out buffer will give us enough slush to
+	 * processing of results since our output buffer will give us enough slush to
 	 * work with and we won't block on sending. So blocking mode is fine.
 	 */
 	if (PQisnonblocking(conn))
@@ -603,7 +603,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 
 	/*
 	 * Now we start inserting. We'll be sending enough data that we could fill
-	 * our out buffer, so to avoid deadlocking we need to enter nonblocking
+	 * our output buffer, so to avoid deadlocking we need to enter nonblocking
 	 * mode and consume input while we send more output. As results of each
 	 * query are processed we should pop them to allow processing of the next
 	 * query. There's no need to finish the pipeline before processing
@@ -635,7 +635,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 		}
 
 		/*
-		 * Process any results, so we keep the server's out buffer free
+		 * Process any results, so we keep the server's output buffer free
 		 * flowing and it can continue to process input
 		 */
 		if (FD_ISSET(sock, &input_mask))
-- 
2.17.0


--oC1+HKm2/end4ao3--





^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* [PATCH 2/2] doc review
@ 2021-03-03 22:36  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 29+ messages in thread

From: Justin Pryzby @ 2021-03-03 22:36 UTC (permalink / raw)

---
 doc/src/sgml/libpq.sgml                | 67 +++++++++++++-------------
 src/interfaces/libpq/fe-exec.c         |  2 +-
 src/test/modules/test_libpq/pipeline.c |  6 +--
 3 files changed, 38 insertions(+), 37 deletions(-)

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index a34ecbb144..e2865a218b 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -3130,8 +3130,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_SYNC</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a point in a
-            pipeline where a synchronization point has been established.
+            The <structname>PGresult</structname> represents a
+            synchronization point in pipeline mode, requested by 
+            <xref linkend="libpq-PQsendPipeline"/>.
             This status occurs only when pipeline mode has been selected.
            </para>
           </listitem>
@@ -3141,9 +3142,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_ABORTED</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a pipeline that's
+            The <structname>PGresult</structname> represents a pipeline that has
             received an error from the server.  <function>PQgetResult</function>
-            must be called repeatedly, and it will return this status code,
+            must be called repeatedly, and each time it will return this status code
             until the end of the current pipeline, at which point it will return
             <literal>PGRES_PIPELINE_SYNC</literal> and normal processing can
             resume.
@@ -4953,7 +4954,7 @@ int PQflush(PGconn *conn);
    <title>Using Pipeline Mode</title>
 
    <para>
-    To issue pipelines the application must switch a connection into pipeline mode.
+    To issue pipelines, the application must switch a connection into pipeline mode.
     Enter pipeline mode with <xref linkend="libpq-PQenterPipelineMode"/>
     or test whether pipeline mode is active with
     <xref linkend="libpq-PQpipelineStatus"/>.
@@ -4975,7 +4976,7 @@ int PQflush(PGconn *conn);
         server will block trying to send results to the client from queries
         it has already processed. This only occurs when the client sends
         enough queries to fill both its output buffer and the server's receive
-        buffer before switching to processing input from the server,
+        buffer before it switches to processing input from the server,
         but it's hard to predict exactly when that will happen.
        </para>
       </footnote>
@@ -5025,7 +5026,7 @@ int PQflush(PGconn *conn);
     <title>Processing Results</title>
 
     <para>
-     To process the result of one pipeline query, the application calls
+     To process the result of one query in a pipeline, the application calls
      <function>PQgetResult</function> repeatedly and handles each result
      until <function>PQgetResult</function> returns null.
      The result from the next query in the pipeline may then be retrieved using
@@ -5057,10 +5058,10 @@ int PQflush(PGconn *conn);
      <type>PGresult</type> types <literal>PGRES_PIPELINE_SYNC</literal>
      and <literal>PGRES_PIPELINE_ABORTED</literal>.
      <literal>PGRES_PIPELINE_SYNC</literal> is reported exactly once for each
-     <function>PQsendPipeline</function> call at the corresponding point in
-     the result stream.
+     <function>PQsendPipeline</function> after retrieving results for all
+     queries in the pipeline.
      <literal>PGRES_PIPELINE_ABORTED</literal> is emitted in place of a normal
-     result stream result for the first error and all subsequent results
+     stream result for the first error and all subsequent results
      except <literal>PGRES_PIPELINE_SYNC</literal> and null;
      see <xref linkend="libpq-pipeline-errors"/>.
     </para>
@@ -5075,7 +5076,8 @@ int PQflush(PGconn *conn);
      application about the query currently being processed (except that
      <function>PQgetResult</function> returns null to indicate that we start
      returning the results of next query). The application must keep track
-     of the order in which it sent queries and the expected results.
+     of the order in which it sent queries, to associate them with their
+     corresponding results.
      Applications will typically use a state machine or a FIFO queue for this.
     </para>
 
@@ -5091,10 +5093,10 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     From the client perspective, after the client gets a
-     <literal>PGRES_FATAL_ERROR</literal> return from
-     <function>PQresultStatus</function> the pipeline is flagged as aborted.
-     <application>libpq</application> will report
+     From the client perspective, after <function>PQresultStatus</function>
+     returns <literal>PGRES_FATAL_ERROR</literal>,
+     the pipeline is flagged as aborted.
+     <function>PQresultStatus</function>, will report a
      <literal>PGRES_PIPELINE_ABORTED</literal> result for each remaining queued
      operation in an aborted pipeline. The result for
      <function>PQsendPipeline</function> is reported as
@@ -5108,8 +5110,8 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     If the pipeline used an implicit transaction then operations that have
-     already executed are rolled back and operations that were queued for after
+     If the pipeline used an implicit transaction, then operations that have
+     already executed are rolled back and operations that were queued to follow
      the failed operation are skipped entirely. The same behaviour holds if the
      pipeline starts and commits a single explicit transaction (i.e. the first
      statement is <literal>BEGIN</literal> and the last is
@@ -5145,11 +5147,11 @@ int PQflush(PGconn *conn);
 
     <para>
      The client application should generally maintain a queue of work
-     still to be dispatched and a queue of work that has been dispatched
+     remaining to be dispatched and a queue of work that has been dispatched
      but not yet had its results processed. When the socket is writable
      it should dispatch more work. When the socket is readable it should
      read results and process them, matching them up to the next entry in
-     its expected results queue.  Based on available memory, results from
+     its expected results queue.  Based on available memory, results from the
      socket should be read frequently: there's no need to wait until the
      pipeline end to read the results.  Pipelines should be scoped to logical
      units of work, usually (but not necessarily) one transaction per pipeline.
@@ -5191,8 +5193,8 @@ int PQflush(PGconn *conn);
 
      <listitem>
       <para>
-      Returns current pipeline mode status of the <application>libpq</application>
-      connection.
+      Returns the current pipeline mode status of the
+      <application>libpq</application> connection.
 <synopsis>
 PGpipelineStatus PQpipelineStatus(const PGconn *conn);
 </synopsis>
@@ -5233,11 +5235,10 @@ PGpipelineStatus PQpipelineStatus(const PGconn *conn);
          <listitem>
           <para>
            The <application>libpq</application> connection is in pipeline
-           mode and an error has occurred while processing the current
-           pipeline.
-           The aborted flag is cleared as soon as the result
-           of the <function>PQsendPipeline</function> at the end of the aborted
-           pipeline is processed. Clients don't usually need this function to
+           mode and an error occurred while processing the current pipeline.
+           The aborted flag is cleared when <function>PQresultStatus</function>
+           returns PGRES_PIPELINE_SYNC at the end of the pipeline.
+           Clients don't usually need this function to
            verify aborted status, as they can tell that the pipeline is aborted
            from the <literal>PGRES_PIPELINE_ABORTED</literal> result code.
           </para>
@@ -5328,7 +5329,7 @@ int PQsendPipeline(PGconn *conn);
        Returns 1 for success. Returns 0 if the connection is not in
        pipeline mode or sending a
        <link linkend="protocol-flow-ext-query">sync message</link>
-       is failed.
+       failed.
       </para>
      </listitem>
     </varlistentry>
@@ -5349,7 +5350,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is most useful when the server is distant, i.e., network latency
     (<quote>ping time</quote>) is high, and also when many small operations
-    are being performed in rapid sequence.  There is usually less benefit
+    are being performed in rapid succession.  There is usually less benefit
     in using pipelined commands when each query takes many multiples of the client/server
     round-trip time to execute.  A 100-statement operation run on a server
     300ms round-trip-time away would take 30 seconds in network latency alone
@@ -5367,7 +5368,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is not useful when information from one operation is required by
     the client to produce the next operation. In such cases, the client
-    must introduce a synchronization point and wait for a full client/server
+    would have to introduce a synchronization point and wait for a full client/server
     round-trip to get the results it needs. However, it's often possible to
     adjust the client design to exchange the required information server-side.
     Read-modify-write cycles are especially good candidates; for example:
@@ -5392,10 +5393,10 @@ UPDATE mytable SET x = x + 1 WHERE id = 42;
 
    <note>
     <para>
-     The pipeline API was introduced in PostgreSQL 14, but clients using
-     the PostgreSQL 14 version of <application>libpq</application> can use
-     pipelines on server versions 7.4 and newer. Pipeline mode works on any server
-     that supports the v3 extended query protocol.
+     The pipeline API was introduced in <productname>PostgreSQL</productname> 14.
+     Pipeline mode is a client-side feature which doesn't require server
+     support, and works on any server that supports the v3 extended query
+     protocol.
     </para>
    </note>
   </sect2>
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index 7ae7c14948..d7b036a35c 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -3803,7 +3803,7 @@ pqPipelineFlush(PGconn *conn)
 {
 	if ((conn->pipelineStatus == PQ_PIPELINE_OFF) ||
 		(conn->outCount >= OUTBUFFER_THRESHOLD))
-		return (pqFlush(conn));
+		return pqFlush(conn);
 	return 0;
 }
 
diff --git a/src/test/modules/test_libpq/pipeline.c b/src/test/modules/test_libpq/pipeline.c
index f4a2bdec57..01d5a9a8ff 100644
--- a/src/test/modules/test_libpq/pipeline.c
+++ b/src/test/modules/test_libpq/pipeline.c
@@ -126,7 +126,7 @@ test_simple_pipeline(PGconn *conn)
 	 * process the results of as they come in.
 	 *
 	 * For a simple case we should be able to do this without interim
-	 * processing of results since our out buffer will give us enough slush to
+	 * processing of results since our output buffer will give us enough slush to
 	 * work with and we won't block on sending. So blocking mode is fine.
 	 */
 	if (PQisnonblocking(conn))
@@ -603,7 +603,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 
 	/*
 	 * Now we start inserting. We'll be sending enough data that we could fill
-	 * our out buffer, so to avoid deadlocking we need to enter nonblocking
+	 * our output buffer, so to avoid deadlocking we need to enter nonblocking
 	 * mode and consume input while we send more output. As results of each
 	 * query are processed we should pop them to allow processing of the next
 	 * query. There's no need to finish the pipeline before processing
@@ -635,7 +635,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 		}
 
 		/*
-		 * Process any results, so we keep the server's out buffer free
+		 * Process any results, so we keep the server's output buffer free
 		 * flowing and it can continue to process input
 		 */
 		if (FD_ISSET(sock, &input_mask))
-- 
2.17.0


--oC1+HKm2/end4ao3--





^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* [PATCH 2/2] doc review
@ 2021-03-03 22:36  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 29+ messages in thread

From: Justin Pryzby @ 2021-03-03 22:36 UTC (permalink / raw)

---
 doc/src/sgml/libpq.sgml                | 67 +++++++++++++-------------
 src/interfaces/libpq/fe-exec.c         |  2 +-
 src/test/modules/test_libpq/pipeline.c |  6 +--
 3 files changed, 38 insertions(+), 37 deletions(-)

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index a34ecbb144..e2865a218b 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -3130,8 +3130,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_SYNC</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a point in a
-            pipeline where a synchronization point has been established.
+            The <structname>PGresult</structname> represents a
+            synchronization point in pipeline mode, requested by 
+            <xref linkend="libpq-PQsendPipeline"/>.
             This status occurs only when pipeline mode has been selected.
            </para>
           </listitem>
@@ -3141,9 +3142,9 @@ ExecStatusType PQresultStatus(const PGresult *res);
           <term><literal>PGRES_PIPELINE_ABORTED</literal></term>
           <listitem>
            <para>
-            The <structname>PGresult</structname> represents a pipeline that's
+            The <structname>PGresult</structname> represents a pipeline that has
             received an error from the server.  <function>PQgetResult</function>
-            must be called repeatedly, and it will return this status code,
+            must be called repeatedly, and each time it will return this status code
             until the end of the current pipeline, at which point it will return
             <literal>PGRES_PIPELINE_SYNC</literal> and normal processing can
             resume.
@@ -4953,7 +4954,7 @@ int PQflush(PGconn *conn);
    <title>Using Pipeline Mode</title>
 
    <para>
-    To issue pipelines the application must switch a connection into pipeline mode.
+    To issue pipelines, the application must switch a connection into pipeline mode.
     Enter pipeline mode with <xref linkend="libpq-PQenterPipelineMode"/>
     or test whether pipeline mode is active with
     <xref linkend="libpq-PQpipelineStatus"/>.
@@ -4975,7 +4976,7 @@ int PQflush(PGconn *conn);
         server will block trying to send results to the client from queries
         it has already processed. This only occurs when the client sends
         enough queries to fill both its output buffer and the server's receive
-        buffer before switching to processing input from the server,
+        buffer before it switches to processing input from the server,
         but it's hard to predict exactly when that will happen.
        </para>
       </footnote>
@@ -5025,7 +5026,7 @@ int PQflush(PGconn *conn);
     <title>Processing Results</title>
 
     <para>
-     To process the result of one pipeline query, the application calls
+     To process the result of one query in a pipeline, the application calls
      <function>PQgetResult</function> repeatedly and handles each result
      until <function>PQgetResult</function> returns null.
      The result from the next query in the pipeline may then be retrieved using
@@ -5057,10 +5058,10 @@ int PQflush(PGconn *conn);
      <type>PGresult</type> types <literal>PGRES_PIPELINE_SYNC</literal>
      and <literal>PGRES_PIPELINE_ABORTED</literal>.
      <literal>PGRES_PIPELINE_SYNC</literal> is reported exactly once for each
-     <function>PQsendPipeline</function> call at the corresponding point in
-     the result stream.
+     <function>PQsendPipeline</function> after retrieving results for all
+     queries in the pipeline.
      <literal>PGRES_PIPELINE_ABORTED</literal> is emitted in place of a normal
-     result stream result for the first error and all subsequent results
+     stream result for the first error and all subsequent results
      except <literal>PGRES_PIPELINE_SYNC</literal> and null;
      see <xref linkend="libpq-pipeline-errors"/>.
     </para>
@@ -5075,7 +5076,8 @@ int PQflush(PGconn *conn);
      application about the query currently being processed (except that
      <function>PQgetResult</function> returns null to indicate that we start
      returning the results of next query). The application must keep track
-     of the order in which it sent queries and the expected results.
+     of the order in which it sent queries, to associate them with their
+     corresponding results.
      Applications will typically use a state machine or a FIFO queue for this.
     </para>
 
@@ -5091,10 +5093,10 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     From the client perspective, after the client gets a
-     <literal>PGRES_FATAL_ERROR</literal> return from
-     <function>PQresultStatus</function> the pipeline is flagged as aborted.
-     <application>libpq</application> will report
+     From the client perspective, after <function>PQresultStatus</function>
+     returns <literal>PGRES_FATAL_ERROR</literal>,
+     the pipeline is flagged as aborted.
+     <function>PQresultStatus</function>, will report a
      <literal>PGRES_PIPELINE_ABORTED</literal> result for each remaining queued
      operation in an aborted pipeline. The result for
      <function>PQsendPipeline</function> is reported as
@@ -5108,8 +5110,8 @@ int PQflush(PGconn *conn);
     </para>
 
     <para>
-     If the pipeline used an implicit transaction then operations that have
-     already executed are rolled back and operations that were queued for after
+     If the pipeline used an implicit transaction, then operations that have
+     already executed are rolled back and operations that were queued to follow
      the failed operation are skipped entirely. The same behaviour holds if the
      pipeline starts and commits a single explicit transaction (i.e. the first
      statement is <literal>BEGIN</literal> and the last is
@@ -5145,11 +5147,11 @@ int PQflush(PGconn *conn);
 
     <para>
      The client application should generally maintain a queue of work
-     still to be dispatched and a queue of work that has been dispatched
+     remaining to be dispatched and a queue of work that has been dispatched
      but not yet had its results processed. When the socket is writable
      it should dispatch more work. When the socket is readable it should
      read results and process them, matching them up to the next entry in
-     its expected results queue.  Based on available memory, results from
+     its expected results queue.  Based on available memory, results from the
      socket should be read frequently: there's no need to wait until the
      pipeline end to read the results.  Pipelines should be scoped to logical
      units of work, usually (but not necessarily) one transaction per pipeline.
@@ -5191,8 +5193,8 @@ int PQflush(PGconn *conn);
 
      <listitem>
       <para>
-      Returns current pipeline mode status of the <application>libpq</application>
-      connection.
+      Returns the current pipeline mode status of the
+      <application>libpq</application> connection.
 <synopsis>
 PGpipelineStatus PQpipelineStatus(const PGconn *conn);
 </synopsis>
@@ -5233,11 +5235,10 @@ PGpipelineStatus PQpipelineStatus(const PGconn *conn);
          <listitem>
           <para>
            The <application>libpq</application> connection is in pipeline
-           mode and an error has occurred while processing the current
-           pipeline.
-           The aborted flag is cleared as soon as the result
-           of the <function>PQsendPipeline</function> at the end of the aborted
-           pipeline is processed. Clients don't usually need this function to
+           mode and an error occurred while processing the current pipeline.
+           The aborted flag is cleared when <function>PQresultStatus</function>
+           returns PGRES_PIPELINE_SYNC at the end of the pipeline.
+           Clients don't usually need this function to
            verify aborted status, as they can tell that the pipeline is aborted
            from the <literal>PGRES_PIPELINE_ABORTED</literal> result code.
           </para>
@@ -5328,7 +5329,7 @@ int PQsendPipeline(PGconn *conn);
        Returns 1 for success. Returns 0 if the connection is not in
        pipeline mode or sending a
        <link linkend="protocol-flow-ext-query">sync message</link>
-       is failed.
+       failed.
       </para>
      </listitem>
     </varlistentry>
@@ -5349,7 +5350,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is most useful when the server is distant, i.e., network latency
     (<quote>ping time</quote>) is high, and also when many small operations
-    are being performed in rapid sequence.  There is usually less benefit
+    are being performed in rapid succession.  There is usually less benefit
     in using pipelined commands when each query takes many multiples of the client/server
     round-trip time to execute.  A 100-statement operation run on a server
     300ms round-trip-time away would take 30 seconds in network latency alone
@@ -5367,7 +5368,7 @@ int PQsendPipeline(PGconn *conn);
    <para>
     Pipeline mode is not useful when information from one operation is required by
     the client to produce the next operation. In such cases, the client
-    must introduce a synchronization point and wait for a full client/server
+    would have to introduce a synchronization point and wait for a full client/server
     round-trip to get the results it needs. However, it's often possible to
     adjust the client design to exchange the required information server-side.
     Read-modify-write cycles are especially good candidates; for example:
@@ -5392,10 +5393,10 @@ UPDATE mytable SET x = x + 1 WHERE id = 42;
 
    <note>
     <para>
-     The pipeline API was introduced in PostgreSQL 14, but clients using
-     the PostgreSQL 14 version of <application>libpq</application> can use
-     pipelines on server versions 7.4 and newer. Pipeline mode works on any server
-     that supports the v3 extended query protocol.
+     The pipeline API was introduced in <productname>PostgreSQL</productname> 14.
+     Pipeline mode is a client-side feature which doesn't require server
+     support, and works on any server that supports the v3 extended query
+     protocol.
     </para>
    </note>
   </sect2>
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index 7ae7c14948..d7b036a35c 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -3803,7 +3803,7 @@ pqPipelineFlush(PGconn *conn)
 {
 	if ((conn->pipelineStatus == PQ_PIPELINE_OFF) ||
 		(conn->outCount >= OUTBUFFER_THRESHOLD))
-		return (pqFlush(conn));
+		return pqFlush(conn);
 	return 0;
 }
 
diff --git a/src/test/modules/test_libpq/pipeline.c b/src/test/modules/test_libpq/pipeline.c
index f4a2bdec57..01d5a9a8ff 100644
--- a/src/test/modules/test_libpq/pipeline.c
+++ b/src/test/modules/test_libpq/pipeline.c
@@ -126,7 +126,7 @@ test_simple_pipeline(PGconn *conn)
 	 * process the results of as they come in.
 	 *
 	 * For a simple case we should be able to do this without interim
-	 * processing of results since our out buffer will give us enough slush to
+	 * processing of results since our output buffer will give us enough slush to
 	 * work with and we won't block on sending. So blocking mode is fine.
 	 */
 	if (PQisnonblocking(conn))
@@ -603,7 +603,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 
 	/*
 	 * Now we start inserting. We'll be sending enough data that we could fill
-	 * our out buffer, so to avoid deadlocking we need to enter nonblocking
+	 * our output buffer, so to avoid deadlocking we need to enter nonblocking
 	 * mode and consume input while we send more output. As results of each
 	 * query are processed we should pop them to allow processing of the next
 	 * query. There's no need to finish the pipeline before processing
@@ -635,7 +635,7 @@ test_pipelined_insert(PGconn *conn, int n_rows)
 		}
 
 		/*
-		 * Process any results, so we keep the server's out buffer free
+		 * Process any results, so we keep the server's output buffer free
 		 * flowing and it can continue to process input
 		 */
 		if (FD_ISSET(sock, &input_mask))
-- 
2.17.0


--oC1+HKm2/end4ao3--





^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Fix propagation of persistence to sequences in ALTER TABLE / ADD COLUMN
@ 2024-02-05 15:51  Peter Eisentraut <[email protected]>
  0 siblings, 1 reply; 29+ messages in thread

From: Peter Eisentraut @ 2024-02-05 15:51 UTC (permalink / raw)
  To: pgsql-hackers

Commit 344d62fb9a9 (2022) introduced unlogged sequences and made it so 
that identity/serial sequences automatically get the persistence level 
of their owning table.  But this works only for CREATE TABLE and not for 
ALTER TABLE / ADD COLUMN.  This patch fixes that.  (should be 
backpatched to 15, 16)
From a3cb389a3aaaea8df9371ef389d9d61ecede3713 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <[email protected]>
Date: Mon, 5 Feb 2024 11:22:01 +0100
Subject: [PATCH] Fix propagation of persistence to sequences in ALTER TABLE /
 ADD COLUMN

Fix for 344d62fb9a9: That commit introduced unlogged sequences and
made it so that identity/serial sequences automatically get the
persistence level of their owning table.  But this works only for
CREATE TABLE and not for ALTER TABLE / ADD COLUMN.  This is fixed
here.

TODO: backpatch to 15, 16
---
 src/backend/parser/parse_utilcmd.c     | 11 ++++++++++-
 src/test/regress/expected/identity.out | 17 +++++++++++++++++
 src/test/regress/sql/identity.sql      |  6 ++++++
 3 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index 56ac4f516ea..c7efd8d8cee 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -459,7 +459,16 @@ generateSerialExtraStmts(CreateStmtContext *cxt, ColumnDef *column,
 	seqstmt = makeNode(CreateSeqStmt);
 	seqstmt->for_identity = for_identity;
 	seqstmt->sequence = makeRangeVar(snamespace, sname, -1);
-	seqstmt->sequence->relpersistence = cxt->relation->relpersistence;
+
+	/*
+	 * Copy the persistence of the table.  For CREATE TABLE, we get the
+	 * persistence from cxt->relation, which comes from the CreateStmt in
+	 * progress.  For ALTER TABLE, the parser won't set
+	 * cxt->relation->relpersistence, but we have cxt->rel as the existing
+	 * table, so we copy the persistence from there.
+	 */
+	seqstmt->sequence->relpersistence = cxt->rel ? cxt->rel->rd_rel->relpersistence : cxt->relation->relpersistence;
+
 	seqstmt->options = seqoptions;
 
 	/*
diff --git a/src/test/regress/expected/identity.out b/src/test/regress/expected/identity.out
index 08f95674ca8..84b59dca13f 100644
--- a/src/test/regress/expected/identity.out
+++ b/src/test/regress/expected/identity.out
@@ -365,6 +365,23 @@ SELECT seqtypid::regtype FROM pg_sequence WHERE seqrelid = 'itest3_a_seq'::regcl
 
 ALTER TABLE itest3 ALTER COLUMN a TYPE text;  -- error
 ERROR:  identity column type must be smallint, integer, or bigint
+-- check that unlogged propagates to sequence
+CREATE UNLOGGED TABLE itest17 (a int NOT NULL, b text);
+ALTER TABLE itest17 ALTER COLUMN a ADD GENERATED ALWAYS AS IDENTITY;
+\d itest17
+                    Unlogged table "public.itest17"
+ Column |  Type   | Collation | Nullable |           Default            
+--------+---------+-----------+----------+------------------------------
+ a      | integer |           | not null | generated always as identity
+ b      | text    |           |          | 
+
+\d itest17_a_seq
+               Unlogged sequence "public.itest17_a_seq"
+  Type   | Start | Minimum |  Maximum   | Increment | Cycles? | Cache 
+---------+-------+---------+------------+-----------+---------+-------
+ integer |     1 |       1 | 2147483647 |         1 | no      |     1
+Sequence for identity column: public.itest17.a
+
 -- kinda silly to change property in the same command, but it should work
 ALTER TABLE itest3
   ADD COLUMN c int GENERATED BY DEFAULT AS IDENTITY,
diff --git a/src/test/regress/sql/identity.sql b/src/test/regress/sql/identity.sql
index 9f35214751c..7596f0a36f8 100644
--- a/src/test/regress/sql/identity.sql
+++ b/src/test/regress/sql/identity.sql
@@ -214,6 +214,12 @@ CREATE TABLE itest5 (a serial, b text);
 
 ALTER TABLE itest3 ALTER COLUMN a TYPE text;  -- error
 
+-- check that unlogged propagates to sequence
+CREATE UNLOGGED TABLE itest17 (a int NOT NULL, b text);
+ALTER TABLE itest17 ALTER COLUMN a ADD GENERATED ALWAYS AS IDENTITY;
+\d itest17
+\d itest17_a_seq
+
 -- kinda silly to change property in the same command, but it should work
 ALTER TABLE itest3
   ADD COLUMN c int GENERATED BY DEFAULT AS IDENTITY,
-- 
2.43.0



Attachments:

  [text/plain] 0001-Fix-propagation-of-persistence-to-sequences-in-ALTER.patch (3.8K, ../../[email protected]/2-0001-Fix-propagation-of-persistence-to-sequences-in-ALTER.patch)
  download | inline diff:
From a3cb389a3aaaea8df9371ef389d9d61ecede3713 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <[email protected]>
Date: Mon, 5 Feb 2024 11:22:01 +0100
Subject: [PATCH] Fix propagation of persistence to sequences in ALTER TABLE /
 ADD COLUMN

Fix for 344d62fb9a9: That commit introduced unlogged sequences and
made it so that identity/serial sequences automatically get the
persistence level of their owning table.  But this works only for
CREATE TABLE and not for ALTER TABLE / ADD COLUMN.  This is fixed
here.

TODO: backpatch to 15, 16
---
 src/backend/parser/parse_utilcmd.c     | 11 ++++++++++-
 src/test/regress/expected/identity.out | 17 +++++++++++++++++
 src/test/regress/sql/identity.sql      |  6 ++++++
 3 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index 56ac4f516ea..c7efd8d8cee 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -459,7 +459,16 @@ generateSerialExtraStmts(CreateStmtContext *cxt, ColumnDef *column,
 	seqstmt = makeNode(CreateSeqStmt);
 	seqstmt->for_identity = for_identity;
 	seqstmt->sequence = makeRangeVar(snamespace, sname, -1);
-	seqstmt->sequence->relpersistence = cxt->relation->relpersistence;
+
+	/*
+	 * Copy the persistence of the table.  For CREATE TABLE, we get the
+	 * persistence from cxt->relation, which comes from the CreateStmt in
+	 * progress.  For ALTER TABLE, the parser won't set
+	 * cxt->relation->relpersistence, but we have cxt->rel as the existing
+	 * table, so we copy the persistence from there.
+	 */
+	seqstmt->sequence->relpersistence = cxt->rel ? cxt->rel->rd_rel->relpersistence : cxt->relation->relpersistence;
+
 	seqstmt->options = seqoptions;
 
 	/*
diff --git a/src/test/regress/expected/identity.out b/src/test/regress/expected/identity.out
index 08f95674ca8..84b59dca13f 100644
--- a/src/test/regress/expected/identity.out
+++ b/src/test/regress/expected/identity.out
@@ -365,6 +365,23 @@ SELECT seqtypid::regtype FROM pg_sequence WHERE seqrelid = 'itest3_a_seq'::regcl
 
 ALTER TABLE itest3 ALTER COLUMN a TYPE text;  -- error
 ERROR:  identity column type must be smallint, integer, or bigint
+-- check that unlogged propagates to sequence
+CREATE UNLOGGED TABLE itest17 (a int NOT NULL, b text);
+ALTER TABLE itest17 ALTER COLUMN a ADD GENERATED ALWAYS AS IDENTITY;
+\d itest17
+                    Unlogged table "public.itest17"
+ Column |  Type   | Collation | Nullable |           Default            
+--------+---------+-----------+----------+------------------------------
+ a      | integer |           | not null | generated always as identity
+ b      | text    |           |          | 
+
+\d itest17_a_seq
+               Unlogged sequence "public.itest17_a_seq"
+  Type   | Start | Minimum |  Maximum   | Increment | Cycles? | Cache 
+---------+-------+---------+------------+-----------+---------+-------
+ integer |     1 |       1 | 2147483647 |         1 | no      |     1
+Sequence for identity column: public.itest17.a
+
 -- kinda silly to change property in the same command, but it should work
 ALTER TABLE itest3
   ADD COLUMN c int GENERATED BY DEFAULT AS IDENTITY,
diff --git a/src/test/regress/sql/identity.sql b/src/test/regress/sql/identity.sql
index 9f35214751c..7596f0a36f8 100644
--- a/src/test/regress/sql/identity.sql
+++ b/src/test/regress/sql/identity.sql
@@ -214,6 +214,12 @@ CREATE TABLE itest5 (a serial, b text);
 
 ALTER TABLE itest3 ALTER COLUMN a TYPE text;  -- error
 
+-- check that unlogged propagates to sequence
+CREATE UNLOGGED TABLE itest17 (a int NOT NULL, b text);
+ALTER TABLE itest17 ALTER COLUMN a ADD GENERATED ALWAYS AS IDENTITY;
+\d itest17
+\d itest17_a_seq
+
 -- kinda silly to change property in the same command, but it should work
 ALTER TABLE itest3
   ADD COLUMN c int GENERATED BY DEFAULT AS IDENTITY,
-- 
2.43.0



^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: Fix propagation of persistence to sequences in ALTER TABLE / ADD COLUMN
@ 2024-02-08 06:04  Ashutosh Bapat <[email protected]>
  parent: Peter Eisentraut <[email protected]>
  0 siblings, 1 reply; 29+ messages in thread

From: Ashutosh Bapat @ 2024-02-08 06:04 UTC (permalink / raw)
  To: Peter Eisentraut <[email protected]>; +Cc: pgsql-hackers

On Mon, Feb 5, 2024 at 9:21 PM Peter Eisentraut <[email protected]> wrote:
>
> Commit 344d62fb9a9 (2022) introduced unlogged sequences and made it so
> that identity/serial sequences automatically get the persistence level
> of their owning table.  But this works only for CREATE TABLE and not for
> ALTER TABLE / ADD COLUMN.  This patch fixes that.  (should be
> backpatched to 15, 16)

The patch looks ok.

+    seqstmt->sequence->relpersistence = cxt->rel ?
cxt->rel->rd_rel->relpersistence : cxt->relation->relpersistence;
+

This condition looks consistent with the other places in the code
around line 435, 498. But I was worried that cxt->rel may not get
latest relpersistence if the ALTER TABLE changes persistence as well.
Added a test (0002) which shows that ctx->rel has up-to-date
relpersistence. Also added a few other tests. Feel free to
include/reject them while committing.

0001 - same as your patch
0002 - additional tests

-- 
Best Wishes,
Ashutosh Bapat


Attachments:

  [text/x-patch] 0001-Fix-propagation-of-persistence-to-sequences-20240208.patch (3.8K, ../../CAExHW5vfiOczkiABV8p6MvsnZi45_3kZmUhg49uoaAq1PGOc1Q@mail.gmail.com/2-0001-Fix-propagation-of-persistence-to-sequences-20240208.patch)
  download | inline diff:
From c142bfc5ec8b3c9c5a01f48693118d132145b45b Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <[email protected]>
Date: Mon, 5 Feb 2024 11:22:01 +0100
Subject: [PATCH 1/2] Fix propagation of persistence to sequences in ALTER
 TABLE / ADD COLUMN

Fix for 344d62fb9a9: That commit introduced unlogged sequences and
made it so that identity/serial sequences automatically get the
persistence level of their owning table.  But this works only for
CREATE TABLE and not for ALTER TABLE / ADD COLUMN.  This is fixed
here.

TODO: backpatch to 15, 16
---
 src/backend/parser/parse_utilcmd.c     | 11 ++++++++++-
 src/test/regress/expected/identity.out | 17 +++++++++++++++++
 src/test/regress/sql/identity.sql      |  6 ++++++
 3 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index 56ac4f516e..c7efd8d8ce 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -459,7 +459,16 @@ generateSerialExtraStmts(CreateStmtContext *cxt, ColumnDef *column,
 	seqstmt = makeNode(CreateSeqStmt);
 	seqstmt->for_identity = for_identity;
 	seqstmt->sequence = makeRangeVar(snamespace, sname, -1);
-	seqstmt->sequence->relpersistence = cxt->relation->relpersistence;
+
+	/*
+	 * Copy the persistence of the table.  For CREATE TABLE, we get the
+	 * persistence from cxt->relation, which comes from the CreateStmt in
+	 * progress.  For ALTER TABLE, the parser won't set
+	 * cxt->relation->relpersistence, but we have cxt->rel as the existing
+	 * table, so we copy the persistence from there.
+	 */
+	seqstmt->sequence->relpersistence = cxt->rel ? cxt->rel->rd_rel->relpersistence : cxt->relation->relpersistence;
+
 	seqstmt->options = seqoptions;
 
 	/*
diff --git a/src/test/regress/expected/identity.out b/src/test/regress/expected/identity.out
index 08f95674ca..84b59dca13 100644
--- a/src/test/regress/expected/identity.out
+++ b/src/test/regress/expected/identity.out
@@ -365,6 +365,23 @@ SELECT seqtypid::regtype FROM pg_sequence WHERE seqrelid = 'itest3_a_seq'::regcl
 
 ALTER TABLE itest3 ALTER COLUMN a TYPE text;  -- error
 ERROR:  identity column type must be smallint, integer, or bigint
+-- check that unlogged propagates to sequence
+CREATE UNLOGGED TABLE itest17 (a int NOT NULL, b text);
+ALTER TABLE itest17 ALTER COLUMN a ADD GENERATED ALWAYS AS IDENTITY;
+\d itest17
+                    Unlogged table "public.itest17"
+ Column |  Type   | Collation | Nullable |           Default            
+--------+---------+-----------+----------+------------------------------
+ a      | integer |           | not null | generated always as identity
+ b      | text    |           |          | 
+
+\d itest17_a_seq
+               Unlogged sequence "public.itest17_a_seq"
+  Type   | Start | Minimum |  Maximum   | Increment | Cycles? | Cache 
+---------+-------+---------+------------+-----------+---------+-------
+ integer |     1 |       1 | 2147483647 |         1 | no      |     1
+Sequence for identity column: public.itest17.a
+
 -- kinda silly to change property in the same command, but it should work
 ALTER TABLE itest3
   ADD COLUMN c int GENERATED BY DEFAULT AS IDENTITY,
diff --git a/src/test/regress/sql/identity.sql b/src/test/regress/sql/identity.sql
index 9f35214751..7596f0a36f 100644
--- a/src/test/regress/sql/identity.sql
+++ b/src/test/regress/sql/identity.sql
@@ -214,6 +214,12 @@ SELECT seqtypid::regtype FROM pg_sequence WHERE seqrelid = 'itest3_a_seq'::regcl
 
 ALTER TABLE itest3 ALTER COLUMN a TYPE text;  -- error
 
+-- check that unlogged propagates to sequence
+CREATE UNLOGGED TABLE itest17 (a int NOT NULL, b text);
+ALTER TABLE itest17 ALTER COLUMN a ADD GENERATED ALWAYS AS IDENTITY;
+\d itest17
+\d itest17_a_seq
+
 -- kinda silly to change property in the same command, but it should work
 ALTER TABLE itest3
   ADD COLUMN c int GENERATED BY DEFAULT AS IDENTITY,
-- 
2.25.1



  [text/x-patch] 0002-Additional-tests-20240208.patch (5.1K, ../../CAExHW5vfiOczkiABV8p6MvsnZi45_3kZmUhg49uoaAq1PGOc1Q@mail.gmail.com/3-0002-Additional-tests-20240208.patch)
  download | inline diff:
From a29aaa16cda9ee70829012a676a14c556cf236c5 Mon Sep 17 00:00:00 2001
From: Ashutosh Bapat <[email protected]>
Date: Thu, 8 Feb 2024 11:26:00 +0530
Subject: [PATCH 2/2] Additional tests.

---
 src/test/regress/expected/identity.out | 55 ++++++++++++++++++++++++++
 src/test/regress/sql/identity.sql      | 12 ++++++
 2 files changed, 67 insertions(+)

diff --git a/src/test/regress/expected/identity.out b/src/test/regress/expected/identity.out
index 84b59dca13..4c45837f66 100644
--- a/src/test/regress/expected/identity.out
+++ b/src/test/regress/expected/identity.out
@@ -368,12 +368,16 @@ ERROR:  identity column type must be smallint, integer, or bigint
 -- check that unlogged propagates to sequence
 CREATE UNLOGGED TABLE itest17 (a int NOT NULL, b text);
 ALTER TABLE itest17 ALTER COLUMN a ADD GENERATED ALWAYS AS IDENTITY;
+ALTER TABLE itest17 ADD COLUMN c int GENERATED ALWAYS AS IDENTITY;
+CREATE TABLE itest18 (a int NOT NULL, b text);
+ALTER TABLE itest18 SET UNLOGGED, ALTER COLUMN a ADD GENERATED ALWAYS AS IDENTITY;
 \d itest17
                     Unlogged table "public.itest17"
  Column |  Type   | Collation | Nullable |           Default            
 --------+---------+-----------+----------+------------------------------
  a      | integer |           | not null | generated always as identity
  b      | text    |           |          | 
+ c      | integer |           | not null | generated always as identity
 
 \d itest17_a_seq
                Unlogged sequence "public.itest17_a_seq"
@@ -382,6 +386,57 @@ ALTER TABLE itest17 ALTER COLUMN a ADD GENERATED ALWAYS AS IDENTITY;
  integer |     1 |       1 | 2147483647 |         1 | no      |     1
 Sequence for identity column: public.itest17.a
 
+\d itest17_c_seq
+               Unlogged sequence "public.itest17_c_seq"
+  Type   | Start | Minimum |  Maximum   | Increment | Cycles? | Cache 
+---------+-------+---------+------------+-----------+---------+-------
+ integer |     1 |       1 | 2147483647 |         1 | no      |     1
+Sequence for identity column: public.itest17.c
+
+\d itest18
+                    Unlogged table "public.itest18"
+ Column |  Type   | Collation | Nullable |           Default            
+--------+---------+-----------+----------+------------------------------
+ a      | integer |           | not null | generated always as identity
+ b      | text    |           |          | 
+
+\d itest18_a_seq
+               Unlogged sequence "public.itest18_a_seq"
+  Type   | Start | Minimum |  Maximum   | Increment | Cycles? | Cache 
+---------+-------+---------+------------+-----------+---------+-------
+ integer |     1 |       1 | 2147483647 |         1 | no      |     1
+Sequence for identity column: public.itest18.a
+
+ALTER TABLE itest18 SET LOGGED;
+\d itest18
+                         Table "public.itest18"
+ Column |  Type   | Collation | Nullable |           Default            
+--------+---------+-----------+----------+------------------------------
+ a      | integer |           | not null | generated always as identity
+ b      | text    |           |          | 
+
+\d itest18_a_seq
+                   Sequence "public.itest18_a_seq"
+  Type   | Start | Minimum |  Maximum   | Increment | Cycles? | Cache 
+---------+-------+---------+------------+-----------+---------+-------
+ integer |     1 |       1 | 2147483647 |         1 | no      |     1
+Sequence for identity column: public.itest18.a
+
+ALTER TABLE itest18 SET UNLOGGED;
+\d itest18
+                    Unlogged table "public.itest18"
+ Column |  Type   | Collation | Nullable |           Default            
+--------+---------+-----------+----------+------------------------------
+ a      | integer |           | not null | generated always as identity
+ b      | text    |           |          | 
+
+\d itest18_a_seq
+               Unlogged sequence "public.itest18_a_seq"
+  Type   | Start | Minimum |  Maximum   | Increment | Cycles? | Cache 
+---------+-------+---------+------------+-----------+---------+-------
+ integer |     1 |       1 | 2147483647 |         1 | no      |     1
+Sequence for identity column: public.itest18.a
+
 -- kinda silly to change property in the same command, but it should work
 ALTER TABLE itest3
   ADD COLUMN c int GENERATED BY DEFAULT AS IDENTITY,
diff --git a/src/test/regress/sql/identity.sql b/src/test/regress/sql/identity.sql
index 7596f0a36f..8c76fa1ceb 100644
--- a/src/test/regress/sql/identity.sql
+++ b/src/test/regress/sql/identity.sql
@@ -217,8 +217,20 @@ ALTER TABLE itest3 ALTER COLUMN a TYPE text;  -- error
 -- check that unlogged propagates to sequence
 CREATE UNLOGGED TABLE itest17 (a int NOT NULL, b text);
 ALTER TABLE itest17 ALTER COLUMN a ADD GENERATED ALWAYS AS IDENTITY;
+ALTER TABLE itest17 ADD COLUMN c int GENERATED ALWAYS AS IDENTITY;
+CREATE TABLE itest18 (a int NOT NULL, b text);
+ALTER TABLE itest18 SET UNLOGGED, ALTER COLUMN a ADD GENERATED ALWAYS AS IDENTITY;
 \d itest17
 \d itest17_a_seq
+\d itest17_c_seq
+\d itest18
+\d itest18_a_seq
+ALTER TABLE itest18 SET LOGGED;
+\d itest18
+\d itest18_a_seq
+ALTER TABLE itest18 SET UNLOGGED;
+\d itest18
+\d itest18_a_seq
 
 -- kinda silly to change property in the same command, but it should work
 ALTER TABLE itest3
-- 
2.25.1



^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: Fix propagation of persistence to sequences in ALTER TABLE / ADD COLUMN
@ 2024-02-09 07:19  Peter Eisentraut <[email protected]>
  parent: Ashutosh Bapat <[email protected]>
  0 siblings, 0 replies; 29+ messages in thread

From: Peter Eisentraut @ 2024-02-09 07:19 UTC (permalink / raw)
  To: Ashutosh Bapat <[email protected]>; +Cc: pgsql-hackers

On 08.02.24 07:04, Ashutosh Bapat wrote:
> The patch looks ok.
> 
> +    seqstmt->sequence->relpersistence = cxt->rel ?
> cxt->rel->rd_rel->relpersistence : cxt->relation->relpersistence;
> +
> 
> This condition looks consistent with the other places in the code
> around line 435, 498.

Ah good, that pattern already existed.

> But I was worried that cxt->rel may not get
> latest relpersistence if the ALTER TABLE changes persistence as well.
> Added a test (0002) which shows that ctx->rel has up-to-date
> relpersistence. Also added a few other tests. Feel free to
> include/reject them while committing.

Yes, this additional coverage seems good.  Committed with your additions.







^ permalink  raw  reply  [nested|flat] 29+ messages in thread


end of thread, other threads:[~2024-02-09 07:19 UTC | newest]

Thread overview: 29+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2018-03-21 21:36 Multiple-output-file make rules: We're Doing It Wrong Tom Lane <[email protected]>
2018-03-22 03:16 ` Tom Lane <[email protected]>
2021-03-03 22:36 [PATCH 2/2] doc review Justin Pryzby <[email protected]>
2021-03-03 22:36 [PATCH 2/2] doc review Justin Pryzby <[email protected]>
2021-03-03 22:36 [PATCH 2/2] doc review Justin Pryzby <[email protected]>
2021-03-03 22:36 [PATCH 2/2] doc review Justin Pryzby <[email protected]>
2021-03-03 22:36 [PATCH 2/2] doc review Justin Pryzby <[email protected]>
2021-03-03 22:36 [PATCH 2/2] doc review Justin Pryzby <[email protected]>
2021-03-03 22:36 [PATCH 2/2] doc review Justin Pryzby <[email protected]>
2021-03-03 22:36 [PATCH 2/2] doc review Justin Pryzby <[email protected]>
2021-03-03 22:36 [PATCH 2/2] doc review Justin Pryzby <[email protected]>
2021-03-03 22:36 [PATCH 2/2] doc review Justin Pryzby <[email protected]>
2021-03-03 22:36 [PATCH 2/2] doc review Justin Pryzby <[email protected]>
2021-03-03 22:36 [PATCH 2/2] doc review Justin Pryzby <[email protected]>
2021-03-03 22:36 [PATCH 2/2] doc review Justin Pryzby <[email protected]>
2021-03-03 22:36 [PATCH 2/2] doc review Justin Pryzby <[email protected]>
2021-03-03 22:36 [PATCH 2/2] doc review Justin Pryzby <[email protected]>
2021-03-03 22:36 [PATCH 2/2] doc review Justin Pryzby <[email protected]>
2021-03-03 22:36 [PATCH 2/2] doc review Justin Pryzby <[email protected]>
2021-03-03 22:36 [PATCH 2/2] doc review Justin Pryzby <[email protected]>
2021-03-03 22:36 [PATCH 2/2] doc review Justin Pryzby <[email protected]>
2021-03-03 22:36 [PATCH 2/2] doc review Justin Pryzby <[email protected]>
2021-03-03 22:36 [PATCH 2/2] doc review Justin Pryzby <[email protected]>
2021-03-03 22:36 [PATCH 2/2] doc review Justin Pryzby <[email protected]>
2021-03-03 22:36 [PATCH 2/2] doc review Justin Pryzby <[email protected]>
2021-03-03 22:36 [PATCH 2/2] doc review Justin Pryzby <[email protected]>
2024-02-05 15:51 Fix propagation of persistence to sequences in ALTER TABLE / ADD COLUMN Peter Eisentraut <[email protected]>
2024-02-08 06:04 ` Re: Fix propagation of persistence to sequences in ALTER TABLE / ADD COLUMN Ashutosh Bapat <[email protected]>
2024-02-09 07:19   ` Re: Fix propagation of persistence to sequences in ALTER TABLE / ADD COLUMN Peter Eisentraut <[email protected]>

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox