CREATE FUNCTION

CREATE FUNCTION — define uma nova função

Sinopse

CREATE [ OR REPLACE ] FUNCTION
    nome ( [
      [ modo_do_argumento ]
      [ nome_do_argumento ]
      tipo_de_dados_do_argumento
      [ { DEFAULT | = } expressão_padrão ] [, ...] ] )
    [ RETURNS tipo_de_dados_retornado |
      RETURNS TABLE ( nome_da_coluna tipo_de_dados_da_coluna [, ...] )
    ]
  { LANGUAGE nome_da_linguagem
    | TRANSFORM { FOR TYPE nome_do_tipo_de_dados } [, ... ]
    | 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 custo_de_execução
    | ROWS linhas_de_resultado
    | SUPPORT função_de_suporte
    | SET parâmetro_de_configuração { TO valor | = valor | FROM CURRENT }
    | AS 'definição'
    | AS 'arquivo_objeto', 'símbolo_de_ligação'
    | corpo_sql
  } ...

Descrição

O comando CREATE FUNCTION define uma nova função. O comando CREATE OR REPLACE FUNCTION define uma nova função, ou substitui uma definição existente. Para poder definir uma função, é necessário ter o privilégio USAGE na linguagem. [125]

Se for incluído o nome do esquema, a função será criada no esquema especificado. Caso contrário, será criada no esquema corrente. O nome da nova função não deve corresponder a nenhuma função ou procedimento existente com os mesmos tipos de dados dos argumentos de entrada no mesmo esquema. Entretanto, funções e procedimentos com diferentes tipos de dados dos argumentos podem compartilhar o mesmo nome (isto se chama sobrecarga).

Para substituir a definição corrente de uma função existente, é usado o comando CREATE OR REPLACE FUNCTION. Não é possível alterar o nome ou os tipos de dados dos argumentos de uma função desta forma (se fosse tentado, na verdade, estaria sendo criada uma função nova e distinta). Além disso, CREATE OR REPLACE FUNCTION não permite alterar o tipo de dados retornado de uma função existente. Para fazer isto, é necessário remover e recriar a função. (Ao usar parâmetros OUT, isto significa que não se pode alterar os tipos de dados de nenhum parâmetro OUT, exceto removendo a função.)

Quando é usado CREATE OR REPLACE FUNCTION para substituir uma função existente, o dono e as permissões da função não mudam. Todas as outras propriedades da função recebem os valores especificados ou implícitos no comando. É necessário ser o dono da função para substituí-la (isto inclui ser membro da função de banco de dados (role) dona).

Se a função for removida e recriada, a nova função não será a mesma entidade que a antiga; é necessário remover as regras, visões, gatilhos, etc. existentes que se referem à função antiga. Deve ser usado o comando CREATE OR REPLACE FUNCTION para alterar uma definição de função sem quebrar os objetos que se referem à função. Além disso, pode ser usado ALTER FUNCTION para alterar a maioria das propriedades auxiliares de uma função existente.

O usuário que cria a função torna-se o dono da função.

Para poder criar uma função, é necessário ter o privilégio USAGE nos tipos de dados dos argumentos e no tipo de dados retornado.

Veja Funções definidas pelo usuário para obter mais informações sobre como escrever funções.

Parâmetros

nome

O nome (opcionalmente qualificado pelo esquema) da função a ser criada.

modo_do_argumento

O modo do argumento: IN, OUT, INOUT, ou VARIADIC. Se omitido, o padrão é IN. Somente argumentos OUT podem seguir um argumento VARIADIC. Além disso, os argumentos OUT e INOUT não podem ser usados com a notação RETURNS TABLE. [126]

nome_do_argumento

