211 lines
6.3 KiB
C++
Executable File
211 lines
6.3 KiB
C++
Executable File
/*
|
|
* Copyright (c) 2020 Huawei Technologies Co.,Ltd.
|
|
*
|
|
* openGauss is licensed under Mulan PSL v2.
|
|
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
|
* You may obtain a copy of Mulan PSL v2 at:
|
|
*
|
|
* http://license.coscl.org.cn/MulanPSL2
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
|
* See the Mulan PSL v2 for more details.
|
|
* ---------------------------------------------------------------------------------------
|
|
*
|
|
* nodePartIterator.cpp
|
|
* data partition: routines to support Partition Wise Join
|
|
*
|
|
* IDENTIFICATION
|
|
* src/gausskernel/runtime/executor/nodePartIterator.cpp
|
|
*
|
|
* ---------------------------------------------------------------------------------------
|
|
*/
|
|
#include "postgres.h"
|
|
#include "knl/knl_variable.h"
|
|
|
|
#include "executor/execdebug.h"
|
|
#include "executor/nodePartIterator.h"
|
|
#include "executor/tuptable.h"
|
|
#include "utils/memutils.h"
|
|
#include "nodes/execnodes.h"
|
|
#include "nodes/plannodes.h"
|
|
#include "vecexecutor/vecnodes.h"
|
|
|
|
/*
|
|
* @@GaussDB@@
|
|
* Target : data partition
|
|
* Brief : initialize PartIterator for partition iteration
|
|
* Description :
|
|
* Notes : it is used for partitioned-table only
|
|
*/
|
|
PartIteratorState* ExecInitPartIterator(PartIterator* node, EState* estate, int eflags)
|
|
{
|
|
PartIteratorState* state = NULL;
|
|
|
|
state = makeNode(PartIteratorState);
|
|
state->ps.plan = (Plan*)node;
|
|
state->ps.state = estate;
|
|
|
|
/* initiate sub node */
|
|
state->ps.lefttree = ExecInitNode(node->plan.lefttree, estate, eflags);
|
|
state->ps.qual = NULL;
|
|
state->ps.righttree = NULL;
|
|
state->ps.subPlan = NULL;
|
|
state->ps.ps_TupFromTlist = false;
|
|
state->ps.ps_ProjInfo = NULL;
|
|
state->currentItr = -1;
|
|
|
|
return state;
|
|
}
|
|
|
|
static void init_scan_partition(PartIteratorState* node)
|
|
{
|
|
int paramno = 0;
|
|
unsigned int itr_idx = 0;
|
|
PartIterator* pi_node = (PartIterator*)node->ps.plan;
|
|
ParamExecData* param = NULL;
|
|
|
|
Assert(ForwardScanDirection == pi_node->direction || BackwardScanDirection == pi_node->direction);
|
|
|
|
/* set iterator parameter */
|
|
node->currentItr++;
|
|
itr_idx = node->currentItr;
|
|
if (BackwardScanDirection == pi_node->direction)
|
|
itr_idx = pi_node->itrs - itr_idx - 1;
|
|
|
|
paramno = pi_node->param->paramno;
|
|
param = &(node->ps.state->es_param_exec_vals[paramno]);
|
|
param->isnull = false;
|
|
param->value = (Datum)itr_idx;
|
|
node->ps.lefttree->chgParam = bms_add_member(node->ps.lefttree->chgParam, paramno);
|
|
|
|
/* reset the plan node so that next partition can be scanned */
|
|
ExecReScan(node->ps.lefttree);
|
|
}
|
|
|
|
/*
|
|
* @@GaussDB@@
|
|
* Target : data partition
|
|
* Brief : Scans the partitioned table with partition iteration and returns
|
|
* : the next qualifying tuple in the direction specified
|
|
* Description : partition iteration is a frame of the Planstate for scan a partitioned
|
|
* : table. it is like a monitor. The real job is done by SeqScan .e.g
|
|
* Notes :
|
|
*/
|
|
TupleTableSlot* ExecPartIterator(PartIteratorState* node)
|
|
{
|
|
TupleTableSlot* slot = NULL;
|
|
PartIterator* pi_node = (PartIterator*)node->ps.plan;
|
|
EState* state = node->ps.lefttree->state;
|
|
bool orig_early_free = state->es_skip_early_free;
|
|
|
|
PlanState* noden = (PlanState*)node->ps.lefttree;
|
|
int partitionScan;
|
|
switch (nodeTag(noden)) {
|
|
case T_SeqScanState:
|
|
partitionScan = ((SeqScanState*)noden)->part_id;
|
|
break;
|
|
case T_IndexScanState:
|
|
partitionScan = ((IndexScanState*)noden)->part_id;
|
|
break;
|
|
case T_IndexOnlyScanState:
|
|
partitionScan = ((IndexOnlyScanState*)noden)->part_id;
|
|
break;
|
|
case T_BitmapHeapScanState:
|
|
partitionScan = ((BitmapHeapScanState*)noden)->part_id;
|
|
break;
|
|
case T_VecToRowState:
|
|
partitionScan = ((VecToRowState*)noden)->part_id;
|
|
break;
|
|
default:
|
|
partitionScan = pi_node->itrs;
|
|
break;
|
|
}
|
|
|
|
if (partitionScan == 0) {
|
|
/* return NULL if no partition is selected */
|
|
return NULL;
|
|
}
|
|
|
|
/* init first scanned partition */
|
|
if (node->currentItr == -1)
|
|
init_scan_partition(node);
|
|
|
|
/* For partition wise join, can not early free left tree's caching memory */
|
|
state->es_skip_early_free = true;
|
|
slot = ExecProcNode(node->ps.lefttree);
|
|
state->es_skip_early_free = orig_early_free;
|
|
|
|
if (!TupIsNull(slot))
|
|
return slot;
|
|
|
|
/* switch to next partition until we get a unempty tuple */
|
|
for (;;) {
|
|
if (node->currentItr + 1 >= partitionScan) /* have scanned all partitions */
|
|
return NULL;
|
|
|
|
/* switch to next partiiton */
|
|
init_scan_partition(node);
|
|
|
|
/* For partition wise join, can not early free left tree's caching memory */
|
|
orig_early_free = state->es_skip_early_free;
|
|
state->es_skip_early_free = true;
|
|
slot = ExecProcNode(node->ps.lefttree);
|
|
state->es_skip_early_free = orig_early_free;
|
|
|
|
if (!TupIsNull(slot))
|
|
return slot;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* @@GaussDB@@
|
|
* Target : data partition
|
|
* Brief : clear out the partition iterator
|
|
* Description :
|
|
* Notes :
|
|
*/
|
|
void ExecEndPartIterator(PartIteratorState* node)
|
|
{
|
|
/* close down subplans */
|
|
ExecEndNode(node->ps.lefttree);
|
|
}
|
|
|
|
/*
|
|
* @@GaussDB@@
|
|
* Target : data partition
|
|
* Brief : Reset the partition iterator node so that its output
|
|
* : can be re-scanned.
|
|
* Description :
|
|
* Notes :
|
|
*/
|
|
void ExecReScanPartIterator(PartIteratorState* node)
|
|
{
|
|
PartIterator* pi_node = NULL;
|
|
int paramno = -1;
|
|
ParamExecData* param = NULL;
|
|
PartIterator* piterator = NULL;
|
|
|
|
piterator = (PartIterator*)node->ps.plan;
|
|
|
|
/* do nothing if there is no partition to scan */
|
|
if (piterator->itrs == 0)
|
|
return;
|
|
|
|
node->currentItr = -1;
|
|
|
|
pi_node = (PartIterator*)node->ps.plan;
|
|
paramno = pi_node->param->paramno;
|
|
param = &(node->ps.state->es_param_exec_vals[paramno]);
|
|
param->isnull = false;
|
|
param->value = (Datum)0;
|
|
node->ps.lefttree->chgParam = bms_add_member(node->ps.lefttree->chgParam, paramno);
|
|
|
|
/*
|
|
* if the pruning result isnot null, Reset the subplan node so
|
|
* that its output can be re-scanned.
|
|
*/
|
|
ExecReScan(node->ps.lefttree);
|
|
}
|