44.1. Funciones PL/Python #

Las funciones en PL/Python se declaran mediante la sintaxis estándar de CREATE FUNCTION:

CREATE FUNCTION funcname (argument-list)
  RETURNS return-type
AS $$
  # cuerpo de la función PL/Python
$$ LANGUAGE plpython3u;

El cuerpo de una función es simplemente un script de Python. Cuando se llama a la función, sus argumentos se pasan como elementos de la lista args; los argumentos con nombre también se pasan como variables ordinarias al script de Python. El uso de argumentos con nombre suele ser más legible. El resultado se devuelve desde el código de Python de la manera habitual, con return o yield (en caso de una sentencia que devuelva un conjunto de resultados). Si no proporcionas un valor de retorno, Python devuelve el valor por defecto None. PL/Python traduce el None de Python en el valor SQL null. En un procedimiento, el resultado del código de Python debe ser None (lo que normalmente se logra terminando el procedimiento sin una sentencia return o usando una sentencia return sin argumento); de lo contrario, se lanzará un error.

Por ejemplo, una función para devolver el mayor de dos enteros se puede definir como:

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

El código Python que se proporciona como cuerpo de la definición de la función se transforma en una función Python. Por ejemplo, lo anterior resulta en:

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

asumiendo que 23456 es el OID asignado a la función por PostgreSQL.

Los argumentos se definen como variables globales. Debido a las reglas de alcance (scoping) de Python, esto tiene la sutil consecuencia de que una variable de argumento no se puede volver a asignar dentro de la función al valor de una expresión que involucre el propio nombre de la variable, a menos que la variable se vuelva a declarar como global en el bloque. Por ejemplo, lo siguiente no funcionará:

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

porque la asignación a x hace que x sea una variable local para todo el bloque, por lo que la x del lado derecho de la asignación se refiere a una variable local x que aún no ha sido asignada, no al parámetro de la función PL/Python. Utilizando la sentencia global, esto se puede hacer que funcione:

CREATE FUNCTION pystrip(x text)
  RETURNS text
AS $$
  global x
  x = x.strip()  # ahora sí
  return x
$$ LANGUAGE plpython3u;

But it is advisable not to rely on this implementation detail of PL/Python. It is better to treat the function parameters as read-only.