O nome do argumento. Algumas linguagens (incluindo SQL e PL/pgSQL) permitem o uso desse nome no corpo da função. Para outras linguagens, o nome do argumento de entrada é apenas documentação extra, no que diz respeito à própria função; mas pode-se usar nomes de argumentos de entrada ao chamar uma função para melhorar a legibilidade (veja Chamadas de função). Em todos os casos, o nome do argumento de saída é significativo, porque define o nome da coluna na linha de resultados. (Se for omitido o nome de um argumento de saída, o sistema escolherá um nome de coluna padrão.)

tipo_de_dados_do_argumento

Os tipos de dados dos argumentos da função (opcionalmente qualificados pelo esquema), se houver. Os tipos de dados dos argumentos podem ser tipos base, compostos ou de domínio, ou podem fazer referência ao tipo de dados de uma coluna da tabela.

Dependendo da linguagem de implementação, também pode ser permitido especificar pseudo-tipos, como cstring. Pseudotipos indicam que o tipo de dados do argumento real está especificado de forma incompleta ou fora do conjunto de tipos de dados SQL comuns.

O tipo de dados de uma coluna é referenciado escrevendo nome_da_tabela.nome_da_coluna%TYPE. O uso desse recurso pode, às vezes, ajudar a tornar a função independente das alterações na definição da tabela.

expressão_padrão

Expressão a ser usada como valor padrão se o parâmetro não for especificado. A expressão deve ser conversível para o tipo de dados do argumento do parâmetro. Somente os parâmetros de entrada (incluindo INOUT) podem ter valor padrão. Todos os parâmetros de entrada que seguem um parâmetro com valor padrão também devem ter valor padrão.

tipo_de_dados_retornado

O tipo de dados retornado (opcionalmente qualificado pelo esquema). O tipo de dados retornado pode ser um tipo base, composto ou de domínio, ou pode referenciar o tipo de dados de uma coluna da tabela. Dependendo da linguagem de implementação, também pode ser permitido especificar pseudo-tipos, como cstring. Se a função não deve retornar um valor, deve der especificado void como o tipo de dados retornado.

Quando existem parâmetros OUT ou INOUT, pode ser omitida a cláusula RETURNS. Se estiver presente, deve corresponder ao tipo de dados do resultado imposto pelos parâmetros de saída: RECORD se houver vários parâmetros de saída, ou o mesmo tipo de dados que o único parâmetro de saída.

O modificador SETOF indica que a função retorna um conjunto de itens, em vez de um único item.

O tipo de dados de uma coluna é referenciado escrevendo nome_da_tabela.nome_da_coluna%TYPE.

nome_da_coluna

O nome da coluna de saída na sintaxe RETURNS TABLE. Esta é outra maneira de declarar um parâmetro OUT com nome, exceto que RETURNS TABLE também implica em RETURNS SETOF.

tipo_de_dados_da_coluna

O tipo de dados de uma coluna de saída na sintaxe RETURNS TABLE.

nome_da_linguagem

O nome da linguagem na qual a função é implementada. Pode ser sql, c, internal, ou o nome de uma linguagem procedural definida pelo usuário, por exemplo, plpgsql. O padrão é sql se for especificado o corpo_sql. Colocar o nome entre apóstrofos é obsoleto, e requer letras maiúsculas e minúsculas correspondentes.

TRANSFORM { FOR TYPE nome_do_tipo_de_dados } [, ... ] }

Lista as transformações aplicadas a uma chamada à função. As transformações convertem entre tipos de dados SQL e tipos de dados específicos da linguagem; veja CREATE TRANSFORM. As implementações das linguagens procedurais geralmente têm conhecimento codificado dos tipos de dados integrados, portanto, estes não precisam ser listados aqui. Se uma implementação de linguagem procedural não souber como lidar com um determinado tipo de dados, e não for fornecida nenhuma transformação, a linguagem adotará o comportamento padrão para converter tipos de dados, mas isto depende da implementação.

WINDOW

O atributo WINDOW indica que a função é uma função de janela, em vez de uma função simples. No momento, só é útil para funções escritas em C. O atributo WINDOW não pode ser alterado ao substituir a definição de função existente.

