@@ -607,8 +607,8 @@ static void setIntValue(PgBenchValue *pv, int64 ival);
607
607
static void setDoubleValue (PgBenchValue * pv , double dval );
608
608
static bool evaluateExpr (TState * thread , CState * st , PgBenchExpr * expr ,
609
609
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 );
612
612
static void doLog (TState * thread , CState * st ,
613
613
StatsData * agg , bool skipped , double latency , double lag );
614
614
static void processXactStats (TState * thread , CState * st , instr_time * now ,
@@ -802,7 +802,7 @@ strtoint64(const char *str, bool errorOK, int64 *result)
802
802
invalid_syntax :
803
803
if (!errorOK )
804
804
fprintf (stderr ,
805
- "invalid input syntax for type bigint: \"%s\"\n" ,str );
805
+ "invalid input syntax for type bigint: \"%s\"\n" , str );
806
806
return false;
807
807
}
808
808
@@ -827,7 +827,7 @@ strtodouble(const char *str, bool errorOK, double *dv)
827
827
{
828
828
if (!errorOK )
829
829
fprintf (stderr ,
830
- "invalid input syntax for type double: \"%s\"\n" ,str );
830
+ "invalid input syntax for type double: \"%s\"\n" , str );
831
831
return false;
832
832
}
833
833
return true;
@@ -3012,6 +3012,8 @@ advanceConnectionState(TState *thread, CState *st, StatsData *agg)
3012
3012
*/
3013
3013
for (;;)
3014
3014
{
3015
+ Command * command ;
3016
+
3015
3017
switch (st -> state )
3016
3018
{
3017
3019
/* Select transaction (script) to run. */
@@ -3151,8 +3153,10 @@ advanceConnectionState(TState *thread, CState *st, StatsData *agg)
3151
3153
* Send a command to server (or execute a meta-command)
3152
3154
*/
3153
3155
case CSTATE_START_COMMAND :
3156
+ command = sql_script [st -> use_file ].commands [st -> command ];
3157
+
3154
3158
/* Transition to script end processing if done */
3155
- if (sql_script [ st -> use_file ]. commands [ st -> command ] == NULL )
3159
+ if (command == NULL )
3156
3160
{
3157
3161
st -> state = CSTATE_END_TX ;
3158
3162
break ;
@@ -3164,7 +3168,28 @@ advanceConnectionState(TState *thread, CState *st, StatsData *agg)
3164
3168
INSTR_TIME_SET_CURRENT_LAZY (now );
3165
3169
st -> stmt_begin = now ;
3166
3170
}
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
+ }
3168
3193
3169
3194
/*
3170
3195
* We're now waiting for an SQL command to complete, or
@@ -3237,7 +3262,8 @@ advanceConnectionState(TState *thread, CState *st, StatsData *agg)
3237
3262
case IFSTATE_IGNORED :
3238
3263
case IFSTATE_ELSE_FALSE :
3239
3264
if (command -> meta == META_IF )
3240
- conditional_stack_push (st -> cstack , IFSTATE_IGNORED );
3265
+ conditional_stack_push (st -> cstack ,
3266
+ IFSTATE_IGNORED );
3241
3267
else if (command -> meta == META_ENDIF )
3242
3268
{
3243
3269
Assert (!conditional_stack_empty (st -> cstack ));
@@ -3387,179 +3413,155 @@ advanceConnectionState(TState *thread, CState *st, StatsData *agg)
3387
3413
}
3388
3414
3389
3415
/*
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 .
3392
3418
*
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.
3394
3421
*/
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 )
3397
3424
{
3398
3425
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 );
3399
3430
3400
- /* execute the command */
3401
- if (command -> type == SQL_COMMAND )
3431
+ argc = command -> argc ;
3432
+ argv = command -> argv ;
3433
+
3434
+ if (debug )
3402
3435
{
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 ))
3404
3453
{
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 ;
3407
3456
}
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 ;
3410
3461
}
3411
- else if (command -> type == META_COMMAND )
3462
+ else if (command -> meta == META_SET )
3412
3463
{
3413
- int argc = command -> argc ;
3414
- char * * argv = command -> argv ;
3464
+ PgBenchExpr * expr = command -> expr ;
3465
+ PgBenchValue result ;
3415
3466
3416
- if (debug )
3467
+ if (! evaluateExpr ( thread , st , expr , & result ) )
3417
3468
{
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 ;
3423
3471
}
3424
3472
3425
- if (command -> meta == META_SLEEP )
3473
+ if (! putVariableValue ( st , argv [ 0 ], argv [ 1 ], & result ) )
3426
3474
{
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 ;
3447
3477
}
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 ;
3459
3485
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 ))
3468
3487
{
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 ;
3483
3490
}
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 ;
3490
3491
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 ;
3507
3501
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 ;
3511
3507
}
3512
- else if (command -> meta == META_ELSE )
3508
+
3509
+ if (!evaluateExpr (thread , st , expr , & result ))
3513
3510
{
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 ;
3528
3513
}
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 ))
3530
3522
{
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);
3533
3534
}
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 ))
3535
3544
{
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 ;
3542
3547
}
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 ))
3544
3552
{
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 ;
3551
3555
}
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 ;
3560
3556
}
3561
3557
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 ;
3563
3565
}
3564
3566
3565
3567
/*
@@ -4281,6 +4283,7 @@ free_command(Command *command)
4281
4283
pg_free (command -> argv [i ]);
4282
4284
if (command -> varprefix )
4283
4285
pg_free (command -> varprefix );
4286
+
4284
4287
/*
4285
4288
* It should also free expr recursively, but this is currently not needed
4286
4289
* as only gset commands (which do not have an expression) are freed.
0 commit comments