怎么使用PostgreSQL中ExecInitExprRec函数
本篇内容主要讲解“怎么使用PostgreSQL中ExecInitExprRec函数”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么使用PostgreSQL中ExecInitExprRec函数”吧!
EEO_XXX宏定义
opcode分发器宏定义
/**Macrosforopcodedispatch.*opcode分发器宏定义**EEO_SWITCH-justhidestheswitchifnotinuse.*EEO_SWITCH-如未使用,则隐藏switch**EEO_CASE-labelstheimplementationofnamedexpressionsteptype.*EEO_CASE-标签化已命名的表达式步骤类型的实现**EEO_DISPATCH-jumptotheimplementationofthesteptypefor'op'.*EEO_DISPATCH-跳到'op'指定的步骤类型的实现**EEO_OPCODE-computeopcoderequiredbyusedexpressionevaluationmethod.*-通过请求的表达式解析方法计算opcode**EEO_NEXT-increment'op'andjumptocorrectnextsteptype.*-'op'++并跳转到下一个步骤类型**EEO_JUMP-jumptothespecifiedstepnumberwithinthecurrentexpression.*EEO_JUMP-在当前表达式中跳转到指定的步骤编号*/#ifdefined(EEO_USE_COMPUTED_GOTO)//---------------定义了EEO_USE_COMPUTED_GOTO/*structforjumptarget->opcodelookuptable*///跳转target->opcode搜索表结构体typedefstructExprEvalOpLookup{constvoid*opcode;ExprEvalOpop;}ExprEvalOpLookup;/*tomakedispatch_tableaccessibleoutsideExecInterpExpr()*/staticconstvoid**dispatch_table=NULL;/*jumptarget->opcodelookuptable*/staticExprEvalOpLookupreverse_dispatch_table[EEOP_LAST];#defineEEO_SWITCH()#defineEEO_CASE(name)CASE_##name:#defineEEO_DISPATCH()goto*((void*)op->opcode)#defineEEO_OPCODE(opcode)((intptr_t)dispatch_table[opcode])#else/*!EEO_USE_COMPUTED_GOTO*///---------------没有定义EEO_USE_COMPUTED_GOTO#defineEEO_SWITCH()starteval:switch((ExprEvalOp)op->opcode)#defineEEO_CASE(name)casename:#defineEEO_DISPATCH()gotostarteval#defineEEO_OPCODE(opcode)(opcode)#endif/*EEO_USE_COMPUTED_GOTO*/#defineEEO_NEXT()\do{\op++;\EEO_DISPATCH();\}while(0)#defineEEO_JUMP(stepno)\do{\op=&state->steps[stepno];\EEO_DISPATCH();\}while(0)
ExprState
解析表达式中运行期状态节点
/*BitsinExprState->flags(seealsoexecExpr.hforprivateflagbits):*//*expressionisforusewithExecQual()*/#defineEEO_FLAG_IS_QUAL(1<<0)typedefstructExprState{//节点tagNodetag;//EEO_FLAG_IS_QUALuint8flags;/*bitmaskofEEO_FLAG_*bits,seeabove*//**Storageforresultvalueofascalarexpression,orforindividual*columnresultswithinexpressionsbuiltbyExecBuildProjectionInfo().*存储scalarexpression表达式*和通过ExecBuildProjectionInfo()函数创建的expressions单列的结果.*/#defineFIELDNO_EXPRSTATE_RESNULL2boolresnull;#defineFIELDNO_EXPRSTATE_RESVALUE3Datumresvalue;/**Ifprojectingatupleresult,thisslotholdstheresult;elseNULL.*如果投影元组结果,该slot存储结果,或者为NULL.*/#defineFIELDNO_EXPRSTATE_RESULTSLOT4TupleTableSlot*resultslot;/**Instructionstocomputeexpression'sreturnvalue.*计算表达式返回结果的基础"架构"*/structExprEvalStep*steps;/**Functionthatactuallyevaluatestheexpression.Thiscanbesetto*differentvaluesdependingonthecomplexityoftheexpression.*实际解析表达式的函数.*根据表达式的复杂程度,可以设置为不同的值.*/ExprStateEvalFuncevalfunc;/*originalexpressiontree,fordebuggingonly*///原始的表达式树,仅用于debuggingExpr*expr;/*privatestateforanevalfunc*///evalfunc的私有状态void*evalfunc_private;/**XXX:followingfieldsonlyneededduring"compilation"(ExecInitExpr);*couldbethrownawayafterwards.*XXX:接下来的字段在"compilation"(ExecInitExpr)期间需要,之后可被"扔掉".*///当前的步数intsteps_len;/*numberofstepscurrently*///steps数组已分配的长度intsteps_alloc;/*allocatedlengthofstepsarray*///父PlanState节点(如存在)structPlanState*parent;/*parentPlanStatenode,ifany*///用于编译PARAM_EXTERN节点ParamListInfoext_params;/*forcompilingPARAM_EXTERNnodes*///Datum*innermost_caseval;bool*innermost_casenull;Datum*innermost_domainval;bool*innermost_domainnull;}ExprState;
ExprEvalStep
表达式解析步骤结构体
typedefstructExprEvalStep{/**Instructiontobeexecuted.Duringinstructionpreparationthisisan*enumExprEvalOp,butlateritcanbechangedtosomeothertype,e.g.a*pointerforcomputedgoto(that'swhyit'sanintptr_t).*待执行指令.*在指令准备期间这是枚举型的ExprEvalOp,*但后续会被改变为某些其他类型,比如用于goto的指针,因此被定义为intprt_t类型*/intptr_topcode;/*wheretostoretheresultofthisstep*///存储该步骤的结果Datum*resvalue;bool*resnull;/**Inlinedatafortheoperation.Inlinedataisfastertoaccess,but*alsobloatsthesizeofallinstructions.Theunionshouldbekeptto*nomorethan40byteson64-bitsystems(sothattheentirestructis*nomorethan64bytes,asinglecachelineoncommonsystems).*操作的内联数据.*内联数据用于更快的访问,但同时会导致指令的盘膨胀.*联合体在64-bit系统上应保持在40字节范围内*(因此整个结构体不应大于64字节,普通系统上的单个缓存线大小)*/union{/*forEEOP_INNER/OUTER/SCAN_FETCHSOME*///用于EEOP_INNER/OUTER/SCAN_FETCHSOMEstruct{/*attributenumberuptowhichtofetch(inclusive)*///获取到的属性编号intlast_var;TupleDescknown_desc;}fetch;/*forEEOP_INNER/OUTER/SCAN_[SYS]VAR[_FIRST]*/struct{/*attnumisattrnumber-1forregularVAR...*///attnum是常规VAR的attrnumber-1/*butit'sjustthenormal(negative)attrnumberforSYSVAR*///对于SYSVAR,该值是常规的attrnumberintattnum;Oidvartype;/*typeOIDofvariable*/}var;/*forEEOP_WHOLEROW*/struct{Var*var;/*originalVarnodeinplantree*/boolfirst;/*firsttimethrough,needtoinitialize?*/boolslow;/*needruntimecheckfornulls?*/TupleDesctupdesc;/*descriptorforresultingtuples*/JunkFilter*junkFilter;/*JunkFiltertoremoveresjunkcols*/}wholerow;/*forEEOP_ASSIGN_*_VAR*/struct{/*targetindexinExprState->resultslot->tts_values/nulls*/intresultnum;/*sourceattributenumber-1*/intattnum;}assign_var;/*forEEOP_ASSIGN_TMP[_MAKE_RO]*/struct{/*targetindexinExprState->resultslot->tts_values/nulls*/intresultnum;}assign_tmp;/*forEEOP_CONST*/struct{/*constant'svalue*/Datumvalue;boolisnull;}constval;/*forEEOP_FUNCEXPR_*/NULLIF/DISTINCT*///对于EEOP_FUNCEXPR_*/NULLIF/DISTINCTstruct{//函数的检索数据FmgrInfo*finfo;/*function'slookupdata*///参数信息等FunctionCallInfofcinfo_data;/*argumentsetc*//*fastertoaccesswithoutadditionalindirection:*///无需额外的指向,更快速的访问PGFunctionfn_addr;/*actualcalladdress*/intnargs;/*numberofarguments*/}func;/*forEEOP_BOOL_*_STEP*/struct{bool*anynull;/*trackifanyinputwasNULL*/intjumpdone;/*jumphereifresultdetermined*/}boolexpr;/*forEEOP_QUAL*/struct{intjumpdone;/*jumphereonfalseornull*/}qualexpr;/*forEEOP_JUMP[_CONDITION]*/struct{intjumpdone;/*targetinstruction'sindex*/}jump;/*forEEOP_NULLTEST_ROWIS[NOT]NULL*/struct{/*cachedtupdescpointer-filledatruntime*/TupleDescargdesc;}nulltest_row;/*forEEOP_PARAM_EXEC/EXTERN*/struct{intparamid;/*numericIDforparameter*/Oidparamtype;/*OIDofparameter'sdatatype*/}param;/*forEEOP_PARAM_CALLBACK*/struct{ExecEvalSubroutineparamfunc;/*add-onevaluationsubroutine*/void*paramarg;/*privatedataforsame*/intparamid;/*numericIDforparameter*/Oidparamtype;/*OIDofparameter'sdatatype*/}cparam;/*forEEOP_CASE_TESTVAL/DOMAIN_TESTVAL*/struct{Datum*value;/*valuetoreturn*/bool*isnull;}casetest;/*forEEOP_MAKE_READONLY*/struct{Datum*value;/*valuetocoercetoread-only*/bool*isnull;}make_readonly;/*forEEOP_IOCOERCE*/struct{/*lookupandcallinfoforsourcetype'soutputfunction*/FmgrInfo*finfo_out;FunctionCallInfofcinfo_data_out;/*lookupandcallinfoforresulttype'sinputfunction*/FmgrInfo*finfo_in;FunctionCallInfofcinfo_data_in;}iocoerce;/*forEEOP_SQLVALUEFUNCTION*/struct{SQLValueFunction*svf;}sqlvaluefunction;/*forEEOP_NEXTVALUEEXPR*///EEOP_NEXTVALUEEXPRstruct{Oidseqid;Oidseqtypid;}nextvalueexpr;/*forEEOP_ARRAYEXPR*/struct{Datum*elemvalues;/*elementvaluesgetstoredhere*/bool*elemnulls;intnelems;/*lengthoftheabovearrays*/Oidelemtype;/*arrayelementtype*/int16elemlength;/*typlenofthearrayelementtype*/boolelembyval;/*istheelementtypepass-by-value?*/charelemalign;/*typalignoftheelementtype*/boolmultidims;/*isarrayexpressionmulti-D?*/}arrayexpr;/*forEEOP_ARRAYCOERCE*/struct{ExprState*elemexprstate;/*nullifnoper-elementwork*/Oidresultelemtype;/*elementtypeofresultarray*/structArrayMapState*amstate;/*workspaceforarray_map*/}arraycoerce;/*forEEOP_ROW*/struct{TupleDesctupdesc;/*descriptorforresulttuples*//*workspaceforthevaluesconstitutingtherow:*/Datum*elemvalues;bool*elemnulls;}row;/*forEEOP_ROWCOMPARE_STEP*/struct{/*lookupandcalldataforcolumncomparisonfunction*/FmgrInfo*finfo;FunctionCallInfofcinfo_data;PGFunctionfn_addr;/*targetforcomparisonresultinginNULL*/intjumpnull;/*targetforcomparisonyieldinginequality*/intjumpdone;}rowcompare_step;/*forEEOP_ROWCOMPARE_FINAL*/struct{RowCompareTyperctype;}rowcompare_final;/*forEEOP_MINMAX*/struct{/*workspaceforargumentvalues*/Datum*values;bool*nulls;intnelems;/*isitGREATESTorLEAST?*/MinMaxOpop;/*lookupandcalldataforcomparisonfunction*/FmgrInfo*finfo;FunctionCallInfofcinfo_data;}minmax;/*forEEOP_FIELDSELECT*/struct{AttrNumberfieldnum;/*fieldnumbertoextract*/Oidresulttype;/*field'stype*//*cachedtupdescpointer-filledatruntime*/TupleDescargdesc;}fieldselect;/*forEEOP_FIELDSTORE_DEFORM/FIELDSTORE_FORM*/struct{/*originalexpressionnode*/FieldStore*fstore;/*cachedtupdescpointer-filledatruntime*//*notethataDEFORMandFORMpairsharethesametupdesc*/TupleDesc*argdesc;/*workspaceforcolumnvalues*/Datum*values;bool*nulls;intncolumns;}fieldstore;/*forEEOP_ARRAYREF_SUBSCRIPT*/struct{/*toobigtohaveinline*/structArrayRefState*state;intoff;/*0-basedindexofthissubscript*/boolisupper;/*isitupperorlowersubscript?*/intjumpdone;/*jumphereonnull*/}arrayref_subscript;/*forEEOP_ARRAYREF_OLD/ASSIGN/FETCH*/struct{/*toobigtohaveinline*/structArrayRefState*state;}arrayref;/*forEEOP_DOMAIN_NOTNULL/DOMAIN_CHECK*/struct{/*nameofconstraint*/char*constraintname;/*wheretheresultofaCHECKconstraintwillbestored*/Datum*checkvalue;bool*checknull;/*OIDofdomaintype*/Oidresulttype;}domaincheck;/*forEEOP_CONVERT_ROWTYPE*/struct{ConvertRowtypeExpr*convert;/*originalexpression*//*thesethreefieldsarefilledatruntime:*/TupleDescindesc;/*tupdescforinputtype*/TupleDescoutdesc;/*tupdescforoutputtype*/TupleConversionMap*map;/*columnmapping*/boolinitialized;/*initializedforcurrenttypes?*/}convert_rowtype;/*forEEOP_SCALARARRAYOP*/struct{/*element_type/typlen/typbyval/typalignarefilledatruntime*/Oidelement_type;/*InvalidOidifnotyetfilled*/booluseOr;/*useORorANDsemantics?*/int16typlen;/*arrayelementtypestorageinfo*/booltypbyval;chartypalign;FmgrInfo*finfo;/*function'slookupdata*/FunctionCallInfofcinfo_data;/*argumentsetc*//*fastertoaccesswithoutadditionalindirection:*/PGFunctionfn_addr;/*actualcalladdress*/}scalararrayop;/*forEEOP_XMLEXPR*/struct{XmlExpr*xexpr;/*originalexpressionnode*//*workspaceforevaluatingnamedargs,ifany*/Datum*named_argvalue;bool*named_argnull;/*workspaceforevaluatingunnamedargs,ifany*/Datum*argvalue;bool*argnull;}xmlexpr;/*forEEOP_AGGREF*/struct{/*out-of-linestate,modifiedbynodeAgg.c*/AggrefExprState*astate;}aggref;/*forEEOP_GROUPING_FUNC*/struct{AggState*parent;/*parentAgg*/List*clauses;/*integerlistofcolumnnumbers*/}grouping_func;/*forEEOP_WINDOW_FUNC*/struct{/*out-of-linestate,modifiedbynodeWindowFunc.c*/WindowFuncExprState*wfstate;}window_func;/*forEEOP_SUBPLAN*/struct{/*out-of-linestate,createdbynodeSubplan.c*/SubPlanState*sstate;}subplan;/*forEEOP_ALTERNATIVE_SUBPLAN*/struct{/*out-of-linestate,createdbynodeSubplan.c*/AlternativeSubPlanState*asstate;}alternative_subplan;/*forEEOP_AGG_*DESERIALIZE*/struct{AggState*aggstate;FunctionCallInfofcinfo_data;intjumpnull;}agg_deserialize;/*forEEOP_AGG_STRICT_INPUT_CHECK*/struct{bool*nulls;intnargs;intjumpnull;}agg_strict_input_check;/*forEEOP_AGG_INIT_TRANS*/struct{AggState*aggstate;AggStatePerTranspertrans;ExprContext*aggcontext;intsetno;inttransno;intsetoff;intjumpnull;}agg_init_trans;/*forEEOP_AGG_STRICT_TRANS_CHECK*/struct{AggState*aggstate;intsetno;inttransno;intsetoff;intjumpnull;}agg_strict_trans_check;/*forEEOP_AGG_{PLAIN,ORDERED}_TRANS**/struct{AggState*aggstate;AggStatePerTranspertrans;ExprContext*aggcontext;intsetno;inttransno;intsetoff;}agg_trans;}d;}ExprEvalStep;
ExprEvalOp
ExprEvalSteps的鉴频器,定义哪个操作将被执行并且联合体ExprEvalStep->d中的哪个struct将被使用.
/**DiscriminatorforExprEvalSteps.*ExprEvalSteps的鉴频器**Identifiestheoperationtobeexecutedandwhichmemberinthe*ExprEvalStep->dunionisvalid.*定义哪个操作将被执行并且联合体ExprEvalStep->d中的哪个struct将被使用.**Theorderofentriesneedstobekeptinsyncwiththedispatch_table[]*arrayinexecExprInterp.c:ExecInterpExpr().*条目的排序需要与execExprInterp.c:ExecInterpExpr()中dispatch_table[]数组的元素保持一致*/typedefenumExprEvalOp{/*entireexpressionhasbeenevaluatedcompletely,return*///整个表达式已被解析,返回EEOP_DONE,/*applyslot_getsomeattrsoncorrespondingtupleslot*///在相应的元组slot上应用了slot_getsomeattrs方法EEOP_INNER_FETCHSOME,EEOP_OUTER_FETCHSOME,EEOP_SCAN_FETCHSOME,/*computenon-systemVarvalue*///计算非系统Var变量值EEOP_INNER_VAR,EEOP_OUTER_VAR,EEOP_SCAN_VAR,/*computesystemVarvalue*///计算系统Var变量值EEOP_INNER_SYSVAR,EEOP_OUTER_SYSVAR,EEOP_SCAN_SYSVAR,/*computewholerowVar*///计算整行VarEEOP_WHOLEROW,/**Computenon-systemVarvalue,assignitintoExprState'sresultslot.*ThesearenotusedifaCheckVarSlotCompatibility()checkwouldbe*needed.*计算非系统Var值,分配到ExprState's的resultslot字段中.*如果CheckVarSlotCompatibility()需要时,这些都不需要.*/EEOP_ASSIGN_INNER_VAR,EEOP_ASSIGN_OUTER_VAR,EEOP_ASSIGN_SCAN_VAR,/*assignExprState'sresvalue/resnulltoacolumnofitsresultslot*///分配ExprState'sresvalue/resnull到该列的resultslot中EEOP_ASSIGN_TMP,/*ditto,applyingMakeExpandedObjectReadOnly()*///同上,应用MakeExpandedObjectReadOnly()EEOP_ASSIGN_TMP_MAKE_RO,/*evaluateConstvalue*///解析常量值EEOP_CONST,/**Evaluatefunctioncall(includingOpExprsetc).Forspeed,we*distinguishintheopcodewhetherthefunctionisstrictand/or*requiresusagestatstracking.*解析函数调用(包括OpExprs等等).*出于性能的考虑,需要区分opcode是strict函数还是非strict函数,以及是否需要统计跟踪.*/EEOP_FUNCEXPR,EEOP_FUNCEXPR_STRICT,EEOP_FUNCEXPR_FUSAGE,EEOP_FUNCEXPR_STRICT_FUSAGE,/**EvaluatebooleanANDexpression,onesteppersubexpression.FIRST/LAST*subexpressionsarespecial-casedforperformance.SinceANDalwayshas*atleasttwosubexpressions,FIRSTandLASTneverapplytothesame*subexpression.*解析布尔AND表达式,每一个子表达式一个步骤.*FIRST/LAST子表达式是性能上的特例.*由于AND通常至少有两个子表达式,FIRST和LAST永远都不会应用在同一个子表达式上.*/EEOP_BOOL_AND_STEP_FIRST,EEOP_BOOL_AND_STEP,EEOP_BOOL_AND_STEP_LAST,/*similarlyforbooleanORexpression*///与布尔OR表达式类似EEOP_BOOL_OR_STEP_FIRST,EEOP_BOOL_OR_STEP,EEOP_BOOL_OR_STEP_LAST,/*evaluatebooleanNOTexpression*///解析布尔NOT表达式EEOP_BOOL_NOT_STEP,/*simplifiedversionofBOOL_AND_STEPforusebyExecQual()*///用于ExecQual()中的BOOL_AND_STEP简化版本EEOP_QUAL,/*unconditionaljumptoanotherstep*///无条件跳转到另外一个步骤EEOP_JUMP,/*conditionaljumpsbasedoncurrentresultvalue*///基于当前结果值的条件跳转EEOP_JUMP_IF_NULL,EEOP_JUMP_IF_NOT_NULL,EEOP_JUMP_IF_NOT_TRUE,/*performNULLtestsforscalarvalues*///为scalar值执行NULL测试EEOP_NULLTEST_ISNULL,EEOP_NULLTEST_ISNOTNULL,/*performNULLtestsforrowvalues*///为行值执行NULL测试EEOP_NULLTEST_ROWISNULL,EEOP_NULLTEST_ROWISNOTNULL,/*evaluateaBooleanTestexpression*///解析BooleanTest表达式EEOP_BOOLTEST_IS_TRUE,EEOP_BOOLTEST_IS_NOT_TRUE,EEOP_BOOLTEST_IS_FALSE,EEOP_BOOLTEST_IS_NOT_FALSE,/*evaluatePARAM_EXEC/EXTERNparameters*///解析PARAM_EXEC/EXTERN参数EEOP_PARAM_EXEC,EEOP_PARAM_EXTERN,EEOP_PARAM_CALLBACK,/*returnCaseTestExprvalue*///返回CaseTestExpr值EEOP_CASE_TESTVAL,/*applyMakeExpandedObjectReadOnly()totargetvalue*///对目标值应用MakeExpandedObjectReadOnly()EEOP_MAKE_READONLY,/*evaluateassortedspecial-purposeexpressiontypes*///解析各种特殊用途的表达式类型EEOP_IOCOERCE,EEOP_DISTINCT,EEOP_NOT_DISTINCT,EEOP_NULLIF,EEOP_SQLVALUEFUNCTION,EEOP_CURRENTOFEXPR,EEOP_NEXTVALUEEXPR,EEOP_ARRAYEXPR,EEOP_ARRAYCOERCE,EEOP_ROW,/**ComparetwoindividualelementsofeachoftwocomparedROW()*expressions.SkiptoROWCOMPARE_FINALifelementsarenotequal.*给出两个需要对比的ROW()表达式,两两比较行中的元素.*如果元素不相等,则跳转到ROWCOMPARE_FINAL*/EEOP_ROWCOMPARE_STEP,/*evaluatebooleanvaluebasedonpreviousROWCOMPARE_STEPoperations*///基于上一步的ROWCOMPARE_STEP操作解析布尔值EEOP_ROWCOMPARE_FINAL,/*evaluateGREATEST()orLEAST()*///解析GREATEST()和LEAST()EEOP_MINMAX,/*evaluateFieldSelectexpression*///解析FieldSelect表达式EEOP_FIELDSELECT,/**Deformtuplebeforeevaluatingnewvaluesforindividualfieldsina*FieldStoreexpression.*在解析FieldStore表达式中的独立列新值前重构元组*/EEOP_FIELDSTORE_DEFORM,/**FormthenewtupleforaFieldStoreexpression.Individualfieldswill*havebeenevaluatedintocolumnsofthetupledeformedbythepreceding*DEFORMstep.*为FieldStore表达式构成新元组.*单独的字段会解析到元组的列中(行已被上一个步骤EEOP_FIELDSTORE_DEFORM析构)*/EEOP_FIELDSTORE_FORM,/*Processanarraysubscript;short-circuitexpressiontoNULLifNULL*///处理数组子脚本.如为NULL则短路表达式为NULLEEOP_ARRAYREF_SUBSCRIPT,/**Computeoldarrayelement/slicewhenanArrayRefassignmentexpression*containsArrayRef/FieldStoresubexpressions.Valueisaccessedusing*theCaseTestmechanism.*在ArrayRef分配表达式包含ArrayRef/FieldStore子表达式时计算旧的数组元素/片.*通过CaseTest机制访问Value*/EEOP_ARRAYREF_OLD,/*computenewvalueforArrayRefassignmentexpression*///为ArrayRef分配118EEOP_ARRAYREF_ASSIGN,/*computeelement/sliceforArrayReffetchexpression*///为ArrayRef提取表达式计算element/sliceEEOP_ARRAYREF_FETCH,/*evaluatevalueforCoerceToDomainValue*///为CoerceToDomainValue解析值EEOP_DOMAIN_TESTVAL,/*evaluateadomain'sNOTNULLconstraint*///解析域NOTNULL约束EEOP_DOMAIN_NOTNULL,/*evaluateasingledomainCHECKconstraint*///解析单个域CHECK约束EEOP_DOMAIN_CHECK,/*evaluateassortedspecial-purposeexpressiontypes*///解析特殊目的的表达式类型EEOP_CONVERT_ROWTYPE,EEOP_SCALARARRAYOP,EEOP_XMLEXPR,EEOP_AGGREF,EEOP_GROUPING_FUNC,EEOP_WINDOW_FUNC,EEOP_SUBPLAN,EEOP_ALTERNATIVE_SUBPLAN,/*aggregationrelatednodes*///聚合相关节点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,/*non-existentoperation,usede.g.tocheckarraylengths*///不存在的操作,比如用于检测数组长度EEOP_LAST}ExprEvalOp;二、源码解读
ExecInitExprRec函数,把表达式解析需要的步骤追加到ExprState->steps中,可能会递归进入到子表达式节点中.
其主要逻辑是根据节点类型,执行相应的处理逻辑,比如节点类型为OpExpr,则其逻辑为:
caseT_OpExpr://操作符表达式{OpExpr*op=(OpExpr*)node;ExecInitFunc(&scratch,node,op->args,op->opfuncid,op->inputcollid,state);ExprEvalPushStep(state,&scratch);break;}
其他节点类型类似,代码虽然很长,但逻辑清晰简单.
/**AppendthestepsnecessaryfortheevaluationofnodetoExprState->steps,*possiblyrecursingintosub-expressionsofnode.*把表达式解析需要的步骤追加到ExprState->steps中,可能会递归进入到子表达式节点中.**node-expressiontoevaluate*state-ExprStatetowhose->stepstoappendthenecessaryoperations*resv/resnull-wheretostoretheresultofthenodeinto*node-待解析的表达式*state-步骤追加到该ExprState->steps中*resv/resnull-节点结果存储的位置*/staticvoidExecInitExprRec(Expr*node,ExprState*state,Datum*resv,bool*resnull){ExprEvalStepscratch={0};/*Guardagainststackoverflowduetooverlycomplexexpressions*///避免出现堆栈溢出check_stack_depth();/*Step'soutputlocationisalwayswhatthecallergaveus*///步骤的输出位置往往是调用者提供给我们的Assert(resv!=NULL&&resnull!=NULL);scratch.resvalue=resv;scratch.resnull=resnull;/*casesshouldbeorderedastheyareinenumNodeTag*///CASE的顺序与NodeTag枚举类型中的顺序一样switch(nodeTag(node)){caseT_Var://VAR{Var*variable=(Var*)node;if(variable->varattno==InvalidAttrNumber){/*whole-rowVar*/ExecInitWholeRowVar(&scratch,variable,state);}elseif(variable->varattno<=0){/*systemcolumn*/scratch.d.var.attnum=variable->varattno;scratch.d.var.vartype=variable->vartype;switch(variable->varno){caseINNER_VAR:scratch.opcode=EEOP_INNER_SYSVAR;break;caseOUTER_VAR:scratch.opcode=EEOP_OUTER_SYSVAR;break;/*INDEX_VARishandledbydefaultcase*/default:scratch.opcode=EEOP_SCAN_SYSVAR;break;}}else{/*regularusercolumn*/scratch.d.var.attnum=variable->varattno-1;scratch.d.var.vartype=variable->vartype;switch(variable->varno){caseINNER_VAR:scratch.opcode=EEOP_INNER_VAR;break;caseOUTER_VAR:scratch.opcode=EEOP_OUTER_VAR;break;/*INDEX_VARishandledbydefaultcase*/default:scratch.opcode=EEOP_SCAN_VAR;break;}}ExprEvalPushStep(state,&scratch);break;}caseT_Const://常量{Const*con=(Const*)node;scratch.opcode=EEOP_CONST;scratch.d.constval.value=con->constvalue;scratch.d.constval.isnull=con->constisnull;ExprEvalPushStep(state,&scratch);break;}caseT_Param://参数{Param*param=(Param*)node;ParamListInfoparams;switch(param->paramkind){casePARAM_EXEC:scratch.opcode=EEOP_PARAM_EXEC;scratch.d.param.paramid=param->paramid;scratch.d.param.paramtype=param->paramtype;ExprEvalPushStep(state,&scratch);break;casePARAM_EXTERN:/**IfwehavearelevantParamCompileHook,useit;*otherwisecompileastandardEEOP_PARAM_EXTERN*step.ext_params,ifsupplied,takesprecedence*overinfofromtheparentnode'sEState(ifany).*/if(state->ext_params)params=state->ext_params;elseif(state->parent&&state->parent->state)params=state->parent->state->es_param_list_info;elseparams=NULL;if(params&¶ms->paramCompile){params->paramCompile(params,param,state,resv,resnull);}else{scratch.opcode=EEOP_PARAM_EXTERN;scratch.d.param.paramid=param->paramid;scratch.d.param.paramtype=param->paramtype;ExprEvalPushStep(state,&scratch);}break;default:elog(ERROR,"unrecognizedparamkind:%d",(int)param->paramkind);break;}break;}caseT_Aggref://聚集{Aggref*aggref=(Aggref*)node;AggrefExprState*astate=makeNode(AggrefExprState);scratch.opcode=EEOP_AGGREF;scratch.d.aggref.astate=astate;astate->aggref=aggref;if(state->parent&&IsA(state->parent,AggState)){AggState*aggstate=(AggState*)state->parent;aggstate->aggs=lcons(astate,aggstate->aggs);aggstate->numaggs++;}else{/*plannermessedup*/elog(ERROR,"Aggreffoundinnon-Aggplannode");}ExprEvalPushStep(state,&scratch);break;}caseT_GroupingFunc:{GroupingFunc*grp_node=(GroupingFunc*)node;Agg*agg;if(!state->parent||!IsA(state->parent,AggState)||!IsA(state->parent->plan,Agg))elog(ERROR,"GroupingFuncfoundinnon-Aggplannode");scratch.opcode=EEOP_GROUPING_FUNC;scratch.d.grouping_func.parent=(AggState*)state->parent;agg=(Agg*)(state->parent->plan);if(agg->groupingSets)scratch.d.grouping_func.clauses=grp_node->cols;elsescratch.d.grouping_func.clauses=NIL;ExprEvalPushStep(state,&scratch);break;}caseT_WindowFunc:{WindowFunc*wfunc=(WindowFunc*)node;WindowFuncExprState*wfstate=makeNode(WindowFuncExprState);wfstate->wfunc=wfunc;if(state->parent&&IsA(state->parent,WindowAggState)){WindowAggState*winstate=(WindowAggState*)state->parent;intnfuncs;winstate->funcs=lcons(wfstate,winstate->funcs);nfuncs=++winstate->numfuncs;if(wfunc->winagg)winstate->numaggs++;/*fornowinitializeaggusingoldstyleexpressions*/wfstate->args=ExecInitExprList(wfunc->args,state->parent);wfstate->aggfilter=ExecInitExpr(wfunc->aggfilter,state->parent);/**Complainifthewindowfunc'sargumentscontainany*windowfuncs;nestedwindowfunctionsaresemantically*nonsensical.(Thisshouldhavebeencaughtearlier,*butwedefendagainstithereanyway.)*/if(nfuncs!=winstate->numfuncs)ereport(ERROR,(errcode(ERRCODE_WINDOWING_ERROR),errmsg("windowfunctioncallscannotbenested")));}else{/*plannermessedup*/elog(ERROR,"WindowFuncfoundinnon-WindowAggplannode");}scratch.opcode=EEOP_WINDOW_FUNC;scratch.d.window_func.wfstate=wfstate;ExprEvalPushStep(state,&scratch);break;}caseT_ArrayRef:{ArrayRef*aref=(ArrayRef*)node;ExecInitArrayRef(&scratch,aref,state,resv,resnull);break;}caseT_FuncExpr://函数表达式{FuncExpr*func=(FuncExpr*)node;ExecInitFunc(&scratch,node,func->args,func->funcid,func->inputcollid,state);ExprEvalPushStep(state,&scratch);break;}caseT_OpExpr://操作符表达式{OpExpr*op=(OpExpr*)node;ExecInitFunc(&scratch,node,op->args,op->opfuncid,op->inputcollid,state);ExprEvalPushStep(state,&scratch);break;}caseT_DistinctExpr:{DistinctExpr*op=(DistinctExpr*)node;ExecInitFunc(&scratch,node,op->args,op->opfuncid,op->inputcollid,state);/**ChangeopcodeofcallinstructiontoEEOP_DISTINCT.**XXX:historicallywe'venotcalledthefunctionusage*pgstatinfrastructure-thatseemsinconsistentgiventhat*wedosofornormalfunction*and*operatorevaluation.If*wedecidedtodothathere,we'dprobablywantseparate*opcodesforFUSAGEornot.*/scratch.opcode=EEOP_DISTINCT;ExprEvalPushStep(state,&scratch);break;}caseT_NullIfExpr:{NullIfExpr*op=(NullIfExpr*)node;ExecInitFunc(&scratch,node,op->args,op->opfuncid,op->inputcollid,state);/**ChangeopcodeofcallinstructiontoEEOP_NULLIF.**XXX:historicallywe'venotcalledthefunctionusage*pgstatinfrastructure-thatseemsinconsistentgiventhat*wedosofornormalfunction*and*operatorevaluation.If*wedecidedtodothathere,we'dprobablywantseparate*opcodesforFUSAGEornot.*/scratch.opcode=EEOP_NULLIF;ExprEvalPushStep(state,&scratch);break;}caseT_ScalarArrayOpExpr:{ScalarArrayOpExpr*opexpr=(ScalarArrayOpExpr*)node;Expr*scalararg;Expr*arrayarg;FmgrInfo*finfo;FunctionCallInfofcinfo;AclResultaclresult;Assert(list_length(opexpr->args)==2);scalararg=(Expr*)linitial(opexpr->args);arrayarg=(Expr*)lsecond(opexpr->args);/*Checkpermissiontocallfunction*/aclresult=pg_proc_aclcheck(opexpr->opfuncid,GetUserId(),ACL_EXECUTE);if(aclresult!=ACLCHECK_OK)aclcheck_error(aclresult,OBJECT_FUNCTION,get_func_name(opexpr->opfuncid));InvokeFunctionExecuteHook(opexpr->opfuncid);/*Setuptheprimaryfmgrlookupinformation*/finfo=palloc0(sizeof(FmgrInfo));fcinfo=palloc0(sizeof(FunctionCallInfoData));fmgr_info(opexpr->opfuncid,finfo);fmgr_info_set_expr((Node*)node,finfo);InitFunctionCallInfoData(*fcinfo,finfo,2,opexpr->inputcollid,NULL,NULL);/*Evaluatescalardirectlyintoleftfunctionargument*/ExecInitExprRec(scalararg,state,&fcinfo->arg[0],&fcinfo->argnull[0]);/**Evaluatearrayargumentintoourreturnvalue.There'sno*dangerinthat,becausethereturnvalueisguaranteedto*beoverwrittenbyEEOP_SCALARARRAYOP,andwillnotbe*passedtoanyotherexpression.*/ExecInitExprRec(arrayarg,state,resv,resnull);/*Andperformtheoperation*/scratch.opcode=EEOP_SCALARARRAYOP;scratch.d.scalararrayop.element_type=InvalidOid;scratch.d.scalararrayop.useOr=opexpr->useOr;scratch.d.scalararrayop.finfo=finfo;scratch.d.scalararrayop.fcinfo_data=fcinfo;scratch.d.scalararrayop.fn_addr=finfo->fn_addr;ExprEvalPushStep(state,&scratch);break;}caseT_BoolExpr:{BoolExpr*boolexpr=(BoolExpr*)node;intnargs=list_length(boolexpr->args);List*adjust_jumps=NIL;intoff;ListCell*lc;/*allocatescratchmemoryusedbyallstepsofAND/OR*/if(boolexpr->boolop!=NOT_EXPR)scratch.d.boolexpr.anynull=(bool*)palloc(sizeof(bool));/**Foreachargumentevaluatetheargumentitself,then*performthebooloperation'sappropriatehandling.**Wecanevaluateeachargumentintoourresultarea,since*theshort-circuitinglogicmeansweonlyneedtoremember*previousNULLvalues.**AND/ORissplitintoseparateSTEP_FIRST(one)/STEP(zero*ormore)/STEP_LAST(one)steps,aseachofthosehasto*performdifferentwork.TheFIRST/LASTsplitisvalid*becauseAND/ORhaveatleasttwoarguments.*/off=0;foreach(lc,boolexpr->args){Expr*arg=(Expr*)lfirst(lc);/*Evaluateargumentintoouroutputvariable*/ExecInitExprRec(arg,state,resv,resnull);/*Performtheappropriatesteptype*/switch(boolexpr->boolop){caseAND_EXPR:Assert(nargs>=2);if(off==0)scratch.opcode=EEOP_BOOL_AND_STEP_FIRST;elseif(off+1==nargs)scratch.opcode=EEOP_BOOL_AND_STEP_LAST;elsescratch.opcode=EEOP_BOOL_AND_STEP;break;caseOR_EXPR:Assert(nargs>=2);if(off==0)scratch.opcode=EEOP_BOOL_OR_STEP_FIRST;elseif(off+1==nargs)scratch.opcode=EEOP_BOOL_OR_STEP_LAST;elsescratch.opcode=EEOP_BOOL_OR_STEP;break;caseNOT_EXPR:Assert(nargs==1);scratch.opcode=EEOP_BOOL_NOT_STEP;break;default:elog(ERROR,"unrecognizedboolop:%d",(int)boolexpr->boolop);break;}scratch.d.boolexpr.jumpdone=-1;ExprEvalPushStep(state,&scratch);adjust_jumps=lappend_int(adjust_jumps,state->steps_len-1);off++;}/*adjustjumptargets*/foreach(lc,adjust_jumps){ExprEvalStep*as=&state->steps[lfirst_int(lc)];Assert(as->d.boolexpr.jumpdone==-1);as->d.boolexpr.jumpdone=state->steps_len;}break;}caseT_SubPlan:{SubPlan*subplan=(SubPlan*)node;SubPlanState*sstate;if(!state->parent)elog(ERROR,"SubPlanfoundwithnoparentplan");sstate=ExecInitSubPlan(subplan,state->parent);/*addSubPlanStatenodestostate->parent->subPlan*/state->parent->subPlan=lappend(state->parent->subPlan,sstate);scratch.opcode=EEOP_SUBPLAN;scratch.d.subplan.sstate=sstate;ExprEvalPushStep(state,&scratch);break;}caseT_AlternativeSubPlan:{AlternativeSubPlan*asplan=(AlternativeSubPlan*)node;AlternativeSubPlanState*asstate;if(!state->parent)elog(ERROR,"AlternativeSubPlanfoundwithnoparentplan");asstate=ExecInitAlternativeSubPlan(asplan,state->parent);scratch.opcode=EEOP_ALTERNATIVE_SUBPLAN;scratch.d.alternative_subplan.asstate=asstate;ExprEvalPushStep(state,&scratch);break;}caseT_FieldSelect:{FieldSelect*fselect=(FieldSelect*)node;/*evaluaterow/recordargumentintoresultarea*/ExecInitExprRec(fselect->arg,state,resv,resnull);/*andextractfield*/scratch.opcode=EEOP_FIELDSELECT;scratch.d.fieldselect.fieldnum=fselect->fieldnum;scratch.d.fieldselect.resulttype=fselect->resulttype;scratch.d.fieldselect.argdesc=NULL;ExprEvalPushStep(state,&scratch);break;}caseT_FieldStore:{FieldStore*fstore=(FieldStore*)node;TupleDesctupDesc;TupleDesc*descp;Datum*values;bool*nulls;intncolumns;ListCell*l1,*l2;/*findoutthenumberofcolumnsinthecompositetype*/tupDesc=lookup_rowtype_tupdesc(fstore->resulttype,-1);ncolumns=tupDesc->natts;DecrTupleDescRefCount(tupDesc);/*createworkspaceforcolumnvalues*/values=(Datum*)palloc(sizeof(Datum)*ncolumns);nulls=(bool*)palloc(sizeof(bool)*ncolumns);/*createworkspaceforruntimetupdesccache*/descp=(TupleDesc*)palloc(sizeof(TupleDesc));*descp=NULL;/*emitcodetoevaluatethecompositeinputvalue*/ExecInitExprRec(fstore->arg,state,resv,resnull);/*next,deformtheinputtupleintoourworkspace*/scratch.opcode=EEOP_FIELDSTORE_DEFORM;scratch.d.fieldstore.fstore=fstore;scratch.d.fieldstore.argdesc=descp;scratch.d.fieldstore.values=values;scratch.d.fieldstore.nulls=nulls;scratch.d.fieldstore.ncolumns=ncolumns;ExprEvalPushStep(state,&scratch);/*evaluatenewfieldvalues,storeinworkspacecolumns*/forboth(l1,fstore->newvals,l2,fstore->fieldnums){Expr*e=(Expr*)lfirst(l1);AttrNumberfieldnum=lfirst_int(l2);Datum*save_innermost_caseval;bool*save_innermost_casenull;if(fieldnum<=0||fieldnum>ncolumns)elog(ERROR,"fieldnumber%disoutofrangeinFieldStore",fieldnum);/**UsetheCaseTestExprmechanismtopassdowntheold*valueofthefieldbeingreplaced;thisisneededin*casethenewvalisitselfaFieldStoreorArrayRefthat*hastoobtainandmodifytheoldvalue.It'ssafeto*reusetheCASEmechanismbecausetherecannotbeaCASE*betweenhereandwherethevaluewouldbeneeded,anda*fieldassignmentcan'tbewithinaCASEeither.(So*savingandrestoringinnermost_casevalisjust*paranoia,butlet'sdoitanyway.)**Anothernon-obviouspointisthatit'ssafetousethe*field'svalues[]/nulls[]entriesasboththecaseval*sourceandtheresultaddressforthissubexpression.*That'sokayonlybecause(1)bothFieldStoreand*ArrayRefevaluatetheirargorrefexprinputsfirst,*and(2)anysuchCaseTestExprisdirectlytheargor*refexprinput.Soanyreadofthecasevalwilloccur*beforethere'sachancetooverwriteit.Also,if*multipleentriesinthenewvals/fieldnumsliststarget*thesamefield,they'lleffectivelybeapplied*left-to-rightwhichiswhatwewant.*/save_innermost_caseval=state->innermost_caseval;save_innermost_casenull=state->innermost_casenull;state->innermost_caseval=&values[fieldnum-1];state->innermost_casenull=&nulls[fieldnum-1];ExecInitExprRec(e,state,&values[fieldnum-1],&nulls[fieldnum-1]);state->innermost_caseval=save_innermost_caseval;state->innermost_casenull=save_innermost_casenull;}/*finally,formresulttuple*/scratch.opcode=EEOP_FIELDSTORE_FORM;scratch.d.fieldstore.fstore=fstore;scratch.d.fieldstore.argdesc=descp;scratch.d.fieldstore.values=values;scratch.d.fieldstore.nulls=nulls;scratch.d.fieldstore.ncolumns=ncolumns;ExprEvalPushStep(state,&scratch);break;}caseT_RelabelType:{/*relabeldoesn'tneedtodoanythingatruntime*/RelabelType*relabel=(RelabelType*)node;ExecInitExprRec(relabel->arg,state,resv,resnull);break;}caseT_CoerceViaIO:{CoerceViaIO*iocoerce=(CoerceViaIO*)node;Oidiofunc;booltypisvarlena;Oidtypioparam;FunctionCallInfofcinfo_in;/*evaluateargumentintostep'sresultarea*/ExecInitExprRec(iocoerce->arg,state,resv,resnull);/**Preparebothoutputandinputfunctioncalls,tobe*evaluatedinsideasingleevaluationstepforspeed-this*canbeaverycommonoperation.**Wedon'tcheckpermissionshereasatype'sinput/output*functionareassumedtobeexecutablebyeveryone.*/scratch.opcode=EEOP_IOCOERCE;/*lookupthesourcetype'soutputfunction*/scratch.d.iocoerce.finfo_out=palloc0(sizeof(FmgrInfo));scratch.d.iocoerce.fcinfo_data_out=palloc0(sizeof(FunctionCallInfoData));getTypeOutputInfo(exprType((Node*)iocoerce->arg),&iofunc,&typisvarlena);fmgr_info(iofunc,scratch.d.iocoerce.finfo_out);fmgr_info_set_expr((Node*)node,scratch.d.iocoerce.finfo_out);InitFunctionCallInfoData(*scratch.d.iocoerce.fcinfo_data_out,scratch.d.iocoerce.finfo_out,1,InvalidOid,NULL,NULL);/*lookuptheresulttype'sinputfunction*/scratch.d.iocoerce.finfo_in=palloc0(sizeof(FmgrInfo));scratch.d.iocoerce.fcinfo_data_in=palloc0(sizeof(FunctionCallInfoData));getTypeInputInfo(iocoerce->resulttype,&iofunc,&typioparam);fmgr_info(iofunc,scratch.d.iocoerce.finfo_in);fmgr_info_set_expr((Node*)node,scratch.d.iocoerce.finfo_in);InitFunctionCallInfoData(*scratch.d.iocoerce.fcinfo_data_in,scratch.d.iocoerce.finfo_in,3,InvalidOid,NULL,NULL);/**Wecanpreloadthesecondandthirdargumentsfortheinput*function,sincethey'reconstants.*/fcinfo_in=scratch.d.iocoerce.fcinfo_data_in;fcinfo_in->arg[1]=ObjectIdGetDatum(typioparam);fcinfo_in->argnull[1]=false;fcinfo_in->arg[2]=Int32GetDatum(-1);fcinfo_in->argnull[2]=false;ExprEvalPushStep(state,&scratch);break;}caseT_ArrayCoerceExpr:{ArrayCoerceExpr*acoerce=(ArrayCoerceExpr*)node;Oidresultelemtype;ExprState*elemstate;/*evaluateargumentintostep'sresultarea*/ExecInitExprRec(acoerce->arg,state,resv,resnull);resultelemtype=get_element_type(acoerce->resulttype);if(!OidIsValid(resultelemtype))ereport(ERROR,(errcode(ERRCODE_INVALID_PARAMETER_VALUE),errmsg("targettypeisnotanarray")));/**Constructasub-expressionfortheper-elementexpression;*butdon'treadyituntilafterwecheckitfortriviality.*Weassumeithasn'tanyVarreferences,butdoeshavea*CaseTestExprrepresentingthesourcearrayelementvalues.*/elemstate=makeNode(ExprState);elemstate->expr=acoerce->elemexpr;elemstate->parent=state->parent;elemstate->ext_params=state->ext_params;elemstate->innermost_caseval=(Datum*)palloc(sizeof(Datum));elemstate->innermost_casenull=(bool*)palloc(sizeof(bool));ExecInitExprRec(acoerce->elemexpr,elemstate,&elemstate->resvalue,&elemstate->resnull);if(elemstate->steps_len==1&&elemstate->steps[0].opcode==EEOP_CASE_TESTVAL){/*Trivial,soweneednoper-elementworkatruntime*/elemstate=NULL;}else{/*Nottrivial,soappendaDONEstep*/scratch.opcode=EEOP_DONE;ExprEvalPushStep(elemstate,&scratch);/*andreadythesubexpression*/ExecReadyExpr(elemstate);}scratch.opcode=EEOP_ARRAYCOERCE;scratch.d.arraycoerce.elemexprstate=elemstate;scratch.d.arraycoerce.resultelemtype=resultelemtype;if(elemstate){/*Setupworkspaceforarray_map*/scratch.d.arraycoerce.amstate=(ArrayMapState*)palloc0(sizeof(ArrayMapState));}else{/*Don'tneedworkspaceifthere'snosubexpression*/scratch.d.arraycoerce.amstate=NULL;}ExprEvalPushStep(state,&scratch);break;}caseT_ConvertRowtypeExpr:{ConvertRowtypeExpr*convert=(ConvertRowtypeExpr*)node;/*evaluateargumentintostep'sresultarea*/ExecInitExprRec(convert->arg,state,resv,resnull);/*andpushconversionstep*/scratch.opcode=EEOP_CONVERT_ROWTYPE;scratch.d.convert_rowtype.convert=convert;scratch.d.convert_rowtype.indesc=NULL;scratch.d.convert_rowtype.outdesc=NULL;scratch.d.convert_rowtype.map=NULL;scratch.d.convert_rowtype.initialized=false;ExprEvalPushStep(state,&scratch);break;}/*notethatCaseWhenexpressionsarehandledwithinthisblock*/caseT_CaseExpr:{CaseExpr*caseExpr=(CaseExpr*)node;List*adjust_jumps=NIL;Datum*caseval=NULL;bool*casenull=NULL;ListCell*lc;/**Ifthere'satestexpression,wehavetoevaluateitand*savethevaluewheretheCaseTestExprplaceholderscanfind*it.*/if(caseExpr->arg!=NULL){/*Evaluatetestexprintocaseval/casenullworkspace*/caseval=palloc(sizeof(Datum));casenull=palloc(sizeof(bool));ExecInitExprRec(caseExpr->arg,state,caseval,casenull);/**Sincevaluemightbereadmultipletimes,forcetoR/O*-butonlyifitcouldbeanexpandeddatum.*/if(get_typlen(exprType((Node*)caseExpr->arg))==-1){/*changecasevalin-place*/scratch.opcode=EEOP_MAKE_READONLY;scratch.resvalue=caseval;scratch.resnull=casenull;scratch.d.make_readonly.value=caseval;scratch.d.make_readonly.isnull=casenull;ExprEvalPushStep(state,&scratch);/*restorenormalsettingsofscratchfields*/scratch.resvalue=resv;scratch.resnull=resnull;}}/**PreparetoevaluateeachoftheWHENclausesinturn;as*soonasoneistruewereturnthevalueofthe*correspondingTHENclause.Ifnonearetruethenwereturn*thevalueoftheELSEclause,orNULLifthereisnone.*/foreach(lc,caseExpr->args){CaseWhen*when=(CaseWhen*)lfirst(lc);Datum*save_innermost_caseval;bool*save_innermost_casenull;intwhenstep;/**MaketestexprresultavailabletoCaseTestExprnodes*withinthecondition.Wemustsaveandrestoreprior*settingofinnermost_casevalfields,incasethisnode*isitselfwithinalargerCASE.**Ifthere'snotestexpression,wedon'tactuallyneed*tosaveandrestorethesefields;butit'slesscodeto*justdosounconditionally.*/save_innermost_caseval=state->innermost_caseval;save_innermost_casenull=state->innermost_casenull;state->innermost_caseval=caseval;state->innermost_casenull=casenull;/*evaluateconditionintoCASE'sresultvariables*/ExecInitExprRec(when->expr,state,resv,resnull);state->innermost_caseval=save_innermost_caseval;state->innermost_casenull=save_innermost_casenull;/*IfWHENresultisn'ttrue,jumptonextCASEarm*/scratch.opcode=EEOP_JUMP_IF_NOT_TRUE;scratch.d.jump.jumpdone=-1;/*computedlater*/ExprEvalPushStep(state,&scratch);whenstep=state->steps_len-1;/**IfWHENresultistrue,evaluateTHENresult,storing*itintotheCASE'sresultvariables.*/ExecInitExprRec(when->result,state,resv,resnull);/*EmitJUMPsteptojumptoendofCASE'scode*/scratch.opcode=EEOP_JUMP;scratch.d.jump.jumpdone=-1;/*computedlater*/ExprEvalPushStep(state,&scratch);/**Don'tknowaddressforthatjumpyet,computeoncethe*wholeCASEexpressionisbuilt.*/adjust_jumps=lappend_int(adjust_jumps,state->steps_len-1);/**ButwecansetWHENtest'sjumptargetnow,tomakeit*jumptothenextWHENsubexpressionortheELSE.*/state->steps[whenstep].d.jump.jumpdone=state->steps_len;}/*transformCaseExpralwaysaddsadefault*/Assert(caseExpr->defresult);/*evaluateELSEexprintoCASE'sresultvariables*/ExecInitExprRec(caseExpr->defresult,state,resv,resnull);/*adjustjumptargets*/foreach(lc,adjust_jumps){ExprEvalStep*as=&state->steps[lfirst_int(lc)];Assert(as->opcode==EEOP_JUMP);Assert(as->d.jump.jumpdone==-1);as->d.jump.jumpdone=state->steps_len;}break;}caseT_CaseTestExpr:{/**Readfromlocationidentifiedbyinnermost_caseval.Note*thatinnermost_casevalcouldbeNULL,ifthisnodeisn't*actuallywithinaCaseExpr,ArrayCoerceExpr,etcstructure.*Thatcanhappenbecausesomepartsofthesystemabuse*CaseTestExprtocauseareadofavalueexternallysupplied*inecontext->caseValue_datum.We'lltakecareofthat*scenarioatruntime.*/scratch.opcode=EEOP_CASE_TESTVAL;scratch.d.casetest.value=state->innermost_caseval;scratch.d.casetest.isnull=state->innermost_casenull;ExprEvalPushStep(state,&scratch);break;}caseT_ArrayExpr:{ArrayExpr*arrayexpr=(ArrayExpr*)node;intnelems=list_length(arrayexpr->elements);ListCell*lc;intelemoff;/**Evaluatebycomputingeachelement,andthenformingthe*array.Elementsarecomputedintoscratcharrays*associatedwiththeARRAYEXPRstep.*/scratch.opcode=EEOP_ARRAYEXPR;scratch.d.arrayexpr.elemvalues=(Datum*)palloc(sizeof(Datum)*nelems);scratch.d.arrayexpr.elemnulls=(bool*)palloc(sizeof(bool)*nelems);scratch.d.arrayexpr.nelems=nelems;/*fillremainingfieldsofstep*/scratch.d.arrayexpr.multidims=arrayexpr->multidims;scratch.d.arrayexpr.elemtype=arrayexpr->element_typeid;/*doone-timecataloglookupfortypeinfo*/get_typlenbyvalalign(arrayexpr->element_typeid,&scratch.d.arrayexpr.elemlength,&scratch.d.arrayexpr.elembyval,&scratch.d.arrayexpr.elemalign);/*preparetoevaluateallarguments*/elemoff=0;foreach(lc,arrayexpr->elements){Expr*e=(Expr*)lfirst(lc);ExecInitExprRec(e,state,&scratch.d.arrayexpr.elemvalues[elemoff],&scratch.d.arrayexpr.elemnulls[elemoff]);elemoff++;}/*andthencollectallintoanarray*/ExprEvalPushStep(state,&scratch);break;}caseT_RowExpr:{RowExpr*rowexpr=(RowExpr*)node;intnelems=list_length(rowexpr->args);TupleDesctupdesc;inti;ListCell*l;/*Buildtupdesctodescriberesulttuples*/if(rowexpr->row_typeid==RECORDOID){/*genericrecord,usetypesofgivenexpressions*/tupdesc=ExecTypeFromExprList(rowexpr->args);}else{/*it'sbeencasttoanamedtype,usethat*/tupdesc=lookup_rowtype_tupdesc_copy(rowexpr->row_typeid,-1);}/*Ineithercase,adoptRowExpr'scolumnaliases*/ExecTypeSetColNames(tupdesc,rowexpr->colnames);/*Blessthetupdescincaseit'snowoftypeRECORD*/BlessTupleDesc(tupdesc);/**Inthenamed-typecase,thetupdesccouldhavemorecolumns*thanareintheargslist,sincethetypemighthavehad*columnsaddedsincetheROW()wasparsed.Wewantthose*extracolumnstogotonulls,sowemakesurethatthe*workspacearraysarelargeenoughandtheninitializeany*extracolumnstoreadasNULLs.*/Assert(nelems<=tupdesc->natts);nelems=Max(nelems,tupdesc->natts);/**Evaluatebyfirstbuildingdatumsforeachfield,andthen*afinalstepformingthecompositedatum.*/scratch.opcode=EEOP_ROW;scratch.d.row.tupdesc=tupdesc;/*spacefortheindividualfielddatums*/scratch.d.row.elemvalues=(Datum*)palloc(sizeof(Datum)*nelems);scratch.d.row.elemnulls=(bool*)palloc(sizeof(bool)*nelems);/*asexplainedabove,makesureanyextracolumnsarenull*/memset(scratch.d.row.elemnulls,true,sizeof(bool)*nelems);/*Setupevaluation,skippinganydeletedcolumns*/i=0;foreach(l,rowexpr->args){Form_pg_attributeatt=TupleDescAttr(tupdesc,i);Expr*e=(Expr*)lfirst(l);if(!att->attisdropped){/**GuardagainstALTERCOLUMNTYPEonrowtypesince*theRowExprwascreated.XXXshouldwecheck*typmodtoo?Notsurewecanbesureit'llbethe*same.*/if(exprType((Node*)e)!=att->atttypid)ereport(ERROR,(errcode(ERRCODE_DATATYPE_MISMATCH),errmsg("ROW()columnhastype%sinsteadoftype%s",format_type_be(exprType((Node*)e)),format_type_be(att->atttypid))));}else{/**IgnoreoriginalexpressionandinsertaNULL.We*don'treallycarewhattypeofNULLitis,so*alwaysmakeanint4NULL.*/e=(Expr*)makeNullConst(INT4OID,-1,InvalidOid);}/*Evaluatecolumnexprintoappropriateworkspaceslot*/ExecInitExprRec(e,state,&scratch.d.row.elemvalues[i],&scratch.d.row.elemnulls[i]);i++;}/*Andfinallybuildtherowvalue*/ExprEvalPushStep(state,&scratch);break;}caseT_RowCompareExpr:{RowCompareExpr*rcexpr=(RowCompareExpr*)node;intnopers=list_length(rcexpr->opnos);List*adjust_jumps=NIL;ListCell*l_left_expr,*l_right_expr,*l_opno,*l_opfamily,*l_inputcollid;ListCell*lc;intoff;/**Iterateovereachfield,preparecomparisons.Tohandle*NULLresults,preparejumpstoaftertheexpression.Ifa*comparisonyieldsa!=0result,jumptothefinalstep.*/Assert(list_length(rcexpr->largs)==nopers);Assert(list_length(rcexpr->rargs)==nopers);Assert(list_length(rcexpr->opfamilies)==nopers);Assert(list_length(rcexpr->inputcollids)==nopers);off=0;for(off=0,l_left_expr=list_head(rcexpr->largs),l_right_expr=list_head(rcexpr->rargs),l_opno=list_head(rcexpr->opnos),l_opfamily=list_head(rcexpr->opfamilies),l_inputcollid=list_head(rcexpr->inputcollids);off<nopers;off++,l_left_expr=lnext(l_left_expr),l_right_expr=lnext(l_right_expr),l_opno=lnext(l_opno),l_opfamily=lnext(l_opfamily),l_inputcollid=lnext(l_inputcollid)){Expr*left_expr=(Expr*)lfirst(l_left_expr);Expr*right_expr=(Expr*)lfirst(l_right_expr);Oidopno=lfirst_oid(l_opno);Oidopfamily=lfirst_oid(l_opfamily);Oidinputcollid=lfirst_oid(l_inputcollid);intstrategy;Oidlefttype;Oidrighttype;Oidproc;FmgrInfo*finfo;FunctionCallInfofcinfo;get_op_opfamily_properties(opno,opfamily,false,&strategy,&lefttype,&righttype);proc=get_opfamily_proc(opfamily,lefttype,righttype,BTORDER_PROC);if(!OidIsValid(proc))elog(ERROR,"missingsupportfunction%d(%u,%u)inopfamily%u",BTORDER_PROC,lefttype,righttype,opfamily);/*Setuptheprimaryfmgrlookupinformation*/finfo=palloc0(sizeof(FmgrInfo));fcinfo=palloc0(sizeof(FunctionCallInfoData));fmgr_info(proc,finfo);fmgr_info_set_expr((Node*)node,finfo);InitFunctionCallInfoData(*fcinfo,finfo,2,inputcollid,NULL,NULL);/**Ifweenforcedpermissionschecksonindexsupport*functions,we'dneedtomakeacheckhere.Butthe*indexsupportmachinerydoesn'tdothat,andthus*neitherdoesthiscode.*//*evaluateleftandrightargsdirectlyintofcinfo*/ExecInitExprRec(left_expr,state,&fcinfo->arg[0],&fcinfo->argnull[0]);ExecInitExprRec(right_expr,state,&fcinfo->arg[1],&fcinfo->argnull[1]);scratch.opcode=EEOP_ROWCOMPARE_STEP;scratch.d.rowcompare_step.finfo=finfo;scratch.d.rowcompare_step.fcinfo_data=fcinfo;scratch.d.rowcompare_step.fn_addr=finfo->fn_addr;/*jumptargetsfilledbelow*/scratch.d.rowcompare_step.jumpnull=-1;scratch.d.rowcompare_step.jumpdone=-1;ExprEvalPushStep(state,&scratch);adjust_jumps=lappend_int(adjust_jumps,state->steps_len-1);}/**Wecouldhaveazero-columnrowtype,inwhichcasetherows*necessarilycompareequal.*/if(nopers==0){scratch.opcode=EEOP_CONST;scratch.d.constval.value=Int32GetDatum(0);scratch.d.constval.isnull=false;ExprEvalPushStep(state,&scratch);}/*Finally,examinethelastcomparisonresult*/scratch.opcode=EEOP_ROWCOMPARE_FINAL;scratch.d.rowcompare_final.rctype=rcexpr->rctype;ExprEvalPushStep(state,&scratch);/*adjustjumptargetss*/foreach(lc,adjust_jumps){ExprEvalStep*as=&state->steps[lfirst_int(lc)];Assert(as->opcode==EEOP_ROWCOMPARE_STEP);Assert(as->d.rowcompare_step.jumpdone==-1);Assert(as->d.rowcompare_step.jumpnull==-1);/*jumptocomparisonevaluation*/as->d.rowcompare_step.jumpdone=state->steps_len-1;/*jumptothefollowingexpression*/as->d.rowcompare_step.jumpnull=state->steps_len;}break;}caseT_CoalesceExpr:{CoalesceExpr*coalesce=(CoalesceExpr*)node;List*adjust_jumps=NIL;ListCell*lc;/*Weassumethere'satleastonearg*/Assert(coalesce->args!=NIL);/**Prepareevaluationofallcoalescedarguments,aftereach*onepushastepthatshort-circuitsifnotnull.*/foreach(lc,coalesce->args){Expr*e=(Expr*)lfirst(lc);/*evaluateargument,directlyintoresultdatum*/ExecInitExprRec(e,state,resv,resnull);/*ifit'snotnull,skiptoendofCOALESCEexpr*/scratch.opcode=EEOP_JUMP_IF_NOT_NULL;scratch.d.jump.jumpdone=-1;/*adjustlater*/ExprEvalPushStep(state,&scratch);adjust_jumps=lappend_int(adjust_jumps,state->steps_len-1);}/**NoneedtoaddaconstantNULLreturn-weonlycangetto*theendoftheexpressionifaNULLalreadyisbeing*returned.*//*adjustjumptargets*/foreach(lc,adjust_jumps){ExprEvalStep*as=&state->steps[lfirst_int(lc)];Assert(as->opcode==EEOP_JUMP_IF_NOT_NULL);Assert(as->d.jump.jumpdone==-1);as->d.jump.jumpdone=state->steps_len;}break;}caseT_MinMaxExpr:{MinMaxExpr*minmaxexpr=(MinMaxExpr*)node;intnelems=list_length(minmaxexpr->args);TypeCacheEntry*typentry;FmgrInfo*finfo;FunctionCallInfofcinfo;ListCell*lc;intoff;/*Lookupthebtreecomparisonfunctionforthedatatype*/typentry=lookup_type_cache(minmaxexpr->minmaxtype,TYPECACHE_CMP_PROC);if(!OidIsValid(typentry->cmp_proc))ereport(ERROR,(errcode(ERRCODE_UNDEFINED_FUNCTION),errmsg("couldnotidentifyacomparisonfunctionfortype%s",format_type_be(minmaxexpr->minmaxtype))));/**Ifweenforcedpermissionschecksonindexsupport*functions,we'dneedtomakeacheckhere.Buttheindex*supportmachinerydoesn'tdothat,andthusneitherdoes*thiscode.*//*Performfunctionlookup*/finfo=palloc0(sizeof(FmgrInfo));fcinfo=palloc0(sizeof(FunctionCallInfoData));fmgr_info(typentry->cmp_proc,finfo);fmgr_info_set_expr((Node*)node,finfo);InitFunctionCallInfoData(*fcinfo,finfo,2,minmaxexpr->inputcollid,NULL,NULL);scratch.opcode=EEOP_MINMAX;/*allocatespacetostorearguments*/scratch.d.minmax.values=(Datum*)palloc(sizeof(Datum)*nelems);scratch.d.minmax.nulls=(bool*)palloc(sizeof(bool)*nelems);scratch.d.minmax.nelems=nelems;scratch.d.minmax.op=minmaxexpr->op;scratch.d.minmax.finfo=finfo;scratch.d.minmax.fcinfo_data=fcinfo;/*evaluateexpressionsintominmax->values/nulls*/off=0;foreach(lc,minmaxexpr->args){Expr*e=(Expr*)lfirst(lc);ExecInitExprRec(e,state,&scratch.d.minmax.values[off],&scratch.d.minmax.nulls[off]);off++;}/*andpushthefinalcomparison*/ExprEvalPushStep(state,&scratch);break;}caseT_SQLValueFunction:{SQLValueFunction*svf=(SQLValueFunction*)node;scratch.opcode=EEOP_SQLVALUEFUNCTION;scratch.d.sqlvaluefunction.svf=svf;ExprEvalPushStep(state,&scratch);break;}caseT_XmlExpr:{XmlExpr*xexpr=(XmlExpr*)node;intnnamed=list_length(xexpr->named_args);intnargs=list_length(xexpr->args);intoff;ListCell*arg;scratch.opcode=EEOP_XMLEXPR;scratch.d.xmlexpr.xexpr=xexpr;/*allocatespaceforstoringallthearguments*/if(nnamed){scratch.d.xmlexpr.named_argvalue=(Datum*)palloc(sizeof(Datum)*nnamed);scratch.d.xmlexpr.named_argnull=(bool*)palloc(sizeof(bool)*nnamed);}else{scratch.d.xmlexpr.named_argvalue=NULL;scratch.d.xmlexpr.named_argnull=NULL;}if(nargs){scratch.d.xmlexpr.argvalue=(Datum*)palloc(sizeof(Datum)*nargs);scratch.d.xmlexpr.argnull=(bool*)palloc(sizeof(bool)*nargs);}else{scratch.d.xmlexpr.argvalue=NULL;scratch.d.xmlexpr.argnull=NULL;}/*prepareargumentexecution*/off=0;foreach(arg,xexpr->named_args){Expr*e=(Expr*)lfirst(arg);ExecInitExprRec(e,state,&scratch.d.xmlexpr.named_argvalue[off],&scratch.d.xmlexpr.named_argnull[off]);off++;}off=0;foreach(arg,xexpr->args){Expr*e=(Expr*)lfirst(arg);ExecInitExprRec(e,state,&scratch.d.xmlexpr.argvalue[off],&scratch.d.xmlexpr.argnull[off]);off++;}/*andevaluatetheactualXMLexpression*/ExprEvalPushStep(state,&scratch);break;}caseT_NullTest:{NullTest*ntest=(NullTest*)node;if(ntest->nulltesttype==IS_NULL){if(ntest->argisrow)scratch.opcode=EEOP_NULLTEST_ROWISNULL;elsescratch.opcode=EEOP_NULLTEST_ISNULL;}elseif(ntest->nulltesttype==IS_NOT_NULL){if(ntest->argisrow)scratch.opcode=EEOP_NULLTEST_ROWISNOTNULL;elsescratch.opcode=EEOP_NULLTEST_ISNOTNULL;}else{elog(ERROR,"unrecognizednulltesttype:%d",(int)ntest->nulltesttype);}/*initializecacheincaseit'sarowtest*/scratch.d.nulltest_row.argdesc=NULL;/*firstevaluateargumentintoresultvariable*/ExecInitExprRec(ntest->arg,state,resv,resnull);/*thenpushthetestofthatargument*/ExprEvalPushStep(state,&scratch);break;}caseT_BooleanTest:{BooleanTest*btest=(BooleanTest*)node;/**Evaluateargument,directlyintoresultdatum.That'sok,*becauseresv/resnullisdefinitelynotusedanywhereelse,*andwillgetoverwrittenbythebelowEEOP_BOOLTEST_IS_**step.*/ExecInitExprRec(btest->arg,state,resv,resnull);switch(btest->booltesttype){caseIS_TRUE:scratch.opcode=EEOP_BOOLTEST_IS_TRUE;break;caseIS_NOT_TRUE:scratch.opcode=EEOP_BOOLTEST_IS_NOT_TRUE;break;caseIS_FALSE:scratch.opcode=EEOP_BOOLTEST_IS_FALSE;break;caseIS_NOT_FALSE:scratch.opcode=EEOP_BOOLTEST_IS_NOT_FALSE;break;caseIS_UNKNOWN:/*SameasscalarISNULLtest*/scratch.opcode=EEOP_NULLTEST_ISNULL;break;caseIS_NOT_UNKNOWN:/*SameasscalarISNOTNULLtest*/scratch.opcode=EEOP_NULLTEST_ISNOTNULL;break;default:elog(ERROR,"unrecognizedbooltesttype:%d",(int)btest->booltesttype);}ExprEvalPushStep(state,&scratch);break;}caseT_CoerceToDomain:{CoerceToDomain*ctest=(CoerceToDomain*)node;ExecInitCoerceToDomain(&scratch,ctest,state,resv,resnull);break;}caseT_CoerceToDomainValue:{/**Readfromlocationidentifiedbyinnermost_domainval.Note*thatinnermost_domainvalcouldbeNULL,ifwe'recompiling*astandalonedomaincheckratherthanoneembeddedina*largerexpression.Inthatcasewemustreadfrom*econtext->domainValue_datum.We'lltakecareofthat*scenarioatruntime.*/scratch.opcode=EEOP_DOMAIN_TESTVAL;/*weshareinstructionunionvariantwithcasetestval*/scratch.d.casetest.value=state->innermost_domainval;scratch.d.casetest.isnull=state->innermost_domainnull;ExprEvalPushStep(state,&scratch);break;}caseT_CurrentOfExpr:{scratch.opcode=EEOP_CURRENTOFEXPR;ExprEvalPushStep(state,&scratch);break;}caseT_NextValueExpr:{NextValueExpr*nve=(NextValueExpr*)node;scratch.opcode=EEOP_NEXTVALUEEXPR;scratch.d.nextvalueexpr.seqid=nve->seqid;scratch.d.nextvalueexpr.seqtypid=nve->typeId;ExprEvalPushStep(state,&scratch);break;}default:elog(ERROR,"unrecognizednodetype:%d",(int)nodeTag(node));break;}}/**AddanotherexpressionevaluationsteptoExprState->steps.*添加表达式解析步骤到ExprState->steps数组中.**Notethatthispotentiallyre-allocateses->steps,thereforenopointer*intothatarraymaybeusedwhiletheexpressionisstillbeingbuilt.*/voidExprEvalPushStep(ExprState*es,constExprEvalStep*s){if(es->steps_alloc==0){es->steps_alloc=16;es->steps=palloc(sizeof(ExprEvalStep)*es->steps_alloc);}elseif(es->steps_alloc==es->steps_len){es->steps_alloc*=2;es->steps=repalloc(es->steps,sizeof(ExprEvalStep)*es->steps_alloc);}memcpy(&es->steps[es->steps_len++],s,sizeof(ExprEvalStep));}三、跟踪分析
测试脚本
testdb=#select1+id,c2fromt_exprwhereid<3;
进入ExecInitExprRec,Node节点为OpExpr,执行ExprEvalPushStep压入步骤中
(gdb)stepExecInitExprRec(node=0x1c9a930,state=0x1c8f7d8,resv=0x1c8f7e0,resnull=0x1c8f7dd)atexecExpr.c:645645ExprEvalStepscratch={0};(gdb)n648check_stack_depth();(gdb)651Assert(resv!=NULL&&resnull!=NULL);(gdb)652scratch.resvalue=resv;(gdb)653scratch.resnull=resnull;(gdb)656switch(nodeTag(node))(gdb)891OpExpr*op=(OpExpr*)node;(gdb)p*node$16={type=T_OpExpr}(gdb)n893ExecInitFunc(&scratch,node,(gdb)896ExprEvalPushStep(state,&scratch);(gdb)897break;(gdb)2122}(gdb)
到此,相信大家对“怎么使用PostgreSQL中ExecInitExprRec函数”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。