广告
返回顶部
首页 > 资讯 > 数据库 >PostgreSQL 聚合函数的实现教程
  • 346
分享到

PostgreSQL 聚合函数的实现教程

2024-04-02 19:04:59 346人浏览 独家记忆
摘要

本篇内容主要讲解“postgresql 聚合函数的实现教程”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Postgresql 聚合函数的实现教程”吧!一、数据结

本篇内容主要讲解“postgresql 聚合函数的实现教程”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Postgresql 聚合函数的实现教程”吧!

一、数据结构

AggState
聚合函数执行时状态结构体,内含AggStatePerAgg等结构体



//在nodeAgg.c中私有的结构体
typedef struct AggStatePerAggData *AggStatePerAgg;
typedef struct AggStatePerTransData *AggStatePerTrans;
typedef struct AggStatePerGroupData *AggStatePerGroup;
typedef struct AggStatePerPhaseData *AggStatePerPhase;
typedef struct AggStatePerHashData *AggStatePerHash;
typedef struct AggState
{
    //第一个字段是NodeTag(继承自ScanState)
    ScanState    ss;                
    //targetlist和quals中所有的Aggref
    List       *aggs;            
    //链表的大小(可以为0)
    int            numaggs;        
    //pertrans条目大小
    int            numtrans;        
    //Agg策略模式
    AggStrategy aggstrategy;    
    //agg-splitting模式,参见nodes.h
    AggSplit    aggsplit;        
    //指向当前步骤数据的指针
    AggStatePerPhase phase;        
    //步骤数(包括0)
    int            numphases;        
    //当前步骤
    int            current_phase;    
    //per-Aggref信息
    AggStatePerAgg peragg;        
    //per-Trans状态信息
    AggStatePerTrans pertrans;    
    //长生命周期数据的ExprContexts(hashtable)
    ExprContext *hashcontext;    
    ////长生命周期数据的ExprContexts(每一个GS使用)
    ExprContext **agGContexts;    
    //输入表达式的ExprContext
    ExprContext *tmpcontext;    
#define FIELDNO_AGGSTATE_CURAGGCONTEXT 14
    //当前活跃的aggcontext
    ExprContext *curaggcontext; 
    //当前活跃的aggregate(如存在)
    AggStatePerAgg curperagg;    
#define FIELDNO_AGGSTATE_CURPERTRANS 16
    //当前活跃的trans state
    AggStatePerTrans curpertrans;    
    //输入结束?
    bool        input_done;        
    //Agg扫描结束?
    bool        agg_done;        
    //最后一个grouping set
    int            projected_set;    
#define FIELDNO_AGGSTATE_CURRENT_SET 20
    //将要解析的当前grouping set
    int            current_set;    
    //当前投影操作的分组列
    Bitmapset  *grouped_cols;    
    //倒序的分组列链表
    List       *all_grouped_cols;    
    
    //-------- 下面的列用于grouping set步骤数据
    //所有步骤中最大的sets大小
    int            maxsets;        
    //所有步骤的数组
    AggStatePerPhase phases;    
    //对于phases > 1,已排序的输入信息
    Tuplesortstate *sort_in;    
    //对于下一个步骤,输入已拷贝
    Tuplesortstate *sort_out;    
    //排序结果的slot
    TupleTableSlot *sort_slot;    
    
    //------- 下面的列用于AGG_PLaiN和AGG_SORTED模式:
    //per-group指针的grouping set编号数组
    AggStatePerGroup *pergroups;    
    //当前组的第一个元组拷贝
    HeapTuple    grp_firstTuple; 
    
    //--------- 下面的列用于AGG_HASHED和AGG_MIXED模式:
    //是否已填充hash表?
    bool        table_filled;    
    //hash桶数?
    int            num_hashes;
    //相应的哈希表数据数组
    AggStatePerHash perhash;    
    //per-group指针的grouping set编号数组
    AggStatePerGroup *hash_pergroup;    
    
    //---------- agg输入表达式解析支持
#define FIELDNO_AGGSTATE_ALL_PERGROUPS 34
    //首先是->pergroups,然后是hash_pergroup
    AggStatePerGroup *all_pergroups;    
    //投影实现机制
    ProjectionInfo *combinedproj;    
} AggState;

//nodeag .c支持的基本选项
#define AGGSPLITOP_COMBINE        0x01    
#define AGGSPLITOP_SKIPFINAL    0x02    
#define AGGSPLITOP_SERIALIZE    0x04    
#define AGGSPLITOP_DESERIALIZE    0x08    

