共计 5616 个字符,预计需要花费 15 分钟才能阅读完成。
这篇文章主要讲解了“PostgreSQL 隐式类型转换中使用哪些操作符实现函数”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着丸趣 TV 小编的思路慢慢深入,一起来研究和学习“PostgreSQL 隐式类型转换中使用哪些操作符实现函数”吧!
一、数据结构
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 的. 如无匹配, 则链表保持不变.
*/
func_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) c
Continuing.
Breakpoint 2, oper_select_candidate (nargs=2, input_typeids=0x7ffeb9cca190, candidates=0x13db8a0, operOid=0x7ffeb9cca22c)
at parse_oper.c:330
330 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- next
Cannot access memory at address 0x0
(gdb) n
334 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- next
Cannot access memory at address 0x0
(gdb)
感谢各位的阅读,以上就是“PostgreSQL 隐式类型转换中使用哪些操作符实现函数”的内容了,经过本文的学习后,相信大家对 PostgreSQL 隐式类型转换中使用哪些操作符实现函数这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是丸趣 TV,丸趣 TV 小编将为大家推送更多相关知识点的文章,欢迎关注!
正文完