提交 1be38f8f 编写于 作者: H Heikki Linnakangas

Use "outer slot" to hold result of Agg's child node.

Long time ago, a hack was put in place in GPDB to use the "scan" slot,
instead of the "outer" slot which is used in the upstream, to hold the
result of an Agg or Window plan node's child. It's not clear to me why
that was done. There was even a comment in fix_upper_expr() saying we
wouldn't need it if we just fixed the executor to not contain that hack,
and there was also a TODO comment in CMappingColIdVarPlStmt.cpp about
that.

Everything seems to work without those hacks, so revert this thing back
to the way it works in the upstream. This is simpler in its own right,
and also reduces our diff vs. upstream, which will make merging easier
in the future.
上级 0d8f5e7b
......@@ -817,7 +817,7 @@ agg_hash_initial_pass(AggState *aggstate)
}
/* set up for advance_aggregates call */
tmpcontext->ecxt_scantuple = outerslot;
tmpcontext->ecxt_outertuple = outerslot;
/* Find or (if there's room) build a hash table entry for the
* input tuple's group. */
......@@ -1583,7 +1583,7 @@ agg_hash_reload(AggState *aggstate)
has_tuples = true;
/* set up for advance_aggregates call */
tmpcontext->ecxt_scantuple = aggstate->hashslot;
tmpcontext->ecxt_outertuple = aggstate->hashslot;
entry = lookup_agg_hash_entry(aggstate, input, INPUT_RECORD_GROUP_AND_AGGS, input_size,
hashkey, reloaded_hash_bit, &isNew);
......
......@@ -502,7 +502,7 @@ invoke_agg_trans_func(FmgrInfo *transfn, int numargs, Datum transValue,
/*
* Advance all the aggregates for one input tuple. The input tuple
* has been stored in tmpcontext->ecxt_scantuple, so that it is accessible
* has been stored in tmpcontext->ecxt_outertuple, so that it is accessible
* to ExecEvalExpr. pergroup is the array of per-group structs to use
* (this might be in a hashtable entry).
*
......@@ -908,8 +908,8 @@ find_unaggregated_cols_walker(Node *node, Bitmapset **colnos)
{
Var *var = (Var *) node;
/* setrefs.c should have set the varno to 0 */
Assert(var->varno == 0);
/* setrefs.c should have set the varno to OUTER */
Assert(var->varno == OUTER);
Assert(var->varlevelsup == 0);
*colnos = bms_add_member(*colnos, var->varattno);
return false;
......@@ -1311,7 +1311,7 @@ agg_retrieve_direct(AggState *aggstate)
maybe_passthru = true;
/* set up for first advance aggregates call */
tmpcontext->ecxt_scantuple = firstSlot;
tmpcontext->ecxt_outertuple = firstSlot;
/*
* Process each outer-plan tuple, and then fetch the next one,
......@@ -1348,7 +1348,7 @@ agg_retrieve_direct(AggState *aggstate)
Gpmon_M_Incr(GpmonPktFromAggState(aggstate), GPMON_QEXEC_M_ROWSIN);
CheckSendPlanStateGpmonPkt(&aggstate->ss.ps);
/* set up for next advance aggregates call */
tmpcontext->ecxt_scantuple = outerslot;
tmpcontext->ecxt_outertuple = outerslot;
/*
* If we are grouping, check whether we've crossed a group
......@@ -1397,7 +1397,7 @@ agg_retrieve_direct(AggState *aggstate)
outer_grouping == input_grouping)
{
has_partial_agg = true;
tmpcontext->ecxt_scantuple = outerslot;
tmpcontext->ecxt_outertuple = outerslot;
advance_aggregates(aggstate, pergroup, &(aggstate->mem_manager));
}
......@@ -1436,7 +1436,7 @@ agg_retrieve_direct(AggState *aggstate)
/* finalize the pass-through tuple */
ResetExprContext(tmpcontext);
tmpcontext->ecxt_scantuple = outerslot;
tmpcontext->ecxt_outertuple = outerslot;
advance_aggregates(aggstate, perpassthru, &(aggstate->mem_manager));
}
......@@ -1477,9 +1477,9 @@ agg_retrieve_direct(AggState *aggstate)
* references to non-aggregated input columns, so no problem.)
*/
if (passthru_ready)
econtext->ecxt_scantuple = outerslot;
econtext->ecxt_outertuple = outerslot;
else
econtext->ecxt_scantuple = firstSlot;
econtext->ecxt_outertuple = firstSlot;
/*
* We obtain GROUP_ID from the input tuples when this is
......@@ -1489,7 +1489,7 @@ agg_retrieve_direct(AggState *aggstate)
(passthru_ready && is_middle_rollup_agg)) &&
input_has_grouping)
econtext->group_id =
get_grouping_groupid(econtext->ecxt_scantuple,
get_grouping_groupid(econtext->ecxt_outertuple,
node->grpColIdx[node->numCols-node->numNullCols-1]);
else
econtext->group_id = node->rollupGSTimes;
......@@ -1499,7 +1499,7 @@ agg_retrieve_direct(AggState *aggstate)
(passthru_ready && is_middle_rollup_agg)) &&
input_has_grouping)
econtext->grouping =
get_grouping_groupid(econtext->ecxt_scantuple,
get_grouping_groupid(econtext->ecxt_outertuple,
node->grpColIdx[node->numCols-node->numNullCols-2]);
else
econtext->grouping = node->grouping;
......@@ -1542,7 +1542,7 @@ agg_retrieve_direct(AggState *aggstate)
*/
if (node->numNullCols > 0)
{
ExecModifyMemTuple(econtext->ecxt_scantuple,
ExecModifyMemTuple(econtext->ecxt_outertuple,
aggstate->replValues,
aggstate->replIsnull,
aggstate->doReplace
......@@ -1650,15 +1650,15 @@ agg_retrieve_hash_table(AggState *aggstate)
* Use the representative input tuple for any references to
* non-aggregated input columns in the qual and tlist.
*/
econtext->ecxt_scantuple = firstSlot;
econtext->ecxt_outertuple = firstSlot;
if (is_final_rollup_agg && input_has_grouping)
{
econtext->group_id =
get_grouping_groupid(econtext->ecxt_scantuple,
get_grouping_groupid(econtext->ecxt_outertuple,
node->grpColIdx[node->numCols-node->numNullCols-1]);
econtext->grouping =
get_grouping_groupid(econtext->ecxt_scantuple,
get_grouping_groupid(econtext->ecxt_outertuple,
node->grpColIdx[node->numCols-node->numNullCols-2]);
}
else
......
......@@ -1179,7 +1179,7 @@ serializeEntry(WindowStatePerLevel level_state,
{
int key_no;
char *written_pos;
TupleTableSlot *slot = econtext->ecxt_scantuple;
TupleTableSlot *slot = econtext->ecxt_outertuple;
*p_len = 0;
Assert(*p_serial_entry != NULL);
......@@ -1315,7 +1315,7 @@ adjustEdgesAfterAppend(WindowStatePerLevel level_state,
{
WindowFrameBuffer buffer = level_state->frame_buffer;
ExprContext *econtext = wstate->ps.ps_ExprContext;
TupleTableSlot *inserting_tuple = econtext->ecxt_scantuple;
TupleTableSlot *inserting_tuple = econtext->ecxt_outertuple;
/*
* If the current_row_reader for the buffer is not set, set it to point to
......@@ -1350,7 +1350,7 @@ adjustEdgesAfterAppend(WindowStatePerLevel level_state,
(EDGE_IS_BOUND_FOLLOWING(level_state->frame->trail) ||
EDGE_IS_DELAYED(level_state->frame->trail)))
{
econtext->ecxt_scantuple = wstate->curslot;
econtext->ecxt_outertuple = wstate->curslot;
forwardEdgeForRange(level_state, wstate,
level_state->frame->trail,
level_state->trail_expr,
......@@ -1358,7 +1358,7 @@ adjustEdgesAfterAppend(WindowStatePerLevel level_state,
level_state->trail_reader,
false);
econtext->ecxt_scantuple = inserting_tuple;
econtext->ecxt_outertuple = inserting_tuple;
}
}
......@@ -1425,14 +1425,14 @@ adjustEdgesAfterAppend(WindowStatePerLevel level_state,
}
else if (EDGE_IS_BOUND(level_state->frame->lead))
{
econtext->ecxt_scantuple = wstate->curslot;
econtext->ecxt_outertuple = wstate->curslot;
forwardEdgeForRange(level_state, wstate,
level_state->frame->lead,
level_state->lead_expr,
level_state->lead_range_expr,
level_state->lead_reader,
true);
econtext->ecxt_scantuple = inserting_tuple;
econtext->ecxt_outertuple = inserting_tuple;
}
else
{
......@@ -2086,18 +2086,18 @@ computeTransValuesThroughScan(WindowStatePerLevel level_state,
}
else
{
TupleTableSlot *slot = econtext->ecxt_scantuple;
TupleTableSlot *slot = econtext->ecxt_outertuple;
bool found;
found = ntuplestore_acc_current_tupleslot(wstate->input_buffer->writer,
wstate->spare);
Assert(found);
econtext->ecxt_scantuple = wstate->spare;
econtext->ecxt_outertuple = wstate->spare;
add_tuple_to_trans(funcstate, wstate, econtext, false);
/* Reset back to its orginial value */
econtext->ecxt_scantuple = slot;
econtext->ecxt_outertuple = slot;
}
}
}
......@@ -2184,15 +2184,15 @@ computeFrameValue(WindowStatePerLevel level_state,
}
else
{
TupleTableSlot *slot = econtext->ecxt_scantuple;
TupleTableSlot *slot = econtext->ecxt_outertuple;
ntuplestore_acc_current_tupleslot(wstate->input_buffer->writer,
wstate->spare);
econtext->ecxt_scantuple = wstate->spare;
econtext->ecxt_outertuple = wstate->spare;
add_tuple_to_trans(funcstate, wstate, econtext, false);
/* Reset back to its orginial value */
econtext->ecxt_scantuple = slot;
econtext->ecxt_outertuple = slot;
}
}
......@@ -3363,7 +3363,7 @@ invokeTrivialFuncs(WindowState * wstate, bool *found)
if (funcstate->trivial_frame)
{
econtext->ecxt_scantuple = wstate->curslot;
econtext->ecxt_outertuple = wstate->curslot;
add_tuple_to_trans(funcstate, wstate, econtext, false);
if (funcstate->isAgg)
......@@ -4012,7 +4012,7 @@ get_delay_edge(WindowFrameEdge * edge,
Assert(EDGE_IS_DELAYED(edge));
econtext->ecxt_scantuple = wstate->curslot;
econtext->ecxt_outertuple = wstate->curslot;
if (TupIsNull(wstate->curslot))
ereport(ERROR,
(errcode(ERROR_INVALID_WINDOW_FRAME_PARAMETER),
......@@ -4864,12 +4864,9 @@ ExecWindow(WindowState * wstate)
econtext = wstate->ps.ps_ExprContext;
/* Fetch the current_row */
econtext->ecxt_scantuple = fetchCurrentRow(wstate);
econtext->ecxt_outertuple =
econtext->ecxt_scantuple; /* XXX really need this? */
econtext->ecxt_outertuple = fetchCurrentRow(wstate);
if (TupIsNull(econtext->ecxt_scantuple))
if (TupIsNull(econtext->ecxt_outertuple))
{
ExecEagerFreeWindow(wstate);
......@@ -4901,7 +4898,7 @@ ExecWindow(WindowState * wstate)
(wstate->cur_slot_key_break != -1 &&
level >= wstate->cur_slot_key_break)))
{
econtext->ecxt_scantuple = wstate->curslot;
econtext->ecxt_outertuple = wstate->curslot;
incrementCurrentRow(level_state->frame_buffer, wstate);
}
}
......@@ -4926,7 +4923,7 @@ ExecWindow(WindowState * wstate)
ResetExprContext(econtext);
econtext->ecxt_scantuple = wstate->curslot;
econtext->ecxt_outertuple = wstate->curslot;
econtext->ecxt_outertuple = wstate->curslot;
invokeWindowFuncs(wstate);
......@@ -5094,10 +5091,10 @@ processTupleSlot(WindowState * wstate, TupleTableSlot * slot, bool last_peer)
}
/*
* Set econtext->ecxt_scantuple because the range frame needs
* Set econtext->ecxt_outertuple because the range frame needs
* this for order keys.
*/
econtext->ecxt_scantuple = wstate->priorslot;
econtext->ecxt_outertuple = wstate->priorslot;
appendToFrameBuffer(level_state, wstate, last_peer);
/*
......@@ -5169,8 +5166,7 @@ processTupleSlot(WindowState * wstate, TupleTableSlot * slot, bool last_peer)
else
{
/* Add this tuple to its transition value */
econtext->ecxt_scantuple = slot;
econtext->ecxt_outertuple = slot; /* XXX really need this? */
econtext->ecxt_outertuple = slot;
add_tuple_to_trans(funcstate, wstate, econtext, true);
......@@ -5193,7 +5189,7 @@ checkOutputReady(WindowState * wstate)
int level;
ExprContext *econtext = wstate->ps.ps_ExprContext;
econtext->ecxt_scantuple = wstate->curslot;
econtext->ecxt_outertuple = wstate->curslot;
if (wstate->input_buffer->part_break)
return true;
......@@ -5282,7 +5278,7 @@ init_bound_frame_edge_expr(WindowFrameEdge * edge, TupleDesc desc,
ltype = desc->attrs[attnum - 1]->atttypid;
rtype = exprType(edge->val);
varexpr = (Expr *)makeVar(0, attnum, ltype, vartypmod, 0);
varexpr = (Expr *) makeVar(OUTER, attnum, ltype, vartypmod, 0);
expr = (Expr *)edge->val;
......@@ -5482,7 +5478,7 @@ make_eq_exprstate(WindowState * wstate, Expr *expr1, Expr *expr2)
/*
* exec_eq_exprstate
* Executes eq_exprstate made in make_eq_exprstate() and returns
* bool result. It sets ecxt_scantuple to the current slot
* bool result. It sets ecxt_outertuple to the current slot
* so that Vars contained in eq_exprstate point to the current row.
*/
static bool
......@@ -5496,7 +5492,7 @@ exec_eq_exprstate(WindowState * wstate, ExprState *eq_exprstate)
Assert(IsA(eq_exprstate->expr, OpExpr));
/* Make sure Var in eq_expr points to the current slot */
econtext->ecxt_scantuple = wstate->curslot;
econtext->ecxt_outertuple = wstate->curslot;
oldctx = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
result = DatumGetBool(ExecEvalExpr(eq_exprstate, econtext, &isnull, NULL));
......@@ -6042,7 +6038,7 @@ windowBufferNextLastAgg(WindowBufferCursor cursor)
FrameBufferEntry *entry = level_state->curr_entry_buf;
bool found;
ExprContext *econtext = wstate->ps.ps_ExprContext;
TupleTableSlot *slot = econtext->ecxt_scantuple;
TupleTableSlot *slot = econtext->ecxt_outertuple;
Size len;
found = ntuplestore_acc_current_tupleslot(wstate->input_buffer->writer,
......@@ -6056,13 +6052,13 @@ windowBufferNextLastAgg(WindowBufferCursor cursor)
* cursor, we do this here. It is actually not so bad, as it's done in
* memory.
*/
econtext->ecxt_scantuple = wstate->spare;
econtext->ecxt_outertuple = wstate->spare;
MemSet(level_state->serial_array, 0, level_state->max_size);
serializeEntry(level_state, econtext,
&(level_state->serial_array), &(level_state->max_size), &len);
entry = deserializeEntry(level_state, entry, level_state->serial_array, len);
/* Get back the slot. */
econtext->ecxt_scantuple = slot;
econtext->ecxt_outertuple = slot;
/* We never use this again as it's the logical last row. */
cursor->use_last_agg = false;
......
......@@ -183,14 +183,7 @@ CMappingColIdVarPlStmt::PvarFromDXLNodeScId
// lookup column in the left child translation context
const TargetEntry *pte = pdxltrctxLeft->Pte(ulColId);
if (pdxltrctxLeft->FParentAggNode())
{
// variable appears in an Agg node: varno must be 0 as expected by GPDB
// TODO: Jan 26, 2011; clean this up once MPP-12034 is fixed
GPOS_ASSERT(NULL != pte);
idxVarno = 0;
}
else if (NULL != pte)
if (NULL != pte)
{
// identifier comes from left child
idxVarno = OUTER;
......
......@@ -68,7 +68,6 @@ typedef struct
PlannerGlobal *glob;
indexed_tlist *subplan_itlist;
int rtoffset;
bool use_scan_slot;
} fix_upper_expr_context;
/*
......@@ -96,8 +95,7 @@ static bool fix_scan_expr_walker(Node *node, fix_scan_expr_context *context);
static void set_join_references(PlannerGlobal *glob, Join *join, int rtoffset);
static void set_inner_join_references(PlannerGlobal *glob, Plan *inner_plan,
indexed_tlist *outer_itlist);
static void set_upper_references(PlannerGlobal *glob, Plan *plan, int rtoffset,
bool use_scan_slot);
static void set_upper_references(PlannerGlobal *glob, Plan *plan, int rtoffset);
static void set_dummy_tlist_references(Plan *plan, int rtoffset);
static indexed_tlist *build_tlist_index(List *tlist);
static Var *search_indexed_tlist_for_var(Var *var,
......@@ -129,8 +127,7 @@ static List *fix_child_hashclauses(PlannerGlobal *glob,
static Node *fix_upper_expr(PlannerGlobal *glob,
Node *node,
indexed_tlist *subplan_itlist,
int rtoffset,
bool use_scan_slot);
int rtoffset);
static Node *fix_upper_expr_mutator(Node *node,
fix_upper_expr_context *context);
static bool fix_opfuncids_walker(Node *node, void *context);
......@@ -255,7 +252,6 @@ static void set_plan_references_output_asserts(PlannerGlobal *glob, Plan *plan)
Assert((var->varno == INNER
|| var->varno == OUTER
|| var->varno == 0 /* GPDB uses 0 for scan tuple slot. */
|| (var->varno > 0 && var->varno <= list_length(glob->finalrtable)))
&& "Plan contains var that refer outside the rtable.");
......@@ -447,8 +443,7 @@ set_plan_refs(PlannerGlobal *glob, Plan *plan, int rtoffset)
(List *)fix_upper_expr(glob,
(Node *)plan->flow->hashExpr,
plan_itlist,
rtoffset,
false);
rtoffset);
pfree(plan_itlist);
}
......@@ -778,10 +773,10 @@ set_plan_refs(PlannerGlobal *glob, Plan *plan, int rtoffset)
}
break;
case T_Agg:
set_upper_references(glob, plan, rtoffset, true);
set_upper_references(glob, plan, rtoffset);
break;
case T_Window:
set_upper_references(glob, plan, rtoffset, true);
set_upper_references(glob, plan, rtoffset);
{
indexed_tlist *subplan_itlist =
build_tlist_index(plan->lefttree->targetlist);
......@@ -806,11 +801,11 @@ set_plan_refs(PlannerGlobal *glob, Plan *plan, int rtoffset)
if (window_edge_is_delayed(frame->trail))
frame->trail->val =
fix_upper_expr(glob, frame->trail->val,
subplan_itlist, rtoffset, true);
subplan_itlist, rtoffset);
if (window_edge_is_delayed(frame->lead))
frame->lead->val =
fix_upper_expr(glob, frame->lead->val,
subplan_itlist, rtoffset, true);
subplan_itlist, rtoffset);
}
}
pfree(subplan_itlist);
......@@ -826,7 +821,7 @@ set_plan_refs(PlannerGlobal *glob, Plan *plan, int rtoffset)
*/
if (splan->plan.lefttree != NULL)
{
set_upper_references(glob, plan, rtoffset, false);
set_upper_references(glob, plan, rtoffset);
}
splan->plan.targetlist =
fix_scan_list(glob, splan->plan.targetlist, rtoffset);
......@@ -839,7 +834,7 @@ set_plan_refs(PlannerGlobal *glob, Plan *plan, int rtoffset)
}
break;
case T_Repeat:
set_upper_references(glob, plan, rtoffset, false); /* GPDB code uses OUTER. */
set_upper_references(glob, plan, rtoffset);
break;
case T_Append:
{
......@@ -897,7 +892,7 @@ set_plan_refs(PlannerGlobal *glob, Plan *plan, int rtoffset)
build_tlist_index(plan->lefttree->targetlist);
motion->hashExpr = (List *)
fix_upper_expr(glob, (Node*) motion->hashExpr, childplan_itlist, rtoffset, false);
fix_upper_expr(glob, (Node*) motion->hashExpr, childplan_itlist, rtoffset);
#ifdef USE_ASSERT_CHECKING
/* 1. Assert that the Motion node has same number of hash data types as that of hash expressions*/
......@@ -1570,8 +1565,7 @@ set_inner_join_references(PlannerGlobal *glob, Plan *inner_plan,
* the expression.
*/
static void
set_upper_references(PlannerGlobal *glob, Plan *plan, int rtoffset,
bool use_scan_slot)
set_upper_references(PlannerGlobal *glob, Plan *plan, int rtoffset)
{
Plan *subplan = plan->lefttree;
indexed_tlist *subplan_itlist;
......@@ -1593,8 +1587,7 @@ set_upper_references(PlannerGlobal *glob, Plan *plan, int rtoffset,
newexpr = fix_upper_expr(glob,
(Node *) tle->expr,
subplan_itlist,
rtoffset,
use_scan_slot);
rtoffset);
tle = flatCopyTargetEntry(tle);
tle->expr = (Expr *) newexpr;
output_targetlist = lappend(output_targetlist, tle);
......@@ -1605,8 +1598,7 @@ set_upper_references(PlannerGlobal *glob, Plan *plan, int rtoffset,
fix_upper_expr(glob,
(Node *) plan->qual,
subplan_itlist,
rtoffset,
use_scan_slot);
rtoffset);
pfree(subplan_itlist);
}
......@@ -2095,27 +2087,18 @@ fix_join_expr_mutator(Node *node, fix_join_expr_context *context)
* The resulting tree is a copy of the original in which all Var nodes have
* varno = OUTER, varattno = resno of corresponding subplan target.
* The original tree is not modified.
*
* GPDB: Some of our executor nodes use the scantuple slot. Caller may
* indicate use of 0 (instead of OUTER) for varno by passing true in
* use_scan_slot.
*
* XXX We could do away with the need for use_scan_slot by adjusting the
* executor!
*/
static Node *
fix_upper_expr(PlannerGlobal *glob,
Node *node,
indexed_tlist *subplan_itlist,
int rtoffset,
bool use_scan_slot)
int rtoffset)
{
fix_upper_expr_context context;
context.glob = glob;
context.subplan_itlist = subplan_itlist;
context.rtoffset = rtoffset;
context.use_scan_slot = use_scan_slot;
return fix_upper_expr_mutator(node, &context);
}
......@@ -2124,24 +2107,17 @@ static Node *
fix_upper_expr_mutator(Node *node, fix_upper_expr_context *context)
{
Var *newvar;
Index slot_varno;
if (node == NULL)
return NULL;
/* GPDB executor uses scantuple instead of outertuple in some cases. */
if (context->use_scan_slot)
slot_varno = 0;
else
slot_varno = OUTER;
if (IsA(node, Var))
{
Var *var = (Var *) node;
newvar = search_indexed_tlist_for_var(var,
context->subplan_itlist,
slot_varno,
OUTER,
context->rtoffset);
if (!newvar)
elog(ERROR, "variable not found in subplan target list");
......@@ -2152,7 +2128,7 @@ fix_upper_expr_mutator(Node *node, fix_upper_expr_context *context)
{
newvar = search_indexed_tlist_for_non_var(node,
context->subplan_itlist,
slot_varno);
OUTER);
if (newvar)
return (Node *) newvar;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册