//支持的操作模式
typedef enum AggSplit
{
    
    //基本 : 非split聚合
    AGGSPLIT_SIMPLE = 0,
    
    //部分聚合的初始步骤,序列化
    AGGSPLIT_INITIAL_SERIAL = AGGSPLITOP_SKIPFINAL | AGGSPLITOP_SERIALIZE,
    
    //部分聚合的最终步骤,反序列化
    AGGSPLIT_FINAL_DESERIAL = AGGSPLITOP_COMBINE | AGGSPLITOP_DESERIALIZE
} AggSplit;

//测试AggSplit选择了哪些基本选项
#define DO_AGGSPLIT_COMBINE(as)        (((as) & AGGSPLITOP_COMBINE) != 0)
#define DO_AGGSPLIT_SKIPFINAL(as)    (((as) & AGGSPLITOP_SKIPFINAL) != 0)
#define DO_AGGSPLIT_SERIALIZE(as)    (((as) & AGGSPLITOP_SERIALIZE) != 0)
#define DO_AGGSPLIT_DESERIALIZE(as) (((as) & AGGSPLITOP_DESERIALIZE) != 0)

二、源码解读

advance_aggregates函数最终会调用ExecInterpExpr函数(先前已介绍),通过一系列的步骤得到结果.


static void
advance_aggregates(AggState *aggstate)
{
    bool        dummynull;
    ExecEvalExprSwitchContext(aggstate->phase->evaltrans,
                              aggstate->tmpcontext,
                              &dummynull);
}

#ifndef FRONTEND
static inline Datum
ExecEvalExprSwitchContext(ExprState *state,
                          ExprContext *econtext,
                          bool *isNull)
{
    Datum        retDatum;
    MemoryContext oldContext;
    oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
    retDatum = state->evalfunc(state, econtext, isNull);
    MemoryContextSwitchTo(oldContext);
    return retDatum;
}
#endif

Datum
ExecInterpExprStillValid(ExprState *state, ExprContext *econtext, bool *isNull)
{
    
    CheckExprStillValid(state, econtext);
    
    //在后续的执行中,跳过检查.
    state->evalfunc = (ExprStateEvalFunc) state->evalfunc_private;
    
    //执行解析函数,获取结果
    return state->evalfunc(state, econtext, isNull);
}
//evalfunc_private --> ExecInterpExpr

ExecInterpExpr
解析给定”econtext”在执行上下文中通过”state”标识的表达式.

//evalfunc_private --> ExecInterpExpr