IMMUTABLE
STABLE
VOLATILE

Estas cláusulas informam ao otimizador de consulta sobre o comportamento da função. Pode ser especificado no máximo uma dessas cláusulas. Se nenhum delas aparecer, é assumido VOLATILE por padrão.

A cláusula IMMUTABLE indica que a função não pode modificar o banco de dados, e sempre retorna o mesmo resultado quando recebe os mesmos valores de argumento; ou seja, não faz consultas ao banco de dados ou usa informações que não estão diretamente presentes em sua lista de argumentos. Se for especificada esta opção, qualquer chamada da função com todos os argumentos constantes pode ser imediatamente substituída pelo valor da função. [127]

A cláusula STABLE indica que a função não pode modificar o banco de dados, e que em uma varredura idêntica da tabela retorna consistentemente o mesmo resultado para os mesmos valores de argumento, mas que o resultado pode mudar conforme as instruções SQL. Esta cláusula é a escolha apropriada para funções cujos resultados dependem de consultas ao banco de dados, variáveis de parâmetro (como a zona horária corrente), etc. (Não é apropriada para gatilhos AFTER que desejam consultar linhas modificadas pelo comando corrente.) Note, também, que a família de funções current_timestamp se qualifica como estável, porque seus valores não mudam em uma transação.

A cláusula VOLATILE indica que o valor da função pode mudar mesmo em uma varredura idêntica da tabela, portanto, nenhuma otimização pode ser feita. Poucas funções de banco de dados são voláteis neste sentido; alguns exemplos são random(), currval(), e timeofday(). Mas note-se que qualquer função que tenha efeitos colaterais deve ser classificada como volátil, mesmo que seu resultado seja bastante previsível, para evitar que as chamadas sejam otimizadas; um exemplo é setval().

Para obter detalhes adicionais, veja a Categorias de volatilidade da função.

LEAKPROOF

A cláusula LEAKPROOF indica que a função não tem efeitos colaterais. A função não revela nenhuma informação sobre seus argumentos, além de seu valor retornado. Por exemplo, uma função que emite uma mensagem de erro para alguns valores de argumento, mas não para outros, ou que inclui os valores dos argumentos em mensagem de erro, não é à prova de vazamentos. Esta cláusula afeta como o sistema executa consultas em visões criadas com a opção security_barrier, ou tabelas com segurança no nível de linha (RLS) ativada. O sistema aplicará as condições de políticas de segurança e de visões com barreira de segurança antes de quaisquer condições fornecidas pelo usuário da própria consulta que contenham funções não à prova de vazamentos, a fim de evitar a exposição inadvertida de dados. As funções e os operadores marcados como à prova de vazamentos são considerados confiáveis, podendo ser executados antes das condições das políticas de segurança e das visões com barreira de segurança. Além disso, as funções que não aceitam argumentos, ou que não recebem nenhum argumento de visão ou tabela, não precisam ser marcadas como à prova de vazamentos para serem executadas antes das condições de segurança. Veja CREATE VIEW e a Regras e privilégios. Esta cláusula só pode ser definida por superusuário.

CALLED ON NULL INPUT
RETURNS NULL ON NULL INPUT
STRICT

A cláusula CALLED ON NULL INPUT (o padrão) indica que a função será chamada normalmente quando algum de seus argumentos for nulo. É então responsabilidade do autor da função verificar se há valores nulos, se necessário, e responder apropriadamente. [128]

A cláusula RETURNS NULL ON NULL INPUT ou STRICT indica que a função retorna nulo sempre que algum de seus argumentos for nulo. Se esta cláusula for especificada, a função não será executada quando houver argumentos nulos; em vez disso, o resultado nulo é assumido automaticamente.

[EXTERNAL] SECURITY INVOKER
[EXTERNAL] SECURITY DEFINER

