为什么80%的码农都做不了架构师?>>>
发现函数 unnest 定义如下:
CREATE OR REPLACE FUNCTION unnest(anyarray)
RETURNS SETOF anyelement AS
'array_unnest'
LANGUAGE internal IMMUTABLE STRICT
COST 1
ROWS 100;
为了可读性,这是还原后的SQL 语句,实际上它是在 pg_proc.h 中定义的:
DATA(insert OID = 2331 ( unnest PGNSP PGUID 12 1 100 0 0 f f f f t t i 1 0 2283 "2277" _null_ _null_ _null_ _null_ array_unnest _null_ _null_ _null_ ));
运行一下:
postgres=# select unnest(array[10,20]);
unnest
--------
10
20
(2 rows)
postgres=#
很正常是吧,换种方式:
postgres=# SELECT unnest(array[10,20],array['foo','bar'],array[1.0]);
ERROR: function unnest(integer[], text[], numeric[]) does not exist
LINE 1: SELECT unnest(array[10,20],array['foo','bar'],array[1.0]);
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
postgres=#
这也正常对吧,只支持一个参数嘛,再换种方式:
postgres=# SELECT * FROM unnest(array[10,20],array['foo','bar'],array[1.0]);
unnest | unnest | unnest
--------+--------+--------
10 | foo | 1.0
20 | bar |
(2 rows)
postgres=#
发生了什么事?
代码(parse_clause.c)在这里:
if (IsA(fexpr, FuncCall))
{
FuncCall *fc = (FuncCall *) fexpr;
if (list_length(fc->funcname) == 1 &&
strcmp(strVal(linitial(fc->funcname)), "unnest") == 0 &&
list_length(fc->args) > 1 &&
fc->agg_order == NIL &&
fc->agg_filter == NULL &&
!fc->agg_star &&
!fc->agg_distinct &&
!fc->func_variadic &&
fc->over == NULL &&
coldeflist == NIL)
{
ListCell *lc;
foreach(lc, fc->args)
{
Node *arg = (Node *) lfirst(lc);
FuncCall *newfc;
newfc = makeFuncCall(SystemFuncName("unnest"),
list_make1(arg),
fc->location);
... // 更多
在 FROM 子句里边的函数调用叫做 RangeFunction,而只有这个 unnest 做了特殊处理,实际上三个参数函数被调用了三次。
如果我们有类似处理需求,这是一个可以参考的手段。
语法引擎(gram.y)代码如下:
from_list:
table_ref { $$ = list_make1($1); }
| from_list ',' table_ref { $$ = lappend($1, $3); }
;
/*
* table_ref is where an alias clause can be attached.
*/
table_ref: relation_expr opt_alias_clause
... // 省略
| func_table func_alias_clause
{
RangeFunction *n = (RangeFunction *) $1;
n->alias = linitial($2);
n->coldeflist = lsecond($2);
$$ = (Node *) n;
}
By, PostgreSQL中国用户会,http://postgres.cn