返回顶部
首页 > 资讯 > 数据库 >PostgreSQL如何构建表达式解析
  • 429
分享到

PostgreSQL如何构建表达式解析

2024-04-02 19:04:59 429人浏览 泡泡鱼
摘要

这篇文章主要介绍postgresql如何构建表达式解析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!一、数据结构EEO_XXX宏定义opcode分发器宏定义 #if def

这篇文章主要介绍postgresql如何构建表达式解析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

一、数据结构

EEO_XXX宏定义
opcode分发器宏定义


#if defined(EEO_USE_COMPUTED_GoTO)
//--------------- 定义了EEO_USE_COMPUTED_GOTO

//跳转target -> opcode搜索表结构体
typedef struct ExprEvalOpLookup
{
    const void *opcode;
    ExprEvalOp  op;
} ExprEvalOpLookup;

static const void **dispatch_table = NULL;

static ExprEvalOpLookup reverse_dispatch_table[EEOP_LAST];
#define EEO_SWITCH()
#define EEO_CASE(name)      CASE_##name:
#define EEO_DISPATCH()      goto *((void *) op->opcode)
#define EEO_OPCODE(opcode)  ((intptr_t) dispatch_table[opcode])
#else                           
//--------------- 没有定义EEO_USE_COMPUTED_GOTO
#define EEO_SWITCH()        starteval: switch ((ExprEvalOp) op->opcode)
#define EEO_CASE(name)      case name:
#define EEO_DISPATCH()      goto starteval
#define EEO_OPCODE(opcode)  (opcode)
#endif                          
#define EEO_NEXT() \
    do { \
        op++; \
        EEO_DISPATCH(); \
    } while (0)
#define EEO_JUMP(stepno) \
    do { \
        op = &state->steps[stepno]; \
        EEO_DISPATCH(); \
    } while (0)

ExprState
解析表达式中运行期状态节点



#define EEO_FLAG_IS_QUAL                    (1 << 0)
typedef struct ExprState
{
    //节点tag
    node        tag;
    //EEO_FLAG_IS_QUAL
    uint8       flags;          
    
#define FIELDNO_EXPRSTATE_RESNULL 2
    bool        resnull;
#define FIELDNO_EXPRSTATE_RESVALUE 3
    Datum       resvalue;
    
#define FIELDNO_EXPRSTATE_RESULTSLOT 4
    TupleTableSlot *resultslot;
    
    struct ExprEvalStep *steps;
    
    ExprStateEvalFunc evalfunc;
    
    //原始的表达式树,仅用于debugging
    Expr       *expr;
    
    //evalfunc的私有状态
    void       *evalfunc_private;
    
    //当前的步数
    int         steps_len;      
    //steps数组已分配的长度
    int         steps_alloc;    
    //父PlanState节点(如存在)
    struct PlanState *parent;   
    //用于编译PARAM_EXTERN节点
    ParamListInfo ext_params;   
    //
    Datum      *innermost_caseval;
    bool       *innermost_casenull;
    Datum      *innermost_domainval;
    bool       *innermost_domainnull;
} ExprState;

ExprEvalStep
表达式解析步骤结构体

typedef struct ExprEvalStep
{
    
    intptr_t    opcode;
    
    //存储该步骤的结果
    Datum      *resvalue;
    bool       *resnull;
    
    uNIOn
    {
        
        //用于EEOP_INNER/OUTER/SCAN_FETCHSOME
        struct
        {
            
            //获取到的属性编号
            int         last_var;
            TupleDesc   known_desc;
        }           fetch;
        
        struct
        {
            
            //attnum是常规VAR的attr number - 1
            
            //对于SYSVAR,该值是常规的attr number
            int         attnum;
            Oid         vartype;    
        }           var;
        
        struct
        {
            Var        *var;    
            bool        first;  
            bool        slow;   
            TupleDesc   tupdesc;    
            JunkFilter *junkFilter; 
        }           wholerow;
        
        struct
        {
            
            int         resultnum;
            
            int         attnum;
        }           assign_var;
        
        struct
        {
            
            int         resultnum;
        }           assign_tmp;
        
        struct
        {
            
            Datum       value;
            bool        isnull;
        }           constval;
        
        //对于EEOP_FUNCEXPR_* / NULLIF / DISTINCT
        struct
        {
            //函数的检索数据
            FmgrInfo   *finfo;  
            //参数信息等
            FunctionCallInfo fcinfo_data;   
            
            //无需额外的指向,更快速的访问
            PGFunction  fn_addr;    
            int         nargs;  
        }           func;
        
        struct
        {
            bool       *anynull;    
            int         jumpdone;   
        }           boolexpr;
        
        struct
        {
            int         jumpdone;   
        }           qualexpr;
        
        struct
        {
            int         jumpdone;   
        }           jump;
        
        struct
        {
            
            TupleDesc   argdesc;
        }           nulltest_row;
        
        struct
        {
            int         paramid;    
            Oid         paramtype;  
        }           param;
        
        struct
        {
            ExecEvalSubroutine paramfunc;   
            void       *paramarg;   
            int         paramid;    
            Oid         paramtype;  
        }           cparam;
        
        struct
        {
            Datum      *value;  
            bool       *isnull;
        }           casetest;
        
        struct
        {
            Datum      *value;  
            bool       *isnull;
        }           make_readonly;
        
        struct
        {
            
            FmgrInfo   *finfo_out;
            FunctionCallInfo fcinfo_data_out;
            
            FmgrInfo   *finfo_in;
            FunctionCallInfo fcinfo_data_in;
        }           iocoerce;
        
        struct
        {
            sqlValueFunction *svf;
        }           sqlvaluefunction;
        
        //EEOP_NEXTVALUEEXPR
        struct
        {
            Oid         seqid;
            Oid         seQtypid;
        }           nextvalueexpr;
        
        struct
        {
            Datum      *elemvalues; 
            bool       *elemnulls;
            int         nelems; 
            Oid         elemtype;   
            int16       elemlength; 
            bool        elembyval;  
            char        elemalign;  
            bool        multidims;  
        }           arrayexpr;
        
        struct
        {
            ExprState  *elemexprstate;  
            Oid         resultelemtype; 
            struct ArrayMapState *amstate;  
        }           arraycoerce;
        
        struct
        {
            TupleDesc   tupdesc;    
            
            Datum      *elemvalues;
            bool       *elemnulls;
        }           row;
        
        struct
        {
            
            FmgrInfo   *finfo;
            FunctionCallInfo fcinfo_data;
            PGFunction  fn_addr;
            
            int         jumpnull;
            
            int         jumpdone;
        }           rowcompare_step;
        
        struct
        {
            RowCompareType rctype;
        }           rowcompare_final;
        
        struct
        {
            
            Datum      *values;
            bool       *nulls;
            int         nelems;
            
            MinMaxOp    op;
            
            FmgrInfo   *finfo;
            FunctionCallInfo fcinfo_data;
        }           minmax;
        
        struct
        {
            AttrNumber  fieldnum;   
            Oid         resulttype; 
            
            TupleDesc   argdesc;
        }           fieldselect;
        
        struct
        {
            
            FieldStore *fstore;
            
            
            TupleDesc  *argdesc;
            
            Datum      *values;
            bool       *nulls;
            int         ncolumns;
        }           fieldstore;
        
        struct
        {
            
            struct ArrayRefState *state;
            int         off;    
            bool        isupper;    
            int         jumpdone;   
        }           arrayref_subscript;
        
        struct
        {
            
            struct ArrayRefState *state;
        }           arrayref;
        
        struct
        {
            
            char       *constraintname;
            
            Datum      *checkvalue;
            bool       *checknull;
            
            Oid         resulttype;
        }           domaincheck;
        
        struct
        {
            ConvertRowtypeExpr *convert;    
            
            TupleDesc   indesc; 
            TupleDesc   outdesc;    
            TupleConversionMap *map;    
            bool        initialized;    
        }           convert_rowtype;
        
        struct
        {
            
            Oid         element_type;   
            bool        useOr;  
            int16       typlen; 
            bool        typbyval;
            char        typalign;
            FmgrInfo   *finfo;  
            FunctionCallInfo fcinfo_data;   
            
            PGFunction  fn_addr;    
        }           Scalararrayop;
        
        struct
        {
            XmlExpr    *xexpr;  
            
            Datum      *named_argvalue;
            bool       *named_argnull;
            
            Datum      *argvalue;
            bool       *argnull;
        }           xmlexpr;
        
        struct
        {
            
            AggrefExprState *astate;
        }           aggref;
        
        struct
        {
            AggState   *parent; 
            List       *clauses;    
        }           grouping_func;
        
        struct
        {
            
            WindowFuncExprState *wfstate;
        }           window_func;
        
        struct
        {
            
            SubPlanState *sstate;
        }           subplan;
        
        struct
        {
            
            AlternativeSubPlanState *asstate;
        }           alternative_subplan;
        
        struct
        {
            AggState   *aggstate;
            FunctionCallInfo fcinfo_data;
            int         jumpnull;
        }           agg_deserialize;
        
        struct
        {
            bool       *nulls;
            int         nargs;
            int         jumpnull;
        }           agg_strict_input_check;
        
        struct
        {
            AggState   *aggstate;
            AggStatePerTrans pertrans;
            ExprContext *agGContext;
            int         setno;
            int         transno;
            int         setoff;
            int         jumpnull;
        }           agg_init_trans;
        
        struct
        {
            AggState   *aggstate;
            int         setno;
            int         transno;
            int         setoff;
            int         jumpnull;
        }           agg_strict_trans_check;
        
        struct
        {
            AggState   *aggstate;
            AggStatePerTrans pertrans;
            ExprContext *aggcontext;
            int         setno;
            int         transno;
            int         setoff;
        }           agg_trans;
    }           d;
} ExprEvalStep;

