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;