7.4. Extensões
Esta seção apresenta um exemplo simples de como criar um novo tipo de dados para representação de coordenadas geográficas.
1. Criando um tipo denominado geo_point
:
CREATE TYPE geo_point AS
(
x REAL,
y REAL,
srid INTEGER
);
2. Criando uma tabela para armazenar a localização de escolas de primeiro e segundo grau:
CREATE TABLE escolas
(
gid SERIAL PRIMARY KEY,
nome VARCHAR(100),
localizacao GEO_POINT
);
3. Inserindo tuplas (linhas ou registros) na tabela escolas
:
INSERT INTO escolas (gid, nome, localizacao)
VALUES (1, 'Escola Estadual Arlindo Bittencourt', '(-47.88497, -22.02557, 4326)'::GEO_POINT),
(2, 'Colégio Arquidiocesano de Ouro Preto', '(-43.51592, -20.38144, 4326)'::GEO_POINT),
(3, 'Instituto São José', '(-45.90245, -23.20000, 4326)'::GEO_POINT);
4. Recuperando as tuplas da tabela escolas
:
SELECT * FROM escolas;
5. Criando uma função para computar a distância entre dois pontos no plano cartesiano:
CREATE OR REPLACE FUNCTION distance(first GEO_POINT, second GEO_POINT)
RETURNS REAL AS $$
DECLARE
dx REAL;
dy REAL;
BEGIN
dx = (first.x - second.x);
dy = (first.y - second.y);
RETURN sqrt(dx * dx + dy * dy);
END;
$$
LANGUAGE plpgsql;
6. Utilizando a função distance
para computar a distância entre dois pontos:
SELECT distance('(1, 1, 4326)'::GEO_POINT, '(2, 2, 4326)'::GEO_POINT);
7. Criando um operador para comparação entre dois pontos:
Criação da função de comparação:
CREATE OR REPLACE FUNCTION less_than(first GEO_POINT, second GEO_POINT)
RETURNS BOOL AS $$
BEGIN
IF(first.x < second.x) THEN
RETURN TRUE;
END IF;
IF(first.x > second.x) THEN
RETURN FALSE;
END IF;
IF(first.y < second.y) THEN
RETURN TRUE;
END IF;
RETURN FALSE;
END;
$$
LANGUAGE plpgsql;
A função acima poderia ser utilizada da seguinte forma:
SELECT less_than('(1, 2, 4326)'::GEO_POINT, '(10, 20, 4326)'::GEO_POINT);
SELECT less_than('(1, 2, 4326)'::GEO_POINT, '(-1, 2, 4326)'::GEO_POINT);
Criando o operador associado à função de comparação:
CREATE OPERATOR <
(
leftarg = GEO_POINT,
rightarg = GEO_POINT,
procedure = less_than,
commutator = >,
negator = >=
);
Utilizando a função
less_than
através do operador<
:
SELECT '(1, 2, 4326)'::GEO_POINT < '(10, 2, 4326)'::GEO_POINT;