文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

怎么使用PostgreSQL的ExprEvalStep

2024-04-02 19:55

关注

本篇内容介绍了“怎么使用PostgreSQL的ExprEvalStep”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

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;

FmgrInfo
在函数通过fmgr调用前,该结构体持有系统目录(字典)信息,用于检索相关信息.
如果相同的函数将被调用多次,检索只需要完成一次即可,该结构体会缓存多次使用.


typedef struct FmgrInfo
{
    //指向函数或者将被调用的处理器
    PGFunction  fn_addr;        
    //函数的oid
    Oid         fn_oid;         
    //输入参数的个数,0..FUNC_MAX_ARGS
    short       fn_nargs;       
    //函数是否严格(strict),输入NULL,输出NULL
    bool        fn_strict;      
    //函数是否返回集合
    bool        fn_retset;      
    //如track_functions > this,则收集统计信息
    unsigned char fn_stats;     
    //handler使用的额外空间
    void       *fn_extra;       
    //存储fn_extra的内存上下文
    MemoryContext fn_mcxt;      
    //表达式解析树,或者为NULL
    fmNodePtr   fn_expr;        
} FmgrInfo;
typedef struct Node *fmNodePtr;

FunctionCallInfoData
该结构体存储了实际传递给fmgr-called函数的参数


typedef struct FunctionCallInfoData
{
    //指向该调用的检索信息
    FmgrInfo   *flinfo;         
    //调用上下文
    fmNodePtr   context;        
    //传递或返回关于结果的特别信息
    fmNodePtr   resultinfo;     
    //函数的collation
    Oid         fncollation;    
#define FIELDNO_FUNCTIONCALLINFODATA_ISNULL 4
    //如结果为NULL,则必须设置为T
    bool        isnull;         
    //实际传递的参数个数
    short       nargs;          
#define FIELDNO_FUNCTIONCALLINFODATA_ARG 6
    //传递给函数的参数
    Datum       arg[FUNC_MAX_ARGS]; 
#define FIELDNO_FUNCTIONCALLINFODATA_ARGNULL 7
    //如arg[i]为NULL,则对应的值为T
    bool        argnull[FUNC_MAX_ARGS]; 
} FunctionCallInfoData;

typedef struct FunctionCallInfoData *FunctionCallInfo;

二、源码解读

ExecInitFunc函数为类函数表达式的执行配置步骤,在*state的steps中追加参数解析步骤,同时设置*scratch以便可以push到步骤中.
其主要逻辑如下:
1.检查调用函数的权限
2.检查nargs是否合法
3.为该调用分配函数检索数据和参数空间
4.配置主要的fmgr检索信息
5.初始化函数调用参数结构体
6.解析参数直接存储到fcinfo结构体中
7.根据函数的严格性和统计级别插入相应的opcode


