first commit for openGauss server
This commit is contained in:
179
src/gausskernel/runtime/executor/nodeUnique.cpp
Executable file
179
src/gausskernel/runtime/executor/nodeUnique.cpp
Executable file
@ -0,0 +1,179 @@
|
||||
/* -------------------------------------------------------------------------
|
||||
*
|
||||
* nodeUnique.cpp
|
||||
* Routines to handle unique'ing of queries where appropriate
|
||||
*
|
||||
* Unique is a very simple node type that just filters out duplicate
|
||||
* tuples from a stream of sorted tuples from its subplan. It's essentially
|
||||
* a dumbed-down form of Group: the duplicate-removal functionality is
|
||||
* identical. However, Unique doesn't do projection nor qual checking,
|
||||
* so it's marginally more efficient for cases where neither is needed.
|
||||
* (It's debatable whether the savings justifies carrying two plan node
|
||||
* types, though.)
|
||||
*
|
||||
* Portions Copyright (c) 2020 Huawei Technologies Co.,Ltd.
|
||||
* Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* src/gausskernel/runtime/executor/nodeUnique.cpp
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* INTERFACE ROUTINES
|
||||
* ExecUnique - generate a unique'd temporary relation
|
||||
* ExecInitUnique - initialize node and subnodes
|
||||
* ExecEndUnique - shutdown node and subnodes
|
||||
*
|
||||
* NOTES
|
||||
* Assumes tuples returned from subplan arrive in
|
||||
* sorted order.
|
||||
*/
|
||||
#include "postgres.h"
|
||||
#include "knl/knl_variable.h"
|
||||
|
||||
#include "executor/executor.h"
|
||||
#include "executor/nodeUnique.h"
|
||||
#include "utils/memutils.h"
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* ExecUnique
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
TupleTableSlot* ExecUnique(UniqueState* node) /* return: a tuple or NULL */
|
||||
{
|
||||
Unique* plan_node = (Unique*)node->ps.plan;
|
||||
TupleTableSlot* slot = NULL;
|
||||
|
||||
/*
|
||||
* get information from the node
|
||||
*/
|
||||
PlanState* outer_plan = outerPlanState(node);
|
||||
TupleTableSlot* result_tuple_slot = node->ps.ps_ResultTupleSlot;
|
||||
|
||||
/*
|
||||
* now loop, returning only non-duplicate tuples. We assume that the
|
||||
* tuples arrive in sorted order so we can detect duplicates easily. The
|
||||
* first tuple of each group is returned.
|
||||
*/
|
||||
for (;;) {
|
||||
/*
|
||||
* fetch a tuple from the outer subplan
|
||||
*/
|
||||
slot = ExecProcNode(outer_plan);
|
||||
if (TupIsNull(slot)) {
|
||||
/* end of subplan, so we're done */
|
||||
(void)ExecClearTuple(result_tuple_slot);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Always return the first tuple from the subplan.
|
||||
*/
|
||||
if (TupIsNull(result_tuple_slot))
|
||||
break;
|
||||
|
||||
/*
|
||||
* Else test if the new tuple and the previously returned tuple match.
|
||||
* If so then we loop back and fetch another new tuple from the
|
||||
* subplan.
|
||||
*/
|
||||
if (!execTuplesMatch(
|
||||
slot, result_tuple_slot, plan_node->numCols, plan_node->uniqColIdx, node->eqfunctions, node->tempContext))
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* We have a new tuple different from the previous saved tuple (if any).
|
||||
* Save it and return it. We must copy it because the source subplan
|
||||
* won't guarantee that this source tuple is still accessible after
|
||||
* fetching the next source tuple.
|
||||
*/
|
||||
return ExecCopySlot(result_tuple_slot, slot);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* ExecInitUnique
|
||||
*
|
||||
* This initializes the unique node state structures and
|
||||
* the node's subplan.
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
UniqueState* ExecInitUnique(Unique* node, EState* estate, int eflags)
|
||||
{
|
||||
/* check for unsupported flags */
|
||||
Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
|
||||
|
||||
/*
|
||||
* create state structure
|
||||
*/
|
||||
UniqueState* unique_state = makeNode(UniqueState);
|
||||
|
||||
unique_state->ps.plan = (Plan*)node;
|
||||
unique_state->ps.state = estate;
|
||||
|
||||
/*
|
||||
* Miscellaneous initialization
|
||||
*
|
||||
* Unique nodes have no ExprContext initialization because they never call
|
||||
* ExecQual or ExecProject. But they do need a per-tuple memory context
|
||||
* anyway for calling execTuplesMatch.
|
||||
*/
|
||||
unique_state->tempContext = AllocSetContextCreate(
|
||||
CurrentMemoryContext, "Unique", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE);
|
||||
|
||||
/*
|
||||
* Tuple table initialization
|
||||
*/
|
||||
ExecInitResultTupleSlot(estate, &unique_state->ps);
|
||||
|
||||
/*
|
||||
* then initialize outer plan
|
||||
*/
|
||||
outerPlanState(unique_state) = ExecInitNode(outerPlan(node), estate, eflags);
|
||||
|
||||
/*
|
||||
* unique nodes do no projections, so initialize projection info for this
|
||||
* node appropriately
|
||||
*/
|
||||
ExecAssignResultTypeFromTL(&unique_state->ps);
|
||||
unique_state->ps.ps_ProjInfo = NULL;
|
||||
|
||||
/*
|
||||
* Precompute fmgr lookup data for inner loop
|
||||
*/
|
||||
unique_state->eqfunctions = execTuplesMatchPrepare(node->numCols, node->uniqOperators);
|
||||
|
||||
return unique_state;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* ExecEndUnique
|
||||
*
|
||||
* This shuts down the subplan and frees resources allocated
|
||||
* to this node.
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
void ExecEndUnique(UniqueState* node)
|
||||
{
|
||||
/* clean up tuple table */
|
||||
(void)ExecClearTuple(node->ps.ps_ResultTupleSlot);
|
||||
|
||||
MemoryContextDelete(node->tempContext);
|
||||
|
||||
ExecEndNode(outerPlanState(node));
|
||||
}
|
||||
|
||||
void ExecReScanUnique(UniqueState* node)
|
||||
{
|
||||
/* must clear result tuple so first input tuple is returned */
|
||||
(void)ExecClearTuple(node->ps.ps_ResultTupleSlot);
|
||||
|
||||
/*
|
||||
* if chgParam of subnode is not null then plan will be re-scanned by
|
||||
* first ExecProcNode.
|
||||
*/
|
||||
if (node->ps.lefttree->chgParam == NULL)
|
||||
ExecReScan(node->ps.lefttree);
|
||||
}
|
||||
Reference in New Issue
Block a user