PostgreSQL函数返回void

Erw*_*ter 17 postgresql null stored-procedures plpgsql void

写入PL/pgSQLSQL可定义为的函数RETURNS void.我最近偶然发现了结果的奇怪差异.

请考虑以下演示:

CREATE OR REPLACE FUNCTION f_sql()
  RETURNS void AS
'SELECT NULL::void' -- "do nothing", no special meaning
  LANGUAGE sql;

CREATE OR REPLACE FUNCTION f_plpgsql()
  RETURNS void AS
$$
BEGIN
NULL; -- "do nothing", no special meaning
END;
$$  LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)

该函数f_sql()使用唯一可能的方法SELECT(在SQL函数中作为最后一个命令)RETURNS void.我使用它只是因为它是用于此测试目的的最简单方法 - 任何其他函数,例如,UPDATE或者DELETE显示相同的行为.

现在,void是一种虚构的类型.虽然plpgsql功能似乎返回一个空字符串类型相当于void有效,''::void.该sql功能似乎回归NULL::void.

db=# SELECT f_sql() IS NULL;
 ?column?
----------
 t

db=# SELECT f_sql()::text IS NULL;
 ?column?
----------
 t

db=# SELECT f_plpgsql() IS NULL;
 ?column?
----------
 f

db=# SELECT f_plpgsql()::text = '';
 ?column?
----------
 t
Run Code Online (Sandbox Code Playgroud)

这可能会产生微妙而混乱的副作用.
差异背后的原因是什么?

Mik*_*ll' 11

(我不是这个源代码的专家.你已经被警告了.)

来源在这里在线.我省略了文件名; 您可以搜索函数名称以查找其定义.我留下了行号(通常),因为它更容易剪切和粘贴,不同的行号意味着源已经改变.

简短的故事是一些"void"返回可能是空的cstrings(空的空终止字符串),而其他的是空指针.

以下是相关的源部分.

00228 /*
00229  * void_out     - output routine for pseudo-type VOID.
00230  *
00231  * We allow this so that "SELECT function_returning_void(...)" works.
00232  */
00233 Datum
00234 void_out(PG_FUNCTION_ARGS)
00235 {
00236     PG_RETURN_CSTRING(pstrdup(""));
00237 }

00251 /*
00252  * void_send    - binary output routine for pseudo-type VOID.
00253  *
00254  * We allow this so that "SELECT function_returning_void(...)" works
00255  * even when binary output is requested.
00256  */
00257 Datum
00258 void_send(PG_FUNCTION_ARGS)
00259 {
00260     StringInfoData buf;
00261 
00262     /* send an empty string */
00263     pq_begintypsend(&buf);
00264     PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
00265 }
Run Code Online (Sandbox Code Playgroud)

我们还有

00285 /* To return a NULL do this: */
00286 #define PG_RETURN_NULL()  \
00287     do { fcinfo->isnull = true; return (Datum) 0; } while (0)
00288 
00289 /* A few internal functions return void (which is not the same as NULL!) */
00290 #define PG_RETURN_VOID()     return (Datum) 0
Run Code Online (Sandbox Code Playgroud)

因此,对我来说,通过PG_RETURN_VOID()返回的用户定义函数不会测试等效于通过void_out()或void_send()返回的函数.我还不知道为什么会这样,但我必须停下来睡一会儿.