static Datum
ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
{
    ExprEvalStep *op;
    TupleTableSlot *resultslot;
    TupleTableSlot *innerslot;
    TupleTableSlot *outerslot;
    TupleTableSlot *scanslot;
    
#if defined(EEO_USE_COMPUTED_GoTO)
    static const void *const dispatch_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_table out of whack with ExprEvalOp");
    if (unlikely(state == NULL))
        //如state == NULL,则调用PointerGetDatum
        return PointerGetDatum(dispatch_table);
#else
    Assert(state != NULL);
#endif                            
    
    //配置状态变量
    op = state->steps;
    resultslot = state->resultslot;
    innerslot = econtext->ecxt_innertuple;
    outerslot = econtext->ecxt_outertuple;
    scanslot = econtext->ecxt_scantuple;
#if defined(EEO_USE_COMPUTED_GOTO)
    EEO_DISPATCH();//分发
#endif
    EEO_SWITCH()
    {
        EEO_CASE(EEOP_DONE)
        {
            goto out;
        }
        EEO_CASE(EEOP_INNER_FETCHSOME)
        {
            
            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)
        {
            int            attnum = op->d.var.attnum;
            
            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)
        {
            int            attnum = op->d.var.attnum;
            
            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)
        {
            int            attnum = op->d.var.attnum;
            
            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)
        {
            int            attnum = op->d.var.attnum;
            Datum        d;
            
            Assert(innerslot->tts_tuple != NULL);
            Assert(innerslot->tts_tuple != &(innerslot->tts_minhdr));
            
            d = heap_getsysattr(innerslot->tts_tuple, attnum,
                                innerslot->tts_tupleDescriptor,
                                op->resnull);
            *op->resvalue = d;
            EEO_NEXT();
        }
        EEO_CASE(EEOP_OUTER_SYSVAR)
        {
            int            attnum = op->d.var.attnum;
            Datum        d;
            
            Assert(outerslot->tts_tuple != NULL);
            Assert(outerslot->tts_tuple != &(outerslot->tts_minhdr));
            
            d = heap_getsysattr(outerslot->tts_tuple, attnum,
                                outerslot->tts_tupleDescriptor,
                                op->resnull);
            *op->resvalue = d;
            EEO_NEXT();
        }
        EEO_CASE(EEOP_SCAN_SYSVAR)
        {
            int            attnum = op->d.var.attnum;
            Datum        d;
            
            Assert(scanslot->tts_tuple != NULL);
            Assert(scanslot->tts_tuple != &(scanslot->tts_minhdr));
            
            d = heap_getsysattr(scanslot->tts_tuple, attnum,
                                scanslot->tts_tupleDescriptor,
                                op->resnull);
            *op->resvalue = d;
            EEO_NEXT();
        }
        EEO_CASE(EEOP_WHOLEROW)
        {
            
            ExecEvalWholeRowVar(state, op, econtext);
            EEO_NEXT();
        }
        EEO_CASE(EEOP_ASSIGN_INNER_VAR)
        {
            int            resultnum = op->d.assign_var.resultnum;
            int            attnum = op->d.assign_var.attnum;
            
            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)
        {
            int            resultnum = op->d.assign_var.resultnum;
            int            attnum = op->d.assign_var.attnum;
            
            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)
        {
            int            resultnum = op->d.assign_var.resultnum;
            int            attnum = op->d.assign_var.attnum;
            
            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)
        {
            int            resultnum = 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)
        {
            int            resultnum = op->d.assign_tmp.resultnum;
            resultslot->tts_isnull[resultnum] = state->resnull;
            if (!resultslot->tts_isnull[resultnum])
                resultslot->tts_values[resultnum] =
                    MakeExpandedObjectReadOnlyInternal(state->resvalue);
            else
                resultslot->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();
        }
        
        EEO_CASE(EEOP_FUNCEXPR)
        {
            FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
            Datum        d;
            fcinfo->isnull = false;
            d = op->d.func.fn_addr(fcinfo);
            *op->resvalue = d;
            *op->resnull = fcinfo->isnull;
            EEO_NEXT();
        }
        EEO_CASE(EEOP_FUNCEXPR_STRICT)
        {
            FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
            bool       *argnull = fcinfo->argnull;
            int            argno;
            Datum        d;
            
            for (argno = 0; argno < op->d.func.nargs; argno++)
            {
                if (argnull[argno])
                {
                    *op->resnull = true;
                    goto strictfail;
                }
            }
            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)
        {
            
            ExecEvalFuncExprFusage(state, op, econtext);
            EEO_NEXT();
        }
        EEO_CASE(EEOP_FUNCEXPR_STRICT_FUSAGE)
        {
            
            ExecEvalFuncExprStrictFusage(state, op, econtext);
            EEO_NEXT();
        }
        
        EEO_CASE(EEOP_BOOL_AND_STEP_FIRST)
        {
            *op->d.boolexpr.anynull = false;
            
            
        }
        EEO_CASE(EEOP_BOOL_AND_STEP)
        {
            if (*op->resnull)
            {
                *op->d.boolexpr.anynull = true;
            }
            else if (!DatumGetBool(*op->resvalue))
            {
                
                
                EEO_JUMP(op->d.boolexpr.jumpdone);
            }
            EEO_NEXT();
        }
        EEO_CASE(EEOP_BOOL_AND_STEP_LAST)
        {
            if (*op->resnull)
            {
                
            }
            else if (!DatumGetBool(*op->resvalue))
            {
                
                
            }
            else if (*op->d.boolexpr.anynull)
            {
                *op->resvalue = (Datum) 0;
                *op->resnull = true;
            }
            else
            {
                
            }
            EEO_NEXT();
        }
        
        EEO_CASE(EEOP_BOOL_OR_STEP_FIRST)
        {
            *op->d.boolexpr.anynull = false;
            
            
        }
        EEO_CASE(EEOP_BOOL_OR_STEP)
        {
            if (*op->resnull)
            {
                *op->d.boolexpr.anynull = true;
            }
            else if (DatumGetBool(*op->resvalue))
            {
                
                
                EEO_JUMP(op->d.boolexpr.jumpdone);
            }
            EEO_NEXT();
        }
        EEO_CASE(EEOP_BOOL_OR_STEP_LAST)
        {
            if (*op->resnull)
            {
                
            }
            else if (DatumGetBool(*op->resvalue))
            {
                
                
            }
            else if (*op->d.boolexpr.anynull)
            {
                *op->resvalue = (Datum) 0;
                *op->resnull = true;
            }
            else
            {
                
            }
            EEO_NEXT();
        }
        EEO_CASE(EEOP_BOOL_NOT_STEP)
        {
            
            *op->resvalue = BoolGetDatum(!DatumGetBool(*op->resvalue));
            EEO_NEXT();
        }
        EEO_CASE(EEOP_QUAL)
        {
            
            
            if (*op->resnull ||
                !DatumGetBool(*op->resvalue))
            {
                
                *op->resnull = false;
                *op->resvalue = BoolGetDatum(false);
                EEO_JUMP(op->d.qualexpr.jumpdone);
            }
            
            EEO_NEXT();
        }
        EEO_CASE(EEOP_JUMP)
        {
            
            EEO_JUMP(op->d.jump.jumpdone);
        }
        EEO_CASE(EEOP_JUMP_IF_NULL)
        {
            
            if (*op->resnull)
                EEO_JUMP(op->d.jump.jumpdone);
            EEO_NEXT();
        }
        EEO_CASE(EEOP_JUMP_IF_NOT_NULL)
        {
            
            if (!*op->resnull)
                EEO_JUMP(op->d.jump.jumpdone);
            EEO_NEXT();
        }
        EEO_CASE(EEOP_JUMP_IF_NOT_TRUE)
        {
            
            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)
        {
            
            ExecEvalRowNull(state, op, econtext);
            EEO_NEXT();
        }
        EEO_CASE(EEOP_NULLTEST_ROWISNOTNULL)
        {
            
            ExecEvalRowNotNull(state, op, econtext);
            EEO_NEXT();
        }
        
        EEO_CASE(EEOP_BOOLTEST_IS_TRUE)
        {
            if (*op->resnull)
            {
                *op->resvalue = BoolGetDatum(false);
                *op->resnull = false;
            }
            
            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;
            }
            
            EEO_NEXT();
        }
        EEO_CASE(EEOP_PARAM_EXEC)
        {
            
            ExecEvalParamExec(state, op, econtext);
            EEO_NEXT();
        }
        EEO_CASE(EEOP_PARAM_EXTERN)
        {
            
            ExecEvalParamExtern(state, op, econtext);
            EEO_NEXT();
        }
        EEO_CASE(EEOP_PARAM_CALLBACK)
        {
            
            op->d.cparam.paramfunc(state, op, econtext);
            EEO_NEXT();
        }
        EEO_CASE(EEOP_CASE_TESTVAL)
        {
            
            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)
        {
            
            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)
        {
            
            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)
        {
            
            char       *str;
            
            if (*op->resnull)
            {
                
                str = NULL;
            }
            else
            {
                FunctionCallInfo fcinfo_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));
                
                Assert(!fcinfo_out->isnull);
            }
            
            if (!op->d.iocoerce.finfo_in->fn_strict || str != NULL)
            {
                FunctionCallInfo fcinfo_in;
                Datum        d;
                fcinfo_in = op->d.iocoerce.fcinfo_data_in;
                fcinfo_in->arg[0] = PointerGetDatum(str);
                fcinfo_in->argnull[0] = *op->resnull;
                
                fcinfo_in->isnull = false;
                d = FunctionCallInvoke(fcinfo_in);
                *op->resvalue = d;
                
                if (str == NULL)
                {
                    Assert(*op->resnull);
                    Assert(fcinfo_in->isnull);
                }
                else
                {
                    Assert(!*op->resnull);
                    Assert(!fcinfo_in->isnull);
                }
            }
            EEO_NEXT();
        }
        EEO_CASE(EEOP_DISTINCT)
        {
            
            FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
            
            if (fcinfo->argnull[0] && fcinfo->argnull[1])
            {
                
                *op->resvalue = BoolGetDatum(false);
                *op->resnull = false;
            }
            else if (fcinfo->argnull[0] || fcinfo->argnull[1])
            {
                
                *op->resvalue = BoolGetDatum(true);
                *op->resnull = false;
            }
            else
            {
                
                Datum        eqresult;
                fcinfo->isnull = false;
                eqresult = op->d.func.fn_addr(fcinfo);
                
                *op->resvalue = BoolGetDatum(!DatumGetBool(eqresult));
                *op->resnull = fcinfo->isnull;
            }
            EEO_NEXT();
        }
        
        EEO_CASE(EEOP_NOT_DISTINCT)
        {
            FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
            if (fcinfo->argnull[0] && fcinfo->argnull[1])
            {
                *op->resvalue = BoolGetDatum(true);
                *op->resnull = false;
            }
            else if (fcinfo->argnull[0] || fcinfo->argnull[1])
            {
                *op->resvalue = BoolGetDatum(false);
                *op->resnull = false;
            }
            else
            {
                Datum        eqresult;
                fcinfo->isnull = false;
                eqresult = op->d.func.fn_addr(fcinfo);
                *op->resvalue = eqresult;
                *op->resnull = fcinfo->isnull;
            }
            EEO_NEXT();
        }
        EEO_CASE(EEOP_NULLIF)
        {
            
            FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
            
            if (!fcinfo->argnull[0] && !fcinfo->argnull[1])
            {
                Datum        result;
                fcinfo->isnull = false;
                result = op->d.func.fn_addr(fcinfo);
                
                if (!fcinfo->isnull && DatumGetBool(result))
                {
                    *op->resvalue = (Datum) 0;
                    *op->resnull = true;
                    EEO_NEXT();
                }
            }
            
            *op->resvalue = fcinfo->arg[0];
            *op->resnull = fcinfo->argnull[0];
            EEO_NEXT();
        }
        EEO_CASE(EEOP_SQLVALUEFUNCTION)
        {
            
            ExecEvalSQLValueFunction(state, op);
            EEO_NEXT();
        }
        EEO_CASE(EEOP_CURRENTOFEXPR)
        {
            
            ExecEvalCurrentOfExpr(state, op);
            EEO_NEXT();
        }
        EEO_CASE(EEOP_NEXTVALUEEXPR)
        {
            
            ExecEvalNextValueExpr(state, op);
            EEO_NEXT();
        }
        EEO_CASE(EEOP_ARRAYEXPR)
        {
            
            ExecEvalArrayExpr(state, op);
            EEO_NEXT();
        }
        EEO_CASE(EEOP_ARRAYCOERCE)
        {
            
            ExecEvalArrayCoerce(state, op, econtext);
            EEO_NEXT();
        }
        EEO_CASE(EEOP_ROW)
        {
            
            ExecEvalRow(state, op);
            EEO_NEXT();
        }
        EEO_CASE(EEOP_ROWCOMPARE_STEP)
        {
            FunctionCallInfo fcinfo = op->d.rowcompare_step.fcinfo_data;
            Datum        d;
            
            if (op->d.rowcompare_step.finfo->fn_strict &&
                (fcinfo->argnull[0] || fcinfo->argnull[1]))
            {
                *op->resnull = true;
                EEO_JUMP(op->d.rowcompare_step.jumpnull);
            }
            
            fcinfo->isnull = false;
            d = op->d.rowcompare_step.fn_addr(fcinfo);
            *op->resvalue = d;
            
            if (fcinfo->isnull)
            {
                *op->resnull = true;
                EEO_JUMP(op->d.rowcompare_step.jumpnull);
            }
            *op->resnull = false;
            
            if (DatumGetInt32(*op->resvalue) != 0)
            {
                EEO_JUMP(op->d.rowcompare_step.jumpdone);
            }
            EEO_NEXT();
        }
        EEO_CASE(EEOP_ROWCOMPARE_FINAL)
        {
            int32        cmpresult = DatumGetInt32(*op->resvalue);
            RowCompareType rctype = op->d.rowcompare_final.rctype;
            *op->resnull = false;
            switch (rctype)
            {
                    
                case ROWCOMPARE_LT:
                    *op->resvalue = BoolGetDatum(cmpresult < 0);
                    break;
                case ROWCOMPARE_LE:
                    *op->resvalue = BoolGetDatum(cmpresult <= 0);
                    break;
                case ROWCOMPARE_GE:
                    *op->resvalue = BoolGetDatum(cmpresult >= 0);
                    break;
                case ROWCOMPARE_GT:
                    *op->resvalue = BoolGetDatum(cmpresult > 0);
                    break;
                default:
                    Assert(false);
                    break;
            }
            EEO_NEXT();
        }
        EEO_CASE(EEOP_MINMAX)
        {
            
            ExecEvalMinMax(state, op);
            EEO_NEXT();
        }
        EEO_CASE(EEOP_FIELDSELECT)
        {
            
            ExecEvalFieldSelect(state, op, econtext);
            EEO_NEXT();
        }
        EEO_CASE(EEOP_FIELDSTORE_DEFORM)
        {
            
            ExecEvalFieldStoreDeForm(state, op, econtext);
            EEO_NEXT();
        }
        EEO_CASE(EEOP_FIELDSTORE_FORM)
        {
            
            ExecEvalFieldStoreForm(state, op, econtext);
            EEO_NEXT();
        }
        EEO_CASE(EEOP_ARRAYREF_SUBSCRIPT)
        {
            
            
            if (ExecEvalArrayRefSubscript(state, op))
            {
                EEO_NEXT();
            }
            else
            {
                
                EEO_JUMP(op->d.arrayref_subscript.jumpdone);
            }
        }
        EEO_CASE(EEOP_ARRAYREF_OLD)
        {
            
            
            ExecEvalArrayRefOld(state, op);
            EEO_NEXT();
        }
        
        EEO_CASE(EEOP_ARRAYREF_ASSIGN)
        {
            
            ExecEvalArrayRefAssign(state, op);
            EEO_NEXT();
        }
        
        EEO_CASE(EEOP_ARRAYREF_FETCH)
        {
            
            ExecEvalArrayRefFetch(state, op);
            EEO_NEXT();
        }
        EEO_CASE(EEOP_CONVERT_ROWTYPE)
        {
            
            ExecEvalConvertRowtype(state, op, econtext);
            EEO_NEXT();
        }
        EEO_CASE(EEOP_SCALARARRAYOP)
        {
            
            ExecEvalScalarArrayOp(state, op);
            EEO_NEXT();
        }
        EEO_CASE(EEOP_DOMAIN_NOTNULL)
        {
            
            ExecEvalConstraintNotNull(state, op);
            EEO_NEXT();
        }
        EEO_CASE(EEOP_DOMAIN_CHECK)
        {
            
            ExecEvalConstraintCheck(state, op);
            EEO_NEXT();
        }
        EEO_CASE(EEOP_XMLEXPR)
        {
            
            ExecEvalXmlExpr(state, op);
            EEO_NEXT();
        }
        EEO_CASE(EEOP_AGGREF)
        {
            
            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)
        {
            
            ExecEvalGroupingFunc(state, op);
            EEO_NEXT();
        }
        EEO_CASE(EEOP_WINDOW_FUNC)
        {
            
            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)
        {
            
            ExecEvalSubPlan(state, op, econtext);
            EEO_NEXT();
        }
        EEO_CASE(EEOP_ALTERNATIVE_SUBPLAN)
        {
            
            ExecEvalAlternativeSubPlan(state, op, econtext);
            EEO_NEXT();
        }
        
        EEO_CASE(EEOP_AGG_STRICT_DESERIALIZE)
        {
            bool       *argnull = op->d.agg_deserialize.fcinfo_data->argnull;
            
            if (argnull[0])
                EEO_JUMP(op->d.agg_deserialize.jumpnull);
            
        }
        
        EEO_CASE(EEOP_AGG_DESERIALIZE)
        {
            FunctionCallInfo fcinfo = op->d.agg_deserialize.fcinfo_data;
            AggState   *aggstate = op->d.agg_deserialize.aggstate;
            MemoryContext oldContext;
            
            oldContext = MemoryContextSwitchTo(aggstate->tmpcontext->ecxt_per_tuple_memory);
            fcinfo->isnull = false;
            *op->resvalue = FunctionCallInvoke(fcinfo);
            *op->resnull = fcinfo->isnull;
            MemoryContextSwitchTo(oldContext);
            EEO_NEXT();
        }
        
        EEO_CASE(EEOP_AGG_STRICT_INPUT_CHECK)
        {
            int            argno;
            bool       *nulls = op->d.agg_strict_input_check.nulls;
            int            nargs = 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();
        }
        
        EEO_CASE(EEOP_AGG_INIT_TRANS)
        {
            AggState   *aggstate;
            AggStatePerGroup pergroup;
            aggstate = op->d.agg_init_trans.aggstate;
            pergroup = &aggstate->all_pergroups
                [op->d.agg_init_trans.setoff]
                [op->d.agg_init_trans.transno];
            
            if (pergroup->noTransValue)
            {
                AggStatePerTrans pertrans = 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);
                
                EEO_JUMP(op->d.agg_init_trans.jumpnull);
            }
            EEO_NEXT();
        }
        
        EEO_CASE(EEOP_AGG_STRICT_TRANS_CHECK)
        {
            AggState   *aggstate;
            AggStatePerGroup pergroup;
            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();
        }
        
        EEO_CASE(EEOP_AGG_PLAIN_TRANS_BYVAL)
        {
            AggState   *aggstate;
            AggStatePerTrans pertrans;
            AggStatePerGroup pergroup;
            FunctionCallInfo fcinfo;
            MemoryContext oldContext;
            Datum        newVal;
            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;
            
            aggstate->curaggcontext = op->d.agg_trans.aggcontext;
            aggstate->current_set = op->d.agg_trans.setno;
            
            aggstate->curpertrans = pertrans;
            
            oldContext = MemoryContextSwitchTo(aggstate->tmpcontext->ecxt_per_tuple_memory);
            fcinfo->arg[0] = pergroup->transValue;
            fcinfo->argnull[0] = pergroup->transValueIsNull;
            fcinfo->isnull = false; 
            newVal = FunctionCallInvoke(fcinfo);
            pergroup->transValue = newVal;
            pergroup->transValueIsNull = fcinfo->isnull;
            MemoryContextSwitchTo(oldContext);
            EEO_NEXT();
        }
        
        EEO_CASE(EEOP_AGG_PLAIN_TRANS)
        {
            AggState   *aggstate;
            AggStatePerTrans pertrans;
            AggStatePerGroup pergroup;
            FunctionCallInfo fcinfo;
            MemoryContext oldContext;
            Datum        newVal;
            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;
            
            aggstate->curaggcontext = op->d.agg_trans.aggcontext;
            aggstate->current_set = op->d.agg_trans.setno;
            
            aggstate->curpertrans = pertrans;
            
            oldContext = MemoryContextSwitchTo(aggstate->tmpcontext->ecxt_per_tuple_memory);
            fcinfo->arg[0] = pergroup->transValue;
            fcinfo->argnull[0] = pergroup->transValueIsNull;
            fcinfo->isnull = false; 
            newVal = FunctionCallInvoke(fcinfo);
            
            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();
        }
        
        EEO_CASE(EEOP_AGG_ORDERED_TRANS_DATUM)
        {
            
            ExecEvalAggOrderedTransDatum(state, op, econtext);
            EEO_NEXT();
        }
        
        EEO_CASE(EEOP_AGG_ORDERED_TRANS_TUPLE)
        {
            
            ExecEvalAggOrderedTransTuple(state, op, econtext);
            EEO_NEXT();
        }
        EEO_CASE(EEOP_LAST)
        {
            
            Assert(false);
            goto out;
        }
    }
