@@ -607,8 +607,8 @@ static void setIntValue(PgBenchValue *pv, int64 ival);
607607static void setDoubleValue (PgBenchValue * pv , double dval );
608608static bool evaluateExpr (TState * thread , CState * st , PgBenchExpr * expr ,
609609 PgBenchValue * retval );
610- static instr_time doExecuteCommand (TState * thread , CState * st ,
611- instr_time now );
610+ static ConnectionStateEnum executeMetaCommand (TState * thread , CState * st ,
611+ instr_time * now );
612612static void doLog (TState * thread , CState * st ,
613613 StatsData * agg , bool skipped , double latency , double lag );
614614static void processXactStats (TState * thread , CState * st , instr_time * now ,
@@ -802,7 +802,7 @@ strtoint64(const char *str, bool errorOK, int64 *result)
802802invalid_syntax :
803803 if (!errorOK )
804804 fprintf (stderr ,
805- "invalid input syntax for type bigint: \"%s\"\n" ,str );
805+ "invalid input syntax for type bigint: \"%s\"\n" , str );
806806 return false;
807807}
808808
@@ -827,7 +827,7 @@ strtodouble(const char *str, bool errorOK, double *dv)
827827 {
828828 if (!errorOK )
829829 fprintf (stderr ,
830- "invalid input syntax for type double: \"%s\"\n" ,str );
830+ "invalid input syntax for type double: \"%s\"\n" , str );
831831 return false;
832832 }
833833 return true;
@@ -3012,6 +3012,8 @@ advanceConnectionState(TState *thread, CState *st, StatsData *agg)
30123012 */
30133013 for (;;)
30143014 {
3015+ Command * command ;
3016+
30153017 switch (st -> state )
30163018 {
30173019 /* Select transaction (script) to run. */
@@ -3151,8 +3153,10 @@ advanceConnectionState(TState *thread, CState *st, StatsData *agg)
31513153 * Send a command to server (or execute a meta-command)
31523154 */
31533155 case CSTATE_START_COMMAND :
3156+ command = sql_script [st -> use_file ].commands [st -> command ];
3157+
31543158 /* Transition to script end processing if done */
3155- if (sql_script [ st -> use_file ]. commands [ st -> command ] == NULL )
3159+ if (command == NULL )
31563160 {
31573161 st -> state = CSTATE_END_TX ;
31583162 break ;
@@ -3164,7 +3168,28 @@ advanceConnectionState(TState *thread, CState *st, StatsData *agg)
31643168 INSTR_TIME_SET_CURRENT_LAZY (now );
31653169 st -> stmt_begin = now ;
31663170 }
3167- now = doExecuteCommand (thread , st , now );
3171+
3172+ /* Execute the command */
3173+ if (command -> type == SQL_COMMAND )
3174+ {
3175+ if (!sendCommand (st , command ))
3176+ {
3177+ commandFailed (st , "SQL" , "SQL command send failed" );
3178+ st -> state = CSTATE_ABORTED ;
3179+ }
3180+ else
3181+ st -> state = CSTATE_WAIT_RESULT ;
3182+ }
3183+ else if (command -> type == META_COMMAND )
3184+ {
3185+ /*-----
3186+ * Possible state changes when executing meta commands:
3187+ * - on errors CSTATE_ABORTED
3188+ * - on sleep CSTATE_SLEEP
3189+ * - else CSTATE_END_COMMAND
3190+ */
3191+ st -> state = executeMetaCommand (thread , st , & now );
3192+ }
31683193
31693194 /*
31703195 * We're now waiting for an SQL command to complete, or
@@ -3237,7 +3262,8 @@ advanceConnectionState(TState *thread, CState *st, StatsData *agg)
32373262 case IFSTATE_IGNORED :
32383263 case IFSTATE_ELSE_FALSE :
32393264 if (command -> meta == META_IF )
3240- conditional_stack_push (st -> cstack , IFSTATE_IGNORED );
3265+ conditional_stack_push (st -> cstack ,
3266+ IFSTATE_IGNORED );
32413267 else if (command -> meta == META_ENDIF )
32423268 {
32433269 Assert (!conditional_stack_empty (st -> cstack ));
@@ -3387,179 +3413,155 @@ advanceConnectionState(TState *thread, CState *st, StatsData *agg)
33873413}
33883414
33893415/*
3390- * Subroutine for advanceConnectionState -- execute or initiate the current
3391- * command, and transition to next state appropriately .
3416+ * Subroutine for advanceConnectionState -- initiate or execute the current
3417+ * meta command, and return the next state to set .
33923418 *
3393- * Returns an updated timestamp from 'now', used to update 'now' at callsite.
3419+ * *now is updated to the current time, unless the command is expected to
3420+ * take no time to execute.
33943421 */
3395- static instr_time
3396- doExecuteCommand (TState * thread , CState * st , instr_time now )
3422+ static ConnectionStateEnum
3423+ executeMetaCommand (TState * thread , CState * st , instr_time * now )
33973424{
33983425 Command * command = sql_script [st -> use_file ].commands [st -> command ];
3426+ int argc ;
3427+ char * * argv ;
3428+
3429+ Assert (command != NULL && command -> type == META_COMMAND );
33993430
3400- /* execute the command */
3401- if (command -> type == SQL_COMMAND )
3431+ argc = command -> argc ;
3432+ argv = command -> argv ;
3433+
3434+ if (debug )
34023435 {
3403- if (!sendCommand (st , command ))
3436+ fprintf (stderr , "client %d executing \\%s" , st -> id , argv [0 ]);
3437+ for (int i = 1 ; i < argc ; i ++ )
3438+ fprintf (stderr , " %s" , argv [i ]);
3439+ fprintf (stderr , "\n" );
3440+ }
3441+
3442+ if (command -> meta == META_SLEEP )
3443+ {
3444+ int usec ;
3445+
3446+ /*
3447+ * A \sleep doesn't execute anything, we just get the delay from the
3448+ * argument, and enter the CSTATE_SLEEP state. (The per-command
3449+ * latency will be recorded in CSTATE_SLEEP state, not here, after the
3450+ * delay has elapsed.)
3451+ */
3452+ if (!evaluateSleep (st , argc , argv , & usec ))
34043453 {
3405- commandFailed (st , "SQL " , "SQL command send failed" );
3406- st -> state = CSTATE_ABORTED ;
3454+ commandFailed (st , "sleep " , "execution of meta-command failed" );
3455+ return CSTATE_ABORTED ;
34073456 }
3408- else
3409- st -> state = CSTATE_WAIT_RESULT ;
3457+
3458+ INSTR_TIME_SET_CURRENT_LAZY (* now );
3459+ st -> sleep_until = INSTR_TIME_GET_MICROSEC (* now ) + usec ;
3460+ return CSTATE_SLEEP ;
34103461 }
3411- else if (command -> type == META_COMMAND )
3462+ else if (command -> meta == META_SET )
34123463 {
3413- int argc = command -> argc ;
3414- char * * argv = command -> argv ;
3464+ PgBenchExpr * expr = command -> expr ;
3465+ PgBenchValue result ;
34153466
3416- if (debug )
3467+ if (! evaluateExpr ( thread , st , expr , & result ) )
34173468 {
3418- fprintf (stderr , "client %d executing \\%s" ,
3419- st -> id , argv [0 ]);
3420- for (int i = 1 ; i < argc ; i ++ )
3421- fprintf (stderr , " %s" , argv [i ]);
3422- fprintf (stderr , "\n" );
3469+ commandFailed (st , argv [0 ], "evaluation of meta-command failed" );
3470+ return CSTATE_ABORTED ;
34233471 }
34243472
3425- if (command -> meta == META_SLEEP )
3473+ if (! putVariableValue ( st , argv [ 0 ], argv [ 1 ], & result ) )
34263474 {
3427- int usec ;
3428-
3429- /*
3430- * A \sleep doesn't execute anything, we just get the delay from
3431- * the argument, and enter the CSTATE_SLEEP state. (The
3432- * per-command latency will be recorded in CSTATE_SLEEP state, not
3433- * here, after the delay has elapsed.)
3434- */
3435- if (!evaluateSleep (st , argc , argv , & usec ))
3436- {
3437- commandFailed (st , "sleep" , "execution of meta-command failed" );
3438- st -> state = CSTATE_ABORTED ;
3439- return now ;
3440- }
3441-
3442- INSTR_TIME_SET_CURRENT_LAZY (now );
3443-
3444- st -> sleep_until = INSTR_TIME_GET_MICROSEC (now ) + usec ;
3445- st -> state = CSTATE_SLEEP ;
3446- return now ;
3475+ commandFailed (st , "set" , "assignment of meta-command failed" );
3476+ return CSTATE_ABORTED ;
34473477 }
3448- else if (command -> meta == META_SET )
3449- {
3450- PgBenchExpr * expr = command -> expr ;
3451- PgBenchValue result ;
3452-
3453- if (!evaluateExpr (thread , st , expr , & result ))
3454- {
3455- commandFailed (st , argv [0 ], "evaluation of meta-command failed" );
3456- st -> state = CSTATE_ABORTED ;
3457- return now ;
3458- }
3478+ }
3479+ else if (command -> meta == META_IF )
3480+ {
3481+ /* backslash commands with an expression to evaluate */
3482+ PgBenchExpr * expr = command -> expr ;
3483+ PgBenchValue result ;
3484+ bool cond ;
34593485
3460- if (!putVariableValue (st , argv [0 ], argv [1 ], & result ))
3461- {
3462- commandFailed (st , "set" , "assignment of meta-command failed" );
3463- st -> state = CSTATE_ABORTED ;
3464- return now ;
3465- }
3466- }
3467- else if (command -> meta == META_IF )
3486+ if (!evaluateExpr (thread , st , expr , & result ))
34683487 {
3469- /* backslash commands with an expression to evaluate */
3470- PgBenchExpr * expr = command -> expr ;
3471- PgBenchValue result ;
3472- bool cond ;
3473-
3474- if (!evaluateExpr (thread , st , expr , & result ))
3475- {
3476- commandFailed (st , argv [0 ], "evaluation of meta-command failed" );
3477- st -> state = CSTATE_ABORTED ;
3478- return now ;
3479- }
3480-
3481- cond = valueTruth (& result );
3482- conditional_stack_push (st -> cstack , cond ? IFSTATE_TRUE : IFSTATE_FALSE );
3488+ commandFailed (st , argv [0 ], "evaluation of meta-command failed" );
3489+ return CSTATE_ABORTED ;
34833490 }
3484- else if (command -> meta == META_ELIF )
3485- {
3486- /* backslash commands with an expression to evaluate */
3487- PgBenchExpr * expr = command -> expr ;
3488- PgBenchValue result ;
3489- bool cond ;
34903491
3491- if (conditional_stack_peek (st -> cstack ) == IFSTATE_TRUE )
3492- {
3493- /*
3494- * elif after executed block, skip eval and wait for endif.
3495- */
3496- conditional_stack_poke (st -> cstack , IFSTATE_IGNORED );
3497- st -> state = CSTATE_END_COMMAND ;
3498- return now ;
3499- }
3500-
3501- if (!evaluateExpr (thread , st , expr , & result ))
3502- {
3503- commandFailed (st , argv [0 ], "evaluation of meta-command failed" );
3504- st -> state = CSTATE_ABORTED ;
3505- return now ;
3506- }
3492+ cond = valueTruth (& result );
3493+ conditional_stack_push (st -> cstack , cond ? IFSTATE_TRUE : IFSTATE_FALSE );
3494+ }
3495+ else if (command -> meta == META_ELIF )
3496+ {
3497+ /* backslash commands with an expression to evaluate */
3498+ PgBenchExpr * expr = command -> expr ;
3499+ PgBenchValue result ;
3500+ bool cond ;
35073501
3508- cond = valueTruth (& result );
3509- Assert (conditional_stack_peek (st -> cstack ) == IFSTATE_FALSE );
3510- conditional_stack_poke (st -> cstack , cond ? IFSTATE_TRUE : IFSTATE_FALSE );
3502+ if (conditional_stack_peek (st -> cstack ) == IFSTATE_TRUE )
3503+ {
3504+ /* elif after executed block, skip eval and wait for endif. */
3505+ conditional_stack_poke (st -> cstack , IFSTATE_IGNORED );
3506+ return CSTATE_END_COMMAND ;
35113507 }
3512- else if (command -> meta == META_ELSE )
3508+
3509+ if (!evaluateExpr (thread , st , expr , & result ))
35133510 {
3514- switch (conditional_stack_peek (st -> cstack ))
3515- {
3516- case IFSTATE_TRUE :
3517- conditional_stack_poke (st -> cstack , IFSTATE_ELSE_FALSE );
3518- break ;
3519- case IFSTATE_FALSE : /* inconsistent if active */
3520- case IFSTATE_IGNORED : /* inconsistent if active */
3521- case IFSTATE_NONE : /* else without if */
3522- case IFSTATE_ELSE_TRUE : /* else after else */
3523- case IFSTATE_ELSE_FALSE : /* else after else */
3524- default :
3525- /* dead code if conditional check is ok */
3526- Assert (false);
3527- }
3511+ commandFailed (st , argv [0 ], "evaluation of meta-command failed" );
3512+ return CSTATE_ABORTED ;
35283513 }
3529- else if (command -> meta == META_ENDIF )
3514+
3515+ cond = valueTruth (& result );
3516+ Assert (conditional_stack_peek (st -> cstack ) == IFSTATE_FALSE );
3517+ conditional_stack_poke (st -> cstack , cond ? IFSTATE_TRUE : IFSTATE_FALSE );
3518+ }
3519+ else if (command -> meta == META_ELSE )
3520+ {
3521+ switch (conditional_stack_peek (st -> cstack ))
35303522 {
3531- Assert (!conditional_stack_empty (st -> cstack ));
3532- conditional_stack_pop (st -> cstack );
3523+ case IFSTATE_TRUE :
3524+ conditional_stack_poke (st -> cstack , IFSTATE_ELSE_FALSE );
3525+ break ;
3526+ case IFSTATE_FALSE : /* inconsistent if active */
3527+ case IFSTATE_IGNORED : /* inconsistent if active */
3528+ case IFSTATE_NONE : /* else without if */
3529+ case IFSTATE_ELSE_TRUE : /* else after else */
3530+ case IFSTATE_ELSE_FALSE : /* else after else */
3531+ default :
3532+ /* dead code if conditional check is ok */
3533+ Assert (false);
35333534 }
3534- else if (command -> meta == META_SETSHELL )
3535+ }
3536+ else if (command -> meta == META_ENDIF )
3537+ {
3538+ Assert (!conditional_stack_empty (st -> cstack ));
3539+ conditional_stack_pop (st -> cstack );
3540+ }
3541+ else if (command -> meta == META_SETSHELL )
3542+ {
3543+ if (!runShellCommand (st , argv [1 ], argv + 2 , argc - 2 ))
35353544 {
3536- if (!runShellCommand (st , argv [1 ], argv + 2 , argc - 2 ))
3537- {
3538- commandFailed (st , "setshell" , "execution of meta-command failed" );
3539- st -> state = CSTATE_ABORTED ;
3540- return now ;
3541- }
3545+ commandFailed (st , "setshell" , "execution of meta-command failed" );
3546+ return CSTATE_ABORTED ;
35423547 }
3543- else if (command -> meta == META_SHELL )
3548+ }
3549+ else if (command -> meta == META_SHELL )
3550+ {
3551+ if (!runShellCommand (st , NULL , argv + 1 , argc - 1 ))
35443552 {
3545- if (!runShellCommand (st , NULL , argv + 1 , argc - 1 ))
3546- {
3547- commandFailed (st , "shell" , "execution of meta-command failed" );
3548- st -> state = CSTATE_ABORTED ;
3549- return now ;
3550- }
3553+ commandFailed (st , "shell" , "execution of meta-command failed" );
3554+ return CSTATE_ABORTED ;
35513555 }
3552-
3553- /*
3554- * executing the expression or shell command might have taken a
3555- * non-negligible amount of time, so reset 'now'
3556- */
3557- INSTR_TIME_SET_ZERO (now );
3558-
3559- st -> state = CSTATE_END_COMMAND ;
35603556 }
35613557
3562- return now ;
3558+ /*
3559+ * executing the expression or shell command might have taken a
3560+ * non-negligible amount of time, so reset 'now'
3561+ */
3562+ INSTR_TIME_SET_ZERO (* now );
3563+
3564+ return CSTATE_END_COMMAND ;
35633565}
35643566
35653567/*
@@ -4281,6 +4283,7 @@ free_command(Command *command)
42814283 pg_free (command -> argv [i ]);
42824284 if (command -> varprefix )
42834285 pg_free (command -> varprefix );
4286+
42844287 /*
42854288 * It should also free expr recursively, but this is currently not needed
42864289 * as only gset commands (which do not have an expression) are freed.
0 commit comments