本篇內(nèi)容介紹了“PostgreSQL如何解析表達(dá)式.”的有關(guān)知識(shí),在實(shí)際案例的操作過程中,不少人都會(huì)遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
創(chuàng)新互聯(lián)公司是一家專業(yè)提供荷塘企業(yè)網(wǎng)站建設(shè),專注與成都網(wǎng)站建設(shè)、網(wǎng)站設(shè)計(jì)、HTML5、小程序制作等業(yè)務(wù)。10年已為荷塘眾多企業(yè)、政府機(jī)構(gòu)等服務(wù)。創(chuàng)新互聯(lián)專業(yè)網(wǎng)站制作公司優(yōu)惠進(jìn)行中。
SQL樣例腳本.
testdb=# select 1+id,c2 from t_expr where id < 3;
FmgrInfo
在函數(shù)通過fmgr調(diào)用前,該結(jié)構(gòu)體持有系統(tǒng)目錄(字典)信息,用于檢索相關(guān)信息.
如果相同的函數(shù)將被調(diào)用多次,檢索只需要完成一次即可,該結(jié)構(gòu)體會(huì)緩存多次使用.
/* * This struct holds the system-catalog information that must be looked up * before a function can be called through fmgr. If the same function is * to be called multiple times, the lookup need be done only once and the * info struct saved for re-use. * 在函數(shù)通過fmgr調(diào)用前,該結(jié)構(gòu)體持有系統(tǒng)目錄(字典)信息,用于檢索相關(guān)信息. * 如果相同的函數(shù)將被調(diào)用多次,檢索只需要完成一次即可,該結(jié)構(gòu)體會(huì)緩存多次使用. * * Note that fn_expr really is parse-time-determined information about the * arguments, rather than about the function itself. But it's convenient * to store it here rather than in FunctionCallInfoData, where it might more * logically belong. * 注意,fn_expr實(shí)際上是關(guān)于參數(shù)的解析時(shí)確定的信息,而不是函數(shù)自身. * 但fn_expr在這里存儲(chǔ)而不是FunctionCallInfoData中存儲(chǔ),因?yàn)閺倪壿嬌蟻碚f,它就應(yīng)該屬于那. * * fn_extra is available for use by the called function; all other fields * should be treated as read-only after the struct is created. * fn_extra可用于被調(diào)用函數(shù)的使用;所有其他字段應(yīng)該在結(jié)構(gòu)體創(chuàng)建后被處理為只讀. */ typedef struct FmgrInfo { //指向函數(shù)或者將被調(diào)用的處理器 PGFunction fn_addr; /* pointer to function or handler to be called */ //函數(shù)的oid Oid fn_oid; /* OID of function (NOT of handler, if any) */ //輸入?yún)?shù)的個(gè)數(shù),0..FUNC_MAX_ARGS short fn_nargs; /* number of input args (0..FUNC_MAX_ARGS) */ //函數(shù)是否嚴(yán)格(strict),輸入NULL,輸出NULL bool fn_strict; /* function is "strict" (NULL in => NULL out) */ //函數(shù)是否返回集合 bool fn_retset; /* function returns a set */ //如track_functions > this,則收集統(tǒng)計(jì)信息 unsigned char fn_stats; /* collect stats if track_functions > this */ //handler使用的額外空間 void *fn_extra; /* extra space for use by handler */ //存儲(chǔ)fn_extra的內(nèi)存上下文 MemoryContext fn_mcxt; /* memory context to store fn_extra in */ //表達(dá)式解析樹,或者為NULL fmNodePtr fn_expr; /* expression parse tree for call, or NULL */ } FmgrInfo; typedef struct Node *fmNodePtr;
FunctionCallInfoData
該結(jié)構(gòu)體存儲(chǔ)了實(shí)際傳遞給fmgr-called函數(shù)的參數(shù)
/* * This struct is the data actually passed to an fmgr-called function. * 該結(jié)構(gòu)體存儲(chǔ)了實(shí)際傳遞給fmgr-called函數(shù)的參數(shù) * * The called function is expected to set isnull, and possibly resultinfo or * fields in whatever resultinfo points to. It should not change any other * fields. (In particular, scribbling on the argument arrays is a bad idea, * since some callers assume they can re-call with the same arguments.) * 被調(diào)用的函數(shù)期望設(shè)置isnull以及可能的resultinfo或者resultinfo指向的域字段. * 不應(yīng)該改變其他字段. * (特別的,在參數(shù)數(shù)組上亂寫是個(gè)壞主意,因?yàn)槟承┱{(diào)用者假定它們可以使用相同的參數(shù)重復(fù)調(diào)用) */ typedef struct FunctionCallInfoData { //指向該調(diào)用的檢索信息 FmgrInfo *flinfo; /* ptr to lookup info used for this call */ //調(diào)用上下文 fmNodePtr context; /* pass info about context of call */ //傳遞或返回關(guān)于結(jié)果的特別信息 fmNodePtr resultinfo; /* pass or return extra info about result */ //函數(shù)的collation Oid fncollation; /* collation for function to use */ #define FIELDNO_FUNCTIONCALLINFODATA_ISNULL 4 //如結(jié)果為NULL,則必須設(shè)置為T bool isnull; /* function must set true if result is NULL */ //實(shí)際傳遞的參數(shù)個(gè)數(shù) short nargs; /* # arguments actually passed */ #define FIELDNO_FUNCTIONCALLINFODATA_ARG 6 //傳遞給函數(shù)的參數(shù) Datum arg[FUNC_MAX_ARGS]; /* Arguments passed to function */ #define FIELDNO_FUNCTIONCALLINFODATA_ARGNULL 7 //如arg[i]為NULL,則對(duì)應(yīng)的值為T bool argnull[FUNC_MAX_ARGS]; /* T if arg[i] is actually NULL */ } FunctionCallInfoData; /* * All functions that can be called directly by fmgr must have this signature. * (Other functions can be called by using a handler that does have this * signature.) * 所有函數(shù)可以通過fmgr直接調(diào)用,但必須持有簽名. * (其他函數(shù)可通過使用handler的方式調(diào)用,也有此簽名) */ typedef struct FunctionCallInfoData *FunctionCallInfo;
ExecInterpExpr
ExecInterpExpr中與表達(dá)式求值相關(guān)的代碼片段如下:
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(); }
如為函數(shù)表達(dá)式,則從ExecInitFunc初始化的步驟信息中獲取統(tǒng)一的調(diào)用參數(shù)fcinfo,然后通過函數(shù)指針(用于封裝)調(diào)用實(shí)際的函數(shù)進(jìn)行表達(dá)式求值.通過統(tǒng)一的參數(shù),統(tǒng)一的返回值,做到了實(shí)現(xiàn)的統(tǒng)一,體現(xiàn)了面向?qū)ο驩O中多態(tài)的思想,這再次說明了OO是思想,用過程性語言一樣可以實(shí)現(xiàn).
int4pl
SQL樣例腳本相應(yīng)的實(shí)現(xiàn)函數(shù)是int4pl,其實(shí)現(xiàn)代碼如下:
Datum int4pl(PG_FUNCTION_ARGS) { int32 arg1 = PG_GETARG_INT32(0); int32 arg2 = PG_GETARG_INT32(1); int32 result; if (unlikely(pg_add_s32_overflow(arg1, arg2, &result))) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); PG_RETURN_INT32(result); } /* * If a + b overflows, return true, otherwise store the result of a + b into * *result. The content of *result is implementation defined in case of * overflow. */ static inline bool pg_add_s32_overflow(int32 a, int32 b, int32 *result) { #if defined(HAVE__BUILTIN_OP_OVERFLOW) return __builtin_add_overflow(a, b, result); #else int64 res = (int64) a + (int64) b; if (res > PG_INT32_MAX || res < PG_INT32_MIN) { *result = 0x5EED; /* to avoid spurious warnings */ return true; } *result = (int32) res; return false; #endif }
函數(shù)實(shí)現(xiàn)相對(duì)比較簡(jiǎn)單,兩個(gè)數(shù)簡(jiǎn)單相加,如溢出則返回T,否則返回F.
“PostgreSQL如何解析表達(dá)式.”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!