PL/pgSQL: Add statement ID to statement structures
authorPeter Eisentraut <[email protected]>
Thu, 24 Jan 2019 21:23:12 +0000 (22:23 +0100)
committerPeter Eisentraut <[email protected]>
Thu, 24 Jan 2019 21:23:12 +0000 (22:23 +0100)
This can be used by a profiler as the index for an array of
per-statement metrics.

Author: Pavel Stehule <[email protected]>
Reviewed-by: Peter Eisentraut <[email protected]>
Discussion: https://www.postgresql.org/message-id/flat/CAFj8pRDRCjN6rpM9ZccU7Ta_afsNX7mg9=n34F+r445Nt9v2tA@mail.gmail.com/

src/pl/plpgsql/src/pl_comp.c
src/pl/plpgsql/src/pl_gram.y
src/pl/plpgsql/src/plpgsql.h

index 2454386af84500adf543250c09ed20b3cf3bc4be..3b8e137ab584fcd8a5a2742d972ecde653baa80e 100644 (file)
@@ -368,6 +368,8 @@ do_compile(FunctionCallInfo fcinfo,
 
    function->fn_prokind = procStruct->prokind;
 
+   function->nstatements = 0;
+
    /*
     * Initialize the compiler, particularly the namespace stack.  The
     * outermost namespace contains function parameters and other special
@@ -880,6 +882,8 @@ plpgsql_compile_inline(char *proc_source)
    function->extra_warnings = 0;
    function->extra_errors = 0;
 
+   function->nstatements = 0;
+
    plpgsql_ns_init();
    plpgsql_ns_push(func_name, PLPGSQL_LABEL_BLOCK);
    plpgsql_DumpExecTree = false;
@@ -1020,6 +1024,7 @@ add_dummy_return(PLpgSQL_function *function)
 
        new = palloc0(sizeof(PLpgSQL_stmt_block));
        new->cmd_type = PLPGSQL_STMT_BLOCK;
+       new->stmtid = ++function->nstatements;
        new->body = list_make1(function->action);
 
        function->action = new;
@@ -1031,6 +1036,7 @@ add_dummy_return(PLpgSQL_function *function)
 
        new = palloc0(sizeof(PLpgSQL_stmt_return));
        new->cmd_type = PLPGSQL_STMT_RETURN;
+       new->stmtid = ++function->nstatements;
        new->expr = NULL;
        new->retvarno = function->out_param_varno;
 
index 59063976b36dd3fa6377af2d47de5c70e3d381f0..03f7cdce8cd5fafdacfcc4d8c053eadd01c26ed7 100644 (file)
@@ -414,6 +414,7 @@ pl_block        : decl_sect K_BEGIN proc_sect exception_sect K_END opt_label
 
                        new->cmd_type   = PLPGSQL_STMT_BLOCK;
                        new->lineno     = plpgsql_location_to_lineno(@2);
+                       new->stmtid     = ++plpgsql_curr_compile->nstatements;
                        new->label      = $1.label;
                        new->n_initvars = $1.n_initvars;
                        new->initvarnos = $1.initvarnos;
@@ -905,6 +906,7 @@ stmt_perform    : K_PERFORM expr_until_semi
                        new = palloc0(sizeof(PLpgSQL_stmt_perform));
                        new->cmd_type = PLPGSQL_STMT_PERFORM;
                        new->lineno   = plpgsql_location_to_lineno(@1);
+                       new->stmtid = ++plpgsql_curr_compile->nstatements;
                        new->expr  = $2;
 
                        $$ = (PLpgSQL_stmt *)new;
@@ -918,6 +920,7 @@ stmt_call       : K_CALL
                        new = palloc0(sizeof(PLpgSQL_stmt_call));
                        new->cmd_type = PLPGSQL_STMT_CALL;
                        new->lineno = plpgsql_location_to_lineno(@1);
+                       new->stmtid = ++plpgsql_curr_compile->nstatements;
                        new->expr = read_sql_stmt("CALL ");
                        new->is_call = true;
 
@@ -932,6 +935,7 @@ stmt_call       : K_CALL
                        new = palloc0(sizeof(PLpgSQL_stmt_call));
                        new->cmd_type = PLPGSQL_STMT_CALL;
                        new->lineno = plpgsql_location_to_lineno(@1);
+                       new->stmtid = ++plpgsql_curr_compile->nstatements;
                        new->expr = read_sql_stmt("DO ");
                        new->is_call = false;
 
@@ -947,6 +951,7 @@ stmt_assign     : assign_var assign_operator expr_until_semi
                        new = palloc0(sizeof(PLpgSQL_stmt_assign));
                        new->cmd_type = PLPGSQL_STMT_ASSIGN;
                        new->lineno   = plpgsql_location_to_lineno(@1);
+                       new->stmtid = ++plpgsql_curr_compile->nstatements;
                        new->varno = $1->dno;
                        new->expr  = $3;
 
@@ -962,6 +967,7 @@ stmt_getdiag    : K_GET getdiag_area_opt K_DIAGNOSTICS getdiag_list ';'
                        new = palloc0(sizeof(PLpgSQL_stmt_getdiag));
                        new->cmd_type = PLPGSQL_STMT_GETDIAG;
                        new->lineno   = plpgsql_location_to_lineno(@1);
+                       new->stmtid   = ++plpgsql_curr_compile->nstatements;
                        new->is_stacked = $2;
                        new->diag_items = $4;
 
@@ -1149,6 +1155,7 @@ stmt_if           : K_IF expr_until_then proc_sect stmt_elsifs stmt_else K_END K_IF ';'
                        new = palloc0(sizeof(PLpgSQL_stmt_if));
                        new->cmd_type   = PLPGSQL_STMT_IF;
                        new->lineno     = plpgsql_location_to_lineno(@1);
+                       new->stmtid     = ++plpgsql_curr_compile->nstatements;
                        new->cond       = $2;
                        new->then_body  = $3;
                        new->elsif_list = $4;
@@ -1253,6 +1260,7 @@ stmt_loop     : opt_loop_label K_LOOP loop_body
                        new = palloc0(sizeof(PLpgSQL_stmt_loop));
                        new->cmd_type = PLPGSQL_STMT_LOOP;
                        new->lineno   = plpgsql_location_to_lineno(@2);
+                       new->stmtid   = ++plpgsql_curr_compile->nstatements;
                        new->label    = $1;
                        new->body     = $3.stmts;
 
@@ -1270,6 +1278,7 @@ stmt_while        : opt_loop_label K_WHILE expr_until_loop loop_body
                        new = palloc0(sizeof(PLpgSQL_stmt_while));
                        new->cmd_type = PLPGSQL_STMT_WHILE;
                        new->lineno   = plpgsql_location_to_lineno(@2);
+                       new->stmtid   = ++plpgsql_curr_compile->nstatements;
                        new->label    = $1;
                        new->cond     = $3;
                        new->body     = $4.stmts;
@@ -1290,6 +1299,7 @@ stmt_for      : opt_loop_label K_FOR for_control loop_body
 
                            new = (PLpgSQL_stmt_fori *) $3;
                            new->lineno   = plpgsql_location_to_lineno(@2);
+                           new->stmtid   = ++plpgsql_curr_compile->nstatements;
                            new->label    = $1;
                            new->body     = $4.stmts;
                            $$ = (PLpgSQL_stmt *) new;
@@ -1304,6 +1314,7 @@ stmt_for      : opt_loop_label K_FOR for_control loop_body
                            /* forq is the common supertype of all three */
                            new = (PLpgSQL_stmt_forq *) $3;
                            new->lineno   = plpgsql_location_to_lineno(@2);
+                           new->stmtid   = ++plpgsql_curr_compile->nstatements;
                            new->label    = $1;
                            new->body     = $4.stmts;
                            $$ = (PLpgSQL_stmt *) new;
@@ -1333,6 +1344,7 @@ for_control       : for_variable K_IN
 
                            new = palloc0(sizeof(PLpgSQL_stmt_dynfors));
                            new->cmd_type = PLPGSQL_STMT_DYNFORS;
+                           new->stmtid   = ++plpgsql_curr_compile->nstatements;
                            if ($1.row)
                            {
                                new->var = (PLpgSQL_variable *) $1.row;
@@ -1378,6 +1390,7 @@ for_control       : for_variable K_IN
 
                            new = (PLpgSQL_stmt_forc *) palloc0(sizeof(PLpgSQL_stmt_forc));
                            new->cmd_type = PLPGSQL_STMT_FORC;
+                           new->stmtid = ++plpgsql_curr_compile->nstatements;
                            new->curvar = cursor->dno;
 
                            /* Should have had a single variable name */
@@ -1492,6 +1505,7 @@ for_control       : for_variable K_IN
 
                                new = palloc0(sizeof(PLpgSQL_stmt_fori));
                                new->cmd_type = PLPGSQL_STMT_FORI;
+                               new->stmtid   = ++plpgsql_curr_compile->nstatements;
                                new->var      = fvar;
                                new->reverse  = reverse;
                                new->lower    = expr1;
@@ -1526,6 +1540,7 @@ for_control       : for_variable K_IN
 
                                new = palloc0(sizeof(PLpgSQL_stmt_fors));
                                new->cmd_type = PLPGSQL_STMT_FORS;
+                               new->stmtid = ++plpgsql_curr_compile->nstatements;
                                if ($1.row)
                                {
                                    new->var = (PLpgSQL_variable *) $1.row;
@@ -1626,6 +1641,7 @@ stmt_foreach_a    : opt_loop_label K_FOREACH for_variable foreach_slice K_IN K_ARRA
                        new = palloc0(sizeof(PLpgSQL_stmt_foreach_a));
                        new->cmd_type = PLPGSQL_STMT_FOREACH_A;
                        new->lineno = plpgsql_location_to_lineno(@2);
+                       new->stmtid = ++plpgsql_curr_compile->nstatements;
                        new->label = $1;
                        new->slice = $4;
                        new->expr = $7;
@@ -1672,6 +1688,7 @@ stmt_exit     : exit_type opt_label opt_exitcond
 
                        new = palloc0(sizeof(PLpgSQL_stmt_exit));
                        new->cmd_type = PLPGSQL_STMT_EXIT;
+                       new->stmtid   = ++plpgsql_curr_compile->nstatements;
                        new->is_exit  = $1;
                        new->lineno   = plpgsql_location_to_lineno(@1);
                        new->label    = $2;
@@ -1763,6 +1780,7 @@ stmt_raise        : K_RAISE
 
                        new->cmd_type   = PLPGSQL_STMT_RAISE;
                        new->lineno     = plpgsql_location_to_lineno(@1);
+                       new->stmtid     = ++plpgsql_curr_compile->nstatements;
                        new->elog_level = ERROR;    /* default */
                        new->condname   = NULL;
                        new->message    = NULL;
@@ -1907,6 +1925,7 @@ stmt_assert       : K_ASSERT
 
                        new->cmd_type   = PLPGSQL_STMT_ASSERT;
                        new->lineno     = plpgsql_location_to_lineno(@1);
+                       new->stmtid     = ++plpgsql_curr_compile->nstatements;
 
                        new->cond = read_sql_expression2(',', ';',
                                                         ", or ;",
@@ -1984,6 +2003,7 @@ stmt_dynexecute : K_EXECUTE
                        new = palloc(sizeof(PLpgSQL_stmt_dynexecute));
                        new->cmd_type = PLPGSQL_STMT_DYNEXECUTE;
                        new->lineno = plpgsql_location_to_lineno(@1);
+                       new->stmtid = ++plpgsql_curr_compile->nstatements;
                        new->query = expr;
                        new->into = false;
                        new->strict = false;
@@ -2040,6 +2060,7 @@ stmt_open     : K_OPEN cursor_variable
                        new = palloc0(sizeof(PLpgSQL_stmt_open));
                        new->cmd_type = PLPGSQL_STMT_OPEN;
                        new->lineno = plpgsql_location_to_lineno(@1);
+                       new->stmtid = ++plpgsql_curr_compile->nstatements;
                        new->curvar = $2->dno;
                        new->cursor_options = CURSOR_OPT_FAST_PLAN;
 
@@ -2164,6 +2185,7 @@ stmt_close        : K_CLOSE cursor_variable ';'
                        new = palloc(sizeof(PLpgSQL_stmt_close));
                        new->cmd_type = PLPGSQL_STMT_CLOSE;
                        new->lineno = plpgsql_location_to_lineno(@1);
+                       new->stmtid = ++plpgsql_curr_compile->nstatements;
                        new->curvar = $2->dno;
 
                        $$ = (PLpgSQL_stmt *)new;
@@ -2184,6 +2206,7 @@ stmt_commit       : K_COMMIT ';'
                        new = palloc(sizeof(PLpgSQL_stmt_commit));
                        new->cmd_type = PLPGSQL_STMT_COMMIT;
                        new->lineno = plpgsql_location_to_lineno(@1);
+                       new->stmtid = ++plpgsql_curr_compile->nstatements;
 
                        $$ = (PLpgSQL_stmt *)new;
                    }
@@ -2196,6 +2219,7 @@ stmt_rollback : K_ROLLBACK ';'
                        new = palloc(sizeof(PLpgSQL_stmt_rollback));
                        new->cmd_type = PLPGSQL_STMT_ROLLBACK;
                        new->lineno = plpgsql_location_to_lineno(@1);
+                       new->stmtid = ++plpgsql_curr_compile->nstatements;
 
                        $$ = (PLpgSQL_stmt *)new;
                    }
@@ -2208,6 +2232,8 @@ stmt_set  : K_SET
                        new = palloc0(sizeof(PLpgSQL_stmt_set));
                        new->cmd_type = PLPGSQL_STMT_SET;
                        new->lineno = plpgsql_location_to_lineno(@1);
+                       new->stmtid = ++plpgsql_curr_compile->nstatements;
+
                        new->expr = read_sql_stmt("SET ");
 
                        $$ = (PLpgSQL_stmt *)new;
@@ -2219,6 +2245,7 @@ stmt_set  : K_SET
                        new = palloc0(sizeof(PLpgSQL_stmt_set));
                        new->cmd_type = PLPGSQL_STMT_SET;
                        new->lineno = plpgsql_location_to_lineno(@1);
+                       new->stmtid = ++plpgsql_curr_compile->nstatements;
                        new->expr = read_sql_stmt("RESET ");
 
                        $$ = (PLpgSQL_stmt *)new;
@@ -3000,6 +3027,7 @@ make_execsql_stmt(int firsttoken, int location)
    execsql = palloc(sizeof(PLpgSQL_stmt_execsql));
    execsql->cmd_type = PLPGSQL_STMT_EXECSQL;
    execsql->lineno  = plpgsql_location_to_lineno(location);
+   execsql->stmtid  = ++plpgsql_curr_compile->nstatements;
    execsql->sqlstmt = expr;
    execsql->into    = have_into;
    execsql->strict  = have_strict;
@@ -3025,6 +3053,7 @@ read_fetch_direction(void)
     */
    fetch = (PLpgSQL_stmt_fetch *) palloc0(sizeof(PLpgSQL_stmt_fetch));
    fetch->cmd_type = PLPGSQL_STMT_FETCH;
+   fetch->stmtid   = ++plpgsql_curr_compile->nstatements;
    /* set direction defaults: */
    fetch->direction = FETCH_FORWARD;
    fetch->how_many  = 1;
@@ -3177,6 +3206,7 @@ make_return_stmt(int location)
    new = palloc0(sizeof(PLpgSQL_stmt_return));
    new->cmd_type = PLPGSQL_STMT_RETURN;
    new->lineno   = plpgsql_location_to_lineno(location);
+   new->stmtid   = ++plpgsql_curr_compile->nstatements;
    new->expr     = NULL;
    new->retvarno = -1;
 
@@ -3264,6 +3294,7 @@ make_return_next_stmt(int location)
    new = palloc0(sizeof(PLpgSQL_stmt_return_next));
    new->cmd_type   = PLPGSQL_STMT_RETURN_NEXT;
    new->lineno     = plpgsql_location_to_lineno(location);
+   new->stmtid     = ++plpgsql_curr_compile->nstatements;
    new->expr       = NULL;
    new->retvarno   = -1;
 
@@ -3327,6 +3358,7 @@ make_return_query_stmt(int location)
    new = palloc0(sizeof(PLpgSQL_stmt_return_query));
    new->cmd_type = PLPGSQL_STMT_RETURN_QUERY;
    new->lineno = plpgsql_location_to_lineno(location);
+   new->stmtid = ++plpgsql_curr_compile->nstatements;
 
    /* check for RETURN QUERY EXECUTE */
    if ((tok = yylex()) != K_EXECUTE)
@@ -3997,6 +4029,7 @@ make_case(int location, PLpgSQL_expr *t_expr,
    new = palloc(sizeof(PLpgSQL_stmt_case));
    new->cmd_type = PLPGSQL_STMT_CASE;
    new->lineno = plpgsql_location_to_lineno(location);
+   new->stmtid = ++plpgsql_curr_compile->nstatements;
    new->t_expr = t_expr;
    new->t_varno = 0;
    new->case_when_list = case_when_list;
index a7118b8386101ece1177248bf122b63b2e4f877d..0a5fbfa9d689bb7c6cfc25b33b540bfa39db6465 100644 (file)
@@ -447,6 +447,13 @@ typedef struct PLpgSQL_stmt
 {
    PLpgSQL_stmt_type cmd_type;
    int         lineno;
+
+   /*
+    * Unique statement ID in this function (starting at 1; 0 is invalid/not
+    * set).  This can be used by a profiler as the index for an array of
+    * per-statement metrics.
+    */
+   unsigned int    stmtid;
 } PLpgSQL_stmt;
 
 /*
@@ -486,6 +493,7 @@ typedef struct PLpgSQL_stmt_block
 {
    PLpgSQL_stmt_type cmd_type;
    int         lineno;
+   unsigned int stmtid;
    char       *label;
    List       *body;           /* List of statements */
    int         n_initvars;     /* Length of initvarnos[] */
@@ -500,6 +508,7 @@ typedef struct PLpgSQL_stmt_assign
 {
    PLpgSQL_stmt_type cmd_type;
    int         lineno;
+   unsigned int stmtid;
    int         varno;
    PLpgSQL_expr *expr;
 } PLpgSQL_stmt_assign;
@@ -511,6 +520,7 @@ typedef struct PLpgSQL_stmt_perform
 {
    PLpgSQL_stmt_type cmd_type;
    int         lineno;
+   unsigned int stmtid;
    PLpgSQL_expr *expr;
 } PLpgSQL_stmt_perform;
 
@@ -521,6 +531,7 @@ typedef struct PLpgSQL_stmt_call
 {
    PLpgSQL_stmt_type cmd_type;
    int         lineno;
+   unsigned int stmtid;
    PLpgSQL_expr *expr;
    bool        is_call;
    PLpgSQL_variable *target;
@@ -533,6 +544,7 @@ typedef struct PLpgSQL_stmt_commit
 {
    PLpgSQL_stmt_type cmd_type;
    int         lineno;
+   unsigned int stmtid;
 } PLpgSQL_stmt_commit;
 
 /*
@@ -542,6 +554,7 @@ typedef struct PLpgSQL_stmt_rollback
 {
    PLpgSQL_stmt_type cmd_type;
    int         lineno;
+   unsigned int stmtid;
 } PLpgSQL_stmt_rollback;
 
 /*
@@ -551,6 +564,7 @@ typedef struct PLpgSQL_stmt_set
 {
    PLpgSQL_stmt_type cmd_type;
    int         lineno;
+   unsigned int stmtid;
    PLpgSQL_expr *expr;
 } PLpgSQL_stmt_set;
 
@@ -570,6 +584,7 @@ typedef struct PLpgSQL_stmt_getdiag
 {
    PLpgSQL_stmt_type cmd_type;
    int         lineno;
+   unsigned int stmtid;
    bool        is_stacked;     /* STACKED or CURRENT diagnostics area? */
    List       *diag_items;     /* List of PLpgSQL_diag_item */
 } PLpgSQL_stmt_getdiag;
@@ -581,6 +596,7 @@ typedef struct PLpgSQL_stmt_if
 {
    PLpgSQL_stmt_type cmd_type;
    int         lineno;
+   unsigned int stmtid;
    PLpgSQL_expr *cond;         /* boolean expression for THEN */
    List       *then_body;      /* List of statements */
    List       *elsif_list;     /* List of PLpgSQL_if_elsif structs */
@@ -604,6 +620,7 @@ typedef struct PLpgSQL_stmt_case
 {
    PLpgSQL_stmt_type cmd_type;
    int         lineno;
+   unsigned int stmtid;
    PLpgSQL_expr *t_expr;       /* test expression, or NULL if none */
    int         t_varno;        /* var to store test expression value into */
    List       *case_when_list; /* List of PLpgSQL_case_when structs */
@@ -628,6 +645,7 @@ typedef struct PLpgSQL_stmt_loop
 {
    PLpgSQL_stmt_type cmd_type;
    int         lineno;
+   unsigned int stmtid;
    char       *label;
    List       *body;           /* List of statements */
 } PLpgSQL_stmt_loop;
@@ -639,6 +657,7 @@ typedef struct PLpgSQL_stmt_while
 {
    PLpgSQL_stmt_type cmd_type;
    int         lineno;
+   unsigned int stmtid;
    char       *label;
    PLpgSQL_expr *cond;
    List       *body;           /* List of statements */
@@ -651,6 +670,7 @@ typedef struct PLpgSQL_stmt_fori
 {
    PLpgSQL_stmt_type cmd_type;
    int         lineno;
+   unsigned int stmtid;
    char       *label;
    PLpgSQL_var *var;
    PLpgSQL_expr *lower;
@@ -669,6 +689,7 @@ typedef struct PLpgSQL_stmt_forq
 {
    PLpgSQL_stmt_type cmd_type;
    int         lineno;
+   unsigned int stmtid;
    char       *label;
    PLpgSQL_variable *var;      /* Loop variable (record or row) */
    List       *body;           /* List of statements */
@@ -681,6 +702,7 @@ typedef struct PLpgSQL_stmt_fors
 {
    PLpgSQL_stmt_type cmd_type;
    int         lineno;
+   unsigned int stmtid;
    char       *label;
    PLpgSQL_variable *var;      /* Loop variable (record or row) */
    List       *body;           /* List of statements */
@@ -695,6 +717,7 @@ typedef struct PLpgSQL_stmt_forc
 {
    PLpgSQL_stmt_type cmd_type;
    int         lineno;
+   unsigned int stmtid;
    char       *label;
    PLpgSQL_variable *var;      /* Loop variable (record or row) */
    List       *body;           /* List of statements */
@@ -710,6 +733,7 @@ typedef struct PLpgSQL_stmt_dynfors
 {
    PLpgSQL_stmt_type cmd_type;
    int         lineno;
+   unsigned int stmtid;
    char       *label;
    PLpgSQL_variable *var;      /* Loop variable (record or row) */
    List       *body;           /* List of statements */
@@ -725,6 +749,7 @@ typedef struct PLpgSQL_stmt_foreach_a
 {
    PLpgSQL_stmt_type cmd_type;
    int         lineno;
+   unsigned int stmtid;
    char       *label;
    int         varno;          /* loop target variable */
    int         slice;          /* slice dimension, or 0 */
@@ -739,6 +764,7 @@ typedef struct PLpgSQL_stmt_open
 {
    PLpgSQL_stmt_type cmd_type;
    int         lineno;
+   unsigned int stmtid;
    int         curvar;
    int         cursor_options;
    PLpgSQL_expr *argquery;
@@ -754,6 +780,7 @@ typedef struct PLpgSQL_stmt_fetch
 {
    PLpgSQL_stmt_type cmd_type;
    int         lineno;
+   unsigned int stmtid;
    PLpgSQL_variable *target;   /* target (record or row) */
    int         curvar;         /* cursor variable to fetch from */
    FetchDirection direction;   /* fetch direction */
@@ -770,6 +797,7 @@ typedef struct PLpgSQL_stmt_close
 {
    PLpgSQL_stmt_type cmd_type;
    int         lineno;
+   unsigned int stmtid;
    int         curvar;
 } PLpgSQL_stmt_close;
 
@@ -780,6 +808,7 @@ typedef struct PLpgSQL_stmt_exit
 {
    PLpgSQL_stmt_type cmd_type;
    int         lineno;
+   unsigned int stmtid;
    bool        is_exit;        /* Is this an exit or a continue? */
    char       *label;          /* NULL if it's an unlabelled EXIT/CONTINUE */
    PLpgSQL_expr *cond;
@@ -792,6 +821,7 @@ typedef struct PLpgSQL_stmt_return
 {
    PLpgSQL_stmt_type cmd_type;
    int         lineno;
+   unsigned int stmtid;
    PLpgSQL_expr *expr;
    int         retvarno;
 } PLpgSQL_stmt_return;
@@ -803,6 +833,7 @@ typedef struct PLpgSQL_stmt_return_next
 {
    PLpgSQL_stmt_type cmd_type;
    int         lineno;
+   unsigned int stmtid;
    PLpgSQL_expr *expr;
    int         retvarno;
 } PLpgSQL_stmt_return_next;
@@ -814,6 +845,7 @@ typedef struct PLpgSQL_stmt_return_query
 {
    PLpgSQL_stmt_type cmd_type;
    int         lineno;
+   unsigned int stmtid;
    PLpgSQL_expr *query;        /* if static query */
    PLpgSQL_expr *dynquery;     /* if dynamic query (RETURN QUERY EXECUTE) */
    List       *params;         /* USING arguments for dynamic query */
@@ -826,6 +858,7 @@ typedef struct PLpgSQL_stmt_raise
 {
    PLpgSQL_stmt_type cmd_type;
    int         lineno;
+   unsigned int stmtid;
    int         elog_level;
    char       *condname;       /* condition name, SQLSTATE, or NULL */
    char       *message;        /* old-style message format literal, or NULL */
@@ -849,6 +882,7 @@ typedef struct PLpgSQL_stmt_assert
 {
    PLpgSQL_stmt_type cmd_type;
    int         lineno;
+   unsigned int stmtid;
    PLpgSQL_expr *cond;
    PLpgSQL_expr *message;
 } PLpgSQL_stmt_assert;
@@ -860,6 +894,7 @@ typedef struct PLpgSQL_stmt_execsql
 {
    PLpgSQL_stmt_type cmd_type;
    int         lineno;
+   unsigned int stmtid;
    PLpgSQL_expr *sqlstmt;
    bool        mod_stmt;       /* is the stmt INSERT/UPDATE/DELETE?  Note:
                                 * mod_stmt is set when we plan the query */
@@ -875,6 +910,7 @@ typedef struct PLpgSQL_stmt_dynexecute
 {
    PLpgSQL_stmt_type cmd_type;
    int         lineno;
+   unsigned int stmtid;
    PLpgSQL_expr *query;        /* string expression */
    bool        into;           /* INTO supplied? */
    bool        strict;         /* INTO STRICT flag */
@@ -963,6 +999,9 @@ typedef struct PLpgSQL_function
    int         extra_warnings;
    int         extra_errors;
 
+   /* count of statements inside function */
+   unsigned int nstatements;
+
    /* the datums representing the function's local variables */
    int         ndatums;
    PLpgSQL_datum **datums;