A cláusula SECURITY INVOKER indica que a função deve ser executada com os privilégios do usuário que a chama. Este é o comportamento padrão. A cláusula SECURITY DEFINER especifica que a função deve ser executada com os privilégios do usuário que é o seu dono. Para obter informações sobre como escrever funções SECURITY DEFINER seguras, veja Escrita de funções SECURITY DEFINER seguras abaixo.

A palavra-chave EXTERNAL é permitida para manter a conformidade com o padrão SQL, mas é opcional, porque, ao contrário do padrão SQL, este recurso se aplica a todas as funções, e não apenas às externas.

PARALLEL

PARALLEL UNSAFE indica que a função não pode ser executada em modo paralelo; a presença de tal função em uma instrução SQL força um plano de execução serial. Este é o padrão. PARALLEL RESTRICTED indica que a função pode ser executada em modo paralelo, mas apenas no processo líder do grupo paralelo. PARALLEL SAFE indica que a função pode ser executada com segurança em modo paralelo sem restrições, inclusive em processos trabalhadores paralelos.

As funções devem ser rotuladas com sem segurança para paralelismo (PARALLEL UNSAFE) se modificarem qualquer estado do banco de dados, alterarem o estado da transação (exceto pelo uso de uma subtransação para recuperação de erros), acessarem sequências (por exemplo, chamando currval) ou fizerem alterações persistentes nas configurações. As funções deverão ser rotulados com paralelismo restrito (PARALLEL RESTRICTED) se acessarem tabelas temporárias, estado de conexão do cliente, cursores, instruções preparadas, ou diversos estados locais do processo servidor que o sistema não pode sincronizar no modo paralelo (por exemplo, setseed não pode ser executada senão pelo líder do grupo, porque uma alteração feita por outro processo não seria refletida no líder). Em geral, se uma função é rotulada como segura quando é restrita ou insegura, ou se é rotulada como restrita quando na verdade é insegura, ela pode emitir erros ou produzir respostas erradas quando usada em uma consulta paralela. As funções da linguagem C poderiam, em teoria, exibir um comportamento totalmente indefinido se rotuladas incorretamente, porque não há como o sistema se proteger contra o código C arbitrário, mas, geralmente, o resultado não é pior do que para qualquer outra função. Em caso de dúvida, as funções devem ser rotuladas como UNSAFE, que é o padrão. [129]

COST custo_de_execução

Um número positivo que dá o custo de execução estimado para a função em unidades de cpu_operator_cost. Se a função retornar conjunto, este será o custo por linha retornada. Se não for especificado o custo, assume-se 1 unidade para a linguagem C e funções internas, e 100 unidades para funções em todas as outras linguagens. Valores maiores fazem com que o planejador tente evitar avaliar a função com mais frequência do que o necessário.

ROWS linhas_de_resultado

Um número positivo que fornece o número estimado de linhas que o planejador deve esperar que a função retorne. Só é permitido quando a função é declarada retornando conjunto. A suposição padrão é de 1.000 linhas.

SUPPORT função_de_suporte

O nome (opcionalmente qualificado pelo esquema) da função de suporte do planejador a ser usada para esta função. Veja Informações sobre otimização de funções para obter detalhes. É necessário ser um superusuário para usar esta opção.

parâmetro_de_configuração
valor

A cláusula SET faz com que o parâmetro de configuração especificado seja definido com o valor especificado quando a função é chamada e, em seguida, restaurado para seu valor anterior quando a função é encerrada. A cláusula SET FROM CURRENT salva o valor corrente do parâmetro quando CREATE FUNCTION é executado como o valor a ser aplicado quando a função é chamada.

Se for anexada a cláusula SET a uma função, então os efeitos do comando SET LOCAL executado dentro da função para a mesma variável ficam restritos à função: o valor anterior do parâmetro de configuração ainda é restaurado na saída da função. No entanto, um comando SET comum (sem LOCAL) substitui a cláusula SET, tanto quanto faria para um comando SET LOCAL anterior: os efeitos desse comando persistirão após a saída da função, a menos que a transação corrente seja desfeita.

