]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
pgbench: fix misprocessing of some nested \if constructs.
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 15 Dec 2024 19:14:15 +0000 (14:14 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 15 Dec 2024 19:14:15 +0000 (14:14 -0500)
An \if command appearing within a false (not-to-be-executed) \if
branch was incorrectly treated the same as \elif.  This could allow
statements within the inner \if to be executed when they should
not be.  Also the missing inner \if stack entry would result in an
assertion failure (in assert-enabled builds) when the final \endif
is reached.

Report and patch by Michail Nikolaev.  Back-patch to all
supported branches.

Discussion: https://postgr.es/m/CANtu0oiA1ke=SP6tauhNqkUdv5QFsJtS1p=aOOf_iU+EhyKkjQ@mail.gmail.com

src/bin/pgbench/pgbench.c
src/bin/pgbench/t/001_pgbench_with_server.pl

index fd2c8f42c50d9085ab9472dd2c5f59d426d94070..1aa6661f14248df1fe8a3b5a3994a418f0ef2040 100644 (file)
@@ -3865,8 +3865,14 @@ advanceConnectionState(TState *thread, CState *st, StatsData *agg)
                                                switch (conditional_stack_peek(st->cstack))
                                                {
                                                        case IFSTATE_FALSE:
-                                                               if (command->meta == META_IF ||
-                                                                       command->meta == META_ELIF)
+                                                               if (command->meta == META_IF)
+                                                               {
+                                                                       /* nested if in skipped branch - ignore */
+                                                                       conditional_stack_push(st->cstack,
+                                                                                                                  IFSTATE_IGNORED);
+                                                                       st->command++;
+                                                               }
+                                                               else if (command->meta == META_ELIF)
                                                                {
                                                                        /* we must evaluate the condition */
                                                                        st->state = CSTATE_START_COMMAND;
@@ -3885,11 +3891,7 @@ advanceConnectionState(TState *thread, CState *st, StatsData *agg)
                                                                        conditional_stack_pop(st->cstack);
                                                                        if (conditional_active(st->cstack))
                                                                                st->state = CSTATE_START_COMMAND;
-
-                                                                       /*
-                                                                        * else state remains in
-                                                                        * CSTATE_SKIP_COMMAND
-                                                                        */
+                                                                       /* else state remains CSTATE_SKIP_COMMAND */
                                                                        st->command++;
                                                                }
                                                                break;
index afc9ecfaf77fed51fffeaf857d9f17587e44e76f..d746987b5303f67864c68f25032ba4030fc85cd9 100644 (file)
@@ -633,6 +633,56 @@ SELECT :v0, :v1, :v2, :v3;
 }
        });
 
+# test nested \if constructs
+$node->pgbench(
+       '--no-vacuum --client=1 --transactions=1',
+       0,
+       [qr{actually processed}],
+       [qr{^$}],
+       'nested ifs',
+       {
+               'pgbench_nested_if' => q(
+                       \if false
+                               SELECT 1 / 0;
+                               \if true
+                                       SELECT 1 / 0;
+                               \elif true
+                                       SELECT 1 / 0;
+                               \else
+                                       SELECT 1 / 0;
+                               \endif
+                               SELECT 1 / 0;
+                       \elif false
+                               \if true
+                                       SELECT 1 / 0;
+                               \elif true
+                                       SELECT 1 / 0;
+                               \else
+                                       SELECT 1 / 0;
+                               \endif
+                       \else
+                               \if false
+                                       SELECT 1 / 0;
+                               \elif false
+                                       SELECT 1 / 0;
+                               \else
+                                       SELECT 'correct';
+                               \endif
+                       \endif
+                       \if true
+                               SELECT 'correct';
+                       \else
+                               \if true
+                                       SELECT 1 / 0;
+                               \elif true
+                                       SELECT 1 / 0;
+                               \else
+                                       SELECT 1 / 0;
+                               \endif
+                       \endif
+               )
+       });
+
 # random determinism when seeded
 $node->safe_psql('postgres',
        'CREATE UNLOGGED TABLE seeded_random(seed INT8 NOT NULL, rand TEXT NOT NULL, val INTEGER NOT NULL);'