Hi rebase
Regards Pavel
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index 3a9349b724..208ba181fc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -4123,6 +4123,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 0b0ff4e5de..82a703639e 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; @@ -963,6 +966,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; @@ -998,7 +1002,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); @@ -1020,6 +1025,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; @@ -1192,6 +1198,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; @@ -1297,6 +1304,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; @@ -1315,6 +1323,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; @@ -1336,6 +1345,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->ns = plpgsql_ns_top(); new->label = $1; new->body = $4.stmts; $$ = (PLpgSQL_stmt *) new; @@ -1351,6 +1361,7 @@ stmt_for : opt_loop_label K_FOR for_control loop_body new = (PLpgSQL_stmt_forq *) $3; new->lineno = plpgsql_location_to_lineno(@2); new->stmtid = ++plpgsql_curr_compile->nstatements; + new->ns = plpgsql_ns_top(); new->label = $1; new->body = $4.stmts; $$ = (PLpgSQL_stmt *) new; @@ -1381,6 +1392,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; @@ -1427,6 +1439,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 */ @@ -1547,6 +1560,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; @@ -1575,6 +1589,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; @@ -1676,6 +1691,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; @@ -1723,6 +1739,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; @@ -1815,6 +1832,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; @@ -1960,6 +1978,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 ;", @@ -2040,6 +2059,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; @@ -2097,6 +2117,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; @@ -2222,6 +2243,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; @@ -2243,6 +2265,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; @@ -2257,6 +2280,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; @@ -2277,6 +2301,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(); @@ -2290,6 +2315,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(); @@ -3077,6 +3103,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; @@ -3103,6 +3130,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; @@ -3256,6 +3284,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; @@ -3344,6 +3373,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; @@ -3408,6 +3438,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) @@ -4072,6 +4103,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 416fda7f3b..2e920337fb 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 */ @@ -1128,8 +1160,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 { @@ -1144,6 +1179,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; /*