您好,登錄后才能下訂單哦!
本篇內容介紹了“PostgreSQL如何解析表達式.”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
SQL樣例腳本.
testdb=# select 1+id,c2 from t_expr where id < 3;
FmgrInfo
在函數通過fmgr調用前,該結構體持有系統目錄(字典)信息,用于檢索相關信息.
如果相同的函數將被調用多次,檢索只需要完成一次即可,該結構體會緩存多次使用.
/* * 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. * 在函數通過fmgr調用前,該結構體持有系統目錄(字典)信息,用于檢索相關信息. * 如果相同的函數將被調用多次,檢索只需要完成一次即可,該結構體會緩存多次使用. * * 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實際上是關于參數的解析時確定的信息,而不是函數自身. * 但fn_expr在這里存儲而不是FunctionCallInfoData中存儲,因為從邏輯上來說,它就應該屬于那. * * 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可用于被調用函數的使用;所有其他字段應該在結構體創建后被處理為只讀. */ typedef struct FmgrInfo { //指向函數或者將被調用的處理器 PGFunction fn_addr; /* pointer to function or handler to be called */ //函數的oid Oid fn_oid; /* OID of function (NOT of handler, if any) */ //輸入參數的個數,0..FUNC_MAX_ARGS short fn_nargs; /* number of input args (0..FUNC_MAX_ARGS) */ //函數是否嚴格(strict),輸入NULL,輸出NULL bool fn_strict; /* function is "strict" (NULL in => NULL out) */ //函數是否返回集合 bool fn_retset; /* function returns a set */ //如track_functions > this,則收集統計信息 unsigned char fn_stats; /* collect stats if track_functions > this */ //handler使用的額外空間 void *fn_extra; /* extra space for use by handler */ //存儲fn_extra的內存上下文 MemoryContext fn_mcxt; /* memory context to store fn_extra in */ //表達式解析樹,或者為NULL fmNodePtr fn_expr; /* expression parse tree for call, or NULL */ } FmgrInfo; typedef struct Node *fmNodePtr;
FunctionCallInfoData
該結構體存儲了實際傳遞給fmgr-called函數的參數
/* * This struct is the data actually passed to an fmgr-called function. * 該結構體存儲了實際傳遞給fmgr-called函數的參數 * * 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.) * 被調用的函數期望設置isnull以及可能的resultinfo或者resultinfo指向的域字段. * 不應該改變其他字段. * (特別的,在參數數組上亂寫是個壞主意,因為某些調用者假定它們可以使用相同的參數重復調用) */ typedef struct FunctionCallInfoData { //指向該調用的檢索信息 FmgrInfo *flinfo; /* ptr to lookup info used for this call */ //調用上下文 fmNodePtr context; /* pass info about context of call */ //傳遞或返回關于結果的特別信息 fmNodePtr resultinfo; /* pass or return extra info about result */ //函數的collation Oid fncollation; /* collation for function to use */ #define FIELDNO_FUNCTIONCALLINFODATA_ISNULL 4 //如結果為NULL,則必須設置為T bool isnull; /* function must set true if result is NULL */ //實際傳遞的參數個數 short nargs; /* # arguments actually passed */ #define FIELDNO_FUNCTIONCALLINFODATA_ARG 6 //傳遞給函數的參數 Datum arg[FUNC_MAX_ARGS]; /* Arguments passed to function */ #define FIELDNO_FUNCTIONCALLINFODATA_ARGNULL 7 //如arg[i]為NULL,則對應的值為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.) * 所有函數可以通過fmgr直接調用,但必須持有簽名. * (其他函數可通過使用handler的方式調用,也有此簽名) */ typedef struct FunctionCallInfoData *FunctionCallInfo;
ExecInterpExpr
ExecInterpExpr中與表達式求值相關的代碼片段如下:
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(); }
如為函數表達式,則從ExecInitFunc初始化的步驟信息中獲取統一的調用參數fcinfo,然后通過函數指針(用于封裝)調用實際的函數進行表達式求值.通過統一的參數,統一的返回值,做到了實現的統一,體現了面向對象OO中多態的思想,這再次說明了OO是思想,用過程性語言一樣可以實現.
int4pl
SQL樣例腳本相應的實現函數是int4pl,其實現代碼如下:
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 }
函數實現相對比較簡單,兩個數簡單相加,如溢出則返回T,否則返回F.
“PostgreSQL如何解析表達式.”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。