Veja SET e Configuração do servidor para obter mais informações sobre nomes e valores de parâmetros permitidos.

definição

Uma constante cadeia de caracteres que define a função; o significado depende da linguagem. Pode ser um nome de função interna, o caminho para um arquivo objeto, um comando SQL, ou texto em uma linguagem procedural.

Muitas vezes é útil usar a delimitação por cifrão (veja Constantes do tipo cadeia de caracteres delimitadas por cifrão) para escrever a cadeia de caracteres de definição da função, em vez da sintaxe normal de apóstrofos. Sem delimitação por cifrão, quaisquer apóstrofos ou contrabarras na definição da função devem ser duplicados.

arquivo_objeto, símbolo_de_ligação

Esta forma da cláusula AS é usada para funções na linguagem C carregáveis dinamicamente, quando o nome da função no código-fonte da linguagem C não é o mesmo que o nome da função SQL. A cadeia de caracteres arquivo_objeto é o nome do arquivo de biblioteca compartilhada que contém a função C compilada, sendo interpretado como para o comando LOAD. A cadeia de caracteres símbolo_de_ligação é o símbolo de ligação da função, ou seja, o nome da função no código-fonte da linguagem C. Se o símbolo de ligação for omitido, é assumido como sendo igual ao nome da função SQL que está sendo definida. Os nomes C de todas as funções devem ser diferentes, então é necessário dar nomes C diferentes às funções C sobrecarregadas (por exemplo, usando os tipos de dados dos argumentos como parte dos nomes C).

Quando o comando CREATE FUNCTION é chamado repetidas vezes para o mesmo arquivo objeto, o arquivo objeto é carregado apenas uma vez por sessão. Para descarregar e recarregar o arquivo (talvez durante o desenvolvimento), deve ser iniciada uma nova sessão.

corpo_sql

O corpo de uma função escrita em LANGUAGE SQL. Pode ser tanto uma única declaração

RETURN expressão

ou um bloco [130]

BEGIN ATOMIC
  instrução;
  instrução;
  ...
  instrução;
END

Esta forma é semelhante a escrever o texto do corpo da função como uma constante cadeia de caracteres (veja definição acima), mas existem algumas diferenças: esta forma funciona apenas para LANGUAGE SQL, enquanto a forma constante cadeia de caracteres funciona para todas as linguagens. Esta forma é analisada no tempo de definição da função, a forma constante cadeia de caracteres é analisada no tempo de execução; portanto, esta forma não pode dar suporte a argumentos com tipos de dados polimórficos, e outras construções que não podem ser resolvidas no momento de definição da função. Esta forma rastreia as dependências entre a função e os objetos usados no corpo da função, portanto, DROP ... CASCADE funcionará corretamente, enquanto a forma que usa literais cadeia de caracteres pode deixar funções pendentes. Finalmente, esta forma é mais compatível com o padrão SQL e outras implementações da linguagem SQL. [131]

Sobrecarga

O PostgreSQL permite sobrecarga de função; ou seja, o mesmo nome pode ser usado por várias funções diferentes, desde que tenham tipos de dados dos argumentos de entrada distintos. Independentemente de ser usado ou não, este recurso envolve precauções de segurança ao chamar funções em bancos de dados onde alguns usuários desconfiam de outros usuários; veja Funções.

Duas funções são consideradas a mesma se tiverem os mesmos nomes e tipos de dados dos argumentos IN, ignorando quaisquer parâmetros OUT. Assim, por exemplo, estas declarações entram em conflito:

CREATE FUNCTION foo(int) ...
CREATE FUNCTION foo(int, out text) ...