ExprEvalOp
ExprEvalSteps的鉴频器,定义哪个操作将被执行并且联合体ExprEvalStep->d中的哪个struct将被使用.


typedef enum ExprEvalOp
{
    
    //整个表达式已被解析,返回
    EEOP_DONE,
    
    //在相应的元组slot上应用了slot_getsomeattrs方法
    EEOP_INNER_FETCHSOME,
    EEOP_OUTER_FETCHSOME,
    EEOP_SCAN_FETCHSOME,
    
    //计算非系统Var变量值
    EEOP_INNER_VAR,
    EEOP_OUTER_VAR,
    EEOP_SCAN_VAR,
    
    //计算系统Var变量值
    EEOP_INNER_SYSVAR,
    EEOP_OUTER_SYSVAR,
    EEOP_SCAN_SYSVAR,
    
    //计算整行Var
    EEOP_WHOLEROW,
    
    EEOP_ASSIGN_INNER_VAR,
    EEOP_ASSIGN_OUTER_VAR,
    EEOP_ASSIGN_SCAN_VAR,
    
    //分配ExprState's resvalue/resnull到该列的resultslot中
    EEOP_ASSIGN_TMP,
    
    //同上,应用MakeExpandedObjectReadOnly()
    EEOP_ASSIGN_TMP_MAKE_RO,
    
    //解析常量值
    EEOP_CONST,
    
    EEOP_FUNCEXPR,
    EEOP_FUNCEXPR_STRICT,
    EEOP_FUNCEXPR_FUSAGE,
    EEOP_FUNCEXPR_STRICT_FUSAGE,
    
    EEOP_BOOL_AND_STEP_FIRST,
    EEOP_BOOL_AND_STEP,
    EEOP_BOOL_AND_STEP_LAST,
    
    //与布尔OR表达式类似
    EEOP_BOOL_OR_STEP_FIRST,
    EEOP_BOOL_OR_STEP,
    EEOP_BOOL_OR_STEP_LAST,
    
    //解析布尔NOT表达式
    EEOP_BOOL_NOT_STEP,
    
    //用于ExecQual()中的BOOL_AND_STEP简化版本
    EEOP_QUAL,
    
    //无条件跳转到另外一个步骤
    EEOP_JUMP,
    
    //基于当前结果值的条件跳转
    EEOP_JUMP_IF_NULL,
    EEOP_JUMP_IF_NOT_NULL,
    EEOP_JUMP_IF_NOT_TRUE,
    
    //为scalar值执行NULL测试
    EEOP_NULLTEST_ISNULL,
    EEOP_NULLTEST_ISNOTNULL,
    
    //为行值执行NULL测试
    EEOP_NULLTEST_ROWISNULL,
    EEOP_NULLTEST_ROWISNOTNULL,
    
    //解析BooleanTest表达式
    EEOP_BOOLTEST_IS_TRUE,
    EEOP_BOOLTEST_IS_NOT_TRUE,
    EEOP_BOOLTEST_IS_FALSE,
    EEOP_BOOLTEST_IS_NOT_FALSE,
    
    //解析PARAM_EXEC/EXTERN参数
    EEOP_PARAM_EXEC,
    EEOP_PARAM_EXTERN,
    EEOP_PARAM_CALLBACK,
    
    //返回CaseTestExpr值
    EEOP_CASE_TESTVAL,
    
    //对目标值应用MakeExpandedObjectReadOnly()
    EEOP_MAKE_READONLY,
    
    //解析各种特殊用途的表达式类型
    EEOP_IOCOERCE,
    EEOP_DISTINCT,
    EEOP_NOT_DISTINCT,
    EEOP_NULLIF,
    EEOP_SQLVALUEFUNCTION,
    EEOP_CURRENTOFEXPR,
    EEOP_NEXTVALUEEXPR,
    EEOP_ARRAYEXPR,
    EEOP_ARRAYCOERCE,
    EEOP_ROW,
    
    EEOP_ROWCOMPARE_STEP,
    
    //基于上一步的ROWCOMPARE_STEP操作解析布尔值
    EEOP_ROWCOMPARE_FINAL,
    
    //解析GREATEST()和LEAST()
    EEOP_MINMAX,
    
    //解析FieldSelect表达式
    EEOP_FIELDSELECT,
    
    EEOP_FIELDSTORE_DEFORM,
    
    EEOP_FIELDSTORE_FORM,
    
    //处理数组子脚本.如为NULL则短路表达式为NULL
    EEOP_ARRAYREF_SUBSCRIPT,
    
    EEOP_ARRAYREF_OLD,
    
    //为ArrayRef分配118
    EEOP_ARRAYREF_ASSIGN,
    
    //为ArrayRef提取表达式计算element/slice
    EEOP_ARRAYREF_FETCH,
    
    //为CoerceToDomainValue解析值
    EEOP_DOMAIN_TESTVAL,
    
    //解析域 NOT NULL 约束
    EEOP_DOMAIN_NOTNULL,
    
    //解析单个域CHECK约束
    EEOP_DOMAIN_CHECK,
    
    //解析特殊目的的表达式类型
    EEOP_CONVERT_ROWTYPE,
    EEOP_SCALARARRAYOP,
    EEOP_XMLEXPR,
    EEOP_AGGREF,
    EEOP_GROUPING_FUNC,
    EEOP_WINDOW_FUNC,
    EEOP_SUBPLAN,
    EEOP_ALTERNATIVE_SUBPLAN,
    
    //聚合相关节点
    EEOP_AGG_STRICT_DESERIALIZE,
    EEOP_AGG_DESERIALIZE,
    EEOP_AGG_STRICT_INPUT_CHECK,
    EEOP_AGG_INIT_TRANS,
    EEOP_AGG_STRICT_TRANS_CHECK,
    EEOP_AGG_PLAIN_TRANS_BYVAL,
    EEOP_AGG_PLAIN_TRANS,
    EEOP_AGG_ORDERED_TRANS_DATUM,
    EEOP_AGG_ORDERED_TRANS_TUPLE,
    
    //不存在的操作,比如用于检测数组长度
    EEOP_LAST
} ExprEvalOp;

二、源码解读

ExecInitIndexScan
初始化Index Scan运行期状态信息,调用ExecAssignScanProjectionInfo->…->ExecBuildProjectionInfo函数构建投影信息.


IndexScanState *
ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
{
    ...
     
    ExecInitResultTupleSlotTL(estate, &indexstate->ss.ps);
    ExecAssignScanProjectionInfo(&indexstate->ss);
    ...
}

ExecBuildProjectionInfo
为给定的econtext中的tlist构建ProjectionInfo,并把结果存储在tuple slot中.(调用者必须确保元组slot与此tlist匹配)
其主要逻辑是:
1.初始化
2.如需要,插入EEOP*_FETCHSOME步骤(调用ExecInitExprSlots)
3.遍历targetList,处理targetList(目标列)中的每一个列
3.1.对于”安全”Var则只需要生成EEOP_ASSIGN*_VAR步骤
3.2对于非”安全”VAr,使用常规办法处理列表达式,调用ExecInitExprRec函数处理,并通过ExprEvalPushStep压步骤
4.压入EEOP_DONE步骤