static void
ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args, Oid funcid,
             Oid inputcollid, ExprState *state)
{
    int         nargs = list_length(args);
    AclResult   aclresult;
    FmgrInfo   *flinfo;
    FunctionCallInfo fcinfo;
    int         argno;
    ListCell   *lc;
    
    //检查调用函数的权限
    aclresult = pg_proc_aclcheck(funcid, GetUserId(), ACL_EXECUTE);
    if (aclresult != ACLCHECK_OK)
        aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(funcid));
    InvokeFunctionExecuteHook(funcid);
    
    if (nargs > FUNC_MAX_ARGS)
        ereport(ERROR,
                (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
                 errmsg_plural("cannot pass more than %d argument to a function",
                               "cannot pass more than %d arguments to a function",
                               FUNC_MAX_ARGS,
                               FUNC_MAX_ARGS)));
    
    //为该调用分配函数检索数据和参数空间
    scratch->d.func.finfo = palloc0(sizeof(FmgrInfo));
    scratch->d.func.fcinfo_data = palloc0(sizeof(FunctionCallInfoData));
    flinfo = scratch->d.func.finfo;
    fcinfo = scratch->d.func.fcinfo_data;
    
    //配置主要的fmgr检索信息
    fmgr_info(funcid, flinfo);
    fmgr_info_set_expr((Node *) node, flinfo);
    
    //初始化函数调用参数结构体
    InitFunctionCallInfoData(*fcinfo, flinfo,
                             nargs, inputcollid, NULL, NULL);
    
    //保留此信息的额外副本,以便在运行时保存间接信息
    scratch->d.func.fn_addr = flinfo->fn_addr;
    scratch->d.func.nargs = nargs;
    
    //只支持non-set函数
    if (flinfo->fn_retset)
        ereport(ERROR,
                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                 errmsg("set-valued function called in context that cannot accept a set"),
                 state->parent ?
                 executor_errposition(state->parent->state,
                                      exprLocation((Node *) node)) : 0));
    
    //解析参数直接存储到fcinfo结构体中
    argno = 0;
    foreach(lc, args)
    {
        //遍历参数
        Expr       *arg = (Expr *) lfirst(lc);
        if (IsA(arg, Const))
        {
            //常量
            
            Const      *con = (Const *) arg;
            fcinfo->arg[argno] = con->constvalue;
            fcinfo->argnull[argno] = con->constisnull;
        }
        else
        {
            //非常量,则递归调用
            ExecInitExprRec(arg, state,
                            &fcinfo->arg[argno], &fcinfo->argnull[argno]);
        }
        argno++;
    }
    
    //根据函数的严格性和统计级别插入相应的opcode
    if (pgstat_track_functions <= flinfo->fn_stats)
    {
        if (flinfo->fn_strict && nargs > 0)
            scratch->opcode = EEOP_FUNCEXPR_STRICT;
        else
            scratch->opcode = EEOP_FUNCEXPR;
    }
    else
    {
        if (flinfo->fn_strict && nargs > 0)
            scratch->opcode = EEOP_FUNCEXPR_STRICT_FUSAGE;
        else
            scratch->opcode = EEOP_FUNCEXPR_FUSAGE;
    }
}

三、跟踪分析

测试脚本

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

设置断点,跟踪

(gdb) b ExecInitFunc
Breakpoint 1 at 0x6c8c33: file execExpr.c, line 2160.
(gdb) c
Continuing.
Breakpoint 1, ExecInitFunc (scratch=0x7ffd862de730, node=0x2e675d8, args=0x2e67520, funcid=177, inputcollid=0, 
    state=0x2f228c0) at execExpr.c:2160
2160        int         nargs = list_length(args);
(gdb) bt
#0  ExecInitFunc (scratch=0x7ffd862de730, node=0x2e675d8, args=0x2e67520, funcid=177, inputcollid=0, state=0x2f228c0)
    at execExpr.c:2160
#1  0x00000000006c6200 in ExecInitExprRec (node=0x2e675d8, state=0x2f228c0, resv=0x2f228c8, resnull=0x2f228c5)
    at execExpr.c:893
#2  0x00000000006c55bc in ExecBuildProjectionInfo (targetList=0x2f2a348, econtext=0x2f223a8, slot=0x2f22820, 
    parent=0x2f22190, inputDesc=0x7ff79b051ab8) at execExpr.c:452
#3  0x00000000006e60d5 in ExecAssignProjectionInfo (planstate=0x2f22190, inputDesc=0x7ff79b051ab8) at execUtils.c:468
#4  0x00000000006e613c in ExecConditionalAssignProjectionInfo (planstate=0x2f22190, inputDesc=0x7ff79b051ab8, varno=1)
    at execUtils.c:493
#5  0x00000000006e23f5 in ExecAssignScanProjectionInfo (node=0x2f22190) at execScan.c:240
#6  0x0000000000700afc in ExecInitIndexScan (node=0x2e425f0, estate=0x2f21f78, eflags=16) at nodeIndexscan.c:962
#7  0x00000000006e00cc in ExecInitNode (node=0x2e425f0, estate=0x2f21f78, eflags=16) at execProcnode.c:217
#8  0x00000000006d6abe in InitPlan (queryDesc=0x2e65688, eflags=16) at execMain.c:1046
#9  0x00000000006d58ad in standard_ExecutorStart (queryDesc=0x2e65688, eflags=16) at execMain.c:265
#10 0x00000000006d5649 in ExecutorStart (queryDesc=0x2e65688, eflags=0) at execMain.c:147
#11 0x00000000008c18d6 in PortalStart (portal=0x2eaf608, params=0x0, eflags=0, snapshot=0x0) at pquery.c:520
#12 0x00000000008bbe1b in exec_simple_query (query_string=0x2e40d78 "select 1+id,c2 from t_expr where id < 3;")
    at postgres.c:1106
