(2) 计算表达式结果。
(3) 判断结果中itemIsDone[resind]参数并生成最后的元组。
ExecTargetList函数的执行流程如图7-19所示。
图7-19 ExecTargetList函数执行流程
ExecProject函数的作用是进行投影操作,投影操作是一种属性过滤过程,该操作将对元组的属性进行精简,把在上层计划节点中不需要用的属性从元组中去掉,从而构造一个精简版的元组。投影操作中被保留下来的那些属性被称为投影属性。主要结构体代码如下:
typedef struct ProjectionInfo {
NodeTag type;
List* pi_targetlist; /*目标列表*/
ExprContext* pi_exprContext; /*内存上下文*/
TupleTableSlot* pi_slot; /*投影结果*/
ExprDoneCond* pi_itemIsDone; /*ExecProject的工作区数组*/
bool pi_directMap;
int pi_numSimpleVars; /*在原始tlist(查询目标列表)中找到的简单变量数*/
int* pi_varSlotOffsets; /*指示变量来自哪个slot(槽位)的数组*/
int* pi_varNumbers; /*包含变量的输入属性数的数组*/
int* pi_varOutputCols; /*包含变量的输出属性数的数组*/
int pi_lastInnerVar; /*内部参数*/
int pi_lastOuterVar; /*外部参数*/
int pi_lastScanVar; /*扫描参数*/
List* pi_acessedVarNumbers;
List* pi_sysAttrList;
List* pi_lateAceessVarNumbers;
List* pi_maxOrmin; /*列表优化,指示获取此列的最大值还是最小值*/
List* pi_PackTCopyVars; /*记录需要移动的列*/
List* pi_PackLateAccessVarNumbers; /*记录cstore(列存储)扫描中移动的内容的列*/
bool pi_const;
VectorBatch* pi_batch;
vectarget_func jitted_vectarget; /* LLVM函数指针*/
VectorBatch* pi_setFuncBatch;
} ProjectionInfo;
ExecProject函数的主要执行流程如下。
(1) 取ProjectionInfo需要投影的信息。按照执行的偏移获取原属性所在的元组,通过偏移量获取该属性,并通过目标属性的序号找到对应的新元组属性位置进行赋值。
(2) 对pi_targetlist进行运算,将结果赋值给对应元组中的属性。
(3)产生一个行记录结果,对slot做标记处理,slot包含一个有效的虚拟元组。
ExecProject函数的执行流程如图7-20所示。
图7-20 ExecProject函数执行流程
ExecEvalParamExec函数的作用是获取并返回PARAM_EXEC类型的参数。PARAM_EXEC参数是指内部执行器参数,是需要执行子计划来获取的结果,最后需要将结果返回到上层计划中。核心代码如下:
prm = &(econtext->ecxt_param_exec_vals[thisParamId]); /* 获取econtext中参数 */
if (prm->execPlan != NULL) { /* 判断是否需要生成参数 */
/* 参数还未计算执行此函数*/
ExecSetParamPlan((SubPlanState*)prm->execPlan, econtext);
/*参数计算完计划重置为空*/
Assert(prm->execPlan == NULL);
prm->isConst = true;
prm->valueType = expression->paramtype;
}
*isNull = prm->isnull;
prm->isChanged = true;
return prm->value; /* 返回生成的参数 */
ExecEvalParamExec函数的主要执行流程如下。
(1) 获取econtext中的ecxt_param_exec_vals参数。
(2) 判断子计划是否为空,若不为空则调用ExecSetParamPlan函数执行子计划获取结果,并把计划置为空,当再次执行此函数时,不需要重新执行计划,直接返回已经获取过结果。
(3) 将结果prm->value返回。
ExecEvalParamExec函数的执行流程如图7-21所示。
图7-21 ExecEvalParamExec函数执行流程
ExecEvalParamExtern函数的作用是获取并返回PARAM_EXTERN类型的参数。该参数是指外部传入参数,例如在PBE执行时,PREPARE的语句中的参数,在需要execute语句执行时传入。核心代码如下:
if (paramInfo && thisParamId > 0 && thisParamId <= paramInfo->numParams) {/* 判断参数 */
ParamExternData* prm = ¶mInfo->params[thisParamId - 1];
if (!OidIsValid(prm->ptype) && paramInfo->paramFetch != NULL) /* 获取动态参数 */
(*paramInfo->paramFetch)(paramInfo, thisParamId);
if (OidIsValid(prm->ptype)) { /*检查参数并返回 */
if (prm->ptype != expression->paramtype)
ereport(……);
*isNull = prm->isnull;
if (econtext->is_cursor && prm->ptype == REFCURSOROID) {
CopyCursorInfoData(&econtext->cursor_data, &prm->cursor_data);
econtext->dno = thisParamId - 1;
}
return prm->value;
}
}
ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("no value found for parameter %d", thisParamId)));
return (Datum)0;
ExecEvalParamExtern函数主要执行流程如下。
(1) 判断PARAM_EXTERN类型的参数否存在,若存在则从ecxt_param_list_info中获取该参数,否则直接报错。
(2) 判断参数是否是动态的,若是动态的则再次获取参数。
(3) 判断参数类型是否符合要求,若符合要求直接返回该参数。
ExecEvalParamExtern函数的执行流程如图7-22所示。
图7-22 ExecEvalParamExtern函数执行流程
7.5 编译执行
为了提高SQL的执行速度,解决传统数据处理引擎条件逻辑冗余的问题ÿ