As funções que possuem listas de tipos de dados dos argumentos diferentes não são consideradas conflitantes no momento da criação, mas se forem fornecidos valores padrão, elas podem ser conflitantes. Por exemplo, considere

CREATE FUNCTION foo(int) ...
CREATE FUNCTION foo(int, int default 42) ...

Uma chamada para foo(10) irá falhar devido à ambiguidade sobre qual função deve ser chamada.

Notas

É permitida a sintaxe completa de tipo de dados SQL para declarar os argumentos de uma função e o valor retornado. Entretanto, os modificadores de tipo de dados entre parênteses (por exemplo, o campo de precisão para o tipo de dados numeric) são descartados por CREATE FUNCTION. Assim, por exemplo, CREATE FUNCTION foo (varchar(10)) ... é exatamente o mesmo que CREATE FUNCTION foo (varchar) ....

Ao substituir uma função existente executando CREATE OR REPLACE FUNCTION, há restrições quanto a alterar os nomes dos parâmetros. Não se pode alterar um nome já atribuído a qualquer parâmetro de entrada (embora se possa adicionar nomes a parâmetros que não tinham nome antes). Havendo mais de um parâmetro de saída, não será possível alterar os nomes dos parâmetros de saída, porque isto alteraria os nomes das colunas do tipo de dados composto anônimo que descreve o resultado da função. Estas restrições são feitas para garantir que as chamadas existentes à função não parem de funcionar quando estas forem substituídas.

Se uma função for declarada STRICT com um argumento VARIADIC, a verificação de conformidade testará se a matriz VARIADIC não é nula como um todo. A função ainda será chamada se a matriz tiver elementos nulos.

Exemplos

Adição de dois números inteiros usando uma função SQL:

CREATE FUNCTION add(integer, integer) RETURNS integer
    AS 'select $1 + $2;'
    LANGUAGE SQL
    IMMUTABLE
    RETURNS NULL ON NULL INPUT;

A mesma função escrita em um estilo mais compatível com o padrão SQL, usando nomes de argumentos e corpo sem apóstrofos:

CREATE FUNCTION add(a integer, b integer) RETURNS integer
    LANGUAGE SQL
    IMMUTABLE
    RETURNS NULL ON NULL INPUT
    RETURN a + b;

Incremento de um número inteiro, fazendo uso do nome do argumento, na linguagem PL/pgSQL:

CREATE OR REPLACE FUNCTION increment(i integer) RETURNS integer AS $$
    BEGIN
        RETURN i + 1;
    END;
$$ LANGUAGE plpgsql;

Retorno de um registro contendo vários parâmetros de saída:

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);

Pode ser feita a mesma coisa de forma mais detalhada usando tipo de dados composto com o nome dado explicitamente:

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);

Outra maneira de retornar várias colunas é com uma função retornando 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);

Entretanto, uma função retornando TABLE é diferente dos exemplos anteriores, porque na verdade retorna um conjunto de registros, e não apenas um registro.

Exemplo 79. Exemplo do tradutor

Cálculo do valor da tangente para um argumento em graus

Esta função usa as funções trigonométricas do PostgreSQL para calcular o valor da tangente para um ângulo fornecido em graus.

CREATE OR REPLACE FUNCTION public.tang(x double precision)
    RETURNS double precision AS
    $$
       BEGIN
          RETURN sin(radians(x))/cos(radians(x));
       END;
    $$ LANGUAGE plpgsql IMMUTABLE;
CREATE FUNCTION
COMMENT ON FUNCTION public.tang(double precision)
    IS 'Retorna o valor da tangente para o argumento em graus';
COMMENT
SELECT tang(0);

 tang
------
    0
(1 linha)

SELECT tang(45);

        tang
--------------------
 0.9999999999999999
(1 linha)

SELECT tang(90);

         tang
-----------------------
 1.633123935319537e+16
(1 linha)

