7.1.7. Retornando Conjuntos ou Tuplas
Podemos definir o tipo de retorno de uma função como sendo um conjunto de valores usando o construtor SETOF
ou TABLE
. Neste caso, ao invés de usar uma única instrução RETURN
, utilizamos as instruções RETURN NEXT
ou RETURN QUERY
.
A função generate_4pts
irá gerar um conjunto com quatro pontos sorteados de forma aleatória:
CREATE OR REPLACE FUNCTION generate_4pts()
RETURNS SETOF GEOMETRY
AS
$$
DECLARE
pt GEOMETRY;
BEGIN
pt := ST_SetSRID(ST_MakePoint(360.0 * random() - 180.0,
180.0 * random() - 90.0), 4326);
RETURN NEXT pt;
pt := ST_SetSRID(ST_MakePoint(360.0 * random() - 180.0,
180.0 * random() - 90.0), 4326);
RETURN NEXT pt;
pt := ST_SetSRID(ST_MakePoint(360.0 * random() - 180.0,
180.0 * random() - 90.0), 4326);
RETURN NEXT pt;
pt := ST_SetSRID(ST_MakePoint(360.0 * random() - 180.0,
180.0 * random() - 90.0), 4326);
RETURN NEXT pt;
RETURN;
END;
$$
LANGUAGE plpgsql;
Atente-se a um detalhe importante no código da função generate_4pts
: ela termina com uma instrução RETURN
.
Podemos invocar a função generate_4pts
da seguinte forma:
SELECT ST_AsText(pt) AS geom FROM generate_4pts() AS pt;
Saída:
geom
--------------------------------------------
POINT(163.76629723236 85.4808924626559)
POINT(-55.0152626819909 55.0285322405398)
POINT(-1.04462971910834 -35.6856297980994)
POINT(-123.348454702646 31.6837284341455)
(4 rows)
Outra possibilidade de retornar um conjunto de valores é através do comando RETURN QUERY
. A função nearest_pluviometros
ilustra como podemos utilizar este comando:
CREATE OR REPLACE FUNCTION nearest_pluviometros(location GEOMETRY,
distance NUMERIC)
RETURNS SETOF pluviometros
AS
$$
DECLARE
q TEXT;
BEGIN
q := 'SELECT * FROM pluviometros' ||
' WHERE ST_DWithin(location, $1, $2)';
RETURN QUERY EXECUTE q USING location, distance;
RETURN;
END;
$$
LANGUAGE plpgsql;
Invocando a função nearest_pluviometros
obtemos o resultado mostrado abaixo:
SELECT gid, ST_AsText(location)
FROM nearest_pluviometros(
ST_SetSRID(ST_MakePoint(-45, -23), 4326),
10.0);
Saída:
gid | st_astext
-----+--------------------------
1 | POINT(-45.8872 -23.1791)
2 | POINT(-43.6419 -20.393)
Outra possibilidade de escrita da função nearest_pluviometros
seria sem a utilização do comando EXECUTE
:
CREATE OR REPLACE FUNCTION nearest_pluviometros(location GEOMETRY,
distance NUMERIC)
RETURNS SETOF pluviometros
AS
$$
BEGIN
RETURN QUERY SELECT *
FROM pluviometros
WHERE ST_DWithin(pluviometros.location,
nearest_pluviometros.location,
distance);
IF NOT FOUND THEN
RAISE EXCEPTION 'Nenhum pluviometro nas proximidades: %', ST_AsText($1);
END IF;
RETURN;
END;
$$
LANGUAGE plpgsql;