#13 0x00000000008c0191 in PostgresMain (argc=1, argv=0x2e6ecb8, dbname=0x2e6eb20 "testdb", username=0x2e3da98 "xdb")
    at postgres.c:4182
#14 0x000000000081e06c in BackendRun (port=0x2e62ae0) at postmaster.c:4361
#15 0x000000000081d7df in BackendStartup (port=0x2e62ae0) at postmaster.c:4033
#16 0x0000000000819bd9 in ServerLoop () at postmaster.c:1706
#17 0x000000000081948f in PostmasterMain (argc=1, argv=0x2e3ba50) at postmaster.c:1379
#18 0x0000000000742931 in main (argc=1, argv=0x2e3ba50) at main.c:228
(gdb)

输入参数

(gdb) p *scratch --> 步骤
$1 = {opcode = 0, resvalue = 0x2f228c8, resnull = 0x2f228c5, 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) p *node
$2 = {type = T_OpExpr}
(gdb) p *(OpExpr *)node  --> OpExpr节点
$3 = {xpr = {type = T_OpExpr}, opno = 551, opfuncid = 177, opresulttype = 23, opretset = false, opcollid = 0, 
  inputcollid = 0, args = 0x2e67520, location = 8}
testdb=# \x
Expanded display is on.
testdb=# select * from pg_proc where oid=177; --> opfuncid = 177对应的系统proc
-[ RECORD 1 ]---+-------
proname         | int4pl
pronamespace    | 11
proowner        | 10
prolang         | 12
procost         | 1
prorows         | 0
provariadic     | 0
protransform    | -
prokind         | f
prosecdef       | f
proleakproof    | f
proisstrict     | t
proretset       | f
provolatile     | i
proparallel     | s
pronargs        | 2
pronargdefaults | 0
prorettype      | 23
proargtypes     | 23 23
proallargtypes  | 
proargmodes     | 
proargnames     | 
proargdefaults  | 
protrftypes     | 
prosrc          | int4pl
probin          | 
proconfig       | 
proacl          | 
#########################################
(gdb) p *args
$4 = {type = T_List, length = 2, head = 0x2e674f8, tail = 0x2e675b0}
#########################################
(gdb) p *state  --> ExprState
$5 = {tag = {type = T_ExprState}, flags = 0 '\000', resnull = false, resvalue = 0, resultslot = 0x2f22820, 
  steps = 0x2f229b0, evalfunc = 0x0, expr = 0x2f2a348, evalfunc_private = 0x0, steps_len = 1, steps_alloc = 16, 
  parent = 0x2f22190, ext_params = 0x0, innermost_caseval = 0x0, innermost_casenull = 0x0, innermost_domainval = 0x0, 
  innermost_domainnull = 0x0}

1.检查调用函数的权限

(gdb) n
2168        aclresult = pg_proc_aclcheck(funcid, GetUserId(), ACL_EXECUTE);
(gdb) 
2169        if (aclresult != ACLCHECK_OK)
(gdb) 
2171        InvokeFunctionExecuteHook(funcid);
(gdb)

2.检查nargs是否合法

(gdb) 
2179        if (nargs > FUNC_MAX_ARGS)
(gdb)

3.为该调用分配函数检索数据和参数空间

(gdb) 
2188        scratch->d.func.finfo = palloc0(sizeof(FmgrInfo));
(gdb) 
2189        scratch->d.func.fcinfo_data = palloc0(sizeof(FunctionCallInfoData));
(gdb)

4.配置主要的fmgr检索信息

