44.1. Funções em PL/Python #

As funções escritas em PL/Python são definidas por meio da sintaxe de CREATE FUNCTION padrão:

CREATE FUNCTION nome_da_função (lista_de_argumentos)
  RETURNS tipo_retornado
AS $$
  # Corpo da função PL/Python
$$ LANGUAGE plpython3u;

O corpo da função é simplesmente um script Python. Quando a função é chamada, seus argumentos são passados ​​como elementos da lista args; os argumentos com nome também são passados ​​como variáveis ​​comuns para o script Python. O uso de argumentos com nome é geralmente mais legível. O resultado é retornado pelo código Python da maneira usual, por meio de return ou yield (no caso de uma instrução com conjunto de resultados). Se não for fornecido o valor de retorno, o Python retornará o valor padrão None. O PL/Python traduz o None do Python no valor nulo do SQL. Em um procedimento, o resultado do código Python deve ser None (normalmente obtido terminando o procedimento sem uma instrução return, ou usando uma instrução return sem argumento); caso contrário, será relatado um erro.

Por exemplo, uma função para retornar o maior valor entre dois números inteiros pode ser definida como:

CREATE FUNCTION pymax (a integer, b integer)
  RETURNS integer
AS $$
  if a > b:
    return a
  return b
$$ LANGUAGE plpython3u;

O código Python fornecido como o corpo da definição da função é transformado em uma função Python. Por exemplo, a função acima resulta em

def __plpython_procedure_pymax_23456():
  if a > b:
    return a
  return b

assumindo que 23456 é o OID atribuído à função pelo PostgreSQL.

Os argumentos são definidos como variáveis ​​globais. Devido às regras de escopo do Python, isto tem a consequência sutil de que uma variável de argumento não pode ser reatribuída dentro da função ao valor de uma expressão que envolve o próprio nome da variável, a menos que a variável seja redeclarada como global no bloco. Por exemplo, o seguinte código não funciona

CREATE FUNCTION pystrip(x text)
  RETURNS text
AS $$
  x = x.strip()  # errado
  return x
$$ LANGUAGE plpython3u;

porque atribuir um valor a x torna x uma variável local para todo o bloco, portanto, o x no lado direito da atribuição refere-se a variável local ainda não atribuída x, e não ao parâmetro da função PL/Python. Usando a instrução global, vai funcionar:

CREATE FUNCTION pystrip(x text)
  RETURNS text
AS $$
  global x
  x = x.strip()  # certo agora
  return x
$$ LANGUAGE plpython3u;

Mas é aconselhável não confiar neste detalhe de implementação do PL/Python. É melhor tratar os parâmetros da função como de leitura-apenas.