void
ExecAssignScanProjectionInfo(ScanState *node)
{
   //扫描节点
   Scan       *scan = (Scan *) node->ps.plan;
   //元组描述符
   TupleDesc   tupdesc = node->ss_ScanTupleSlot->tts_tupleDescriptor;
   //执行ExecConditionalAssignProjectionInfo
   ExecConditionalAssignProjectionInfo(&node->ps, tupdesc, scan->scanrelid);
}

void
ExecConditionalAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc,
                                   Index varno)
{
   //正好匹配元组类型,则设计为NULL
   if (tlist_matches_tupdesc(planstate,
                             planstate->plan->targetlist,
                             varno,
                             inputDesc))
       planstate->ps_ProjInfo = NULL;
   else
       //否则执行ExecAssignProjectionInfo
       ExecAssignProjectionInfo(planstate, inputDesc);
}

void
ExecAssignProjectionInfo(PlanState *planstate,
                        TupleDesc inputDesc)
{
   //直接调用ExecBuildProjectionInfo
   planstate->ps_ProjInfo =
       ExecBuildProjectionInfo(planstate->plan->targetlist,
                               planstate->ps_ExprContext,
                               planstate->ps_ResultTupleSlot,
                               planstate,
                               inputDesc);
}

ProjectionInfo *
ExecBuildProjectionInfo(List *targetList,
                       ExprContext *econtext,
                       TupleTableSlot *slot,
                       PlanState *parent,
                       TupleDesc inputDesc)
{
   //生成ProjectionInfo节点
   ProjectionInfo *projInfo = makeNode(ProjectionInfo);
   //表达式状态节点
   ExprState  *state;
   //表达式解析步骤
   ExprEvalStep scratch = {0};
   //临时变量
   ListCell   *lc;
   //expr上下文
   projInfo->pi_exprContext = econtext;
   
   //集成ExprState到ProjectionInfo中,而不需要另外的palloc
   projInfo->pi_state.tag.type = T_ExprState;
   state = &projInfo->pi_state;
   state->expr = (Expr *) targetList;
   state->parent = parent;
   state->ext_params = NULL;
   state->resultslot = slot;
   
   //如需要,插入EEOP_*_FETCHSOME步骤
   ExecInitExprSlots(state, (Node *) targetList);
   
   //现在"编译"tlist中的每一个列
   foreach(lc, targetList)
   {
       TargetEntry *tle = lfirst_node(TargetEntry, lc);
       Var        *variable = NULL;
       AttrNumber  attnum = 0;
       bool        isSafeVar = false;
       
       if (tle->expr != NULL &&
           IsA(tle->expr, Var) &&
           ((Var *) tle->expr)->varattno > 0)
       {
           
           //非系统Var,但有多安全呢?
           variable = (Var *) tle->expr;
           attnum = variable->varattno;
           if (inputDesc == NULL)
               //无法检查,假定是OK的.
               isSafeVar = true;  
           else if (attnum <= inputDesc->natts)
           {
               //---- 属性编号小于输入的属性个数
               Form_pg_attribute attr = TupleDescAttr(inputDesc, attnum - 1);
               
               if (!attr->attisdropped && variable->vartype == attr->atttypid)
               {
                   isSafeVar = true;
               }
           }
       }
       if (isSafeVar)
       {
           //--- 如为安全的Var
           
           //Fast-path: 只需要生成EEOP_ASSIGN_*_VAR步骤即可
           switch (variable->varno)
           {
               case INNER_VAR:
                   
                   //内关系VAR,从inner节点获取元组
                   scratch.opcode = EEOP_ASSIGN_INNER_VAR;
                   break;
               case OUTER_VAR:
                   
                   //从外关系获取元组
                   scratch.opcode = EEOP_ASSIGN_OUTER_VAR;
                   break;
                   
                   //默认: INDEX_VAR
               default:
                   
                   //从正在扫描的关系中获取元组
                   scratch.opcode = EEOP_ASSIGN_SCAN_VAR;
                   break;
           }
           //EEOP_ASSIGN_*_VAR
           scratch.d.assign_var.attnum = attnum - 1;
           scratch.d.assign_var.resultnum = tle->resno - 1;
           ExprEvalPushStep(state, &scratch);
       }
       else
       {
           
           ExecInitExprRec(tle->expr, state,
                           &state->resvalue, &state->resnull);
           
           //d.assign_tmp.resultnum/attnum
           if (get_typlen(exprType((Node *) tle->expr)) == -1)
               scratch.opcode = EEOP_ASSIGN_TMP_MAKE_RO;
           else
               scratch.opcode = EEOP_ASSIGN_TMP;
           scratch.d.assign_tmp.resultnum = tle->resno - 1;
           ExprEvalPushStep(state, &scratch);
       }
   }
   scratch.opcode = EEOP_DONE;
   ExprEvalPushStep(state, &scratch);
   ExecReadyExpr(state);
   //返回投影信息.
   return projInfo;
}

三、跟踪分析

测试脚本

testdb=# select 1+id,c2 from t_expr where id < 3;

调用栈

(gdb) bt
#0  ExecBuildProjectionInfo (targetList=0x1cc7550, econtext=0x1c8f408, slot=0x1c8f710, parent=0x1c8f1f0,
   inputDesc=0x7f8386bb6ab8) at execExpr.c:355
#1  0x00000000006e60d5 in ExecAssignProjectionInfo (planstate=0x1c8f1f0, inputDesc=0x7f8386bb6ab8) at execUtils.c:468
#2  0x00000000006e613c in ExecConditionalAssignProjectionInfo (planstate=0x1c8f1f0, inputDesc=0x7f8386bb6ab8, varno=1)
   at execUtils.c:493
#3  0x00000000006e23f5 in ExecAssignScanProjectionInfo (node=0x1c8f1f0) at execScan.c:240
#4  0x0000000000700afc in ExecInitIndexScan (node=0x1ba8a18, estate=0x1c8efd8, eflags=16) at nodeIndexscan.c:962
#5  0x00000000006e00cc in ExecInitNode (node=0x1ba8a18, estate=0x1c8efd8, eflags=16) at execProcnode.c:217
#6  0x00000000006d6abe in InitPlan (queryDesc=0x1c94aa8, eflags=16) at execMain.c:1046
#7  0x00000000006d58ad in standard_ExecutorStart (queryDesc=0x1c94aa8, eflags=16) at execMain.c:265
#8  0x00000000006d5649 in ExecutorStart (queryDesc=0x1c94aa8, eflags=0) at execMain.c:147
#9  0x00000000008c18d6 in PortalStart (portal=0x1c15608, params=0x0, eflags=0, snapshot=0x0) at pquery.c:520
#10 0x00000000008bbe1b in exec_simple_query (query_string=0x1ba6d78 "select 1+id,c2 from t_expr where id < 3;")
   at postgres.c:1106
#11 0x00000000008c0191 in PostgresMain (argc=1, argv=0x1bd4cb8, dbname=0x1bd4b20 "testdb", username=0x1ba3a98 "xdb")
   at postgres.c:4182
#12 0x000000000081e06c in BackendRun (port=0x1bc8ae0) at postmaster.c:4361
#13 0x000000000081d7df in BackendStartup (port=0x1bc8ae0) at postmaster.c:4033
#14 0x0000000000819bd9 in ServerLoop () at postmaster.c:1706
#15 0x000000000081948f in PostmasterMain (argc=1, argv=0x1ba1a50) at postmaster.c:1379
#16 0x0000000000742931 in main (argc=1, argv=0x1ba1a50) at main.c:228

执行跟踪,进入函数ExecBuildProjectionInfo

(gdb) b ExecBuildProjectionInfo
Breakpoint 1 at 0x6c5377: file execExpr.c, line 355.
(gdb) c
Continuing.
Breakpoint 1, ExecBuildProjectionInfo (targetList=0x1c93498, econtext=0x1c883a8, slot=0x1c887c8, parent=0x1c88190,
   inputDesc=0x1c884a0) at execExpr.c:355
355     ProjectionInfo *projInfo = makeNode(ProjectionInfo);
(gdb)

1.初始化

