Oracle sdo_geomery 자료를 PostgreSQL + PostGIS 기반으로 옮겨가기
이글은 이전 홈페이지에서 2012년 쓰다만 글입니다.
그래도 남겨 놓아야겠기에.
이젠 많이 바뀌어서 아래 글이 바르지 않을 수도 있습니다.
오라클 sdo_geometry 자료형에 대해서는
페이지를
sdo_geometry 자료형을 PostgreSQL 자료형으로 변환 하는 원문은
페이지를
PostGIS 관련 문서는
페이지들을 참조로 작성될 것입니다.
Oracle sdo_geometry 자료형 구조
PostgreSQL용 오라클 호환 sdo_geometry
먼저 위에서 언급한 대로 일단 똑같은 mdsys.sdo_geometry 자료형을 하나 만든다.
CREATE DOMAIN mdsys.sdo_elem_info_array AS numeric[]; CREATE DOMAIN mdsys.sdo_ordinate_array AS numeric[]; CREATE TYPE mdsys.sdo_point_type AS (x numeric, y numeric, z numeric); CREATE TYPE mdsys.sdo_geometry AS ( sdo_gtype numeric, sdo_srid numeric, sdo_point mdsys.sdo_point_type, sdo_elem_info mdsys.sdo_elem_info_array, sdo_ordinates mdsys.sdo_ordinate_array);
이 자료형은 PostgreSQL 표준 복합 자료형이 됨으로, 입출력 또한 그대로 하면 된다.
dblink를 이용한 자료 옮기기
먼저 오라클에서 sdo_geometry 자료를 PostgreSQL 입력 포멧으로 바꾸기 위해서, 위에서 언급한 사이트에서 제공한 패키지를 약간 수정해서 만든다.
CREATE OR REPLACE PACKAGE pg_user_geom_util AS
-- copyright (c) 2012, Nicander Ltd
-- url: http://www.tolon.co.uk/2012/09/geometry-objects-across-dblink/
-- modified by ioseph
-- Translates a geometry object into a string representation
-- for storage and transport. See also StringToGeom.
FUNCTION GeomToString(pGeom IN mdsys.sdo_geometry ) RETURN VARCHAR2 DETERMINISTIC;
END pg_user_geom_util;
CREATE OR REPLACE PACKAGE BODY ADMCHOI.pg_user_geom_util AS
-- copyright (c) 2012, Nicander Ltd
-- url: http://www.tolon.co.uk/2012/09/geometry-objects-across-dblink/
-- modified by ioseph
-- Gets the next token in a separated list. See StringToGeom for an example.
PROCEDURE get_token( iStart IN NUMBER,
sPattern in VARCHAR2,
sBuffer in VARCHAR2,
sResult OUT NOCOPY VARCHAR2,
iNextPos OUT NOCOPY NUMBER ) IS
nPos1 number;
nPos2 number;
BEGIN
nPos1 := Instr(sBuffer, sPattern, iStart);
IF nPos1 = 0 then
sResult := rtrim(ltrim(substr(sBuffer, iStart, LENGTH(sBuffer) - iStart)));
ELSE
sResult := Rtrim(Ltrim(Substr(sBuffer, iStart, nPos1 - iStart)));
iNextPos := nPos1 + 1;
END IF;
END;
--------------------------------------------------------------------------------
FUNCTION NumberToString(pNumber IN NUMBER) RETURN VARCHAR2 IS
BEGIN
IF (pNumber IS NULL) THEN
RETURN '';
ELSE
RETURN TO_CHAR(pNumber);
END IF;
EXCEPTION
WHEN OTHERS THEN
RETURN '';
END;
function emptytonull(pString in varchar2) return varchar2 is
begin
return case when pString = '' then 'null' else pString end;
end;
--------------------------------------------------------------------------------
FUNCTION StringToNumber(pString IN VARCHAR2) RETURN NUMBER IS
BEGIN
RETURN TO_NUMBER(pString);
EXCEPTION
WHEN OTHERS THEN
RETURN NULL;
END;
--------------------------------------------------------------------------------
-- String format is as follows:
--
-- ,,,,
--
-- Where:
-- :=
-- :=
-- := NULL | SDO_POINT_TYPE, OPTIONAL_NUMBER, OPTIONAL_NUMBER, OPTIONAL_NUMBER
-- := NULL | SDO_ELEM_INFO_ARRAY, NUMBER, {OPTIONAL_NUMBER, ...}
-- := NULL | SDO_ORDINATE_ARRAY, NUMBER, {OPTIONAL_NUMBER, ...}
--
-- := NULL | NUMBER
-- entries in curly braces are repeated from n times
FUNCTION GeomToString(pGeom IN mdsys.sdo_geometry ) RETURN VARCHAR2 DETERMINISTIC IS
vString VARCHAR(32767);
vCount NUMBER;
BEGIN
-- GTYPE
vString := NumberToString(pGeom.SDO_GTYPE);
-- SRID
vString := vString || ',' || NumberToString(pGeom.SDO_SRID);
-- POINT
IF (pGeom.SDO_POINT IS NULL) THEN
vString := vString || ',';
ELSE
vString := vString || ',"(' || NumberToString(pGeom.SDO_POINT.X) || ',' || NumberToString(pGeom.SDO_POINT.Y) || ',' || NumberToString(pGeom.SDO_POINT.Z) || ')"';
END IF;
-- ELEM_INFO
IF (pGeom.SDO_ELEM_INFO IS NULL) THEN
vString := vString || ',';
ELSE
vCount := pGeom.SDO_ELEM_INFO.COUNT;
vString := vString || ',"{';
FOR i IN 1..vCount LOOP
if i > 1 then
vString := vString || ',';
end if;
vString := vString || emptytonull(NumberToString(pGeom.SDO_ELEM_INFO(i)));
END LOOP;
vString := vString || '}"';
END IF;
-- ORDINATES
IF (pGeom.SDO_ORDINATES IS NULL) THEN
vString := vString || ',';
ELSE
vCount := pGeom.SDO_ORDINATES.COUNT;
vString := vString || ',"{';
FOR i IN 1..vCount LOOP
if i > 1 then
vString := vString || ',';
end if;
vString := vString || emptytonull(NumberToString(pGeom.SDO_ORDINATES(i)));
END LOOP;
vString := vString || '}"';
END IF;
RETURN '(' || vString || ')';
END;
END pg_user_geom_util; 이것을 가지고, 옮겨감.
문제는 어떻게 옮겨갈 것인가인데, PosgreSQL 쪽에서는 oracle_fdw 뿐인듯하다.