\pset null "(nulo)"
A exibição de nulos é ""(nulo)"".
SELECT tang(NULL);

   tang
----------
 "(nulo)"
(1 linha)

Como se viu, os valores podem ser aproximados.


Exemplo 80. Exemplo do tradutor

Inversão dos caracteres de uma cadeia de caracteres

Esta função retorna a cadeia de caracteres recebida como argumento com os caracteres na ordem inversa, ou seja, de trás para a frente.

CREATE OR REPLACE FUNCTION public.reverso(txt text)
RETURNS text AS
$BODY$
DECLARE
    rev text := '';
    len integer := LENGTH(txt);
BEGIN
    WHILE len > 0 LOOP
        rev := rev || SUBSTRING(txt, len, 1);
        len := len - 1;
    END LOOP;
    RETURN rev;
END;
$BODY$
LANGUAGE plpgsql RETURNS NULL ON NULL INPUT;
CREATE FUNCTION
COMMENT ON FUNCTION public.reverso(txt text)
    IS 'Retorna o texto do argumento de trás para a frente';
COMMENT
SELECT reverso('O rato roeu a roupa do rei de Roma');

              reverso
------------------------------------
 amoR ed ier od apuor a ueor otar O
(1 linha)


Escrita de funções SECURITY DEFINER seguras

Como uma função SECURITY DEFINER é executada com os privilégios do usuário que é o seu dono, é necessário cuidado para garantir que a função não seja mal utilizada. Por segurança, search_path deve ser definido excluindo quaisquer esquemas que possam ser escritos por usuários não confiáveis. Isto evita que usuários mal-intencionados criem objetos (por exemplo, tabelas, funções e operadores) que mascaram os objetos destinados a serem usados pela função. É particularmente importante a este respeito o esquema de tabelas temporárias, pesquisado primeiro por padrão, e que normalmente pode ser escrito por qualquer pessoa. Pode ser obtido um arranjo seguro forçando o esquema temporário ser pesquisado por último. Para fazer isto, deve ser escrito pg_temp omo a última entrada em search_path. Esta função mostra o uso seguro:

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
    -- Definir um caminho de procura seguro:
    --   primeiro os esquemas confiáveis,
    --   por último 'pg_temp'.
    SET search_path = admin, pg_temp;

A intenção desta função é acessar a tabela admin.pwds. Mas sem a cláusula SET, ou com uma cláusula SET mencionando apenas admin, a função poderia ser subvertida criando uma tabela temporária chamada pwds.

Se a função definidora de segurança que pretende criar funções de banco de dados (roles) estiver sendo executada como um usuário sem privilégios de superusuário, o parâmetro createrole_self_grant também deve ser definido com um valor conhecido usando a cláusula SET.

Outro ponto a se ter em mente é que, por padrão, o privilégio de execução é concedido a PUBLIC para funções recém-criadas (veja Privilégios para obter mais informações). Frequentemente, deseja-se restringir o uso de uma função security definer a apenas alguns usuários. Para fazer isto, é necessário revogar os privilégios padrão para PUBLIC, e conceder o privilégio de execução seletivamente. Para evitar a existência de uma janela onde a nova função esteja acessível a todos, deve ser criada a função e definido os privilégios numa única transação. Por exemplo:

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;

Conformidade

O comando CREATE FUNCTION é definido no padrão SQL. A implementação do PostgreSQL pode ser usada de forma compatível, mas possui várias extensões. Por outro lado, o padrão SQL especifica vários recursos opcionais que não são implementados no PostgreSQL.