(gdb) 
2194        fmgr_info(funcid, flinfo);
(gdb) 
2195        fmgr_info_set_expr((Node *) node, flinfo);
(gdb) 
(gdb) p *flinfo
$6 = {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 = 0x2f21e60, fn_expr = 0x2e675d8}
(gdb) p *node
$7 = {type = T_OpExpr}
(gdb) p *(OpExpr *)node
$8 = {xpr = {type = T_OpExpr}, opno = 551, opfuncid = 177, opresulttype = 23, opretset = false, opcollid = 0, 
  inputcollid = 0, args = 0x2e67520, location = 8}
(gdb)

5.初始化函数调用参数结构体

(gdb) 
2198        InitFunctionCallInfoData(*fcinfo, flinfo,
(gdb) n
2202        scratch->d.func.fn_addr = flinfo->fn_addr;
(gdb) 
2203        scratch->d.func.nargs = nargs;
(gdb) 
2206        if (flinfo->fn_retset)
(gdb) 
2215        argno = 0;
(gdb) 
2216        foreach(lc, args)
(gdb) p nargs
$9 = 2
(gdb) p flinfo->fn_addr
$10 = (PGFunction) 0x93d60c <int4pl>
(gdb) p *fcinfo
$11 = {flinfo = 0x2f226b0, context = 0x0, resultinfo = 0x0, fncollation = 0, isnull = false, nargs = 2, arg = {
    0 <repeats 100 times>}, argnull = {false <repeats 100 times>}}
(gdb) p scratch->d.func
$12 = {finfo = 0x2f226b0, fcinfo_data = 0x2f22dc8, fn_addr = 0x93d60c <int4pl>, nargs = 2}
(gdb)

6.循环解析参数args直接存储到fcinfo结构体中
第1个参数,是常量1

(gdb) n
2218            Expr       *arg = (Expr *) lfirst(lc);
(gdb) 
2220            if (IsA(arg, Const))
(gdb) p *arg
$13 = {type = T_Const}
(gdb) p *(Const *)arg
$14 = {xpr = {type = T_Const}, consttype = 23, consttypmod = -1, constcollid = 0, constlen = 4, constvalue = 1, 
  constisnull = false, constbyval = true, location = 7}
(gdb) n
2226                Const      *con = (Const *) arg;
(gdb) 
2228                fcinfo->arg[argno] = con->constvalue;
(gdb) 
2229                fcinfo->argnull[argno] = con->constisnull;
(gdb) 
2236            argno++;
(gdb)

第2个参数,是Var,递归调用ExecInitExprRec解析

(gdb) 
2216        foreach(lc, args)
(gdb) 
2218            Expr       *arg = (Expr *) lfirst(lc);
(gdb) 
2220            if (IsA(arg, Const))
(gdb) 
2233                ExecInitExprRec(arg, state,
(gdb) p *arg
$15 = {type = T_Var}
(gdb) p *(Var *)arg
$16 = {xpr = {type = T_Var}, varno = 1, varattno = 1, vartype = 23, vartypmod = -1, varcollid = 0, varlevelsup = 0, 
  varnoold = 1, varoattno = 1, location = 9}
(gdb) n
2236            argno++;
(gdb) 
(gdb) n
2216        foreach(lc, args)
(gdb)

7.根据函数的严格性和统计级别插入相应的opcode

2240        if (pgstat_track_functions <= flinfo->fn_stats)
(gdb) n
2242            if (flinfo->fn_strict && nargs > 0)
(gdb) 
2243                scratch->opcode = EEOP_FUNCEXPR_STRICT;
(gdb) p pgstat_track_functions
$17 = 0
(gdb) p flinfo->fn_stats
$18 = 2 '\002'
(gdb) n

完成调用

2254    }
(gdb) 
ExecInitExprRec (node=0x2e675d8, state=0x2f228c0, resv=0x2f228c8, resnull=0x2f228c5) at execExpr.c:896
896                 ExprEvalPushStep(state, &scratch);
(gdb)

“怎么使用PostgreSQL的ExprEvalStep”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-数据库
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