first commit for openGauss server
This commit is contained in:
187
src/gausskernel/runtime/executor/nodeExtensible.cpp
Executable file
187
src/gausskernel/runtime/executor/nodeExtensible.cpp
Executable file
@ -0,0 +1,187 @@
|
||||
/*
|
||||
* 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.
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* nodeExtensible.cpp
|
||||
* ExtensiblePlan is an extended plan node which supports various customize operations.
|
||||
* Normally we built our ExtensiblePlan on the upper level of the original plan.
|
||||
* To implement the ExtensiblePlan, we should first implement BeginExtensiblePlan() method,
|
||||
* ExecExtensiblePlan() method, EndExtensiblePlan() method ReScanExtensiblePlan() method.
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* src/gausskernel/runtime/executor/nodeExtensible.cpp
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*/
|
||||
#include "postgres.h"
|
||||
#include "knl/knl_variable.h"
|
||||
|
||||
#include "executor/executor.h"
|
||||
#include "executor/nodeExtensible.h"
|
||||
#include "nodes/execnodes.h"
|
||||
#include "nodes/plannodes.h"
|
||||
#include "parser/parsetree.h"
|
||||
#include "utils/hsearch.h"
|
||||
#include "utils/memutils.h"
|
||||
#include "utils/rel.h"
|
||||
|
||||
const int EXTNODENAME_MAX_LEN = 64;
|
||||
static HTAB* g_extensible_plan_methods = NULL;
|
||||
const int HASHTABLE_LENGTH = 100;
|
||||
|
||||
typedef struct {
|
||||
char extnodename[EXTNODENAME_MAX_LEN];
|
||||
void* extnodemethods;
|
||||
} ExtensibleNodeEntry;
|
||||
|
||||
ExtensiblePlanState* ExecInitExtensiblePlan(ExtensiblePlan* eplan, EState* estate, int eflags)
|
||||
{
|
||||
ExtensiblePlanState* extensionPlanState;
|
||||
Relation scan_rel = NULL;
|
||||
Index scanrelid = eplan->scan.scanrelid;
|
||||
Index tlistvarno;
|
||||
|
||||
/*
|
||||
* Allocate the ExtensiblePlanState object. We let the extensible scan provider
|
||||
* do the palloc, in case it wants to make a larger object that embeds
|
||||
* ExtensiblePlanState as the first field. It must set the node tag and the
|
||||
* methods field correctly at this time. Other standard fields should be
|
||||
* set to zero.
|
||||
*/
|
||||
extensionPlanState = (ExtensiblePlanState*)eplan->methods->CreateExtensiblePlanState(eplan);
|
||||
|
||||
/* ensure flags is filled correctly */
|
||||
extensionPlanState->flags = eplan->flags;
|
||||
|
||||
/* fill up fields of ScanState */
|
||||
extensionPlanState->ss.ps.plan = &eplan->scan.plan;
|
||||
extensionPlanState->ss.ps.state = estate;
|
||||
|
||||
/* create expression context for node */
|
||||
ExecAssignExprContext(estate, &extensionPlanState->ss.ps);
|
||||
|
||||
extensionPlanState->ss.ps.ps_TupFromTlist = false;
|
||||
|
||||
/* initialize child expressions */
|
||||
extensionPlanState->ss.ps.targetlist =
|
||||
(List*)ExecInitExpr((Expr*)eplan->scan.plan.targetlist, (PlanState*)extensionPlanState);
|
||||
extensionPlanState->ss.ps.qual = (List*)ExecInitExpr((Expr*)eplan->scan.plan.qual, (PlanState*)extensionPlanState);
|
||||
|
||||
/* tuple table initialization */
|
||||
ExecInitScanTupleSlot(estate, &extensionPlanState->ss);
|
||||
ExecInitResultTupleSlot(estate, &extensionPlanState->ss.ps);
|
||||
|
||||
/*
|
||||
* open the base relation, if any, and acquire an appropriate lock on it
|
||||
*/
|
||||
if (scanrelid > 0) {
|
||||
scan_rel = ExecOpenScanRelation(estate, scanrelid);
|
||||
extensionPlanState->ss.ss_currentRelation = scan_rel;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine the scan tuple type. If the extensible scan provider provided a
|
||||
* targetlist describing the scan tuples, use that; else use base
|
||||
* relation's rowtype.
|
||||
*/
|
||||
if (eplan->extensible_plan_tlist != NIL || scan_rel == NULL) {
|
||||
TupleDesc scan_tupdesc;
|
||||
|
||||
scan_tupdesc = ExecTypeFromTL(eplan->extensible_plan_tlist, false);
|
||||
ExecAssignScanType(&extensionPlanState->ss, scan_tupdesc);
|
||||
/* Node's targetlist will contain Vars with varno = INDEX_VAR */
|
||||
tlistvarno = INDEX_VAR;
|
||||
} else {
|
||||
ExecAssignScanType(&extensionPlanState->ss, RelationGetDescr(scan_rel));
|
||||
/* Node's targetlist will contain Vars with varno = scanrelid */
|
||||
tlistvarno = scanrelid;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize result tuple type and projection info.
|
||||
*/
|
||||
ExecAssignResultTypeFromTL(&extensionPlanState->ss.ps);
|
||||
ExecAssignScanProjectionInfoWithVarno(&extensionPlanState->ss, tlistvarno);
|
||||
|
||||
/*
|
||||
* The callback of extensible-scan provider applies the final initialization
|
||||
* of the extensible-scan-state node according to its logic.
|
||||
*/
|
||||
extensionPlanState->methods->BeginExtensiblePlan(extensionPlanState, estate, eflags);
|
||||
|
||||
return extensionPlanState;
|
||||
}
|
||||
|
||||
TupleTableSlot* ExecExtensiblePlan(ExtensiblePlanState* node)
|
||||
{
|
||||
Assert(node->methods->ExecExtensiblePlan != NULL);
|
||||
return node->methods->ExecExtensiblePlan(node);
|
||||
}
|
||||
|
||||
void ExecEndExtensiblePlan(ExtensiblePlanState* node)
|
||||
{
|
||||
Assert(node->methods->EndExtensiblePlan != NULL);
|
||||
node->methods->EndExtensiblePlan(node);
|
||||
|
||||
/* Free the exprcontext */
|
||||
ExecFreeExprContext(&node->ss.ps);
|
||||
|
||||
/* Clean out the tuple table */
|
||||
(void)ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
|
||||
(void)ExecClearTuple(node->ss.ss_ScanTupleSlot);
|
||||
|
||||
/* Close the heap relation */
|
||||
if (node->ss.ss_currentRelation) {
|
||||
ExecCloseScanRelation(node->ss.ss_currentRelation);
|
||||
}
|
||||
}
|
||||
|
||||
void ExecReScanExtensiblePlan(ExtensiblePlanState* node)
|
||||
{
|
||||
Assert(node->methods->ReScanExtensiblePlan != NULL);
|
||||
node->methods->ReScanExtensiblePlan(node);
|
||||
}
|
||||
|
||||
/*
|
||||
* An internal routine to get an ExtensibleNodeEntry by the given identifier
|
||||
*/
|
||||
static void* GetExtensibleNodeEntry(HTAB* htable, const char* extnodename, bool missing_ok)
|
||||
{
|
||||
ExtensibleNodeEntry* entry = NULL;
|
||||
|
||||
if (htable != NULL) {
|
||||
entry = (ExtensibleNodeEntry*)hash_search(htable, extnodename, HASH_FIND, NULL);
|
||||
}
|
||||
if (entry != NULL) {
|
||||
if (missing_ok) {
|
||||
return NULL;
|
||||
}
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("ExtensibleNodeMethods \"%s\" was not registered", extnodename)));
|
||||
}
|
||||
if (entry != NULL) {
|
||||
return entry->extnodemethods;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the methods for a given name of ExtensiblePlanMethods
|
||||
*/
|
||||
ExtensiblePlanMethods* GetExtensiblePlanMethods(const char* ExtensibleName, bool missing_ok)
|
||||
{
|
||||
return (ExtensiblePlanMethods*)GetExtensibleNodeEntry(g_extensible_plan_methods, ExtensibleName, missing_ok);
|
||||
}
|
||||
Reference in New Issue
Block a user