標籤:
CREATE AGGREGATE Rbitmap_union2 (Rbitmap)( sfunc = myfunction, stype = mytype, FINALFUNC = myfunction_final);
在編寫彙總函式時,對每一行都會重複調用指定同一函數,如果要處理的資料是累加的,那麼如果不在每次調用之間共用記憶體空間,而是不停的申請釋放新的記憶體,那麼速度會變得很慢,所以在這時共用記憶體是十分有用的:
PostgreSQL 有 MemoryContext 的概念,如果普通的使用 palloc 申請記憶體空間,系統會向 CurrentMemoryContext 申請,而據我實驗猜測,彙總函式在每次調用時,都會切換 CurrentMemoryContext,所以普通的 palloc 是不能使用的。
在使用 Version 1 Calling Conventions 時,有如下宏定義, PG_FUNCTION_ARGS 是我們編寫函數的實際入參:
#define PG_FUNCTION_ARGSFunctionCallInfo fcinfo
FunctionCallInfo 是指向 FunctionCallInfoData 結構的指標:
/* * This struct is the data actually passed to an fmgr-called function. */typedef struct FunctionCallInfoData{FmgrInfo *flinfo;/* ptr to lookup info used for this call */fmNodePtrcontext;/* pass info about context of call */fmNodePtrresultinfo;/* pass or return extra info about result */Oidfncollation;/* collation for function to use */boolisnull;/* function must set true if result is NULL */shortnargs;/* # arguments actually passed */Datumarg[FUNC_MAX_ARGS];/* Arguments passed to function */boolargnull[FUNC_MAX_ARGS]; /* T if arg[i] is actually NULL */} FunctionCallInfoData;
其中的 flinfo 指向 FmgrInfo
typedef struct FmgrInfo{PGFunctionfn_addr;/* pointer to function or handler to be called */Oidfn_oid;/* OID of function (NOT of handler, if any) */shortfn_nargs;/* number of input args (0..FUNC_MAX_ARGS) */boolfn_strict;/* function is "strict" (NULL in => NULL out) */boolfn_retset;/* function returns a set */unsigned char fn_stats;/* collect stats if track_functions > this */<span style="color:#ff0000;">void *fn_extra</span>;/* extra space for use by handler */<span style="color:#ff0000;">MemoryContext fn_mcxt</span>;/* memory context to store fn_extra in */fmNodePtrfn_expr;/* expression parse tree for call, or NULL */} FmgrInfo;
我們只要在 fn_mcxt 這個 MemoryContext 下申請記憶體,就可以讓它保持在整個彙總的過程中,申請到的記憶體塊指標,可以存放到 fn_extra 中,也可以作為返回值和入參傳遞在每次調用間,最後使用 FINALFUNC 指定的函數進行最終處理。
向指定 MemoryContext - fn_mcxt 申請記憶體的函數如下:
MemoryContextAlloc(fcinfo->flinfo->fn_mcxt, sizeof(some_type));
它會返回一個指向申請記憶體空間的 void * 指標。
可以參考 src/backend/utils/adt/arrayfuncs.c 以及下列文章。
參考文章:
http://stackoverflow.com/questions/30515552/can-a-postgres-c-language-function-reference-a-stateful-variable-c-side-possibl
PostgreSQL 彙總函式共用申請的記憶體空間