New features (and bug fixes)

1. alter large sequence
    2. subpartition
    2.1 split subpartition
    2.2 truncate subpartition
    3. 支持load
    4. 支持start-with/connect-by
    5. ...
This commit is contained in:
dengxuyue
2021-12-23 20:34:44 +08:00
committed by zhangzhiyang
parent 27bdb0d62b
commit c7b25efcff
1276 changed files with 332499 additions and 94042 deletions

View File

@ -6,6 +6,7 @@
* 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
* Portions Copyright (c) 2021, openGauss Contributors
*
*
* IDENTIFICATION
@ -19,6 +20,7 @@
#include "access/xact.h"
#include "executor/exec/execdebug.h"
#include "executor/node/nodeAgg.h"
#include "executor/node/nodeCtescan.h"
#include "executor/node/nodeHashjoin.h"
#include "executor/node/nodeMaterial.h"
#include "executor/node/nodeRecursiveunion.h"
@ -68,6 +70,11 @@ static void StartNextRecursiveIteration(RecursiveUnionController* controller, in
static void ExecInitRecursiveResultTupleSlot(EState* estate, PlanState* planstate);
#endif
static inline bool IsUnderStartWith(RecursiveUnion *ruplan)
{
return (ruplan->internalEntryList != NIL);
}
/*
* To implement UNION (without ALL), we need a hashtable that stores tuples
* already seen. The hash key is computed from the grouping columns.
@ -178,6 +185,15 @@ TupleTableSlot* ExecRecursiveUnion(RecursiveUnionState* node)
continue;
}
}
/*
* Add RUITR and nessary internal pseudo columns before store into worktable,
* only processed in start-with case
*/
if (IsUnderStartWith((RecursiveUnion *)node->ps.plan)) {
slot = ConvertRuScanOutputSlot(node, slot, false);
}
/* Each non-duplicate tuple goes to the working table ... */
tuplestore_puttupleslot(node->working_table, slot);
@ -205,8 +221,11 @@ TupleTableSlot* ExecRecursiveUnion(RecursiveUnionState* node)
/* Kick-Off next step */
StartNextRecursiveIteration(node->rucontroller, WITH_RECURSIVE_SYNC_NONERQ);
}
node->iteration = 1;
#endif
node->iteration = 1;
/* Need reset sw_tuple_idx to 1 when non-recursive term finish */
node->sw_tuple_idx = 1;
}
/* 2. Execute recursive term */
@ -217,6 +236,14 @@ TupleTableSlot* ExecRecursiveUnion(RecursiveUnionState* node)
for (;;) {
slot = ExecProcNode(inner_plan);
if (TupIsNull(slot)) {
/* debug information for SWCBcase */
if (IsUnderStartWith((RecursiveUnion *)node->ps.plan)) {
ereport(DEBUG1, (errmodule(MOD_EXECUTOR),
errmsg("[SWCB DEBUG] current iteration is done: level:%d rownum_current:%d rownum_total:%lu",
node->iteration + 1,
node->swstate->sw_numtuples,
node->swstate->sw_rownum)));
}
#ifdef ENABLE_MULTIPLE_NODES
/*
* Check the recursive union is run out of max allowed iterations
@ -249,6 +276,8 @@ TupleTableSlot* ExecRecursiveUnion(RecursiveUnionState* node)
break;
}
#endif
/* Need reset sw_tuple_idx to 1 when current iteration finish */
node->sw_tuple_idx = 1;
/* done with old working table ... */
tuplestore_end(node->working_table);
@ -292,6 +321,7 @@ TupleTableSlot* ExecRecursiveUnion(RecursiveUnionState* node)
StartNextRecursiveIteration(node->rucontroller, WITH_RECURSIVE_SYNC_RQSTEP);
}
#else
node->iteration++;
node->intermediate_table = tuplestore_begin_heap(false, false, u_sess->attr.attr_memory.work_mem);
/* reset the recursive term */
inner_plan->chgParam = bms_add_member(inner_plan->chgParam, plan->wtParam);
@ -315,6 +345,49 @@ TupleTableSlot* ExecRecursiveUnion(RecursiveUnionState* node)
/* Else, tuple is good; stash it in intermediate table ... */
node->intermediate_empty = false;
/* For start-with, reason ditto */
if (IsUnderStartWith((RecursiveUnion *)node->ps.plan)) {
int max_times = u_sess->attr.attr_sql.max_recursive_times;
StartWithOp *swplan = (StartWithOp *)node->swstate->ps.plan;
/*
* Cannot exceed max_recursive_times
* The reason we also keep iteration check here is
* avoid order siblings by exist.
* */
if (node->iteration > max_times) {
ereport(ERROR,
(errcode(ERRCODE_CONFIGURATION_LIMIT_EXCEEDED),
errmsg("Current Start With...Connect by has exceeded max iteration times %d", max_times),
errhint("Please check your connect by clause carefully")));
}
slot = ConvertRuScanOutputSlot(node, slot, true);
/*
* In ORDER SIBLINGS case, as we add SORT-Operator(material) on top of
* RecursiveUnion, so we have to do nocycle check here
*/
if (swplan->swoptions->siblings_orderby_clause) {
StartWithOpState *swstate = (StartWithOpState *)node->swstate;
if (swstate->sw_nocycleStopOrderSiblings) {
return (TupleTableSlot *)NULL;
}
if (CheckCycleExeception(swstate, slot)) {
/*
* Mark execution stop for order siblings, note we let the cycle-causing
* tuple return to upper node and stop next one
*/
swstate->sw_nocycleStopOrderSiblings = true;
elog(DEBUG1, "nocycle option take effect on RecursiveUnion for Order Siblings! %s",
swstate->sw_curKeyArrayStr);
}
}
}
tuplestore_puttupleslot(node->intermediate_table, slot);
/* ... and return it */
@ -530,6 +603,16 @@ RecursiveUnionState* ExecInitRecursiveUnion(RecursiveUnion* node, EState* estate
memset_s(&((rustate->ps.instrument)->recursiveInfo), sizeof(RecursiveInfo), 0, sizeof(RecursiveInfo));
securec_check(rc, "\0", "\0");
}
/* Init start with related variables */
rustate->swstate = NULL;
rustate->sw_tuple_idx = 1;
rustate->convertContext = AllocSetContextCreate(CurrentMemoryContext,
"RecursiveUnion Start With",
ALLOCSET_DEFAULT_MINSIZE,
ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE);
return rustate;
}
@ -558,6 +641,9 @@ void ExecEndRecursiveUnion(RecursiveUnionState* node)
MemoryContextDelete(node->tempContext);
if (node->tableContext)
MemoryContextDelete(node->tableContext);
if (node->convertContext) {
MemoryContextDelete(node->convertContext);
}
/*
* clean out the upper tuple table
@ -608,6 +694,7 @@ void ExecReScanRecursiveUnion(RecursiveUnionState* node)
/* reset processing state */
node->recursing = false;
node->intermediate_empty = true;
node->iteration = 0;
tuplestore_clear(node->working_table);
tuplestore_clear(node->intermediate_table);
}