|
675 | 675 | that will accept any message type at any time that it could make sense,
|
676 | 676 | rather than wiring in assumptions about the exact sequence of messages.
|
677 | 677 | </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> |
678 | 797 | </sect2>
|
679 | 798 |
|
680 | 799 | <sect2 id="protocol-flow-ext-query">
|
|
0 commit comments