PostgreSQL如何解析查询语句中的表达式列并计算得出该列的值
这篇文章主要介绍PostgreSQL如何解析查询语句中的表达式列并计算得出该列的值,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!
表达式列是指除关系定义中的系统列/定义列之外的其他投影列.比如:
testdb=#createtablet_expr(idint);CREATETABLEtestdb=#insertintot_exprvalues(1);INSERT01testdb=#insertintot_exprvalues(2);INSERT01testdb=#altertablet_expraddcolumnc2varchar(20);ALTERTABLEtestdb=#insertintot_expr(id,c2)selectx,'c2'||xfromgenerate_series(3,100000)asx;INSERT099998testdb=#select1+idfromt_expr;
该SQL语句中的”1+id”投影列视为表达式列.
一、数据结构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;二、源码解读
ExecInterpExpr函数是实现表达式列解析的主函数,解析给定”econtext”在执行上下文中通过”state”标识的表达式.
其主要实现逻辑是根据ExprState->opcode(ExprState的初始化后续再行介绍)指定的操作指定,调整到相应的实现逻辑中,执行完毕调到下一个步骤直至到达EEOP_DONE,即完成所有步骤.
/**Evaluateexpressionidentifiedby"state"intheexecutioncontext*givenby"econtext".*isnullissettotheis-nullflagfortheresult,*andtheDatumvalueisthefunctionresult.*解析给定"econtext"在执行上下文中通过"state"标识的表达式.**isnull用于设置结果是否为null,Datum是函数执行的结果.**Asaspecialcase,returnthedispatchtable'saddressifstateisNULL.*ThisisusedbyExecInitInterpretertosetupthedispatch_tableglobal.*(OnlyapplieswhenEEO_USE_COMPUTED_GOTOisdefined.)*作为一个特别的情况,如state为NULL,返回分发器表的地址.*这个情况用于ExecInitInterpreter配置dispatch_table.*(只是在定义了EEO_USE_COMPUTED_GOTO时才应用)*/staticDatumExecInterpExpr(ExprState*state,ExprContext*econtext,bool*isnull){ExprEvalStep*op;TupleTableSlot*resultslot;TupleTableSlot*innerslot;TupleTableSlot*outerslot;TupleTableSlot*scanslot;/**ThisarrayhastobeinthesameorderasenumExprEvalOp.*该数组在枚举类型ExprEvalOp中具有同样的顺序*/#ifdefined(EEO_USE_COMPUTED_GOTO)staticconstvoid*constdispatch_table[]={&&CASE_EEOP_DONE,&&CASE_EEOP_INNER_FETCHSOME,&&CASE_EEOP_OUTER_FETCHSOME,&&CASE_EEOP_SCAN_FETCHSOME,&&CASE_EEOP_INNER_VAR,&&CASE_EEOP_OUTER_VAR,&&CASE_EEOP_SCAN_VAR,&&CASE_EEOP_INNER_SYSVAR,&&CASE_EEOP_OUTER_SYSVAR,&&CASE_EEOP_SCAN_SYSVAR,&&CASE_EEOP_WHOLEROW,&&CASE_EEOP_ASSIGN_INNER_VAR,&&CASE_EEOP_ASSIGN_OUTER_VAR,&&CASE_EEOP_ASSIGN_SCAN_VAR,&&CASE_EEOP_ASSIGN_TMP,&&CASE_EEOP_ASSIGN_TMP_MAKE_RO,&&CASE_EEOP_CONST,&&CASE_EEOP_FUNCEXPR,&&CASE_EEOP_FUNCEXPR_STRICT,&&CASE_EEOP_FUNCEXPR_FUSAGE,&&CASE_EEOP_FUNCEXPR_STRICT_FUSAGE,&&CASE_EEOP_BOOL_AND_STEP_FIRST,&&CASE_EEOP_BOOL_AND_STEP,&&CASE_EEOP_BOOL_AND_STEP_LAST,&&CASE_EEOP_BOOL_OR_STEP_FIRST,&&CASE_EEOP_BOOL_OR_STEP,&&CASE_EEOP_BOOL_OR_STEP_LAST,&&CASE_EEOP_BOOL_NOT_STEP,&&CASE_EEOP_QUAL,&&CASE_EEOP_JUMP,&&CASE_EEOP_JUMP_IF_NULL,&&CASE_EEOP_JUMP_IF_NOT_NULL,&&CASE_EEOP_JUMP_IF_NOT_TRUE,&&CASE_EEOP_NULLTEST_ISNULL,&&CASE_EEOP_NULLTEST_ISNOTNULL,&&CASE_EEOP_NULLTEST_ROWISNULL,&&CASE_EEOP_NULLTEST_ROWISNOTNULL,&&CASE_EEOP_BOOLTEST_IS_TRUE,&&CASE_EEOP_BOOLTEST_IS_NOT_TRUE,&&CASE_EEOP_BOOLTEST_IS_FALSE,&&CASE_EEOP_BOOLTEST_IS_NOT_FALSE,&&CASE_EEOP_PARAM_EXEC,&&CASE_EEOP_PARAM_EXTERN,&&CASE_EEOP_PARAM_CALLBACK,&&CASE_EEOP_CASE_TESTVAL,&&CASE_EEOP_MAKE_READONLY,&&CASE_EEOP_IOCOERCE,&&CASE_EEOP_DISTINCT,&&CASE_EEOP_NOT_DISTINCT,&&CASE_EEOP_NULLIF,&&CASE_EEOP_SQLVALUEFUNCTION,&&CASE_EEOP_CURRENTOFEXPR,&&CASE_EEOP_NEXTVALUEEXPR,&&CASE_EEOP_ARRAYEXPR,&&CASE_EEOP_ARRAYCOERCE,&&CASE_EEOP_ROW,&&CASE_EEOP_ROWCOMPARE_STEP,&&CASE_EEOP_ROWCOMPARE_FINAL,&&CASE_EEOP_MINMAX,&&CASE_EEOP_FIELDSELECT,&&CASE_EEOP_FIELDSTORE_DEFORM,&&CASE_EEOP_FIELDSTORE_FORM,&&CASE_EEOP_ARRAYREF_SUBSCRIPT,&&CASE_EEOP_ARRAYREF_OLD,&&CASE_EEOP_ARRAYREF_ASSIGN,&&CASE_EEOP_ARRAYREF_FETCH,&&CASE_EEOP_DOMAIN_TESTVAL,&&CASE_EEOP_DOMAIN_NOTNULL,&&CASE_EEOP_DOMAIN_CHECK,&&CASE_EEOP_CONVERT_ROWTYPE,&&CASE_EEOP_SCALARARRAYOP,&&CASE_EEOP_XMLEXPR,&&CASE_EEOP_AGGREF,&&CASE_EEOP_GROUPING_FUNC,&&CASE_EEOP_WINDOW_FUNC,&&CASE_EEOP_SUBPLAN,&&CASE_EEOP_ALTERNATIVE_SUBPLAN,&&CASE_EEOP_AGG_STRICT_DESERIALIZE,&&CASE_EEOP_AGG_DESERIALIZE,&&CASE_EEOP_AGG_STRICT_INPUT_CHECK,&&CASE_EEOP_AGG_INIT_TRANS,&&CASE_EEOP_AGG_STRICT_TRANS_CHECK,&&CASE_EEOP_AGG_PLAIN_TRANS_BYVAL,&&CASE_EEOP_AGG_PLAIN_TRANS,&&CASE_EEOP_AGG_ORDERED_TRANS_DATUM,&&CASE_EEOP_AGG_ORDERED_TRANS_TUPLE,&&CASE_EEOP_LAST};StaticAssertStmt(EEOP_LAST+1==lengthof(dispatch_table),"dispatch_tableoutofwhackwithExprEvalOp");if(unlikely(state==NULL))//如state==NULL,则调用PointerGetDatumreturnPointerGetDatum(dispatch_table);#elseAssert(state!=NULL);#endif/*EEO_USE_COMPUTED_GOTO*//*setupstate*///配置状态变量op=state->steps;resultslot=state->resultslot;innerslot=econtext->ecxt_innertuple;outerslot=econtext->ecxt_outertuple;scanslot=econtext->ecxt_scantuple;#ifdefined(EEO_USE_COMPUTED_GOTO)EEO_DISPATCH();//分发#endifEEO_SWITCH(){EEO_CASE(EEOP_DONE){gotoout;}EEO_CASE(EEOP_INNER_FETCHSOME){/*XXX:worthwhiletochecktts_nvalidinlinefirst?*/slot_getsomeattrs(innerslot,op->d.fetch.last_var);EEO_NEXT();}EEO_CASE(EEOP_OUTER_FETCHSOME){slot_getsomeattrs(outerslot,op->d.fetch.last_var);EEO_NEXT();}EEO_CASE(EEOP_SCAN_FETCHSOME){slot_getsomeattrs(scanslot,op->d.fetch.last_var);EEO_NEXT();}EEO_CASE(EEOP_INNER_VAR){intattnum=op->d.var.attnum;/**Sincewealreadyextractedallreferencedcolumnsfromthe*tuplewithaFETCHSOMEstep,wecanjustgrabthevalue*directlyoutoftheslot'sdecomposed-dataarrays.Butlet's*haveanAsserttocheckthatthatdidhappen.*/Assert(attnum>=0&&attnum<innerslot->tts_nvalid);*op->resvalue=innerslot->tts_values[attnum];*op->resnull=innerslot->tts_isnull[attnum];EEO_NEXT();}EEO_CASE(EEOP_OUTER_VAR){intattnum=op->d.var.attnum;/*SeeEEOP_INNER_VARcomments*/Assert(attnum>=0&&attnum<outerslot->tts_nvalid);*op->resvalue=outerslot->tts_values[attnum];*op->resnull=outerslot->tts_isnull[attnum];EEO_NEXT();}EEO_CASE(EEOP_SCAN_VAR){intattnum=op->d.var.attnum;/*SeeEEOP_INNER_VARcomments*/Assert(attnum>=0&&attnum<scanslot->tts_nvalid);*op->resvalue=scanslot->tts_values[attnum];*op->resnull=scanslot->tts_isnull[attnum];EEO_NEXT();}EEO_CASE(EEOP_INNER_SYSVAR){intattnum=op->d.var.attnum;Datumd;/*theseassertsmustmatchdefensesinslot_getattr*/Assert(innerslot->tts_tuple!=NULL);Assert(innerslot->tts_tuple!=&(innerslot->tts_minhdr));/*heap_getsysattrhassufficientdefensesagainstbadattnums*/d=heap_getsysattr(innerslot->tts_tuple,attnum,innerslot->tts_tupleDescriptor,op->resnull);*op->resvalue=d;EEO_NEXT();}EEO_CASE(EEOP_OUTER_SYSVAR){intattnum=op->d.var.attnum;Datumd;/*theseassertsmustmatchdefensesinslot_getattr*/Assert(outerslot->tts_tuple!=NULL);Assert(outerslot->tts_tuple!=&(outerslot->tts_minhdr));/*heap_getsysattrhassufficientdefensesagainstbadattnums*/d=heap_getsysattr(outerslot->tts_tuple,attnum,outerslot->tts_tupleDescriptor,op->resnull);*op->resvalue=d;EEO_NEXT();}EEO_CASE(EEOP_SCAN_SYSVAR){intattnum=op->d.var.attnum;Datumd;/*theseassertsmustmatchdefensesinslot_getattr*/Assert(scanslot->tts_tuple!=NULL);Assert(scanslot->tts_tuple!=&(scanslot->tts_minhdr));/*heap_getsysattrhassufficientdefensesagainstbadattnums*/d=heap_getsysattr(scanslot->tts_tuple,attnum,scanslot->tts_tupleDescriptor,op->resnull);*op->resvalue=d;EEO_NEXT();}EEO_CASE(EEOP_WHOLEROW){/*toocomplexforaninlineimplementation*/ExecEvalWholeRowVar(state,op,econtext);EEO_NEXT();}EEO_CASE(EEOP_ASSIGN_INNER_VAR){intresultnum=op->d.assign_var.resultnum;intattnum=op->d.assign_var.attnum;/**WedonotneedCheckVarSlotCompatibilityhere;thatwastaken*careofatcompilationtime.ButseeEEOP_INNER_VARcomments.*/Assert(attnum>=0&&attnum<innerslot->tts_nvalid);resultslot->tts_values[resultnum]=innerslot->tts_values[attnum];resultslot->tts_isnull[resultnum]=innerslot->tts_isnull[attnum];EEO_NEXT();}EEO_CASE(EEOP_ASSIGN_OUTER_VAR){intresultnum=op->d.assign_var.resultnum;intattnum=op->d.assign_var.attnum;/**WedonotneedCheckVarSlotCompatibilityhere;thatwastaken*careofatcompilationtime.ButseeEEOP_INNER_VARcomments.*/Assert(attnum>=0&&attnum<outerslot->tts_nvalid);resultslot->tts_values[resultnum]=outerslot->tts_values[attnum];resultslot->tts_isnull[resultnum]=outerslot->tts_isnull[attnum];EEO_NEXT();}EEO_CASE(EEOP_ASSIGN_SCAN_VAR){intresultnum=op->d.assign_var.resultnum;intattnum=op->d.assign_var.attnum;/**WedonotneedCheckVarSlotCompatibilityhere;thatwastaken*careofatcompilationtime.ButseeEEOP_INNER_VARcomments.*/Assert(attnum>=0&&attnum<scanslot->tts_nvalid);resultslot->tts_values[resultnum]=scanslot->tts_values[attnum];resultslot->tts_isnull[resultnum]=scanslot->tts_isnull[attnum];EEO_NEXT();}EEO_CASE(EEOP_ASSIGN_TMP){intresultnum=op->d.assign_tmp.resultnum;resultslot->tts_values[resultnum]=state->resvalue;resultslot->tts_isnull[resultnum]=state->resnull;EEO_NEXT();}EEO_CASE(EEOP_ASSIGN_TMP_MAKE_RO){intresultnum=op->d.assign_tmp.resultnum;resultslot->tts_isnull[resultnum]=state->resnull;if(!resultslot->tts_isnull[resultnum])resultslot->tts_values[resultnum]=MakeExpandedObjectReadOnlyInternal(state->resvalue);elseresultslot->tts_values[resultnum]=state->resvalue;EEO_NEXT();}EEO_CASE(EEOP_CONST){*op->resnull=op->d.constval.isnull;*op->resvalue=op->d.constval.value;EEO_NEXT();}/**Function-callimplementations.Argumentshavepreviouslybeen*evaluateddirectlyintofcinfo->args.**AsbothSTRICTchecksandfunction-usagearenoticeableperformance*wise,andfunctioncallsareaveryhot-path(theyalsoback*operators!),it'sworthhavingsomanyseparateopcodes.**Note:thereasonforusingatemporaryvariable"d",hereandin*otherplaces,isthatsomecompilersthink"*op->resvalue=f();"*requiresthemtoevaluateop->resvalueintoaregisterbefore*callingf(),justincasef()isabletomodifyop->resvalue*somehow.Theextralineofcodecansaveauselessregisterspill*andreloadacrossthefunctioncall.*/EEO_CASE(EEOP_FUNCEXPR){FunctionCallInfofcinfo=op->d.func.fcinfo_data;Datumd;fcinfo->isnull=false;d=op->d.func.fn_addr(fcinfo);*op->resvalue=d;*op->resnull=fcinfo->isnull;EEO_NEXT();}EEO_CASE(EEOP_FUNCEXPR_STRICT){FunctionCallInfofcinfo=op->d.func.fcinfo_data;bool*argnull=fcinfo->argnull;intargno;Datumd;/*strictfunction,socheckforNULLargs*/for(argno=0;argno<op->d.func.nargs;argno++){if(argnull[argno]){*op->resnull=true;gotostrictfail;}}fcinfo->isnull=false;d=op->d.func.fn_addr(fcinfo);*op->resvalue=d;*op->resnull=fcinfo->isnull;strictfail:EEO_NEXT();}EEO_CASE(EEOP_FUNCEXPR_FUSAGE){/*notcommonenoughtoinline*/ExecEvalFuncExprFusage(state,op,econtext);EEO_NEXT();}EEO_CASE(EEOP_FUNCEXPR_STRICT_FUSAGE){/*notcommonenoughtoinline*/ExecEvalFuncExprStrictFusage(state,op,econtext);EEO_NEXT();}/**IfanyofitsclausesisFALSE,anAND'sresultisFALSEregardless*ofthestatesoftherestoftheclauses,sowecanstopevaluating*andreturnFALSEimmediately.IfnoneareFALSEandoneormoreis*NULL,wereturnNULL;otherwisewereturnTRUE.Thismakessense*whenyouinterpretNULLas"don'tknow":perhapsoneofthe"don't*knows"wouldhavebeenFALSEifwe'dknownitsvalue.Onlywhen*alltheinputsareknowntobeTRUEcanwestateconfidentlythat*theAND'sresultisTRUE.*/EEO_CASE(EEOP_BOOL_AND_STEP_FIRST){*op->d.boolexpr.anynull=false;/**EEOP_BOOL_AND_STEP_FIRSTresetsanynull,otherwiseit'sthe*sameasEEOP_BOOL_AND_STEP-sofallthroughtothat.*//*FALLTHROUGH*/}EEO_CASE(EEOP_BOOL_AND_STEP){if(*op->resnull){*op->d.boolexpr.anynull=true;}elseif(!DatumGetBool(*op->resvalue)){/*resultisalreadysettoFALSE,neednotchangeit*//*bailoutearly*/EEO_JUMP(op->d.boolexpr.jumpdone);}EEO_NEXT();}EEO_CASE(EEOP_BOOL_AND_STEP_LAST){if(*op->resnull){/*resultisalreadysettoNULL,neednotchangeit*/}elseif(!DatumGetBool(*op->resvalue)){/*resultisalreadysettoFALSE,neednotchangeit*//**Nopointjumpingearlytojumpdone-wouldbesametarget*(asthisisthelastargumenttotheANDexpression),*exceptmoreexpensive.*/}elseif(*op->d.boolexpr.anynull){*op->resvalue=(Datum)0;*op->resnull=true;}else{/*resultisalreadysettoTRUE,neednotchangeit*/}EEO_NEXT();}/**IfanyofitsclausesisTRUE,anOR'sresultisTRUEregardlessof*thestatesoftherestoftheclauses,sowecanstopevaluating*andreturnTRUEimmediately.IfnoneareTRUEandoneormoreis*NULL,wereturnNULL;otherwisewereturnFALSE.Thismakessense*whenyouinterpretNULLas"don'tknow":perhapsoneofthe"don't*knows"wouldhavebeenTRUEifwe'dknownitsvalue.Onlywhenall*theinputsareknowntobeFALSEcanwestateconfidentlythatthe*OR'sresultisFALSE.*/EEO_CASE(EEOP_BOOL_OR_STEP_FIRST){*op->d.boolexpr.anynull=false;/**EEOP_BOOL_OR_STEP_FIRSTresetsanynull,otherwiseit'sthesame*asEEOP_BOOL_OR_STEP-sofallthroughtothat.*//*FALLTHROUGH*/}EEO_CASE(EEOP_BOOL_OR_STEP){if(*op->resnull){*op->d.boolexpr.anynull=true;}elseif(DatumGetBool(*op->resvalue)){/*resultisalreadysettoTRUE,neednotchangeit*//*bailoutearly*/EEO_JUMP(op->d.boolexpr.jumpdone);}EEO_NEXT();}EEO_CASE(EEOP_BOOL_OR_STEP_LAST){if(*op->resnull){/*resultisalreadysettoNULL,neednotchangeit*/}elseif(DatumGetBool(*op->resvalue)){/*resultisalreadysettoTRUE,neednotchangeit*//**Nopointjumpingtojumpdone-wouldbesametarget(as*thisisthelastargumenttotheANDexpression),except*moreexpensive.*/}elseif(*op->d.boolexpr.anynull){*op->resvalue=(Datum)0;*op->resnull=true;}else{/*resultisalreadysettoFALSE,neednotchangeit*/}EEO_NEXT();}EEO_CASE(EEOP_BOOL_NOT_STEP){/**Evaluationof'not'issimple...ifexprisfalse,thenreturn*'true'andviceversa.It'ssafetodothisevenona*nominallynullvalue,soweignoreresnull;thatmeansthat*NULLinproducesNULLout,whichiswhatwewant.*/*op->resvalue=BoolGetDatum(!DatumGetBool(*op->resvalue));EEO_NEXT();}EEO_CASE(EEOP_QUAL){/*simplifiedversionofBOOL_AND_STEPforusebyExecQual()*//*Ifargument(alsoresult)isfalseornull...*/if(*op->resnull||!DatumGetBool(*op->resvalue)){/*...bailoutearly,returningFALSE*/*op->resnull=false;*op->resvalue=BoolGetDatum(false);EEO_JUMP(op->d.qualexpr.jumpdone);}/**Otherwise,leavetheTRUEvalueinplace,incasethisisthe*lastqual.Then,TRUEisthecorrectanswer.*/EEO_NEXT();}EEO_CASE(EEOP_JUMP){/*Unconditionallyjumptotargetstep*/EEO_JUMP(op->d.jump.jumpdone);}EEO_CASE(EEOP_JUMP_IF_NULL){/*Transfercontrolifcurrentresultisnull*/if(*op->resnull)EEO_JUMP(op->d.jump.jumpdone);EEO_NEXT();}EEO_CASE(EEOP_JUMP_IF_NOT_NULL){/*Transfercontrolifcurrentresultisnon-null*/if(!*op->resnull)EEO_JUMP(op->d.jump.jumpdone);EEO_NEXT();}EEO_CASE(EEOP_JUMP_IF_NOT_TRUE){/*Transfercontrolifcurrentresultisnullorfalse*/if(*op->resnull||!DatumGetBool(*op->resvalue))EEO_JUMP(op->d.jump.jumpdone);EEO_NEXT();}EEO_CASE(EEOP_NULLTEST_ISNULL){*op->resvalue=BoolGetDatum(*op->resnull);*op->resnull=false;EEO_NEXT();}EEO_CASE(EEOP_NULLTEST_ISNOTNULL){*op->resvalue=BoolGetDatum(!*op->resnull);*op->resnull=false;EEO_NEXT();}EEO_CASE(EEOP_NULLTEST_ROWISNULL){/*outoflineimplementation:toolarge*/ExecEvalRowNull(state,op,econtext);EEO_NEXT();}EEO_CASE(EEOP_NULLTEST_ROWISNOTNULL){/*outoflineimplementation:toolarge*/ExecEvalRowNotNull(state,op,econtext);EEO_NEXT();}/*BooleanTestimplementationsforallbooltesttypes*/EEO_CASE(EEOP_BOOLTEST_IS_TRUE){if(*op->resnull){*op->resvalue=BoolGetDatum(false);*op->resnull=false;}/*else,inputvalueisthecorrectoutputaswell*/EEO_NEXT();}EEO_CASE(EEOP_BOOLTEST_IS_NOT_TRUE){if(*op->resnull){*op->resvalue=BoolGetDatum(true);*op->resnull=false;}else*op->resvalue=BoolGetDatum(!DatumGetBool(*op->resvalue));EEO_NEXT();}EEO_CASE(EEOP_BOOLTEST_IS_FALSE){if(*op->resnull){*op->resvalue=BoolGetDatum(false);*op->resnull=false;}else*op->resvalue=BoolGetDatum(!DatumGetBool(*op->resvalue));EEO_NEXT();}EEO_CASE(EEOP_BOOLTEST_IS_NOT_FALSE){if(*op->resnull){*op->resvalue=BoolGetDatum(true);*op->resnull=false;}/*else,inputvalueisthecorrectoutputaswell*/EEO_NEXT();}EEO_CASE(EEOP_PARAM_EXEC){/*outoflineimplementation:toolarge*/ExecEvalParamExec(state,op,econtext);EEO_NEXT();}EEO_CASE(EEOP_PARAM_EXTERN){/*outoflineimplementation:toolarge*/ExecEvalParamExtern(state,op,econtext);EEO_NEXT();}EEO_CASE(EEOP_PARAM_CALLBACK){/*allowanextensionmoduletosupplyaPARAM_EXTERNvalue*/op->d.cparam.paramfunc(state,op,econtext);EEO_NEXT();}EEO_CASE(EEOP_CASE_TESTVAL){/**Normallyupperpartsoftheexpressiontreehavesetupthe*valuestobereturnedhere,butsomepartsofthesystem*currentlymisuse{caseValue,domainValue}_{datum,isNull}toset*run-timedata.Soifnovalueshavebeenset-up,use*ExprContext's.Thisisn'tpretty,butalsonot*that*ugly,*andthisisunlikelytobeperformancesensitiveenoughto*worryaboutanextrabranch.*/if(op->d.casetest.value){*op->resvalue=*op->d.casetest.value;*op->resnull=*op->d.casetest.isnull;}else{*op->resvalue=econtext->caseValue_datum;*op->resnull=econtext->caseValue_isNull;}EEO_NEXT();}EEO_CASE(EEOP_DOMAIN_TESTVAL){/**SeeEEOP_CASE_TESTVALcomment.*/if(op->d.casetest.value){*op->resvalue=*op->d.casetest.value;*op->resnull=*op->d.casetest.isnull;}else{*op->resvalue=econtext->domainValue_datum;*op->resnull=econtext->domainValue_isNull;}EEO_NEXT();}EEO_CASE(EEOP_MAKE_READONLY){/**ForceavarlenavaluethatmightbereadmultipletimestoR/O*/if(!*op->d.make_readonly.isnull)*op->resvalue=MakeExpandedObjectReadOnlyInternal(*op->d.make_readonly.value);*op->resnull=*op->d.make_readonly.isnull;EEO_NEXT();}EEO_CASE(EEOP_IOCOERCE){/**EvaluateaCoerceViaIOnode.Thiscanbequiteahotpath,so*inlineasmuchworkaspossible.Thesourcevalueisinour*resultvariable.*/char*str;/*calloutputfunction(similartoOutputFunctionCall)*/if(*op->resnull){/*outputfunctionsarenotcalledonnulls*/str=NULL;}else{FunctionCallInfofcinfo_out;fcinfo_out=op->d.iocoerce.fcinfo_data_out;fcinfo_out->arg[0]=*op->resvalue;fcinfo_out->argnull[0]=false;fcinfo_out->isnull=false;str=DatumGetCString(FunctionCallInvoke(fcinfo_out));/*OutputFunctionCallassumesresultisn'tnull*/Assert(!fcinfo_out->isnull);}/*callinputfunction(similartoInputFunctionCall)*/if(!op->d.iocoerce.finfo_in->fn_strict||str!=NULL){FunctionCallInfofcinfo_in;Datumd;fcinfo_in=op->d.iocoerce.fcinfo_data_in;fcinfo_in->arg[0]=PointerGetDatum(str);fcinfo_in->argnull[0]=*op->resnull;/*secondandthirdargumentsarealreadysetup*/fcinfo_in->isnull=false;d=FunctionCallInvoke(fcinfo_in);*op->resvalue=d;/*ShouldgetnullresultifandonlyifstrisNULL*/if(str==NULL){Assert(*op->resnull);Assert(fcinfo_in->isnull);}else{Assert(!*op->resnull);Assert(!fcinfo_in->isnull);}}EEO_NEXT();}EEO_CASE(EEOP_DISTINCT){/**ISDISTINCTFROMmustevaluatearguments(alreadydoneinto*fcinfo->arg/argnull)todeterminewhethertheyareNULL;if*eitherisNULLthentheresultisdetermined.Ifneitheris*NULL,thenproceedtoevaluatethecomparisonfunction,which*isjustthetype'sstandardequalityoperator.Weneednot*carewhetherthatfunctionisstrict.Becausethehandlingof*nullsisdifferent,wecan'tjustreuseEEOP_FUNCEXPR.*/FunctionCallInfofcinfo=op->d.func.fcinfo_data;/*checkfunctionargumentsforNULLness*/if(fcinfo->argnull[0]&&fcinfo->argnull[1]){/*BothNULL?Thenisnotdistinct...*/*op->resvalue=BoolGetDatum(false);*op->resnull=false;}elseif(fcinfo->argnull[0]||fcinfo->argnull[1]){/*OnlyoneisNULL?Thenisdistinct...*/*op->resvalue=BoolGetDatum(true);*op->resnull=false;}else{/*Neithernull,soapplytheequalityfunction*/Datumeqresult;fcinfo->isnull=false;eqresult=op->d.func.fn_addr(fcinfo);/*Mustinvertresultof"=";safetodoevenifnull*/*op->resvalue=BoolGetDatum(!DatumGetBool(eqresult));*op->resnull=fcinfo->isnull;}EEO_NEXT();}/*seeEEOP_DISTINCTforcomments,thisisjustinverted*/EEO_CASE(EEOP_NOT_DISTINCT){FunctionCallInfofcinfo=op->d.func.fcinfo_data;if(fcinfo->argnull[0]&&fcinfo->argnull[1]){*op->resvalue=BoolGetDatum(true);*op->resnull=false;}elseif(fcinfo->argnull[0]||fcinfo->argnull[1]){*op->resvalue=BoolGetDatum(false);*op->resnull=false;}else{Datumeqresult;fcinfo->isnull=false;eqresult=op->d.func.fn_addr(fcinfo);*op->resvalue=eqresult;*op->resnull=fcinfo->isnull;}EEO_NEXT();}EEO_CASE(EEOP_NULLIF){/**Theargumentsarealreadyevaluatedintofcinfo->arg/argnull.*/FunctionCallInfofcinfo=op->d.func.fcinfo_data;/*ifeitherargumentisNULLtheycan'tbeequal*/if(!fcinfo->argnull[0]&&!fcinfo->argnull[1]){Datumresult;fcinfo->isnull=false;result=op->d.func.fn_addr(fcinfo);/*iftheargumentsareequalreturnnull*/if(!fcinfo->isnull&&DatumGetBool(result)){*op->resvalue=(Datum)0;*op->resnull=true;EEO_NEXT();}}/*Argumentsaren'tequal,soreturnthefirstone*/*op->resvalue=fcinfo->arg[0];*op->resnull=fcinfo->argnull[0];EEO_NEXT();}EEO_CASE(EEOP_SQLVALUEFUNCTION){/**Doesn'tseemworthwhiletohaveaninlineimplementation*efficiency-wise.*/ExecEvalSQLValueFunction(state,op);EEO_NEXT();}EEO_CASE(EEOP_CURRENTOFEXPR){/*errorinvocationusesspace,andshouldn'teveroccur*/ExecEvalCurrentOfExpr(state,op);EEO_NEXT();}EEO_CASE(EEOP_NEXTVALUEEXPR){/**Doesn'tseemworthwhiletohaveaninlineimplementation*efficiency-wise.*/ExecEvalNextValueExpr(state,op);EEO_NEXT();}EEO_CASE(EEOP_ARRAYEXPR){/*toocomplexforaninlineimplementation*/ExecEvalArrayExpr(state,op);EEO_NEXT();}EEO_CASE(EEOP_ARRAYCOERCE){/*toocomplexforaninlineimplementation*/ExecEvalArrayCoerce(state,op,econtext);EEO_NEXT();}EEO_CASE(EEOP_ROW){/*toocomplexforaninlineimplementation*/ExecEvalRow(state,op);EEO_NEXT();}EEO_CASE(EEOP_ROWCOMPARE_STEP){FunctionCallInfofcinfo=op->d.rowcompare_step.fcinfo_data;Datumd;/*forceNULLresultifstrictfnandNULLinput*/if(op->d.rowcompare_step.finfo->fn_strict&&(fcinfo->argnull[0]||fcinfo->argnull[1])){*op->resnull=true;EEO_JUMP(op->d.rowcompare_step.jumpnull);}/*Applycomparisonfunction*/fcinfo->isnull=false;d=op->d.rowcompare_step.fn_addr(fcinfo);*op->resvalue=d;/*forceNULLresultifNULLfunctionresult*/if(fcinfo->isnull){*op->resnull=true;EEO_JUMP(op->d.rowcompare_step.jumpnull);}*op->resnull=false;/*Ifunequal,noneedtocompareremainingcolumns*/if(DatumGetInt32(*op->resvalue)!=0){EEO_JUMP(op->d.rowcompare_step.jumpdone);}EEO_NEXT();}EEO_CASE(EEOP_ROWCOMPARE_FINAL){int32cmpresult=DatumGetInt32(*op->resvalue);RowCompareTyperctype=op->d.rowcompare_final.rctype;*op->resnull=false;switch(rctype){/*EQandNEcasesaren'tallowedhere*/caseROWCOMPARE_LT:*op->resvalue=BoolGetDatum(cmpresult<0);break;caseROWCOMPARE_LE:*op->resvalue=BoolGetDatum(cmpresult<=0);break;caseROWCOMPARE_GE:*op->resvalue=BoolGetDatum(cmpresult>=0);break;caseROWCOMPARE_GT:*op->resvalue=BoolGetDatum(cmpresult>0);break;default:Assert(false);break;}EEO_NEXT();}EEO_CASE(EEOP_MINMAX){/*toocomplexforaninlineimplementation*/ExecEvalMinMax(state,op);EEO_NEXT();}EEO_CASE(EEOP_FIELDSELECT){/*toocomplexforaninlineimplementation*/ExecEvalFieldSelect(state,op,econtext);EEO_NEXT();}EEO_CASE(EEOP_FIELDSTORE_DEFORM){/*toocomplexforaninlineimplementation*/ExecEvalFieldStoreDeForm(state,op,econtext);EEO_NEXT();}EEO_CASE(EEOP_FIELDSTORE_FORM){/*toocomplexforaninlineimplementation*/ExecEvalFieldStoreForm(state,op,econtext);EEO_NEXT();}EEO_CASE(EEOP_ARRAYREF_SUBSCRIPT){/*Processanarraysubscript*//*toocomplexforaninlineimplementation*/if(ExecEvalArrayRefSubscript(state,op)){EEO_NEXT();}else{/*Subscriptisnull,short-circuitArrayReftoNULL*/EEO_JUMP(op->d.arrayref_subscript.jumpdone);}}EEO_CASE(EEOP_ARRAYREF_OLD){/**Fetchtheoldvalueinanarrayrefassignment,incaseit's*referenced(viaaCaseTestExpr)insidetheassignment*expression.*//*toocomplexforaninlineimplementation*/ExecEvalArrayRefOld(state,op);EEO_NEXT();}/**PerformArrayRefassignment*/EEO_CASE(EEOP_ARRAYREF_ASSIGN){/*toocomplexforaninlineimplementation*/ExecEvalArrayRefAssign(state,op);EEO_NEXT();}/**Fetchsubsetofanarray.*/EEO_CASE(EEOP_ARRAYREF_FETCH){/*toocomplexforaninlineimplementation*/ExecEvalArrayRefFetch(state,op);EEO_NEXT();}EEO_CASE(EEOP_CONVERT_ROWTYPE){/*toocomplexforaninlineimplementation*/ExecEvalConvertRowtype(state,op,econtext);EEO_NEXT();}EEO_CASE(EEOP_SCALARARRAYOP){/*toocomplexforaninlineimplementation*/ExecEvalScalarArrayOp(state,op);EEO_NEXT();}EEO_CASE(EEOP_DOMAIN_NOTNULL){/*toocomplexforaninlineimplementation*/ExecEvalConstraintNotNull(state,op);EEO_NEXT();}EEO_CASE(EEOP_DOMAIN_CHECK){/*toocomplexforaninlineimplementation*/ExecEvalConstraintCheck(state,op);EEO_NEXT();}EEO_CASE(EEOP_XMLEXPR){/*toocomplexforaninlineimplementation*/ExecEvalXmlExpr(state,op);EEO_NEXT();}EEO_CASE(EEOP_AGGREF){/**ReturnsaDatumwhosevalueistheprecomputedaggregatevalue*foundinthegivenexpressioncontext.*/AggrefExprState*aggref=op->d.aggref.astate;Assert(econtext->ecxt_aggvalues!=NULL);*op->resvalue=econtext->ecxt_aggvalues[aggref->aggno];*op->resnull=econtext->ecxt_aggnulls[aggref->aggno];EEO_NEXT();}EEO_CASE(EEOP_GROUPING_FUNC){/*toocomplex/uncommonforaninlineimplementation*/ExecEvalGroupingFunc(state,op);EEO_NEXT();}EEO_CASE(EEOP_WINDOW_FUNC){/**LikeAggref,justreturnaprecomputedvaluefromtheecontext.*/WindowFuncExprState*wfunc=op->d.window_func.wfstate;Assert(econtext->ecxt_aggvalues!=NULL);*op->resvalue=econtext->ecxt_aggvalues[wfunc->wfuncno];*op->resnull=econtext->ecxt_aggnulls[wfunc->wfuncno];EEO_NEXT();}EEO_CASE(EEOP_SUBPLAN){/*toocomplexforaninlineimplementation*/ExecEvalSubPlan(state,op,econtext);EEO_NEXT();}EEO_CASE(EEOP_ALTERNATIVE_SUBPLAN){/*toocomplexforaninlineimplementation*/ExecEvalAlternativeSubPlan(state,op,econtext);EEO_NEXT();}/*evaluateastrictaggregatedeserializationfunction*/EEO_CASE(EEOP_AGG_STRICT_DESERIALIZE){bool*argnull=op->d.agg_deserialize.fcinfo_data->argnull;/*Don'tcallastrictdeserializationfunctionwithNULLinput*/if(argnull[0])EEO_JUMP(op->d.agg_deserialize.jumpnull);/*fallthrough*/}/*evaluateaggregatedeserializationfunction(non-strictportion)*/EEO_CASE(EEOP_AGG_DESERIALIZE){FunctionCallInfofcinfo=op->d.agg_deserialize.fcinfo_data;AggState*aggstate=op->d.agg_deserialize.aggstate;MemoryContextoldContext;/**Werunthedeserializationfunctionsinper-input-tuplememory*context.*/oldContext=MemoryContextSwitchTo(aggstate->tmpcontext->ecxt_per_tuple_memory);fcinfo->isnull=false;*op->resvalue=FunctionCallInvoke(fcinfo);*op->resnull=fcinfo->isnull;MemoryContextSwitchTo(oldContext);EEO_NEXT();}/**Checkthatastrictaggregatetransition/combinationfunction's*inputisnotNULL.*/EEO_CASE(EEOP_AGG_STRICT_INPUT_CHECK){intargno;bool*nulls=op->d.agg_strict_input_check.nulls;intnargs=op->d.agg_strict_input_check.nargs;for(argno=0;argno<nargs;argno++){if(nulls[argno])EEO_JUMP(op->d.agg_strict_input_check.jumpnull);}EEO_NEXT();}/**Initializeanaggregate'sfirstvalueifnecessary.*/EEO_CASE(EEOP_AGG_INIT_TRANS){AggState*aggstate;AggStatePerGrouppergroup;aggstate=op->d.agg_init_trans.aggstate;pergroup=&aggstate->all_pergroups[op->d.agg_init_trans.setoff][op->d.agg_init_trans.transno];/*IftransValuehasnotyetbeeninitialized,dosonow.*/if(pergroup->noTransValue){AggStatePerTranspertrans=op->d.agg_init_trans.pertrans;aggstate->curaggcontext=op->d.agg_init_trans.aggcontext;aggstate->current_set=op->d.agg_init_trans.setno;ExecAggInitGroup(aggstate,pertrans,pergroup);/*copiedtransvaluefrominput,donethisround*/EEO_JUMP(op->d.agg_init_trans.jumpnull);}EEO_NEXT();}/*checkthatastrictaggregate'sinputisn'tNULL*/EEO_CASE(EEOP_AGG_STRICT_TRANS_CHECK){AggState*aggstate;AggStatePerGrouppergroup;aggstate=op->d.agg_strict_trans_check.aggstate;pergroup=&aggstate->all_pergroups[op->d.agg_strict_trans_check.setoff][op->d.agg_strict_trans_check.transno];if(unlikely(pergroup->transValueIsNull))EEO_JUMP(op->d.agg_strict_trans_check.jumpnull);EEO_NEXT();}/**Evaluateaggregatetransition/combinefunctionthathasa*by-valuetransitiontype.That'saseperatecasefromthe*by-referenceimplementationbecauseit'sabitsimpler.*/EEO_CASE(EEOP_AGG_PLAIN_TRANS_BYVAL){AggState*aggstate;AggStatePerTranspertrans;AggStatePerGrouppergroup;FunctionCallInfofcinfo;MemoryContextoldContext;DatumnewVal;aggstate=op->d.agg_trans.aggstate;pertrans=op->d.agg_trans.pertrans;pergroup=&aggstate->all_pergroups[op->d.agg_trans.setoff][op->d.agg_trans.transno];Assert(pertrans->transtypeByVal);fcinfo=&pertrans->transfn_fcinfo;/*cf.select_current_set()*/aggstate->curaggcontext=op->d.agg_trans.aggcontext;aggstate->current_set=op->d.agg_trans.setno;/*setupaggstate->curpertransforAggGetAggref()*/aggstate->curpertrans=pertrans;/*invoketransitionfunctioninper-tuplecontext*/oldContext=MemoryContextSwitchTo(aggstate->tmpcontext->ecxt_per_tuple_memory);fcinfo->arg[0]=pergroup->transValue;fcinfo->argnull[0]=pergroup->transValueIsNull;fcinfo->isnull=false;/*justincasetransfndoesn'tsetit*/newVal=FunctionCallInvoke(fcinfo);pergroup->transValue=newVal;pergroup->transValueIsNull=fcinfo->isnull;MemoryContextSwitchTo(oldContext);EEO_NEXT();}/**Evaluateaggregatetransition/combinefunctionthathasa*by-referencetransitiontype.**Couldoptimizeabitfurtherbysplittingoffby-reference*fixed-lengthtypes,butcurrentlythatdoesn'tseemworthit.*/EEO_CASE(EEOP_AGG_PLAIN_TRANS){AggState*aggstate;AggStatePerTranspertrans;AggStatePerGrouppergroup;FunctionCallInfofcinfo;MemoryContextoldContext;DatumnewVal;aggstate=op->d.agg_trans.aggstate;pertrans=op->d.agg_trans.pertrans;pergroup=&aggstate->all_pergroups[op->d.agg_trans.setoff][op->d.agg_trans.transno];Assert(!pertrans->transtypeByVal);fcinfo=&pertrans->transfn_fcinfo;/*cf.select_current_set()*/aggstate->curaggcontext=op->d.agg_trans.aggcontext;aggstate->current_set=op->d.agg_trans.setno;/*setupaggstate->curpertransforAggGetAggref()*/aggstate->curpertrans=pertrans;/*invoketransitionfunctioninper-tuplecontext*/oldContext=MemoryContextSwitchTo(aggstate->tmpcontext->ecxt_per_tuple_memory);fcinfo->arg[0]=pergroup->transValue;fcinfo->argnull[0]=pergroup->transValueIsNull;fcinfo->isnull=false;/*justincasetransfndoesn'tsetit*/newVal=FunctionCallInvoke(fcinfo);/**Forpass-by-refdatatype,mustcopythenewvalueinto*aggcontextandfreethepriortransValue.Butiftransfn*returnedapointertoitsfirstinput,wedon'tneedtodo*anything.Also,iftransfnreturnedapointertoaR/W*expandedobjectthatisalreadyachildoftheaggcontext,*assumewecanadoptthatvaluewithoutcopyingit.*/if(DatumGetPointer(newVal)!=DatumGetPointer(pergroup->transValue))newVal=ExecAggTransReparent(aggstate,pertrans,newVal,fcinfo->isnull,pergroup->transValue,pergroup->transValueIsNull);pergroup->transValue=newVal;pergroup->transValueIsNull=fcinfo->isnull;MemoryContextSwitchTo(oldContext);EEO_NEXT();}/*processsingle-columnorderedaggregatedatum*/EEO_CASE(EEOP_AGG_ORDERED_TRANS_DATUM){/*toocomplexforaninlineimplementation*/ExecEvalAggOrderedTransDatum(state,op,econtext);EEO_NEXT();}/*processmulti-columnorderedaggregatetuple*/EEO_CASE(EEOP_AGG_ORDERED_TRANS_TUPLE){/*toocomplexforaninlineimplementation*/ExecEvalAggOrderedTransTuple(state,op,econtext);EEO_NEXT();}EEO_CASE(EEOP_LAST){/*unreachable*/Assert(false);gotoout;}}out:*isnull=state->resnull;returnstate->resvalue;}三、跟踪分析
测试脚本
testdb=#altertablet_expraddprimarykey(id);ALTERTABLEtestdb=#select1+idfromt_exprwhereid<3;
调用栈
(gdb)bt#0ExecInterpExpr(state=0x1e6baa8,econtext=0x1e6b6d8,isnull=0x7fffdbc3b877)atexecExprInterp.c:402#10x00000000006cd7edinExecInterpExprStillValid(state=0x1e6baa8,econtext=0x1e6b6d8,isNull=0x7fffdbc3b877)atexecExprInterp.c:1786#20x00000000006e1f7finExecEvalExprSwitchContext(state=0x1e6baa8,econtext=0x1e6b6d8,isNull=0x7fffdbc3b877)at../../../src/include/executor/executor.h:313#30x00000000006e1fe8inExecProject(projInfo=0x1e6baa0)at../../../src/include/executor/executor.h:347#40x00000000006e2358inExecScan(node=0x1e6b5c0,accessMtd=0x7103a9<SeqNext>,recheckMtd=0x710474<SeqRecheck>)atexecScan.c:201#50x00000000007104beinExecSeqScan(pstate=0x1e6b5c0)atnodeSeqscan.c:129#60x00000000006e05bbinExecProcNodeFirst(node=0x1e6b5c0)atexecProcnode.c:445#70x00000000006d551einExecProcNode(node=0x1e6b5c0)at../../../src/include/executor/executor.h:247#80x00000000006d7d56inExecutePlan(estate=0x1e6b3a8,planstate=0x1e6b5c0,use_parallel_mode=false,operation=CMD_SELECT,sendTuples=true,numberTuples=0,direction=ForwardScanDirection,dest=0x1e5ff50,execute_once=true)atexecMain.c:1723#90x00000000006d5ae8instandard_ExecutorRun(queryDesc=0x1da77e8,direction=ForwardScanDirection,count=0,execute_once=true)atexecMain.c:364#100x00000000006d5910inExecutorRun(queryDesc=0x1da77e8,direction=ForwardScanDirection,count=0,execute_once=true)atexecMain.c:307#110x00000000008c2206inPortalRunSelect(portal=0x1df4608,forward=true,count=0,dest=0x1e5ff50)atpquery.c:932#120x00000000008c1ea4inPortalRun(portal=0x1df4608,count=9223372036854775807,isTopLevel=true,run_once=true,dest=0x1e5ff50,altdest=0x1e5ff50,completionTag=0x7fffdbc3bc20"")atpquery.c:773#130x00000000008bbf06inexec_simple_query(query_string=0x1d85d78"select1+idfromt_expr;")atpostgres.c:1145#140x00000000008c0191inPostgresMain(argc=1,argv=0x1db3cd8,dbname=0x1db3b40"testdb",username=0x1db3b20"xdb")atpostgres.c:4182#150x000000000081e06cinBackendRun(port=0x1da7ae0)atpostmaster.c:4361#160x000000000081d7dfinBackendStartup(port=0x1da7ae0)atpostmaster.c:4033#170x0000000000819bd9inServerLoop()atpostmaster.c:1706---Type<return>tocontinue,orq<return>toquit---#180x000000000081948finPostmasterMain(argc=1,argv=0x1d80a50)atpostmaster.c:1379#190x0000000000742931inmain(argc=1,argv=0x1d80a50)atmain.c:228
跟踪分析
进入ExecInterpExpr
Breakpoint1,ExecInterpExpr(state=0x1e67678,econtext=0x1e672a8,isnull=0x7fffdbc3b897)atexecExprInterp.c:402402if(unlikely(state==NULL))(gdb)cContinuing.Breakpoint1,ExecInterpExpr(state=0x1e67678,econtext=0x1e672a8,isnull=0x7fffdbc3b877)atexecExprInterp.c:402402if(unlikely(state==NULL))
获取步骤数组和相关的slot
(gdb)n409op=state->steps;(gdb)410resultslot=state->resultslot;(gdb)411innerslot=econtext->ecxt_innertuple;(gdb)412outerslot=econtext->ecxt_outertuple;(gdb)p*econtext$21={type=T_ExprContext,ecxt_scantuple=0x1e673a0,ecxt_innertuple=0x0,ecxt_outertuple=0x0,ecxt_per_query_memory=0x1e66e60,ecxt_per_tuple_memory=0x1e6d290,ecxt_param_exec_vals=0x0,ecxt_param_list_info=0x0,ecxt_aggvalues=0x0,ecxt_aggnulls=0x0,caseValue_datum=0,caseValue_isNull=true,domainValue_datum=0,domainValue_isNull=true,ecxt_estate=0x1e66f78,ecxt_callbacks=0x0}(gdb)n413scanslot=econtext->ecxt_scantuple;(gdb)(gdb)p*scanslot$22={type=T_TupleTableSlot,tts_isempty=false,tts_shouldFree=false,tts_shouldFreeMin=false,tts_slow=false,tts_tuple=0x1e683f0,tts_tupleDescriptor=0x7fa4f307fab8,tts_mcxt=0x1e66e60,tts_buffer=98,tts_nvalid=0,tts_values=0x1e67400,tts_isnull=0x1e67408,tts_mintuple=0x0,tts_minhdr={t_len=0,t_self={ip_blkid={bi_hi=0,bi_lo=0},ip_posid=0},t_tableOid=0,t_data=0x0},tts_off=0,tts_fixedTupleDescriptor=true}
进行分发
416EEO_DISPATCH();
首先是EEOP_SCAN_FETCHSOME(STEP 1),获取结果slot
(gdb)n443slot_getsomeattrs(scanslot,op->d.fetch.last_var);(gdb)n445EEO_NEXT();(gdb)
跳转到下一个步骤EEOP_SCAN_VAR(STEP 2),获取扫描获得的id列值
480intattnum=op->d.var.attnum;(gdb)484Assert(attnum>=0&&attnum<scanslot->tts_nvalid);(gdb)485*op->resvalue=scanslot->tts_values[attnum];(gdb)486*op->resnull=scanslot->tts_isnull[attnum];(gdb)488EEO_NEXT();(gdb)
跳转到下一个步骤EEOP_FUNCEXPR_STRICT(STEP 3)
首先获取函数调用信息(参数),然后根据参数个数循环判断,接着调用实际的函数(fn_addr指向的函数),调用后赋值给联合体d.
663FunctionCallInfofcinfo=op->d.func.fcinfo_data;(gdb)664bool*argnull=fcinfo->argnull;(gdb)pfcinfo$23=(FunctionCallInfo)0x1e67b78(gdb)p*fcinfo$24={flinfo=0x1e67b20,context=0x0,resultinfo=0x0,fncollation=0,isnull=false,nargs=2,arg={1,1,0<repeats98times>},argnull={false<repeats100times>}}(gdb)p*fcinfo->flinfo$25={fn_addr=0x93d60c<int4pl>,fn_oid=177,fn_nargs=2,fn_strict=true,fn_retset=false,fn_stats=2'\002',fn_extra=0x0,fn_mcxt=0x1e66e60,fn_expr=0x1d87bf8}(gdb)p*fcinfo->flinfo->fn_expr$26={type=T_OpExpr}(gdb)n669for(argno=0;argno<op->d.func.nargs;argno++)(gdb)671if(argnull[argno])(gdb)669for(argno=0;argno<op->d.func.nargs;argno++)(gdb)671if(argnull[argno])(gdb)669for(argno=0;argno<op->d.func.nargs;argno++)(gdb)677fcinfo->isnull=false;(gdb)678d=op->d.func.fn_addr(fcinfo);(gdb)679*op->resvalue=d;(gdb)680*op->resnull=fcinfo->isnull;(gdb)683EEO_NEXT();(gdb)
跳转到下一个步骤EEOP_ASSIGN_TMP(STEP 4),获取结果列所在的编号,赋值
603intresultnum=op->d.assign_tmp.resultnum;(gdb)605resultslot->tts_values[resultnum]=state->resvalue;(gdb)606resultslot->tts_isnull[resultnum]=state->resnull;(gdb)pstate->resvalue$27=2(gdb)n608EEO_NEXT();
跳转到下一个步骤,EEO_DONE(STEP 5)
(gdb)423gotoout;
退出,返回结果值
(gdb)n1764*isnull=state->resnull;(gdb)1765returnstate->resvalue;(gdb)1766}(gdb)ExecInterpExprStillValid(state=0x1e67678,econtext=0x1e672a8,isNull=0x7fffdbc3b877)atexecExprInterp.c:17871787}(gdb)cContinuing.
以上是“PostgreSQL如何解析查询语句中的表达式列并计算得出该列的值”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注亿速云行业资讯频道!
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。