---------- * exec_assign_value Put a value into a target datum * * Note: in some code paths, this will leak memory in the eval_mcontext; * we assume that will be cleaned up later by exec_eval_cleanup. We cannot * call exec_eval_cleanup here for fear of destroying the input Datum value. * ---------- */
| 5008 | * ---------- |
| 5009 | */ |
| 5010 | static void |
| 5011 | exec_assign_value(PLpgSQL_execstate *estate, |
| 5012 | PLpgSQL_datum *target, |
| 5013 | Datum value, bool isNull, |
| 5014 | Oid valtype, int32 valtypmod) |
| 5015 | { |
| 5016 | switch (target->dtype) |
| 5017 | { |
| 5018 | case PLPGSQL_DTYPE_VAR: |
| 5019 | case PLPGSQL_DTYPE_PROMISE: |
| 5020 | { |
| 5021 | /* |
| 5022 | * Target is a variable |
| 5023 | */ |
| 5024 | PLpgSQL_var *var = (PLpgSQL_var *) target; |
| 5025 | Datum newvalue; |
| 5026 | |
| 5027 | newvalue = exec_cast_value(estate, |
| 5028 | value, |
| 5029 | &isNull, |
| 5030 | valtype, |
| 5031 | valtypmod, |
| 5032 | var->datatype->typoid, |
| 5033 | var->datatype->atttypmod); |
| 5034 | |
| 5035 | if (isNull && var->notnull) |
| 5036 | ereport(ERROR, |
| 5037 | (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), |
| 5038 | errmsg("null value cannot be assigned to variable \"%s\" declared NOT NULL", |
| 5039 | var->refname))); |
| 5040 | |
| 5041 | /* |
| 5042 | * If type is by-reference, copy the new value (which is |
| 5043 | * probably in the eval_mcontext) into the procedure's main |
| 5044 | * memory context. But if it's a read/write reference to an |
| 5045 | * expanded object, no physical copy needs to happen; at most |
| 5046 | * we need to reparent the object's memory context. |
| 5047 | * |
| 5048 | * If it's an array, we force the value to be stored in R/W |
| 5049 | * expanded form. This wins if the function later does, say, |
| 5050 | * a lot of array subscripting operations on the variable, and |
| 5051 | * otherwise might lose. We might need to use a different |
| 5052 | * heuristic, but it's too soon to tell. Also, are there |
| 5053 | * cases where it'd be useful to force non-array values into |
| 5054 | * expanded form? |
| 5055 | */ |
| 5056 | if (!var->datatype->typbyval && !isNull) |
| 5057 | { |
| 5058 | if (var->datatype->typisarray && |
| 5059 | !VARATT_IS_EXTERNAL_EXPANDED_RW(DatumGetPointer(newvalue))) |
| 5060 | { |
| 5061 | /* array and not already R/W, so apply expand_array */ |
| 5062 | newvalue = expand_array(newvalue, |
| 5063 | estate->datum_context, |
| 5064 | NULL); |
| 5065 | } |
| 5066 | else |
| 5067 | { |
no test coverage detected