diff options
author | Tom Lane | 2014-11-25 17:21:22 +0000 |
---|---|---|
committer | Tom Lane | 2014-11-25 17:21:28 +0000 |
commit | bac27394a1c69c20ec904729c593e59485c75c69 (patch) | |
tree | 7bdf15b078bfcef745a5bb2c7c479d6f8bd45f15 /src/backend/executor/nodeSubplan.c | |
parent | 25976710dfd8611d3fc79c0c1e20179ff7a940ec (diff) |
Support arrays as input to array_agg() and ARRAY(SELECT ...).
These cases formerly failed with errors about "could not find array type
for data type". Now they yield arrays of the same element type and one
higher dimension.
The implementation involves creating functions with API similar to the
existing accumArrayResult() family. I (tgl) also extended the base family
by adding an initArrayResult() function, which allows callers to avoid
special-casing the zero-inputs case if they just want an empty array as
result. (Not all do, so the previous calling convention remains valid.)
This allowed simplifying some existing code in xml.c and plperl.c.
Ali Akbar, reviewed by Pavel Stehule, significantly modified by me
Diffstat (limited to 'src/backend/executor/nodeSubplan.c')
-rw-r--r-- | src/backend/executor/nodeSubplan.c | 38 |
1 files changed, 20 insertions, 18 deletions
diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c index 401bad45b59..d9faf2000cd 100644 --- a/src/backend/executor/nodeSubplan.c +++ b/src/backend/executor/nodeSubplan.c @@ -231,7 +231,7 @@ ExecScanSubPlan(SubPlanState *node, bool found = false; /* TRUE if got at least one subplan tuple */ ListCell *pvar; ListCell *l; - ArrayBuildState *astate = NULL; + ArrayBuildStateAny *astate = NULL; /* * MULTIEXPR subplans, when "executed", just return NULL; but first we @@ -259,6 +259,11 @@ ExecScanSubPlan(SubPlanState *node, return (Datum) 0; } + /* Initialize ArrayBuildStateAny in caller's context, if needed */ + if (subLinkType == ARRAY_SUBLINK) + astate = initArrayResultAny(subplan->firstColType, + CurrentMemoryContext); + /* * We are probably in a short-lived expression-evaluation context. Switch * to the per-query context for manipulating the child plan's chgParam, @@ -366,8 +371,8 @@ ExecScanSubPlan(SubPlanState *node, /* stash away current value */ Assert(subplan->firstColType == tdesc->attrs[0]->atttypid); dvalue = slot_getattr(slot, 1, &disnull); - astate = accumArrayResult(astate, dvalue, disnull, - subplan->firstColType, oldcontext); + astate = accumArrayResultAny(astate, dvalue, disnull, + subplan->firstColType, oldcontext); /* keep scanning subplan to collect all values */ continue; } @@ -437,10 +442,7 @@ ExecScanSubPlan(SubPlanState *node, if (subLinkType == ARRAY_SUBLINK) { /* We return the result in the caller's context */ - if (astate != NULL) - result = makeArrayResult(astate, oldcontext); - else - result = PointerGetDatum(construct_empty_array(subplan->firstColType)); + result = makeArrayResultAny(astate, oldcontext, true); } else if (!found) { @@ -951,7 +953,7 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext) ListCell *pvar; ListCell *l; bool found = false; - ArrayBuildState *astate = NULL; + ArrayBuildStateAny *astate = NULL; if (subLinkType == ANY_SUBLINK || subLinkType == ALL_SUBLINK) @@ -959,6 +961,11 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext) if (subLinkType == CTE_SUBLINK) elog(ERROR, "CTE subplans should not be executed via ExecSetParamPlan"); + /* Initialize ArrayBuildStateAny in caller's context, if needed */ + if (subLinkType == ARRAY_SUBLINK) + astate = initArrayResultAny(subplan->firstColType, + CurrentMemoryContext); + /* * Must switch to per-query memory context. */ @@ -1018,8 +1025,8 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext) /* stash away current value */ Assert(subplan->firstColType == tdesc->attrs[0]->atttypid); dvalue = slot_getattr(slot, 1, &disnull); - astate = accumArrayResult(astate, dvalue, disnull, - subplan->firstColType, oldcontext); + astate = accumArrayResultAny(astate, dvalue, disnull, + subplan->firstColType, oldcontext); /* keep scanning subplan to collect all values */ continue; } @@ -1072,14 +1079,9 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext) */ if (node->curArray != PointerGetDatum(NULL)) pfree(DatumGetPointer(node->curArray)); - if (astate != NULL) - node->curArray = makeArrayResult(astate, - econtext->ecxt_per_query_memory); - else - { - MemoryContextSwitchTo(econtext->ecxt_per_query_memory); - node->curArray = PointerGetDatum(construct_empty_array(subplan->firstColType)); - } + node->curArray = makeArrayResultAny(astate, + econtext->ecxt_per_query_memory, + true); prm->execPlan = NULL; prm->value = node->curArray; prm->isnull = false; |