这篇文章主要介绍postgresql如何构建表达式解析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!一、数据结构EEO_XXX宏定义opcode分发器宏定义 #if def
这篇文章主要介绍postgresql如何构建表达式解析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!
EEO_XXX宏定义
opcode分发器宏定义
#if defined(EEO_USE_COMPUTED_GoTO)
//--------------- 定义了EEO_USE_COMPUTED_GOTO
//跳转target -> opcode搜索表结构体
typedef struct ExprEvalOpLookup
{
const void *opcode;
ExprEvalOp op;
} ExprEvalOpLookup;
static const void **dispatch_table = NULL;
static ExprEvalOpLookup reverse_dispatch_table[EEOP_LAST];
#define EEO_SWITCH()
#define EEO_CASE(name) CASE_##name:
#define EEO_DISPATCH() goto *((void *) op->opcode)
#define EEO_OPCODE(opcode) ((intptr_t) dispatch_table[opcode])
#else
//--------------- 没有定义EEO_USE_COMPUTED_GOTO
#define EEO_SWITCH() starteval: switch ((ExprEvalOp) op->opcode)
#define EEO_CASE(name) case name:
#define EEO_DISPATCH() goto starteval
#define EEO_OPCODE(opcode) (opcode)
#endif
#define EEO_NEXT() \
do { \
op++; \
EEO_DISPATCH(); \
} while (0)
#define EEO_JUMP(stepno) \
do { \
op = &state->steps[stepno]; \
EEO_DISPATCH(); \
} while (0)
ExprState
解析表达式中运行期状态节点
#define EEO_FLAG_IS_QUAL (1 << 0)
typedef struct ExprState
{
//节点tag
node tag;
//EEO_FLAG_IS_QUAL
uint8 flags;
#define FIELDNO_EXPRSTATE_RESNULL 2
bool resnull;
#define FIELDNO_EXPRSTATE_RESVALUE 3
Datum resvalue;
#define FIELDNO_EXPRSTATE_RESULTSLOT 4
TupleTableSlot *resultslot;
struct ExprEvalStep *steps;
ExprStateEvalFunc evalfunc;
//原始的表达式树,仅用于debugging
Expr *expr;
//evalfunc的私有状态
void *evalfunc_private;
//当前的步数
int steps_len;
//steps数组已分配的长度
int steps_alloc;
//父PlanState节点(如存在)
struct PlanState *parent;
//用于编译PARAM_EXTERN节点
ParamListInfo ext_params;
//
Datum *innermost_caseval;
bool *innermost_casenull;
Datum *innermost_domainval;
bool *innermost_domainnull;
} ExprState;
ExprEvalStep
表达式解析步骤结构体
typedef struct ExprEvalStep
{
intptr_t opcode;
//存储该步骤的结果
Datum *resvalue;
bool *resnull;
uNIOn
{
//用于EEOP_INNER/OUTER/SCAN_FETCHSOME
struct
{
//获取到的属性编号
int last_var;
TupleDesc known_desc;
} fetch;
struct
{
//attnum是常规VAR的attr number - 1
//对于SYSVAR,该值是常规的attr number
int attnum;
Oid vartype;
} var;
struct
{
Var *var;
bool first;
bool slow;
TupleDesc tupdesc;
JunkFilter *junkFilter;
} wholerow;
struct
{
int resultnum;
int attnum;
} assign_var;
struct
{
int resultnum;
} assign_tmp;
struct
{
Datum value;
bool isnull;
} constval;
//对于EEOP_FUNCEXPR_* / NULLIF / DISTINCT
struct
{
//函数的检索数据
FmgrInfo *finfo;
//参数信息等
FunctionCallInfo fcinfo_data;
//无需额外的指向,更快速的访问
PGFunction fn_addr;
int nargs;
} func;
struct
{
bool *anynull;
int jumpdone;
} boolexpr;
struct
{
int jumpdone;
} qualexpr;
struct
{
int jumpdone;
} jump;
struct
{
TupleDesc argdesc;
} nulltest_row;
struct
{
int paramid;
Oid paramtype;
} param;
struct
{
ExecEvalSubroutine paramfunc;
void *paramarg;
int paramid;
Oid paramtype;
} cparam;
struct
{
Datum *value;
bool *isnull;
} casetest;
struct
{
Datum *value;
bool *isnull;
} make_readonly;
struct
{
FmgrInfo *finfo_out;
FunctionCallInfo fcinfo_data_out;
FmgrInfo *finfo_in;
FunctionCallInfo fcinfo_data_in;
} iocoerce;
struct
{
sqlValueFunction *svf;
} sqlvaluefunction;
//EEOP_NEXTVALUEEXPR
struct
{
Oid seqid;
Oid seQtypid;
} nextvalueexpr;
struct
{
Datum *elemvalues;
bool *elemnulls;
int nelems;
Oid elemtype;
int16 elemlength;
bool elembyval;
char elemalign;
bool multidims;
} arrayexpr;
struct
{
ExprState *elemexprstate;
Oid resultelemtype;
struct ArrayMapState *amstate;
} arraycoerce;
struct
{
TupleDesc tupdesc;
Datum *elemvalues;
bool *elemnulls;
} row;
struct
{
FmgrInfo *finfo;
FunctionCallInfo fcinfo_data;
PGFunction fn_addr;
int jumpnull;
int jumpdone;
} rowcompare_step;
struct
{
RowCompareType rctype;
} rowcompare_final;
struct
{
Datum *values;
bool *nulls;
int nelems;
MinMaxOp op;
FmgrInfo *finfo;
FunctionCallInfo fcinfo_data;
} minmax;
struct
{
AttrNumber fieldnum;
Oid resulttype;
TupleDesc argdesc;
} fieldselect;
struct
{
FieldStore *fstore;
TupleDesc *argdesc;
Datum *values;
bool *nulls;
int ncolumns;
} fieldstore;
struct
{
struct ArrayRefState *state;
int off;
bool isupper;
int jumpdone;
} arrayref_subscript;
struct
{
struct ArrayRefState *state;
} arrayref;
struct
{
char *constraintname;
Datum *checkvalue;
bool *checknull;
Oid resulttype;
} domaincheck;
struct
{
ConvertRowtypeExpr *convert;
TupleDesc indesc;
TupleDesc outdesc;
TupleConversionMap *map;
bool initialized;
} convert_rowtype;
struct
{
Oid element_type;
bool useOr;
int16 typlen;
bool typbyval;
char typalign;
FmgrInfo *finfo;
FunctionCallInfo fcinfo_data;
PGFunction fn_addr;
} Scalararrayop;
struct
{
XmlExpr *xexpr;
Datum *named_argvalue;
bool *named_argnull;
Datum *argvalue;
bool *argnull;
} xmlexpr;
struct
{
AggrefExprState *astate;
} aggref;
struct
{
AggState *parent;
List *clauses;
} grouping_func;
struct
{
WindowFuncExprState *wfstate;
} window_func;
struct
{
SubPlanState *sstate;
} subplan;
struct
{
AlternativeSubPlanState *asstate;
} alternative_subplan;
struct
{
AggState *aggstate;
FunctionCallInfo fcinfo_data;
int jumpnull;
} agg_deserialize;
struct
{
bool *nulls;
int nargs;
int jumpnull;
} agg_strict_input_check;
struct
{
AggState *aggstate;
AggStatePerTrans pertrans;
ExprContext *agGContext;
int setno;
int transno;
int setoff;
int jumpnull;
} agg_init_trans;
struct
{
AggState *aggstate;
int setno;
int transno;
int setoff;
int jumpnull;
} agg_strict_trans_check;
struct
{
AggState *aggstate;
AggStatePerTrans pertrans;
ExprContext *aggcontext;
int setno;
int transno;
int setoff;
} agg_trans;
} d;
} ExprEvalStep;
ExprEvalOp
ExprEvalSteps的鉴频器,定义哪个操作将被执行并且联合体ExprEvalStep->d中的哪个struct将被使用.
typedef enum ExprEvalOp
{
//整个表达式已被解析,返回
EEOP_DONE,
//在相应的元组slot上应用了slot_getsomeattrs方法
EEOP_INNER_FETCHSOME,
EEOP_OUTER_FETCHSOME,
EEOP_SCAN_FETCHSOME,
//计算非系统Var变量值
EEOP_INNER_VAR,
EEOP_OUTER_VAR,
EEOP_SCAN_VAR,
//计算系统Var变量值
EEOP_INNER_SYSVAR,
EEOP_OUTER_SYSVAR,
EEOP_SCAN_SYSVAR,
//计算整行Var
EEOP_WHOLEROW,
EEOP_ASSIGN_INNER_VAR,
EEOP_ASSIGN_OUTER_VAR,
EEOP_ASSIGN_SCAN_VAR,
//分配ExprState's resvalue/resnull到该列的resultslot中
EEOP_ASSIGN_TMP,
//同上,应用MakeExpandedObjectReadOnly()
EEOP_ASSIGN_TMP_MAKE_RO,
//解析常量值
EEOP_CONST,
EEOP_FUNCEXPR,
EEOP_FUNCEXPR_STRICT,
EEOP_FUNCEXPR_FUSAGE,
EEOP_FUNCEXPR_STRICT_FUSAGE,
EEOP_BOOL_AND_STEP_FIRST,
EEOP_BOOL_AND_STEP,
EEOP_BOOL_AND_STEP_LAST,
//与布尔OR表达式类似
EEOP_BOOL_OR_STEP_FIRST,
EEOP_BOOL_OR_STEP,
EEOP_BOOL_OR_STEP_LAST,
//解析布尔NOT表达式
EEOP_BOOL_NOT_STEP,
//用于ExecQual()中的BOOL_AND_STEP简化版本
EEOP_QUAL,
//无条件跳转到另外一个步骤
EEOP_JUMP,
//基于当前结果值的条件跳转
EEOP_JUMP_IF_NULL,
EEOP_JUMP_IF_NOT_NULL,
EEOP_JUMP_IF_NOT_TRUE,
//为scalar值执行NULL测试
EEOP_NULLTEST_ISNULL,
EEOP_NULLTEST_ISNOTNULL,
//为行值执行NULL测试
EEOP_NULLTEST_ROWISNULL,
EEOP_NULLTEST_ROWISNOTNULL,
//解析BooleanTest表达式
EEOP_BOOLTEST_IS_TRUE,
EEOP_BOOLTEST_IS_NOT_TRUE,
EEOP_BOOLTEST_IS_FALSE,
EEOP_BOOLTEST_IS_NOT_FALSE,
//解析PARAM_EXEC/EXTERN参数
EEOP_PARAM_EXEC,
EEOP_PARAM_EXTERN,
EEOP_PARAM_CALLBACK,
//返回CaseTestExpr值
EEOP_CASE_TESTVAL,
//对目标值应用MakeExpandedObjectReadOnly()
EEOP_MAKE_READONLY,
//解析各种特殊用途的表达式类型
EEOP_IOCOERCE,
EEOP_DISTINCT,
EEOP_NOT_DISTINCT,
EEOP_NULLIF,
EEOP_SQLVALUEFUNCTION,
EEOP_CURRENTOFEXPR,
EEOP_NEXTVALUEEXPR,
EEOP_ARRAYEXPR,
EEOP_ARRAYCOERCE,
EEOP_ROW,
EEOP_ROWCOMPARE_STEP,
//基于上一步的ROWCOMPARE_STEP操作解析布尔值
EEOP_ROWCOMPARE_FINAL,
//解析GREATEST()和LEAST()
EEOP_MINMAX,
//解析FieldSelect表达式
EEOP_FIELDSELECT,
EEOP_FIELDSTORE_DEFORM,
EEOP_FIELDSTORE_FORM,
//处理数组子脚本.如为NULL则短路表达式为NULL
EEOP_ARRAYREF_SUBSCRIPT,
EEOP_ARRAYREF_OLD,
//为ArrayRef分配118
EEOP_ARRAYREF_ASSIGN,
//为ArrayRef提取表达式计算element/slice
EEOP_ARRAYREF_FETCH,
//为CoerceToDomainValue解析值
EEOP_DOMAIN_TESTVAL,
//解析域 NOT NULL 约束
EEOP_DOMAIN_NOTNULL,
//解析单个域CHECK约束
EEOP_DOMAIN_CHECK,
//解析特殊目的的表达式类型
EEOP_CONVERT_ROWTYPE,
EEOP_SCALARARRAYOP,
EEOP_XMLEXPR,
EEOP_AGGREF,
EEOP_GROUPING_FUNC,
EEOP_WINDOW_FUNC,
EEOP_SUBPLAN,
EEOP_ALTERNATIVE_SUBPLAN,
//聚合相关节点
EEOP_AGG_STRICT_DESERIALIZE,
EEOP_AGG_DESERIALIZE,
EEOP_AGG_STRICT_INPUT_CHECK,
EEOP_AGG_INIT_TRANS,
EEOP_AGG_STRICT_TRANS_CHECK,
EEOP_AGG_PLAIN_TRANS_BYVAL,
EEOP_AGG_PLAIN_TRANS,
EEOP_AGG_ORDERED_TRANS_DATUM,
EEOP_AGG_ORDERED_TRANS_TUPLE,
//不存在的操作,比如用于检测数组长度
EEOP_LAST
} ExprEvalOp;
ExecInitIndexScan
初始化Index Scan运行期状态信息,调用ExecAssignScanProjectionInfo->…->ExecBuildProjectionInfo函数构建投影信息.
IndexScanState *
ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
{
...
ExecInitResultTupleSlotTL(estate, &indexstate->ss.ps);
ExecAssignScanProjectionInfo(&indexstate->ss);
...
}
ExecBuildProjectionInfo
为给定的econtext中的tlist构建ProjectionInfo,并把结果存储在tuple slot中.(调用者必须确保元组slot与此tlist匹配)
其主要逻辑是:
1.初始化
2.如需要,插入EEOP*_FETCHSOME步骤(调用ExecInitExprSlots)
3.遍历targetList,处理targetList(目标列)中的每一个列
3.1.对于”安全”Var则只需要生成EEOP_ASSIGN*_VAR步骤
3.2对于非”安全”VAr,使用常规办法处理列表达式,调用ExecInitExprRec函数处理,并通过ExprEvalPushStep压步骤
4.压入EEOP_DONE步骤
void
ExecAssignScanProjectionInfo(ScanState *node)
{
//扫描节点
Scan *scan = (Scan *) node->ps.plan;
//元组描述符
TupleDesc tupdesc = node->ss_ScanTupleSlot->tts_tupleDescriptor;
//执行ExecConditionalAssignProjectionInfo
ExecConditionalAssignProjectionInfo(&node->ps, tupdesc, scan->scanrelid);
}
void
ExecConditionalAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc,
Index varno)
{
//正好匹配元组类型,则设计为NULL
if (tlist_matches_tupdesc(planstate,
planstate->plan->targetlist,
varno,
inputDesc))
planstate->ps_ProjInfo = NULL;
else
//否则执行ExecAssignProjectionInfo
ExecAssignProjectionInfo(planstate, inputDesc);
}
void
ExecAssignProjectionInfo(PlanState *planstate,
TupleDesc inputDesc)
{
//直接调用ExecBuildProjectionInfo
planstate->ps_ProjInfo =
ExecBuildProjectionInfo(planstate->plan->targetlist,
planstate->ps_ExprContext,
planstate->ps_ResultTupleSlot,
planstate,
inputDesc);
}
ProjectionInfo *
ExecBuildProjectionInfo(List *targetList,
ExprContext *econtext,
TupleTableSlot *slot,
PlanState *parent,
TupleDesc inputDesc)
{
//生成ProjectionInfo节点
ProjectionInfo *projInfo = makeNode(ProjectionInfo);
//表达式状态节点
ExprState *state;
//表达式解析步骤
ExprEvalStep scratch = {0};
//临时变量
ListCell *lc;
//expr上下文
projInfo->pi_exprContext = econtext;
//集成ExprState到ProjectionInfo中,而不需要另外的palloc
projInfo->pi_state.tag.type = T_ExprState;
state = &projInfo->pi_state;
state->expr = (Expr *) targetList;
state->parent = parent;
state->ext_params = NULL;
state->resultslot = slot;
//如需要,插入EEOP_*_FETCHSOME步骤
ExecInitExprSlots(state, (Node *) targetList);
//现在"编译"tlist中的每一个列
foreach(lc, targetList)
{
TargetEntry *tle = lfirst_node(TargetEntry, lc);
Var *variable = NULL;
AttrNumber attnum = 0;
bool isSafeVar = false;
if (tle->expr != NULL &&
IsA(tle->expr, Var) &&
((Var *) tle->expr)->varattno > 0)
{
//非系统Var,但有多安全呢?
variable = (Var *) tle->expr;
attnum = variable->varattno;
if (inputDesc == NULL)
//无法检查,假定是OK的.
isSafeVar = true;
else if (attnum <= inputDesc->natts)
{
//---- 属性编号小于输入的属性个数
Form_pg_attribute attr = TupleDescAttr(inputDesc, attnum - 1);
if (!attr->attisdropped && variable->vartype == attr->atttypid)
{
isSafeVar = true;
}
}
}
if (isSafeVar)
{
//--- 如为安全的Var
//Fast-path: 只需要生成EEOP_ASSIGN_*_VAR步骤即可
switch (variable->varno)
{
case INNER_VAR:
//内关系VAR,从inner节点获取元组
scratch.opcode = EEOP_ASSIGN_INNER_VAR;
break;
case OUTER_VAR:
//从外关系获取元组
scratch.opcode = EEOP_ASSIGN_OUTER_VAR;
break;
//默认: INDEX_VAR
default:
//从正在扫描的关系中获取元组
scratch.opcode = EEOP_ASSIGN_SCAN_VAR;
break;
}
//EEOP_ASSIGN_*_VAR
scratch.d.assign_var.attnum = attnum - 1;
scratch.d.assign_var.resultnum = tle->resno - 1;
ExprEvalPushStep(state, &scratch);
}
else
{
ExecInitExprRec(tle->expr, state,
&state->resvalue, &state->resnull);
//d.assign_tmp.resultnum/attnum
if (get_typlen(exprType((Node *) tle->expr)) == -1)
scratch.opcode = EEOP_ASSIGN_TMP_MAKE_RO;
else
scratch.opcode = EEOP_ASSIGN_TMP;
scratch.d.assign_tmp.resultnum = tle->resno - 1;
ExprEvalPushStep(state, &scratch);
}
}
scratch.opcode = EEOP_DONE;
ExprEvalPushStep(state, &scratch);
ExecReadyExpr(state);
//返回投影信息.
return projInfo;
}
测试脚本
testdb=# select 1+id,c2 from t_expr where id < 3;
调用栈
(gdb) bt
#0 ExecBuildProjectionInfo (targetList=0x1cc7550, econtext=0x1c8f408, slot=0x1c8f710, parent=0x1c8f1f0,
inputDesc=0x7f8386bb6ab8) at execExpr.c:355
#1 0x00000000006e60d5 in ExecAssignProjectionInfo (planstate=0x1c8f1f0, inputDesc=0x7f8386bb6ab8) at execUtils.c:468
#2 0x00000000006e613c in ExecConditionalAssignProjectionInfo (planstate=0x1c8f1f0, inputDesc=0x7f8386bb6ab8, varno=1)
at execUtils.c:493
#3 0x00000000006e23f5 in ExecAssignScanProjectionInfo (node=0x1c8f1f0) at execScan.c:240
#4 0x0000000000700afc in ExecInitIndexScan (node=0x1ba8a18, estate=0x1c8efd8, eflags=16) at nodeIndexscan.c:962
#5 0x00000000006e00cc in ExecInitNode (node=0x1ba8a18, estate=0x1c8efd8, eflags=16) at execProcnode.c:217
#6 0x00000000006d6abe in InitPlan (queryDesc=0x1c94aa8, eflags=16) at execMain.c:1046
#7 0x00000000006d58ad in standard_ExecutorStart (queryDesc=0x1c94aa8, eflags=16) at execMain.c:265
#8 0x00000000006d5649 in ExecutorStart (queryDesc=0x1c94aa8, eflags=0) at execMain.c:147
#9 0x00000000008c18d6 in PortalStart (portal=0x1c15608, params=0x0, eflags=0, snapshot=0x0) at pquery.c:520
#10 0x00000000008bbe1b in exec_simple_query (query_string=0x1ba6d78 "select 1+id,c2 from t_expr where id < 3;")
at postgres.c:1106
#11 0x00000000008c0191 in PostgresMain (argc=1, argv=0x1bd4cb8, dbname=0x1bd4b20 "testdb", username=0x1ba3a98 "xdb")
at postgres.c:4182
#12 0x000000000081e06c in BackendRun (port=0x1bc8ae0) at postmaster.c:4361
#13 0x000000000081d7df in BackendStartup (port=0x1bc8ae0) at postmaster.c:4033
#14 0x0000000000819bd9 in ServerLoop () at postmaster.c:1706
#15 0x000000000081948f in PostmasterMain (argc=1, argv=0x1ba1a50) at postmaster.c:1379
#16 0x0000000000742931 in main (argc=1, argv=0x1ba1a50) at main.c:228
执行跟踪,进入函数ExecBuildProjectionInfo
(gdb) b ExecBuildProjectionInfo
Breakpoint 1 at 0x6c5377: file execExpr.c, line 355.
(gdb) c
Continuing.
Breakpoint 1, ExecBuildProjectionInfo (targetList=0x1c93498, econtext=0x1c883a8, slot=0x1c887c8, parent=0x1c88190,
inputDesc=0x1c884a0) at execExpr.c:355
355 ProjectionInfo *projInfo = makeNode(ProjectionInfo);
(gdb)
1.初始化
(gdb) n
357 ExprEvalStep scratch = {0};
(gdb)
360 projInfo->pi_exprContext = econtext;
(gdb)
362 projInfo->pi_state.tag.type = T_ExprState;
(gdb)
363 state = &projInfo->pi_state;
(gdb)
364 state->expr = (Expr *) targetList;
(gdb)
365 state->parent = parent;
(gdb)
366 state->ext_params = NULL;
(gdb)
368 state->resultslot = slot;
(gdb)
查看相关变量
(gdb) p *state
$1 = {tag = {type = T_ExprState}, flags = 0 '\000', resnull = false, resvalue = 0, resultslot = 0x1c8f710, steps = 0x0,
evalfunc = 0x0, expr = 0x1cc7550, evalfunc_private = 0x0, steps_len = 0, steps_alloc = 0, parent = 0x1c8f1f0,
ext_params = 0x0, innermost_caseval = 0x0, innermost_casenull = 0x0, innermost_domainval = 0x0,
innermost_domainnull = 0x0}
目标列链表
(gdb) p targetList
$2 = (List *) 0x1cc7550
(gdb) p *targetList
$3 = {type = T_List, length = 2, head = 0x1cc7528, tail = 0x1cc75e0}
第一个元素是1+id,第二个元素是c2
(gdb) p *(TargetEntry *)targetList->head->data.ptr_value
$7 = {xpr = {type = T_TargetEntry}, expr = 0x1c9a930, resno = 1, resname = 0xbcf498 "?column?", ressortgroupref = 0,
resorigtbl = 0, resorigcol = 0, resjunk = false}
(gdb) p *(OpExpr *)((TargetEntry *)targetList->head->data.ptr_value)->expr
$9 = {xpr = {type = T_OpExpr}, opno = 551, opfuncid = 177, opresulttype = 23, opretset = false, opcollid = 0,
inputcollid = 0, args = 0x1c9a878, location = 8}
(gdb) p *(Node *)targetList->head->next->data.ptr_value
$10 = {type = T_TargetEntry}
(gdb) p *(TargetEntry *)targetList->head->next->data.ptr_value
$11 = {xpr = {type = T_TargetEntry}, expr = 0x1c9aa40, resno = 2, resname = 0x1ba7a40 "c2", ressortgroupref = 0,
resorigtbl = 237600, resorigcol = 2, resjunk = false}
2.如需要,插入EEOP_*_FETCHSOME步骤(调用ExecInitExprSlots)
(gdb)
371 ExecInitExprSlots(state, (Node *) targetList);
第一个步骤,opcode = 3,即EEOP_SCAN_FETCHSOME
(gdb) n
374 foreach(lc, targetList)
(gdb) p *state
$13 = {tag = {type = T_ExprState}, flags = 0 '\000', resnull = false, resvalue = 0, resultslot = 0x1c8f710,
steps = 0x1c8f868, evalfunc = 0x0, expr = 0x1cc7550, evalfunc_private = 0x0, steps_len = 1, steps_alloc = 16,
parent = 0x1c8f1f0, ext_params = 0x0, innermost_caseval = 0x0, innermost_casenull = 0x0, innermost_domainval = 0x0,
innermost_domainnull = 0x0}
(gdb) p state->steps[0]
$14 = {opcode = 3, resvalue = 0x0, resnull = 0x0, d = {fetch = {last_var = 2, known_desc = 0x0}, var = {attnum = 2,
vartype = 0}, wholerow = {var = 0x2, first = false, slow = false, tupdesc = 0x0, junkFilter = 0x0}, assign_var = {
resultnum = 2, attnum = 0}, assign_tmp = {resultnum = 2}, constval = {value = 2, isnull = false}, func = {
finfo = 0x2, fcinfo_data = 0x0, fn_addr = 0x0, nargs = 0}, boolexpr = {anynull = 0x2, jumpdone = 0}, qualexpr = {
jumpdone = 2}, jump = {jumpdone = 2}, nulltest_row = {argdesc = 0x2}, param = {paramid = 2, paramtype = 0}, cparam = {
paramfunc = 0x2, paramarg = 0x0, paramid = 0, paramtype = 0}, casetest = {value = 0x2, isnull = 0x0},
make_readonly = {value = 0x2, isnull = 0x0}, iocoerce = {finfo_out = 0x2, fcinfo_data_out = 0x0, finfo_in = 0x0,
fcinfo_data_in = 0x0}, sqlvaluefunction = {svf = 0x2}, nextvalueexpr = {seqid = 2, seqtypid = 0}, arrayexpr = {
elemvalues = 0x2, elemnulls = 0x0, nelems = 0, elemtype = 0, elemlength = 0, elembyval = false, elemalign = 0 '\000',
multidims = false}, arraycoerce = {elemexprstate = 0x2, resultelemtype = 0, amstate = 0x0}, row = {tupdesc = 0x2,
elemvalues = 0x0, elemnulls = 0x0}, rowcompare_step = {finfo = 0x2, fcinfo_data = 0x0, fn_addr = 0x0, jumpnull = 0,
jumpdone = 0}, rowcompare_final = {rctype = ROWCOMPARE_LE}, minmax = {values = 0x2, nulls = 0x0, nelems = 0,
op = IS_GREATEST, finfo = 0x0, fcinfo_data = 0x0}, fieldselect = {fieldnum = 2, resulttype = 0, argdesc = 0x0},
fieldstore = {fstore = 0x2, argdesc = 0x0, values = 0x0, nulls = 0x0, ncolumns = 0}, arrayref_subscript = {state = 0x2,
off = 0, isupper = false, jumpdone = 0}, arrayref = {state = 0x2}, domaincheck = {
constraintname = 0x2 <Address 0x2 out of bounds>, checkvalue = 0x0, checknull = 0x0, resulttype = 0},
convert_rowtype = {convert = 0x2, indesc = 0x0, outdesc = 0x0, map = 0x0, initialized = false}, scalararrayop = {
element_type = 2, useOr = false, typlen = 0, typbyval = false, typalign = 0 '\000', finfo = 0x0, fcinfo_data = 0x0,
fn_addr = 0x0}, xmlexpr = {xexpr = 0x2, named_argvalue = 0x0, named_argnull = 0x0, argvalue = 0x0, argnull = 0x0},
aggref = {astate = 0x2}, grouping_func = {parent = 0x2, clauses = 0x0}, window_func = {wfstate = 0x2}, subplan = {
sstate = 0x2}, alternative_subplan = {asstate = 0x2}, agg_deserialize = {aggstate = 0x2, fcinfo_data = 0x0,
jumpnull = 0}, agg_strict_input_check = {nulls = 0x2, nargs = 0, jumpnull = 0}, agg_init_trans = {aggstate = 0x2,
pertrans = 0x0, aggcontext = 0x0, setno = 0, transno = 0, setoff = 0, jumpnull = 0}, agg_strict_trans_check = {
aggstate = 0x2, setno = 0, transno = 0, setoff = 0, jumpnull = 0}, agg_trans = {aggstate = 0x2, pertrans = 0x0,
aggcontext = 0x0, setno = 0, transno = 0, setoff = 0}}}
(gdb)
3.遍历targetList,处理targetList(目标列)中的每一个列
3.1.对于”安全”Var则只需要生成EEOPASSIGN*_VAR步骤
3.2.对于非”安全”VAr,使用常规办法处理列表达式,调用ExecInitExprRec函数处理,并通过ExprEvalPushStep压步骤
(gdb) n
376 TargetEntry *tle = lfirst_node(TargetEntry, lc);
(gdb)
377 Var *variable = NULL;
(gdb)
378 AttrNumber attnum = 0;
(gdb)
379 bool isSafeVar = false;
(gdb)
389 if (tle->expr != NULL &&
(gdb)
390 IsA(tle->expr, Var) &&
(gdb)
389 if (tle->expr != NULL &&
(gdb)
415 if (isSafeVar)
(gdb) p *tle
$15 = {xpr = {type = T_TargetEntry}, expr = 0x1c9a930, resno = 1, resname = 0xbcf498 "?column?", ressortgroupref = 0,
resorigtbl = 0, resorigcol = 0, resjunk = false}
(gdb) n
452 ExecInitExprRec(tle->expr, state,
(gdb)
进入ExecInitExprRec,Node节点为OpExpr,执行ExprEvalPushStep压入步骤中
(gdb) step
ExecInitExprRec (node=0x1c9a930, state=0x1c8f7d8, resv=0x1c8f7e0, resnull=0x1c8f7dd) at execExpr.c:645
645 ExprEvalStep scratch = {0};
(gdb) n
648 check_stack_depth();
(gdb)
651 Assert(resv != NULL && resnull != NULL);
(gdb)
652 scratch.resvalue = resv;
(gdb)
653 scratch.resnull = resnull;
(gdb)
656 switch (nodeTag(node))
(gdb)
891 OpExpr *op = (OpExpr *) node;
(gdb) p *node
$16 = {type = T_OpExpr}
(gdb) n
893 ExecInitFunc(&scratch, node,
(gdb)
896 ExprEvalPushStep(state, &scratch);
(gdb)
897 break;
(gdb)
2122 }
(gdb)
ExecBuildProjectionInfo (targetList=0x1cc7550, econtext=0x1c8f408, slot=0x1c8f710, parent=0x1c8f1f0,
inputDesc=0x7f8386bb6ab8) at execExpr.c:459
459 if (get_typlen(exprType((Node *) tle->expr)) == -1)
(gdb)
462 scratch.opcode = EEOP_ASSIGN_TMP;
(gdb)
ExecInitExprRec调用完毕,增加了2个步骤,分别是:
1.opcode = 6,即EEOP_SCAN_VAR
2.opcode = 18,即EEOP_FUNCEXPR_STRICT
(gdb) p *state
$17 = {tag = {type = T_ExprState}, flags = 0 '\000', resnull = false, resvalue = 0, resultslot = 0x1c8f710,
steps = 0x1c8f868, evalfunc = 0x0, expr = 0x1cc7550, evalfunc_private = 0x0, steps_len = 3, steps_alloc = 16,
parent = 0x1c8f1f0, ext_params = 0x0, innermost_caseval = 0x0, innermost_casenull = 0x0, innermost_domainval = 0x0,
innermost_domainnull = 0x0}
(gdb) p state->steps[1]
$18 = {opcode = 6, resvalue = 0x1c8fd00, resnull = 0x1c90019, d = {fetch = {last_var = 0, known_desc = 0x0}, var = {
attnum = 0, vartype = 23}, wholerow = {var = 0x1700000000, first = false, slow = false, tupdesc = 0x0,
junkFilter = 0x0}, assign_var = {resultnum = 0, attnum = 23}, assign_tmp = {resultnum = 0}, constval = {
value = 98784247808, isnull = false}, func = {finfo = 0x1700000000, fcinfo_data = 0x0, fn_addr = 0x0, nargs = 0},
boolexpr = {anynull = 0x1700000000, jumpdone = 0}, qualexpr = {jumpdone = 0}, jump = {jumpdone = 0}, nulltest_row = {
argdesc = 0x1700000000}, param = {paramid = 0, paramtype = 23}, cparam = {paramfunc = 0x1700000000, paramarg = 0x0,
paramid = 0, paramtype = 0}, casetest = {value = 0x1700000000, isnull = 0x0}, make_readonly = {value = 0x1700000000,
isnull = 0x0}, iocoerce = {finfo_out = 0x1700000000, fcinfo_data_out = 0x0, finfo_in = 0x0, fcinfo_data_in = 0x0},
sqlvaluefunction = {svf = 0x1700000000}, nextvalueexpr = {seqid = 0, seqtypid = 23}, arrayexpr = {
elemvalues = 0x1700000000, elemnulls = 0x0, nelems = 0, elemtype = 0, elemlength = 0, elembyval = false,
elemalign = 0 '\000', multidims = false}, arraycoerce = {elemexprstate = 0x1700000000, resultelemtype = 0,
amstate = 0x0}, row = {tupdesc = 0x1700000000, elemvalues = 0x0, elemnulls = 0x0}, rowcompare_step = {
finfo = 0x1700000000, fcinfo_data = 0x0, fn_addr = 0x0, jumpnull = 0, jumpdone = 0}, rowcompare_final = {rctype = 0},
minmax = {values = 0x1700000000, nulls = 0x0, nelems = 0, op = IS_GREATEST, finfo = 0x0, fcinfo_data = 0x0},
fieldselect = {fieldnum = 0, resulttype = 23, argdesc = 0x0}, fieldstore = {fstore = 0x1700000000, argdesc = 0x0,
values = 0x0, nulls = 0x0, ncolumns = 0}, arrayref_subscript = {state = 0x1700000000, off = 0, isupper = false,
jumpdone = 0}, arrayref = {state = 0x1700000000}, domaincheck = {
constraintname = 0x1700000000 <Address 0x1700000000 out of bounds>, checkvalue = 0x0, checknull = 0x0,
resulttype = 0}, convert_rowtype = {convert = 0x1700000000, indesc = 0x0, outdesc = 0x0, map = 0x0,
initialized = false}, scalararrayop = {element_type = 0, useOr = 23, typlen = 0, typbyval = false,
typalign = 0 '\000', finfo = 0x0, fcinfo_data = 0x0, fn_addr = 0x0}, xmlexpr = {xexpr = 0x1700000000,
named_argvalue = 0x0, named_argnull = 0x0, argvalue = 0x0, argnull = 0x0}, aggref = {astate = 0x1700000000},
grouping_func = {parent = 0x1700000000, clauses = 0x0}, window_func = {wfstate = 0x1700000000}, subplan = {
sstate = 0x1700000000}, alternative_subplan = {asstate = 0x1700000000}, agg_deserialize = {aggstate = 0x1700000000,
fcinfo_data = 0x0, jumpnull = 0}, agg_strict_input_check = {nulls = 0x1700000000, nargs = 0, jumpnull = 0},
agg_init_trans = {aggstate = 0x1700000000, pertrans = 0x0, aggcontext = 0x0, setno = 0, transno = 0, setoff = 0,
jumpnull = 0}, agg_strict_trans_check = {aggstate = 0x1700000000, setno = 0, transno = 0, setoff = 0, jumpnull = 0},
---Type <return> to continue, or q <return> to quit---
agg_trans = {aggstate = 0x1700000000, pertrans = 0x0, aggcontext = 0x0, setno = 0, transno = 0, setoff = 0}}}
(gdb) p state->steps[2]
$19 = {opcode = 18, resvalue = 0x1c8f7e0, resnull = 0x1c8f7dd, d = {fetch = {last_var = 29949056, known_desc = 0x1c8fcd8},
var = {attnum = 29949056, vartype = 0}, wholerow = {var = 0x1c8fc80, first = 216, slow = 252,
tupdesc = 0x93D60c <int4pl>, junkFilter = 0x2}, assign_var = {resultnum = 29949056, attnum = 0}, assign_tmp = {
resultnum = 29949056}, constval = {value = 29949056, isnull = 216}, func = {finfo = 0x1c8fc80,
fcinfo_data = 0x1c8fcd8, fn_addr = 0x93d60c <int4pl>, nargs = 2}, boolexpr = {anynull = 0x1c8fc80,
jumpdone = 29949144}, qualexpr = {jumpdone = 29949056}, jump = {jumpdone = 29949056}, nulltest_row = {
argdesc = 0x1c8fc80}, param = {paramid = 29949056, paramtype = 0}, cparam = {paramfunc = 0x1c8fc80,
paramarg = 0x1c8fcd8, paramid = 9688588, paramtype = 0}, casetest = {value = 0x1c8fc80, isnull = 0x1c8fcd8},
make_readonly = {value = 0x1c8fc80, isnull = 0x1c8fcd8}, iocoerce = {finfo_out = 0x1c8fc80,
fcinfo_data_out = 0x1c8fcd8, finfo_in = 0x93d60c <int4pl>, fcinfo_data_in = 0x2}, sqlvaluefunction = {
svf = 0x1c8fc80}, nextvalueexpr = {seqid = 29949056, seqtypid = 0}, arrayexpr = {elemvalues = 0x1c8fc80,
elemnulls = 0x1c8fcd8, nelems = 9688588, elemtype = 0, elemlength = 2, elembyval = false, elemalign = 0 '\000',
multidims = false}, arraycoerce = {elemexprstate = 0x1c8fc80, resultelemtype = 29949144,
amstate = 0x93d60c <int4pl>}, row = {tupdesc = 0x1c8fc80, elemvalues = 0x1c8fcd8, elemnulls = 0x93d60c <int4pl>},
rowcompare_step = {finfo = 0x1c8fc80, fcinfo_data = 0x1c8fcd8, fn_addr = 0x93d60c <int4pl>, jumpnull = 2,
jumpdone = 0}, rowcompare_final = {rctype = 29949056}, minmax = {values = 0x1c8fc80, nulls = 0x1c8fcd8,
nelems = 9688588, op = IS_GREATEST, finfo = 0x2, fcinfo_data = 0x0}, fieldselect = {fieldnum = -896, resulttype = 0,
argdesc = 0x1c8fcd8}, fieldstore = {fstore = 0x1c8fc80, argdesc = 0x1c8fcd8, values = 0x93d60c <int4pl>, nulls = 0x2,
ncolumns = 0}, arrayref_subscript = {state = 0x1c8fc80, off = 29949144, isupper = false, jumpdone = 9688588},
arrayref = {state = 0x1c8fc80}, domaincheck = {constraintname = 0x1c8fc80 "\f֓", checkvalue = 0x1c8fcd8,
checknull = 0x93d60c <int4pl>, resulttype = 2}, convert_rowtype = {convert = 0x1c8fc80, indesc = 0x1c8fcd8,
outdesc = 0x93d60c <int4pl>, map = 0x2, initialized = false}, scalararrayop = {element_type = 29949056,
useOr = false, typlen = 0, typbyval = 216, typalign = -4 '\374', finfo = 0x93d60c <int4pl>, fcinfo_data = 0x2,
fn_addr = 0x0}, xmlexpr = {xexpr = 0x1c8fc80, named_argvalue = 0x1c8fcd8, named_argnull = 0x93d60c <int4pl>,
argvalue = 0x2, argnull = 0x0}, aggref = {astate = 0x1c8fc80}, grouping_func = {parent = 0x1c8fc80,
clauses = 0x1c8fcd8}, window_func = {wfstate = 0x1c8fc80}, subplan = {sstate = 0x1c8fc80}, alternative_subplan = {
asstate = 0x1c8fc80}, agg_deserialize = {aggstate = 0x1c8fc80, fcinfo_data = 0x1c8fcd8, jumpnull = 9688588},
---Type <return> to continue, or q <return> to quit---
agg_strict_input_check = {nulls = 0x1c8fc80, nargs = 29949144, jumpnull = 0}, agg_init_trans = {aggstate = 0x1c8fc80,
pertrans = 0x1c8fcd8, aggcontext = 0x93d60c <int4pl>, setno = 2, transno = 0, setoff = 0, jumpnull = 0},
agg_strict_trans_check = {aggstate = 0x1c8fc80, setno = 29949144, transno = 0, setoff = 9688588, jumpnull = 0},
agg_trans = {aggstate = 0x1c8fc80, pertrans = 0x1c8fcd8, aggcontext = 0x93d60c <int4pl>, setno = 2, transno = 0,
setoff = 0}}}
(gdb)
压入对应该表达式列的编号,opcode = 14,即EEOP_ASSIGN_TMP
(gdb) n
463 scratch.d.assign_tmp.resultnum = tle->resno - 1;
(gdb)
464 ExprEvalPushStep(state, &scratch);
(gdb)
(gdb)
374 foreach(lc, targetList)
(gdb) p *state
$20 = {tag = {type = T_ExprState}, flags = 0 '\000', resnull = false, resvalue = 0, resultslot = 0x1c8f710,
steps = 0x1c8f868, evalfunc = 0x0, expr = 0x1cc7550, evalfunc_private = 0x0, steps_len = 4, steps_alloc = 16,
parent = 0x1c8f1f0, ext_params = 0x0, innermost_caseval = 0x0, innermost_casenull = 0x0, innermost_domainval = 0x0,
innermost_domainnull = 0x0}
(gdb) p state->steps[3]
$21 = {opcode = 14, resvalue = 0x0, resnull = 0x0, d = {fetch = {last_var = 0, known_desc = 0x0}, var = {attnum = 0,
vartype = 0}, wholerow = {var = 0x0, first = false, slow = false, tupdesc = 0x0, junkFilter = 0x0}, assign_var = {
resultnum = 0, attnum = 0}, assign_tmp = {resultnum = 0}, constval = {value = 0, isnull = false}, func = {
finfo = 0x0, fcinfo_data = 0x0, fn_addr = 0x0, nargs = 0}, boolexpr = {anynull = 0x0, jumpdone = 0}, qualexpr = {
jumpdone = 0}, jump = {jumpdone = 0}, nulltest_row = {argdesc = 0x0}, param = {paramid = 0, paramtype = 0}, cparam = {
paramfunc = 0x0, paramarg = 0x0, paramid = 0, paramtype = 0}, casetest = {value = 0x0, isnull = 0x0},
make_readonly = {value = 0x0, isnull = 0x0}, iocoerce = {finfo_out = 0x0, fcinfo_data_out = 0x0, finfo_in = 0x0,
fcinfo_data_in = 0x0}, sqlvaluefunction = {svf = 0x0}, nextvalueexpr = {seqid = 0, seqtypid = 0}, arrayexpr = {
elemvalues = 0x0, elemnulls = 0x0, nelems = 0, elemtype = 0, elemlength = 0, elembyval = false, elemalign = 0 '\000',
multidims = false}, arraycoerce = {elemexprstate = 0x0, resultelemtype = 0, amstate = 0x0}, row = {tupdesc = 0x0,
elemvalues = 0x0, elemnulls = 0x0}, rowcompare_step = {finfo = 0x0, fcinfo_data = 0x0, fn_addr = 0x0, jumpnull = 0,
jumpdone = 0}, rowcompare_final = {rctype = 0}, minmax = {values = 0x0, nulls = 0x0, nelems = 0, op = IS_GREATEST,
finfo = 0x0, fcinfo_data = 0x0}, fieldselect = {fieldnum = 0, resulttype = 0, argdesc = 0x0}, fieldstore = {
fstore = 0x0, argdesc = 0x0, values = 0x0, nulls = 0x0, ncolumns = 0}, arrayref_subscript = {state = 0x0, off = 0,
isupper = false, jumpdone = 0}, arrayref = {state = 0x0}, domaincheck = {constraintname = 0x0, checkvalue = 0x0,
checknull = 0x0, resulttype = 0}, convert_rowtype = {convert = 0x0, indesc = 0x0, outdesc = 0x0, map = 0x0,
initialized = false}, scalararrayop = {element_type = 0, useOr = false, typlen = 0, typbyval = false,
typalign = 0 '\000', finfo = 0x0, fcinfo_data = 0x0, fn_addr = 0x0}, xmlexpr = {xexpr = 0x0, named_argvalue = 0x0,
named_argnull = 0x0, argvalue = 0x0, argnull = 0x0}, aggref = {astate = 0x0}, grouping_func = {parent = 0x0,
clauses = 0x0}, window_func = {wfstate = 0x0}, subplan = {sstate = 0x0}, alternative_subplan = {asstate = 0x0},
agg_deserialize = {aggstate = 0x0, fcinfo_data = 0x0, jumpnull = 0}, agg_strict_input_check = {nulls = 0x0, nargs = 0,
jumpnull = 0}, agg_init_trans = {aggstate = 0x0, pertrans = 0x0, aggcontext = 0x0, setno = 0, transno = 0,
setoff = 0, jumpnull = 0}, agg_strict_trans_check = {aggstate = 0x0, setno = 0, transno = 0, setoff = 0,
jumpnull = 0}, agg_trans = {aggstate = 0x0, pertrans = 0x0, aggcontext = 0x0, setno = 0, transno = 0, setoff = 0}}}
(gdb)
继续处理下一个列,这是一个”安全”列,压入EEOP_ASSIGN_SCAN_VAR步骤
(gdb) n
376 TargetEntry *tle = lfirst_node(TargetEntry, lc);
(gdb)
377 Var *variable = NULL;
(gdb) p *tle
$22 = {xpr = {type = T_TargetEntry}, expr = 0x1c9aa40, resno = 2, resname = 0x1ba7a40 "c2", ressortgroupref = 0,
resorigtbl = 237600, resorigcol = 2, resjunk = false}
(gdb) n
378 AttrNumber attnum = 0;
(gdb)
379 bool isSafeVar = false;
(gdb)
389 if (tle->expr != NULL &&
(gdb)
390 IsA(tle->expr, Var) &&
(gdb)
389 if (tle->expr != NULL &&
(gdb)
391 ((Var *) tle->expr)->varattno > 0)
(gdb)
390 IsA(tle->expr, Var) &&
(gdb)
394 variable = (Var *) tle->expr;
(gdb)
395 attnum = variable->varattno;
(gdb)
397 if (inputDesc == NULL)
(gdb)
399 else if (attnum <= inputDesc->natts)
(gdb)
401 Form_pg_attribute attr = TupleDescAttr(inputDesc, attnum - 1);
(gdb)
408 if (!attr->attisdropped && variable->vartype == attr->atttypid)
(gdb)
410 isSafeVar = true;
(gdb)
415 if (isSafeVar)
(gdb)
418 switch (variable->varno)
(gdb)
434 scratch.opcode = EEOP_ASSIGN_SCAN_VAR;
(gdb)
435 break;
(gdb)
438 scratch.d.assign_var.attnum = attnum - 1;
(gdb)
439 scratch.d.assign_var.resultnum = tle->resno - 1;
(gdb)
440 ExprEvalPushStep(state, &scratch);
(gdb) p *state
$23 = {tag = {type = T_ExprState}, flags = 0 '\000', resnull = false, resvalue = 0, resultslot = 0x1c8f710,
steps = 0x1c8f868, evalfunc = 0x0, expr = 0x1cc7550, evalfunc_private = 0x0, steps_len = 4, steps_alloc = 16,
parent = 0x1c8f1f0, ext_params = 0x0, innermost_caseval = 0x0, innermost_casenull = 0x0, innermost_domainval = 0x0,
innermost_domainnull = 0x0}
(gdb) n
374 foreach(lc, targetList)
(gdb) p *state
$24 = {tag = {type = T_ExprState}, flags = 0 '\000', resnull = false, resvalue = 0, resultslot = 0x1c8f710,
steps = 0x1c8f868, evalfunc = 0x0, expr = 0x1cc7550, evalfunc_private = 0x0, steps_len = 5, steps_alloc = 16,
parent = 0x1c8f1f0, ext_params = 0x0, innermost_caseval = 0x0, innermost_casenull = 0x0, innermost_domainval = 0x0,
innermost_domainnull = 0x0}
(gdb) p state->steps[4]
$25 = {opcode = 13, resvalue = 0x0, resnull = 0x0, d = {fetch = {last_var = 1, known_desc = 0x0}, var = {attnum = 1,
vartype = 1}, wholerow = {var = 0x100000001, first = false, slow = false, tupdesc = 0x0, junkFilter = 0x0},
assign_var = {resultnum = 1, attnum = 1}, assign_tmp = {resultnum = 1}, constval = {value = 4294967297,
isnull = false}, func = {finfo = 0x100000001, fcinfo_data = 0x0, fn_addr = 0x0, nargs = 0}, boolexpr = {
anynull = 0x100000001, jumpdone = 0}, qualexpr = {jumpdone = 1}, jump = {jumpdone = 1}, nulltest_row = {
argdesc = 0x100000001}, param = {paramid = 1, paramtype = 1}, cparam = {paramfunc = 0x100000001, paramarg = 0x0,
paramid = 0, paramtype = 0}, casetest = {value = 0x100000001, isnull = 0x0}, make_readonly = {value = 0x100000001,
isnull = 0x0}, iocoerce = {finfo_out = 0x100000001, fcinfo_data_out = 0x0, finfo_in = 0x0, fcinfo_data_in = 0x0},
sqlvaluefunction = {svf = 0x100000001}, nextvalueexpr = {seqid = 1, seqtypid = 1}, arrayexpr = {
elemvalues = 0x100000001, elemnulls = 0x0, nelems = 0, elemtype = 0, elemlength = 0, elembyval = false,
elemalign = 0 '\000', multidims = false}, arraycoerce = {elemexprstate = 0x100000001, resultelemtype = 0,
amstate = 0x0}, row = {tupdesc = 0x100000001, elemvalues = 0x0, elemnulls = 0x0}, rowcompare_step = {
finfo = 0x100000001, fcinfo_data = 0x0, fn_addr = 0x0, jumpnull = 0, jumpdone = 0}, rowcompare_final = {
rctype = ROWCOMPARE_LT}, minmax = {values = 0x100000001, nulls = 0x0, nelems = 0, op = IS_GREATEST, finfo = 0x0,
fcinfo_data = 0x0}, fieldselect = {fieldnum = 1, resulttype = 1, argdesc = 0x0}, fieldstore = {fstore = 0x100000001,
argdesc = 0x0, values = 0x0, nulls = 0x0, ncolumns = 0}, arrayref_subscript = {state = 0x100000001, off = 0,
isupper = false, jumpdone = 0}, arrayref = {state = 0x100000001}, domaincheck = {
constraintname = 0x100000001 <Address 0x100000001 out of bounds>, checkvalue = 0x0, checknull = 0x0, resulttype = 0},
convert_rowtype = {convert = 0x100000001, indesc = 0x0, outdesc = 0x0, map = 0x0, initialized = false},
scalararrayop = {element_type = 1, useOr = true, typlen = 0, typbyval = false, typalign = 0 '\000', finfo = 0x0,
fcinfo_data = 0x0, fn_addr = 0x0}, xmlexpr = {xexpr = 0x100000001, named_argvalue = 0x0, named_argnull = 0x0,
argvalue = 0x0, argnull = 0x0}, aggref = {astate = 0x100000001}, grouping_func = {parent = 0x100000001,
clauses = 0x0}, window_func = {wfstate = 0x100000001}, subplan = {sstate = 0x100000001}, alternative_subplan = {
asstate = 0x100000001}, agg_deserialize = {aggstate = 0x100000001, fcinfo_data = 0x0, jumpnull = 0},
agg_strict_input_check = {nulls = 0x100000001, nargs = 0, jumpnull = 0}, agg_init_trans = {aggstate = 0x100000001,
pertrans = 0x0, aggcontext = 0x0, setno = 0, transno = 0, setoff = 0, jumpnull = 0}, agg_strict_trans_check = {
aggstate = 0x100000001, setno = 0, transno = 0, setoff = 0, jumpnull = 0}, agg_trans = {aggstate = 0x100000001,
---Type <return> to continue, or q <return> to quit---
pertrans = 0x0, aggcontext = 0x0, setno = 0, transno = 0, setoff = 0}}}
(gdb)
4.压入EEOP_DONE步骤
(gdb) n
468 scratch.opcode = EEOP_DONE;
(gdb)
469 ExprEvalPushStep(state, &scratch);
(gdb)
471 ExecReadyExpr(state);
(gdb) p state->steps[5]
$26 = {opcode = 0, resvalue = 0x0, resnull = 0x0, d = {fetch = {last_var = 1, known_desc = 0x0}, var = {attnum = 1,
vartype = 1}, wholerow = {var = 0x100000001, first = false, slow = false, tupdesc = 0x0, junkFilter = 0x0},
assign_var = {resultnum = 1, attnum = 1}, assign_tmp = {resultnum = 1}, constval = {value = 4294967297,
isnull = false}, func = {finfo = 0x100000001, fcinfo_data = 0x0, fn_addr = 0x0, nargs = 0}, boolexpr = {
anynull = 0x100000001, jumpdone = 0}, qualexpr = {jumpdone = 1}, jump = {jumpdone = 1}, nulltest_row = {
argdesc = 0x100000001}, param = {paramid = 1, paramtype = 1}, cparam = {paramfunc = 0x100000001, paramarg = 0x0,
paramid = 0, paramtype = 0}, casetest = {value = 0x100000001, isnull = 0x0}, make_readonly = {value = 0x100000001,
isnull = 0x0}, iocoerce = {finfo_out = 0x100000001, fcinfo_data_out = 0x0, finfo_in = 0x0, fcinfo_data_in = 0x0},
sqlvaluefunction = {svf = 0x100000001}, nextvalueexpr = {seqid = 1, seqtypid = 1}, arrayexpr = {
elemvalues = 0x100000001, elemnulls = 0x0, nelems = 0, elemtype = 0, elemlength = 0, elembyval = false,
elemalign = 0 '\000', multidims = false}, arraycoerce = {elemexprstate = 0x100000001, resultelemtype = 0,
amstate = 0x0}, row = {tupdesc = 0x100000001, elemvalues = 0x0, elemnulls = 0x0}, rowcompare_step = {
finfo = 0x100000001, fcinfo_data = 0x0, fn_addr = 0x0, jumpnull = 0, jumpdone = 0}, rowcompare_final = {
rctype = ROWCOMPARE_LT}, minmax = {values = 0x100000001, nulls = 0x0, nelems = 0, op = IS_GREATEST, finfo = 0x0,
fcinfo_data = 0x0}, fieldselect = {fieldnum = 1, resulttype = 1, argdesc = 0x0}, fieldstore = {fstore = 0x100000001,
argdesc = 0x0, values = 0x0, nulls = 0x0, ncolumns = 0}, arrayref_subscript = {state = 0x100000001, off = 0,
isupper = false, jumpdone = 0}, arrayref = {state = 0x100000001}, domaincheck = {
constraintname = 0x100000001 <Address 0x100000001 out of bounds>, checkvalue = 0x0, checknull = 0x0, resulttype = 0},
convert_rowtype = {convert = 0x100000001, indesc = 0x0, outdesc = 0x0, map = 0x0, initialized = false},
scalararrayop = {element_type = 1, useOr = true, typlen = 0, typbyval = false, typalign = 0 '\000', finfo = 0x0,
fcinfo_data = 0x0, fn_addr = 0x0}, xmlexpr = {xexpr = 0x100000001, named_argvalue = 0x0, named_argnull = 0x0,
argvalue = 0x0, argnull = 0x0}, aggref = {astate = 0x100000001}, grouping_func = {parent = 0x100000001,
clauses = 0x0}, window_func = {wfstate = 0x100000001}, subplan = {sstate = 0x100000001}, alternative_subplan = {
asstate = 0x100000001}, agg_deserialize = {aggstate = 0x100000001, fcinfo_data = 0x0, jumpnull = 0},
agg_strict_input_check = {nulls = 0x100000001, nargs = 0, jumpnull = 0}, agg_init_trans = {aggstate = 0x100000001,
pertrans = 0x0, aggcontext = 0x0, setno = 0, transno = 0, setoff = 0, jumpnull = 0}, agg_strict_trans_check = {
aggstate = 0x100000001, setno = 0, transno = 0, setoff = 0, jumpnull = 0}, agg_trans = {aggstate = 0x100000001,
---Type <return> to continue, or q <return> to quit---
pertrans = 0x0, aggcontext = 0x0, setno = 0, transno = 0, setoff = 0}}}
(gdb)
结束调用
(gdb) n
473 return projInfo;
(gdb)
474 }
(gdb)
ExecAssignProjectionInfo (planstate=0x1c8f1f0, inputDesc=0x7f8386bb6ab8) at execUtils.c:467
467 planstate->ps_ProjInfo =
(gdb)
以上是“PostgreSQL如何构建表达式解析”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注编程网数据库频道!
--结束END--
本文标题: PostgreSQL如何构建表达式解析
本文链接: https://lsjlt.com/news/63690.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-10-23
2024-10-22
2024-10-22
2024-10-22
2024-10-22
2024-10-22
2024-10-22
2024-10-22
2024-10-22
2024-10-22
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0