文档章节

诡异的 unnest 函数

有理想的猪
 有理想的猪
发布于 2015/12/28 17:19
字数 422
阅读 100
收藏 0
点赞 0
评论 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

© 著作权归作者所有

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

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

云雷 ⋅ 06/19 ⋅ 0

正确使用PostgreSQL的数组类型

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

威武不能笑 ⋅ 2014/09/04 ⋅ 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 ⋅ 3

c++的诡异与艺术一例

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

晨曦之光 ⋅ 2012/04/10 ⋅ 0

关于post的末尾路径的问题求指点,盼大神。

最近在写个东西,发现了一个很诡异的问题。 如果用浏览器GET或POST提交到 http://domain/api?id=12345,那么浏览器会自动在api的后面加上路径字符“/”,变成http://domain/api/?id=12345 ,这...

买红薯 ⋅ 2013/11/25 ⋅ 1

PostgreSQL数组使用

开发的语言有数组的概念,对应于postgresql也有相关的数据字段类型,数组是英文array的翻译,可以定义一维,二维甚至更多维度,数学上跟矩阵很类似。在postgres里面可以直接存储使用,某些场...

kenyon_君羊 ⋅ 2013/05/28 ⋅ 1

Linux系统编程 sigaction & 信号量 -- 调用一次sem_post,但却出现post两次的效果

遇到一个非常诡异的问题: 函数大致流程: 在ALARM信号处理函数中post信号量,主函数中while(1)循环sem_wait等待信号量到来并打印"hello"字符串。 然而,而当用sigaction注册信号处理函数时,w...

Mrlee1994 ⋅ 2017/08/08 ⋅ 0

深入解析C++输入输出运算符重载

其实算不上什么深入解析,只不过最近看CArchive类的实现,其中一些写法完全颠覆了我对输入输出运算符重载的一些理解,所以在这里mark一下。 我们以输出运算符为例。首先输出运算符重载的一般...

Shawphy ⋅ 2012/05/07 ⋅ 0

JavaScript中的this关键字

一般用处 2. this.x 与 apply()、call() 3. 无意义(诡异)的this用处 4. 事件监听函数中的this 5. 总结 在JavaScript中this变量是一个令人难以摸清的关键字,this可谓是非常强大,充分了解t...

xiahuawuyu ⋅ 2012/05/25 ⋅ 2

诡异的JavaScript语法

前几天一个同事问我如下的JavaScript代码如何理解: (function($){})(jQuery); 其实比较简单,要理解几个概念: 1、(),在JavaScript里()表示执行一个方法,如: function x(){ alert("xxx")...

晨曦之光 ⋅ 2012/03/09 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

DevOps 资讯 | PostgreSQL 的时代到来了吗 ?

PostgreSQL是对象-关系型数据库,BSD 许可证。拼读为"post-gress-Q-L"。 作者: Tony Baer 原文: Has the time finally come for PostgreSQL?(有删节) 近30年来 PostgreSQL 无疑是您从未听...

RiboseYim ⋅ 9分钟前 ⋅ 0

Cube、Cuboid 和 Cube Segment

1.Cube (或Data Cube),即数据立方体,是一种常用于数据分析与索引的技术;它可以对原始数据建立多维度索引。通过 Cube 对数据进行分析,可以大大加快数据的查询效率 2.Cuboid 在 Kylin 中特...

无精疯 ⋅ 48分钟前 ⋅ 0

github太慢

1:用浏览器访问 IPAddress.com or http://tool.chinaz.com 使用 IP Lookup 工具获得github.com和github.global.ssl.fastly.net域名的ip地址 2:/etc/hosts文件中添加如下格式(IP最好自己查一...

whoisliang ⋅ 49分钟前 ⋅ 0

非阻塞同步之 CAS

为解决线程安全问题,互斥同步相当于以时间换空间。多线程情况下,只有一个线程可以访问同步代码。这种同步也叫阻塞同步(Blocking Synchronization). 这种同步属于一种悲观并发策略。认为只...

长安一梦 ⋅ 今天 ⋅ 0

云计算的选择悖论如何对待?

人们都希望在工作和生活中有所选择。但心理学家的调查研究表明,在多种选项中进行选择并不一定会使人们更快乐,甚至不会产生更好的决策。心理学家Barry Schwartz称之为“选择悖论”。云计算为...

linux-tao ⋅ 今天 ⋅ 0

Redis 注册为 Windows 服务

Redis 注册为 Windows 服务 redis 注册为 windows 服务相关命令 注册服务 redis-server.exe –service-install redis.windows.conf 删除服务 redis-server –service-uninstall 启动服务 re......

Os_yxguang ⋅ 今天 ⋅ 0

世界那么大,语言那么多,为什么选择Micropython,它的优势在哪?

最近国内MicroPython风靡程序界,是什么原因导致它这么火呢?是因为他功能强大,遵循Mit协议开源么? 错!因为使用它真的是太舒服了!!! Micropython的由来,这得益于Damien George这位伟大...

bodasisiter ⋅ 今天 ⋅ 0

docker 清理总结

杀死所有正在运行的容器 docker kill $(docker ps -a -q) 删除所有已经停止的容器(docker rm没有加-f参数,运行中的容器不会删掉) docker rm $(docker ps -a -q) 删除所有未打 dangling 标...

vvx1024 ⋅ 今天 ⋅ 0

关于学习

以前学车的时候,教练说了这样的一句话:如果一个人坐在车上一直学,一直学,反而不如大家轮流着学。因为一个人一直学,就没有给自己留空间来反思和改进。而轮流着学的时候大家下来之后思考上...

mskk ⋅ 今天 ⋅ 0

压缩工具之gzip-bzip2-xz

win下常见压缩工具:rar zip 7z linux下常见压缩工具:zip gz bz2 xz tar.gz tar.bz2 tar.xz gzip 不支持目录压缩 gzip 1.txt #压缩。执行后1.txt消失,生成1.txt.gz压缩文件 gzip -d 1.txt....

ZHENG-JY ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部