Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit b976499

Browse files
committed
Improve documentation about behavior of multi-statement Query messages.
We've long done our best to sweep this topic under the rug, but in view of recent work it seems like it's time to explain it more precisely. Here's an initial cut at doing that. Discussion: https://postgr.es/m/0A3221C70F24FB45833433255569204D1F6BE40D@G01JPEXMBYT05
1 parent 1356f78 commit b976499

File tree

3 files changed

+168
-4
lines changed

3 files changed

+168
-4
lines changed

doc/src/sgml/libpq.sgml

+3-1
Original file line numberDiff line numberDiff line change
@@ -2223,7 +2223,9 @@ PGresult *PQexec(PGconn *conn, const char *command);
22232223
<function>PQexec</> call are processed in a single transaction, unless
22242224
there are explicit <command>BEGIN</command>/<command>COMMIT</command>
22252225
commands included in the query string to divide it into multiple
2226-
transactions. Note however that the returned
2226+
transactions. (See <xref linkend="protocol-flow-multi-statement">
2227+
for more details about how the server handles multi-query strings.)
2228+
Note however that the returned
22272229
<structname>PGresult</structname> structure describes only the result
22282230
of the last command executed from the string. Should one of the
22292231
commands fail, processing of the string stops with it and the returned

doc/src/sgml/protocol.sgml

+119
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,125 @@
675675
that will accept any message type at any time that it could make sense,
676676
rather than wiring in assumptions about the exact sequence of messages.
677677
</para>
678+
679+
<sect3 id="protocol-flow-multi-statement">
680+
<title>Multiple Statements in a Simple Query</title>
681+
682+
<para>
683+
When a simple Query message contains more than one SQL statement
684+
(separated by semicolons), those statements are executed as a single
685+
transaction, unless explicit transaction control commands are included
686+
to force a different behavior. For example, if the message contains
687+
<programlisting>
688+
INSERT INTO mytable VALUES(1);
689+
SELECT 1/0;
690+
INSERT INTO mytable VALUES(2);
691+
</programlisting>
692+
then the divide-by-zero failure in the <command>SELECT</> will force
693+
rollback of the first <command>INSERT</>. Furthermore, because
694+
execution of the message is abandoned at the first error, the second
695+
<command>INSERT</> is never attempted at all.
696+
</para>
697+
698+
<para>
699+
If instead the message contains
700+
<programlisting>
701+
BEGIN;
702+
INSERT INTO mytable VALUES(1);
703+
COMMIT;
704+
INSERT INTO mytable VALUES(2);
705+
SELECT 1/0;
706+
</programlisting>
707+
then the first <command>INSERT</> is committed by the
708+
explicit <command>COMMIT</> command. The second <command>INSERT</>
709+
and the <command>SELECT</> are still treated as a single transaction,
710+
so that the divide-by-zero failure will roll back the
711+
second <command>INSERT</>, but not the first one.
712+
</para>
713+
714+
<para>
715+
This behavior is implemented by running the statements in a
716+
multi-statement Query message in an <firstterm>implicit transaction
717+
block</> unless there is some explicit transaction block for them to
718+
run in. The main difference between an implicit transaction block and
719+
a regular one is that an implicit block is closed automatically at the
720+
end of the Query message, either by an implicit commit if there was no
721+
error, or an implicit rollback if there was an error. This is similar
722+
to the implicit commit or rollback that happens for a statement
723+
executed by itself (when not in a transaction block).
724+
</para>
725+
726+
<para>
727+
If the session is already in a transaction block, as a result of
728+
a <command>BEGIN</> in some previous message, then the Query message
729+
simply continues that transaction block, whether the message contains
730+
one statement or several. However, if the Query message contains
731+
a <command>COMMIT</> or <command>ROLLBACK</> closing the existing
732+
transaction block, then any following statements are executed in an
733+
implicit transaction block.
734+
Conversely, if a <command>BEGIN</> appears in a multi-statement Query
735+
message, then it starts a regular transaction block that will only be
736+
terminated by an explicit <command>COMMIT</> or <command>ROLLBACK</>,
737+
whether that appears in this Query message or a later one.
738+
If the <command>BEGIN</> follows some statements that were executed as
739+
an implicit transaction block, those statements are not immediately
740+
committed; in effect, they are retroactively included into the new
741+
regular transaction block.
742+
</para>
743+
744+
<para>
745+
A <command>COMMIT</> or <command>ROLLBACK</> appearing in an implicit
746+
transaction block is executed as normal, closing the implicit block;
747+
however, a warning will be issued since a <command>COMMIT</>
748+
or <command>ROLLBACK</> without a previous <command>BEGIN</> might
749+
represent a mistake. If more statements follow, a new implicit
750+
transaction block will be started for them.
751+
</para>
752+
753+
<para>
754+
Savepoints are not allowed in an implicit transaction block, since
755+
they would conflict with the behavior of automatically closing the
756+
block upon any error.
757+
</para>
758+
759+
<para>
760+
Remember that, regardless of any transaction control commands that may
761+
be present, execution of the Query message stops at the first error.
762+
Thus for example given
763+
<programlisting>
764+
BEGIN;
765+
SELECT 1/0;
766+
ROLLBACK;
767+
</programlisting>
768+
in a single Query message, the session will be left inside a failed
769+
regular transaction block, since the <command>ROLLBACK</> is not
770+
reached after the divide-by-zero error. Another <command>ROLLBACK</>
771+
will be needed to restore the session to a usable state.
772+
</para>
773+
774+
<para>
775+
Another behavior of note is that initial lexical and syntactic
776+
analysis is done on the entire query string before any of it is
777+
executed. Thus simple errors (such as a misspelled keyword) in later
778+
statements can prevent execution of any of the statements. This
779+
is normally invisible to users since the statements would all roll
780+
back anyway when done as an implicit transaction block. However,
781+
it can be visible when attempting to do multiple transactions within a
782+
multi-statement Query. For instance, if a typo turned our previous
783+
example into
784+
<programlisting>
785+
BEGIN;
786+
INSERT INTO mytable VALUES(1);
787+
COMMIT;
788+
INSERT INTO mytable VALUES(2);
789+
SELCT 1/0;
790+
</programlisting>
791+
then none of the statements would get run, resulting in the visible
792+
difference that the first <command>INSERT</> is not committed.
793+
Errors detected at semantic analysis or later, such as a misspelled
794+
table or column name, do not have this effect.
795+
</para>
796+
</sect3>
678797
</sect2>
679798

