Функции PostgreSQL, возвращающие void - PullRequest
16 голосов
/ 30 ноября 2011

Функции, записанные в PL/pgSQL или SQL, могут быть определены как 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;

Функция 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

Это может иметь незначительные и запутанные побочные эффекты.
В чем причина разницы?

1 Ответ

11 голосов
/ 30 ноября 2011

(Я не эксперт в этом исходном коде. Вы были предупреждены.)

Источник онлайн здесь .Я опустил имена файлов;Вы можете искать имена функций, чтобы найти их определения.Я оставил номера строк (обычно), потому что их легче вырезать и вставлять, а разные номера строк будут означать, что источник изменился.

Коротко говоря, некоторые "пустые" возвраты - это, вероятно, пустые строки (пустой ноль)строки) и другие являются нулевыми указателями.

Вот части источника, которые выглядят актуальными.

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 }

У нас также есть

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

Такдля меня имеет смысл, что пользовательская функция, которая возвращается через PG_RETURN_VOID (), не будет тестировать эквивалентную функцию, которая возвращается через void_out () или void_send ().Я пока не знаю, почему это так, но мне нужно остановиться и немного поспать.

...