Hi fresh rebase
Regards Pavel
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..1bafd202ff 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -4093,6 +4093,8 @@ plpgsql_estate_setup(PLpgSQL_execstate *estate, { (*plpgsql_plugin_ptr)->error_callback = plpgsql_exec_error_callback; (*plpgsql_plugin_ptr)->assign_expr = exec_assign_expr; + (*plpgsql_plugin_ptr)->eval_datum = exec_eval_datum; + (*plpgsql_plugin_ptr)->cast_value = do_cast_value; if ((*plpgsql_plugin_ptr)->func_setup) ((*plpgsql_plugin_ptr)->func_setup) (estate, func); diff --git a/src/pl/plpgsql/src/pl_gram.y b/src/pl/plpgsql/src/pl_gram.y index 34e0520719..d23b1f5752 100644 --- a/src/pl/plpgsql/src/pl_gram.y +++ b/src/pl/plpgsql/src/pl_gram.y @@ -417,6 +417,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->ns = plpgsql_ns_top(); new->label = $1.label; new->n_initvars = $1.n_initvars; new->initvarnos = $1.initvarnos; @@ -911,7 +912,8 @@ stmt_perform : K_PERFORM 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->stmtid = ++plpgsql_curr_compile->nstatements; + new->ns = plpgsql_ns_top(); plpgsql_push_back_token(K_PERFORM); /* @@ -947,6 +949,7 @@ stmt_call : K_CALL new->cmd_type = PLPGSQL_STMT_CALL; new->lineno = plpgsql_location_to_lineno(@1); new->stmtid = ++plpgsql_curr_compile->nstatements; + new->ns = plpgsql_ns_top(); plpgsql_push_back_token(K_CALL); new->expr = read_sql_stmt(); new->is_call = true; @@ -966,6 +969,7 @@ stmt_call : K_CALL new->cmd_type = PLPGSQL_STMT_CALL; new->lineno = plpgsql_location_to_lineno(@1); new->stmtid = ++plpgsql_curr_compile->nstatements; + new->ns = plpgsql_ns_top(); plpgsql_push_back_token(K_DO); new->expr = read_sql_stmt(); new->is_call = false; @@ -1004,7 +1008,8 @@ stmt_assign : T_DATUM 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->stmtid = ++plpgsql_curr_compile->nstatements; + new->ns = plpgsql_ns_top(); new->varno = $1.datum->dno; /* Push back the head name to include it in the stmt */ plpgsql_push_back_token(T_DATUM); @@ -1026,6 +1031,7 @@ stmt_getdiag : K_GET getdiag_area_opt K_DIAGNOSTICS getdiag_list ';' new->cmd_type = PLPGSQL_STMT_GETDIAG; new->lineno = plpgsql_location_to_lineno(@1); new->stmtid = ++plpgsql_curr_compile->nstatements; + new->ns = plpgsql_ns_top(); new->is_stacked = $2; new->diag_items = $4; @@ -1198,6 +1204,7 @@ stmt_if : K_IF expr_until_then proc_sect stmt_elsifs stmt_else K_END K_IF ';' new->cmd_type = PLPGSQL_STMT_IF; new->lineno = plpgsql_location_to_lineno(@1); new->stmtid = ++plpgsql_curr_compile->nstatements; + new->ns = plpgsql_ns_top(); new->cond = $2; new->then_body = $3; new->elsif_list = $4; @@ -1303,6 +1310,7 @@ stmt_loop : opt_loop_label K_LOOP loop_body new->cmd_type = PLPGSQL_STMT_LOOP; new->lineno = plpgsql_location_to_lineno(@2); new->stmtid = ++plpgsql_curr_compile->nstatements; + new->ns = plpgsql_ns_top(); new->label = $1; new->body = $3.stmts; @@ -1321,6 +1329,7 @@ stmt_while : opt_loop_label K_WHILE expr_until_loop loop_body new->cmd_type = PLPGSQL_STMT_WHILE; new->lineno = plpgsql_location_to_lineno(@2); new->stmtid = ++plpgsql_curr_compile->nstatements; + new->ns = plpgsql_ns_top(); new->label = $1; new->cond = $3; new->body = $4.stmts; @@ -1385,6 +1394,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; + new->ns = plpgsql_ns_top(); if ($1.row) { new->var = (PLpgSQL_variable *) $1.row; @@ -1431,6 +1441,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->ns = plpgsql_ns_top(); new->curvar = cursor->dno; /* Should have had a single variable name */ @@ -1551,6 +1562,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->ns = plpgsql_ns_top(); new->var = fvar; new->reverse = reverse; new->lower = expr1; @@ -1579,6 +1591,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; + new->ns = plpgsql_ns_top(); if ($1.row) { new->var = (PLpgSQL_variable *) $1.row; @@ -1680,6 +1693,7 @@ stmt_foreach_a : opt_loop_label K_FOREACH for_variable foreach_slice K_IN K_ARRA new->cmd_type = PLPGSQL_STMT_FOREACH_A; new->lineno = plpgsql_location_to_lineno(@2); new->stmtid = ++plpgsql_curr_compile->nstatements; + new->ns = plpgsql_ns_top(); new->label = $1; new->slice = $4; new->expr = $7; @@ -1727,6 +1741,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->ns = plpgsql_ns_top(); new->is_exit = $1; new->lineno = plpgsql_location_to_lineno(@1); new->label = $2; @@ -1819,6 +1834,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->ns = plpgsql_ns_top(); new->elog_level = ERROR; /* default */ new->condname = NULL; new->message = NULL; @@ -1964,6 +1980,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->ns = plpgsql_ns_top(); new->cond = read_sql_expression2(',', ';', ", or ;", @@ -2044,6 +2061,7 @@ stmt_dynexecute : K_EXECUTE new->cmd_type = PLPGSQL_STMT_DYNEXECUTE; new->lineno = plpgsql_location_to_lineno(@1); new->stmtid = ++plpgsql_curr_compile->nstatements; + new->ns = plpgsql_ns_top(); new->query = expr; new->into = false; new->strict = false; @@ -2101,6 +2119,7 @@ stmt_open : K_OPEN cursor_variable new->cmd_type = PLPGSQL_STMT_OPEN; new->lineno = plpgsql_location_to_lineno(@1); new->stmtid = ++plpgsql_curr_compile->nstatements; + new->ns = plpgsql_ns_top(); new->curvar = $2->dno; new->cursor_options = CURSOR_OPT_FAST_PLAN; @@ -2226,6 +2245,7 @@ stmt_close : K_CLOSE cursor_variable ';' new->cmd_type = PLPGSQL_STMT_CLOSE; new->lineno = plpgsql_location_to_lineno(@1); new->stmtid = ++plpgsql_curr_compile->nstatements; + new->ns = plpgsql_ns_top(); new->curvar = $2->dno; $$ = (PLpgSQL_stmt *)new; @@ -2247,6 +2267,7 @@ stmt_commit : K_COMMIT opt_transaction_chain ';' new->cmd_type = PLPGSQL_STMT_COMMIT; new->lineno = plpgsql_location_to_lineno(@1); new->stmtid = ++plpgsql_curr_compile->nstatements; + new->ns = plpgsql_ns_top(); new->chain = $2; $$ = (PLpgSQL_stmt *)new; @@ -2261,6 +2282,7 @@ stmt_rollback : K_ROLLBACK opt_transaction_chain ';' new->cmd_type = PLPGSQL_STMT_ROLLBACK; new->lineno = plpgsql_location_to_lineno(@1); new->stmtid = ++plpgsql_curr_compile->nstatements; + new->ns = plpgsql_ns_top(); new->chain = $2; $$ = (PLpgSQL_stmt *)new; @@ -2281,6 +2303,7 @@ stmt_set : K_SET new->cmd_type = PLPGSQL_STMT_SET; new->lineno = plpgsql_location_to_lineno(@1); new->stmtid = ++plpgsql_curr_compile->nstatements; + new->ns = plpgsql_ns_top(); plpgsql_push_back_token(K_SET); new->expr = read_sql_stmt(); @@ -2294,6 +2317,7 @@ stmt_set : K_SET new->cmd_type = PLPGSQL_STMT_SET; new->lineno = plpgsql_location_to_lineno(@1); new->stmtid = ++plpgsql_curr_compile->nstatements; + new->ns = plpgsql_ns_top(); plpgsql_push_back_token(K_RESET); new->expr = read_sql_stmt(); @@ -3081,6 +3105,7 @@ make_execsql_stmt(int firsttoken, int location) execsql->cmd_type = PLPGSQL_STMT_EXECSQL; execsql->lineno = plpgsql_location_to_lineno(location); execsql->stmtid = ++plpgsql_curr_compile->nstatements; + execsql->ns = plpgsql_ns_top(); execsql->sqlstmt = expr; execsql->into = have_into; execsql->strict = have_strict; @@ -3107,6 +3132,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; + fetch->ns = plpgsql_ns_top(); /* set direction defaults: */ fetch->direction = FETCH_FORWARD; fetch->how_many = 1; @@ -3260,6 +3286,7 @@ make_return_stmt(int location) new->cmd_type = PLPGSQL_STMT_RETURN; new->lineno = plpgsql_location_to_lineno(location); new->stmtid = ++plpgsql_curr_compile->nstatements; + new->ns = plpgsql_ns_top(); new->expr = NULL; new->retvarno = -1; @@ -3348,6 +3375,7 @@ make_return_next_stmt(int location) new->cmd_type = PLPGSQL_STMT_RETURN_NEXT; new->lineno = plpgsql_location_to_lineno(location); new->stmtid = ++plpgsql_curr_compile->nstatements; + new->ns = plpgsql_ns_top(); new->expr = NULL; new->retvarno = -1; @@ -3412,6 +3440,7 @@ make_return_query_stmt(int location) new->cmd_type = PLPGSQL_STMT_RETURN_QUERY; new->lineno = plpgsql_location_to_lineno(location); new->stmtid = ++plpgsql_curr_compile->nstatements; + new->ns = plpgsql_ns_top(); /* check for RETURN QUERY EXECUTE */ if ((tok = yylex()) != K_EXECUTE) @@ -4076,6 +4105,7 @@ make_case(int location, PLpgSQL_expr *t_expr, new->cmd_type = PLPGSQL_STMT_CASE; new->lineno = plpgsql_location_to_lineno(location); new->stmtid = ++plpgsql_curr_compile->nstatements; + new->ns = plpgsql_ns_top(); 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 d5010862a5..9faf42e418 100644 --- a/src/pl/plpgsql/src/plpgsql.h +++ b/src/pl/plpgsql/src/plpgsql.h @@ -461,6 +461,9 @@ typedef struct PLpgSQL_stmt * per-statement metrics. */ unsigned int stmtid; + + /* namespace chain visible to this statement */ + PLpgSQL_nsitem *ns; } PLpgSQL_stmt; /* @@ -501,6 +504,7 @@ typedef struct PLpgSQL_stmt_block PLpgSQL_stmt_type cmd_type; int lineno; unsigned int stmtid; + PLpgSQL_nsitem *ns; char *label; List *body; /* List of statements */ int n_initvars; /* Length of initvarnos[] */ @@ -516,6 +520,7 @@ typedef struct PLpgSQL_stmt_assign PLpgSQL_stmt_type cmd_type; int lineno; unsigned int stmtid; + PLpgSQL_nsitem *ns; int varno; PLpgSQL_expr *expr; } PLpgSQL_stmt_assign; @@ -528,6 +533,7 @@ typedef struct PLpgSQL_stmt_perform PLpgSQL_stmt_type cmd_type; int lineno; unsigned int stmtid; + PLpgSQL_nsitem *ns; PLpgSQL_expr *expr; } PLpgSQL_stmt_perform; @@ -539,6 +545,7 @@ typedef struct PLpgSQL_stmt_call PLpgSQL_stmt_type cmd_type; int lineno; unsigned int stmtid; + PLpgSQL_nsitem *ns; PLpgSQL_expr *expr; bool is_call; PLpgSQL_variable *target; @@ -552,6 +559,7 @@ typedef struct PLpgSQL_stmt_commit PLpgSQL_stmt_type cmd_type; int lineno; unsigned int stmtid; + PLpgSQL_nsitem *ns; bool chain; } PLpgSQL_stmt_commit; @@ -563,6 +571,7 @@ typedef struct PLpgSQL_stmt_rollback PLpgSQL_stmt_type cmd_type; int lineno; unsigned int stmtid; + PLpgSQL_nsitem *ns; bool chain; } PLpgSQL_stmt_rollback; @@ -574,6 +583,7 @@ typedef struct PLpgSQL_stmt_set PLpgSQL_stmt_type cmd_type; int lineno; unsigned int stmtid; + PLpgSQL_nsitem *ns; PLpgSQL_expr *expr; } PLpgSQL_stmt_set; @@ -594,6 +604,7 @@ typedef struct PLpgSQL_stmt_getdiag PLpgSQL_stmt_type cmd_type; int lineno; unsigned int stmtid; + PLpgSQL_nsitem *ns; bool is_stacked; /* STACKED or CURRENT diagnostics area? */ List *diag_items; /* List of PLpgSQL_diag_item */ } PLpgSQL_stmt_getdiag; @@ -606,6 +617,7 @@ typedef struct PLpgSQL_stmt_if PLpgSQL_stmt_type cmd_type; int lineno; unsigned int stmtid; + PLpgSQL_nsitem *ns; PLpgSQL_expr *cond; /* boolean expression for THEN */ List *then_body; /* List of statements */ List *elsif_list; /* List of PLpgSQL_if_elsif structs */ @@ -630,6 +642,7 @@ typedef struct PLpgSQL_stmt_case PLpgSQL_stmt_type cmd_type; int lineno; unsigned int stmtid; + PLpgSQL_nsitem *ns; 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 */ @@ -655,6 +668,7 @@ typedef struct PLpgSQL_stmt_loop PLpgSQL_stmt_type cmd_type; int lineno; unsigned int stmtid; + PLpgSQL_nsitem *ns; char *label; List *body; /* List of statements */ } PLpgSQL_stmt_loop; @@ -667,6 +681,7 @@ typedef struct PLpgSQL_stmt_while PLpgSQL_stmt_type cmd_type; int lineno; unsigned int stmtid; + PLpgSQL_nsitem *ns; char *label; PLpgSQL_expr *cond; List *body; /* List of statements */ @@ -680,6 +695,7 @@ typedef struct PLpgSQL_stmt_fori PLpgSQL_stmt_type cmd_type; int lineno; unsigned int stmtid; + PLpgSQL_nsitem *ns; char *label; PLpgSQL_var *var; PLpgSQL_expr *lower; @@ -699,6 +715,7 @@ typedef struct PLpgSQL_stmt_forq PLpgSQL_stmt_type cmd_type; int lineno; unsigned int stmtid; + PLpgSQL_nsitem *ns; char *label; PLpgSQL_variable *var; /* Loop variable (record or row) */ List *body; /* List of statements */ @@ -712,6 +729,7 @@ typedef struct PLpgSQL_stmt_fors PLpgSQL_stmt_type cmd_type; int lineno; unsigned int stmtid; + PLpgSQL_nsitem *ns; char *label; PLpgSQL_variable *var; /* Loop variable (record or row) */ List *body; /* List of statements */ @@ -727,6 +745,7 @@ typedef struct PLpgSQL_stmt_forc PLpgSQL_stmt_type cmd_type; int lineno; unsigned int stmtid; + PLpgSQL_nsitem *ns; char *label; PLpgSQL_variable *var; /* Loop variable (record or row) */ List *body; /* List of statements */ @@ -743,6 +762,7 @@ typedef struct PLpgSQL_stmt_dynfors PLpgSQL_stmt_type cmd_type; int lineno; unsigned int stmtid; + PLpgSQL_nsitem *ns; char *label; PLpgSQL_variable *var; /* Loop variable (record or row) */ List *body; /* List of statements */ @@ -759,6 +779,7 @@ typedef struct PLpgSQL_stmt_foreach_a PLpgSQL_stmt_type cmd_type; int lineno; unsigned int stmtid; + PLpgSQL_nsitem *ns; char *label; int varno; /* loop target variable */ int slice; /* slice dimension, or 0 */ @@ -774,6 +795,7 @@ typedef struct PLpgSQL_stmt_open PLpgSQL_stmt_type cmd_type; int lineno; unsigned int stmtid; + PLpgSQL_nsitem *ns; int curvar; int cursor_options; PLpgSQL_expr *argquery; @@ -790,6 +812,7 @@ typedef struct PLpgSQL_stmt_fetch PLpgSQL_stmt_type cmd_type; int lineno; unsigned int stmtid; + PLpgSQL_nsitem *ns; PLpgSQL_variable *target; /* target (record or row) */ int curvar; /* cursor variable to fetch from */ FetchDirection direction; /* fetch direction */ @@ -807,6 +830,7 @@ typedef struct PLpgSQL_stmt_close PLpgSQL_stmt_type cmd_type; int lineno; unsigned int stmtid; + PLpgSQL_nsitem *ns; int curvar; } PLpgSQL_stmt_close; @@ -818,6 +842,7 @@ typedef struct PLpgSQL_stmt_exit PLpgSQL_stmt_type cmd_type; int lineno; unsigned int stmtid; + PLpgSQL_nsitem *ns; bool is_exit; /* Is this an exit or a continue? */ char *label; /* NULL if it's an unlabeled EXIT/CONTINUE */ PLpgSQL_expr *cond; @@ -831,6 +856,7 @@ typedef struct PLpgSQL_stmt_return PLpgSQL_stmt_type cmd_type; int lineno; unsigned int stmtid; + PLpgSQL_nsitem *ns; PLpgSQL_expr *expr; int retvarno; } PLpgSQL_stmt_return; @@ -843,6 +869,7 @@ typedef struct PLpgSQL_stmt_return_next PLpgSQL_stmt_type cmd_type; int lineno; unsigned int stmtid; + PLpgSQL_nsitem *ns; PLpgSQL_expr *expr; int retvarno; } PLpgSQL_stmt_return_next; @@ -855,6 +882,7 @@ typedef struct PLpgSQL_stmt_return_query PLpgSQL_stmt_type cmd_type; int lineno; unsigned int stmtid; + PLpgSQL_nsitem *ns; PLpgSQL_expr *query; /* if static query */ PLpgSQL_expr *dynquery; /* if dynamic query (RETURN QUERY EXECUTE) */ List *params; /* USING arguments for dynamic query */ @@ -868,6 +896,7 @@ typedef struct PLpgSQL_stmt_raise PLpgSQL_stmt_type cmd_type; int lineno; unsigned int stmtid; + PLpgSQL_nsitem *ns; int elog_level; char *condname; /* condition name, SQLSTATE, or NULL */ char *message; /* old-style message format literal, or NULL */ @@ -892,6 +921,7 @@ typedef struct PLpgSQL_stmt_assert PLpgSQL_stmt_type cmd_type; int lineno; unsigned int stmtid; + PLpgSQL_nsitem *ns; PLpgSQL_expr *cond; PLpgSQL_expr *message; } PLpgSQL_stmt_assert; @@ -904,6 +934,7 @@ typedef struct PLpgSQL_stmt_execsql PLpgSQL_stmt_type cmd_type; int lineno; unsigned int stmtid; + PLpgSQL_nsitem *ns; PLpgSQL_expr *sqlstmt; bool mod_stmt; /* is the stmt INSERT/UPDATE/DELETE? Note: * mod_stmt is set when we plan the query */ @@ -920,6 +951,7 @@ typedef struct PLpgSQL_stmt_dynexecute PLpgSQL_stmt_type cmd_type; int lineno; unsigned int stmtid; + PLpgSQL_nsitem *ns; PLpgSQL_expr *query; /* string expression */ bool into; /* INTO supplied? */ bool strict; /* INTO STRICT flag */ @@ -1132,8 +1164,11 @@ typedef struct PLpgSQL_execstate * * Also, immediately before any call to func_setup, PL/pgSQL fills in the * error_callback and assign_expr fields with pointers to its own - * plpgsql_exec_error_callback and exec_assign_expr functions. This is - * a somewhat ad-hoc expedient to simplify life for debugger plugins. + * plpgsql_exec_error_callback and exec_assign_expr functions. eval_datum + * is assigned to function exec_eval_datum, and cast_value to function + * do_cast_value. With last two functions is easy to get content of + * any PLpgSQL_datum in any expected type. This is a somewhat ad-hoc + * expedient to simplify life for debugger plugins. */ typedef struct PLpgSQL_plugin { @@ -1148,6 +1183,13 @@ typedef struct PLpgSQL_plugin void (*error_callback) (void *arg); void (*assign_expr) (PLpgSQL_execstate *estate, PLpgSQL_datum *target, PLpgSQL_expr *expr); + void (*eval_datum) (PLpgSQL_execstate *estate, PLpgSQL_datum *datum, + Oid *typeid, int32 *typetypmod, Datum *value, + bool *isnull); + Datum (*cast_value) (PLpgSQL_execstate *estate, + Datum value, bool *isnull, + Oid valtype, int32 valtypmod, + Oid reqtype, int32 reqtypmod); } PLpgSQL_plugin; /*