MCPcopy Create free account
hub / github.com/apache/cloudberry / assign_simple_var

Function assign_simple_var

src/pl/plpgsql/src/pl_exec.c:8397–8459  ·  view source on GitHub ↗

* assign_simple_var --- assign a new value to any VAR datum. * * This should be the only mechanism for assignment to simple variables, * lest we do the release of the old value incorrectly (not to mention * the detoasting business). */

Source from the content-addressed store, hash-verified

8395 * the detoasting business).
8396 */
8397static void
8398assign_simple_var(PLpgSQL_execstate *estate, PLpgSQL_var *var,
8399 Datum newvalue, bool isnull, bool freeable)
8400{
8401 Assert(var->dtype == PLPGSQL_DTYPE_VAR ||
8402 var->dtype == PLPGSQL_DTYPE_PROMISE);
8403
8404 /*
8405 * In non-atomic contexts, we do not want to store TOAST pointers in
8406 * variables, because such pointers might become stale after a commit.
8407 * Forcibly detoast in such cases. We don't want to detoast (flatten)
8408 * expanded objects, however; those should be OK across a transaction
8409 * boundary since they're just memory-resident objects. (Elsewhere in
8410 * this module, operations on expanded records likewise need to request
8411 * detoasting of record fields when !estate->atomic. Expanded arrays are
8412 * not a problem since all array entries are always detoasted.)
8413 */
8414 if (!estate->atomic && !isnull && var->datatype->typlen == -1 &&
8415 VARATT_IS_EXTERNAL_NON_EXPANDED(DatumGetPointer(newvalue)))
8416 {
8417 MemoryContext oldcxt;
8418 Datum detoasted;
8419
8420 /*
8421 * Do the detoasting in the eval_mcontext to avoid long-term leakage
8422 * of whatever memory toast fetching might leak. Then we have to copy
8423 * the detoasted datum to the function's main context, which is a
8424 * pain, but there's little choice.
8425 */
8426 oldcxt = MemoryContextSwitchTo(get_eval_mcontext(estate));
8427 detoasted = PointerGetDatum(detoast_external_attr((struct varlena *) DatumGetPointer(newvalue)));
8428 MemoryContextSwitchTo(oldcxt);
8429 /* Now's a good time to not leak the input value if it's freeable */
8430 if (freeable)
8431 pfree(DatumGetPointer(newvalue));
8432 /* Once we copy the value, it's definitely freeable */
8433 newvalue = datumCopy(detoasted, false, -1);
8434 freeable = true;
8435 /* Can't clean up eval_mcontext here, but it'll happen before long */
8436 }
8437
8438 /* Free the old value if needed */
8439 if (var->freeval)
8440 {
8441 if (DatumIsReadWriteExpandedObject(var->value,
8442 var->isnull,
8443 var->datatype->typlen))
8444 DeleteExpandedObject(var->value);
8445 else
8446 pfree(DatumGetPointer(var->value));
8447 }
8448 /* Assign new value to datum */
8449 var->value = newvalue;
8450 var->isnull = isnull;
8451 var->freeval = freeable;
8452
8453 /*
8454 * If it's a promise variable, then either we just assigned the promised

Callers 9

plpgsql_exec_functionFunction · 0.85
plpgsql_fulfill_promiseFunction · 0.85
exec_stmt_blockFunction · 0.85
exec_stmt_caseFunction · 0.85
exec_stmt_foriFunction · 0.85
exec_stmt_forcFunction · 0.85
exec_assign_valueFunction · 0.85
exec_set_foundFunction · 0.85
assign_text_varFunction · 0.85

Calls 5

MemoryContextSwitchToFunction · 0.85
detoast_external_attrFunction · 0.85
datumCopyFunction · 0.85
DeleteExpandedObjectFunction · 0.85
pfreeFunction · 0.50

Tested by

no test coverage detected