diff options
| author | Tom Lane | 2016-11-08 20:36:36 +0000 |
|---|---|---|
| committer | Tom Lane | 2016-11-08 20:36:44 +0000 |
| commit | 9257f0787257022e31c61cd77449127adfccf37f (patch) | |
| tree | 4c75b862abe7b4d0610e280c97edc66390e283d0 /src/pl | |
| parent | dce429b117be027f059bb9df5c76eb5eadcc456d (diff) | |
Replace uses of SPI_modifytuple that intend to allocate in current context.
Invent a new function heap_modify_tuple_by_cols() that is functionally
equivalent to SPI_modifytuple except that it always allocates its result
by simple palloc. I chose however to make the API details a bit more
like heap_modify_tuple: pass a tupdesc rather than a Relation, and use
bool convention for the isnull array.
Use this function in place of SPI_modifytuple at all call sites where the
intended behavior is to allocate in current context. (There actually are
only two call sites left that depend on the old behavior, which makes me
wonder if we should just drop this function rather than keep it.)
This new function is easier to use than heap_modify_tuple() for purposes
of replacing a single column (or, really, any fixed number of columns).
There are a number of places where it would simplify the code to change
over, but I resisted that temptation for the moment ... everywhere except
in plpgsql's exec_assign_value(); changing that might offer some small
performance benefit, so I did it.
This is on the way to removing SPI_push/SPI_pop, but it seems like
good code cleanup in its own right.
Discussion: <9633.1478552022@sss.pgh.pa.us>
Diffstat (limited to 'src/pl')
| -rw-r--r-- | src/pl/plpgsql/src/pl_exec.c | 57 |
1 files changed, 19 insertions, 38 deletions
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index 042b31fd77..91e1f8dd3f 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -4562,10 +4562,9 @@ exec_assign_value(PLpgSQL_execstate *estate, PLpgSQL_rec *rec; int fno; HeapTuple newtup; - int natts; - Datum *values; - bool *nulls; - bool *replaces; + int colnums[1]; + Datum values[1]; + bool nulls[1]; Oid atttype; int32 atttypmod; @@ -4584,9 +4583,8 @@ exec_assign_value(PLpgSQL_execstate *estate, errdetail("The tuple structure of a not-yet-assigned record is indeterminate."))); /* - * Get the number of the records field to change and the - * number of attributes in the tuple. Note: disallow system - * column names because the code below won't cope. + * Get the number of the record field to change. Disallow + * system columns because the code below won't cope. */ fno = SPI_fnumber(rec->tupdesc, recfield->fieldname); if (fno <= 0) @@ -4594,42 +4592,25 @@ exec_assign_value(PLpgSQL_execstate *estate, (errcode(ERRCODE_UNDEFINED_COLUMN), errmsg("record \"%s\" has no field \"%s\"", rec->refname, recfield->fieldname))); - fno--; - natts = rec->tupdesc->natts; - - /* - * Set up values/control arrays for heap_modify_tuple. For all - * the attributes except the one we want to replace, use the - * value that's in the old tuple. - */ - values = eval_mcontext_alloc(estate, sizeof(Datum) * natts); - nulls = eval_mcontext_alloc(estate, sizeof(bool) * natts); - replaces = eval_mcontext_alloc(estate, sizeof(bool) * natts); - - memset(replaces, false, sizeof(bool) * natts); - replaces[fno] = true; + colnums[0] = fno; /* * Now insert the new value, being careful to cast it to the * right type. */ - atttype = rec->tupdesc->attrs[fno]->atttypid; - atttypmod = rec->tupdesc->attrs[fno]->atttypmod; - values[fno] = exec_cast_value(estate, - value, - &isNull, - valtype, - valtypmod, - atttype, - atttypmod); - nulls[fno] = isNull; - - /* - * Now call heap_modify_tuple() to create a new tuple that - * replaces the old one in the record. - */ - newtup = heap_modify_tuple(rec->tup, rec->tupdesc, - values, nulls, replaces); + atttype = rec->tupdesc->attrs[fno - 1]->atttypid; + atttypmod = rec->tupdesc->attrs[fno - 1]->atttypmod; + values[0] = exec_cast_value(estate, + value, + &isNull, + valtype, + valtypmod, + atttype, + atttypmod); + nulls[0] = isNull; + + newtup = heap_modify_tuple_by_cols(rec->tup, rec->tupdesc, + 1, colnums, values, nulls); if (rec->freetup) heap_freetuple(rec->tup); |
