00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "plpgsql.h"
00017
00018 #include <ctype.h>
00019
00020 #include "access/htup_details.h"
00021 #include "access/transam.h"
00022 #include "access/tupconvert.h"
00023 #include "catalog/pg_proc.h"
00024 #include "catalog/pg_type.h"
00025 #include "executor/spi.h"
00026 #include "funcapi.h"
00027 #include "miscadmin.h"
00028 #include "nodes/nodeFuncs.h"
00029 #include "parser/scansup.h"
00030 #include "storage/proc.h"
00031 #include "tcop/tcopprot.h"
00032 #include "utils/array.h"
00033 #include "utils/builtins.h"
00034 #include "utils/datum.h"
00035 #include "utils/lsyscache.h"
00036 #include "utils/memutils.h"
00037 #include "utils/rel.h"
00038 #include "utils/snapmgr.h"
00039 #include "utils/typcache.h"
00040
00041
00042 static const char *const raise_skip_msg = "RAISE";
00043
00044 typedef struct
00045 {
00046 int nargs;
00047 Oid *types;
00048 Datum *values;
00049 char *nulls;
00050 bool *freevals;
00051 } PreparedParamsData;
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070 typedef struct SimpleEcontextStackEntry
00071 {
00072 ExprContext *stack_econtext;
00073 SubTransactionId xact_subxid;
00074 struct SimpleEcontextStackEntry *next;
00075 } SimpleEcontextStackEntry;
00076
00077 static EState *simple_eval_estate = NULL;
00078 static SimpleEcontextStackEntry *simple_econtext_stack = NULL;
00079
00080
00081
00082
00083 static void plpgsql_exec_error_callback(void *arg);
00084 static PLpgSQL_datum *copy_plpgsql_datum(PLpgSQL_datum *datum);
00085
00086 static int exec_stmt_block(PLpgSQL_execstate *estate,
00087 PLpgSQL_stmt_block *block);
00088 static int exec_stmts(PLpgSQL_execstate *estate,
00089 List *stmts);
00090 static int exec_stmt(PLpgSQL_execstate *estate,
00091 PLpgSQL_stmt *stmt);
00092 static int exec_stmt_assign(PLpgSQL_execstate *estate,
00093 PLpgSQL_stmt_assign *stmt);
00094 static int exec_stmt_perform(PLpgSQL_execstate *estate,
00095 PLpgSQL_stmt_perform *stmt);
00096 static int exec_stmt_getdiag(PLpgSQL_execstate *estate,
00097 PLpgSQL_stmt_getdiag *stmt);
00098 static int exec_stmt_if(PLpgSQL_execstate *estate,
00099 PLpgSQL_stmt_if *stmt);
00100 static int exec_stmt_case(PLpgSQL_execstate *estate,
00101 PLpgSQL_stmt_case *stmt);
00102 static int exec_stmt_loop(PLpgSQL_execstate *estate,
00103 PLpgSQL_stmt_loop *stmt);
00104 static int exec_stmt_while(PLpgSQL_execstate *estate,
00105 PLpgSQL_stmt_while *stmt);
00106 static int exec_stmt_fori(PLpgSQL_execstate *estate,
00107 PLpgSQL_stmt_fori *stmt);
00108 static int exec_stmt_fors(PLpgSQL_execstate *estate,
00109 PLpgSQL_stmt_fors *stmt);
00110 static int exec_stmt_forc(PLpgSQL_execstate *estate,
00111 PLpgSQL_stmt_forc *stmt);
00112 static int exec_stmt_foreach_a(PLpgSQL_execstate *estate,
00113 PLpgSQL_stmt_foreach_a *stmt);
00114 static int exec_stmt_open(PLpgSQL_execstate *estate,
00115 PLpgSQL_stmt_open *stmt);
00116 static int exec_stmt_fetch(PLpgSQL_execstate *estate,
00117 PLpgSQL_stmt_fetch *stmt);
00118 static int exec_stmt_close(PLpgSQL_execstate *estate,
00119 PLpgSQL_stmt_close *stmt);
00120 static int exec_stmt_exit(PLpgSQL_execstate *estate,
00121 PLpgSQL_stmt_exit *stmt);
00122 static int exec_stmt_return(PLpgSQL_execstate *estate,
00123 PLpgSQL_stmt_return *stmt);
00124 static int exec_stmt_return_next(PLpgSQL_execstate *estate,
00125 PLpgSQL_stmt_return_next *stmt);
00126 static int exec_stmt_return_query(PLpgSQL_execstate *estate,
00127 PLpgSQL_stmt_return_query *stmt);
00128 static int exec_stmt_raise(PLpgSQL_execstate *estate,
00129 PLpgSQL_stmt_raise *stmt);
00130 static int exec_stmt_execsql(PLpgSQL_execstate *estate,
00131 PLpgSQL_stmt_execsql *stmt);
00132 static int exec_stmt_dynexecute(PLpgSQL_execstate *estate,
00133 PLpgSQL_stmt_dynexecute *stmt);
00134 static int exec_stmt_dynfors(PLpgSQL_execstate *estate,
00135 PLpgSQL_stmt_dynfors *stmt);
00136
00137 static void plpgsql_estate_setup(PLpgSQL_execstate *estate,
00138 PLpgSQL_function *func,
00139 ReturnSetInfo *rsi);
00140 static void exec_eval_cleanup(PLpgSQL_execstate *estate);
00141
00142 static void exec_prepare_plan(PLpgSQL_execstate *estate,
00143 PLpgSQL_expr *expr, int cursorOptions);
00144 static bool exec_simple_check_node(Node *node);
00145 static void exec_simple_check_plan(PLpgSQL_expr *expr);
00146 static void exec_simple_recheck_plan(PLpgSQL_expr *expr, CachedPlan *cplan);
00147 static bool exec_eval_simple_expr(PLpgSQL_execstate *estate,
00148 PLpgSQL_expr *expr,
00149 Datum *result,
00150 bool *isNull,
00151 Oid *rettype);
00152
00153 static void exec_assign_expr(PLpgSQL_execstate *estate,
00154 PLpgSQL_datum *target,
00155 PLpgSQL_expr *expr);
00156 static void exec_assign_c_string(PLpgSQL_execstate *estate,
00157 PLpgSQL_datum *target,
00158 const char *str);
00159 static void exec_assign_value(PLpgSQL_execstate *estate,
00160 PLpgSQL_datum *target,
00161 Datum value, Oid valtype, bool *isNull);
00162 static void exec_eval_datum(PLpgSQL_execstate *estate,
00163 PLpgSQL_datum *datum,
00164 Oid *typeid,
00165 int32 *typetypmod,
00166 Datum *value,
00167 bool *isnull);
00168 static int exec_eval_integer(PLpgSQL_execstate *estate,
00169 PLpgSQL_expr *expr,
00170 bool *isNull);
00171 static bool exec_eval_boolean(PLpgSQL_execstate *estate,
00172 PLpgSQL_expr *expr,
00173 bool *isNull);
00174 static Datum exec_eval_expr(PLpgSQL_execstate *estate,
00175 PLpgSQL_expr *expr,
00176 bool *isNull,
00177 Oid *rettype);
00178 static int exec_run_select(PLpgSQL_execstate *estate,
00179 PLpgSQL_expr *expr, long maxtuples, Portal *portalP);
00180 static int exec_for_query(PLpgSQL_execstate *estate, PLpgSQL_stmt_forq *stmt,
00181 Portal portal, bool prefetch_ok);
00182 static ParamListInfo setup_param_list(PLpgSQL_execstate *estate,
00183 PLpgSQL_expr *expr);
00184 static void plpgsql_param_fetch(ParamListInfo params, int paramid);
00185 static void exec_move_row(PLpgSQL_execstate *estate,
00186 PLpgSQL_rec *rec,
00187 PLpgSQL_row *row,
00188 HeapTuple tup, TupleDesc tupdesc);
00189 static HeapTuple make_tuple_from_row(PLpgSQL_execstate *estate,
00190 PLpgSQL_row *row,
00191 TupleDesc tupdesc);
00192 static HeapTuple get_tuple_from_datum(Datum value);
00193 static TupleDesc get_tupdesc_from_datum(Datum value);
00194 static void exec_move_row_from_datum(PLpgSQL_execstate *estate,
00195 PLpgSQL_rec *rec,
00196 PLpgSQL_row *row,
00197 Datum value);
00198 static char *convert_value_to_string(PLpgSQL_execstate *estate,
00199 Datum value, Oid valtype);
00200 static Datum exec_cast_value(PLpgSQL_execstate *estate,
00201 Datum value, Oid valtype,
00202 Oid reqtype,
00203 FmgrInfo *reqinput,
00204 Oid reqtypioparam,
00205 int32 reqtypmod,
00206 bool isnull);
00207 static Datum exec_simple_cast_value(PLpgSQL_execstate *estate,
00208 Datum value, Oid valtype,
00209 Oid reqtype, int32 reqtypmod,
00210 bool isnull);
00211 static void exec_init_tuple_store(PLpgSQL_execstate *estate);
00212 static void exec_set_found(PLpgSQL_execstate *estate, bool state);
00213 static void plpgsql_create_econtext(PLpgSQL_execstate *estate);
00214 static void plpgsql_destroy_econtext(PLpgSQL_execstate *estate);
00215 static void free_var(PLpgSQL_var *var);
00216 static void assign_text_var(PLpgSQL_var *var, const char *str);
00217 static PreparedParamsData *exec_eval_using_params(PLpgSQL_execstate *estate,
00218 List *params);
00219 static void free_params_data(PreparedParamsData *ppd);
00220 static Portal exec_dynquery_with_params(PLpgSQL_execstate *estate,
00221 PLpgSQL_expr *dynquery, List *params,
00222 const char *portalname, int cursorOptions);
00223
00224
00225
00226
00227
00228
00229
00230 Datum
00231 plpgsql_exec_function(PLpgSQL_function *func, FunctionCallInfo fcinfo)
00232 {
00233 PLpgSQL_execstate estate;
00234 ErrorContextCallback plerrcontext;
00235 int i;
00236 int rc;
00237
00238
00239
00240
00241 plpgsql_estate_setup(&estate, func, (ReturnSetInfo *) fcinfo->resultinfo);
00242
00243
00244
00245
00246 plerrcontext.callback = plpgsql_exec_error_callback;
00247 plerrcontext.arg = &estate;
00248 plerrcontext.previous = error_context_stack;
00249 error_context_stack = &plerrcontext;
00250
00251
00252
00253
00254 estate.err_text = gettext_noop("during initialization of execution state");
00255 for (i = 0; i < estate.ndatums; i++)
00256 estate.datums[i] = copy_plpgsql_datum(func->datums[i]);
00257
00258
00259
00260
00261 estate.err_text = gettext_noop("while storing call arguments into local variables");
00262 for (i = 0; i < func->fn_nargs; i++)
00263 {
00264 int n = func->fn_argvarnos[i];
00265
00266 switch (estate.datums[n]->dtype)
00267 {
00268 case PLPGSQL_DTYPE_VAR:
00269 {
00270 PLpgSQL_var *var = (PLpgSQL_var *) estate.datums[n];
00271
00272 var->value = fcinfo->arg[i];
00273 var->isnull = fcinfo->argnull[i];
00274 var->freeval = false;
00275 }
00276 break;
00277
00278 case PLPGSQL_DTYPE_ROW:
00279 {
00280 PLpgSQL_row *row = (PLpgSQL_row *) estate.datums[n];
00281
00282 if (!fcinfo->argnull[i])
00283 {
00284
00285 exec_move_row_from_datum(&estate, NULL, row,
00286 fcinfo->arg[i]);
00287 }
00288 else
00289 {
00290
00291 exec_move_row(&estate, NULL, row, NULL, NULL);
00292 }
00293
00294 exec_eval_cleanup(&estate);
00295 }
00296 break;
00297
00298 default:
00299 elog(ERROR, "unrecognized dtype: %d", func->datums[i]->dtype);
00300 }
00301 }
00302
00303 estate.err_text = gettext_noop("during function entry");
00304
00305
00306
00307
00308 exec_set_found(&estate, false);
00309
00310
00311
00312
00313 if (*plugin_ptr && (*plugin_ptr)->func_beg)
00314 ((*plugin_ptr)->func_beg) (&estate, func);
00315
00316
00317
00318
00319 estate.err_text = NULL;
00320 estate.err_stmt = (PLpgSQL_stmt *) (func->action);
00321 rc = exec_stmt_block(&estate, func->action);
00322 if (rc != PLPGSQL_RC_RETURN)
00323 {
00324 estate.err_stmt = NULL;
00325 estate.err_text = NULL;
00326
00327
00328
00329
00330
00331 if (rc == PLPGSQL_RC_CONTINUE)
00332 ereport(ERROR,
00333 (errcode(ERRCODE_SYNTAX_ERROR),
00334 errmsg("CONTINUE cannot be used outside a loop")));
00335 else
00336 ereport(ERROR,
00337 (errcode(ERRCODE_S_R_E_FUNCTION_EXECUTED_NO_RETURN_STATEMENT),
00338 errmsg("control reached end of function without RETURN")));
00339 }
00340
00341
00342
00343
00344 estate.err_stmt = NULL;
00345 estate.err_text = gettext_noop("while casting return value to function's return type");
00346
00347 fcinfo->isnull = estate.retisnull;
00348
00349 if (estate.retisset)
00350 {
00351 ReturnSetInfo *rsi = estate.rsi;
00352
00353
00354 if (!rsi || !IsA(rsi, ReturnSetInfo) ||
00355 (rsi->allowedModes & SFRM_Materialize) == 0)
00356 ereport(ERROR,
00357 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00358 errmsg("set-valued function called in context that cannot accept a set")));
00359 rsi->returnMode = SFRM_Materialize;
00360
00361
00362 if (estate.tuple_store)
00363 {
00364 rsi->setResult = estate.tuple_store;
00365 if (estate.rettupdesc)
00366 {
00367 MemoryContext oldcxt;
00368
00369 oldcxt = MemoryContextSwitchTo(estate.tuple_store_cxt);
00370 rsi->setDesc = CreateTupleDescCopy(estate.rettupdesc);
00371 MemoryContextSwitchTo(oldcxt);
00372 }
00373 }
00374 estate.retval = (Datum) 0;
00375 fcinfo->isnull = true;
00376 }
00377 else if (!estate.retisnull)
00378 {
00379 if (estate.retistuple)
00380 {
00381
00382
00383
00384
00385
00386 HeapTuple rettup = (HeapTuple) DatumGetPointer(estate.retval);
00387 TupleDesc tupdesc;
00388 TupleConversionMap *tupmap;
00389
00390 switch (get_call_result_type(fcinfo, NULL, &tupdesc))
00391 {
00392 case TYPEFUNC_COMPOSITE:
00393
00394 tupmap = convert_tuples_by_position(estate.rettupdesc,
00395 tupdesc,
00396 gettext_noop("returned record type does not match expected record type"));
00397
00398 if (tupmap)
00399 rettup = do_convert_tuple(rettup, tupmap);
00400
00401 break;
00402 case TYPEFUNC_RECORD:
00403
00404
00405
00406
00407
00408
00409
00410
00411 tupdesc = estate.rettupdesc;
00412 if (tupdesc == NULL)
00413 elog(ERROR, "return type must be a row type");
00414 break;
00415 default:
00416
00417 elog(ERROR, "return type must be a row type");
00418 break;
00419 }
00420
00421
00422
00423
00424
00425 estate.retval = PointerGetDatum(SPI_returntuple(rettup, tupdesc));
00426 }
00427 else
00428 {
00429
00430 estate.retval = exec_cast_value(&estate,
00431 estate.retval,
00432 estate.rettype,
00433 func->fn_rettype,
00434 &(func->fn_retinput),
00435 func->fn_rettypioparam,
00436 -1,
00437 fcinfo->isnull);
00438
00439
00440
00441
00442
00443 if (!fcinfo->isnull && !func->fn_retbyval)
00444 {
00445 Size len;
00446 void *tmp;
00447
00448 len = datumGetSize(estate.retval, false, func->fn_rettyplen);
00449 tmp = SPI_palloc(len);
00450 memcpy(tmp, DatumGetPointer(estate.retval), len);
00451 estate.retval = PointerGetDatum(tmp);
00452 }
00453 }
00454 }
00455
00456 estate.err_text = gettext_noop("during function exit");
00457
00458
00459
00460
00461 if (*plugin_ptr && (*plugin_ptr)->func_end)
00462 ((*plugin_ptr)->func_end) (&estate, func);
00463
00464
00465 plpgsql_destroy_econtext(&estate);
00466 exec_eval_cleanup(&estate);
00467
00468
00469
00470
00471 error_context_stack = plerrcontext.previous;
00472
00473
00474
00475
00476 return estate.retval;
00477 }
00478
00479
00480
00481
00482
00483
00484
00485 HeapTuple
00486 plpgsql_exec_trigger(PLpgSQL_function *func,
00487 TriggerData *trigdata)
00488 {
00489 PLpgSQL_execstate estate;
00490 ErrorContextCallback plerrcontext;
00491 int i;
00492 int rc;
00493 PLpgSQL_var *var;
00494 PLpgSQL_rec *rec_new,
00495 *rec_old;
00496 HeapTuple rettup;
00497
00498
00499
00500
00501 plpgsql_estate_setup(&estate, func, NULL);
00502
00503
00504
00505
00506 plerrcontext.callback = plpgsql_exec_error_callback;
00507 plerrcontext.arg = &estate;
00508 plerrcontext.previous = error_context_stack;
00509 error_context_stack = &plerrcontext;
00510
00511
00512
00513
00514 estate.err_text = gettext_noop("during initialization of execution state");
00515 for (i = 0; i < estate.ndatums; i++)
00516 estate.datums[i] = copy_plpgsql_datum(func->datums[i]);
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527 rec_new = (PLpgSQL_rec *) (estate.datums[func->new_varno]);
00528 rec_new->freetup = false;
00529 rec_new->tupdesc = trigdata->tg_relation->rd_att;
00530 rec_new->freetupdesc = false;
00531 rec_old = (PLpgSQL_rec *) (estate.datums[func->old_varno]);
00532 rec_old->freetup = false;
00533 rec_old->tupdesc = trigdata->tg_relation->rd_att;
00534 rec_old->freetupdesc = false;
00535
00536 if (!TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
00537 {
00538
00539
00540
00541 rec_new->tup = NULL;
00542 rec_old->tup = NULL;
00543 }
00544 else if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
00545 {
00546 rec_new->tup = trigdata->tg_trigtuple;
00547 rec_old->tup = NULL;
00548 }
00549 else if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
00550 {
00551 rec_new->tup = trigdata->tg_newtuple;
00552 rec_old->tup = trigdata->tg_trigtuple;
00553 }
00554 else if (TRIGGER_FIRED_BY_DELETE(trigdata->tg_event))
00555 {
00556 rec_new->tup = NULL;
00557 rec_old->tup = trigdata->tg_trigtuple;
00558 }
00559 else
00560 elog(ERROR, "unrecognized trigger action: not INSERT, DELETE, or UPDATE");
00561
00562
00563
00564
00565
00566 var = (PLpgSQL_var *) (estate.datums[func->tg_op_varno]);
00567 if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
00568 var->value = CStringGetTextDatum("INSERT");
00569 else if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
00570 var->value = CStringGetTextDatum("UPDATE");
00571 else if (TRIGGER_FIRED_BY_DELETE(trigdata->tg_event))
00572 var->value = CStringGetTextDatum("DELETE");
00573 else if (TRIGGER_FIRED_BY_TRUNCATE(trigdata->tg_event))
00574 var->value = CStringGetTextDatum("TRUNCATE");
00575 else
00576 elog(ERROR, "unrecognized trigger action: not INSERT, DELETE, UPDATE, or TRUNCATE");
00577 var->isnull = false;
00578 var->freeval = true;
00579
00580 var = (PLpgSQL_var *) (estate.datums[func->tg_name_varno]);
00581 var->value = DirectFunctionCall1(namein,
00582 CStringGetDatum(trigdata->tg_trigger->tgname));
00583 var->isnull = false;
00584 var->freeval = true;
00585
00586 var = (PLpgSQL_var *) (estate.datums[func->tg_when_varno]);
00587 if (TRIGGER_FIRED_BEFORE(trigdata->tg_event))
00588 var->value = CStringGetTextDatum("BEFORE");
00589 else if (TRIGGER_FIRED_AFTER(trigdata->tg_event))
00590 var->value = CStringGetTextDatum("AFTER");
00591 else if (TRIGGER_FIRED_INSTEAD(trigdata->tg_event))
00592 var->value = CStringGetTextDatum("INSTEAD OF");
00593 else
00594 elog(ERROR, "unrecognized trigger execution time: not BEFORE, AFTER, or INSTEAD OF");
00595 var->isnull = false;
00596 var->freeval = true;
00597
00598 var = (PLpgSQL_var *) (estate.datums[func->tg_level_varno]);
00599 if (TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
00600 var->value = CStringGetTextDatum("ROW");
00601 else if (TRIGGER_FIRED_FOR_STATEMENT(trigdata->tg_event))
00602 var->value = CStringGetTextDatum("STATEMENT");
00603 else
00604 elog(ERROR, "unrecognized trigger event type: not ROW or STATEMENT");
00605 var->isnull = false;
00606 var->freeval = true;
00607
00608 var = (PLpgSQL_var *) (estate.datums[func->tg_relid_varno]);
00609 var->value = ObjectIdGetDatum(trigdata->tg_relation->rd_id);
00610 var->isnull = false;
00611 var->freeval = false;
00612
00613 var = (PLpgSQL_var *) (estate.datums[func->tg_relname_varno]);
00614 var->value = DirectFunctionCall1(namein,
00615 CStringGetDatum(RelationGetRelationName(trigdata->tg_relation)));
00616 var->isnull = false;
00617 var->freeval = true;
00618
00619 var = (PLpgSQL_var *) (estate.datums[func->tg_table_name_varno]);
00620 var->value = DirectFunctionCall1(namein,
00621 CStringGetDatum(RelationGetRelationName(trigdata->tg_relation)));
00622 var->isnull = false;
00623 var->freeval = true;
00624
00625 var = (PLpgSQL_var *) (estate.datums[func->tg_table_schema_varno]);
00626 var->value = DirectFunctionCall1(namein,
00627 CStringGetDatum(
00628 get_namespace_name(
00629 RelationGetNamespace(
00630 trigdata->tg_relation))));
00631 var->isnull = false;
00632 var->freeval = true;
00633
00634 var = (PLpgSQL_var *) (estate.datums[func->tg_nargs_varno]);
00635 var->value = Int16GetDatum(trigdata->tg_trigger->tgnargs);
00636 var->isnull = false;
00637 var->freeval = false;
00638
00639 var = (PLpgSQL_var *) (estate.datums[func->tg_argv_varno]);
00640 if (trigdata->tg_trigger->tgnargs > 0)
00641 {
00642
00643
00644
00645
00646 int nelems = trigdata->tg_trigger->tgnargs;
00647 Datum *elems;
00648 int dims[1];
00649 int lbs[1];
00650
00651 elems = palloc(sizeof(Datum) * nelems);
00652 for (i = 0; i < nelems; i++)
00653 elems[i] = CStringGetTextDatum(trigdata->tg_trigger->tgargs[i]);
00654 dims[0] = nelems;
00655 lbs[0] = 0;
00656
00657 var->value = PointerGetDatum(construct_md_array(elems, NULL,
00658 1, dims, lbs,
00659 TEXTOID,
00660 -1, false, 'i'));
00661 var->isnull = false;
00662 var->freeval = true;
00663 }
00664 else
00665 {
00666 var->value = (Datum) 0;
00667 var->isnull = true;
00668 var->freeval = false;
00669 }
00670
00671 estate.err_text = gettext_noop("during function entry");
00672
00673
00674
00675
00676 exec_set_found(&estate, false);
00677
00678
00679
00680
00681 if (*plugin_ptr && (*plugin_ptr)->func_beg)
00682 ((*plugin_ptr)->func_beg) (&estate, func);
00683
00684
00685
00686
00687 estate.err_text = NULL;
00688 estate.err_stmt = (PLpgSQL_stmt *) (func->action);
00689 rc = exec_stmt_block(&estate, func->action);
00690 if (rc != PLPGSQL_RC_RETURN)
00691 {
00692 estate.err_stmt = NULL;
00693 estate.err_text = NULL;
00694
00695
00696
00697
00698
00699 if (rc == PLPGSQL_RC_CONTINUE)
00700 ereport(ERROR,
00701 (errcode(ERRCODE_SYNTAX_ERROR),
00702 errmsg("CONTINUE cannot be used outside a loop")));
00703 else
00704 ereport(ERROR,
00705 (errcode(ERRCODE_S_R_E_FUNCTION_EXECUTED_NO_RETURN_STATEMENT),
00706 errmsg("control reached end of trigger procedure without RETURN")));
00707 }
00708
00709 estate.err_stmt = NULL;
00710 estate.err_text = gettext_noop("during function exit");
00711
00712 if (estate.retisset)
00713 ereport(ERROR,
00714 (errcode(ERRCODE_DATATYPE_MISMATCH),
00715 errmsg("trigger procedure cannot return a set")));
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727 if (estate.retisnull || !TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
00728 rettup = NULL;
00729 else
00730 {
00731 TupleConversionMap *tupmap;
00732
00733 rettup = (HeapTuple) DatumGetPointer(estate.retval);
00734
00735 tupmap = convert_tuples_by_position(estate.rettupdesc,
00736 trigdata->tg_relation->rd_att,
00737 gettext_noop("returned row structure does not match the structure of the triggering table"));
00738
00739 if (tupmap)
00740 rettup = do_convert_tuple(rettup, tupmap);
00741
00742
00743
00744 rettup = SPI_copytuple(rettup);
00745 }
00746
00747
00748
00749
00750 if (*plugin_ptr && (*plugin_ptr)->func_end)
00751 ((*plugin_ptr)->func_end) (&estate, func);
00752
00753
00754 plpgsql_destroy_econtext(&estate);
00755 exec_eval_cleanup(&estate);
00756
00757
00758
00759
00760 error_context_stack = plerrcontext.previous;
00761
00762
00763
00764
00765 return rettup;
00766 }
00767
00768 void
00769 plpgsql_exec_event_trigger(PLpgSQL_function *func, EventTriggerData *trigdata)
00770 {
00771 PLpgSQL_execstate estate;
00772 ErrorContextCallback plerrcontext;
00773 int i;
00774 int rc;
00775 PLpgSQL_var *var;
00776
00777
00778
00779
00780 plpgsql_estate_setup(&estate, func, NULL);
00781
00782
00783
00784
00785 plerrcontext.callback = plpgsql_exec_error_callback;
00786 plerrcontext.arg = &estate;
00787 plerrcontext.previous = error_context_stack;
00788 error_context_stack = &plerrcontext;
00789
00790
00791
00792
00793 estate.err_text = gettext_noop("during initialization of execution state");
00794 for (i = 0; i < estate.ndatums; i++)
00795 estate.datums[i] = copy_plpgsql_datum(func->datums[i]);
00796
00797
00798
00799
00800 var = (PLpgSQL_var *) (estate.datums[func->tg_event_varno]);
00801 var->value = CStringGetTextDatum(trigdata->event);
00802 var->isnull = false;
00803 var->freeval = true;
00804
00805 var = (PLpgSQL_var *) (estate.datums[func->tg_tag_varno]);
00806 var->value = CStringGetTextDatum(trigdata->tag);
00807 var->isnull = false;
00808 var->freeval = true;
00809
00810
00811
00812
00813 if (*plugin_ptr && (*plugin_ptr)->func_beg)
00814 ((*plugin_ptr)->func_beg) (&estate, func);
00815
00816
00817
00818
00819 estate.err_text = NULL;
00820 estate.err_stmt = (PLpgSQL_stmt *) (func->action);
00821 rc = exec_stmt_block(&estate, func->action);
00822 if (rc != PLPGSQL_RC_RETURN)
00823 {
00824 estate.err_stmt = NULL;
00825 estate.err_text = NULL;
00826
00827
00828
00829
00830
00831 if (rc == PLPGSQL_RC_CONTINUE)
00832 ereport(ERROR,
00833 (errcode(ERRCODE_SYNTAX_ERROR),
00834 errmsg("CONTINUE cannot be used outside a loop")));
00835 else
00836 ereport(ERROR,
00837 (errcode(ERRCODE_S_R_E_FUNCTION_EXECUTED_NO_RETURN_STATEMENT),
00838 errmsg("control reached end of trigger procedure without RETURN")));
00839 }
00840
00841 estate.err_stmt = NULL;
00842 estate.err_text = gettext_noop("during function exit");
00843
00844
00845
00846
00847 if (*plugin_ptr && (*plugin_ptr)->func_end)
00848 ((*plugin_ptr)->func_end) (&estate, func);
00849
00850
00851 plpgsql_destroy_econtext(&estate);
00852 exec_eval_cleanup(&estate);
00853
00854
00855
00856
00857 error_context_stack = plerrcontext.previous;
00858
00859 return;
00860 }
00861
00862
00863
00864
00865 static void
00866 plpgsql_exec_error_callback(void *arg)
00867 {
00868 PLpgSQL_execstate *estate = (PLpgSQL_execstate *) arg;
00869
00870
00871 if (estate->err_text == raise_skip_msg)
00872 return;
00873
00874 if (estate->err_text != NULL)
00875 {
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887 if (estate->err_stmt != NULL)
00888 {
00889
00890
00891
00892
00893 errcontext("PL/pgSQL function %s line %d %s",
00894 estate->func->fn_signature,
00895 estate->err_stmt->lineno,
00896 _(estate->err_text));
00897 }
00898 else
00899 {
00900
00901
00902
00903
00904 errcontext("PL/pgSQL function %s %s",
00905 estate->func->fn_signature,
00906 _(estate->err_text));
00907 }
00908 }
00909 else if (estate->err_stmt != NULL)
00910 {
00911
00912 errcontext("PL/pgSQL function %s line %d at %s",
00913 estate->func->fn_signature,
00914 estate->err_stmt->lineno,
00915 plpgsql_stmt_typename(estate->err_stmt));
00916 }
00917 else
00918 errcontext("PL/pgSQL function %s",
00919 estate->func->fn_signature);
00920 }
00921
00922
00923
00924
00925
00926
00927 static PLpgSQL_datum *
00928 copy_plpgsql_datum(PLpgSQL_datum *datum)
00929 {
00930 PLpgSQL_datum *result;
00931
00932 switch (datum->dtype)
00933 {
00934 case PLPGSQL_DTYPE_VAR:
00935 {
00936 PLpgSQL_var *new = palloc(sizeof(PLpgSQL_var));
00937
00938 memcpy(new, datum, sizeof(PLpgSQL_var));
00939
00940 new->value = 0;
00941 new->isnull = true;
00942 new->freeval = false;
00943
00944 result = (PLpgSQL_datum *) new;
00945 }
00946 break;
00947
00948 case PLPGSQL_DTYPE_REC:
00949 {
00950 PLpgSQL_rec *new = palloc(sizeof(PLpgSQL_rec));
00951
00952 memcpy(new, datum, sizeof(PLpgSQL_rec));
00953
00954 new->tup = NULL;
00955 new->tupdesc = NULL;
00956 new->freetup = false;
00957 new->freetupdesc = false;
00958
00959 result = (PLpgSQL_datum *) new;
00960 }
00961 break;
00962
00963 case PLPGSQL_DTYPE_ROW:
00964 case PLPGSQL_DTYPE_RECFIELD:
00965 case PLPGSQL_DTYPE_ARRAYELEM:
00966
00967
00968
00969
00970
00971
00972 result = datum;
00973 break;
00974
00975 default:
00976 elog(ERROR, "unrecognized dtype: %d", datum->dtype);
00977 result = NULL;
00978 break;
00979 }
00980
00981 return result;
00982 }
00983
00984
00985 static bool
00986 exception_matches_conditions(ErrorData *edata, PLpgSQL_condition *cond)
00987 {
00988 for (; cond != NULL; cond = cond->next)
00989 {
00990 int sqlerrstate = cond->sqlerrstate;
00991
00992
00993
00994
00995
00996 if (sqlerrstate == 0)
00997 {
00998 if (edata->sqlerrcode != ERRCODE_QUERY_CANCELED)
00999 return true;
01000 }
01001
01002 else if (edata->sqlerrcode == sqlerrstate)
01003 return true;
01004
01005 else if (ERRCODE_IS_CATEGORY(sqlerrstate) &&
01006 ERRCODE_TO_CATEGORY(edata->sqlerrcode) == sqlerrstate)
01007 return true;
01008 }
01009 return false;
01010 }
01011
01012
01013
01014
01015
01016
01017 static int
01018 exec_stmt_block(PLpgSQL_execstate *estate, PLpgSQL_stmt_block *block)
01019 {
01020 volatile int rc = -1;
01021 int i;
01022 int n;
01023
01024
01025
01026
01027 estate->err_text = gettext_noop("during statement block local variable initialization");
01028
01029 for (i = 0; i < block->n_initvars; i++)
01030 {
01031 n = block->initvarnos[i];
01032
01033 switch (estate->datums[n]->dtype)
01034 {
01035 case PLPGSQL_DTYPE_VAR:
01036 {
01037 PLpgSQL_var *var = (PLpgSQL_var *) (estate->datums[n]);
01038
01039
01040 free_var(var);
01041
01042
01043 var->value = (Datum) 0;
01044 var->isnull = true;
01045
01046 if (var->default_val == NULL)
01047 {
01048
01049
01050
01051
01052
01053
01054
01055
01056 if (!var->datatype->typinput.fn_strict)
01057 {
01058 bool valIsNull = true;
01059
01060 exec_assign_value(estate,
01061 (PLpgSQL_datum *) var,
01062 (Datum) 0,
01063 UNKNOWNOID,
01064 &valIsNull);
01065 }
01066 if (var->notnull)
01067 ereport(ERROR,
01068 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
01069 errmsg("variable \"%s\" declared NOT NULL cannot default to NULL",
01070 var->refname)));
01071 }
01072 else
01073 {
01074 exec_assign_expr(estate, (PLpgSQL_datum *) var,
01075 var->default_val);
01076 }
01077 }
01078 break;
01079
01080 case PLPGSQL_DTYPE_REC:
01081 {
01082 PLpgSQL_rec *rec = (PLpgSQL_rec *) (estate->datums[n]);
01083
01084 if (rec->freetup)
01085 {
01086 heap_freetuple(rec->tup);
01087 rec->freetup = false;
01088 }
01089 if (rec->freetupdesc)
01090 {
01091 FreeTupleDesc(rec->tupdesc);
01092 rec->freetupdesc = false;
01093 }
01094 rec->tup = NULL;
01095 rec->tupdesc = NULL;
01096 }
01097 break;
01098
01099 case PLPGSQL_DTYPE_RECFIELD:
01100 case PLPGSQL_DTYPE_ARRAYELEM:
01101 break;
01102
01103 default:
01104 elog(ERROR, "unrecognized dtype: %d",
01105 estate->datums[n]->dtype);
01106 }
01107 }
01108
01109 if (block->exceptions)
01110 {
01111
01112
01113
01114 MemoryContext oldcontext = CurrentMemoryContext;
01115 ResourceOwner oldowner = CurrentResourceOwner;
01116 ExprContext *old_eval_econtext = estate->eval_econtext;
01117 ErrorData *save_cur_error = estate->cur_error;
01118
01119 estate->err_text = gettext_noop("during statement block entry");
01120
01121 BeginInternalSubTransaction(NULL);
01122
01123 MemoryContextSwitchTo(oldcontext);
01124
01125 PG_TRY();
01126 {
01127
01128
01129
01130
01131
01132
01133 plpgsql_create_econtext(estate);
01134
01135 estate->err_text = NULL;
01136
01137
01138 rc = exec_stmts(estate, block->body);
01139
01140 estate->err_text = gettext_noop("during statement block exit");
01141
01142
01143
01144
01145
01146
01147
01148 if (rc == PLPGSQL_RC_RETURN &&
01149 !estate->retisset &&
01150 !estate->retisnull &&
01151 estate->rettupdesc == NULL)
01152 {
01153 int16 resTypLen;
01154 bool resTypByVal;
01155
01156 get_typlenbyval(estate->rettype, &resTypLen, &resTypByVal);
01157 estate->retval = datumCopy(estate->retval,
01158 resTypByVal, resTypLen);
01159 }
01160
01161
01162 ReleaseCurrentSubTransaction();
01163 MemoryContextSwitchTo(oldcontext);
01164 CurrentResourceOwner = oldowner;
01165
01166
01167
01168
01169
01170 estate->eval_econtext = old_eval_econtext;
01171
01172
01173
01174
01175
01176 SPI_restore_connection();
01177 }
01178 PG_CATCH();
01179 {
01180 ErrorData *edata;
01181 ListCell *e;
01182
01183 estate->err_text = gettext_noop("during exception cleanup");
01184
01185
01186 MemoryContextSwitchTo(oldcontext);
01187 edata = CopyErrorData();
01188 FlushErrorState();
01189
01190
01191 RollbackAndReleaseCurrentSubTransaction();
01192 MemoryContextSwitchTo(oldcontext);
01193 CurrentResourceOwner = oldowner;
01194
01195
01196 estate->eval_econtext = old_eval_econtext;
01197
01198
01199
01200
01201
01202
01203 SPI_restore_connection();
01204
01205
01206 exec_eval_cleanup(estate);
01207
01208
01209 foreach(e, block->exceptions->exc_list)
01210 {
01211 PLpgSQL_exception *exception = (PLpgSQL_exception *) lfirst(e);
01212
01213 if (exception_matches_conditions(edata, exception->conditions))
01214 {
01215
01216
01217
01218
01219
01220 PLpgSQL_var *state_var;
01221 PLpgSQL_var *errm_var;
01222
01223 state_var = (PLpgSQL_var *)
01224 estate->datums[block->exceptions->sqlstate_varno];
01225 errm_var = (PLpgSQL_var *)
01226 estate->datums[block->exceptions->sqlerrm_varno];
01227
01228 assign_text_var(state_var,
01229 unpack_sql_state(edata->sqlerrcode));
01230 assign_text_var(errm_var, edata->message);
01231
01232
01233
01234
01235
01236 estate->cur_error = edata;
01237
01238 estate->err_text = NULL;
01239
01240 rc = exec_stmts(estate, exception->action);
01241
01242 free_var(state_var);
01243 state_var->value = (Datum) 0;
01244 state_var->isnull = true;
01245 free_var(errm_var);
01246 errm_var->value = (Datum) 0;
01247 errm_var->isnull = true;
01248
01249 break;
01250 }
01251 }
01252
01253
01254
01255
01256
01257
01258 estate->cur_error = save_cur_error;
01259
01260
01261 if (e == NULL)
01262 ReThrowError(edata);
01263 else
01264 FreeErrorData(edata);
01265 }
01266 PG_END_TRY();
01267
01268 Assert(save_cur_error == estate->cur_error);
01269 }
01270 else
01271 {
01272
01273
01274
01275 estate->err_text = NULL;
01276
01277 rc = exec_stmts(estate, block->body);
01278 }
01279
01280 estate->err_text = NULL;
01281
01282
01283
01284
01285 switch (rc)
01286 {
01287 case PLPGSQL_RC_OK:
01288 case PLPGSQL_RC_RETURN:
01289 case PLPGSQL_RC_CONTINUE:
01290 return rc;
01291
01292 case PLPGSQL_RC_EXIT:
01293
01294
01295
01296
01297
01298 if (estate->exitlabel == NULL)
01299 return PLPGSQL_RC_EXIT;
01300 if (block->label == NULL)
01301 return PLPGSQL_RC_EXIT;
01302 if (strcmp(block->label, estate->exitlabel) != 0)
01303 return PLPGSQL_RC_EXIT;
01304 estate->exitlabel = NULL;
01305 return PLPGSQL_RC_OK;
01306
01307 default:
01308 elog(ERROR, "unrecognized rc: %d", rc);
01309 }
01310
01311 return PLPGSQL_RC_OK;
01312 }
01313
01314
01315
01316
01317
01318
01319
01320 static int
01321 exec_stmts(PLpgSQL_execstate *estate, List *stmts)
01322 {
01323 ListCell *s;
01324
01325 if (stmts == NIL)
01326 {
01327
01328
01329
01330
01331
01332 CHECK_FOR_INTERRUPTS();
01333 return PLPGSQL_RC_OK;
01334 }
01335
01336 foreach(s, stmts)
01337 {
01338 PLpgSQL_stmt *stmt = (PLpgSQL_stmt *) lfirst(s);
01339 int rc = exec_stmt(estate, stmt);
01340
01341 if (rc != PLPGSQL_RC_OK)
01342 return rc;
01343 }
01344
01345 return PLPGSQL_RC_OK;
01346 }
01347
01348
01349
01350
01351
01352
01353
01354 static int
01355 exec_stmt(PLpgSQL_execstate *estate, PLpgSQL_stmt *stmt)
01356 {
01357 PLpgSQL_stmt *save_estmt;
01358 int rc = -1;
01359
01360 save_estmt = estate->err_stmt;
01361 estate->err_stmt = stmt;
01362
01363
01364 if (*plugin_ptr && (*plugin_ptr)->stmt_beg)
01365 ((*plugin_ptr)->stmt_beg) (estate, stmt);
01366
01367 CHECK_FOR_INTERRUPTS();
01368
01369 switch ((enum PLpgSQL_stmt_types) stmt->cmd_type)
01370 {
01371 case PLPGSQL_STMT_BLOCK:
01372 rc = exec_stmt_block(estate, (PLpgSQL_stmt_block *) stmt);
01373 break;
01374
01375 case PLPGSQL_STMT_ASSIGN:
01376 rc = exec_stmt_assign(estate, (PLpgSQL_stmt_assign *) stmt);
01377 break;
01378
01379 case PLPGSQL_STMT_PERFORM:
01380 rc = exec_stmt_perform(estate, (PLpgSQL_stmt_perform *) stmt);
01381 break;
01382
01383 case PLPGSQL_STMT_GETDIAG:
01384 rc = exec_stmt_getdiag(estate, (PLpgSQL_stmt_getdiag *) stmt);
01385 break;
01386
01387 case PLPGSQL_STMT_IF:
01388 rc = exec_stmt_if(estate, (PLpgSQL_stmt_if *) stmt);
01389 break;
01390
01391 case PLPGSQL_STMT_CASE:
01392 rc = exec_stmt_case(estate, (PLpgSQL_stmt_case *) stmt);
01393 break;
01394
01395 case PLPGSQL_STMT_LOOP:
01396 rc = exec_stmt_loop(estate, (PLpgSQL_stmt_loop *) stmt);
01397 break;
01398
01399 case PLPGSQL_STMT_WHILE:
01400 rc = exec_stmt_while(estate, (PLpgSQL_stmt_while *) stmt);
01401 break;
01402
01403 case PLPGSQL_STMT_FORI:
01404 rc = exec_stmt_fori(estate, (PLpgSQL_stmt_fori *) stmt);
01405 break;
01406
01407 case PLPGSQL_STMT_FORS:
01408 rc = exec_stmt_fors(estate, (PLpgSQL_stmt_fors *) stmt);
01409 break;
01410
01411 case PLPGSQL_STMT_FORC:
01412 rc = exec_stmt_forc(estate, (PLpgSQL_stmt_forc *) stmt);
01413 break;
01414
01415 case PLPGSQL_STMT_FOREACH_A:
01416 rc = exec_stmt_foreach_a(estate, (PLpgSQL_stmt_foreach_a *) stmt);
01417 break;
01418
01419 case PLPGSQL_STMT_EXIT:
01420 rc = exec_stmt_exit(estate, (PLpgSQL_stmt_exit *) stmt);
01421 break;
01422
01423 case PLPGSQL_STMT_RETURN:
01424 rc = exec_stmt_return(estate, (PLpgSQL_stmt_return *) stmt);
01425 break;
01426
01427 case PLPGSQL_STMT_RETURN_NEXT:
01428 rc = exec_stmt_return_next(estate, (PLpgSQL_stmt_return_next *) stmt);
01429 break;
01430
01431 case PLPGSQL_STMT_RETURN_QUERY:
01432 rc = exec_stmt_return_query(estate, (PLpgSQL_stmt_return_query *) stmt);
01433 break;
01434
01435 case PLPGSQL_STMT_RAISE:
01436 rc = exec_stmt_raise(estate, (PLpgSQL_stmt_raise *) stmt);
01437 break;
01438
01439 case PLPGSQL_STMT_EXECSQL:
01440 rc = exec_stmt_execsql(estate, (PLpgSQL_stmt_execsql *) stmt);
01441 break;
01442
01443 case PLPGSQL_STMT_DYNEXECUTE:
01444 rc = exec_stmt_dynexecute(estate, (PLpgSQL_stmt_dynexecute *) stmt);
01445 break;
01446
01447 case PLPGSQL_STMT_DYNFORS:
01448 rc = exec_stmt_dynfors(estate, (PLpgSQL_stmt_dynfors *) stmt);
01449 break;
01450
01451 case PLPGSQL_STMT_OPEN:
01452 rc = exec_stmt_open(estate, (PLpgSQL_stmt_open *) stmt);
01453 break;
01454
01455 case PLPGSQL_STMT_FETCH:
01456 rc = exec_stmt_fetch(estate, (PLpgSQL_stmt_fetch *) stmt);
01457 break;
01458
01459 case PLPGSQL_STMT_CLOSE:
01460 rc = exec_stmt_close(estate, (PLpgSQL_stmt_close *) stmt);
01461 break;
01462
01463 default:
01464 estate->err_stmt = save_estmt;
01465 elog(ERROR, "unrecognized cmdtype: %d", stmt->cmd_type);
01466 }
01467
01468
01469 if (*plugin_ptr && (*plugin_ptr)->stmt_end)
01470 ((*plugin_ptr)->stmt_end) (estate, stmt);
01471
01472 estate->err_stmt = save_estmt;
01473
01474 return rc;
01475 }
01476
01477
01478
01479
01480
01481
01482
01483 static int
01484 exec_stmt_assign(PLpgSQL_execstate *estate, PLpgSQL_stmt_assign *stmt)
01485 {
01486 Assert(stmt->varno >= 0);
01487
01488 exec_assign_expr(estate, estate->datums[stmt->varno], stmt->expr);
01489
01490 return PLPGSQL_RC_OK;
01491 }
01492
01493
01494
01495
01496
01497
01498
01499 static int
01500 exec_stmt_perform(PLpgSQL_execstate *estate, PLpgSQL_stmt_perform *stmt)
01501 {
01502 PLpgSQL_expr *expr = stmt->expr;
01503
01504 (void) exec_run_select(estate, expr, 0, NULL);
01505 exec_set_found(estate, (estate->eval_processed != 0));
01506 exec_eval_cleanup(estate);
01507
01508 return PLPGSQL_RC_OK;
01509 }
01510
01511
01512
01513
01514
01515
01516 static int
01517 exec_stmt_getdiag(PLpgSQL_execstate *estate, PLpgSQL_stmt_getdiag *stmt)
01518 {
01519 ListCell *lc;
01520
01521
01522
01523
01524
01525
01526
01527 if (stmt->is_stacked && estate->cur_error == NULL)
01528 ereport(ERROR,
01529 (errcode(ERRCODE_STACKED_DIAGNOSTICS_ACCESSED_WITHOUT_ACTIVE_HANDLER),
01530 errmsg("GET STACKED DIAGNOSTICS cannot be used outside an exception handler")));
01531
01532 foreach(lc, stmt->diag_items)
01533 {
01534 PLpgSQL_diag_item *diag_item = (PLpgSQL_diag_item *) lfirst(lc);
01535 PLpgSQL_datum *var = estate->datums[diag_item->target];
01536 bool isnull = false;
01537
01538 switch (diag_item->kind)
01539 {
01540 case PLPGSQL_GETDIAG_ROW_COUNT:
01541 exec_assign_value(estate, var,
01542 UInt32GetDatum(estate->eval_processed),
01543 INT4OID, &isnull);
01544 break;
01545
01546 case PLPGSQL_GETDIAG_RESULT_OID:
01547 exec_assign_value(estate, var,
01548 ObjectIdGetDatum(estate->eval_lastoid),
01549 OIDOID, &isnull);
01550 break;
01551
01552 case PLPGSQL_GETDIAG_ERROR_CONTEXT:
01553 exec_assign_c_string(estate, var,
01554 estate->cur_error->context);
01555 break;
01556
01557 case PLPGSQL_GETDIAG_ERROR_DETAIL:
01558 exec_assign_c_string(estate, var,
01559 estate->cur_error->detail);
01560 break;
01561
01562 case PLPGSQL_GETDIAG_ERROR_HINT:
01563 exec_assign_c_string(estate, var,
01564 estate->cur_error->hint);
01565 break;
01566
01567 case PLPGSQL_GETDIAG_RETURNED_SQLSTATE:
01568 exec_assign_c_string(estate, var,
01569 unpack_sql_state(estate->cur_error->sqlerrcode));
01570 break;
01571
01572 case PLPGSQL_GETDIAG_MESSAGE_TEXT:
01573 exec_assign_c_string(estate, var,
01574 estate->cur_error->message);
01575 break;
01576
01577 default:
01578 elog(ERROR, "unrecognized diagnostic item kind: %d",
01579 diag_item->kind);
01580 }
01581 }
01582
01583 return PLPGSQL_RC_OK;
01584 }
01585
01586
01587
01588
01589
01590
01591
01592 static int
01593 exec_stmt_if(PLpgSQL_execstate *estate, PLpgSQL_stmt_if *stmt)
01594 {
01595 bool value;
01596 bool isnull;
01597 ListCell *lc;
01598
01599 value = exec_eval_boolean(estate, stmt->cond, &isnull);
01600 exec_eval_cleanup(estate);
01601 if (!isnull && value)
01602 return exec_stmts(estate, stmt->then_body);
01603
01604 foreach(lc, stmt->elsif_list)
01605 {
01606 PLpgSQL_if_elsif *elif = (PLpgSQL_if_elsif *) lfirst(lc);
01607
01608 value = exec_eval_boolean(estate, elif->cond, &isnull);
01609 exec_eval_cleanup(estate);
01610 if (!isnull && value)
01611 return exec_stmts(estate, elif->stmts);
01612 }
01613
01614 return exec_stmts(estate, stmt->else_body);
01615 }
01616
01617
01618
01619
01620
01621
01622 static int
01623 exec_stmt_case(PLpgSQL_execstate *estate, PLpgSQL_stmt_case *stmt)
01624 {
01625 PLpgSQL_var *t_var = NULL;
01626 bool isnull;
01627 ListCell *l;
01628
01629 if (stmt->t_expr != NULL)
01630 {
01631
01632 Datum t_val;
01633 Oid t_oid;
01634
01635 t_val = exec_eval_expr(estate, stmt->t_expr, &isnull, &t_oid);
01636
01637 t_var = (PLpgSQL_var *) estate->datums[stmt->t_varno];
01638
01639
01640
01641
01642
01643
01644 if (t_var->datatype->typoid != t_oid)
01645 t_var->datatype = plpgsql_build_datatype(t_oid,
01646 -1,
01647 estate->func->fn_input_collation);
01648
01649
01650 exec_assign_value(estate,
01651 (PLpgSQL_datum *) t_var,
01652 t_val,
01653 t_oid,
01654 &isnull);
01655
01656 exec_eval_cleanup(estate);
01657 }
01658
01659
01660 foreach(l, stmt->case_when_list)
01661 {
01662 PLpgSQL_case_when *cwt = (PLpgSQL_case_when *) lfirst(l);
01663 bool value;
01664
01665 value = exec_eval_boolean(estate, cwt->expr, &isnull);
01666 exec_eval_cleanup(estate);
01667 if (!isnull && value)
01668 {
01669
01670
01671
01672 if (t_var != NULL)
01673 {
01674 free_var(t_var);
01675 t_var->value = (Datum) 0;
01676 t_var->isnull = true;
01677 }
01678
01679
01680 return exec_stmts(estate, cwt->stmts);
01681 }
01682 }
01683
01684
01685 if (t_var != NULL)
01686 {
01687 free_var(t_var);
01688 t_var->value = (Datum) 0;
01689 t_var->isnull = true;
01690 }
01691
01692
01693 if (!stmt->have_else)
01694 ereport(ERROR,
01695 (errcode(ERRCODE_CASE_NOT_FOUND),
01696 errmsg("case not found"),
01697 errhint("CASE statement is missing ELSE part.")));
01698
01699
01700 return exec_stmts(estate, stmt->else_stmts);
01701 }
01702
01703
01704
01705
01706
01707
01708
01709 static int
01710 exec_stmt_loop(PLpgSQL_execstate *estate, PLpgSQL_stmt_loop *stmt)
01711 {
01712 for (;;)
01713 {
01714 int rc = exec_stmts(estate, stmt->body);
01715
01716 switch (rc)
01717 {
01718 case PLPGSQL_RC_OK:
01719 break;
01720
01721 case PLPGSQL_RC_EXIT:
01722 if (estate->exitlabel == NULL)
01723 return PLPGSQL_RC_OK;
01724 if (stmt->label == NULL)
01725 return PLPGSQL_RC_EXIT;
01726 if (strcmp(stmt->label, estate->exitlabel) != 0)
01727 return PLPGSQL_RC_EXIT;
01728 estate->exitlabel = NULL;
01729 return PLPGSQL_RC_OK;
01730
01731 case PLPGSQL_RC_CONTINUE:
01732 if (estate->exitlabel == NULL)
01733
01734 break;
01735 else if (stmt->label != NULL &&
01736 strcmp(stmt->label, estate->exitlabel) == 0)
01737
01738 estate->exitlabel = NULL;
01739 else
01740
01741 return PLPGSQL_RC_CONTINUE;
01742 break;
01743
01744 case PLPGSQL_RC_RETURN:
01745 return rc;
01746
01747 default:
01748 elog(ERROR, "unrecognized rc: %d", rc);
01749 }
01750 }
01751 }
01752
01753
01754
01755
01756
01757
01758
01759
01760 static int
01761 exec_stmt_while(PLpgSQL_execstate *estate, PLpgSQL_stmt_while *stmt)
01762 {
01763 for (;;)
01764 {
01765 int rc;
01766 bool value;
01767 bool isnull;
01768
01769 value = exec_eval_boolean(estate, stmt->cond, &isnull);
01770 exec_eval_cleanup(estate);
01771
01772 if (isnull || !value)
01773 break;
01774
01775 rc = exec_stmts(estate, stmt->body);
01776
01777 switch (rc)
01778 {
01779 case PLPGSQL_RC_OK:
01780 break;
01781
01782 case PLPGSQL_RC_EXIT:
01783 if (estate->exitlabel == NULL)
01784 return PLPGSQL_RC_OK;
01785 if (stmt->label == NULL)
01786 return PLPGSQL_RC_EXIT;
01787 if (strcmp(stmt->label, estate->exitlabel) != 0)
01788 return PLPGSQL_RC_EXIT;
01789 estate->exitlabel = NULL;
01790 return PLPGSQL_RC_OK;
01791
01792 case PLPGSQL_RC_CONTINUE:
01793 if (estate->exitlabel == NULL)
01794
01795 break;
01796 else if (stmt->label != NULL &&
01797 strcmp(stmt->label, estate->exitlabel) == 0)
01798
01799 estate->exitlabel = NULL;
01800 else
01801
01802 return PLPGSQL_RC_CONTINUE;
01803 break;
01804
01805 case PLPGSQL_RC_RETURN:
01806 return rc;
01807
01808 default:
01809 elog(ERROR, "unrecognized rc: %d", rc);
01810 }
01811 }
01812
01813 return PLPGSQL_RC_OK;
01814 }
01815
01816
01817
01818
01819
01820
01821
01822
01823 static int
01824 exec_stmt_fori(PLpgSQL_execstate *estate, PLpgSQL_stmt_fori *stmt)
01825 {
01826 PLpgSQL_var *var;
01827 Datum value;
01828 bool isnull;
01829 Oid valtype;
01830 int32 loop_value;
01831 int32 end_value;
01832 int32 step_value;
01833 bool found = false;
01834 int rc = PLPGSQL_RC_OK;
01835
01836 var = (PLpgSQL_var *) (estate->datums[stmt->var->dno]);
01837
01838
01839
01840
01841 value = exec_eval_expr(estate, stmt->lower, &isnull, &valtype);
01842 value = exec_cast_value(estate, value, valtype, var->datatype->typoid,
01843 &(var->datatype->typinput),
01844 var->datatype->typioparam,
01845 var->datatype->atttypmod, isnull);
01846 if (isnull)
01847 ereport(ERROR,
01848 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
01849 errmsg("lower bound of FOR loop cannot be null")));
01850 loop_value = DatumGetInt32(value);
01851 exec_eval_cleanup(estate);
01852
01853
01854
01855
01856 value = exec_eval_expr(estate, stmt->upper, &isnull, &valtype);
01857 value = exec_cast_value(estate, value, valtype, var->datatype->typoid,
01858 &(var->datatype->typinput),
01859 var->datatype->typioparam,
01860 var->datatype->atttypmod, isnull);
01861 if (isnull)
01862 ereport(ERROR,
01863 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
01864 errmsg("upper bound of FOR loop cannot be null")));
01865 end_value = DatumGetInt32(value);
01866 exec_eval_cleanup(estate);
01867
01868
01869
01870
01871 if (stmt->step)
01872 {
01873 value = exec_eval_expr(estate, stmt->step, &isnull, &valtype);
01874 value = exec_cast_value(estate, value, valtype, var->datatype->typoid,
01875 &(var->datatype->typinput),
01876 var->datatype->typioparam,
01877 var->datatype->atttypmod, isnull);
01878 if (isnull)
01879 ereport(ERROR,
01880 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
01881 errmsg("BY value of FOR loop cannot be null")));
01882 step_value = DatumGetInt32(value);
01883 exec_eval_cleanup(estate);
01884 if (step_value <= 0)
01885 ereport(ERROR,
01886 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
01887 errmsg("BY value of FOR loop must be greater than zero")));
01888 }
01889 else
01890 step_value = 1;
01891
01892
01893
01894
01895 for (;;)
01896 {
01897
01898
01899
01900 if (stmt->reverse)
01901 {
01902 if (loop_value < end_value)
01903 break;
01904 }
01905 else
01906 {
01907 if (loop_value > end_value)
01908 break;
01909 }
01910
01911 found = true;
01912
01913
01914
01915
01916 var->value = Int32GetDatum(loop_value);
01917 var->isnull = false;
01918
01919
01920
01921
01922 rc = exec_stmts(estate, stmt->body);
01923
01924 if (rc == PLPGSQL_RC_RETURN)
01925 break;
01926 else if (rc == PLPGSQL_RC_EXIT)
01927 {
01928 if (estate->exitlabel == NULL)
01929
01930 rc = PLPGSQL_RC_OK;
01931 else if (stmt->label != NULL &&
01932 strcmp(stmt->label, estate->exitlabel) == 0)
01933 {
01934
01935 estate->exitlabel = NULL;
01936 rc = PLPGSQL_RC_OK;
01937 }
01938
01939
01940
01941
01942
01943
01944 break;
01945 }
01946 else if (rc == PLPGSQL_RC_CONTINUE)
01947 {
01948 if (estate->exitlabel == NULL)
01949
01950 rc = PLPGSQL_RC_OK;
01951 else if (stmt->label != NULL &&
01952 strcmp(stmt->label, estate->exitlabel) == 0)
01953 {
01954
01955 estate->exitlabel = NULL;
01956 rc = PLPGSQL_RC_OK;
01957 }
01958 else
01959 {
01960
01961
01962
01963
01964
01965 break;
01966 }
01967 }
01968
01969
01970
01971
01972
01973 if (stmt->reverse)
01974 {
01975 if ((int32) (loop_value - step_value) > loop_value)
01976 break;
01977 loop_value -= step_value;
01978 }
01979 else
01980 {
01981 if ((int32) (loop_value + step_value) < loop_value)
01982 break;
01983 loop_value += step_value;
01984 }
01985 }
01986
01987
01988
01989
01990
01991
01992
01993 exec_set_found(estate, found);
01994
01995 return rc;
01996 }
01997
01998
01999
02000
02001
02002
02003
02004
02005
02006 static int
02007 exec_stmt_fors(PLpgSQL_execstate *estate, PLpgSQL_stmt_fors *stmt)
02008 {
02009 Portal portal;
02010 int rc;
02011
02012
02013
02014
02015 exec_run_select(estate, stmt->query, 0, &portal);
02016
02017
02018
02019
02020 rc = exec_for_query(estate, (PLpgSQL_stmt_forq *) stmt, portal, true);
02021
02022
02023
02024
02025 SPI_cursor_close(portal);
02026
02027 return rc;
02028 }
02029
02030
02031
02032
02033
02034
02035 static int
02036 exec_stmt_forc(PLpgSQL_execstate *estate, PLpgSQL_stmt_forc *stmt)
02037 {
02038 PLpgSQL_var *curvar;
02039 char *curname = NULL;
02040 PLpgSQL_expr *query;
02041 ParamListInfo paramLI;
02042 Portal portal;
02043 int rc;
02044
02045
02046
02047
02048
02049
02050 curvar = (PLpgSQL_var *) (estate->datums[stmt->curvar]);
02051 if (!curvar->isnull)
02052 {
02053 curname = TextDatumGetCString(curvar->value);
02054 if (SPI_cursor_find(curname) != NULL)
02055 ereport(ERROR,
02056 (errcode(ERRCODE_DUPLICATE_CURSOR),
02057 errmsg("cursor \"%s\" already in use", curname)));
02058 }
02059
02060
02061
02062
02063
02064
02065
02066
02067 if (stmt->argquery != NULL)
02068 {
02069
02070
02071
02072
02073
02074
02075 PLpgSQL_stmt_execsql set_args;
02076
02077 if (curvar->cursor_explicit_argrow < 0)
02078 ereport(ERROR,
02079 (errcode(ERRCODE_SYNTAX_ERROR),
02080 errmsg("arguments given for cursor without arguments")));
02081
02082 memset(&set_args, 0, sizeof(set_args));
02083 set_args.cmd_type = PLPGSQL_STMT_EXECSQL;
02084 set_args.lineno = stmt->lineno;
02085 set_args.sqlstmt = stmt->argquery;
02086 set_args.into = true;
02087
02088 set_args.row = (PLpgSQL_row *)
02089 (estate->datums[curvar->cursor_explicit_argrow]);
02090
02091 if (exec_stmt_execsql(estate, &set_args) != PLPGSQL_RC_OK)
02092 elog(ERROR, "open cursor failed during argument processing");
02093 }
02094 else
02095 {
02096 if (curvar->cursor_explicit_argrow >= 0)
02097 ereport(ERROR,
02098 (errcode(ERRCODE_SYNTAX_ERROR),
02099 errmsg("arguments required for cursor")));
02100 }
02101
02102 query = curvar->cursor_explicit_expr;
02103 Assert(query);
02104
02105 if (query->plan == NULL)
02106 exec_prepare_plan(estate, query, curvar->cursor_options);
02107
02108
02109
02110
02111 paramLI = setup_param_list(estate, query);
02112
02113
02114
02115
02116 portal = SPI_cursor_open_with_paramlist(curname, query->plan,
02117 paramLI,
02118 estate->readonly_func);
02119 if (portal == NULL)
02120 elog(ERROR, "could not open cursor: %s",
02121 SPI_result_code_string(SPI_result));
02122
02123
02124 if (paramLI)
02125 pfree(paramLI);
02126
02127
02128
02129
02130 if (curname == NULL)
02131 assign_text_var(curvar, portal->name);
02132
02133
02134
02135
02136
02137 rc = exec_for_query(estate, (PLpgSQL_stmt_forq *) stmt, portal, false);
02138
02139
02140
02141
02142
02143 SPI_cursor_close(portal);
02144
02145 if (curname == NULL)
02146 {
02147 free_var(curvar);
02148 curvar->value = (Datum) 0;
02149 curvar->isnull = true;
02150 }
02151
02152 if (curname)
02153 pfree(curname);
02154
02155 return rc;
02156 }
02157
02158
02159
02160
02161
02162
02163
02164
02165
02166
02167 static int
02168 exec_stmt_foreach_a(PLpgSQL_execstate *estate, PLpgSQL_stmt_foreach_a *stmt)
02169 {
02170 ArrayType *arr;
02171 Oid arrtype;
02172 PLpgSQL_datum *loop_var;
02173 Oid loop_var_elem_type;
02174 bool found = false;
02175 int rc = PLPGSQL_RC_OK;
02176 ArrayIterator array_iterator;
02177 Oid iterator_result_type;
02178 Datum value;
02179 bool isnull;
02180
02181
02182 value = exec_eval_expr(estate, stmt->expr, &isnull, &arrtype);
02183 if (isnull)
02184 ereport(ERROR,
02185 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
02186 errmsg("FOREACH expression must not be null")));
02187
02188
02189 if (!OidIsValid(get_element_type(arrtype)))
02190 ereport(ERROR,
02191 (errcode(ERRCODE_DATATYPE_MISMATCH),
02192 errmsg("FOREACH expression must yield an array, not type %s",
02193 format_type_be(arrtype))));
02194
02195
02196
02197
02198
02199
02200 arr = DatumGetArrayTypePCopy(value);
02201
02202
02203 exec_eval_cleanup(estate);
02204
02205
02206 if (stmt->slice < 0 || stmt->slice > ARR_NDIM(arr))
02207 ereport(ERROR,
02208 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
02209 errmsg("slice dimension (%d) is out of the valid range 0..%d",
02210 stmt->slice, ARR_NDIM(arr))));
02211
02212
02213 loop_var = estate->datums[stmt->varno];
02214 if (loop_var->dtype == PLPGSQL_DTYPE_REC ||
02215 loop_var->dtype == PLPGSQL_DTYPE_ROW)
02216 {
02217
02218
02219
02220
02221 loop_var_elem_type = InvalidOid;
02222 }
02223 else
02224 loop_var_elem_type = get_element_type(exec_get_datum_type(estate,
02225 loop_var));
02226
02227
02228
02229
02230
02231
02232
02233 if (stmt->slice > 0 && loop_var_elem_type == InvalidOid)
02234 ereport(ERROR,
02235 (errcode(ERRCODE_DATATYPE_MISMATCH),
02236 errmsg("FOREACH ... SLICE loop variable must be of an array type")));
02237 if (stmt->slice == 0 && loop_var_elem_type != InvalidOid)
02238 ereport(ERROR,
02239 (errcode(ERRCODE_DATATYPE_MISMATCH),
02240 errmsg("FOREACH loop variable must not be of an array type")));
02241
02242
02243 array_iterator = array_create_iterator(arr, stmt->slice);
02244
02245
02246 if (stmt->slice > 0)
02247 {
02248
02249 iterator_result_type = arrtype;
02250 }
02251 else
02252 {
02253
02254 iterator_result_type = ARR_ELEMTYPE(arr);
02255 }
02256
02257
02258 while (array_iterate(array_iterator, &value, &isnull))
02259 {
02260 found = true;
02261
02262
02263 exec_assign_value(estate, loop_var, value, iterator_result_type,
02264 &isnull);
02265
02266
02267 if (stmt->slice > 0)
02268 pfree(DatumGetPointer(value));
02269
02270
02271
02272
02273 rc = exec_stmts(estate, stmt->body);
02274
02275
02276 if (rc == PLPGSQL_RC_RETURN)
02277 break;
02278 else if (rc == PLPGSQL_RC_EXIT)
02279 {
02280 if (estate->exitlabel == NULL)
02281
02282 rc = PLPGSQL_RC_OK;
02283 else if (stmt->label != NULL &&
02284 strcmp(stmt->label, estate->exitlabel) == 0)
02285 {
02286
02287 estate->exitlabel = NULL;
02288 rc = PLPGSQL_RC_OK;
02289 }
02290
02291
02292
02293
02294
02295
02296 break;
02297 }
02298 else if (rc == PLPGSQL_RC_CONTINUE)
02299 {
02300 if (estate->exitlabel == NULL)
02301
02302 rc = PLPGSQL_RC_OK;
02303 else if (stmt->label != NULL &&
02304 strcmp(stmt->label, estate->exitlabel) == 0)
02305 {
02306
02307 estate->exitlabel = NULL;
02308 rc = PLPGSQL_RC_OK;
02309 }
02310 else
02311 {
02312
02313
02314
02315
02316
02317 break;
02318 }
02319 }
02320 }
02321
02322
02323 array_free_iterator(array_iterator);
02324 pfree(arr);
02325
02326
02327
02328
02329
02330
02331
02332 exec_set_found(estate, found);
02333
02334 return rc;
02335 }
02336
02337
02338
02339
02340
02341
02342
02343
02344 static int
02345 exec_stmt_exit(PLpgSQL_execstate *estate, PLpgSQL_stmt_exit *stmt)
02346 {
02347
02348
02349
02350 if (stmt->cond != NULL)
02351 {
02352 bool value;
02353 bool isnull;
02354
02355 value = exec_eval_boolean(estate, stmt->cond, &isnull);
02356 exec_eval_cleanup(estate);
02357 if (isnull || value == false)
02358 return PLPGSQL_RC_OK;
02359 }
02360
02361 estate->exitlabel = stmt->label;
02362 if (stmt->is_exit)
02363 return PLPGSQL_RC_EXIT;
02364 else
02365 return PLPGSQL_RC_CONTINUE;
02366 }
02367
02368
02369
02370
02371
02372
02373
02374 static int
02375 exec_stmt_return(PLpgSQL_execstate *estate, PLpgSQL_stmt_return *stmt)
02376 {
02377
02378
02379
02380
02381
02382 if (estate->retisset)
02383 return PLPGSQL_RC_RETURN;
02384
02385
02386 estate->retval = (Datum) 0;
02387 estate->rettupdesc = NULL;
02388 estate->retisnull = true;
02389
02390
02391
02392
02393
02394 if (stmt->retvarno >= 0)
02395 {
02396 PLpgSQL_datum *retvar = estate->datums[stmt->retvarno];
02397
02398 switch (retvar->dtype)
02399 {
02400 case PLPGSQL_DTYPE_VAR:
02401 {
02402 PLpgSQL_var *var = (PLpgSQL_var *) retvar;
02403
02404 estate->retval = var->value;
02405 estate->retisnull = var->isnull;
02406 estate->rettype = var->datatype->typoid;
02407 }
02408 break;
02409
02410 case PLPGSQL_DTYPE_REC:
02411 {
02412 PLpgSQL_rec *rec = (PLpgSQL_rec *) retvar;
02413
02414 if (HeapTupleIsValid(rec->tup))
02415 {
02416 estate->retval = PointerGetDatum(rec->tup);
02417 estate->rettupdesc = rec->tupdesc;
02418 estate->retisnull = false;
02419 }
02420 }
02421 break;
02422
02423 case PLPGSQL_DTYPE_ROW:
02424 {
02425 PLpgSQL_row *row = (PLpgSQL_row *) retvar;
02426
02427 Assert(row->rowtupdesc);
02428 estate->retval =
02429 PointerGetDatum(make_tuple_from_row(estate, row,
02430 row->rowtupdesc));
02431 if (DatumGetPointer(estate->retval) == NULL)
02432 elog(ERROR, "row not compatible with its own tupdesc");
02433 estate->rettupdesc = row->rowtupdesc;
02434 estate->retisnull = false;
02435 }
02436 break;
02437
02438 default:
02439 elog(ERROR, "unrecognized dtype: %d", retvar->dtype);
02440 }
02441
02442 return PLPGSQL_RC_RETURN;
02443 }
02444
02445 if (stmt->expr != NULL)
02446 {
02447 estate->retval = exec_eval_expr(estate, stmt->expr,
02448 &(estate->retisnull),
02449 &(estate->rettype));
02450
02451 if (estate->retistuple && !estate->retisnull)
02452 {
02453
02454 HeapTuple tuple;
02455 TupleDesc tupdesc;
02456
02457
02458 if (!type_is_rowtype(estate->rettype))
02459 ereport(ERROR,
02460 (errcode(ERRCODE_DATATYPE_MISMATCH),
02461 errmsg("cannot return non-composite value from function returning composite type")));
02462 tuple = get_tuple_from_datum(estate->retval);
02463 tupdesc = get_tupdesc_from_datum(estate->retval);
02464 estate->retval = PointerGetDatum(tuple);
02465 estate->rettupdesc = CreateTupleDescCopy(tupdesc);
02466 ReleaseTupleDesc(tupdesc);
02467 }
02468
02469 return PLPGSQL_RC_RETURN;
02470 }
02471
02472
02473
02474
02475
02476
02477 if (estate->fn_rettype == VOIDOID)
02478 {
02479 estate->retval = (Datum) 0;
02480 estate->retisnull = false;
02481 estate->rettype = VOIDOID;
02482 }
02483
02484 return PLPGSQL_RC_RETURN;
02485 }
02486
02487
02488
02489
02490
02491
02492
02493 static int
02494 exec_stmt_return_next(PLpgSQL_execstate *estate,
02495 PLpgSQL_stmt_return_next *stmt)
02496 {
02497 TupleDesc tupdesc;
02498 int natts;
02499 HeapTuple tuple = NULL;
02500 bool free_tuple = false;
02501
02502 if (!estate->retisset)
02503 ereport(ERROR,
02504 (errcode(ERRCODE_SYNTAX_ERROR),
02505 errmsg("cannot use RETURN NEXT in a non-SETOF function")));
02506
02507 if (estate->tuple_store == NULL)
02508 exec_init_tuple_store(estate);
02509
02510
02511 tupdesc = estate->rettupdesc;
02512 natts = tupdesc->natts;
02513
02514
02515
02516
02517
02518 if (stmt->retvarno >= 0)
02519 {
02520 PLpgSQL_datum *retvar = estate->datums[stmt->retvarno];
02521
02522 switch (retvar->dtype)
02523 {
02524 case PLPGSQL_DTYPE_VAR:
02525 {
02526 PLpgSQL_var *var = (PLpgSQL_var *) retvar;
02527 Datum retval = var->value;
02528 bool isNull = var->isnull;
02529
02530 if (natts != 1)
02531 ereport(ERROR,
02532 (errcode(ERRCODE_DATATYPE_MISMATCH),
02533 errmsg("wrong result type supplied in RETURN NEXT")));
02534
02535
02536 retval = exec_simple_cast_value(estate,
02537 retval,
02538 var->datatype->typoid,
02539 tupdesc->attrs[0]->atttypid,
02540 tupdesc->attrs[0]->atttypmod,
02541 isNull);
02542
02543 tuplestore_putvalues(estate->tuple_store, tupdesc,
02544 &retval, &isNull);
02545 }
02546 break;
02547
02548 case PLPGSQL_DTYPE_REC:
02549 {
02550 PLpgSQL_rec *rec = (PLpgSQL_rec *) retvar;
02551 TupleConversionMap *tupmap;
02552
02553 if (!HeapTupleIsValid(rec->tup))
02554 ereport(ERROR,
02555 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
02556 errmsg("record \"%s\" is not assigned yet",
02557 rec->refname),
02558 errdetail("The tuple structure of a not-yet-assigned"
02559 " record is indeterminate.")));
02560 tupmap = convert_tuples_by_position(rec->tupdesc,
02561 tupdesc,
02562 gettext_noop("wrong record type supplied in RETURN NEXT"));
02563 tuple = rec->tup;
02564
02565 if (tupmap)
02566 {
02567 tuple = do_convert_tuple(tuple, tupmap);
02568 free_conversion_map(tupmap);
02569 free_tuple = true;
02570 }
02571 }
02572 break;
02573
02574 case PLPGSQL_DTYPE_ROW:
02575 {
02576 PLpgSQL_row *row = (PLpgSQL_row *) retvar;
02577
02578 tuple = make_tuple_from_row(estate, row, tupdesc);
02579 if (tuple == NULL)
02580 ereport(ERROR,
02581 (errcode(ERRCODE_DATATYPE_MISMATCH),
02582 errmsg("wrong record type supplied in RETURN NEXT")));
02583 free_tuple = true;
02584 }
02585 break;
02586
02587 default:
02588 elog(ERROR, "unrecognized dtype: %d", retvar->dtype);
02589 break;
02590 }
02591 }
02592 else if (stmt->expr)
02593 {
02594 Datum retval;
02595 bool isNull;
02596 Oid rettype;
02597
02598 retval = exec_eval_expr(estate,
02599 stmt->expr,
02600 &isNull,
02601 &rettype);
02602
02603 if (estate->retistuple)
02604 {
02605
02606 if (!isNull)
02607 {
02608 TupleDesc retvaldesc;
02609 TupleConversionMap *tupmap;
02610
02611 if (!type_is_rowtype(rettype))
02612 ereport(ERROR,
02613 (errcode(ERRCODE_DATATYPE_MISMATCH),
02614 errmsg("cannot return non-composite value from function returning composite type")));
02615
02616 tuple = get_tuple_from_datum(retval);
02617 free_tuple = true;
02618
02619
02620 retvaldesc = get_tupdesc_from_datum(retval);
02621 tupmap = convert_tuples_by_position(retvaldesc, tupdesc,
02622 gettext_noop("returned record type does not match expected record type"));
02623 if (tupmap)
02624 {
02625 HeapTuple newtuple;
02626
02627 newtuple = do_convert_tuple(tuple, tupmap);
02628 free_conversion_map(tupmap);
02629 heap_freetuple(tuple);
02630 tuple = newtuple;
02631 }
02632 ReleaseTupleDesc(retvaldesc);
02633
02634 }
02635 else
02636 {
02637
02638 Datum *nulldatums;
02639 bool *nullflags;
02640
02641 nulldatums = (Datum *) palloc0(natts * sizeof(Datum));
02642 nullflags = (bool *) palloc(natts * sizeof(bool));
02643 memset(nullflags, true, natts * sizeof(bool));
02644 tuplestore_putvalues(estate->tuple_store, tupdesc,
02645 nulldatums, nullflags);
02646 pfree(nulldatums);
02647 pfree(nullflags);
02648 }
02649 }
02650 else
02651 {
02652
02653 if (natts != 1)
02654 ereport(ERROR,
02655 (errcode(ERRCODE_DATATYPE_MISMATCH),
02656 errmsg("wrong result type supplied in RETURN NEXT")));
02657
02658
02659 retval = exec_simple_cast_value(estate,
02660 retval,
02661 rettype,
02662 tupdesc->attrs[0]->atttypid,
02663 tupdesc->attrs[0]->atttypmod,
02664 isNull);
02665
02666 tuplestore_putvalues(estate->tuple_store, tupdesc,
02667 &retval, &isNull);
02668 }
02669 }
02670 else
02671 {
02672 ereport(ERROR,
02673 (errcode(ERRCODE_SYNTAX_ERROR),
02674 errmsg("RETURN NEXT must have a parameter")));
02675 }
02676
02677 if (HeapTupleIsValid(tuple))
02678 {
02679 tuplestore_puttuple(estate->tuple_store, tuple);
02680
02681 if (free_tuple)
02682 heap_freetuple(tuple);
02683 }
02684
02685 exec_eval_cleanup(estate);
02686
02687 return PLPGSQL_RC_OK;
02688 }
02689
02690
02691
02692
02693
02694
02695
02696 static int
02697 exec_stmt_return_query(PLpgSQL_execstate *estate,
02698 PLpgSQL_stmt_return_query *stmt)
02699 {
02700 Portal portal;
02701 uint32 processed = 0;
02702 TupleConversionMap *tupmap;
02703
02704 if (!estate->retisset)
02705 ereport(ERROR,
02706 (errcode(ERRCODE_SYNTAX_ERROR),
02707 errmsg("cannot use RETURN QUERY in a non-SETOF function")));
02708
02709 if (estate->tuple_store == NULL)
02710 exec_init_tuple_store(estate);
02711
02712 if (stmt->query != NULL)
02713 {
02714
02715 exec_run_select(estate, stmt->query, 0, &portal);
02716 }
02717 else
02718 {
02719
02720 Assert(stmt->dynquery != NULL);
02721 portal = exec_dynquery_with_params(estate, stmt->dynquery,
02722 stmt->params, NULL, 0);
02723 }
02724
02725 tupmap = convert_tuples_by_position(portal->tupDesc,
02726 estate->rettupdesc,
02727 gettext_noop("structure of query does not match function result type"));
02728
02729 while (true)
02730 {
02731 int i;
02732
02733 SPI_cursor_fetch(portal, true, 50);
02734 if (SPI_processed == 0)
02735 break;
02736
02737 for (i = 0; i < SPI_processed; i++)
02738 {
02739 HeapTuple tuple = SPI_tuptable->vals[i];
02740
02741 if (tupmap)
02742 tuple = do_convert_tuple(tuple, tupmap);
02743 tuplestore_puttuple(estate->tuple_store, tuple);
02744 if (tupmap)
02745 heap_freetuple(tuple);
02746 processed++;
02747 }
02748
02749 SPI_freetuptable(SPI_tuptable);
02750 }
02751
02752 if (tupmap)
02753 free_conversion_map(tupmap);
02754
02755 SPI_freetuptable(SPI_tuptable);
02756 SPI_cursor_close(portal);
02757
02758 estate->eval_processed = processed;
02759 exec_set_found(estate, processed != 0);
02760
02761 return PLPGSQL_RC_OK;
02762 }
02763
02764 static void
02765 exec_init_tuple_store(PLpgSQL_execstate *estate)
02766 {
02767 ReturnSetInfo *rsi = estate->rsi;
02768 MemoryContext oldcxt;
02769 ResourceOwner oldowner;
02770
02771
02772
02773
02774 if (!rsi || !IsA(rsi, ReturnSetInfo) ||
02775 (rsi->allowedModes & SFRM_Materialize) == 0 ||
02776 rsi->expectedDesc == NULL)
02777 ereport(ERROR,
02778 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
02779 errmsg("set-valued function called in context that cannot accept a set")));
02780
02781
02782
02783
02784
02785
02786
02787
02788 oldcxt = MemoryContextSwitchTo(estate->tuple_store_cxt);
02789 oldowner = CurrentResourceOwner;
02790 CurrentResourceOwner = estate->tuple_store_owner;
02791
02792 estate->tuple_store =
02793 tuplestore_begin_heap(rsi->allowedModes & SFRM_Materialize_Random,
02794 false, work_mem);
02795
02796 CurrentResourceOwner = oldowner;
02797 MemoryContextSwitchTo(oldcxt);
02798
02799 estate->rettupdesc = rsi->expectedDesc;
02800 }
02801
02802
02803
02804
02805
02806 static int
02807 exec_stmt_raise(PLpgSQL_execstate *estate, PLpgSQL_stmt_raise *stmt)
02808 {
02809 int err_code = 0;
02810 char *condname = NULL;
02811 char *err_message = NULL;
02812 char *err_detail = NULL;
02813 char *err_hint = NULL;
02814 ListCell *lc;
02815
02816
02817 if (stmt->condname == NULL && stmt->message == NULL &&
02818 stmt->options == NIL)
02819 {
02820 if (estate->cur_error != NULL)
02821 ReThrowError(estate->cur_error);
02822
02823 ereport(ERROR,
02824 (errcode(ERRCODE_STACKED_DIAGNOSTICS_ACCESSED_WITHOUT_ACTIVE_HANDLER),
02825 errmsg("RAISE without parameters cannot be used outside an exception handler")));
02826 }
02827
02828 if (stmt->condname)
02829 {
02830 err_code = plpgsql_recognize_err_condition(stmt->condname, true);
02831 condname = pstrdup(stmt->condname);
02832 }
02833
02834 if (stmt->message)
02835 {
02836 StringInfoData ds;
02837 ListCell *current_param;
02838 char *cp;
02839
02840 initStringInfo(&ds);
02841 current_param = list_head(stmt->params);
02842
02843 for (cp = stmt->message; *cp; cp++)
02844 {
02845
02846
02847
02848
02849 if (cp[0] == '%')
02850 {
02851 Oid paramtypeid;
02852 Datum paramvalue;
02853 bool paramisnull;
02854 char *extval;
02855
02856 if (cp[1] == '%')
02857 {
02858 appendStringInfoChar(&ds, '%');
02859 cp++;
02860 continue;
02861 }
02862
02863 if (current_param == NULL)
02864 ereport(ERROR,
02865 (errcode(ERRCODE_SYNTAX_ERROR),
02866 errmsg("too few parameters specified for RAISE")));
02867
02868 paramvalue = exec_eval_expr(estate,
02869 (PLpgSQL_expr *) lfirst(current_param),
02870 ¶misnull,
02871 ¶mtypeid);
02872
02873 if (paramisnull)
02874 extval = "<NULL>";
02875 else
02876 extval = convert_value_to_string(estate,
02877 paramvalue,
02878 paramtypeid);
02879 appendStringInfoString(&ds, extval);
02880 current_param = lnext(current_param);
02881 exec_eval_cleanup(estate);
02882 }
02883 else
02884 appendStringInfoChar(&ds, cp[0]);
02885 }
02886
02887
02888
02889
02890
02891 if (current_param != NULL)
02892 ereport(ERROR,
02893 (errcode(ERRCODE_SYNTAX_ERROR),
02894 errmsg("too many parameters specified for RAISE")));
02895
02896 err_message = ds.data;
02897
02898 }
02899
02900 foreach(lc, stmt->options)
02901 {
02902 PLpgSQL_raise_option *opt = (PLpgSQL_raise_option *) lfirst(lc);
02903 Datum optionvalue;
02904 bool optionisnull;
02905 Oid optiontypeid;
02906 char *extval;
02907
02908 optionvalue = exec_eval_expr(estate, opt->expr,
02909 &optionisnull,
02910 &optiontypeid);
02911 if (optionisnull)
02912 ereport(ERROR,
02913 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
02914 errmsg("RAISE statement option cannot be null")));
02915
02916 extval = convert_value_to_string(estate, optionvalue, optiontypeid);
02917
02918 switch (opt->opt_type)
02919 {
02920 case PLPGSQL_RAISEOPTION_ERRCODE:
02921 if (err_code)
02922 ereport(ERROR,
02923 (errcode(ERRCODE_SYNTAX_ERROR),
02924 errmsg("RAISE option already specified: %s",
02925 "ERRCODE")));
02926 err_code = plpgsql_recognize_err_condition(extval, true);
02927 condname = pstrdup(extval);
02928 break;
02929 case PLPGSQL_RAISEOPTION_MESSAGE:
02930 if (err_message)
02931 ereport(ERROR,
02932 (errcode(ERRCODE_SYNTAX_ERROR),
02933 errmsg("RAISE option already specified: %s",
02934 "MESSAGE")));
02935 err_message = pstrdup(extval);
02936 break;
02937 case PLPGSQL_RAISEOPTION_DETAIL:
02938 if (err_detail)
02939 ereport(ERROR,
02940 (errcode(ERRCODE_SYNTAX_ERROR),
02941 errmsg("RAISE option already specified: %s",
02942 "DETAIL")));
02943 err_detail = pstrdup(extval);
02944 break;
02945 case PLPGSQL_RAISEOPTION_HINT:
02946 if (err_hint)
02947 ereport(ERROR,
02948 (errcode(ERRCODE_SYNTAX_ERROR),
02949 errmsg("RAISE option already specified: %s",
02950 "HINT")));
02951 err_hint = pstrdup(extval);
02952 break;
02953 default:
02954 elog(ERROR, "unrecognized raise option: %d", opt->opt_type);
02955 }
02956
02957 exec_eval_cleanup(estate);
02958 }
02959
02960
02961 if (err_code == 0 && stmt->elog_level >= ERROR)
02962 err_code = ERRCODE_RAISE_EXCEPTION;
02963
02964
02965 if (err_message == NULL)
02966 {
02967 if (condname)
02968 {
02969 err_message = condname;
02970 condname = NULL;
02971 }
02972 else
02973 err_message = pstrdup(unpack_sql_state(err_code));
02974 }
02975
02976
02977
02978
02979 estate->err_text = raise_skip_msg;
02980
02981 ereport(stmt->elog_level,
02982 (err_code ? errcode(err_code) : 0,
02983 errmsg_internal("%s", err_message),
02984 (err_detail != NULL) ? errdetail_internal("%s", err_detail) : 0,
02985 (err_hint != NULL) ? errhint("%s", err_hint) : 0));
02986
02987 estate->err_text = NULL;
02988
02989 if (condname != NULL)
02990 pfree(condname);
02991 if (err_message != NULL)
02992 pfree(err_message);
02993 if (err_detail != NULL)
02994 pfree(err_detail);
02995 if (err_hint != NULL)
02996 pfree(err_hint);
02997
02998 return PLPGSQL_RC_OK;
02999 }
03000
03001
03002
03003
03004
03005
03006 static void
03007 plpgsql_estate_setup(PLpgSQL_execstate *estate,
03008 PLpgSQL_function *func,
03009 ReturnSetInfo *rsi)
03010 {
03011
03012 func->cur_estate = estate;
03013
03014 estate->func = func;
03015
03016 estate->retval = (Datum) 0;
03017 estate->retisnull = true;
03018 estate->rettype = InvalidOid;
03019
03020 estate->fn_rettype = func->fn_rettype;
03021 estate->retistuple = func->fn_retistuple;
03022 estate->retisset = func->fn_retset;
03023
03024 estate->readonly_func = func->fn_readonly;
03025
03026 estate->rettupdesc = NULL;
03027 estate->exitlabel = NULL;
03028 estate->cur_error = NULL;
03029
03030 estate->tuple_store = NULL;
03031 if (rsi)
03032 {
03033 estate->tuple_store_cxt = rsi->econtext->ecxt_per_query_memory;
03034 estate->tuple_store_owner = CurrentResourceOwner;
03035 }
03036 else
03037 {
03038 estate->tuple_store_cxt = NULL;
03039 estate->tuple_store_owner = NULL;
03040 }
03041 estate->rsi = rsi;
03042
03043 estate->found_varno = func->found_varno;
03044 estate->ndatums = func->ndatums;
03045 estate->datums = palloc(sizeof(PLpgSQL_datum *) * estate->ndatums);
03046
03047
03048 estate->eval_tuptable = NULL;
03049 estate->eval_processed = 0;
03050 estate->eval_lastoid = InvalidOid;
03051 estate->eval_econtext = NULL;
03052 estate->cur_expr = NULL;
03053
03054 estate->err_stmt = NULL;
03055 estate->err_text = NULL;
03056
03057 estate->plugin_info = NULL;
03058
03059
03060
03061
03062 plpgsql_create_econtext(estate);
03063
03064
03065
03066
03067
03068
03069
03070 if (*plugin_ptr)
03071 {
03072 (*plugin_ptr)->error_callback = plpgsql_exec_error_callback;
03073 (*plugin_ptr)->assign_expr = exec_assign_expr;
03074
03075 if ((*plugin_ptr)->func_setup)
03076 ((*plugin_ptr)->func_setup) (estate, func);
03077 }
03078 }
03079
03080
03081
03082
03083
03084
03085
03086
03087
03088
03089
03090 static void
03091 exec_eval_cleanup(PLpgSQL_execstate *estate)
03092 {
03093
03094 if (estate->eval_tuptable != NULL)
03095 SPI_freetuptable(estate->eval_tuptable);
03096 estate->eval_tuptable = NULL;
03097
03098
03099 if (estate->eval_econtext != NULL)
03100 ResetExprContext(estate->eval_econtext);
03101 }
03102
03103
03104
03105
03106
03107
03108 static void
03109 exec_prepare_plan(PLpgSQL_execstate *estate,
03110 PLpgSQL_expr *expr, int cursorOptions)
03111 {
03112 SPIPlanPtr plan;
03113
03114
03115
03116
03117
03118 expr->func = estate->func;
03119
03120
03121
03122
03123 plan = SPI_prepare_params(expr->query,
03124 (ParserSetupHook) plpgsql_parser_setup,
03125 (void *) expr,
03126 cursorOptions);
03127 if (plan == NULL)
03128 {
03129
03130 switch (SPI_result)
03131 {
03132 case SPI_ERROR_COPY:
03133 ereport(ERROR,
03134 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
03135 errmsg("cannot COPY to/from client in PL/pgSQL")));
03136 case SPI_ERROR_TRANSACTION:
03137 ereport(ERROR,
03138 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
03139 errmsg("cannot begin/end transactions in PL/pgSQL"),
03140 errhint("Use a BEGIN block with an EXCEPTION clause instead.")));
03141 default:
03142 elog(ERROR, "SPI_prepare_params failed for \"%s\": %s",
03143 expr->query, SPI_result_code_string(SPI_result));
03144 }
03145 }
03146 SPI_keepplan(plan);
03147 expr->plan = plan;
03148
03149
03150 exec_simple_check_plan(expr);
03151 }
03152
03153
03154
03155
03156
03157
03158 static int
03159 exec_stmt_execsql(PLpgSQL_execstate *estate,
03160 PLpgSQL_stmt_execsql *stmt)
03161 {
03162 ParamListInfo paramLI;
03163 long tcount;
03164 int rc;
03165 PLpgSQL_expr *expr = stmt->sqlstmt;
03166
03167
03168
03169
03170
03171 if (expr->plan == NULL)
03172 {
03173 ListCell *l;
03174
03175 exec_prepare_plan(estate, expr, 0);
03176 stmt->mod_stmt = false;
03177 foreach(l, SPI_plan_get_plan_sources(expr->plan))
03178 {
03179 CachedPlanSource *plansource = (CachedPlanSource *) lfirst(l);
03180 ListCell *l2;
03181
03182 foreach(l2, plansource->query_list)
03183 {
03184 Query *q = (Query *) lfirst(l2);
03185
03186 Assert(IsA(q, Query));
03187 if (q->canSetTag)
03188 {
03189 if (q->commandType == CMD_INSERT ||
03190 q->commandType == CMD_UPDATE ||
03191 q->commandType == CMD_DELETE)
03192 stmt->mod_stmt = true;
03193 }
03194 }
03195 }
03196 }
03197
03198
03199
03200
03201 paramLI = setup_param_list(estate, expr);
03202
03203
03204
03205
03206
03207
03208
03209
03210
03211
03212
03213
03214 if (stmt->into)
03215 {
03216 if (stmt->strict || stmt->mod_stmt)
03217 tcount = 2;
03218 else
03219 tcount = 1;
03220 }
03221 else
03222 tcount = 0;
03223
03224
03225
03226
03227 rc = SPI_execute_plan_with_paramlist(expr->plan, paramLI,
03228 estate->readonly_func, tcount);
03229
03230
03231
03232
03233
03234
03235 switch (rc)
03236 {
03237 case SPI_OK_SELECT:
03238 Assert(!stmt->mod_stmt);
03239 exec_set_found(estate, (SPI_processed != 0));
03240 break;
03241
03242 case SPI_OK_INSERT:
03243 case SPI_OK_UPDATE:
03244 case SPI_OK_DELETE:
03245 case SPI_OK_INSERT_RETURNING:
03246 case SPI_OK_UPDATE_RETURNING:
03247 case SPI_OK_DELETE_RETURNING:
03248 Assert(stmt->mod_stmt);
03249 exec_set_found(estate, (SPI_processed != 0));
03250 break;
03251
03252 case SPI_OK_SELINTO:
03253 case SPI_OK_UTILITY:
03254 Assert(!stmt->mod_stmt);
03255 break;
03256
03257 case SPI_OK_REWRITTEN:
03258 Assert(!stmt->mod_stmt);
03259
03260
03261
03262
03263
03264
03265 exec_set_found(estate, false);
03266 break;
03267
03268
03269 case SPI_ERROR_COPY:
03270 ereport(ERROR,
03271 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
03272 errmsg("cannot COPY to/from client in PL/pgSQL")));
03273 case SPI_ERROR_TRANSACTION:
03274 ereport(ERROR,
03275 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
03276 errmsg("cannot begin/end transactions in PL/pgSQL"),
03277 errhint("Use a BEGIN block with an EXCEPTION clause instead.")));
03278
03279 default:
03280 elog(ERROR, "SPI_execute_plan_with_paramlist failed executing query \"%s\": %s",
03281 expr->query, SPI_result_code_string(rc));
03282 }
03283
03284
03285 estate->eval_processed = SPI_processed;
03286 estate->eval_lastoid = SPI_lastoid;
03287
03288
03289 if (stmt->into)
03290 {
03291 SPITupleTable *tuptab = SPI_tuptable;
03292 uint32 n = SPI_processed;
03293 PLpgSQL_rec *rec = NULL;
03294 PLpgSQL_row *row = NULL;
03295
03296
03297 if (tuptab == NULL)
03298 ereport(ERROR,
03299 (errcode(ERRCODE_SYNTAX_ERROR),
03300 errmsg("INTO used with a command that cannot return data")));
03301
03302
03303 if (stmt->rec != NULL)
03304 rec = (PLpgSQL_rec *) (estate->datums[stmt->rec->dno]);
03305 else if (stmt->row != NULL)
03306 row = (PLpgSQL_row *) (estate->datums[stmt->row->dno]);
03307 else
03308 elog(ERROR, "unsupported target");
03309
03310
03311
03312
03313
03314
03315 if (n == 0)
03316 {
03317 if (stmt->strict)
03318 ereport(ERROR,
03319 (errcode(ERRCODE_NO_DATA_FOUND),
03320 errmsg("query returned no rows")));
03321
03322 exec_move_row(estate, rec, row, NULL, tuptab->tupdesc);
03323 }
03324 else
03325 {
03326 if (n > 1 && (stmt->strict || stmt->mod_stmt))
03327 ereport(ERROR,
03328 (errcode(ERRCODE_TOO_MANY_ROWS),
03329 errmsg("query returned more than one row")));
03330
03331 exec_move_row(estate, rec, row, tuptab->vals[0], tuptab->tupdesc);
03332 }
03333
03334
03335 exec_eval_cleanup(estate);
03336 SPI_freetuptable(SPI_tuptable);
03337 }
03338 else
03339 {
03340
03341 if (SPI_tuptable != NULL)
03342 ereport(ERROR,
03343 (errcode(ERRCODE_SYNTAX_ERROR),
03344 errmsg("query has no destination for result data"),
03345 (rc == SPI_OK_SELECT) ? errhint("If you want to discard the results of a SELECT, use PERFORM instead.") : 0));
03346 }
03347
03348 if (paramLI)
03349 pfree(paramLI);
03350
03351 return PLPGSQL_RC_OK;
03352 }
03353
03354
03355
03356
03357
03358
03359
03360 static int
03361 exec_stmt_dynexecute(PLpgSQL_execstate *estate,
03362 PLpgSQL_stmt_dynexecute *stmt)
03363 {
03364 Datum query;
03365 bool isnull = false;
03366 Oid restype;
03367 char *querystr;
03368 int exec_res;
03369
03370
03371
03372
03373
03374 query = exec_eval_expr(estate, stmt->query, &isnull, &restype);
03375 if (isnull)
03376 ereport(ERROR,
03377 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
03378 errmsg("query string argument of EXECUTE is null")));
03379
03380
03381 querystr = convert_value_to_string(estate, query, restype);
03382
03383
03384 querystr = pstrdup(querystr);
03385
03386 exec_eval_cleanup(estate);
03387
03388
03389
03390
03391 if (stmt->params)
03392 {
03393 PreparedParamsData *ppd;
03394
03395 ppd = exec_eval_using_params(estate, stmt->params);
03396 exec_res = SPI_execute_with_args(querystr,
03397 ppd->nargs, ppd->types,
03398 ppd->values, ppd->nulls,
03399 estate->readonly_func, 0);
03400 free_params_data(ppd);
03401 }
03402 else
03403 exec_res = SPI_execute(querystr, estate->readonly_func, 0);
03404
03405 switch (exec_res)
03406 {
03407 case SPI_OK_SELECT:
03408 case SPI_OK_INSERT:
03409 case SPI_OK_UPDATE:
03410 case SPI_OK_DELETE:
03411 case SPI_OK_INSERT_RETURNING:
03412 case SPI_OK_UPDATE_RETURNING:
03413 case SPI_OK_DELETE_RETURNING:
03414 case SPI_OK_UTILITY:
03415 case SPI_OK_REWRITTEN:
03416 break;
03417
03418 case 0:
03419
03420
03421
03422
03423
03424 break;
03425
03426 case SPI_OK_SELINTO:
03427
03428
03429
03430
03431
03432
03433
03434
03435 ereport(ERROR,
03436 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
03437 errmsg("EXECUTE of SELECT ... INTO is not implemented"),
03438 errhint("You might want to use EXECUTE ... INTO or EXECUTE CREATE TABLE ... AS instead.")));
03439 break;
03440
03441
03442 case SPI_ERROR_COPY:
03443 ereport(ERROR,
03444 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
03445 errmsg("cannot COPY to/from client in PL/pgSQL")));
03446 case SPI_ERROR_TRANSACTION:
03447 ereport(ERROR,
03448 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
03449 errmsg("cannot begin/end transactions in PL/pgSQL"),
03450 errhint("Use a BEGIN block with an EXCEPTION clause instead.")));
03451
03452 default:
03453 elog(ERROR, "SPI_execute failed executing query \"%s\": %s",
03454 querystr, SPI_result_code_string(exec_res));
03455 break;
03456 }
03457
03458
03459 estate->eval_processed = SPI_processed;
03460 estate->eval_lastoid = SPI_lastoid;
03461
03462
03463 if (stmt->into)
03464 {
03465 SPITupleTable *tuptab = SPI_tuptable;
03466 uint32 n = SPI_processed;
03467 PLpgSQL_rec *rec = NULL;
03468 PLpgSQL_row *row = NULL;
03469
03470
03471 if (tuptab == NULL)
03472 ereport(ERROR,
03473 (errcode(ERRCODE_SYNTAX_ERROR),
03474 errmsg("INTO used with a command that cannot return data")));
03475
03476
03477 if (stmt->rec != NULL)
03478 rec = (PLpgSQL_rec *) (estate->datums[stmt->rec->dno]);
03479 else if (stmt->row != NULL)
03480 row = (PLpgSQL_row *) (estate->datums[stmt->row->dno]);
03481 else
03482 elog(ERROR, "unsupported target");
03483
03484
03485
03486
03487
03488
03489 if (n == 0)
03490 {
03491 if (stmt->strict)
03492 ereport(ERROR,
03493 (errcode(ERRCODE_NO_DATA_FOUND),
03494 errmsg("query returned no rows")));
03495
03496 exec_move_row(estate, rec, row, NULL, tuptab->tupdesc);
03497 }
03498 else
03499 {
03500 if (n > 1 && stmt->strict)
03501 ereport(ERROR,
03502 (errcode(ERRCODE_TOO_MANY_ROWS),
03503 errmsg("query returned more than one row")));
03504
03505 exec_move_row(estate, rec, row, tuptab->vals[0], tuptab->tupdesc);
03506 }
03507
03508 exec_eval_cleanup(estate);
03509 }
03510 else
03511 {
03512
03513
03514
03515
03516
03517 }
03518
03519
03520 SPI_freetuptable(SPI_tuptable);
03521 pfree(querystr);
03522
03523 return PLPGSQL_RC_OK;
03524 }
03525
03526
03527
03528
03529
03530
03531
03532
03533
03534 static int
03535 exec_stmt_dynfors(PLpgSQL_execstate *estate, PLpgSQL_stmt_dynfors *stmt)
03536 {
03537 Portal portal;
03538 int rc;
03539
03540 portal = exec_dynquery_with_params(estate, stmt->query, stmt->params,
03541 NULL, 0);
03542
03543
03544
03545
03546 rc = exec_for_query(estate, (PLpgSQL_stmt_forq *) stmt, portal, true);
03547
03548
03549
03550
03551 SPI_cursor_close(portal);
03552
03553 return rc;
03554 }
03555
03556
03557
03558
03559
03560
03561 static int
03562 exec_stmt_open(PLpgSQL_execstate *estate, PLpgSQL_stmt_open *stmt)
03563 {
03564 PLpgSQL_var *curvar;
03565 char *curname = NULL;
03566 PLpgSQL_expr *query;
03567 Portal portal;
03568 ParamListInfo paramLI;
03569
03570
03571
03572
03573
03574
03575 curvar = (PLpgSQL_var *) (estate->datums[stmt->curvar]);
03576 if (!curvar->isnull)
03577 {
03578 curname = TextDatumGetCString(curvar->value);
03579 if (SPI_cursor_find(curname) != NULL)
03580 ereport(ERROR,
03581 (errcode(ERRCODE_DUPLICATE_CURSOR),
03582 errmsg("cursor \"%s\" already in use", curname)));
03583 }
03584
03585
03586
03587
03588
03589 if (stmt->query != NULL)
03590 {
03591
03592
03593
03594
03595
03596
03597
03598 query = stmt->query;
03599 if (query->plan == NULL)
03600 exec_prepare_plan(estate, query, stmt->cursor_options);
03601 }
03602 else if (stmt->dynquery != NULL)
03603 {
03604
03605
03606
03607
03608 portal = exec_dynquery_with_params(estate,
03609 stmt->dynquery,
03610 stmt->params,
03611 curname,
03612 stmt->cursor_options);
03613
03614
03615
03616
03617 if (curname == NULL)
03618 assign_text_var(curvar, portal->name);
03619
03620 return PLPGSQL_RC_OK;
03621 }
03622 else
03623 {
03624
03625
03626
03627
03628
03629
03630
03631 if (stmt->argquery != NULL)
03632 {
03633
03634
03635
03636
03637
03638
03639 PLpgSQL_stmt_execsql set_args;
03640
03641 if (curvar->cursor_explicit_argrow < 0)
03642 ereport(ERROR,
03643 (errcode(ERRCODE_SYNTAX_ERROR),
03644 errmsg("arguments given for cursor without arguments")));
03645
03646 memset(&set_args, 0, sizeof(set_args));
03647 set_args.cmd_type = PLPGSQL_STMT_EXECSQL;
03648 set_args.lineno = stmt->lineno;
03649 set_args.sqlstmt = stmt->argquery;
03650 set_args.into = true;
03651
03652 set_args.row = (PLpgSQL_row *)
03653 (estate->datums[curvar->cursor_explicit_argrow]);
03654
03655 if (exec_stmt_execsql(estate, &set_args) != PLPGSQL_RC_OK)
03656 elog(ERROR, "open cursor failed during argument processing");
03657 }
03658 else
03659 {
03660 if (curvar->cursor_explicit_argrow >= 0)
03661 ereport(ERROR,
03662 (errcode(ERRCODE_SYNTAX_ERROR),
03663 errmsg("arguments required for cursor")));
03664 }
03665
03666 query = curvar->cursor_explicit_expr;
03667 if (query->plan == NULL)
03668 exec_prepare_plan(estate, query, curvar->cursor_options);
03669 }
03670
03671
03672
03673
03674 paramLI = setup_param_list(estate, query);
03675
03676
03677
03678
03679 portal = SPI_cursor_open_with_paramlist(curname, query->plan,
03680 paramLI,
03681 estate->readonly_func);
03682 if (portal == NULL)
03683 elog(ERROR, "could not open cursor: %s",
03684 SPI_result_code_string(SPI_result));
03685
03686
03687
03688
03689 if (curname == NULL)
03690 assign_text_var(curvar, portal->name);
03691
03692 if (curname)
03693 pfree(curname);
03694 if (paramLI)
03695 pfree(paramLI);
03696
03697 return PLPGSQL_RC_OK;
03698 }
03699
03700
03701
03702
03703
03704
03705
03706 static int
03707 exec_stmt_fetch(PLpgSQL_execstate *estate, PLpgSQL_stmt_fetch *stmt)
03708 {
03709 PLpgSQL_var *curvar = NULL;
03710 PLpgSQL_rec *rec = NULL;
03711 PLpgSQL_row *row = NULL;
03712 long how_many = stmt->how_many;
03713 SPITupleTable *tuptab;
03714 Portal portal;
03715 char *curname;
03716 uint32 n;
03717
03718
03719
03720
03721
03722 curvar = (PLpgSQL_var *) (estate->datums[stmt->curvar]);
03723 if (curvar->isnull)
03724 ereport(ERROR,
03725 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
03726 errmsg("cursor variable \"%s\" is null", curvar->refname)));
03727 curname = TextDatumGetCString(curvar->value);
03728
03729 portal = SPI_cursor_find(curname);
03730 if (portal == NULL)
03731 ereport(ERROR,
03732 (errcode(ERRCODE_UNDEFINED_CURSOR),
03733 errmsg("cursor \"%s\" does not exist", curname)));
03734 pfree(curname);
03735
03736
03737 if (stmt->expr)
03738 {
03739 bool isnull;
03740
03741
03742 how_many = exec_eval_integer(estate, stmt->expr, &isnull);
03743
03744 if (isnull)
03745 ereport(ERROR,
03746 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
03747 errmsg("relative or absolute cursor position is null")));
03748
03749 exec_eval_cleanup(estate);
03750 }
03751
03752 if (!stmt->is_move)
03753 {
03754
03755
03756
03757
03758 if (stmt->rec != NULL)
03759 rec = (PLpgSQL_rec *) (estate->datums[stmt->rec->dno]);
03760 else if (stmt->row != NULL)
03761 row = (PLpgSQL_row *) (estate->datums[stmt->row->dno]);
03762 else
03763 elog(ERROR, "unsupported target");
03764
03765
03766
03767
03768
03769 SPI_scroll_cursor_fetch(portal, stmt->direction, how_many);
03770 tuptab = SPI_tuptable;
03771 n = SPI_processed;
03772
03773
03774
03775
03776
03777 if (n == 0)
03778 exec_move_row(estate, rec, row, NULL, tuptab->tupdesc);
03779 else
03780 exec_move_row(estate, rec, row, tuptab->vals[0], tuptab->tupdesc);
03781
03782 exec_eval_cleanup(estate);
03783 SPI_freetuptable(tuptab);
03784 }
03785 else
03786 {
03787
03788 SPI_scroll_cursor_move(portal, stmt->direction, how_many);
03789 n = SPI_processed;
03790 }
03791
03792
03793 estate->eval_processed = n;
03794 exec_set_found(estate, n != 0);
03795
03796 return PLPGSQL_RC_OK;
03797 }
03798
03799
03800
03801
03802
03803 static int
03804 exec_stmt_close(PLpgSQL_execstate *estate, PLpgSQL_stmt_close *stmt)
03805 {
03806 PLpgSQL_var *curvar = NULL;
03807 Portal portal;
03808 char *curname;
03809
03810
03811
03812
03813
03814 curvar = (PLpgSQL_var *) (estate->datums[stmt->curvar]);
03815 if (curvar->isnull)
03816 ereport(ERROR,
03817 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
03818 errmsg("cursor variable \"%s\" is null", curvar->refname)));
03819 curname = TextDatumGetCString(curvar->value);
03820
03821 portal = SPI_cursor_find(curname);
03822 if (portal == NULL)
03823 ereport(ERROR,
03824 (errcode(ERRCODE_UNDEFINED_CURSOR),
03825 errmsg("cursor \"%s\" does not exist", curname)));
03826 pfree(curname);
03827
03828
03829
03830
03831
03832 SPI_cursor_close(portal);
03833
03834 return PLPGSQL_RC_OK;
03835 }
03836
03837
03838
03839
03840
03841
03842 static void
03843 exec_assign_expr(PLpgSQL_execstate *estate, PLpgSQL_datum *target,
03844 PLpgSQL_expr *expr)
03845 {
03846 Datum value;
03847 Oid valtype;
03848 bool isnull = false;
03849
03850 value = exec_eval_expr(estate, expr, &isnull, &valtype);
03851 exec_assign_value(estate, target, value, valtype, &isnull);
03852 exec_eval_cleanup(estate);
03853 }
03854
03855
03856
03857
03858
03859
03860
03861
03862 static void
03863 exec_assign_c_string(PLpgSQL_execstate *estate, PLpgSQL_datum *target,
03864 const char *str)
03865 {
03866 text *value;
03867 bool isnull = false;
03868
03869 if (str != NULL)
03870 value = cstring_to_text(str);
03871 else
03872 value = cstring_to_text("");
03873 exec_assign_value(estate, target, PointerGetDatum(value),
03874 TEXTOID, &isnull);
03875 pfree(value);
03876 }
03877
03878
03879
03880
03881
03882
03883
03884
03885
03886
03887 static void
03888 exec_assign_value(PLpgSQL_execstate *estate,
03889 PLpgSQL_datum *target,
03890 Datum value, Oid valtype, bool *isNull)
03891 {
03892 switch (target->dtype)
03893 {
03894 case PLPGSQL_DTYPE_VAR:
03895 {
03896
03897
03898
03899 PLpgSQL_var *var = (PLpgSQL_var *) target;
03900 Datum newvalue;
03901
03902 newvalue = exec_cast_value(estate,
03903 value,
03904 valtype,
03905 var->datatype->typoid,
03906 &(var->datatype->typinput),
03907 var->datatype->typioparam,
03908 var->datatype->atttypmod,
03909 *isNull);
03910
03911 if (*isNull && var->notnull)
03912 ereport(ERROR,
03913 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
03914 errmsg("null value cannot be assigned to variable \"%s\" declared NOT NULL",
03915 var->refname)));
03916
03917
03918
03919
03920
03921
03922 if (!var->datatype->typbyval && !*isNull)
03923 newvalue = datumCopy(newvalue,
03924 false,
03925 var->datatype->typlen);
03926
03927
03928
03929
03930
03931
03932
03933
03934 free_var(var);
03935
03936 var->value = newvalue;
03937 var->isnull = *isNull;
03938 if (!var->datatype->typbyval && !*isNull)
03939 var->freeval = true;
03940 break;
03941 }
03942
03943 case PLPGSQL_DTYPE_ROW:
03944 {
03945
03946
03947
03948 PLpgSQL_row *row = (PLpgSQL_row *) target;
03949
03950 if (*isNull)
03951 {
03952
03953 exec_move_row(estate, NULL, row, NULL, NULL);
03954 }
03955 else
03956 {
03957
03958 if (!type_is_rowtype(valtype))
03959 ereport(ERROR,
03960 (errcode(ERRCODE_DATATYPE_MISMATCH),
03961 errmsg("cannot assign non-composite value to a row variable")));
03962 exec_move_row_from_datum(estate, NULL, row, value);
03963 }
03964 break;
03965 }
03966
03967 case PLPGSQL_DTYPE_REC:
03968 {
03969
03970
03971
03972 PLpgSQL_rec *rec = (PLpgSQL_rec *) target;
03973
03974 if (*isNull)
03975 {
03976
03977 exec_move_row(estate, rec, NULL, NULL, NULL);
03978 }
03979 else
03980 {
03981
03982 if (!type_is_rowtype(valtype))
03983 ereport(ERROR,
03984 (errcode(ERRCODE_DATATYPE_MISMATCH),
03985 errmsg("cannot assign non-composite value to a record variable")));
03986 exec_move_row_from_datum(estate, rec, NULL, value);
03987 }
03988 break;
03989 }
03990
03991 case PLPGSQL_DTYPE_RECFIELD:
03992 {
03993
03994
03995
03996 PLpgSQL_recfield *recfield = (PLpgSQL_recfield *) target;
03997 PLpgSQL_rec *rec;
03998 int fno;
03999 HeapTuple newtup;
04000 int natts;
04001 Datum *values;
04002 bool *nulls;
04003 bool *replaces;
04004 bool attisnull;
04005 Oid atttype;
04006 int32 atttypmod;
04007
04008 rec = (PLpgSQL_rec *) (estate->datums[recfield->recparentno]);
04009
04010
04011
04012
04013
04014
04015 if (!HeapTupleIsValid(rec->tup))
04016 ereport(ERROR,
04017 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
04018 errmsg("record \"%s\" is not assigned yet",
04019 rec->refname),
04020 errdetail("The tuple structure of a not-yet-assigned record is indeterminate.")));
04021
04022
04023
04024
04025
04026
04027 fno = SPI_fnumber(rec->tupdesc, recfield->fieldname);
04028 if (fno <= 0)
04029 ereport(ERROR,
04030 (errcode(ERRCODE_UNDEFINED_COLUMN),
04031 errmsg("record \"%s\" has no field \"%s\"",
04032 rec->refname, recfield->fieldname)));
04033 fno--;
04034 natts = rec->tupdesc->natts;
04035
04036
04037
04038
04039
04040
04041 values = palloc(sizeof(Datum) * natts);
04042 nulls = palloc(sizeof(bool) * natts);
04043 replaces = palloc(sizeof(bool) * natts);
04044
04045 memset(replaces, false, sizeof(bool) * natts);
04046 replaces[fno] = true;
04047
04048
04049
04050
04051
04052 atttype = SPI_gettypeid(rec->tupdesc, fno + 1);
04053 atttypmod = rec->tupdesc->attrs[fno]->atttypmod;
04054 attisnull = *isNull;
04055 values[fno] = exec_simple_cast_value(estate,
04056 value,
04057 valtype,
04058 atttype,
04059 atttypmod,
04060 attisnull);
04061 nulls[fno] = attisnull;
04062
04063
04064
04065
04066
04067 newtup = heap_modify_tuple(rec->tup, rec->tupdesc,
04068 values, nulls, replaces);
04069
04070 if (rec->freetup)
04071 heap_freetuple(rec->tup);
04072
04073 rec->tup = newtup;
04074 rec->freetup = true;
04075
04076 pfree(values);
04077 pfree(nulls);
04078 pfree(replaces);
04079
04080 break;
04081 }
04082
04083 case PLPGSQL_DTYPE_ARRAYELEM:
04084 {
04085
04086
04087
04088 PLpgSQL_arrayelem *arrayelem;
04089 int nsubscripts;
04090 int i;
04091 PLpgSQL_expr *subscripts[MAXDIM];
04092 int subscriptvals[MAXDIM];
04093 Datum oldarraydatum,
04094 coerced_value;
04095 bool oldarrayisnull;
04096 Oid parenttypoid;
04097 int32 parenttypmod;
04098 ArrayType *oldarrayval;
04099 ArrayType *newarrayval;
04100 SPITupleTable *save_eval_tuptable;
04101 MemoryContext oldcontext;
04102
04103
04104
04105
04106
04107
04108
04109
04110 save_eval_tuptable = estate->eval_tuptable;
04111 estate->eval_tuptable = NULL;
04112
04113
04114
04115
04116
04117
04118
04119
04120
04121
04122
04123 nsubscripts = 0;
04124 do
04125 {
04126 arrayelem = (PLpgSQL_arrayelem *) target;
04127 if (nsubscripts >= MAXDIM)
04128 ereport(ERROR,
04129 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
04130 errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
04131 nsubscripts + 1, MAXDIM)));
04132 subscripts[nsubscripts++] = arrayelem->subscript;
04133 target = estate->datums[arrayelem->arrayparentno];
04134 } while (target->dtype == PLPGSQL_DTYPE_ARRAYELEM);
04135
04136
04137 exec_eval_datum(estate, target,
04138 &parenttypoid, &parenttypmod,
04139 &oldarraydatum, &oldarrayisnull);
04140
04141
04142 if (arrayelem->parenttypoid != parenttypoid ||
04143 arrayelem->parenttypmod != parenttypmod)
04144 {
04145 Oid arraytypoid;
04146 int32 arraytypmod = parenttypmod;
04147 int16 arraytyplen;
04148 Oid elemtypoid;
04149 int16 elemtyplen;
04150 bool elemtypbyval;
04151 char elemtypalign;
04152
04153
04154 arraytypoid = getBaseTypeAndTypmod(parenttypoid,
04155 &arraytypmod);
04156
04157
04158 elemtypoid = get_element_type(arraytypoid);
04159 if (!OidIsValid(elemtypoid))
04160 ereport(ERROR,
04161 (errcode(ERRCODE_DATATYPE_MISMATCH),
04162 errmsg("subscripted object is not an array")));
04163
04164
04165 arraytyplen = get_typlen(arraytypoid);
04166
04167 get_typlenbyvalalign(elemtypoid,
04168 &elemtyplen,
04169 &elemtypbyval,
04170 &elemtypalign);
04171
04172
04173 arrayelem->parenttypoid = parenttypoid;
04174 arrayelem->parenttypmod = parenttypmod;
04175 arrayelem->arraytypoid = arraytypoid;
04176 arrayelem->arraytypmod = arraytypmod;
04177 arrayelem->arraytyplen = arraytyplen;
04178 arrayelem->elemtypoid = elemtypoid;
04179 arrayelem->elemtyplen = elemtyplen;
04180 arrayelem->elemtypbyval = elemtypbyval;
04181 arrayelem->elemtypalign = elemtypalign;
04182 }
04183
04184
04185
04186
04187
04188 for (i = 0; i < nsubscripts; i++)
04189 {
04190 bool subisnull;
04191
04192 subscriptvals[i] =
04193 exec_eval_integer(estate,
04194 subscripts[nsubscripts - 1 - i],
04195 &subisnull);
04196 if (subisnull)
04197 ereport(ERROR,
04198 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
04199 errmsg("array subscript in assignment must not be null")));
04200
04201
04202
04203
04204
04205
04206
04207
04208 if (estate->eval_tuptable != NULL)
04209 SPI_freetuptable(estate->eval_tuptable);
04210 estate->eval_tuptable = NULL;
04211 }
04212
04213
04214 Assert(estate->eval_tuptable == NULL);
04215 estate->eval_tuptable = save_eval_tuptable;
04216
04217
04218 coerced_value = exec_simple_cast_value(estate,
04219 value,
04220 valtype,
04221 arrayelem->elemtypoid,
04222 arrayelem->arraytypmod,
04223 *isNull);
04224
04225
04226
04227
04228
04229
04230
04231
04232
04233
04234
04235 if (arrayelem->arraytyplen > 0 &&
04236 (oldarrayisnull || *isNull))
04237 return;
04238
04239
04240 oldcontext = MemoryContextSwitchTo(estate->eval_econtext->ecxt_per_tuple_memory);
04241
04242 if (oldarrayisnull)
04243 oldarrayval = construct_empty_array(arrayelem->elemtypoid);
04244 else
04245 oldarrayval = (ArrayType *) DatumGetPointer(oldarraydatum);
04246
04247
04248
04249
04250 newarrayval = array_set(oldarrayval,
04251 nsubscripts,
04252 subscriptvals,
04253 coerced_value,
04254 *isNull,
04255 arrayelem->arraytyplen,
04256 arrayelem->elemtyplen,
04257 arrayelem->elemtypbyval,
04258 arrayelem->elemtypalign);
04259
04260 MemoryContextSwitchTo(oldcontext);
04261
04262
04263
04264
04265
04266
04267
04268 *isNull = false;
04269 exec_assign_value(estate, target,
04270 PointerGetDatum(newarrayval),
04271 arrayelem->arraytypoid, isNull);
04272 break;
04273 }
04274
04275 default:
04276 elog(ERROR, "unrecognized dtype: %d", target->dtype);
04277 }
04278 }
04279
04280
04281
04282
04283
04284
04285
04286
04287
04288
04289
04290
04291
04292 static void
04293 exec_eval_datum(PLpgSQL_execstate *estate,
04294 PLpgSQL_datum *datum,
04295 Oid *typeid,
04296 int32 *typetypmod,
04297 Datum *value,
04298 bool *isnull)
04299 {
04300 MemoryContext oldcontext;
04301
04302 switch (datum->dtype)
04303 {
04304 case PLPGSQL_DTYPE_VAR:
04305 {
04306 PLpgSQL_var *var = (PLpgSQL_var *) datum;
04307
04308 *typeid = var->datatype->typoid;
04309 *typetypmod = var->datatype->atttypmod;
04310 *value = var->value;
04311 *isnull = var->isnull;
04312 break;
04313 }
04314
04315 case PLPGSQL_DTYPE_ROW:
04316 {
04317 PLpgSQL_row *row = (PLpgSQL_row *) datum;
04318 HeapTuple tup;
04319
04320 if (!row->rowtupdesc)
04321 elog(ERROR, "row variable has no tupdesc");
04322
04323 BlessTupleDesc(row->rowtupdesc);
04324 oldcontext = MemoryContextSwitchTo(estate->eval_econtext->ecxt_per_tuple_memory);
04325 tup = make_tuple_from_row(estate, row, row->rowtupdesc);
04326 if (tup == NULL)
04327 elog(ERROR, "row not compatible with its own tupdesc");
04328 MemoryContextSwitchTo(oldcontext);
04329 *typeid = row->rowtupdesc->tdtypeid;
04330 *typetypmod = row->rowtupdesc->tdtypmod;
04331 *value = HeapTupleGetDatum(tup);
04332 *isnull = false;
04333 break;
04334 }
04335
04336 case PLPGSQL_DTYPE_REC:
04337 {
04338 PLpgSQL_rec *rec = (PLpgSQL_rec *) datum;
04339 HeapTupleData worktup;
04340
04341 if (!HeapTupleIsValid(rec->tup))
04342 ereport(ERROR,
04343 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
04344 errmsg("record \"%s\" is not assigned yet",
04345 rec->refname),
04346 errdetail("The tuple structure of a not-yet-assigned record is indeterminate.")));
04347 Assert(rec->tupdesc != NULL);
04348
04349 BlessTupleDesc(rec->tupdesc);
04350
04351
04352
04353
04354
04355
04356 oldcontext = MemoryContextSwitchTo(estate->eval_econtext->ecxt_per_tuple_memory);
04357 heap_copytuple_with_tuple(rec->tup, &worktup);
04358 HeapTupleHeaderSetDatumLength(worktup.t_data, worktup.t_len);
04359 HeapTupleHeaderSetTypeId(worktup.t_data, rec->tupdesc->tdtypeid);
04360 HeapTupleHeaderSetTypMod(worktup.t_data, rec->tupdesc->tdtypmod);
04361 MemoryContextSwitchTo(oldcontext);
04362 *typeid = rec->tupdesc->tdtypeid;
04363 *typetypmod = rec->tupdesc->tdtypmod;
04364 *value = HeapTupleGetDatum(&worktup);
04365 *isnull = false;
04366 break;
04367 }
04368
04369 case PLPGSQL_DTYPE_RECFIELD:
04370 {
04371 PLpgSQL_recfield *recfield = (PLpgSQL_recfield *) datum;
04372 PLpgSQL_rec *rec;
04373 int fno;
04374
04375 rec = (PLpgSQL_rec *) (estate->datums[recfield->recparentno]);
04376 if (!HeapTupleIsValid(rec->tup))
04377 ereport(ERROR,
04378 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
04379 errmsg("record \"%s\" is not assigned yet",
04380 rec->refname),
04381 errdetail("The tuple structure of a not-yet-assigned record is indeterminate.")));
04382 fno = SPI_fnumber(rec->tupdesc, recfield->fieldname);
04383 if (fno == SPI_ERROR_NOATTRIBUTE)
04384 ereport(ERROR,
04385 (errcode(ERRCODE_UNDEFINED_COLUMN),
04386 errmsg("record \"%s\" has no field \"%s\"",
04387 rec->refname, recfield->fieldname)));
04388 *typeid = SPI_gettypeid(rec->tupdesc, fno);
04389
04390 if (fno > 0)
04391 *typetypmod = rec->tupdesc->attrs[fno - 1]->atttypmod;
04392 else
04393 *typetypmod = -1;
04394 *value = SPI_getbinval(rec->tup, rec->tupdesc, fno, isnull);
04395 break;
04396 }
04397
04398 default:
04399 elog(ERROR, "unrecognized dtype: %d", datum->dtype);
04400 }
04401 }
04402
04403
04404
04405
04406
04407
04408
04409
04410
04411 Oid
04412 exec_get_datum_type(PLpgSQL_execstate *estate,
04413 PLpgSQL_datum *datum)
04414 {
04415 Oid typeid;
04416
04417 switch (datum->dtype)
04418 {
04419 case PLPGSQL_DTYPE_VAR:
04420 {
04421 PLpgSQL_var *var = (PLpgSQL_var *) datum;
04422
04423 typeid = var->datatype->typoid;
04424 break;
04425 }
04426
04427 case PLPGSQL_DTYPE_ROW:
04428 {
04429 PLpgSQL_row *row = (PLpgSQL_row *) datum;
04430
04431 if (!row->rowtupdesc)
04432 elog(ERROR, "row variable has no tupdesc");
04433
04434 BlessTupleDesc(row->rowtupdesc);
04435 typeid = row->rowtupdesc->tdtypeid;
04436 break;
04437 }
04438
04439 case PLPGSQL_DTYPE_REC:
04440 {
04441 PLpgSQL_rec *rec = (PLpgSQL_rec *) datum;
04442
04443 if (rec->tupdesc == NULL)
04444 ereport(ERROR,
04445 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
04446 errmsg("record \"%s\" is not assigned yet",
04447 rec->refname),
04448 errdetail("The tuple structure of a not-yet-assigned record is indeterminate.")));
04449
04450 BlessTupleDesc(rec->tupdesc);
04451 typeid = rec->tupdesc->tdtypeid;
04452 break;
04453 }
04454
04455 case PLPGSQL_DTYPE_RECFIELD:
04456 {
04457 PLpgSQL_recfield *recfield = (PLpgSQL_recfield *) datum;
04458 PLpgSQL_rec *rec;
04459 int fno;
04460
04461 rec = (PLpgSQL_rec *) (estate->datums[recfield->recparentno]);
04462 if (rec->tupdesc == NULL)
04463 ereport(ERROR,
04464 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
04465 errmsg("record \"%s\" is not assigned yet",
04466 rec->refname),
04467 errdetail("The tuple structure of a not-yet-assigned record is indeterminate.")));
04468 fno = SPI_fnumber(rec->tupdesc, recfield->fieldname);
04469 if (fno == SPI_ERROR_NOATTRIBUTE)
04470 ereport(ERROR,
04471 (errcode(ERRCODE_UNDEFINED_COLUMN),
04472 errmsg("record \"%s\" has no field \"%s\"",
04473 rec->refname, recfield->fieldname)));
04474 typeid = SPI_gettypeid(rec->tupdesc, fno);
04475 break;
04476 }
04477
04478 default:
04479 elog(ERROR, "unrecognized dtype: %d", datum->dtype);
04480 typeid = InvalidOid;
04481 break;
04482 }
04483
04484 return typeid;
04485 }
04486
04487
04488
04489
04490
04491
04492
04493 void
04494 exec_get_datum_type_info(PLpgSQL_execstate *estate,
04495 PLpgSQL_datum *datum,
04496 Oid *typeid, int32 *typmod, Oid *collation)
04497 {
04498 switch (datum->dtype)
04499 {
04500 case PLPGSQL_DTYPE_VAR:
04501 {
04502 PLpgSQL_var *var = (PLpgSQL_var *) datum;
04503
04504 *typeid = var->datatype->typoid;
04505 *typmod = var->datatype->atttypmod;
04506 *collation = var->datatype->collation;
04507 break;
04508 }
04509
04510 case PLPGSQL_DTYPE_ROW:
04511 {
04512 PLpgSQL_row *row = (PLpgSQL_row *) datum;
04513
04514 if (!row->rowtupdesc)
04515 elog(ERROR, "row variable has no tupdesc");
04516
04517 BlessTupleDesc(row->rowtupdesc);
04518 *typeid = row->rowtupdesc->tdtypeid;
04519
04520 *typmod = -1;
04521
04522 *collation = InvalidOid;
04523 break;
04524 }
04525
04526 case PLPGSQL_DTYPE_REC:
04527 {
04528 PLpgSQL_rec *rec = (PLpgSQL_rec *) datum;
04529
04530 if (rec->tupdesc == NULL)
04531 ereport(ERROR,
04532 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
04533 errmsg("record \"%s\" is not assigned yet",
04534 rec->refname),
04535 errdetail("The tuple structure of a not-yet-assigned record is indeterminate.")));
04536
04537 BlessTupleDesc(rec->tupdesc);
04538 *typeid = rec->tupdesc->tdtypeid;
04539
04540 *typmod = -1;
04541
04542 *collation = InvalidOid;
04543 break;
04544 }
04545
04546 case PLPGSQL_DTYPE_RECFIELD:
04547 {
04548 PLpgSQL_recfield *recfield = (PLpgSQL_recfield *) datum;
04549 PLpgSQL_rec *rec;
04550 int fno;
04551
04552 rec = (PLpgSQL_rec *) (estate->datums[recfield->recparentno]);
04553 if (rec->tupdesc == NULL)
04554 ereport(ERROR,
04555 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
04556 errmsg("record \"%s\" is not assigned yet",
04557 rec->refname),
04558 errdetail("The tuple structure of a not-yet-assigned record is indeterminate.")));
04559 fno = SPI_fnumber(rec->tupdesc, recfield->fieldname);
04560 if (fno == SPI_ERROR_NOATTRIBUTE)
04561 ereport(ERROR,
04562 (errcode(ERRCODE_UNDEFINED_COLUMN),
04563 errmsg("record \"%s\" has no field \"%s\"",
04564 rec->refname, recfield->fieldname)));
04565 *typeid = SPI_gettypeid(rec->tupdesc, fno);
04566
04567 if (fno > 0)
04568 *typmod = rec->tupdesc->attrs[fno - 1]->atttypmod;
04569 else
04570 *typmod = -1;
04571
04572 if (fno > 0)
04573 *collation = rec->tupdesc->attrs[fno - 1]->attcollation;
04574 else
04575 *collation = InvalidOid;
04576 break;
04577 }
04578
04579 default:
04580 elog(ERROR, "unrecognized dtype: %d", datum->dtype);
04581 *typeid = InvalidOid;
04582 *typmod = -1;
04583 *collation = InvalidOid;
04584 break;
04585 }
04586 }
04587
04588
04589
04590
04591
04592
04593
04594
04595
04596
04597
04598 static int
04599 exec_eval_integer(PLpgSQL_execstate *estate,
04600 PLpgSQL_expr *expr,
04601 bool *isNull)
04602 {
04603 Datum exprdatum;
04604 Oid exprtypeid;
04605
04606 exprdatum = exec_eval_expr(estate, expr, isNull, &exprtypeid);
04607 exprdatum = exec_simple_cast_value(estate, exprdatum, exprtypeid,
04608 INT4OID, -1,
04609 *isNull);
04610 return DatumGetInt32(exprdatum);
04611 }
04612
04613
04614
04615
04616
04617
04618
04619
04620 static bool
04621 exec_eval_boolean(PLpgSQL_execstate *estate,
04622 PLpgSQL_expr *expr,
04623 bool *isNull)
04624 {
04625 Datum exprdatum;
04626 Oid exprtypeid;
04627
04628 exprdatum = exec_eval_expr(estate, expr, isNull, &exprtypeid);
04629 exprdatum = exec_simple_cast_value(estate, exprdatum, exprtypeid,
04630 BOOLOID, -1,
04631 *isNull);
04632 return DatumGetBool(exprdatum);
04633 }
04634
04635
04636
04637
04638
04639
04640
04641
04642 static Datum
04643 exec_eval_expr(PLpgSQL_execstate *estate,
04644 PLpgSQL_expr *expr,
04645 bool *isNull,
04646 Oid *rettype)
04647 {
04648 Datum result = 0;
04649 int rc;
04650
04651
04652
04653
04654 if (expr->plan == NULL)
04655 exec_prepare_plan(estate, expr, 0);
04656
04657
04658
04659
04660
04661 if (exec_eval_simple_expr(estate, expr, &result, isNull, rettype))
04662 return result;
04663
04664
04665
04666
04667 rc = exec_run_select(estate, expr, 2, NULL);
04668 if (rc != SPI_OK_SELECT)
04669 ereport(ERROR,
04670 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
04671 errmsg("query \"%s\" did not return data", expr->query)));
04672
04673
04674
04675
04676 if (estate->eval_tuptable->tupdesc->natts != 1)
04677 ereport(ERROR,
04678 (errcode(ERRCODE_SYNTAX_ERROR),
04679 errmsg_plural("query \"%s\" returned %d column",
04680 "query \"%s\" returned %d columns",
04681 estate->eval_tuptable->tupdesc->natts,
04682 expr->query,
04683 estate->eval_tuptable->tupdesc->natts)));
04684
04685
04686
04687
04688 *rettype = SPI_gettypeid(estate->eval_tuptable->tupdesc, 1);
04689
04690
04691
04692
04693 if (estate->eval_processed == 0)
04694 {
04695 *isNull = true;
04696 return (Datum) 0;
04697 }
04698
04699
04700
04701
04702 if (estate->eval_processed != 1)
04703 ereport(ERROR,
04704 (errcode(ERRCODE_CARDINALITY_VIOLATION),
04705 errmsg("query \"%s\" returned more than one row",
04706 expr->query)));
04707
04708
04709
04710
04711 return SPI_getbinval(estate->eval_tuptable->vals[0],
04712 estate->eval_tuptable->tupdesc, 1, isNull);
04713 }
04714
04715
04716
04717
04718
04719
04720 static int
04721 exec_run_select(PLpgSQL_execstate *estate,
04722 PLpgSQL_expr *expr, long maxtuples, Portal *portalP)
04723 {
04724 ParamListInfo paramLI;
04725 int rc;
04726
04727
04728
04729
04730 if (expr->plan == NULL)
04731 exec_prepare_plan(estate, expr, 0);
04732
04733
04734
04735
04736 paramLI = setup_param_list(estate, expr);
04737
04738
04739
04740
04741 if (portalP != NULL)
04742 {
04743 *portalP = SPI_cursor_open_with_paramlist(NULL, expr->plan,
04744 paramLI,
04745 estate->readonly_func);
04746 if (*portalP == NULL)
04747 elog(ERROR, "could not open implicit cursor for query \"%s\": %s",
04748 expr->query, SPI_result_code_string(SPI_result));
04749 if (paramLI)
04750 pfree(paramLI);
04751 return SPI_OK_CURSOR;
04752 }
04753
04754
04755
04756
04757 rc = SPI_execute_plan_with_paramlist(expr->plan, paramLI,
04758 estate->readonly_func, maxtuples);
04759 if (rc != SPI_OK_SELECT)
04760 ereport(ERROR,
04761 (errcode(ERRCODE_SYNTAX_ERROR),
04762 errmsg("query \"%s\" is not a SELECT", expr->query)));
04763
04764
04765 Assert(estate->eval_tuptable == NULL);
04766 estate->eval_tuptable = SPI_tuptable;
04767 estate->eval_processed = SPI_processed;
04768 estate->eval_lastoid = SPI_lastoid;
04769
04770 if (paramLI)
04771 pfree(paramLI);
04772
04773 return rc;
04774 }
04775
04776
04777
04778
04779
04780
04781
04782 static int
04783 exec_for_query(PLpgSQL_execstate *estate, PLpgSQL_stmt_forq *stmt,
04784 Portal portal, bool prefetch_ok)
04785 {
04786 PLpgSQL_rec *rec = NULL;
04787 PLpgSQL_row *row = NULL;
04788 SPITupleTable *tuptab;
04789 bool found = false;
04790 int rc = PLPGSQL_RC_OK;
04791 int n;
04792
04793
04794
04795
04796 if (stmt->rec != NULL)
04797 rec = (PLpgSQL_rec *) (estate->datums[stmt->rec->dno]);
04798 else if (stmt->row != NULL)
04799 row = (PLpgSQL_row *) (estate->datums[stmt->row->dno]);
04800 else
04801 elog(ERROR, "unsupported target");
04802
04803
04804
04805
04806
04807 PinPortal(portal);
04808
04809
04810
04811
04812
04813
04814 SPI_cursor_fetch(portal, true, prefetch_ok ? 10 : 1);
04815 tuptab = SPI_tuptable;
04816 n = SPI_processed;
04817
04818
04819
04820
04821
04822 if (n <= 0)
04823 {
04824 exec_move_row(estate, rec, row, NULL, tuptab->tupdesc);
04825 exec_eval_cleanup(estate);
04826 }
04827 else
04828 found = true;
04829
04830
04831
04832
04833 while (n > 0)
04834 {
04835 int i;
04836
04837 for (i = 0; i < n; i++)
04838 {
04839
04840
04841
04842 exec_move_row(estate, rec, row, tuptab->vals[i], tuptab->tupdesc);
04843 exec_eval_cleanup(estate);
04844
04845
04846
04847
04848 rc = exec_stmts(estate, stmt->body);
04849
04850 if (rc != PLPGSQL_RC_OK)
04851 {
04852 if (rc == PLPGSQL_RC_EXIT)
04853 {
04854 if (estate->exitlabel == NULL)
04855 {
04856
04857 rc = PLPGSQL_RC_OK;
04858 }
04859 else if (stmt->label != NULL &&
04860 strcmp(stmt->label, estate->exitlabel) == 0)
04861 {
04862
04863 estate->exitlabel = NULL;
04864 rc = PLPGSQL_RC_OK;
04865 }
04866
04867
04868
04869
04870
04871
04872 }
04873 else if (rc == PLPGSQL_RC_CONTINUE)
04874 {
04875 if (estate->exitlabel == NULL)
04876 {
04877
04878 rc = PLPGSQL_RC_OK;
04879 continue;
04880 }
04881 else if (stmt->label != NULL &&
04882 strcmp(stmt->label, estate->exitlabel) == 0)
04883 {
04884
04885 estate->exitlabel = NULL;
04886 rc = PLPGSQL_RC_OK;
04887 continue;
04888 }
04889
04890
04891
04892
04893
04894
04895
04896 }
04897
04898
04899
04900
04901
04902 goto loop_exit;
04903 }
04904 }
04905
04906 SPI_freetuptable(tuptab);
04907
04908
04909
04910
04911 SPI_cursor_fetch(portal, true, prefetch_ok ? 50 : 1);
04912 tuptab = SPI_tuptable;
04913 n = SPI_processed;
04914 }
04915
04916 loop_exit:
04917
04918
04919
04920
04921 SPI_freetuptable(tuptab);
04922
04923 UnpinPortal(portal);
04924
04925
04926
04927
04928
04929
04930
04931 exec_set_found(estate, found);
04932
04933 return rc;
04934 }
04935
04936
04937
04938
04939
04940
04941
04942
04943
04944
04945
04946
04947
04948
04949
04950
04951
04952
04953
04954
04955
04956
04957
04958
04959
04960
04961
04962
04963
04964
04965
04966
04967
04968 static bool
04969 exec_eval_simple_expr(PLpgSQL_execstate *estate,
04970 PLpgSQL_expr *expr,
04971 Datum *result,
04972 bool *isNull,
04973 Oid *rettype)
04974 {
04975 ExprContext *econtext = estate->eval_econtext;
04976 LocalTransactionId curlxid = MyProc->lxid;
04977 CachedPlan *cplan;
04978 ParamListInfo paramLI;
04979 PLpgSQL_expr *save_cur_expr;
04980 MemoryContext oldcontext;
04981
04982
04983
04984
04985 if (expr->expr_simple_expr == NULL)
04986 return false;
04987
04988
04989
04990
04991 if (expr->expr_simple_in_use && expr->expr_simple_lxid == curlxid)
04992 return false;
04993
04994
04995
04996
04997
04998 cplan = SPI_plan_get_cached_plan(expr->plan);
04999
05000
05001
05002
05003
05004
05005 Assert(cplan != NULL);
05006
05007 if (cplan->generation != expr->expr_simple_generation)
05008 {
05009
05010 exec_simple_recheck_plan(expr, cplan);
05011 if (expr->expr_simple_expr == NULL)
05012 {
05013
05014 ReleaseCachedPlan(cplan, true);
05015 return false;
05016 }
05017 }
05018
05019
05020
05021
05022 *rettype = expr->expr_simple_type;
05023
05024
05025
05026
05027
05028
05029 if (expr->expr_simple_lxid != curlxid)
05030 {
05031 oldcontext = MemoryContextSwitchTo(simple_eval_estate->es_query_cxt);
05032 expr->expr_simple_state = ExecInitExpr(expr->expr_simple_expr, NULL);
05033 expr->expr_simple_in_use = false;
05034 expr->expr_simple_lxid = curlxid;
05035 MemoryContextSwitchTo(oldcontext);
05036 }
05037
05038
05039
05040
05041
05042
05043
05044 SPI_push();
05045
05046 oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
05047 if (!estate->readonly_func)
05048 {
05049 CommandCounterIncrement();
05050 PushActiveSnapshot(GetTransactionSnapshot());
05051 }
05052
05053
05054
05055
05056
05057
05058
05059
05060
05061 save_cur_expr = estate->cur_expr;
05062
05063 paramLI = setup_param_list(estate, expr);
05064 econtext->ecxt_param_list_info = paramLI;
05065
05066
05067
05068
05069 expr->expr_simple_in_use = true;
05070
05071
05072
05073
05074 *result = ExecEvalExpr(expr->expr_simple_state,
05075 econtext,
05076 isNull,
05077 NULL);
05078
05079
05080 expr->expr_simple_in_use = false;
05081
05082 estate->cur_expr = save_cur_expr;
05083
05084 if (!estate->readonly_func)
05085 PopActiveSnapshot();
05086
05087 MemoryContextSwitchTo(oldcontext);
05088
05089 SPI_pop();
05090
05091
05092
05093
05094 ReleaseCachedPlan(cplan, true);
05095
05096
05097
05098
05099 return true;
05100 }
05101
05102
05103
05104
05105
05106
05107
05108
05109
05110
05111
05112
05113
05114
05115
05116
05117
05118
05119 static ParamListInfo
05120 setup_param_list(PLpgSQL_execstate *estate, PLpgSQL_expr *expr)
05121 {
05122 ParamListInfo paramLI;
05123
05124
05125
05126
05127
05128 Assert(expr->plan != NULL);
05129
05130
05131
05132
05133
05134
05135 if (!bms_is_empty(expr->paramnos))
05136 {
05137 Bitmapset *tmpset;
05138 int dno;
05139
05140 paramLI = (ParamListInfo)
05141 palloc0(offsetof(ParamListInfoData, params) +
05142 estate->ndatums * sizeof(ParamExternData));
05143 paramLI->paramFetch = plpgsql_param_fetch;
05144 paramLI->paramFetchArg = (void *) estate;
05145 paramLI->parserSetup = (ParserSetupHook) plpgsql_parser_setup;
05146 paramLI->parserSetupArg = (void *) expr;
05147 paramLI->numParams = estate->ndatums;
05148
05149
05150 tmpset = bms_copy(expr->paramnos);
05151 while ((dno = bms_first_member(tmpset)) >= 0)
05152 {
05153 PLpgSQL_datum *datum = estate->datums[dno];
05154
05155 if (datum->dtype == PLPGSQL_DTYPE_VAR)
05156 {
05157 PLpgSQL_var *var = (PLpgSQL_var *) datum;
05158 ParamExternData *prm = ¶mLI->params[dno];
05159
05160 prm->value = var->value;
05161 prm->isnull = var->isnull;
05162 prm->pflags = PARAM_FLAG_CONST;
05163 prm->ptype = var->datatype->typoid;
05164 }
05165 }
05166 bms_free(tmpset);
05167
05168
05169
05170
05171
05172
05173 estate->cur_expr = expr;
05174
05175
05176
05177
05178
05179
05180 expr->func = estate->func;
05181 }
05182 else
05183 {
05184
05185
05186
05187
05188
05189 paramLI = NULL;
05190 }
05191 return paramLI;
05192 }
05193
05194
05195
05196
05197 static void
05198 plpgsql_param_fetch(ParamListInfo params, int paramid)
05199 {
05200 int dno;
05201 PLpgSQL_execstate *estate;
05202 PLpgSQL_expr *expr;
05203 PLpgSQL_datum *datum;
05204 ParamExternData *prm;
05205 int32 prmtypmod;
05206
05207
05208 dno = paramid - 1;
05209 Assert(dno >= 0 && dno < params->numParams);
05210
05211
05212 estate = (PLpgSQL_execstate *) params->paramFetchArg;
05213 expr = estate->cur_expr;
05214 Assert(params->numParams == estate->ndatums);
05215
05216
05217
05218
05219
05220
05221 if (!bms_is_member(dno, expr->paramnos))
05222 return;
05223
05224
05225 datum = estate->datums[dno];
05226 prm = ¶ms->params[dno];
05227 exec_eval_datum(estate, datum,
05228 &prm->ptype, &prmtypmod,
05229 &prm->value, &prm->isnull);
05230 }
05231
05232
05233
05234
05235
05236
05237
05238
05239
05240 static void
05241 exec_move_row(PLpgSQL_execstate *estate,
05242 PLpgSQL_rec *rec,
05243 PLpgSQL_row *row,
05244 HeapTuple tup, TupleDesc tupdesc)
05245 {
05246
05247
05248
05249
05250 if (rec != NULL)
05251 {
05252
05253
05254
05255 if (HeapTupleIsValid(tup))
05256 tup = heap_copytuple(tup);
05257 else if (tupdesc)
05258 {
05259
05260 bool *nulls;
05261
05262 nulls = (bool *) palloc(tupdesc->natts * sizeof(bool));
05263 memset(nulls, true, tupdesc->natts * sizeof(bool));
05264
05265 tup = heap_form_tuple(tupdesc, NULL, nulls);
05266
05267 pfree(nulls);
05268 }
05269
05270 if (tupdesc)
05271 tupdesc = CreateTupleDescCopy(tupdesc);
05272
05273
05274 if (rec->freetup)
05275 {
05276 heap_freetuple(rec->tup);
05277 rec->freetup = false;
05278 }
05279 if (rec->freetupdesc)
05280 {
05281 FreeTupleDesc(rec->tupdesc);
05282 rec->freetupdesc = false;
05283 }
05284
05285
05286 if (HeapTupleIsValid(tup))
05287 {
05288 rec->tup = tup;
05289 rec->freetup = true;
05290 }
05291 else
05292 rec->tup = NULL;
05293
05294 if (tupdesc)
05295 {
05296 rec->tupdesc = tupdesc;
05297 rec->freetupdesc = true;
05298 }
05299 else
05300 rec->tupdesc = NULL;
05301
05302 return;
05303 }
05304
05305
05306
05307
05308
05309
05310
05311
05312
05313
05314
05315
05316
05317
05318
05319
05320
05321 if (row != NULL)
05322 {
05323 int td_natts = tupdesc ? tupdesc->natts : 0;
05324 int t_natts;
05325 int fnum;
05326 int anum;
05327
05328 if (HeapTupleIsValid(tup))
05329 t_natts = HeapTupleHeaderGetNatts(tup->t_data);
05330 else
05331 t_natts = 0;
05332
05333 anum = 0;
05334 for (fnum = 0; fnum < row->nfields; fnum++)
05335 {
05336 PLpgSQL_var *var;
05337 Datum value;
05338 bool isnull;
05339 Oid valtype;
05340
05341 if (row->varnos[fnum] < 0)
05342 continue;
05343
05344 var = (PLpgSQL_var *) (estate->datums[row->varnos[fnum]]);
05345
05346 while (anum < td_natts && tupdesc->attrs[anum]->attisdropped)
05347 anum++;
05348
05349 if (anum < td_natts)
05350 {
05351 if (anum < t_natts)
05352 value = SPI_getbinval(tup, tupdesc, anum + 1, &isnull);
05353 else
05354 {
05355 value = (Datum) 0;
05356 isnull = true;
05357 }
05358 valtype = SPI_gettypeid(tupdesc, anum + 1);
05359 anum++;
05360 }
05361 else
05362 {
05363 value = (Datum) 0;
05364 isnull = true;
05365
05366
05367
05368
05369
05370 valtype = InvalidOid;
05371 }
05372
05373 exec_assign_value(estate, (PLpgSQL_datum *) var,
05374 value, valtype, &isnull);
05375 }
05376
05377 return;
05378 }
05379
05380 elog(ERROR, "unsupported target");
05381 }
05382
05383
05384
05385
05386
05387
05388
05389 static HeapTuple
05390 make_tuple_from_row(PLpgSQL_execstate *estate,
05391 PLpgSQL_row *row,
05392 TupleDesc tupdesc)
05393 {
05394 int natts = tupdesc->natts;
05395 HeapTuple tuple;
05396 Datum *dvalues;
05397 bool *nulls;
05398 int i;
05399
05400 if (natts != row->nfields)
05401 return NULL;
05402
05403 dvalues = (Datum *) palloc0(natts * sizeof(Datum));
05404 nulls = (bool *) palloc(natts * sizeof(bool));
05405
05406 for (i = 0; i < natts; i++)
05407 {
05408 Oid fieldtypeid;
05409 int32 fieldtypmod;
05410
05411 if (tupdesc->attrs[i]->attisdropped)
05412 {
05413 nulls[i] = true;
05414 continue;
05415 }
05416 if (row->varnos[i] < 0)
05417 elog(ERROR, "dropped rowtype entry for non-dropped column");
05418
05419 exec_eval_datum(estate, estate->datums[row->varnos[i]],
05420 &fieldtypeid, &fieldtypmod,
05421 &dvalues[i], &nulls[i]);
05422 if (fieldtypeid != tupdesc->attrs[i]->atttypid)
05423 return NULL;
05424
05425 }
05426
05427 tuple = heap_form_tuple(tupdesc, dvalues, nulls);
05428
05429 pfree(dvalues);
05430 pfree(nulls);
05431
05432 return tuple;
05433 }
05434
05435
05436
05437
05438
05439
05440
05441
05442
05443 static HeapTuple
05444 get_tuple_from_datum(Datum value)
05445 {
05446 HeapTupleHeader td = DatumGetHeapTupleHeader(value);
05447 HeapTupleData tmptup;
05448
05449
05450 tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
05451 ItemPointerSetInvalid(&(tmptup.t_self));
05452 tmptup.t_tableOid = InvalidOid;
05453 tmptup.t_data = td;
05454
05455
05456 return heap_copytuple(&tmptup);
05457 }
05458
05459
05460
05461
05462
05463
05464
05465
05466
05467
05468 static TupleDesc
05469 get_tupdesc_from_datum(Datum value)
05470 {
05471 HeapTupleHeader td = DatumGetHeapTupleHeader(value);
05472 Oid tupType;
05473 int32 tupTypmod;
05474
05475
05476 tupType = HeapTupleHeaderGetTypeId(td);
05477 tupTypmod = HeapTupleHeaderGetTypMod(td);
05478 return lookup_rowtype_tupdesc(tupType, tupTypmod);
05479 }
05480
05481
05482
05483
05484
05485
05486
05487
05488 static void
05489 exec_move_row_from_datum(PLpgSQL_execstate *estate,
05490 PLpgSQL_rec *rec,
05491 PLpgSQL_row *row,
05492 Datum value)
05493 {
05494 HeapTupleHeader td = DatumGetHeapTupleHeader(value);
05495 Oid tupType;
05496 int32 tupTypmod;
05497 TupleDesc tupdesc;
05498 HeapTupleData tmptup;
05499
05500
05501 tupType = HeapTupleHeaderGetTypeId(td);
05502 tupTypmod = HeapTupleHeaderGetTypMod(td);
05503 tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
05504
05505
05506 tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
05507 ItemPointerSetInvalid(&(tmptup.t_self));
05508 tmptup.t_tableOid = InvalidOid;
05509 tmptup.t_data = td;
05510
05511
05512 exec_move_row(estate, rec, row, &tmptup, tupdesc);
05513
05514
05515 ReleaseTupleDesc(tupdesc);
05516 }
05517
05518
05519
05520
05521
05522
05523
05524
05525
05526
05527
05528
05529
05530
05531 static char *
05532 convert_value_to_string(PLpgSQL_execstate *estate, Datum value, Oid valtype)
05533 {
05534 char *result;
05535 MemoryContext oldcontext;
05536 Oid typoutput;
05537 bool typIsVarlena;
05538
05539 oldcontext = MemoryContextSwitchTo(estate->eval_econtext->ecxt_per_tuple_memory);
05540 getTypeOutputInfo(valtype, &typoutput, &typIsVarlena);
05541 result = OidOutputFunctionCall(typoutput, value);
05542 MemoryContextSwitchTo(oldcontext);
05543
05544 return result;
05545 }
05546
05547
05548
05549
05550
05551
05552
05553
05554
05555
05556 static Datum
05557 exec_cast_value(PLpgSQL_execstate *estate,
05558 Datum value, Oid valtype,
05559 Oid reqtype,
05560 FmgrInfo *reqinput,
05561 Oid reqtypioparam,
05562 int32 reqtypmod,
05563 bool isnull)
05564 {
05565
05566
05567
05568 if (valtype != reqtype || reqtypmod != -1)
05569 {
05570 MemoryContext oldcontext;
05571
05572 oldcontext = MemoryContextSwitchTo(estate->eval_econtext->ecxt_per_tuple_memory);
05573 if (!isnull)
05574 {
05575 char *extval;
05576
05577 extval = convert_value_to_string(estate, value, valtype);
05578 value = InputFunctionCall(reqinput, extval,
05579 reqtypioparam, reqtypmod);
05580 }
05581 else
05582 {
05583 value = InputFunctionCall(reqinput, NULL,
05584 reqtypioparam, reqtypmod);
05585 }
05586 MemoryContextSwitchTo(oldcontext);
05587 }
05588
05589 return value;
05590 }
05591
05592
05593
05594
05595
05596
05597
05598
05599
05600 static Datum
05601 exec_simple_cast_value(PLpgSQL_execstate *estate,
05602 Datum value, Oid valtype,
05603 Oid reqtype, int32 reqtypmod,
05604 bool isnull)
05605 {
05606 if (valtype != reqtype || reqtypmod != -1)
05607 {
05608 Oid typinput;
05609 Oid typioparam;
05610 FmgrInfo finfo_input;
05611
05612 getTypeInputInfo(reqtype, &typinput, &typioparam);
05613
05614 fmgr_info(typinput, &finfo_input);
05615
05616 value = exec_cast_value(estate,
05617 value,
05618 valtype,
05619 reqtype,
05620 &finfo_input,
05621 typioparam,
05622 reqtypmod,
05623 isnull);
05624 }
05625
05626 return value;
05627 }
05628
05629
05630
05631
05632
05633
05634
05635
05636
05637 static bool
05638 exec_simple_check_node(Node *node)
05639 {
05640 if (node == NULL)
05641 return TRUE;
05642
05643 switch (nodeTag(node))
05644 {
05645 case T_Const:
05646 return TRUE;
05647
05648 case T_Param:
05649 return TRUE;
05650
05651 case T_ArrayRef:
05652 {
05653 ArrayRef *expr = (ArrayRef *) node;
05654
05655 if (!exec_simple_check_node((Node *) expr->refupperindexpr))
05656 return FALSE;
05657 if (!exec_simple_check_node((Node *) expr->reflowerindexpr))
05658 return FALSE;
05659 if (!exec_simple_check_node((Node *) expr->refexpr))
05660 return FALSE;
05661 if (!exec_simple_check_node((Node *) expr->refassgnexpr))
05662 return FALSE;
05663
05664 return TRUE;
05665 }
05666
05667 case T_FuncExpr:
05668 {
05669 FuncExpr *expr = (FuncExpr *) node;
05670
05671 if (expr->funcretset)
05672 return FALSE;
05673 if (!exec_simple_check_node((Node *) expr->args))
05674 return FALSE;
05675
05676 return TRUE;
05677 }
05678
05679 case T_OpExpr:
05680 {
05681 OpExpr *expr = (OpExpr *) node;
05682
05683 if (expr->opretset)
05684 return FALSE;
05685 if (!exec_simple_check_node((Node *) expr->args))
05686 return FALSE;
05687
05688 return TRUE;
05689 }
05690
05691 case T_DistinctExpr:
05692 {
05693 DistinctExpr *expr = (DistinctExpr *) node;
05694
05695 if (expr->opretset)
05696 return FALSE;
05697 if (!exec_simple_check_node((Node *) expr->args))
05698 return FALSE;
05699
05700 return TRUE;
05701 }
05702
05703 case T_NullIfExpr:
05704 {
05705 NullIfExpr *expr = (NullIfExpr *) node;
05706
05707 if (expr->opretset)
05708 return FALSE;
05709 if (!exec_simple_check_node((Node *) expr->args))
05710 return FALSE;
05711
05712 return TRUE;
05713 }
05714
05715 case T_ScalarArrayOpExpr:
05716 {
05717 ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
05718
05719 if (!exec_simple_check_node((Node *) expr->args))
05720 return FALSE;
05721
05722 return TRUE;
05723 }
05724
05725 case T_BoolExpr:
05726 {
05727 BoolExpr *expr = (BoolExpr *) node;
05728
05729 if (!exec_simple_check_node((Node *) expr->args))
05730 return FALSE;
05731
05732 return TRUE;
05733 }
05734
05735 case T_FieldSelect:
05736 return exec_simple_check_node((Node *) ((FieldSelect *) node)->arg);
05737
05738 case T_FieldStore:
05739 {
05740 FieldStore *expr = (FieldStore *) node;
05741
05742 if (!exec_simple_check_node((Node *) expr->arg))
05743 return FALSE;
05744 if (!exec_simple_check_node((Node *) expr->newvals))
05745 return FALSE;
05746
05747 return TRUE;
05748 }
05749
05750 case T_RelabelType:
05751 return exec_simple_check_node((Node *) ((RelabelType *) node)->arg);
05752
05753 case T_CoerceViaIO:
05754 return exec_simple_check_node((Node *) ((CoerceViaIO *) node)->arg);
05755
05756 case T_ArrayCoerceExpr:
05757 return exec_simple_check_node((Node *) ((ArrayCoerceExpr *) node)->arg);
05758
05759 case T_ConvertRowtypeExpr:
05760 return exec_simple_check_node((Node *) ((ConvertRowtypeExpr *) node)->arg);
05761
05762 case T_CaseExpr:
05763 {
05764 CaseExpr *expr = (CaseExpr *) node;
05765
05766 if (!exec_simple_check_node((Node *) expr->arg))
05767 return FALSE;
05768 if (!exec_simple_check_node((Node *) expr->args))
05769 return FALSE;
05770 if (!exec_simple_check_node((Node *) expr->defresult))
05771 return FALSE;
05772
05773 return TRUE;
05774 }
05775
05776 case T_CaseWhen:
05777 {
05778 CaseWhen *when = (CaseWhen *) node;
05779
05780 if (!exec_simple_check_node((Node *) when->expr))
05781 return FALSE;
05782 if (!exec_simple_check_node((Node *) when->result))
05783 return FALSE;
05784
05785 return TRUE;
05786 }
05787
05788 case T_CaseTestExpr:
05789 return TRUE;
05790
05791 case T_ArrayExpr:
05792 {
05793 ArrayExpr *expr = (ArrayExpr *) node;
05794
05795 if (!exec_simple_check_node((Node *) expr->elements))
05796 return FALSE;
05797
05798 return TRUE;
05799 }
05800
05801 case T_RowExpr:
05802 {
05803 RowExpr *expr = (RowExpr *) node;
05804
05805 if (!exec_simple_check_node((Node *) expr->args))
05806 return FALSE;
05807
05808 return TRUE;
05809 }
05810
05811 case T_RowCompareExpr:
05812 {
05813 RowCompareExpr *expr = (RowCompareExpr *) node;
05814
05815 if (!exec_simple_check_node((Node *) expr->largs))
05816 return FALSE;
05817 if (!exec_simple_check_node((Node *) expr->rargs))
05818 return FALSE;
05819
05820 return TRUE;
05821 }
05822
05823 case T_CoalesceExpr:
05824 {
05825 CoalesceExpr *expr = (CoalesceExpr *) node;
05826
05827 if (!exec_simple_check_node((Node *) expr->args))
05828 return FALSE;
05829
05830 return TRUE;
05831 }
05832
05833 case T_MinMaxExpr:
05834 {
05835 MinMaxExpr *expr = (MinMaxExpr *) node;
05836
05837 if (!exec_simple_check_node((Node *) expr->args))
05838 return FALSE;
05839
05840 return TRUE;
05841 }
05842
05843 case T_XmlExpr:
05844 {
05845 XmlExpr *expr = (XmlExpr *) node;
05846
05847 if (!exec_simple_check_node((Node *) expr->named_args))
05848 return FALSE;
05849 if (!exec_simple_check_node((Node *) expr->args))
05850 return FALSE;
05851
05852 return TRUE;
05853 }
05854
05855 case T_NullTest:
05856 return exec_simple_check_node((Node *) ((NullTest *) node)->arg);
05857
05858 case T_BooleanTest:
05859 return exec_simple_check_node((Node *) ((BooleanTest *) node)->arg);
05860
05861 case T_CoerceToDomain:
05862 return exec_simple_check_node((Node *) ((CoerceToDomain *) node)->arg);
05863
05864 case T_CoerceToDomainValue:
05865 return TRUE;
05866
05867 case T_List:
05868 {
05869 List *expr = (List *) node;
05870 ListCell *l;
05871
05872 foreach(l, expr)
05873 {
05874 if (!exec_simple_check_node(lfirst(l)))
05875 return FALSE;
05876 }
05877
05878 return TRUE;
05879 }
05880
05881 default:
05882 return FALSE;
05883 }
05884 }
05885
05886
05887
05888
05889
05890
05891
05892
05893 static void
05894 exec_simple_check_plan(PLpgSQL_expr *expr)
05895 {
05896 List *plansources;
05897 CachedPlanSource *plansource;
05898 Query *query;
05899 CachedPlan *cplan;
05900
05901
05902
05903
05904
05905
05906 expr->expr_simple_expr = NULL;
05907 expr->expr_simple_generation = 0;
05908
05909
05910
05911
05912 plansources = SPI_plan_get_plan_sources(expr->plan);
05913 if (list_length(plansources) != 1)
05914 return;
05915 plansource = (CachedPlanSource *) linitial(plansources);
05916
05917
05918
05919
05920
05921
05922
05923
05924
05925
05926
05927
05928
05929 if (list_length(plansource->query_list) != 1)
05930 return;
05931 query = (Query *) linitial(plansource->query_list);
05932
05933
05934
05935
05936 if (!IsA(query, Query))
05937 return;
05938 if (query->commandType != CMD_SELECT)
05939 return;
05940 if (query->rtable != NIL)
05941 return;
05942
05943
05944
05945
05946 if (query->hasAggs ||
05947 query->hasWindowFuncs ||
05948 query->hasSubLinks ||
05949 query->hasForUpdate ||
05950 query->cteList ||
05951 query->jointree->quals ||
05952 query->groupClause ||
05953 query->havingQual ||
05954 query->windowClause ||
05955 query->distinctClause ||
05956 query->sortClause ||
05957 query->limitOffset ||
05958 query->limitCount ||
05959 query->setOperations)
05960 return;
05961
05962
05963
05964
05965 if (list_length(query->targetList) != 1)
05966 return;
05967
05968
05969
05970
05971
05972
05973 cplan = SPI_plan_get_cached_plan(expr->plan);
05974
05975
05976 Assert(cplan != NULL);
05977
05978
05979 exec_simple_recheck_plan(expr, cplan);
05980
05981
05982 ReleaseCachedPlan(cplan, true);
05983 }
05984
05985
05986
05987
05988 static void
05989 exec_simple_recheck_plan(PLpgSQL_expr *expr, CachedPlan *cplan)
05990 {
05991 PlannedStmt *stmt;
05992 Plan *plan;
05993 TargetEntry *tle;
05994
05995
05996
05997
05998
05999 expr->expr_simple_expr = NULL;
06000 expr->expr_simple_generation = cplan->generation;
06001
06002
06003
06004
06005 if (list_length(cplan->stmt_list) != 1)
06006 return;
06007 stmt = (PlannedStmt *) linitial(cplan->stmt_list);
06008
06009
06010
06011
06012 if (!IsA(stmt, PlannedStmt))
06013 return;
06014 if (stmt->commandType != CMD_SELECT)
06015 return;
06016 plan = stmt->planTree;
06017 if (!IsA(plan, Result))
06018 return;
06019
06020
06021
06022
06023 if (plan->lefttree != NULL ||
06024 plan->righttree != NULL ||
06025 plan->initPlan != NULL ||
06026 plan->qual != NULL ||
06027 ((Result *) plan)->resconstantqual != NULL)
06028 return;
06029
06030
06031
06032
06033 if (list_length(plan->targetlist) != 1)
06034 return;
06035
06036 tle = (TargetEntry *) linitial(plan->targetlist);
06037
06038
06039
06040
06041 if (!exec_simple_check_node((Node *) tle->expr))
06042 return;
06043
06044
06045
06046
06047
06048 expr->expr_simple_expr = tle->expr;
06049 expr->expr_simple_state = NULL;
06050 expr->expr_simple_in_use = false;
06051 expr->expr_simple_lxid = InvalidLocalTransactionId;
06052
06053 expr->expr_simple_type = exprType((Node *) tle->expr);
06054 }
06055
06056
06057
06058
06059
06060 static void
06061 exec_set_found(PLpgSQL_execstate *estate, bool state)
06062 {
06063 PLpgSQL_var *var;
06064
06065 var = (PLpgSQL_var *) (estate->datums[estate->found_varno]);
06066 var->value = BoolGetDatum(state);
06067 var->isnull = false;
06068 }
06069
06070
06071
06072
06073
06074
06075
06076
06077 static void
06078 plpgsql_create_econtext(PLpgSQL_execstate *estate)
06079 {
06080 SimpleEcontextStackEntry *entry;
06081
06082
06083
06084
06085
06086
06087 if (simple_eval_estate == NULL)
06088 {
06089 MemoryContext oldcontext;
06090
06091 oldcontext = MemoryContextSwitchTo(TopTransactionContext);
06092 simple_eval_estate = CreateExecutorState();
06093 MemoryContextSwitchTo(oldcontext);
06094 }
06095
06096
06097
06098
06099 estate->eval_econtext = CreateExprContext(simple_eval_estate);
06100
06101
06102
06103
06104
06105 entry = (SimpleEcontextStackEntry *)
06106 MemoryContextAlloc(TopTransactionContext,
06107 sizeof(SimpleEcontextStackEntry));
06108
06109 entry->stack_econtext = estate->eval_econtext;
06110 entry->xact_subxid = GetCurrentSubTransactionId();
06111
06112 entry->next = simple_econtext_stack;
06113 simple_econtext_stack = entry;
06114 }
06115
06116
06117
06118
06119
06120
06121
06122 static void
06123 plpgsql_destroy_econtext(PLpgSQL_execstate *estate)
06124 {
06125 SimpleEcontextStackEntry *next;
06126
06127 Assert(simple_econtext_stack != NULL);
06128 Assert(simple_econtext_stack->stack_econtext == estate->eval_econtext);
06129
06130 next = simple_econtext_stack->next;
06131 pfree(simple_econtext_stack);
06132 simple_econtext_stack = next;
06133
06134 FreeExprContext(estate->eval_econtext, true);
06135 estate->eval_econtext = NULL;
06136 }
06137
06138
06139
06140
06141
06142
06143
06144 void
06145 plpgsql_xact_cb(XactEvent event, void *arg)
06146 {
06147
06148
06149
06150
06151
06152
06153 if (event == XACT_EVENT_COMMIT || event == XACT_EVENT_PREPARE)
06154 {
06155
06156 Assert(simple_econtext_stack == NULL);
06157
06158 if (simple_eval_estate)
06159 FreeExecutorState(simple_eval_estate);
06160 simple_eval_estate = NULL;
06161 }
06162 else if (event == XACT_EVENT_ABORT)
06163 {
06164 simple_econtext_stack = NULL;
06165 simple_eval_estate = NULL;
06166 }
06167 }
06168
06169
06170
06171
06172
06173
06174
06175
06176
06177 void
06178 plpgsql_subxact_cb(SubXactEvent event, SubTransactionId mySubid,
06179 SubTransactionId parentSubid, void *arg)
06180 {
06181 if (event == SUBXACT_EVENT_COMMIT_SUB || event == SUBXACT_EVENT_ABORT_SUB)
06182 {
06183 while (simple_econtext_stack != NULL &&
06184 simple_econtext_stack->xact_subxid == mySubid)
06185 {
06186 SimpleEcontextStackEntry *next;
06187
06188 FreeExprContext(simple_econtext_stack->stack_econtext,
06189 (event == SUBXACT_EVENT_COMMIT_SUB));
06190 next = simple_econtext_stack->next;
06191 pfree(simple_econtext_stack);
06192 simple_econtext_stack = next;
06193 }
06194 }
06195 }
06196
06197
06198
06199
06200
06201
06202
06203 static void
06204 free_var(PLpgSQL_var *var)
06205 {
06206 if (var->freeval)
06207 {
06208 pfree(DatumGetPointer(var->value));
06209 var->freeval = false;
06210 }
06211 }
06212
06213
06214
06215
06216 static void
06217 assign_text_var(PLpgSQL_var *var, const char *str)
06218 {
06219 free_var(var);
06220 var->value = CStringGetTextDatum(str);
06221 var->isnull = false;
06222 var->freeval = true;
06223 }
06224
06225
06226
06227
06228 static PreparedParamsData *
06229 exec_eval_using_params(PLpgSQL_execstate *estate, List *params)
06230 {
06231 PreparedParamsData *ppd;
06232 int nargs;
06233 int i;
06234 ListCell *lc;
06235
06236 ppd = (PreparedParamsData *) palloc(sizeof(PreparedParamsData));
06237 nargs = list_length(params);
06238
06239 ppd->nargs = nargs;
06240 ppd->types = (Oid *) palloc(nargs * sizeof(Oid));
06241 ppd->values = (Datum *) palloc(nargs * sizeof(Datum));
06242 ppd->nulls = (char *) palloc(nargs * sizeof(char));
06243 ppd->freevals = (bool *) palloc(nargs * sizeof(bool));
06244
06245 i = 0;
06246 foreach(lc, params)
06247 {
06248 PLpgSQL_expr *param = (PLpgSQL_expr *) lfirst(lc);
06249 bool isnull;
06250
06251 ppd->values[i] = exec_eval_expr(estate, param,
06252 &isnull,
06253 &ppd->types[i]);
06254 ppd->nulls[i] = isnull ? 'n' : ' ';
06255 ppd->freevals[i] = false;
06256
06257 if (ppd->types[i] == UNKNOWNOID)
06258 {
06259
06260
06261
06262
06263
06264
06265
06266 ppd->types[i] = TEXTOID;
06267 if (!isnull)
06268 {
06269 ppd->values[i] = CStringGetTextDatum(DatumGetCString(ppd->values[i]));
06270 ppd->freevals[i] = true;
06271 }
06272 }
06273
06274 else if (!isnull)
06275 {
06276 int16 typLen;
06277 bool typByVal;
06278
06279 get_typlenbyval(ppd->types[i], &typLen, &typByVal);
06280 if (!typByVal)
06281 {
06282 ppd->values[i] = datumCopy(ppd->values[i], typByVal, typLen);
06283 ppd->freevals[i] = true;
06284 }
06285 }
06286
06287 exec_eval_cleanup(estate);
06288
06289 i++;
06290 }
06291
06292 return ppd;
06293 }
06294
06295
06296
06297
06298 static void
06299 free_params_data(PreparedParamsData *ppd)
06300 {
06301 int i;
06302
06303 for (i = 0; i < ppd->nargs; i++)
06304 {
06305 if (ppd->freevals[i])
06306 pfree(DatumGetPointer(ppd->values[i]));
06307 }
06308
06309 pfree(ppd->types);
06310 pfree(ppd->values);
06311 pfree(ppd->nulls);
06312 pfree(ppd->freevals);
06313
06314 pfree(ppd);
06315 }
06316
06317
06318
06319
06320 static Portal
06321 exec_dynquery_with_params(PLpgSQL_execstate *estate,
06322 PLpgSQL_expr *dynquery,
06323 List *params,
06324 const char *portalname,
06325 int cursorOptions)
06326 {
06327 Portal portal;
06328 Datum query;
06329 bool isnull;
06330 Oid restype;
06331 char *querystr;
06332
06333
06334
06335
06336
06337 query = exec_eval_expr(estate, dynquery, &isnull, &restype);
06338 if (isnull)
06339 ereport(ERROR,
06340 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
06341 errmsg("query string argument of EXECUTE is null")));
06342
06343
06344 querystr = convert_value_to_string(estate, query, restype);
06345
06346
06347 querystr = pstrdup(querystr);
06348
06349 exec_eval_cleanup(estate);
06350
06351
06352
06353
06354
06355
06356 if (params)
06357 {
06358 PreparedParamsData *ppd;
06359
06360 ppd = exec_eval_using_params(estate, params);
06361 portal = SPI_cursor_open_with_args(portalname,
06362 querystr,
06363 ppd->nargs, ppd->types,
06364 ppd->values, ppd->nulls,
06365 estate->readonly_func,
06366 cursorOptions);
06367 free_params_data(ppd);
06368 }
06369 else
06370 {
06371 portal = SPI_cursor_open_with_args(portalname,
06372 querystr,
06373 0, NULL,
06374 NULL, NULL,
06375 estate->readonly_func,
06376 cursorOptions);
06377 }
06378
06379 if (portal == NULL)
06380 elog(ERROR, "could not open implicit cursor for query \"%s\": %s",
06381 querystr, SPI_result_code_string(SPI_result));
06382 pfree(querystr);
06383
06384 return portal;
06385 }