PostgreSQL 函数返回 void

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8319986/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-20 23:26:14  来源:igfitidea点击:

PostgreSQL functions returning void

postgresqlstored-proceduresnullplpgsqlvoid

提问by Erwin Brandstetter

Functions written in PL/pgSQLor SQLcan be defined as RETURNS void. I recently stumbled upon an odd difference in the result.

PL/pgSQL或编写的函数SQL可以定义为RETURNS void. 我最近偶然发现了结果的奇怪差异。

Consider the following demo:

考虑以下演示:

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;

The function f_sql()uses the only possible way for a SELECT(as last command) in a SQL function that RETURNS void. I use it just because it is the simplest way for the purposes of this test - any other function, with UPDATEor DELETEfor instance, shows the same behavior.

该函数f_sql()SELECTSQL 函数中的(作为最后一个命令)使用唯一可能的方法,即RETURNS void. 我使用它,因为它是这个测试的目的,最简单的方法-任何其他的功能,配合UPDATEDELETE例如,显示了相同的行为。

Now, voidis a fictive type. While the plpgsqlfunction seems to return the equivalent of an empty string as type void, effectively ''::void. The sqlfunction seems to return NULL::void.

现在,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

This can have subtle and confusing side effects.
What is the reason behind the difference?

这可能会产生微妙而令人困惑的副作用。
差异背后的原因是什么?

采纳答案by Mike Sherrill 'Cat Recall'

(I'm no expert in this source code. You've been warned.)

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

The source is online here. I've omitted the filenames; you can search for the function names to find their definitions. I left the line numbers (usually) because it's easier to cut and paste, and different line numbers will mean the source has changed.

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

The short story is that some "void" returns are probably empty cstrings (empty null-terminated strings), and others are null pointers.

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

Here are the parts of the source that look relevant.

以下是看起来相关的源代码部分。

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 }

We also have

我们还有

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

So it makes sense to me that a user-defined function that returns through PG_RETURN_VOID() would not test equivalent to one that returns through void_out() or void_send(). I don't yet know why that is, but I have to stop and get some sleep.

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