文档章节

诡异的 unnest 函数

有理想的猪
 有理想的猪
发布于 2015/12/28 17:19
字数 422
阅读 102
收藏 0

发现函数 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

© 著作权归作者所有

共有 人打赏支持
有理想的猪
粉丝 135
博文 86
码字总数 29655
作品 0
红挢
高级程序员
SQL老司机,在SQL中计算 array & map & json数据

场景 通常,我们处理数据,一列数据类型要么是字符串,要么是数字,这些都是primitive类型的数据。在某些比较复杂的业务场景下,我们会在一列中使用复杂的格式,例如数组array, 对象(map),j...

云雷
06/19
0
0
正确使用PostgreSQL的数组类型

2014-03-03 10:10 佚名 开源中国编译 我要评论(0) 字号:T | T 在Heap中,我们依靠PostgreSQL支撑大多数后端繁重的任务,我们存储每个事件为一个hstore blob,我们为每个跟踪的用户维护一个已...

威武不能笑
2014/09/04
0
0
踩坑CBO,解决那些坑爹的SQL优化问题

本文根据DBAplus社群第93期线上分享整理而成。 本次分享大纲: CBO( Cost Based Optimizer)优化器是目前Oracle广泛使用的优化器,其使用统计信息、查询转换等计算各种可能的访问路径成本,并...

丁俊
2017/02/27
0
0
jOOQ 1.6.4 发布,Java的ORM框架

jOOQ 高效的合并了复杂SQL、类型安全、源码生成、Active Records、存储过程以及高级数据类型的 Java 类库。 示例代码: // Create a new record and insert it into the databaseTBookRecor...

红薯
2011/08/08
643
3
c++的诡异与艺术一例

c++到底是诡异的还是艺术的,可能都是吧,说它诡异是因为没有理解它的精髓,说它艺术那是因为理解了它的精髓,我这里仅以一个实际的例子说明,在工作过程中,我的项目经理让我看一段程序,可...

晨曦之光
2012/04/10
27
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Ubuntu18.04 显卡GF-940MX安装NVIDIA-390.77

解决办法: 下面就给大家一个正确的姿势在Ubuntu上安装Nvidia驱动: (a)首先去N卡官网下载自己显卡对应的驱动:www.geforce.cn/drivers (b)下载后好放在英文路径的目录下,怎么简单怎么来...

AI_SKI
今天
0
0
深夜胡思乱想

魔兽世界 最近魔兽世界出了新版本, 周末两天升到了满级,比之前的版本体验好很多,做任务不用抢怪了,不用组队打怪也是共享拾取的。技能简化了很多,哪个亮按哪个。 运维 服务器 产品 之间的...

Firxiao
今天
0
0
MySQL 8 在 Windows 下安装及使用

MySQL 8 带来了全新的体验,比如支持 NoSQL、JSON 等,拥有比 MySQL 5.7 两倍以上的性能提升。本文讲解如何在 Windows 下安装 MySQL 8,以及基本的 MySQL 用法。 下载 下载地址 https://dev....

waylau
今天
0
0
微信第三方平台 access_token is invalid or not latest

微信第三方开发平台code换session_key说的特别容易,但是我一使用就带来无穷无尽的烦恼,搞了一整天也无济于事. 现在记录一下解决问题的过程,方便后来人参考. 我遇到的这个问题搜索了整个网络也...

自由的开源
今天
2
0
openJDK之sun.misc.Unsafe类CAS底层实现

注:这篇文章参考了https://www.cnblogs.com/snowater/p/8303698.html 1.sun.misc.Unsafe中CAS方法 在sun.misc.Unsafe中CAS方法如下: compareAndSwapObject(java.lang.Object arg0, long a......

汉斯-冯-拉特
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部