Hi
I am try to enhance plpgsql_check about profiler functionality and I have
to solve how to identify every plpgsql statement across different sessions.
There is lineno, but surely it should not be unique. I propose introduce
stmtid to every statement structure. This number will be unique inside
function.
Comments, notes?
Regards
Pavel
diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c
index 59460d2643..64ecfdbe2d 100644
--- a/src/pl/plpgsql/src/pl_comp.c
+++ b/src/pl/plpgsql/src/pl_comp.c
@@ -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
@@ -911,6 +913,8 @@ plpgsql_compile_inline(char *proc_source)
true);
function->found_varno = var->dno;
+ function->nstatements = 0;
+
/*
* Now parse the function's text
*/
@@ -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;
diff --git a/src/pl/plpgsql/src/pl_gram.y b/src/pl/plpgsql/src/pl_gram.y
index 68e399f9cf..744156db2b 100644
--- a/src/pl/plpgsql/src/pl_gram.y
+++ b/src/pl/plpgsql/src/pl_gram.y
@@ -415,6 +415,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;
@@ -919,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;
@@ -933,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;
@@ -948,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;
@@ -963,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;
@@ -1154,6 +1159,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;
@@ -1258,6 +1264,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;
@@ -1275,6 +1282,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;
@@ -1295,6 +1303,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;
@@ -1309,6 +1318,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;
@@ -1338,6 +1348,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;
@@ -1383,6 +1394,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 */
@@ -1497,6 +1509,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;
@@ -1531,6 +1544,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;
@@ -1631,6 +1645,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;
@@ -1677,6 +1692,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;
@@ -1768,6 +1784,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;
@@ -1912,6 +1929,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 ;",
@@ -1989,6 +2007,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;
@@ -2045,6 +2064,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;
@@ -2169,6 +2189,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;
@@ -2189,6 +2210,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;
}
@@ -2201,6 +2223,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;
}
@@ -2213,6 +2236,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;
@@ -2224,6 +2249,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;
@@ -3006,6 +3032,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;
@@ -3031,6 +3058,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;
@@ -3183,6 +3211,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;
@@ -3270,6 +3299,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;
@@ -3332,6 +3362,7 @@ make_return_query_stmt(int location)
new = palloc0(sizeof(PLpgSQL_stmt_return_query));
new->cmd_type = PLPGSQL_STMT_RETURN_QUERY;
+ new->stmtid = plpgsql_curr_compile->nstatements++;
new->lineno = plpgsql_location_to_lineno(location);
/* check for RETURN QUERY EXECUTE */
@@ -4003,6 +4034,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;
diff --git a/src/pl/plpgsql/src/plpgsql.h b/src/pl/plpgsql/src/plpgsql.h
index f6c35a5049..c6bf270594 100644
--- a/src/pl/plpgsql/src/plpgsql.h
+++ b/src/pl/plpgsql/src/plpgsql.h
@@ -448,6 +448,7 @@ typedef struct PLpgSQL_stmt
{
PLpgSQL_stmt_type cmd_type;
int lineno;
+ int stmtid;
} PLpgSQL_stmt;
/*
@@ -487,6 +488,7 @@ typedef struct PLpgSQL_stmt_block
{
PLpgSQL_stmt_type cmd_type;
int lineno;
+ int stmtid;
char *label;
List *body; /* List of statements */
int n_initvars; /* Length of initvarnos[] */
@@ -501,6 +503,7 @@ typedef struct PLpgSQL_stmt_assign
{
PLpgSQL_stmt_type cmd_type;
int lineno;
+ int stmtid;
int varno;
PLpgSQL_expr *expr;
} PLpgSQL_stmt_assign;
@@ -512,6 +515,7 @@ typedef struct PLpgSQL_stmt_perform
{
PLpgSQL_stmt_type cmd_type;
int lineno;
+ int stmtid;
PLpgSQL_expr *expr;
} PLpgSQL_stmt_perform;
@@ -522,6 +526,7 @@ typedef struct PLpgSQL_stmt_call
{
PLpgSQL_stmt_type cmd_type;
int lineno;
+ int stmtid;
PLpgSQL_expr *expr;
bool is_call;
PLpgSQL_variable *target;
@@ -534,6 +539,7 @@ typedef struct PLpgSQL_stmt_commit
{
PLpgSQL_stmt_type cmd_type;
int lineno;
+ int stmtid;
} PLpgSQL_stmt_commit;
/*
@@ -543,6 +549,7 @@ typedef struct PLpgSQL_stmt_rollback
{
PLpgSQL_stmt_type cmd_type;
int lineno;
+ int stmtid;
} PLpgSQL_stmt_rollback;
/*
@@ -552,6 +559,7 @@ typedef struct PLpgSQL_stmt_set
{
PLpgSQL_stmt_type cmd_type;
int lineno;
+ int stmtid;
PLpgSQL_expr *expr;
} PLpgSQL_stmt_set;
@@ -571,6 +579,7 @@ typedef struct PLpgSQL_stmt_getdiag
{
PLpgSQL_stmt_type cmd_type;
int lineno;
+ int stmtid;
bool is_stacked; /* STACKED or CURRENT diagnostics area? */
List *diag_items; /* List of PLpgSQL_diag_item */
} PLpgSQL_stmt_getdiag;
@@ -582,6 +591,7 @@ typedef struct PLpgSQL_stmt_if
{
PLpgSQL_stmt_type cmd_type;
int lineno;
+ int stmtid;
PLpgSQL_expr *cond; /* boolean expression for THEN */
List *then_body; /* List of statements */
List *elsif_list; /* List of PLpgSQL_if_elsif structs */
@@ -605,6 +615,7 @@ typedef struct PLpgSQL_stmt_case
{
PLpgSQL_stmt_type cmd_type;
int lineno;
+ 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 +639,7 @@ typedef struct PLpgSQL_case_when
typedef struct PLpgSQL_stmt_loop
{
PLpgSQL_stmt_type cmd_type;
+ int stmtid;
int lineno;
char *label;
List *body; /* List of statements */
@@ -640,6 +652,7 @@ typedef struct PLpgSQL_stmt_while
{
PLpgSQL_stmt_type cmd_type;
int lineno;
+ int stmtid;
char *label;
PLpgSQL_expr *cond;
List *body; /* List of statements */
@@ -652,6 +665,7 @@ typedef struct PLpgSQL_stmt_fori
{
PLpgSQL_stmt_type cmd_type;
int lineno;
+ int stmtid;
char *label;
PLpgSQL_var *var;
PLpgSQL_expr *lower;
@@ -670,6 +684,7 @@ typedef struct PLpgSQL_stmt_forq
{
PLpgSQL_stmt_type cmd_type;
int lineno;
+ int stmtid;
char *label;
PLpgSQL_variable *var; /* Loop variable (record or row) */
List *body; /* List of statements */
@@ -682,6 +697,7 @@ typedef struct PLpgSQL_stmt_fors
{
PLpgSQL_stmt_type cmd_type;
int lineno;
+ int stmtid;
char *label;
PLpgSQL_variable *var; /* Loop variable (record or row) */
List *body; /* List of statements */
@@ -696,6 +712,7 @@ typedef struct PLpgSQL_stmt_forc
{
PLpgSQL_stmt_type cmd_type;
int lineno;
+ int stmtid;
char *label;
PLpgSQL_variable *var; /* Loop variable (record or row) */
List *body; /* List of statements */
@@ -711,6 +728,7 @@ typedef struct PLpgSQL_stmt_dynfors
{
PLpgSQL_stmt_type cmd_type;
int lineno;
+ int stmtid;
char *label;
PLpgSQL_variable *var; /* Loop variable (record or row) */
List *body; /* List of statements */
@@ -726,6 +744,7 @@ typedef struct PLpgSQL_stmt_foreach_a
{
PLpgSQL_stmt_type cmd_type;
int lineno;
+ int stmtid;
char *label;
int varno; /* loop target variable */
int slice; /* slice dimension, or 0 */
@@ -740,6 +759,7 @@ typedef struct PLpgSQL_stmt_open
{
PLpgSQL_stmt_type cmd_type;
int lineno;
+ int stmtid;
int curvar;
int cursor_options;
PLpgSQL_expr *argquery;
@@ -755,6 +775,7 @@ typedef struct PLpgSQL_stmt_fetch
{
PLpgSQL_stmt_type cmd_type;
int lineno;
+ int stmtid;
PLpgSQL_variable *target; /* target (record or row) */
int curvar; /* cursor variable to fetch from */
FetchDirection direction; /* fetch direction */
@@ -771,6 +792,7 @@ typedef struct PLpgSQL_stmt_close
{
PLpgSQL_stmt_type cmd_type;
int lineno;
+ int stmtid;
int curvar;
} PLpgSQL_stmt_close;
@@ -781,6 +803,7 @@ typedef struct PLpgSQL_stmt_exit
{
PLpgSQL_stmt_type cmd_type;
int lineno;
+ 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;
@@ -793,6 +816,7 @@ typedef struct PLpgSQL_stmt_return
{
PLpgSQL_stmt_type cmd_type;
int lineno;
+ int stmtid;
PLpgSQL_expr *expr;
int retvarno;
} PLpgSQL_stmt_return;
@@ -804,6 +828,7 @@ typedef struct PLpgSQL_stmt_return_next
{
PLpgSQL_stmt_type cmd_type;
int lineno;
+ int stmtid;
PLpgSQL_expr *expr;
int retvarno;
} PLpgSQL_stmt_return_next;
@@ -815,6 +840,7 @@ typedef struct PLpgSQL_stmt_return_query
{
PLpgSQL_stmt_type cmd_type;
int lineno;
+ int stmtid;
PLpgSQL_expr *query; /* if static query */
PLpgSQL_expr *dynquery; /* if dynamic query (RETURN QUERY EXECUTE) */
List *params; /* USING arguments for dynamic query */
@@ -827,6 +853,7 @@ typedef struct PLpgSQL_stmt_raise
{
PLpgSQL_stmt_type cmd_type;
int lineno;
+ int stmtid;
int elog_level;
char *condname; /* condition name, SQLSTATE, or NULL */
char *message; /* old-style message format literal, or NULL */
@@ -850,6 +877,7 @@ typedef struct PLpgSQL_stmt_assert
{
PLpgSQL_stmt_type cmd_type;
int lineno;
+ int stmtid;
PLpgSQL_expr *cond;
PLpgSQL_expr *message;
} PLpgSQL_stmt_assert;
@@ -861,6 +889,7 @@ typedef struct PLpgSQL_stmt_execsql
{
PLpgSQL_stmt_type cmd_type;
int lineno;
+ int stmtid;
PLpgSQL_expr *sqlstmt;
bool mod_stmt; /* is the stmt INSERT/UPDATE/DELETE? Note:
* mod_stmt is set when we plan the query */
@@ -876,6 +905,7 @@ typedef struct PLpgSQL_stmt_dynexecute
{
PLpgSQL_stmt_type cmd_type;
int lineno;
+ int stmtid;
PLpgSQL_expr *query; /* string expression */
bool into; /* INTO supplied? */
bool strict; /* INTO STRICT flag */
@@ -972,6 +1002,9 @@ typedef struct PLpgSQL_function
/* function body parsetree */
PLpgSQL_stmt_block *action;
+ /* number of statements inside functions */
+ int nstatements;
+
/* these fields change when the function is used */
struct PLpgSQL_execstate *cur_estate;
unsigned long use_count;