680799
<sect2 id="protocol-flow-ext-query">

doc/src/sgml/ref/psql-ref.sgml

+46-3
Original file line numberDiff line numberDiff line change
@@ -120,20 +120,22 @@ echo '\x \\ SELECT * FROM foo;' | psql
120120
</para>
121121
<para>
122122
Each <acronym>SQL</acronym> command string passed
123-
to <option>-c</option> is sent to the server as a single query.
123+
to <option>-c</option> is sent to the server as a single request.
124124
Because of this, the server executes it as a single transaction even
125125
if the string contains multiple <acronym>SQL</acronym> commands,
126126
unless there are explicit <command>BEGIN</>/<command>COMMIT</>
127127
commands included in the string to divide it into multiple
128-
transactions. Also, <application>psql</application> only prints the
128+
transactions. (See <xref linkend="protocol-flow-multi-statement">
129+
for more details about how the server handles multi-query strings.)
130+
Also, <application>psql</application> only prints the
129131
result of the last <acronym>SQL</acronym> command in the string.
130132
This is different from the behavior when the same string is read from
131133
a file or fed to <application>psql</application>'s standard input,
132134
because then <application>psql</application> sends
133135
each <acronym>SQL</acronym> command separately.
134136
</para>
135137
<para>
136-
Because of this behavior, putting more than one command in a
138+
Because of this behavior, putting more than one SQL command in a
137139
single <option>-c</option> string often has unexpected results.
138140
It's better to use repeated <option>-c</option> commands or feed
139141
multiple commands to <application>psql</application>'s standard input,
@@ -3179,6 +3181,47 @@ testdb=&gt; <userinput>\setenv LESS -imx4F</userinput>
31793181
</listitem>
31803182
</varlistentry>
31813183

3184+
3185+
<varlistentry>
3186+
<term><literal>\;</literal></term>
3187+
<listitem>
3188+
<para>
3189+
Backslash-semicolon is not a meta-command in the same way as the
3190+
preceding commands; rather, it simply causes a semicolon to be
3191+
added to the query buffer without any further processing.
3192+
</para>
3193+
3194+
<para>
3195+
Normally, <application>psql</> will dispatch a SQL command to the
3196+
server as soon as it reaches the command-ending semicolon, even if
3197+
more input remains on the current line. Thus for example entering
3198+
<programlisting>
3199+
select 1; select 2; select 3;
3200+
</programlisting>
3201+
will result in the three SQL commands being individually sent to
3202+
the server, with each one's results being displayed before
3203+
continuing to the next command. However, a semicolon entered
3204+
as <literal>\;</> will not trigger command processing, so that the
3205+
command before it and the one after are effectively combined and
3206+
sent to the server in one request. So for example
3207+
<programlisting>
3208+
select 1\; select 2\; select 3;
3209+
</programlisting>
3210+
results in sending the three SQL commands to the server in a single
3211+
request, when the non-backslashed semicolon is reached.
3212+
The server executes such a request as a single transaction,
3213+
unless there are explicit <command>BEGIN</>/<command>COMMIT</>
3214+
commands included in the string to divide it into multiple
3215+
transactions. (See <xref linkend="protocol-flow-multi-statement">
3216+
for more details about how the server handles multi-query strings.)
3217+
<application>psql</application> prints only the last query result
3218+
it receives for each request; in this example, although all
3219+
three <command>SELECT</>s are indeed executed, <application>psql</>
3220+
only prints the <literal>3</>.
3221+
</para>
3222+
</listitem>
3223+
</varlistentry>
3224+
31823225
</variablelist>
31833226
</para>
31843227

0 commit comments

Comments
 (0)