out:
    *isnull = state->resnull;
    return state->resvalue;
}

到此,相信大家对“PostgreSQL 聚合函数的实现教程”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

您可能感兴趣的文档:

--结束END--

本文标题: PostgreSQL 聚合函数的实现教程

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

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

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • PostgreSQL 聚合函数的实现教程
    本篇内容主要讲解“PostgreSQL 聚合函数的实现教程”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“PostgreSQL 聚合函数的实现教程”吧!一、数据结...
    99+
    2022-10-18
  • PostgreSQL聚合函数的实现方法是什么
    本篇内容介绍了“PostgreSQL聚合函数的实现方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!...
    99+
    2022-10-18
  • PostgreSQL绍聚合函数实现中怎么使用的simplehash
    这篇文章主要讲解了“PostgreSQL绍聚合函数实现中怎么使用的simplehash”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“PostgreSQL绍聚...
    99+
    2022-10-18
  • PostgreSQL聚合函数的分组排序使用示例
    目录聚合函数COUNTSUM、AVGMAX、MIN聚合函数+DISTINCTGROUP BYHAVINGORDER BY聚合函数 用于汇总的函数。 COUNT COUNT,计...
    99+
    2022-11-13
  • PostgreSQL聚合函数的分组排序怎么使用
    本篇内容介绍了“PostgreSQL聚合函数的分组排序怎么使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!聚合函数用于汇总的函数。COUN...
    99+
    2023-06-30
  • PostgreSQL执行聚合函数所使用的数据结构有哪些
    这篇文章主要讲解了“PostgreSQL执行聚合函数所使用的数据结构有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“PostgreSQL执行聚合函数所使...
    99+
    2022-10-18
  • ClickHouse源码笔记1:聚合函数的实现
    由于工作的需求,后续笔者工作需要和开源的OLAP数据库ClickHouse打交道。ClickHouse是Yandex在2016年6月15日开源了一个分析型数据库,以强悍的单机处理能力被称道。 笔者在实际测试ClickHouse和...
    99+
    2018-06-25
    ClickHouse源码笔记1:聚合函数的实现
  • uniapp实现地图点聚合功能的详细教程
    目录任务效果图生成页面顶部标题tab切换地图画布map.html页面设置实现页面通信,分解url参数初始化地图点聚合功能实现搜索功能实现总结任务 在工作中接到的一个任务,在app端实...
    99+
    2022-12-10
    uniapp实现地图点聚合 uniapp地图点聚合 uniapp实例教程
  • mongodb中按天进行聚合查询的实例教程
    前言 最近在写项目的时候遇到一个问题,使用mongodb记录了用例的执行结果,但是在时间的记录上使用的是date格式,现在有一个需求,以天为单位,统计一下每天成功的用例和失败的用例,说到统计,肯定是要用到聚...
    99+
    2022-10-18
  • ClickHouse源码笔记2:聚合流程的实现
    上篇笔记讲到了聚合函数的实现并且带大家看了聚合函数是如何注册到ClickHouse之中的并被调用使用的。这篇笔记,笔者会续上上篇的内容,将剖析一把ClickHouse聚合流程的整体实现。 第二篇文章,我们来一起看看聚合流程的实现...
    99+
    2016-07-29
    ClickHouse源码笔记2:聚合流程的实现
  • pandas数据聚合与分组运算的实现
    数据聚合与分组运算 对数据集进行分组并对各组应用一个函数(无论是聚合还是转换),通常是数据分析工作中的重要环节。在将数据集加载、融合、准备好之后,通常就是计算分组统计或生成透视表。p...
    99+
    2023-01-28
    pandas 数据聚合 pandas 分组运算
  • 【小计】PostgreSQL实现Oracle的decode函数功能
    create or replace function decode(variadic p_decode_list text[]) ret...
    99+
    2022-10-18
  • PostgreSQL中PortalRunMulti函数和PortalRun函数的实现逻辑是什么
    本篇内容主要讲解“PostgreSQL中PortalRunMulti函数和PortalRun函数的实现逻辑是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“P...
    99+
    2022-10-19
  • java通过聚合查询实现elasticsearch的groupby后的数量
    通过聚合查询获取group by 后的数量 public static int getKeyCount(String key, String index) { ...
    99+
    2022-11-12
  • PostgreSQL中create_plan函数连接计划的实现过程是什么
    本篇内容介绍了“PostgreSQL中create_plan函数连接计划的实现过程是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望...
    99+
    2022-10-18
  • PostgreSQL如何实现类似CURRENT_DATE函数的功能
    小编给大家分享一下PostgreSQL如何实现类似CURRENT_DATE函数的功能,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧...
    99+
    2022-10-18
  • PostgreSQL中函数StartTransaction的实现逻辑是什么
    这篇文章主要讲解了“PostgreSQL中函数StartTransaction的实现逻辑是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“PostgreS...
    99+
    2022-10-19
  • PostgreSQL中PostgresMain函数的实现逻辑是什么
    本篇内容主要讲解“PostgreSQL中PostgresMain函数的实现逻辑是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“PostgreSQL中Post...
    99+
    2022-10-19
  • PostgreSQL中exec_simple_query函数的实现逻辑是什么
    这篇文章主要介绍“PostgreSQL中exec_simple_query函数的实现逻辑是什么”,在日常操作中,相信很多人在PostgreSQL中exec_simple_query函数的实现逻辑是什么问题上...
    99+
    2022-10-19
  • PostgreSQL中ExecInsert函数的实现逻辑是什么
    这篇文章主要介绍“PostgreSQL中ExecInsert函数的实现逻辑是什么”,在日常操作中,相信很多人在PostgreSQL中ExecInsert函数的实现逻辑是什么问题上存在疑惑,小编查阅了各式资料...
    99+
    2022-10-19
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作