PostgreSQL 源碼解讀(210)- 隱式類型轉換(func_match_argtypes)

本節簡單介紹了PostgreSQL隱式類型轉換中使用哪些操作符(pg_operator)的實現函數func_match_argtypes.

一、數據結構

FuncCandidateList 
該結構體存儲檢索得到的所有可能選中的函數或操作符鏈表.

/* *  This structure holds a list of possible functions or operators *  found by namespace lookup.  Each function/operator is identified *  by OID and by argument types; the list must be pruned by type *  resolution rules that are embodied in the parser, not here. *  See FuncnameGetCandidates's comments for more info. *  該結構體存儲檢索得到的所有可能選中的函數或操作符鏈表. *  每一個函數/操作符通過OID和參數類型唯一確定, *  通過集成到分析器中的type resolution rules來確定裁剪該鏈表(但不是在這裏實現) *  詳細可參考FuncnameGetCandidates函數. */typedef struct _FuncCandidateList{    struct _FuncCandidateList *next;    //用於namespace檢索內部使用    int         pathpos;        /* for internal use of namespace lookup */    //OID    Oid         oid;            /* the function or operator's OID */    //參數個數     int         nargs;          /* number of arg types returned */    //variadic array的參數個數    int         nvargs;         /* number of args to become variadic array */    //默認參數個數    int         ndargs;         /* number of defaulted args */    //參數位置索引    int        *argnumbers;     /* args' positional indexes, if named call */    //參數類型    Oid         args[FLEXIBLE_ARRAY_MEMBER];    /* arg types */}          *FuncCandidateList;

二、源碼解讀

func_match_argtypes 
給定候選函數列表(正確的函數名稱/參數個數匹配)和輸入數據類型OIDs數組,生成實際可匹配輸入數據類型(完全匹配或可轉換)的候選函數鏈表,然後符合條件的候選函數個數.

/* func_match_argtypes() * * Given a list of candidate functions (having the right name and number * of arguments) and an array of input datatype OIDs, produce a shortlist of * those candidates that actually accept the input datatypes (either exactly * or by coercion), and return the number of such candidates. * 給定候選函數列表(正確的函數名稱/參數個數匹配)和輸入數據類型OIDs數組, * 生成實際可匹配輸入數據類型(完全匹配或可轉換)的候選函數鏈表,然後符合條件的候選函數個數 * * Note that can_coerce_type will assume that UNKNOWN inputs are coercible to * anything, so candidates will not be eliminated on that basis. * can_coerce_type函數假定UNKNOWN輸入可轉換爲任意類型. * * NB: okay to modify input list structure, as long as we find at least * one match.  If no match at all, the list must remain unmodified. * 注意:如果只是找到一個匹配的候選函數,修改輸入鏈表結構是OK的.如無匹配,則鏈表保持不變. */intfunc_match_argtypes(int nargs,                    Oid *input_typeids,                    FuncCandidateList raw_candidates,                    FuncCandidateList *candidates)  /* return value */{    FuncCandidateList current_candidate;//當前候選    FuncCandidateList next_candidate;//下一候選    int         ncandidates = 0;    *candidates = NULL;    for (current_candidate = raw_candidates;         current_candidate != NULL;         current_candidate = next_candidate)//遍歷候選函數    {        next_candidate = current_candidate->next;        if (can_coerce_type(nargs, input_typeids, current_candidate->args,                            COERCION_IMPLICIT))//可匹配輸入數據類型(完全匹配或可轉換)        {            current_candidate->next = *candidates;            *candidates = current_candidate;            ncandidates++;        }    }    return ncandidates;}                               /* func_match_argtypes() */

在pg_operator中,輸入參數類型與operator的參數類型匹配或可轉換,可進入候選函數鏈表.

三、跟蹤分析

測試腳本

create cast(integer as text) with inout as implicit;select id||'X' from t_cast;

跟蹤分析

(gdb) cContinuing.Breakpoint 2, oper_select_candidate (nargs=2, input_typeids=0x7ffeb9cca190, candidates=0x13db8a0, operOid=0x7ffeb9cca22c)    at parse_oper.c:330330     ncandidates = func_match_argtypes(nargs, input_typeids,(gdb) p *candidates$1 = {next = 0x13db870, pathpos = 0, oid = 3284, nargs = 2, nvargs = 0, ndargs = 0, argnumbers = 0x0, args = 0x13db8c8}(gdb) p *candidates->next$2 = {next = 0x13db840, pathpos = 0, oid = 3681, nargs = 2, nvargs = 0, ndargs = 0, argnumbers = 0x0, args = 0x13db898}(gdb) p *candidates->next->next$3 = {next = 0x13db810, pathpos = 0, oid = 3633, nargs = 2, nvargs = 0, ndargs = 0, argnumbers = 0x0, args = 0x13db868}(gdb) p *candidates->next->next->next$4 = {next = 0x13db7e0, pathpos = 0, oid = 2780, nargs = 2, nvargs = 0, ndargs = 0, argnumbers = 0x0, args = 0x13db838}(gdb) p *candidates->next->next->next->next$5 = {next = 0x13db7b0, pathpos = 0, oid = 374, nargs = 2, nvargs = 0, ndargs = 0, argnumbers = 0x0, args = 0x13db808}(gdb) p *candidates->next->next->next->next->next$6 = {next = 0x13db780, pathpos = 0, oid = 349, nargs = 2, nvargs = 0, ndargs = 0, argnumbers = 0x0, args = 0x13db7d8}(gdb) p *candidates->next->next->next->next->next->next$7 = {next = 0x13db750, pathpos = 0, oid = 375, nargs = 2, nvargs = 0, ndargs = 0, argnumbers = 0x0, args = 0x13db7a8}(gdb) p *candidates->next->next->next->next->next->next->next$8 = {next = 0x13db720, pathpos = 0, oid = 1797, nargs = 2, nvargs = 0, ndargs = 0, argnumbers = 0x0, args = 0x13db778}(gdb) p *candidates->next->next->next->next->next->next->next->next$9 = {next = 0x13db6f0, pathpos = 0, oid = 2779, nargs = 2, nvargs = 0, ndargs = 0, argnumbers = 0x0, args = 0x13db748}(gdb) p *candidates->next->next->next->next->next->next->next->next->next$10 = {next = 0x13db6c0, pathpos = 0, oid = 654, nargs = 2, nvargs = 0, ndargs = 0, argnumbers = 0x0, args = 0x13db718}(gdb) p *candidates->next->next->next->next->next->next->next->next->next->next$11 = {next = 0x0, pathpos = 0, oid = 2018, nargs = 2, nvargs = 0, ndargs = 0, argnumbers = 0x0, args = 0x13db6e8}(gdb) p *candidates->next->next->next->next->next->next->next->next->next->next->nextCannot access memory at address 0x0(gdb) n334     if (ncandidates == 0)(gdb) 339     if (ncandidates == 1)(gdb) 349     candidates = func_select_candidate(nargs, input_typeids, candidates);(gdb) p ncandidates$12 = 2(gdb) p *candidates$13 = {next = 0x13db810, pathpos = 0, oid = 374, nargs = 2, nvargs = 0, ndargs = 0, argnumbers = 0x0, args = 0x13db808}(gdb) p *candidates->next$14 = {next = 0x0, pathpos = 0, oid = 2780, nargs = 2, nvargs = 0, ndargs = 0, argnumbers = 0x0, args = 0x13db838}(gdb) p *candidates->next->nextCannot access memory at address 0x0(gdb)

DONE!        鄭州×××醫院×××:http://myyk.familydoctor.com.cn/yiyuanzaixian/zztjyy//

四、參考資料

PostgreSQL Type Conversion


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章