CREATE FUNCTION — создание новой функции
CREATE [ OR REPLACE ] FUNCTION
name ( [ [ argmode ] [ argname ] argtype [ { DEFAULT | = } default_expr ] [, ...] ] )
[ RETURNS rettype
| RETURNS TABLE ( column_name column_type [, ...] ) ]
{ LANGUAGE lang_name
| TRANSFORM { FOR TYPE type_name } [, ... ]
| WINDOW
| { IMMUTABLE | STABLE | VOLATILE }
| [ NOT ] LEAKPROOF
| { CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT }
| { [ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER }
| PARALLEL { UNSAFE | RESTRICTED | SAFE }
| COST execution_cost
| ROWS result_rows
| SUPPORT support_function
| SET configuration_parameter { TO value | = value | FROM CURRENT }
| AS 'definition'
| AS 'obj_file', 'link_symbol'
| sql_body
} ...
Команда CREATE FUNCTION определяет новую функцию.
Команда CREATE OR REPLACE FUNCTION либо создаст новую функцию, либо заменит существующее определение.
Чтобы иметь возможность определить функцию, пользователь должен иметь привилегию USAGE для языка.
Если указано имя схемы, то функция создаётся в указанной схеме. В противном случае она создаётся в текущей схеме. Имя новой функции не должно совпадать с именем любой существующей функции или процедуры с теми же входными типами аргументов в той же схеме. Однако функции и процедуры с разными типами аргументов могут иметь одинаковое имя (это называется перегрузкой).
Чтобы заменить текущее определение существующей функции, используйте CREATE OR REPLACE FUNCTION. Нельзя изменить имя или типы аргументов функции таким способом (если вы попытаетесь, вы фактически создадите новую, отличную функцию). Кроме того, CREATE OR REPLACE FUNCTION не позволит изменить возвращаемый тип существующей функции. Для этого необходимо удалить и заново создать функцию. (При использовании параметров OUT это означает, что вы не можете изменить типы любых параметров OUT, кроме как удалив функцию.)
Когда CREATE OR REPLACE FUNCTION используется для замены существующей функции, владение и разрешения функции не меняются. Все остальные свойства функции присваиваются значениям, указанным или подразумеваемым в команде. Вы должны владеть функцией, чтобы заменить её (включая членство в роли-владельце).
Если вы удалите, а затем пересоздадите функцию, новая функция не будет той же сущностью, что и старая; вам придётся удалить существующие правила, представления, триггеры и т.д., которые ссылаются на старую функцию. Используйте CREATE OR REPLACE FUNCTION, чтобы изменить определение функции, не нарушая объекты, которые ссылаются на неё. Также ALTER FUNCTION можно использовать для изменения большинства вспомогательных свойств существующей функции.
Пользователь, создающий функцию, становится её владельцем.
Чтобы иметь возможность создать функцию, вы должны иметь привилегию USAGE на типы аргументов и возвращаемый тип.
Дополнительную информацию о написании функций см. в разделе Раздел 5.1.3.
nameИмя (возможно, с указанием схемы) создаваемой функции.
argmode
Режим аргумента: IN, OUT, INOUT или VARIADIC. Если опущено, по умолчанию используется IN. Только аргументы OUT могут следовать за VARIADIC. Также аргументы OUT и INOUT не могут использоваться вместе с обозначением RETURNS TABLE.
argnameИмя аргумента. Некоторые языки (включая SQL и PL/pgSQL) позволяют использовать это имя в теле функции. Для других языков имя входного аргумента является лишь дополнительной документацией, насколько это касается самой функции; но вы можете использовать имена входных аргументов при вызове функции для улучшения читаемости (см. Раздел 2.1.3). В любом случае имя выходного аргумента значимо, поскольку оно определяет имя столбца в типе результирующей строки. (Если вы опустите имя для выходного аргумента, система выберет имя столбца по умолчанию.)
argtypeТип(ы) данных аргументов функции (возможно, с указанием схемы), если таковые имеются. Типы аргументов могут быть базовыми, составными или доменными типами, а также могут ссылаться на тип столбца таблицы.
В зависимости от языка реализации также может быть разрешено указывать «псевдотипы», такие как cstring. Псевдотипы указывают, что фактический тип аргумента либо не полностью определён, либо выходит за рамки обычных типов данных SQL.
Тип столбца указывается записью . Использование этой возможности иногда может помочь сделать функцию независимой от изменений в определении таблицы.
table_name.column_name%TYPE
default_expr
Выражение, используемое в качестве значения по умолчанию, если параметр не указан. Выражение должно быть приводимо к типу аргумента параметра. Только входные (включая INOUT) параметры могут иметь значение по умолчанию. Все входные параметры, следующие за параметром со значением по умолчанию, также должны иметь значения по умолчанию.
rettype
Возвращаемый тип данных (возможно, с указанием схемы). Возвращаемый тип может быть базовым, составным или доменным типом, а также может ссылаться на тип столбца таблицы. В зависимости от языка реализации также может быть разрешено указывать «псевдотипы», такие как cstring. Если функция не должна возвращать значение, укажите void в качестве возвращаемого типа.
При наличии параметров OUT или INOUT предложение RETURNS можно опустить. Если оно присутствует, должно соответствовать типу результата, подразумеваемому выходными параметрами: RECORD, если выходных параметров несколько, или тому же типу, что и единственный выходной параметр.
Модификатор SETOF указывает, что функция будет возвращать набор элементов, а не один элемент.
Тип столбца указывается записью .
table_name.column_name%TYPE
column_name
Имя выходного столбца в синтаксисе RETURNS TABLE. Это, по сути, другой способ объявления именованного параметра OUT, за исключением того, что RETURNS TABLE также подразумевает RETURNS SETOF.
column_type
Тип данных выходного столбца в синтаксисе RETURNS TABLE.
lang_name
Имя языка, на котором реализована функция. Это может быть sql, c, internal или имя определённого пользователем процедурного языка, например, plpgsql. По умолчанию используется sql, если указан sql_body. Заключение имени в одинарные кавычки устарело и требует совпадения регистра.
TRANSFORM { FOR TYPE type_name } [, ... ] }Указывает, какие преобразования следует применять при вызове функции. Преобразования выполняют конвертацию между типами SQL и типами данных, специфичными для языка; см. CREATE TRANSFORM. Реализации процедурных языков обычно имеют жёстко закодированные знания о встроенных типах, поэтому их не нужно здесь перечислять. Если реализация процедурного языка не знает, как обрабатывать тип, и преобразование не предоставлено, будет использовано поведение по умолчанию для преобразования типов данных, но это зависит от реализации.
WINDOW
WINDOW указывает, что функция является оконной функцией, а не обычной функцией. В настоящее время это полезно только для функций, написанных на C. Атрибут WINDOW нельзя изменить при замене существующего определения функции.
IMMUTABLESTABLEVOLATILE
Эти атрибуты информируют планировщик запросов о поведении функции. Можно указать не более одного варианта. Если ни один из них не указан, по умолчанию предполагается VOLATILE.
IMMUTABLE указывает, что функция не может изменять базу данных и всегда возвращает один и тот же результат при задании одинаковых значений аргументов; то есть она не выполняет обращений к базе данных и не использует информацию, не представленную непосредственно в её списке аргументов. Если задан этот параметр, любой вызов функции со всеми константными аргументами может быть немедленно заменён значением функции.
STABLE указывает, что функция не может изменять базу данных и что в пределах одного сканирования таблицы она будет последовательно возвращать один и тот же результат для одинаковых значений аргументов, но её результат может меняться между SQL-операторами. Это подходящий выбор для функций, результаты которых зависят от обращений к базе данных, переменных параметров (таких как текущий часовой пояс) и т.д. (Это неприемлемо для триггеров AFTER, которые хотят запрашивать строки, изменённые текущей командой.) Также обратите внимание, что семейство функций current_timestamp считается стабильным, поскольку их значения не меняются в пределах транзакции.
VOLATILE указывает, что значение функции может меняться даже в пределах одного сканирования таблицы, поэтому никакие оптимизации невозможны. Относительно немногие функции базы данных являются волатильными в этом смысле; некоторые примеры: random(), currval(), timeofday(). Но обратите внимание, что любая функция, имеющая побочные эффекты, должна быть классифицирована как волатильная, даже если её результат вполне предсказуем, чтобы предотвратить оптимизацию вызовов; пример — setval().
Дополнительные сведения см. в разделе Раздел 5.1.7.
LEAKPROOF
LEAKPROOF указывает, что функция не имеет побочных эффектов. Она не раскрывает никакой информации о своих аргументах, кроме возвращаемого значения. Например, функция, которая выдаёт сообщение об ошибке для некоторых значений аргументов, но не для других, или которая включает значения аргументов в любое сообщение об ошибке, не является непроницаемой для утечек. Это влияет на то, как система выполняет запросы к представлениям, созданным с параметром security_barrier, или к таблицам с включённой безопасностью на уровне строк. Система будет применять условия из политик безопасности и представлений-барьеров безопасности до любых предоставленных пользователем условий из самого запроса, которые содержат функции, не являющиеся непроницаемыми для утечек, чтобы предотвратить непреднамеренное раскрытие данных. Функции и операторы, помеченные как непроницаемые для утечек, считаются доверенными и могут выполняться до условий из политик безопасности и представлений-барьеров безопасности. Кроме того, функции, которые не принимают аргументов или которым не передаются аргументы от представления-барьера безопасности или таблицы, не обязательно помечать как непроницаемые для утечек, чтобы они выполнялись до условий безопасности. См. CREATE VIEW и Раздел 5.4.5. Этот параметр может устанавливать только суперпользователь.
CALLED ON NULL INPUTRETURNS NULL ON NULL INPUTSTRICT
CALLED ON NULL INPUT (по умолчанию) указывает, что функция будет вызываться обычным образом, когда некоторые её аргументы равны null. Тогда ответственность за проверку значений null при необходимости и соответствующую реакцию лежит на авторе функции.
RETURNS NULL ON NULL INPUT или STRICT указывает, что функция всегда возвращает null, когда любой из её аргументов равен null. Если этот параметр указан, функция не выполняется при наличии аргументов null; вместо этого автоматически предполагается результат null.
[EXTERNAL] SECURITY INVOKER[EXTERNAL] SECURITY DEFINER
SECURITY INVOKER указывает, что функция должна выполняться с привилегиями пользователя, который её вызывает. Это поведение по умолчанию. SECURITY DEFINER указывает, что функция должна выполняться с привилегиями пользователя, который ею владеет. Информацию о том, как безопасно писать функции SECURITY DEFINER, см. ниже.
Ключевое слово EXTERNAL допускается для соответствия SQL, но оно является необязательным, поскольку, в отличие от SQL, эта возможность применяется ко всем функциям, а не только к внешним.
PARALLEL
PARALLEL UNSAFE указывает, что функцию нельзя выполнять в параллельном режиме; наличие такой функции в SQL-операторе заставляет использовать последовательный план выполнения. Это поведение по умолчанию. PARALLEL RESTRICTED указывает, что функцию можно выполнять в параллельном режиме, но только в процессе-лидере параллельной группы. PARALLEL SAFE указывает, что функцию безопасно запускать в параллельном режиме без ограничений, включая рабочие процессы параллельного режима.
Функции должны быть помечены как небезопасные для параллельного выполнения, если они изменяют состояние базы данных, меняют состояние транзакции (кроме как с использованием подтранзакции для восстановления после ошибок), обращаются к последовательностям (например, вызывая currval) или вносят постоянные изменения в настройки. Они должны быть помечены как ограниченные для параллельного выполнения, если они обращаются к временным таблицам, состоянию подключения клиента, курсорам, подготовленным операторам или другому локальному для серверного процесса состоянию, которое система не может синхронизировать в параллельном режиме (например, setseed не может быть выполнен ни кем, кроме лидера группы, поскольку изменение, сделанное другим процессом, не отразится в лидере). В общем случае, если функция помечена как безопасная, когда она ограниченная или небезопасная, или если она помечена как ограниченная, когда она фактически небезопасная, при использовании в параллельном запросе могут возникать ошибки или выдаваться неверные ответы. Функции на языке C теоретически могут демонстрировать совершенно неопределённое поведение при неправильной маркировке, поскольку система не может защититься от произвольного кода на C, но в большинстве вероятных случаев результат будет не хуже, чем для любой другой функции. При сомнениях функции следует помечать как UNSAFE, что и используется по умолчанию.
COST execution_costПоложительное число, задающее предполагаемую стоимость выполнения функции в единицах cpu_operator_cost. Если функция возвращает набор, это стоимость на возвращаемую строку. Если стоимость не указана, предполагается 1 единица для функций на языке C и внутренних функций и 100 единиц для функций на всех других языках. Большие значения заставляют планировщик пытаться избегать вычисления функции чаще, чем необходимо.
ROWS result_rowsПоложительное число, задающее предполагаемое количество строк, которое, как ожидает планировщик, вернёт функция. Это допускается только тогда, когда функция объявлена как возвращающая набор. По умолчанию предполагается 1000 строк.
SUPPORT support_functionИмя (возможно, с указанием схемы) функции поддержки планировщика для использования с этой функцией. Подробности см. в разделе Раздел 5.1.11. Чтобы использовать этот параметр, вы должны быть суперпользователем.
configuration_parametervalue
Предложение SET приводит к тому, что указанный параметр конфигурации устанавливается в указанное значение при входе в функцию, а затем восстанавливается в предыдущее значение при выходе из функции. SET FROM CURRENT сохраняет значение параметра, которое является текущим при выполнении CREATE FUNCTION, в качестве значения, применяемого при входе в функцию.
Если к функции прикреплено предложение SET, то эффекты команды SET LOCAL, выполненной внутри функции для той же переменной, ограничиваются функцией: предыдущее значение параметра конфигурации всё равно восстанавливается при выходе из функции. Однако обычная команда SET (без LOCAL) переопределяет предложение SET, подобно тому, как она переопределила бы предыдущую команду SET LOCAL: эффекты такой команды будут сохраняться после выхода из функции, если текущая транзакция не откатывается.
Дополнительную информацию о допустимых именах и значениях параметров см. в разделах SET и Глава 3.4.
definitionСтроковая константа, определяющая функцию; значение зависит от языка. Это может быть имя внутренней функции, путь к файлу объекта, SQL-команда или текст на процедурном языке.
Часто полезно использовать долларовые кавычки (см. Раздел 2.1.1.2.4), чтобы записать строку определения функции, а не обычный синтаксис с одинарными кавычками. Без долларовых кавычек любые одинарные кавычки или обратные косые черты в определении функции должны быть экранированы удвоением.
obj_file, link_symbol
Эта форма предложения AS используется для динамически загружаемых функций на языке C, когда имя функции в исходном коде на C отличается от имени SQL-функции. Строка obj_file — это имя файла общей библиотеки, содержащего скомпилированную функцию на C, и интерпретируется так же, как и для команды LOAD. Строка link_symbol — это символ связывания функции, то есть имя функции в исходном коде на C. Если символ связывания опущен, предполагается, что он совпадает с именем определяемой SQL-функции. Имена всех функций на C должны быть разными, поэтому перегруженным функциям на C необходимо давать разные имена на C (например, использовать типы аргументов как часть имён на C).
Когда повторные вызовы CREATE FUNCTION ссылаются на один и тот же файл объекта, файл загружается только один раз за сеанс. Чтобы выгрузить и перезагрузить файл (возможно, во время разработки), начните новый сеанс.
sql_body
Тело функции с LANGUAGE SQL. Это может быть либо один оператор
RETURN expression
либо блок
BEGIN ATOMICstatement;statement; ...statement; END
Это похоже на запись текста тела функции в виде строковой константы (см. definition выше), но есть некоторые различия: эта форма работает только для LANGUAGE SQL, а форма строковой константы работает для всех языков. Эта форма разбирается во время определения функции, а форма строковой константы разбирается во время выполнения; поэтому эта форма не может поддерживать полиморфные типы аргументов и другие конструкции, не разрешимые во время определения функции. Эта форма отслеживает зависимости между функцией и объектами, используемыми в теле функции, поэтому DROP ... CASCADE будет работать правильно, тогда как форма, использующая строковые литералы, может оставлять висячие функции. Наконец, эта форма более совместима со стандартом SQL и другими реализациями SQL.
Digital Q.DataBase позволяет перегружать функции; то есть одно и то же имя может использоваться для нескольких различных функций, при условии что они имеют различные входные типы аргументов. Используете ли вы эту возможность или нет, она влечёт за собой меры предосторожности при вызове функций в базах данных, где одни пользователи не доверяют другим; см. Раздел 2.7.3.
Две функции считаются одинаковыми, если они имеют одинаковые имена и входные типы аргументов, игнорируя любые параметры OUT. Таким образом, например, эти объявления конфликтуют:
CREATE FUNCTION foo(int) ... CREATE FUNCTION foo(int, out text) ...
Функции с разными списками типов аргументов не будут считаться конфликтующими во время создания, но если предоставлены значения по умолчанию, они могут конфликтовать при использовании. Например, рассмотрим
CREATE FUNCTION foo(int) ... CREATE FUNCTION foo(int, int default 42) ...
Вызов foo(10) завершится ошибкой из-за неоднозначности в том, какую функцию следует вызвать.
Для объявления аргументов функции и возвращаемого значения допускается полный синтаксис типов SQL. Однако модификаторы типа в скобках (например, поле точности для типа numeric) отбрасываются командой CREATE FUNCTION. Таким образом, например, CREATE FUNCTION foo (varchar(10)) ... в точности совпадает с CREATE FUNCTION foo (varchar) ....
При замене существующей функции с помощью CREATE OR REPLACE FUNCTION существуют ограничения на изменение имён параметров. Нельзя изменить имя, уже присвоенное любому входному параметру (хотя можно добавить имена к параметрам, у которых их раньше не было). Если выходных параметров более одного, нельзя изменять имена выходных параметров, потому что это изменило бы имена столбцов анонимного составного типа, описывающего результат функции. Эти ограничения введены для того, чтобы существующие вызовы функции не перестали работать при её замене.
Если функция объявлена как STRICT с аргументом VARIADIC, проверка строгости тестирует, что вариативный массив в целом не равен null. Функция всё равно будет вызвана, если массив содержит элементы null.
Сложить два целых числа с помощью SQL-функции:
CREATE FUNCTION add(integer, integer) RETURNS integer
AS 'select $1 + $2;'
LANGUAGE SQL
IMMUTABLE
RETURNS NULL ON NULL INPUT;
Та же функция, написанная в более соответствующем SQL стиле, с использованием имён аргументов и тела без кавычек:
CREATE FUNCTION add(a integer, b integer) RETURNS integer
LANGUAGE SQL
IMMUTABLE
RETURNS NULL ON NULL INPUT
RETURN a + b;
Увеличить целое число, используя имя аргумента, на PL/pgSQL:
CREATE OR REPLACE FUNCTION increment(i integer) RETURNS integer AS $$
BEGIN
RETURN i + 1;
END;
$$ LANGUAGE plpgsql;
Вернуть запись, содержащую несколько выходных параметров:
CREATE FUNCTION dup(in int, out f1 int, out f2 text)
AS $$ SELECT $1, CAST($1 AS text) || ' is text' $$
LANGUAGE SQL;
SELECT * FROM dup(42);
То же самое можно сделать более подробно, с явно именованным составным типом:
CREATE TYPE dup_result AS (f1 int, f2 text);
CREATE FUNCTION dup(int) RETURNS dup_result
AS $$ SELECT $1, CAST($1 AS text) || ' is text' $$
LANGUAGE SQL;
SELECT * FROM dup(42);
Другой способ вернуть несколько столбцов — использовать функцию TABLE:
CREATE FUNCTION dup(int) RETURNS TABLE(f1 int, f2 text)
AS $$ SELECT $1, CAST($1 AS text) || ' is text' $$
LANGUAGE SQL;
SELECT * FROM dup(42);
Однако функция TABLE отличается от предыдущих примеров, потому что она фактически возвращает набор записей, а не одну запись.
SECURITY DEFINER
Поскольку функция SECURITY DEFINER выполняется с привилегиями пользователя, который ею владеет, необходимо позаботиться о том, чтобы функция не могла быть неправильно использована. В целях безопасности search_path должен быть установлен так, чтобы исключать любые схемы, доступные для записи ненадёжным пользователям. Это предотвращает создание злонамеренными пользователями объектов (например, таблиц, функций и операторов), которые маскируют объекты, предназначенные для использования функцией. Особенно важна в этом отношении схема временных таблиц, которая по умолчанию ищется первой и обычно доступна для записи всем. Безопасную конфигурацию можно получить, заставив временную схему искаться последней. Для этого запишите pg_temp последней записью в search_path. Эта функция иллюстрирует безопасное использование:
CREATE FUNCTION check_password(uname TEXT, pass TEXT)
RETURNS BOOLEAN AS $$
DECLARE passed BOOLEAN;
BEGIN
SELECT (pwd = $2) INTO passed
FROM pwds
WHERE username = $1;
RETURN passed;
END;
$$ LANGUAGE plpgsql
SECURITY DEFINER
-- Установить безопасный search_path: доверенная схема(ы), затем 'pg_temp'.
SET search_path = admin, pg_temp;
Намерение этой функции — обращаться к таблице admin.pwds. Но без предложения SET или с предложением SET, упоминающим только admin, функция может быть подорвана путём создания временной таблицы с именем pwds.
Если функция с владельцем безопасности намеревается создавать роли, и если она выполняется от имени не-суперпользователя, также следует установить createrole_self_grant в известное значение с помощью предложения SET.
Ещё один момент, который следует иметь в виду, заключается в том, что по умолчанию право выполнения предоставляется PUBLIC для вновь созданных функций (дополнительную информацию см. в Раздел 2.2.8). Часто вы захотите ограничить использование функции с владельцем безопасности только некоторыми пользователями. Для этого необходимо отозвать привилегии PUBLIC по умолчанию, а затем выборочно предоставить право выполнения. Чтобы избежать окна, когда новая функция доступна всем, создайте её и установите привилегии в пределах одной транзакции. Например:
BEGIN; CREATE FUNCTION check_password(uname TEXT, pass TEXT) ... SECURITY DEFINER; REVOKE ALL ON FUNCTION check_password(uname TEXT, pass TEXT) FROM PUBLIC; GRANT EXECUTE ON FUNCTION check_password(uname TEXT, pass TEXT) TO admins; COMMIT;
Команда CREATE FUNCTION определена в стандарте SQL. Реализация Digital Q.DataBase может использоваться совместимым образом, но имеет много расширений. И наоборот, стандарт SQL определяет ряд дополнительных возможностей, которые не реализованы в Digital Q.DataBase.
Вот важные вопросы совместимости:
OR REPLACE является расширением PostgreSQL.
Для совместимости с некоторыми другими системами баз данных argmode можно записывать либо до, либо после argname. Но только первый способ соответствует стандарту.
Для параметров по умолчанию стандарт SQL определяет только синтаксис с ключевым словом DEFAULT. Синтаксис с = используется в T-SQL и Firebird.
Модификатор SETOF является расширением PostgreSQL.
Только SQL стандартизирован как язык.
Все остальные атрибуты, кроме CALLED ON NULL INPUT и RETURNS NULL ON NULL INPUT, не стандартизированы.
Для тела функций LANGUAGE SQL стандарт SQL определяет только форму sql_body.
Простые функции LANGUAGE SQL могут быть написаны таким образом, чтобы они одновременно соответствовали стандарту и были переносимы в другие реализации. Более сложные функции, использующие расширенные возможности, атрибуты оптимизации или другие языки, обязательно будут в значительной степени специфичны для PostgreSQL.