A seguir estão questões de compatibilidade importantes:

  • OR REPLACE é uma extensão do PostgreSQL.

  • Para compatibilidade com alguns outros sistemas de banco de dados, o modo_do_argumento pode ser escrito antes ou depois do nome_do_argumento, mas apenas a primeira maneira está em conformidade com o padrão.

  • Para valores padrão de parâmetro, o padrão SQL especifica apenas a sintaxe com a palavra-chave DEFAULT. A sintaxe com = é usada no T-SQL e no Firebird.

  • O modificador SETOF é uma extensão do PostgreSQL.

  • Somente é padronizada SQL como linguagem.

  • Todos os outros atributos, exceto CALLED ON NULL INPUT e RETURNS NULL ON NULL INPUT não são padronizados.

  • Para o corpo das funções em LANGUAGE SQL, o padrão SQL especifica apenas a forma corpo_sql.

Funções simples em LANGUAGE SQL podem ser escritas de uma forma que estejam em conformidade com o padrão e portável para outras implementações. Funções mais complexas usando recursos avançados, atributos de otimização ou outras linguagens serão necessariamente específicas do PostgreSQL de maneira significativa.

Veja também

ALTER FUNCTION, DROP FUNCTION, GRANT, LOAD, REVOKE


[125] OR REPLACE: Especifica a substituição da definição da função, caso uma exista no servidor corrente. A definição existente é efetivamente descartada antes que a nova definição seja substituída no catálogo, com a exceção de que os privilégios concedidos na função não são afetados. Esta opção pode ser especificada apenas pelo dono do objeto. Esta opção será ignorada se não existir uma definição para a função no servidor corrente. Para substituir uma função existente, o nome específico e o nome da função da nova definição devem ser iguais ao nome específico e ao nome da função da definição antiga, ou a assinatura da nova definição deverá corresponder à assinatura da definição antiga. Caso contrário, será criada uma nova função. IBM DB2 12.1.x CREATE FUNCTION (N. T.)

[126] RETURNS TABLE: Especifica que a saída da função é uma tabela. IBM DB2 12.1.x CREATE FUNCTION (N. T.)

[127] DETERMINISTIC ou NOT DETERMINISTIC: Esta cláusula opcional especifica se a função sempre retorna os mesmos resultados para determinados valores de argumento (DETERMINISTIC), ou se a função depende de alguns valores de estado que afetam os resultados (NOT DETERMINISTIC). Ou seja, uma função determinística deve retornar sempre a mesma tabela para chamadas sucessivas com entradas idênticas. Para evitar que as otimizações se aproveitem do fato de que entradas idênticas sempre produzem os mesmos resultados, deve ser especificado NOT DETERMINISTIC. IBM DB2 12.1.x CREATE FUNCTION (N. T.)

[128] CALLED ON NULL INPUT: Esta cláusula indica que a função é chamada independentemente de qualquer um de seus argumentos ser nulo. A função pode retornar um valor nulo ou um valor não nulo. A responsabilidade de testar valores de argumentos nulos é da função definida pelo usuário. IBM DB2 12.1.x CREATE FUNCTION (N. T.)

[129] ALLOW PARALLEL ou DISALLOW PARALLEL: Esta cláusula especifica se uma função definida pelo usuário pode ser paralelizada, ou seja, se uma única chamada da função definida pelo usuário pode fazer com que várias instâncias da função definida pelo usuário (geralmente uma instância por partição) sejam executadas em paralelo. IBM DB2 12.1.x CREATE FUNCTION (N. T.)

[130] ATOMIC: Se for especificado ATOMIC, apenas uma instância de um fluxo de mensagens (ou seja, uma thread) poderá executar as instruções de uma instrução específica BEGIN ATOMIC... END (identificada por seu esquema e rótulo), a qualquer momento. É útil quando uma série de alterações precisam ser feitas em uma variável compartilhada, sendo importante evitar que outras instâncias vejam os estados intermediários dos dados. IBM Integration Bus (N. T.)

[131] SQL-function-body: Especifica o corpo da função. Os nomes dos parâmetros podem ser referenciados no corpo da função SQL. Os nomes dos parâmetros podem ser qualificados com o nome da função para evitar referências ambíguas. IBM DB2 12.1.x CREATE FUNCTION (N. T.)