(gdb) n
357     ExprEvalStep scratch = {0};
(gdb)
360     projInfo->pi_exprContext = econtext;
(gdb)
362     projInfo->pi_state.tag.type = T_ExprState;
(gdb)
363     state = &projInfo->pi_state;
(gdb)
364     state->expr = (Expr *) targetList;
(gdb)
365     state->parent = parent;
(gdb)
366     state->ext_params = NULL;
(gdb)
368     state->resultslot = slot;
(gdb)

查看相关变量

(gdb) p *state
$1 = {tag = {type = T_ExprState}, flags = 0 '\000', resnull = false, resvalue = 0, resultslot = 0x1c8f710, steps = 0x0,
 evalfunc = 0x0, expr = 0x1cc7550, evalfunc_private = 0x0, steps_len = 0, steps_alloc = 0, parent = 0x1c8f1f0,
 ext_params = 0x0, innermost_caseval = 0x0, innermost_casenull = 0x0, innermost_domainval = 0x0,
 innermost_domainnull = 0x0}

目标列链表

(gdb) p targetList
$2 = (List *) 0x1cc7550
(gdb) p *targetList
$3 = {type = T_List, length = 2, head = 0x1cc7528, tail = 0x1cc75e0}

第一个元素是1+id,第二个元素是c2

(gdb) p *(TargetEntry *)targetList->head->data.ptr_value
$7 = {xpr = {type = T_TargetEntry}, expr = 0x1c9a930, resno = 1, resname = 0xbcf498 "?column?", ressortgroupref = 0,
 resorigtbl = 0, resorigcol = 0, resjunk = false}
(gdb) p *(OpExpr *)((TargetEntry *)targetList->head->data.ptr_value)->expr
$9 = {xpr = {type = T_OpExpr}, opno = 551, opfuncid = 177, opresulttype = 23, opretset = false, opcollid = 0,
 inputcollid = 0, args = 0x1c9a878, location = 8}
(gdb) p *(Node *)targetList->head->next->data.ptr_value
$10 = {type = T_TargetEntry}
(gdb) p *(TargetEntry *)targetList->head->next->data.ptr_value
$11 = {xpr = {type = T_TargetEntry}, expr = 0x1c9aa40, resno = 2, resname = 0x1ba7a40 "c2", ressortgroupref = 0,
 resorigtbl = 237600, resorigcol = 2, resjunk = false}

2.如需要,插入EEOP_*_FETCHSOME步骤(调用ExecInitExprSlots)

(gdb) 
371     ExecInitExprSlots(state, (Node *) targetList);

第一个步骤,opcode = 3,即EEOP_SCAN_FETCHSOME

(gdb) n
374     foreach(lc, targetList)
(gdb) p *state
$13 = {tag = {type = T_ExprState}, flags = 0 '\000', resnull = false, resvalue = 0, resultslot = 0x1c8f710,
 steps = 0x1c8f868, evalfunc = 0x0, expr = 0x1cc7550, evalfunc_private = 0x0, steps_len = 1, steps_alloc = 16,
 parent = 0x1c8f1f0, ext_params = 0x0, innermost_caseval = 0x0, innermost_casenull = 0x0, innermost_domainval = 0x0,
 innermost_domainnull = 0x0}
(gdb) p state->steps[0]
$14 = {opcode = 3, resvalue = 0x0, resnull = 0x0, d = {fetch = {last_var = 2, known_desc = 0x0}, var = {attnum = 2,
     vartype = 0}, wholerow = {var = 0x2, first = false, slow = false, tupdesc = 0x0, junkFilter = 0x0}, assign_var = {
     resultnum = 2, attnum = 0}, assign_tmp = {resultnum = 2}, constval = {value = 2, isnull = false}, func = {
     finfo = 0x2, fcinfo_data = 0x0, fn_addr = 0x0, nargs = 0}, boolexpr = {anynull = 0x2, jumpdone = 0}, qualexpr = {
     jumpdone = 2}, jump = {jumpdone = 2}, nulltest_row = {argdesc = 0x2}, param = {paramid = 2, paramtype = 0}, cparam = {
     paramfunc = 0x2, paramarg = 0x0, paramid = 0, paramtype = 0}, casetest = {value = 0x2, isnull = 0x0},
   make_readonly = {value = 0x2, isnull = 0x0}, iocoerce = {finfo_out = 0x2, fcinfo_data_out = 0x0, finfo_in = 0x0,
     fcinfo_data_in = 0x0}, sqlvaluefunction = {svf = 0x2}, nextvalueexpr = {seqid = 2, seqtypid = 0}, arrayexpr = {
     elemvalues = 0x2, elemnulls = 0x0, nelems = 0, elemtype = 0, elemlength = 0, elembyval = false, elemalign = 0 '\000',
     multidims = false}, arraycoerce = {elemexprstate = 0x2, resultelemtype = 0, amstate = 0x0}, row = {tupdesc = 0x2,
     elemvalues = 0x0, elemnulls = 0x0}, rowcompare_step = {finfo = 0x2, fcinfo_data = 0x0, fn_addr = 0x0, jumpnull = 0,
     jumpdone = 0}, rowcompare_final = {rctype = ROWCOMPARE_LE}, minmax = {values = 0x2, nulls = 0x0, nelems = 0,
     op = IS_GREATEST, finfo = 0x0, fcinfo_data = 0x0}, fieldselect = {fieldnum = 2, resulttype = 0, argdesc = 0x0},
   fieldstore = {fstore = 0x2, argdesc = 0x0, values = 0x0, nulls = 0x0, ncolumns = 0}, arrayref_subscript = {state = 0x2,
     off = 0, isupper = false, jumpdone = 0}, arrayref = {state = 0x2}, domaincheck = {
     constraintname = 0x2 <Address 0x2 out of bounds>, checkvalue = 0x0, checknull = 0x0, resulttype = 0},
   convert_rowtype = {convert = 0x2, indesc = 0x0, outdesc = 0x0, map = 0x0, initialized = false}, scalararrayop = {
     element_type = 2, useOr = false, typlen = 0, typbyval = false, typalign = 0 '\000', finfo = 0x0, fcinfo_data = 0x0,
     fn_addr = 0x0}, xmlexpr = {xexpr = 0x2, named_argvalue = 0x0, named_argnull = 0x0, argvalue = 0x0, argnull = 0x0},
   aggref = {astate = 0x2}, grouping_func = {parent = 0x2, clauses = 0x0}, window_func = {wfstate = 0x2}, subplan = {
     sstate = 0x2}, alternative_subplan = {asstate = 0x2}, agg_deserialize = {aggstate = 0x2, fcinfo_data = 0x0,
     jumpnull = 0}, agg_strict_input_check = {nulls = 0x2, nargs = 0, jumpnull = 0}, agg_init_trans = {aggstate = 0x2,
     pertrans = 0x0, aggcontext = 0x0, setno = 0, transno = 0, setoff = 0, jumpnull = 0}, agg_strict_trans_check = {
     aggstate = 0x2, setno = 0, transno = 0, setoff = 0, jumpnull = 0}, agg_trans = {aggstate = 0x2, pertrans = 0x0,
     aggcontext = 0x0, setno = 0, transno = 0, setoff = 0}}}
(gdb)

3.遍历targetList,处理targetList(目标列)中的每一个列
3.1.对于”安全”Var则只需要生成EEOPASSIGN*_VAR步骤
3.2.对于非”安全”VAr,使用常规办法处理列表达式,调用ExecInitExprRec函数处理,并通过ExprEvalPushStep压步骤

