LCOV - differential code coverage report
Current view: top level - src/bin/pgbench - exprparse.y (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage 16@8cea358b128 vs 17@8cea358b128 Lines: 99.3 % 151 150 1 150
Current Date: 2024-04-14 14:21:10 Functions: 100.0 % 12 12 12
Baseline: 16@8cea358b128 Branches: 91.1 % 45 41 4 41
Baseline Date: 2024-04-14 14:21:09 Line coverage date bins:
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed (240..) days: 99.3 % 151 150 1 150
Function coverage date bins:
(240..) days: 100.0 % 12 12 12
Branch coverage date bins:
(240..) days: 91.1 % 45 41 4 41

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : %{
                                  2                 :                : /*-------------------------------------------------------------------------
                                  3                 :                :  *
                                  4                 :                :  * exprparse.y
                                  5                 :                :  *    bison grammar for a simple expression syntax
                                  6                 :                :  *
                                  7                 :                :  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
                                  8                 :                :  * Portions Copyright (c) 1994, Regents of the University of California
                                  9                 :                :  *
                                 10                 :                :  * src/bin/pgbench/exprparse.y
                                 11                 :                :  *
                                 12                 :                :  *-------------------------------------------------------------------------
                                 13                 :                :  */
                                 14                 :                : 
                                 15                 :                : #include "postgres_fe.h"
                                 16                 :                : 
                                 17                 :                : #include "pgbench.h"
                                 18                 :                : 
                                 19                 :                : #define PGBENCH_NARGS_VARIABLE  (-1)
                                 20                 :                : #define PGBENCH_NARGS_CASE      (-2)
                                 21                 :                : #define PGBENCH_NARGS_HASH      (-3)
                                 22                 :                : #define PGBENCH_NARGS_PERMUTE   (-4)
                                 23                 :                : 
                                 24                 :                : PgBenchExpr *expr_parse_result;
                                 25                 :                : 
                                 26                 :                : static PgBenchExprList *make_elist(PgBenchExpr *expr, PgBenchExprList *list);
                                 27                 :                : static PgBenchExpr *make_null_constant(void);
                                 28                 :                : static PgBenchExpr *make_boolean_constant(bool bval);
                                 29                 :                : static PgBenchExpr *make_integer_constant(int64 ival);
                                 30                 :                : static PgBenchExpr *make_double_constant(double dval);
                                 31                 :                : static PgBenchExpr *make_variable(char *varname);
                                 32                 :                : static PgBenchExpr *make_op(yyscan_t yyscanner, const char *operator,
                                 33                 :                :                             PgBenchExpr *lexpr, PgBenchExpr *rexpr);
                                 34                 :                : static PgBenchExpr *make_uop(yyscan_t yyscanner, const char *operator, PgBenchExpr *expr);
                                 35                 :                : static int  find_func(yyscan_t yyscanner, const char *fname);
                                 36                 :                : static PgBenchExpr *make_func(yyscan_t yyscanner, int fnumber, PgBenchExprList *args);
                                 37                 :                : static PgBenchExpr *make_case(yyscan_t yyscanner, PgBenchExprList *when_then_list, PgBenchExpr *else_part);
                                 38                 :                : 
                                 39                 :                : %}
                                 40                 :                : 
                                 41                 :                : %pure-parser
                                 42                 :                : %expect 0
                                 43                 :                : %name-prefix="expr_yy"
                                 44                 :                : 
                                 45                 :                : %parse-param {yyscan_t yyscanner}
                                 46                 :                : %lex-param   {yyscan_t yyscanner}
                                 47                 :                : 
                                 48                 :                : %union
                                 49                 :                : {
                                 50                 :                :     int64       ival;
                                 51                 :                :     double      dval;
                                 52                 :                :     bool        bval;
                                 53                 :                :     char       *str;
                                 54                 :                :     PgBenchExpr *expr;
                                 55                 :                :     PgBenchExprList *elist;
                                 56                 :                : }
                                 57                 :                : 
                                 58                 :                : %type <elist> elist when_then_list
                                 59                 :                : %type <expr> expr case_control
                                 60                 :                : %type <ival> INTEGER_CONST function
                                 61                 :                : %type <dval> DOUBLE_CONST
                                 62                 :                : %type <bval> BOOLEAN_CONST
                                 63                 :                : %type <str> VARIABLE FUNCTION
                                 64                 :                : 
                                 65                 :                : %token NULL_CONST INTEGER_CONST MAXINT_PLUS_ONE_CONST DOUBLE_CONST
                                 66                 :                : %token BOOLEAN_CONST VARIABLE FUNCTION
                                 67                 :                : %token AND_OP OR_OP NOT_OP NE_OP LE_OP GE_OP LS_OP RS_OP IS_OP
                                 68                 :                : %token CASE_KW WHEN_KW THEN_KW ELSE_KW END_KW
                                 69                 :                : 
                                 70                 :                : /* Precedence: lowest to highest, taken from postgres SQL parser */
                                 71                 :                : %left   OR_OP
                                 72                 :                : %left   AND_OP
                                 73                 :                : %right  NOT_OP
                                 74                 :                : %nonassoc IS_OP ISNULL_OP NOTNULL_OP
                                 75                 :                : %nonassoc '<' '>' '=' LE_OP GE_OP NE_OP
                                 76                 :                : %left   '|' '#' '&' LS_OP RS_OP '~'
                                 77                 :                : %left   '+' '-'
                                 78                 :                : %left   '*' '/' '%'
                                 79                 :                : %right  UNARY
                                 80                 :                : 
                                 81                 :                : %%
                                 82                 :                : 
                                 83                 :                : result: expr                {
  572 tgl@sss.pgh.pa.us          84                 :CBC         367 :                                 expr_parse_result = $1;
                                 85                 :                :                                 (void) yynerrs; /* suppress compiler warning */
                                 86                 :                :                             }
                                 87                 :                : 
 2287 teodor@sigaev.ru           88                 :              5 : elist:                      { $$ = NULL; }
                                 89                 :            393 :     | expr                  { $$ = make_elist($1, NULL); }
 2966 rhaas@postgresql.org       90                 :            343 :     | elist ',' expr        { $$ = make_elist($3, $1); }
                                 91                 :                :     ;
                                 92                 :                : 
 3331                            93                 :             52 : expr: '(' expr ')'          { $$ = $2; }
 2287 teodor@sigaev.ru           94                 :              2 :     | '+' expr %prec UNARY  { $$ = $2; }
                                 95                 :                :     /* unary minus "-x" implemented as "0 - x" */
                                 96                 :             46 :     | '-' expr %prec UNARY  { $$ = make_op(yyscanner, "-",
                                 97                 :                :                                            make_integer_constant(0), $2); }
                                 98                 :                :     /* special PG_INT64_MIN handling, only after a unary minus */
                                 99                 :                :     | '-' MAXINT_PLUS_ONE_CONST %prec UNARY
 2026 andres@anarazel.de        100                 :              1 :                             { $$ = make_integer_constant(PG_INT64_MIN); }
                                101                 :                :     /* binary ones complement "~x" implemented as 0xffff... xor x" */
 2287 teodor@sigaev.ru          102                 :              2 :     | '~' expr              { $$ = make_op(yyscanner, "#",
                                103                 :                :                                            make_integer_constant(~INT64CONST(0)), $2); }
                                104                 :             12 :     | NOT_OP expr           { $$ = make_uop(yyscanner, "!not", $2); }
 2948 tgl@sss.pgh.pa.us         105                 :             48 :     | expr '+' expr         { $$ = make_op(yyscanner, "+", $1, $3); }
                                106                 :             18 :     | expr '-' expr         { $$ = make_op(yyscanner, "-", $1, $3); }
                                107                 :            204 :     | expr '*' expr         { $$ = make_op(yyscanner, "*", $1, $3); }
                                108                 :             13 :     | expr '/' expr         { $$ = make_op(yyscanner, "/", $1, $3); }
 2287 teodor@sigaev.ru          109                 :              2 :     | expr '%' expr         { $$ = make_op(yyscanner, "mod", $1, $3); }
                                110                 :             10 :     | expr '<' expr          { $$ = make_op(yyscanner, "<", $1, $3); }
                                111                 :              4 :     | expr LE_OP expr       { $$ = make_op(yyscanner, "<=", $1, $3); }
                                112                 :              6 :     | expr '>' expr          { $$ = make_op(yyscanner, "<", $3, $1); }
                                113                 :              3 :     | expr GE_OP expr       { $$ = make_op(yyscanner, "<=", $3, $1); }
                                114                 :             32 :     | expr '=' expr         { $$ = make_op(yyscanner, "=", $1, $3); }
                                115                 :              8 :     | expr NE_OP expr       { $$ = make_op(yyscanner, "<>", $1, $3); }
                                116                 :              1 :     | expr '&' expr         { $$ = make_op(yyscanner, "&", $1, $3); }
                                117                 :              2 :     | expr '|' expr         { $$ = make_op(yyscanner, "|", $1, $3); }
                                118                 :              1 :     | expr '#' expr         { $$ = make_op(yyscanner, "#", $1, $3); }
                                119                 :              7 :     | expr LS_OP expr       { $$ = make_op(yyscanner, "<<", $1, $3); }
                                120                 :              1 :     | expr RS_OP expr       { $$ = make_op(yyscanner, ">>", $1, $3); }
                                121                 :             44 :     | expr AND_OP expr      { $$ = make_op(yyscanner, "!and", $1, $3); }
                                122                 :              5 :     | expr OR_OP expr       { $$ = make_op(yyscanner, "!or", $1, $3); }
                                123                 :                :     /* IS variants */
                                124                 :              1 :     | expr ISNULL_OP        { $$ = make_op(yyscanner, "!is", $1, make_null_constant()); }
                                125                 :                :     | expr NOTNULL_OP       {
                                126                 :              2 :                                 $$ = make_uop(yyscanner, "!not",
                                127                 :              1 :                                               make_op(yyscanner, "!is", $1, make_null_constant()));
                                128                 :                :                             }
                                129                 :              4 :     | expr IS_OP NULL_CONST { $$ = make_op(yyscanner, "!is", $1, make_null_constant()); }
                                130                 :                :     | expr IS_OP NOT_OP NULL_CONST
                                131                 :                :                             {
                                132                 :              4 :                                 $$ = make_uop(yyscanner, "!not",
                                133                 :              2 :                                               make_op(yyscanner, "!is", $1, make_null_constant()));
                                134                 :                :                             }
                                135                 :                :     | expr IS_OP BOOLEAN_CONST
                                136                 :                :                             {
                                137                 :              1 :                                 $$ = make_op(yyscanner, "!is", $1, make_boolean_constant($3));
                                138                 :                :                             }
                                139                 :                :     | expr IS_OP NOT_OP BOOLEAN_CONST
                                140                 :                :                             {
                                141                 :              1 :                                 $$ = make_uop(yyscanner, "!not",
                                142                 :              1 :                                               make_op(yyscanner, "!is", $1, make_boolean_constant($4)));
                                143                 :                :                             }
                                144                 :                :     /* constants */
                                145                 :              6 :     | NULL_CONST            { $$ = make_null_constant(); }
                                146                 :             20 :     | BOOLEAN_CONST         { $$ = make_boolean_constant($1); }
 2938 tgl@sss.pgh.pa.us         147                 :            794 :     | INTEGER_CONST         { $$ = make_integer_constant($1); }
                                148                 :             61 :     | DOUBLE_CONST          { $$ = make_double_constant($1); }
                                149                 :                :     /* misc */
 2287 teodor@sigaev.ru          150                 :            270 :     | VARIABLE              { $$ = make_variable($1); }
 2948 tgl@sss.pgh.pa.us         151                 :            398 :     | function '(' elist ')' { $$ = make_func(yyscanner, $1, $3); }
 2287 teodor@sigaev.ru          152                 :             14 :     | case_control          { $$ = $1; }
                                153                 :                :     ;
                                154                 :                : 
                                155                 :                : when_then_list:
                                156                 :              2 :       when_then_list WHEN_KW expr THEN_KW expr { $$ = make_elist($5, make_elist($3, $1)); }
                                157                 :             14 :     | WHEN_KW expr THEN_KW expr { $$ = make_elist($4, make_elist($2, NULL)); }
                                158                 :                : 
                                159                 :                : case_control:
                                160                 :              4 :       CASE_KW when_then_list END_KW { $$ = make_case(yyscanner, $2, make_null_constant()); }
                                161                 :             10 :     | CASE_KW when_then_list ELSE_KW expr END_KW { $$ = make_case(yyscanner, $2, $4); }
                                162                 :                : 
 2948 tgl@sss.pgh.pa.us         163                 :            399 : function: FUNCTION          { $$ = find_func(yyscanner, $1); pg_free($1); }
                                164                 :                :     ;
                                165                 :                : 
                                166                 :                : %%
                                167                 :                : 
                                168                 :                : static PgBenchExpr *
 2287 teodor@sigaev.ru          169                 :             18 : make_null_constant(void)
                                170                 :                : {
                                171                 :             18 :     PgBenchExpr *expr = pg_malloc(sizeof(PgBenchExpr));
                                172                 :                : 
                                173                 :             18 :     expr->etype = ENODE_CONSTANT;
                                174                 :             18 :     expr->u.constant.type = PGBT_NULL;
                                175                 :             18 :     expr->u.constant.u.ival = 0;
                                176                 :             18 :     return expr;
                                177                 :                : }
                                178                 :                : 
                                179                 :                : static PgBenchExpr *
 3331 rhaas@postgresql.org      180                 :            843 : make_integer_constant(int64 ival)
                                181                 :                : {
                                182                 :            843 :     PgBenchExpr *expr = pg_malloc(sizeof(PgBenchExpr));
                                183                 :                : 
 2939                           184                 :            843 :     expr->etype = ENODE_CONSTANT;
                                185                 :            843 :     expr->u.constant.type = PGBT_INT;
                                186                 :            843 :     expr->u.constant.u.ival = ival;
                                187                 :            843 :     return expr;
                                188                 :                : }
                                189                 :                : 
                                190                 :                : static PgBenchExpr *
                                191                 :             61 : make_double_constant(double dval)
                                192                 :                : {
                                193                 :             61 :     PgBenchExpr *expr = pg_malloc(sizeof(PgBenchExpr));
                                194                 :                : 
                                195                 :             61 :     expr->etype = ENODE_CONSTANT;
                                196                 :             61 :     expr->u.constant.type = PGBT_DOUBLE;
                                197                 :             61 :     expr->u.constant.u.dval = dval;
 3331                           198                 :             61 :     return expr;
                                199                 :                : }
                                200                 :                : 
                                201                 :                : static PgBenchExpr *
 2287 teodor@sigaev.ru          202                 :             22 : make_boolean_constant(bool bval)
                                203                 :                : {
                                204                 :             22 :     PgBenchExpr *expr = pg_malloc(sizeof(PgBenchExpr));
                                205                 :                : 
                                206                 :             22 :     expr->etype = ENODE_CONSTANT;
                                207                 :             22 :     expr->u.constant.type = PGBT_BOOLEAN;
                                208                 :             22 :     expr->u.constant.u.bval = bval;
                                209                 :             22 :     return expr;
                                210                 :                : }
                                211                 :                : 
                                212                 :                : static PgBenchExpr *
 3331 rhaas@postgresql.org      213                 :            307 : make_variable(char *varname)
                                214                 :                : {
                                215                 :            307 :     PgBenchExpr *expr = pg_malloc(sizeof(PgBenchExpr));
                                216                 :                : 
                                217                 :            307 :     expr->etype = ENODE_VARIABLE;
                                218                 :            307 :     expr->u.variable.varname = varname;
                                219                 :            307 :     return expr;
                                220                 :                : }
                                221                 :                : 
                                222                 :                : /* binary operators */
                                223                 :                : static PgBenchExpr *
 2948 tgl@sss.pgh.pa.us         224                 :            467 : make_op(yyscan_t yyscanner, const char *operator,
                                225                 :                :         PgBenchExpr *lexpr, PgBenchExpr *rexpr)
                                226                 :                : {
                                227                 :            467 :     return make_func(yyscanner, find_func(yyscanner, operator),
                                228                 :                :                      make_elist(rexpr, make_elist(lexpr, NULL)));
                                229                 :                : }
                                230                 :                : 
                                231                 :                : /* unary operator */
                                232                 :                : static PgBenchExpr *
 2287 teodor@sigaev.ru          233                 :             16 : make_uop(yyscan_t yyscanner, const char *operator, PgBenchExpr *expr)
                                234                 :                : {
                                235                 :             16 :     return make_func(yyscanner, find_func(yyscanner, operator), make_elist(expr, NULL));
                                236                 :                : }
                                237                 :                : 
                                238                 :                : /*
                                239                 :                :  * List of available functions:
                                240                 :                :  * - fname: function name, "!..." for special internal functions
                                241                 :                :  * - nargs: number of arguments. Special cases:
                                242                 :                :  *          - PGBENCH_NARGS_VARIABLE is a special value for least & greatest
                                243                 :                :  *            meaning #args >= 1;
                                244                 :                :  *          - PGBENCH_NARGS_CASE is for the "CASE WHEN ..." function, which
                                245                 :                :  *            has #args >= 3 and odd;
                                246                 :                :  *          - PGBENCH_NARGS_HASH is for hash functions, which have one required
                                247                 :                :  *            and one optional argument;
                                248                 :                :  * - tag: function identifier from PgBenchFunction enum
                                249                 :                :  */
                                250                 :                : static const struct
                                251                 :                : {
                                252                 :                :     const char *fname;
                                253                 :                :     int         nargs;
                                254                 :                :     PgBenchFunction tag;
                                255                 :                : }   PGBENCH_FUNCTIONS[] =
                                256                 :                : {
                                257                 :                :     /* parsed as operators, executed as functions */
                                258                 :                :     {
                                259                 :                :         "+", 2, PGBENCH_ADD
                                260                 :                :     },
                                261                 :                :     {
                                262                 :                :         "-", 2, PGBENCH_SUB
                                263                 :                :     },
                                264                 :                :     {
                                265                 :                :         "*", 2, PGBENCH_MUL
                                266                 :                :     },
                                267                 :                :     {
                                268                 :                :         "/", 2, PGBENCH_DIV
                                269                 :                :     },
                                270                 :                :     {
                                271                 :                :         "mod", 2, PGBENCH_MOD
                                272                 :                :     },
                                273                 :                :     /* actual functions */
                                274                 :                :     {
                                275                 :                :         "abs", 1, PGBENCH_ABS
                                276                 :                :     },
                                277                 :                :     {
                                278                 :                :         "least", PGBENCH_NARGS_VARIABLE, PGBENCH_LEAST
                                279                 :                :     },
                                280                 :                :     {
                                281                 :                :         "greatest", PGBENCH_NARGS_VARIABLE, PGBENCH_GREATEST
                                282                 :                :     },
                                283                 :                :     {
                                284                 :                :         "debug", 1, PGBENCH_DEBUG
                                285                 :                :     },
                                286                 :                :     {
                                287                 :                :         "pi", 0, PGBENCH_PI
                                288                 :                :     },
                                289                 :                :     {
                                290                 :                :         "sqrt", 1, PGBENCH_SQRT
                                291                 :                :     },
                                292                 :                :     {
                                293                 :                :         "ln", 1, PGBENCH_LN
                                294                 :                :     },
                                295                 :                :     {
                                296                 :                :         "exp", 1, PGBENCH_EXP
                                297                 :                :     },
                                298                 :                :     {
                                299                 :                :         "int", 1, PGBENCH_INT
                                300                 :                :     },
                                301                 :                :     {
                                302                 :                :         "double", 1, PGBENCH_DOUBLE
                                303                 :                :     },
                                304                 :                :     {
                                305                 :                :         "random", 2, PGBENCH_RANDOM
                                306                 :                :     },
                                307                 :                :     {
                                308                 :                :         "random_gaussian", 3, PGBENCH_RANDOM_GAUSSIAN
                                309                 :                :     },
                                310                 :                :     {
                                311                 :                :         "random_exponential", 3, PGBENCH_RANDOM_EXPONENTIAL
                                312                 :                :     },
                                313                 :                :     {
                                314                 :                :         "random_zipfian", 3, PGBENCH_RANDOM_ZIPFIAN
                                315                 :                :     },
                                316                 :                :     {
                                317                 :                :         "pow", 2, PGBENCH_POW
                                318                 :                :     },
                                319                 :                :     {
                                320                 :                :         "power", 2, PGBENCH_POW
                                321                 :                :     },
                                322                 :                :     /* logical operators */
                                323                 :                :     {
                                324                 :                :         "!and", 2, PGBENCH_AND
                                325                 :                :     },
                                326                 :                :     {
                                327                 :                :         "!or", 2, PGBENCH_OR
                                328                 :                :     },
                                329                 :                :     {
                                330                 :                :         "!not", 1, PGBENCH_NOT
                                331                 :                :     },
                                332                 :                :     /* bitwise integer operators */
                                333                 :                :     {
                                334                 :                :         "&", 2, PGBENCH_BITAND
                                335                 :                :     },
                                336                 :                :     {
                                337                 :                :         "|", 2, PGBENCH_BITOR
                                338                 :                :     },
                                339                 :                :     {
                                340                 :                :         "#", 2, PGBENCH_BITXOR
                                341                 :                :     },
                                342                 :                :     {
                                343                 :                :         "<<", 2, PGBENCH_LSHIFT
                                344                 :                :     },
                                345                 :                :     {
                                346                 :                :         ">>", 2, PGBENCH_RSHIFT
                                347                 :                :     },
                                348                 :                :     /* comparison operators */
                                349                 :                :     {
                                350                 :                :         "=", 2, PGBENCH_EQ
                                351                 :                :     },
                                352                 :                :     {
                                353                 :                :         "<>", 2, PGBENCH_NE
                                354                 :                :     },
                                355                 :                :     {
                                356                 :                :         "<=", 2, PGBENCH_LE
                                357                 :                :     },
                                358                 :                :     {
                                359                 :                :         "<", 2, PGBENCH_LT
                                360                 :                :     },
                                361                 :                :     {
                                362                 :                :         "!is", 2, PGBENCH_IS
                                363                 :                :     },
                                364                 :                :     /* "case when ... then ... else ... end" construction */
                                365                 :                :     {
                                366                 :                :         "!case_end", PGBENCH_NARGS_CASE, PGBENCH_CASE
                                367                 :                :     },
                                368                 :                :     {
                                369                 :                :         "hash", PGBENCH_NARGS_HASH, PGBENCH_HASH_MURMUR2
                                370                 :                :     },
                                371                 :                :     {
                                372                 :                :         "hash_murmur2", PGBENCH_NARGS_HASH, PGBENCH_HASH_MURMUR2
                                373                 :                :     },
                                374                 :                :     {
                                375                 :                :         "hash_fnv1a", PGBENCH_NARGS_HASH, PGBENCH_HASH_FNV1A
                                376                 :                :     },
                                377                 :                :     {
                                378                 :                :         "permute", PGBENCH_NARGS_PERMUTE, PGBENCH_PERMUTE
                                379                 :                :     },
                                380                 :                :     /* keep as last array element */
                                381                 :                :     {
                                382                 :                :         NULL, 0, 0
                                383                 :                :     }
                                384                 :                : };
                                385                 :                : 
                                386                 :                : /*
                                387                 :                :  * Find a function from its name
                                388                 :                :  *
                                389                 :                :  * return the index of the function from the PGBENCH_FUNCTIONS array
                                390                 :                :  * or fail if the function is unknown.
                                391                 :                :  */
                                392                 :                : static int
 2948 tgl@sss.pgh.pa.us         393                 :            896 : find_func(yyscan_t yyscanner, const char *fname)
                                394                 :                : {
 2947                           395                 :            896 :     int         i = 0;
                                396                 :                : 
 2966 rhaas@postgresql.org      397         [ +  + ]:          12490 :     while (PGBENCH_FUNCTIONS[i].fname)
                                398                 :                :     {
                                399         [ +  + ]:          12489 :         if (pg_strcasecmp(fname, PGBENCH_FUNCTIONS[i].fname) == 0)
                                400                 :            895 :             return i;
                                401                 :          11594 :         i++;
                                402                 :                :     }
                                403                 :                : 
 2948 tgl@sss.pgh.pa.us         404                 :              1 :     expr_yyerror_more(yyscanner, "unexpected function name", fname);
                                405                 :                : 
                                406                 :                :     /* not reached */
                                407                 :                :     return -1;
                                408                 :                : }
                                409                 :                : 
                                410                 :                : /* Expression linked list builder */
                                411                 :                : static PgBenchExprList *
 2966 rhaas@postgresql.org      412                 :           1769 : make_elist(PgBenchExpr *expr, PgBenchExprList *list)
                                413                 :                : {
                                414                 :                :     PgBenchExprLink *cons;
                                415                 :                : 
                                416         [ +  + ]:           1769 :     if (list == NULL)
                                417                 :                :     {
                                418                 :            890 :         list = pg_malloc(sizeof(PgBenchExprList));
                                419                 :            890 :         list->head = NULL;
                                420                 :            890 :         list->tail = NULL;
                                421                 :                :     }
                                422                 :                : 
                                423                 :           1769 :     cons = pg_malloc(sizeof(PgBenchExprLink));
                                424                 :           1769 :     cons->expr = expr;
                                425                 :           1769 :     cons->next = NULL;
                                426                 :                : 
                                427         [ +  + ]:           1769 :     if (list->head == NULL)
                                428                 :            890 :         list->head = cons;
                                429                 :                :     else
                                430                 :            879 :         list->tail->next = cons;
                                431                 :                : 
                                432                 :           1769 :     list->tail = cons;
                                433                 :                : 
                                434                 :           1769 :     return list;
                                435                 :                : }
                                436                 :                : 
                                437                 :                : /* Return the length of an expression list */
                                438                 :                : static int
                                439                 :            895 : elist_length(PgBenchExprList *list)
                                440                 :                : {
 2947 tgl@sss.pgh.pa.us         441         [ +  + ]:            895 :     PgBenchExprLink *link = list != NULL ? list->head : NULL;
                                442                 :            895 :     int         len = 0;
                                443                 :                : 
 2966 rhaas@postgresql.org      444         [ +  + ]:           2627 :     for (; link != NULL; link = link->next)
                                445                 :           1732 :         len++;
                                446                 :                : 
                                447                 :            895 :     return len;
                                448                 :                : }
                                449                 :                : 
                                450                 :                : /* Build function call expression */
                                451                 :                : static PgBenchExpr *
 2948 tgl@sss.pgh.pa.us         452                 :            895 : make_func(yyscan_t yyscanner, int fnumber, PgBenchExprList *args)
                                453                 :                : {
 2216 teodor@sigaev.ru          454                 :            895 :     int len = elist_length(args);
                                455                 :                : 
 3331 rhaas@postgresql.org      456                 :            895 :     PgBenchExpr *expr = pg_malloc(sizeof(PgBenchExpr));
                                457                 :                : 
 2966                           458         [ -  + ]:            895 :     Assert(fnumber >= 0);
                                459                 :                : 
                                460                 :                :     /* validate arguments number including few special cases */
 2216 teodor@sigaev.ru          461   [ +  +  +  +  :            895 :     switch (PGBENCH_FUNCTIONS[fnumber].nargs)
                                                 + ]
                                462                 :                :     {
                                463                 :                :         /* check at least one arg for least & greatest */
                                464                 :              8 :         case PGBENCH_NARGS_VARIABLE:
                                465         [ +  + ]:              8 :             if (len == 0)
                                466                 :              3 :                 expr_yyerror_more(yyscanner, "at least one argument expected",
                                467                 :              3 :                                   PGBENCH_FUNCTIONS[fnumber].fname);
                                468                 :              5 :             break;
                                469                 :                : 
                                470                 :                :         /* case (when ... then ...)+ (else ...)? end */
                                471                 :             14 :         case PGBENCH_NARGS_CASE:
                                472                 :                :             /* 'else' branch is always present, but could be a NULL-constant */
                                473   [ +  -  -  + ]:             14 :             if (len < 3 || len % 2 != 1)
 2216 teodor@sigaev.ru          474                 :UBC           0 :                 expr_yyerror_more(yyscanner,
                                475                 :                :                                   "odd and >= 3 number of arguments expected",
                                476                 :                :                                   "case control structure");
 2216 teodor@sigaev.ru          477                 :CBC          14 :             break;
                                478                 :                : 
                                479                 :                :         /* hash functions with optional seed argument */
                                480                 :              8 :         case PGBENCH_NARGS_HASH:
 2088 michael@paquier.xyz       481   [ +  +  +  + ]:              8 :             if (len < 1 || len > 2)
 2216 teodor@sigaev.ru          482                 :              2 :                 expr_yyerror_more(yyscanner, "unexpected number of arguments",
                                483                 :              2 :                                   PGBENCH_FUNCTIONS[fnumber].fname);
                                484                 :                : 
                                485         [ +  + ]:              6 :             if (len == 1)
                                486                 :                :             {
                                487                 :              2 :                 PgBenchExpr *var = make_variable("default_seed");
                                488                 :              2 :                 args = make_elist(var, args);
                                489                 :                :             }
                                490                 :              6 :             break;
                                491                 :                : 
                                492                 :                :         /* pseudorandom permutation function with optional seed argument */
 1104 dean.a.rasheed@gmail      493                 :             48 :         case PGBENCH_NARGS_PERMUTE:
                                494   [ +  +  +  + ]:             48 :             if (len < 2 || len > 3)
                                495                 :              2 :                 expr_yyerror_more(yyscanner, "unexpected number of arguments",
                                496                 :              2 :                                   PGBENCH_FUNCTIONS[fnumber].fname);
                                497                 :                : 
                                498         [ +  + ]:             46 :             if (len == 2)
                                499                 :                :             {
                                500                 :             35 :                 PgBenchExpr *var = make_variable("default_seed");
                                501                 :             35 :                 args = make_elist(var, args);
                                502                 :                :             }
                                503                 :             46 :             break;
                                504                 :                : 
                                505                 :                :         /* common case: positive arguments number */
 2216 teodor@sigaev.ru          506                 :            817 :         default:
                                507         [ -  + ]:            817 :             Assert(PGBENCH_FUNCTIONS[fnumber].nargs >= 0);
                                508                 :                : 
                                509         [ +  + ]:            817 :             if (PGBENCH_FUNCTIONS[fnumber].nargs != len)
                                510                 :              1 :                 expr_yyerror_more(yyscanner, "unexpected number of arguments",
                                511                 :              1 :                                   PGBENCH_FUNCTIONS[fnumber].fname);
                                512                 :                :     }
                                513                 :                : 
 2966 rhaas@postgresql.org      514                 :            887 :     expr->etype = ENODE_FUNCTION;
                                515                 :            887 :     expr->u.function.function = PGBENCH_FUNCTIONS[fnumber].tag;
                                516                 :                : 
                                517                 :                :     /* only the link is used, the head/tail is not useful anymore */
 2947 tgl@sss.pgh.pa.us         518         [ +  + ]:            887 :     expr->u.function.args = args != NULL ? args->head : NULL;
 2966 rhaas@postgresql.org      519         [ +  + ]:            887 :     if (args)
                                520                 :            886 :         pg_free(args);
                                521                 :                : 
 3331                           522                 :            887 :     return expr;
                                523                 :                : }
                                524                 :                : 
                                525                 :                : static PgBenchExpr *
 2287 teodor@sigaev.ru          526                 :             14 : make_case(yyscan_t yyscanner, PgBenchExprList *when_then_list, PgBenchExpr *else_part)
                                527                 :                : {
                                528                 :             14 :     return make_func(yyscanner,
                                529                 :                :                      find_func(yyscanner, "!case_end"),
                                530                 :                :                      make_elist(else_part, when_then_list));
                                531                 :                : }
        

Generated by: LCOV version 2.1-beta2-3-g6141622