that will accept any message type at any time that it could make sense,
rather than wiring in assumptions about the exact sequence of messages.
</para>
+
+ <sect3 id="protocol-flow-multi-statement">
+ <title>Multiple Statements in a Simple Query</title>
+
+ <para>
+ When a simple Query message contains more than one SQL statement
+ (separated by semicolons), those statements are executed as a single
+ transaction, unless explicit transaction control commands are included
+ to force a different behavior. For example, if the message contains
+<programlisting>
+INSERT INTO mytable VALUES(1);
+SELECT 1/0;
+INSERT INTO mytable VALUES(2);
+</programlisting>
+ then the divide-by-zero failure in the <command>SELECT</> will force
+ rollback of the first <command>INSERT</>. Furthermore, because
+ execution of the message is abandoned at the first error, the second
+ <command>INSERT</> is never attempted at all.
+ </para>
+
+ <para>
+ If instead the message contains
+<programlisting>
+BEGIN;
+INSERT INTO mytable VALUES(1);
+COMMIT;
+INSERT INTO mytable VALUES(2);
+SELECT 1/0;
+</programlisting>
+ then the first <command>INSERT</> is committed by the
+ explicit <command>COMMIT</> command. The second <command>INSERT</>
+ and the <command>SELECT</> are still treated as a single transaction,
+ so that the divide-by-zero failure will roll back the
+ second <command>INSERT</>, but not the first one.
+ </para>
+
+ <para>
+ This behavior is implemented by running the statements in a
+ multi-statement Query message in an <firstterm>implicit transaction
+ block</> unless there is some explicit transaction block for them to
+ run in. The main difference between an implicit transaction block and
+ a regular one is that an implicit block is closed automatically at the
+ end of the Query message, either by an implicit commit if there was no
+ error, or an implicit rollback if there was an error. This is similar
+ to the implicit commit or rollback that happens for a statement
+ executed by itself (when not in a transaction block).
+ </para>
+
+ <para>
+ If the session is already in a transaction block, as a result of
+ a <command>BEGIN</> in some previous message, then the Query message
+ simply continues that transaction block, whether the message contains
+ one statement or several. However, if the Query message contains
+ a <command>COMMIT</> or <command>ROLLBACK</> closing the existing
+ transaction block, then any following statements are executed in an
+ implicit transaction block.
+ Conversely, if a <command>BEGIN</> appears in a multi-statement Query
+ message, then it starts a regular transaction block that will only be
+ terminated by an explicit <command>COMMIT</> or <command>ROLLBACK</>,
+ whether that appears in this Query message or a later one.
+ If the <command>BEGIN</> follows some statements that were executed as
+ an implicit transaction block, those statements are not immediately
+ committed; in effect, they are retroactively included into the new
+ regular transaction block.
+ </para>
+
+ <para>
+ A <command>COMMIT</> or <command>ROLLBACK</> appearing in an implicit
+ transaction block is executed as normal, closing the implicit block;
+ however, a warning will be issued since a <command>COMMIT</>
+ or <command>ROLLBACK</> without a previous <command>BEGIN</> might
+ represent a mistake. If more statements follow, a new implicit
+ transaction block will be started for them.
+ </para>
+
+ <para>
+ Savepoints are not allowed in an implicit transaction block, since
+ they would conflict with the behavior of automatically closing the
+ block upon any error.
+ </para>
+
+ <para>
+ Remember that, regardless of any transaction control commands that may
+ be present, execution of the Query message stops at the first error.
+ Thus for example given
+<programlisting>
+BEGIN;
+SELECT 1/0;
+ROLLBACK;
+</programlisting>
+ in a single Query message, the session will be left inside a failed
+ regular transaction block, since the <command>ROLLBACK</> is not
+ reached after the divide-by-zero error. Another <command>ROLLBACK</>
+ will be needed to restore the session to a usable state.
+ </para>
+
+ <para>
+ Another behavior of note is that initial lexical and syntactic
+ analysis is done on the entire query string before any of it is
+ executed. Thus simple errors (such as a misspelled keyword) in later
+ statements can prevent execution of any of the statements. This
+ is normally invisible to users since the statements would all roll
+ back anyway when done as an implicit transaction block. However,
+ it can be visible when attempting to do multiple transactions within a
+ multi-statement Query. For instance, if a typo turned our previous
+ example into
+<programlisting>
+BEGIN;
+INSERT INTO mytable VALUES(1);
+COMMIT;
+INSERT INTO mytable VALUES(2);
+SELCT 1/0;
+</programlisting>
+ then none of the statements would get run, resulting in the visible
+ difference that the first <command>INSERT</> is not committed.
+ Errors detected at semantic analysis or later, such as a misspelled
+ table or column name, do not have this effect.
+ </para>
+ </sect3>
</sect2>
<sect2 id="protocol-flow-ext-query">
</para>
<para>
Each <acronym>SQL</acronym> command string passed
- to <option>-c</option> is sent to the server as a single query.
+ to <option>-c</option> is sent to the server as a single request.
Because of this, the server executes it as a single transaction even
if the string contains multiple <acronym>SQL</acronym> commands,
unless there are explicit <command>BEGIN</>/<command>COMMIT</>
commands included in the string to divide it into multiple
- transactions. Also, <application>psql</application> only prints the
+ transactions. (See <xref linkend="protocol-flow-multi-statement">
+ for more details about how the server handles multi-query strings.)
+ Also, <application>psql</application> only prints the
result of the last <acronym>SQL</acronym> command in the string.
This is different from the behavior when the same string is read from
a file or fed to <application>psql</application>'s standard input,
each <acronym>SQL</acronym> command separately.
</para>
<para>
- Because of this behavior, putting more than one command in a
+ Because of this behavior, putting more than one SQL command in a
single <option>-c</option> string often has unexpected results.
It's better to use repeated <option>-c</option> commands or feed
multiple commands to <application>psql</application>'s standard input,
</listitem>
</varlistentry>
+
+ <varlistentry>
+ <term><literal>\;</literal></term>
+ <listitem>
+ <para>
+ Backslash-semicolon is not a meta-command in the same way as the
+ preceding commands; rather, it simply causes a semicolon to be
+ added to the query buffer without any further processing.
+ </para>
+
+ <para>
+ Normally, <application>psql</> will dispatch a SQL command to the
+ server as soon as it reaches the command-ending semicolon, even if
+ more input remains on the current line. Thus for example entering
+<programlisting>
+select 1; select 2; select 3;
+</programlisting>
+ will result in the three SQL commands being individually sent to
+ the server, with each one's results being displayed before
+ continuing to the next command. However, a semicolon entered
+ as <literal>\;</> will not trigger command processing, so that the
+ command before it and the one after are effectively combined and
+ sent to the server in one request. So for example
+<programlisting>
+select 1\; select 2\; select 3;
+</programlisting>
+ results in sending the three SQL commands to the server in a single
+ request, when the non-backslashed semicolon is reached.
+ The server executes such a request as a single transaction,
+ unless there are explicit <command>BEGIN</>/<command>COMMIT</>
+ commands included in the string to divide it into multiple
+ transactions. (See <xref linkend="protocol-flow-multi-statement">
+ for more details about how the server handles multi-query strings.)
+ <application>psql</application> prints only the last query result
+ it receives for each request; in this example, although all
+ three <command>SELECT</>s are indeed executed, <application>psql</>
+ only prints the <literal>3</>.
+ </para>
+ </listitem>
+ </varlistentry>
+
</variablelist>
</para>