(gdb) n
376         TargetEntry *tle = lfirst_node(TargetEntry, lc);
(gdb)
377         Var        *variable = NULL;
(gdb)
378         AttrNumber  attnum = 0;
(gdb)
379         bool        isSafeVar = false;
(gdb)
389         if (tle->expr != NULL &&
(gdb)
390             IsA(tle->expr, Var) &&
(gdb)
389         if (tle->expr != NULL &&
(gdb)
415         if (isSafeVar)
(gdb) p *tle
$15 = {xpr = {type = T_TargetEntry}, expr = 0x1c9a930, resno = 1, resname = 0xbcf498 "?column?", ressortgroupref = 0,
 resorigtbl = 0, resorigcol = 0, resjunk = false}
(gdb) n
452             ExecInitExprRec(tle->expr, state,
(gdb)

进入ExecInitExprRec,Node节点为OpExpr,执行ExprEvalPushStep压入步骤中

(gdb) step
ExecInitExprRec (node=0x1c9a930, state=0x1c8f7d8, resv=0x1c8f7e0, resnull=0x1c8f7dd) at execExpr.c:645
645     ExprEvalStep scratch = {0};
(gdb) n
648     check_stack_depth();
(gdb)
651     Assert(resv != NULL && resnull != NULL);
(gdb)
652     scratch.resvalue = resv;
(gdb)
653     scratch.resnull = resnull;
(gdb)
656     switch (nodeTag(node))
(gdb)
891                 OpExpr     *op = (OpExpr *) node;
(gdb) p *node
$16 = {type = T_OpExpr}
(gdb) n
893                 ExecInitFunc(&scratch, node,
(gdb)
896                 ExprEvalPushStep(state, &scratch);
(gdb)
897                 break;
(gdb)
2122    }
(gdb)
ExecBuildProjectionInfo (targetList=0x1cc7550, econtext=0x1c8f408, slot=0x1c8f710, parent=0x1c8f1f0,
   inputDesc=0x7f8386bb6ab8) at execExpr.c:459
459             if (get_typlen(exprType((Node *) tle->expr)) == -1)
(gdb)
462                 scratch.opcode = EEOP_ASSIGN_TMP;
(gdb)

ExecInitExprRec调用完毕,增加了2个步骤,分别是:
1.opcode = 6,即EEOP_SCAN_VAR
2.opcode = 18,即EEOP_FUNCEXPR_STRICT

(gdb) p *state
$17 = {tag = {type = T_ExprState}, flags = 0 '\000', resnull = false, resvalue = 0, resultslot = 0x1c8f710,
 steps = 0x1c8f868, evalfunc = 0x0, expr = 0x1cc7550, evalfunc_private = 0x0, steps_len = 3, steps_alloc = 16,
 parent = 0x1c8f1f0, ext_params = 0x0, innermost_caseval = 0x0, innermost_casenull = 0x0, innermost_domainval = 0x0,
 innermost_domainnull = 0x0}
(gdb) p state->steps[1]
$18 = {opcode = 6, resvalue = 0x1c8fd00, resnull = 0x1c90019, d = {fetch = {last_var = 0, known_desc = 0x0}, var = {
     attnum = 0, vartype = 23}, wholerow = {var = 0x1700000000, first = false, slow = false, tupdesc = 0x0,
     junkFilter = 0x0}, assign_var = {resultnum = 0, attnum = 23}, assign_tmp = {resultnum = 0}, constval = {
     value = 98784247808, isnull = false}, func = {finfo = 0x1700000000, fcinfo_data = 0x0, fn_addr = 0x0, nargs = 0},
   boolexpr = {anynull = 0x1700000000, jumpdone = 0}, qualexpr = {jumpdone = 0}, jump = {jumpdone = 0}, nulltest_row = {
     argdesc = 0x1700000000}, param = {paramid = 0, paramtype = 23}, cparam = {paramfunc = 0x1700000000, paramarg = 0x0,
     paramid = 0, paramtype = 0}, casetest = {value = 0x1700000000, isnull = 0x0}, make_readonly = {value = 0x1700000000,
     isnull = 0x0}, iocoerce = {finfo_out = 0x1700000000, fcinfo_data_out = 0x0, finfo_in = 0x0, fcinfo_data_in = 0x0},
   sqlvaluefunction = {svf = 0x1700000000}, nextvalueexpr = {seqid = 0, seqtypid = 23}, arrayexpr = {
     elemvalues = 0x1700000000, elemnulls = 0x0, nelems = 0, elemtype = 0, elemlength = 0, elembyval = false,
     elemalign = 0 '\000', multidims = false}, arraycoerce = {elemexprstate = 0x1700000000, resultelemtype = 0,
     amstate = 0x0}, row = {tupdesc = 0x1700000000, elemvalues = 0x0, elemnulls = 0x0}, rowcompare_step = {
     finfo = 0x1700000000, fcinfo_data = 0x0, fn_addr = 0x0, jumpnull = 0, jumpdone = 0}, rowcompare_final = {rctype = 0},
   minmax = {values = 0x1700000000, nulls = 0x0, nelems = 0, op = IS_GREATEST, finfo = 0x0, fcinfo_data = 0x0},
   fieldselect = {fieldnum = 0, resulttype = 23, argdesc = 0x0}, fieldstore = {fstore = 0x1700000000, argdesc = 0x0,
     values = 0x0, nulls = 0x0, ncolumns = 0}, arrayref_subscript = {state = 0x1700000000, off = 0, isupper = false,
     jumpdone = 0}, arrayref = {state = 0x1700000000}, domaincheck = {
     constraintname = 0x1700000000 <Address 0x1700000000 out of bounds>, checkvalue = 0x0, checknull = 0x0,
     resulttype = 0}, convert_rowtype = {convert = 0x1700000000, indesc = 0x0, outdesc = 0x0, map = 0x0,
     initialized = false}, scalararrayop = {element_type = 0, useOr = 23, typlen = 0, typbyval = false,
     typalign = 0 '\000', finfo = 0x0, fcinfo_data = 0x0, fn_addr = 0x0}, xmlexpr = {xexpr = 0x1700000000,
     named_argvalue = 0x0, named_argnull = 0x0, argvalue = 0x0, argnull = 0x0}, aggref = {astate = 0x1700000000},
   grouping_func = {parent = 0x1700000000, clauses = 0x0}, window_func = {wfstate = 0x1700000000}, subplan = {
     sstate = 0x1700000000}, alternative_subplan = {asstate = 0x1700000000}, agg_deserialize = {aggstate = 0x1700000000,
     fcinfo_data = 0x0, jumpnull = 0}, agg_strict_input_check = {nulls = 0x1700000000, nargs = 0, jumpnull = 0},
   agg_init_trans = {aggstate = 0x1700000000, pertrans = 0x0, aggcontext = 0x0, setno = 0, transno = 0, setoff = 0,
     jumpnull = 0}, agg_strict_trans_check = {aggstate = 0x1700000000, setno = 0, transno = 0, setoff = 0, jumpnull = 0},
---Type <return> to continue, or q <return> to quit---
   agg_trans = {aggstate = 0x1700000000, pertrans = 0x0, aggcontext = 0x0, setno = 0, transno = 0, setoff = 0}}}
(gdb) p state->steps[2]
$19 = {opcode = 18, resvalue = 0x1c8f7e0, resnull = 0x1c8f7dd, d = {fetch = {last_var = 29949056, known_desc = 0x1c8fcd8},
   var = {attnum = 29949056, vartype = 0}, wholerow = {var = 0x1c8fc80, first = 216, slow = 252,
     tupdesc = 0x93D60c <int4pl>, junkFilter = 0x2}, assign_var = {resultnum = 29949056, attnum = 0}, assign_tmp = {
     resultnum = 29949056}, constval = {value = 29949056, isnull = 216}, func = {finfo = 0x1c8fc80,
     fcinfo_data = 0x1c8fcd8, fn_addr = 0x93d60c <int4pl>, nargs = 2}, boolexpr = {anynull = 0x1c8fc80,
     jumpdone = 29949144}, qualexpr = {jumpdone = 29949056}, jump = {jumpdone = 29949056}, nulltest_row = {
     argdesc = 0x1c8fc80}, param = {paramid = 29949056, paramtype = 0}, cparam = {paramfunc = 0x1c8fc80,
     paramarg = 0x1c8fcd8, paramid = 9688588, paramtype = 0}, casetest = {value = 0x1c8fc80, isnull = 0x1c8fcd8},
   make_readonly = {value = 0x1c8fc80, isnull = 0x1c8fcd8}, iocoerce = {finfo_out = 0x1c8fc80,
     fcinfo_data_out = 0x1c8fcd8, finfo_in = 0x93d60c <int4pl>, fcinfo_data_in = 0x2}, sqlvaluefunction = {
     svf = 0x1c8fc80}, nextvalueexpr = {seqid = 29949056, seqtypid = 0}, arrayexpr = {elemvalues = 0x1c8fc80,
     elemnulls = 0x1c8fcd8, nelems = 9688588, elemtype = 0, elemlength = 2, elembyval = false, elemalign = 0 '\000',
     multidims = false}, arraycoerce = {elemexprstate = 0x1c8fc80, resultelemtype = 29949144,
     amstate = 0x93d60c <int4pl>}, row = {tupdesc = 0x1c8fc80, elemvalues = 0x1c8fcd8, elemnulls = 0x93d60c <int4pl>},
   rowcompare_step = {finfo = 0x1c8fc80, fcinfo_data = 0x1c8fcd8, fn_addr = 0x93d60c <int4pl>, jumpnull = 2,
     jumpdone = 0}, rowcompare_final = {rctype = 29949056}, minmax = {values = 0x1c8fc80, nulls = 0x1c8fcd8,
     nelems = 9688588, op = IS_GREATEST, finfo = 0x2, fcinfo_data = 0x0}, fieldselect = {fieldnum = -896, resulttype = 0,
     argdesc = 0x1c8fcd8}, fieldstore = {fstore = 0x1c8fc80, argdesc = 0x1c8fcd8, values = 0x93d60c <int4pl>, nulls = 0x2,
     ncolumns = 0}, arrayref_subscript = {state = 0x1c8fc80, off = 29949144, isupper = false, jumpdone = 9688588},
   arrayref = {state = 0x1c8fc80}, domaincheck = {constraintname = 0x1c8fc80 "\f֓", checkvalue = 0x1c8fcd8,
     checknull = 0x93d60c <int4pl>, resulttype = 2}, convert_rowtype = {convert = 0x1c8fc80, indesc = 0x1c8fcd8,
     outdesc = 0x93d60c <int4pl>, map = 0x2, initialized = false}, scalararrayop = {element_type = 29949056,
     useOr = false, typlen = 0, typbyval = 216, typalign = -4 '\374', finfo = 0x93d60c <int4pl>, fcinfo_data = 0x2,
     fn_addr = 0x0}, xmlexpr = {xexpr = 0x1c8fc80, named_argvalue = 0x1c8fcd8, named_argnull = 0x93d60c <int4pl>,
     argvalue = 0x2, argnull = 0x0}, aggref = {astate = 0x1c8fc80}, grouping_func = {parent = 0x1c8fc80,
     clauses = 0x1c8fcd8}, window_func = {wfstate = 0x1c8fc80}, subplan = {sstate = 0x1c8fc80}, alternative_subplan = {
     asstate = 0x1c8fc80}, agg_deserialize = {aggstate = 0x1c8fc80, fcinfo_data = 0x1c8fcd8, jumpnull = 9688588},
---Type <return> to continue, or q <return> to quit---
   agg_strict_input_check = {nulls = 0x1c8fc80, nargs = 29949144, jumpnull = 0}, agg_init_trans = {aggstate = 0x1c8fc80,
     pertrans = 0x1c8fcd8, aggcontext = 0x93d60c <int4pl>, setno = 2, transno = 0, setoff = 0, jumpnull = 0},
   agg_strict_trans_check = {aggstate = 0x1c8fc80, setno = 29949144, transno = 0, setoff = 9688588, jumpnull = 0},
   agg_trans = {aggstate = 0x1c8fc80, pertrans = 0x1c8fcd8, aggcontext = 0x93d60c <int4pl>, setno = 2, transno = 0,
     setoff = 0}}}
(gdb)

压入对应该表达式列的编号,opcode = 14,即EEOP_ASSIGN_TMP

(gdb) n
463             scratch.d.assign_tmp.resultnum = tle->resno - 1;
(gdb)
464             ExprEvalPushStep(state, &scratch);
(gdb)
(gdb)
374     foreach(lc, targetList)
(gdb) p *state
$20 = {tag = {type = T_ExprState}, flags = 0 '\000', resnull = false, resvalue = 0, resultslot = 0x1c8f710,
 steps = 0x1c8f868, evalfunc = 0x0, expr = 0x1cc7550, evalfunc_private = 0x0, steps_len = 4, steps_alloc = 16,
 parent = 0x1c8f1f0, ext_params = 0x0, innermost_caseval = 0x0, innermost_casenull = 0x0, innermost_domainval = 0x0,
 innermost_domainnull = 0x0}
(gdb) p state->steps[3]
$21 = {opcode = 14, resvalue = 0x0, resnull = 0x0, d = {fetch = {last_var = 0, known_desc = 0x0}, var = {attnum = 0,
     vartype = 0}, wholerow = {var = 0x0, first = false, slow = false, tupdesc = 0x0, junkFilter = 0x0}, assign_var = {
     resultnum = 0, attnum = 0}, assign_tmp = {resultnum = 0}, constval = {value = 0, isnull = false}, func = {
     finfo = 0x0, fcinfo_data = 0x0, fn_addr = 0x0, nargs = 0}, boolexpr = {anynull = 0x0, jumpdone = 0}, qualexpr = {
     jumpdone = 0}, jump = {jumpdone = 0}, nulltest_row = {argdesc = 0x0}, param = {paramid = 0, paramtype = 0}, cparam = {
     paramfunc = 0x0, paramarg = 0x0, paramid = 0, paramtype = 0}, casetest = {value = 0x0, isnull = 0x0},
   make_readonly = {value = 0x0, isnull = 0x0}, iocoerce = {finfo_out = 0x0, fcinfo_data_out = 0x0, finfo_in = 0x0,
     fcinfo_data_in = 0x0}, sqlvaluefunction = {svf = 0x0}, nextvalueexpr = {seqid = 0, seqtypid = 0}, arrayexpr = {
     elemvalues = 0x0, elemnulls = 0x0, nelems = 0, elemtype = 0, elemlength = 0, elembyval = false, elemalign = 0 '\000',
     multidims = false}, arraycoerce = {elemexprstate = 0x0, resultelemtype = 0, amstate = 0x0}, row = {tupdesc = 0x0,
     elemvalues = 0x0, elemnulls = 0x0}, rowcompare_step = {finfo = 0x0, fcinfo_data = 0x0, fn_addr = 0x0, jumpnull = 0,
     jumpdone = 0}, rowcompare_final = {rctype = 0}, minmax = {values = 0x0, nulls = 0x0, nelems = 0, op = IS_GREATEST,
     finfo = 0x0, fcinfo_data = 0x0}, fieldselect = {fieldnum = 0, resulttype = 0, argdesc = 0x0}, fieldstore = {
     fstore = 0x0, argdesc = 0x0, values = 0x0, nulls = 0x0, ncolumns = 0}, arrayref_subscript = {state = 0x0, off = 0,
     isupper = false, jumpdone = 0}, arrayref = {state = 0x0}, domaincheck = {constraintname = 0x0, checkvalue = 0x0,
     checknull = 0x0, resulttype = 0}, convert_rowtype = {convert = 0x0, indesc = 0x0, outdesc = 0x0, map = 0x0,
     initialized = false}, scalararrayop = {element_type = 0, useOr = false, typlen = 0, typbyval = false,
     typalign = 0 '\000', finfo = 0x0, fcinfo_data = 0x0, fn_addr = 0x0}, xmlexpr = {xexpr = 0x0, named_argvalue = 0x0,
     named_argnull = 0x0, argvalue = 0x0, argnull = 0x0}, aggref = {astate = 0x0}, grouping_func = {parent = 0x0,
     clauses = 0x0}, window_func = {wfstate = 0x0}, subplan = {sstate = 0x0}, alternative_subplan = {asstate = 0x0},
   agg_deserialize = {aggstate = 0x0, fcinfo_data = 0x0, jumpnull = 0}, agg_strict_input_check = {nulls = 0x0, nargs = 0,
     jumpnull = 0}, agg_init_trans = {aggstate = 0x0, pertrans = 0x0, aggcontext = 0x0, setno = 0, transno = 0,
     setoff = 0, jumpnull = 0}, agg_strict_trans_check = {aggstate = 0x0, setno = 0, transno = 0, setoff = 0,
     jumpnull = 0}, agg_trans = {aggstate = 0x0, pertrans = 0x0, aggcontext = 0x0, setno = 0, transno = 0, setoff = 0}}}
(gdb)

继续处理下一个列,这是一个”安全”列,压入EEOP_ASSIGN_SCAN_VAR步骤

(gdb) n
376         TargetEntry *tle = lfirst_node(TargetEntry, lc);
(gdb)
377         Var        *variable = NULL;
(gdb) p *tle
$22 = {xpr = {type = T_TargetEntry}, expr = 0x1c9aa40, resno = 2, resname = 0x1ba7a40 "c2", ressortgroupref = 0,
 resorigtbl = 237600, resorigcol = 2, resjunk = false}
(gdb) n
378         AttrNumber  attnum = 0;
(gdb)
379         bool        isSafeVar = false;
(gdb)
389         if (tle->expr != NULL &&
(gdb)
390             IsA(tle->expr, Var) &&
(gdb)
389         if (tle->expr != NULL &&
(gdb)
391             ((Var *) tle->expr)->varattno > 0)
(gdb)
390             IsA(tle->expr, Var) &&
(gdb)
394             variable = (Var *) tle->expr;
(gdb)
395             attnum = variable->varattno;
(gdb)
397             if (inputDesc == NULL)
(gdb)
399             else if (attnum <= inputDesc->natts)
(gdb)
401                 Form_pg_attribute attr = TupleDescAttr(inputDesc, attnum - 1);
(gdb)
408                 if (!attr->attisdropped && variable->vartype == attr->atttypid)
(gdb)
410                     isSafeVar = true;
(gdb)
415         if (isSafeVar)
(gdb)
418             switch (variable->varno)
(gdb)
434                     scratch.opcode = EEOP_ASSIGN_SCAN_VAR;
(gdb)
435                     break;
(gdb)
438             scratch.d.assign_var.attnum = attnum - 1;
(gdb)
439             scratch.d.assign_var.resultnum = tle->resno - 1;
(gdb)
440             ExprEvalPushStep(state, &scratch);
(gdb) p *state
$23 = {tag = {type = T_ExprState}, flags = 0 '\000', resnull = false, resvalue = 0, resultslot = 0x1c8f710,
 steps = 0x1c8f868, evalfunc = 0x0, expr = 0x1cc7550, evalfunc_private = 0x0, steps_len = 4, steps_alloc = 16,
 parent = 0x1c8f1f0, ext_params = 0x0, innermost_caseval = 0x0, innermost_casenull = 0x0, innermost_domainval = 0x0,
 innermost_domainnull = 0x0}
(gdb) n
374     foreach(lc, targetList)
(gdb) p *state
$24 = {tag = {type = T_ExprState}, flags = 0 '\000', resnull = false, resvalue = 0, resultslot = 0x1c8f710,
 steps = 0x1c8f868, evalfunc = 0x0, expr = 0x1cc7550, evalfunc_private = 0x0, steps_len = 5, steps_alloc = 16,
 parent = 0x1c8f1f0, ext_params = 0x0, innermost_caseval = 0x0, innermost_casenull = 0x0, innermost_domainval = 0x0,
 innermost_domainnull = 0x0}
(gdb) p state->steps[4]
$25 = {opcode = 13, resvalue = 0x0, resnull = 0x0, d = {fetch = {last_var = 1, known_desc = 0x0}, var = {attnum = 1,
     vartype = 1}, wholerow = {var = 0x100000001, first = false, slow = false, tupdesc = 0x0, junkFilter = 0x0},
   assign_var = {resultnum = 1, attnum = 1}, assign_tmp = {resultnum = 1}, constval = {value = 4294967297,
     isnull = false}, func = {finfo = 0x100000001, fcinfo_data = 0x0, fn_addr = 0x0, nargs = 0}, boolexpr = {
     anynull = 0x100000001, jumpdone = 0}, qualexpr = {jumpdone = 1}, jump = {jumpdone = 1}, nulltest_row = {
     argdesc = 0x100000001}, param = {paramid = 1, paramtype = 1}, cparam = {paramfunc = 0x100000001, paramarg = 0x0,
     paramid = 0, paramtype = 0}, casetest = {value = 0x100000001, isnull = 0x0}, make_readonly = {value = 0x100000001,
     isnull = 0x0}, iocoerce = {finfo_out = 0x100000001, fcinfo_data_out = 0x0, finfo_in = 0x0, fcinfo_data_in = 0x0},
   sqlvaluefunction = {svf = 0x100000001}, nextvalueexpr = {seqid = 1, seqtypid = 1}, arrayexpr = {
     elemvalues = 0x100000001, elemnulls = 0x0, nelems = 0, elemtype = 0, elemlength = 0, elembyval = false,
     elemalign = 0 '\000', multidims = false}, arraycoerce = {elemexprstate = 0x100000001, resultelemtype = 0,
     amstate = 0x0}, row = {tupdesc = 0x100000001, elemvalues = 0x0, elemnulls = 0x0}, rowcompare_step = {
     finfo = 0x100000001, fcinfo_data = 0x0, fn_addr = 0x0, jumpnull = 0, jumpdone = 0}, rowcompare_final = {
     rctype = ROWCOMPARE_LT}, minmax = {values = 0x100000001, nulls = 0x0, nelems = 0, op = IS_GREATEST, finfo = 0x0,
     fcinfo_data = 0x0}, fieldselect = {fieldnum = 1, resulttype = 1, argdesc = 0x0}, fieldstore = {fstore = 0x100000001,
     argdesc = 0x0, values = 0x0, nulls = 0x0, ncolumns = 0}, arrayref_subscript = {state = 0x100000001, off = 0,
     isupper = false, jumpdone = 0}, arrayref = {state = 0x100000001}, domaincheck = {
     constraintname = 0x100000001 <Address 0x100000001 out of bounds>, checkvalue = 0x0, checknull = 0x0, resulttype = 0},
   convert_rowtype = {convert = 0x100000001, indesc = 0x0, outdesc = 0x0, map = 0x0, initialized = false},
   scalararrayop = {element_type = 1, useOr = true, typlen = 0, typbyval = false, typalign = 0 '\000', finfo = 0x0,
     fcinfo_data = 0x0, fn_addr = 0x0}, xmlexpr = {xexpr = 0x100000001, named_argvalue = 0x0, named_argnull = 0x0,
     argvalue = 0x0, argnull = 0x0}, aggref = {astate = 0x100000001}, grouping_func = {parent = 0x100000001,
     clauses = 0x0}, window_func = {wfstate = 0x100000001}, subplan = {sstate = 0x100000001}, alternative_subplan = {
     asstate = 0x100000001}, agg_deserialize = {aggstate = 0x100000001, fcinfo_data = 0x0, jumpnull = 0},
   agg_strict_input_check = {nulls = 0x100000001, nargs = 0, jumpnull = 0}, agg_init_trans = {aggstate = 0x100000001,
     pertrans = 0x0, aggcontext = 0x0, setno = 0, transno = 0, setoff = 0, jumpnull = 0}, agg_strict_trans_check = {
     aggstate = 0x100000001, setno = 0, transno = 0, setoff = 0, jumpnull = 0}, agg_trans = {aggstate = 0x100000001,
---Type <return> to continue, or q <return> to quit---
     pertrans = 0x0, aggcontext = 0x0, setno = 0, transno = 0, setoff = 0}}}
(gdb)

4.压入EEOP_DONE步骤

(gdb) n
468     scratch.opcode = EEOP_DONE;
(gdb)
469     ExprEvalPushStep(state, &scratch);
(gdb)
471     ExecReadyExpr(state);
(gdb) p state->steps[5]
$26 = {opcode = 0, resvalue = 0x0, resnull = 0x0, d = {fetch = {last_var = 1, known_desc = 0x0}, var = {attnum = 1,
     vartype = 1}, wholerow = {var = 0x100000001, first = false, slow = false, tupdesc = 0x0, junkFilter = 0x0},
   assign_var = {resultnum = 1, attnum = 1}, assign_tmp = {resultnum = 1}, constval = {value = 4294967297,
     isnull = false}, func = {finfo = 0x100000001, fcinfo_data = 0x0, fn_addr = 0x0, nargs = 0}, boolexpr = {
     anynull = 0x100000001, jumpdone = 0}, qualexpr = {jumpdone = 1}, jump = {jumpdone = 1}, nulltest_row = {
     argdesc = 0x100000001}, param = {paramid = 1, paramtype = 1}, cparam = {paramfunc = 0x100000001, paramarg = 0x0,
     paramid = 0, paramtype = 0}, casetest = {value = 0x100000001, isnull = 0x0}, make_readonly = {value = 0x100000001,
     isnull = 0x0}, iocoerce = {finfo_out = 0x100000001, fcinfo_data_out = 0x0, finfo_in = 0x0, fcinfo_data_in = 0x0},
   sqlvaluefunction = {svf = 0x100000001}, nextvalueexpr = {seqid = 1, seqtypid = 1}, arrayexpr = {
     elemvalues = 0x100000001, elemnulls = 0x0, nelems = 0, elemtype = 0, elemlength = 0, elembyval = false,
     elemalign = 0 '\000', multidims = false}, arraycoerce = {elemexprstate = 0x100000001, resultelemtype = 0,
     amstate = 0x0}, row = {tupdesc = 0x100000001, elemvalues = 0x0, elemnulls = 0x0}, rowcompare_step = {
     finfo = 0x100000001, fcinfo_data = 0x0, fn_addr = 0x0, jumpnull = 0, jumpdone = 0}, rowcompare_final = {
     rctype = ROWCOMPARE_LT}, minmax = {values = 0x100000001, nulls = 0x0, nelems = 0, op = IS_GREATEST, finfo = 0x0,
     fcinfo_data = 0x0}, fieldselect = {fieldnum = 1, resulttype = 1, argdesc = 0x0}, fieldstore = {fstore = 0x100000001,
     argdesc = 0x0, values = 0x0, nulls = 0x0, ncolumns = 0}, arrayref_subscript = {state = 0x100000001, off = 0,
     isupper = false, jumpdone = 0}, arrayref = {state = 0x100000001}, domaincheck = {
     constraintname = 0x100000001 <Address 0x100000001 out of bounds>, checkvalue = 0x0, checknull = 0x0, resulttype = 0},
   convert_rowtype = {convert = 0x100000001, indesc = 0x0, outdesc = 0x0, map = 0x0, initialized = false},
   scalararrayop = {element_type = 1, useOr = true, typlen = 0, typbyval = false, typalign = 0 '\000', finfo = 0x0,
     fcinfo_data = 0x0, fn_addr = 0x0}, xmlexpr = {xexpr = 0x100000001, named_argvalue = 0x0, named_argnull = 0x0,
     argvalue = 0x0, argnull = 0x0}, aggref = {astate = 0x100000001}, grouping_func = {parent = 0x100000001,
     clauses = 0x0}, window_func = {wfstate = 0x100000001}, subplan = {sstate = 0x100000001}, alternative_subplan = {
     asstate = 0x100000001}, agg_deserialize = {aggstate = 0x100000001, fcinfo_data = 0x0, jumpnull = 0},
   agg_strict_input_check = {nulls = 0x100000001, nargs = 0, jumpnull = 0}, agg_init_trans = {aggstate = 0x100000001,
     pertrans = 0x0, aggcontext = 0x0, setno = 0, transno = 0, setoff = 0, jumpnull = 0}, agg_strict_trans_check = {
     aggstate = 0x100000001, setno = 0, transno = 0, setoff = 0, jumpnull = 0}, agg_trans = {aggstate = 0x100000001,
---Type <return> to continue, or q <return> to quit---
     pertrans = 0x0, aggcontext = 0x0, setno = 0, transno = 0, setoff = 0}}}
(gdb)

结束调用

(gdb) n
473     return projInfo;
(gdb)
474 }
(gdb)
ExecAssignProjectionInfo (planstate=0x1c8f1f0, inputDesc=0x7f8386bb6ab8) at execUtils.c:467
467     planstate->ps_ProjInfo =
(gdb)

以上是“PostgreSQL如何构建表达式解析”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注编程网数据库频道!

您可能感兴趣的文档:

--结束END--

本文标题: PostgreSQL如何构建表达式解析

本文链接: https://lsjlt.com/news/63690.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • PostgreSQL如何构建表达式解析
    这篇文章主要介绍PostgreSQL如何构建表达式解析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!一、数据结构EEO_XXX宏定义opcode分发器宏定义 #if def...
    99+
    2024-04-02
  • PostgreSQL如何解析表达式.
    本篇内容介绍了“PostgreSQL如何解析表达式.”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!SQL样...
    99+
    2024-04-02
  • 如何构建用于正则表达式的抽象Java API
    这篇文章主要介绍了如何构建用于正则表达式的抽象Java API,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。简介尽管您可能认为编写需要分析文本的 Java 应用程序是一项简单...
    99+
    2023-06-03
  • 如何理解SqlServer表达式
    这篇文章将为大家详细讲解有关如何理解SqlServer 表达式,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。0.1 使用范围SQL Server(2008开...
    99+
    2024-04-02
  • C#如何动态创建lambda表达式
    目录C#动态创建lambda表达式Lambda表达式动态拼接生成工具类总结C#动态创建lambda表达式 近日在使用了一下EF框架,在做多条件where查询的时候不知道怎么...
    99+
    2023-02-26
    C# lambda表达式 创建lambda表达式 C#表达式
  • Python列表解析和生成器表达式的结构是什么
    今天小编给大家分享一下Python列表解析和生成器表达式的结构是什么的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下...
    99+
    2024-04-02
  • Java Lambda 表达式源码解析
    Java Lambda 源码分析 问题: Lambda 表达式是什么?JVM 内部究竟是如何实现 Lambda 表达式的?为什么要这样实现? 一、基本概念 1、Lambda 表达式 下面的例子中,() -> System.out.p...
    99+
    2021-12-25
    Java Lambda 表达式 Java Lambda源码
  • ​PostgreSQL如何解析查询语句中的表达式列并计算得出该列的值
    这篇文章主要介绍PostgreSQL如何解析查询语句中的表达式列并计算得出该列的值,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!表达式列是指除关系定义中的系统列/定义列之外的其他投影...
    99+
    2024-04-02
  • 如何在PostgreSQL中使用递归查询和公共表表达式
    在PostgreSQL中,可以使用递归查询和公共表表达式(CTE)来实现递归查询。以下是一个简单的示例,演示如何在PostgreSQ...
    99+
    2024-04-02
  • 如何在C#项目中创建一个Lambda表达式和Lambda表达式树
    如何在C#项目中创建一个Lambda表达式和Lambda表达式树?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。表达式Lambda  表达式位于 => 运算符右侧的 l...
    99+
    2023-06-06
  • 如何使用ABAP正则表达式解析HTML标签
    小编给大家分享一下如何使用ABAP正则表达式解析HTML标签,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!需求就是我用ABAP的某个函数从数据库读取一个字符串出来,该字符串的内容是一个网页。网页的form里包含了很多隐藏的...
    99+
    2023-06-04
  • 如何在 Golang 中创建正则表达式?
    如何在 golang 中创建正则表达式?使用 regexp.mustcompile 函数创建正则表达式对象。使用 regexp.matchstring 函数匹配字符串。使用 regexp...
    99+
    2024-05-13
    golang 正则表达式 字符串数组
  • 如何理解JavaScript正则表达式
    如何理解JavaScript正则表达式,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。一、正则表达式创建var reg = /test/;var reg = new RegExp...
    99+
    2023-06-02
  • python生成器表达式和列表解析
    绝大多数情况下,遍历一个集合都是为了对元素应用某个动作或是进行筛选。如果看过本文的第二部分,你应该还记得有内建函数map和filter提供了这些功能,但Python仍然为这些操作提供了语言级的支持。 (...
    99+
    2022-06-04
    生成器 表达式 列表
  • Python中 Lambda表达式全面解析
    什么是Lambda表达式 “Lambda 表达式”(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstra...
    99+
    2022-06-04
    表达式 Python Lambda
  • JavaLambda表达式实例解析原理
    目录1、实例解析2、InvokeDynamic2.1 方法调用2.2 指令规范2.3 执行过程2.4 MethodHandle1、实例解析 先从一个例子开始: public clas...
    99+
    2023-03-14
    Java Lambda表达式 Java Lambda原理
  • ASP.NET表达式树怎么构建DomainRoute的URL域名
    本篇内容主要讲解“ASP.NET表达式树怎么构建DomainRoute的URL域名”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“ASP.NET表达式树怎么构建DomainRoute的URL域名”...
    99+
    2023-06-17
  • 如何解析中文字体在CSS中的表达方式
    这篇文章将为大家详细讲解有关如何解析中文字体在CSS中的表达方式,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。在写一个网站的样式表的时候,都会不可避免地用到...
    99+
    2024-04-02
  • PostgreSQL如何创建分区表
    这篇文章主要介绍“PostgreSQL如何创建分区表”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“PostgreSQL如何创建分区表”文章能帮助大家解决问题。前言PG 假如我们想像Hive那也创建动...
    99+
    2023-07-02
  • 如何在PostgreSQL中创建表
    要在PostgreSQL中创建表,您可以使用CREATE TABLE语句。以下是一个示例: CREATE TABLE table_n...
    99+
    2024-04-09
    PostgreSQL
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作