2017-11-02 14 views
-1

함수를 사용하여 Postgres 9.6에서 복합 유형으로 변환 할 때 이상한 동작이 발생합니다.Postgres Cast 복합 유형

내가 X, Y, Z 등의 복합 형 "벡터"선언

- 다음과 같이 배정 밀도의 각뿐만 아니라 캐스트 :

create or replace function vector_from_text(text, out result vector) strict immutable language plpgsql as $$ 
declare 
    d double precision[]; 
begin 
    result := null; 
    if ($1 is null) then 
     return; 
    end if; 

    begin 
     with c1 as (
       select $1::jsonb src 
     ) 
     select row((src->>'x')::double precision, (src->>'y')::double precision, (src->>'z')::double precision)::vector 
     **into result** -- see below 
     from c1; 
    exception 
     when others then 
      d := translate($1, '()', '{}')::double precision[]; 
      result := row(d[1], d[2], d[3])::vector; 
    end; 
end$$ 
; 
:

create type vector as(
x double precision, 
y double precision, 
z double precision 
); 

create cast (text as vector) 
with function vector_from_text(text) as implicit; 

기능 vector_from_text은 다음과 같습니다

이 함수는 null에서 null을 반환하거나 '{ "x": 0, "y": 0, "z": 0}'과 같은 json-string 또는 ' (0,0,0) '이다.

문제점 :

를 들어 JSON과 같은 입력 기능은 선택 문이 결과에 선 을 포함하는 즉시 오류를

invalid input syntax for type double precision: "(0,0,0)" 

를 반환합니다. 이 줄을 제거하거나 출력 변수를 으로 변경하면 함수가 예상대로 작동합니다.

벡터 벡터에 이미 입력 된 값을 벡터에 할당 할 수없는 이유는 무엇입니까? 그것을 얻지 마십시오!

답변

0

텍스트에서 캐스트를 생성 할 필요는 없습니다. 당신이 복합 형을 만들 때 당신은 어떤 추가 단계없이 유형에 텍스트를 캐스팅 할 수 있습니다

create type my_record as(
    x int, 
    y int, 
    z int 
); 

select '(1,2,3)'::my_record; 

my_record 
----------- 
(1,2,3) 
(1 row) 

당신이 jsonb을 사용 유형에 jsonb에서 캐스트를 만들려면 :

create or replace function my_record_from_jsonb(obj jsonb, out result my_record) 
strict immutable language plpgsql as $$ 
begin 
    select (obj->>'x')::int, (obj->>'y')::int, (obj->>'z')::int 
    into result; 
end 
$$; 

create cast (jsonb as my_record) 
    with function my_record_from_jsonb(jsonb); 

select '{"x":1, "y":2, "z":3}'::jsonb::my_record; 

my_record 
----------- 
(1,2,3) 
(1 row) 

마 텍스트 리터럴을 두 가지 다른 방식으로 해석하려고 시도하지 마십시오. jsonb 구문을 사용하려면 jsonb 유형을 사용하십시오. 사용자 정의 암시 적 캐스트을 텍스트로 작성하는 것은 특히 비합리적입니다. 읽기 in the documentation: :

암시 적으로 캐스팅을 표시하는 것이 보수적 인 것이 좋습니다. 암시 적 캐스팅 경로가 너무 많으면 PostgreSQL에서 여러 가지 가능한 해석이 있기 때문에 명령의 놀라운 해석을 선택하거나 명령을 전혀 해석하지 못할 수 있습니다. 경험상 좋은 법칙은 동일한 일반 유형 범주의 유형간에 정보를 보존하는 변형에 대해서만 암시 적으로 호출 할 수 있도록하는 것입니다. 예를 들어 int2에서 int4 로의 캐스트는 합리적 일 수 있지만 float8에서 int4 로의 캐스트는 할당 전용이어야합니다. 텍스트와 같은 int4에 대한 교차 유형 카테고리 캐스트는 명시 적으로 만 가장 적합합니다.