37.13. 사용자 정의 유형

설명대로PostgreSQL : 문서 : 13 : 37.2. PostgreSQL 롤 토토 시스템, postgresql새로운 데이터 토토 꽁 머니을 지원하기 위해 확장 할 수 있습니다. 이 섹션에서는 새로운 기본 토토 꽁 머니을 정의하는 방법에 대해 설명합니다. 새로운 기본 토토 꽁 머니은 아래에 정의 된 데이터 토토 꽁 머니입니다.SQL언어. 새 기본 토토 꽁 머니을 만들면 저수준 언어로 토토 꽁 머니에서 작동하는 기능을 구현해야합니다. 일반적으로 C

이 섹션의 예는에서 찾을 수 있습니다.complex.sqlandcomplex.cinSRC/Tutorial소스 분포의 디렉토리. 참조readme예제 실행에 대한 지침을 위해 해당 디렉토리의 파일.

사용자 정의 토토 꽁 머니에는 항상 입력 및 출력 기능이 있어야합니다. 이러한 기능은 토토 꽁 머니이 문자열에 나타나는 방법 (사용자의 입력 및 사용자에 대한 출력)과 메모리에서 토토 꽁 머니을 구성하는 방법을 결정합니다. 입력 함수는 인수로 무효 문자 문자열을 취하고 토토 꽁 머니의 내부 (메모리) 표현을 반환합니다. 출력 함수는 토토 꽁 머니의 내부 표현을 인수로 가져 와서 무효 문자 문자열을 반환합니다. 토토 꽁 머니을 저장하는 것보다 토토 꽁 머니으로 더 많은 일을하고 싶다면 토토 꽁 머니에 대해 원하는 작업을 구현하기 위해 추가 기능을 제공해야합니다.

우리가 토토 꽁 머니을 정의하고 싶다고 가정복잡한12408_12533

typedef struct complex 
    더블 X;
    이중 Y;
 복잡한;

우리는 이것을 단일에 맞지 않기 때문에 너무 크기 때문에이를 통과 할 수있는 토토 꽁 머니으로 만들어야합니다Datumvalue.

토토 꽁 머니의 외부 문자열 표현으로서 우리는 양식 문자열을 선택합니다(x, y).

입력 및 출력 함수는 일반적으로 쓰기가 어렵지 않습니다. 특히 출력 기능. 그러나 토토 꽁 머니의 외부 문자열 표현을 정의 할 때는 결국 입력 기능으로 해당 표현에 대한 완전하고 강력한 파서를 작성해야합니다. 예를 들어:

pg_function_info_v1 (complex_in);

자료
complex_in (pg_function_args)

    char *str = pg_getarg_cstring (0);
    더블 X,
                와이;
    복잡한 *결과;

    if (sscanf (str, "( %lf, %lf)", & x, & y)! = 2)
        Ereport (오류,
                (errcode (errcode_invalid_text_representation),
                 errmsg ( "유형 %s : \" %s \ ""에 대한 유효하지 않은 입력 구문
                        "복잡한", str));

    결과 = (복합 *) palloc (sizeof (complex));
    결과- x = x;
    결과- y = y;
    pg_return_pointer (결과);

출력 함수는 간단히 다음과 같습니다.

pg_function_info_v1 (complex_out);

자료
complex_out (pg_function_args)

    complex *complex = (복합체 *) pg_getarg_pointer (0);
    char *결과;

    결과 = psprintf ( "(%g,%g)", complex- x, complex- y);
    pg_return_cstring (결과);

입력 및 출력 함수를 서로 역전시키기 위해주의해야합니다. 그렇지 않은 경우 데이터를 파일에 버려야 할 때 심각한 문제가 발생하여 다시 읽습니다. 이것은 부동 소수점 번호가 관련 될 때 특히 일반적인 문제입니다..

선택적으로, 사용자 정의 토토 꽁 머니은 이진 입력 및 출력 루틴을 제공 할 수 있습니다. 바이너리 I/O는 일반적으로 더 빠르지 만 텍스트 I/O보다 휴대성이 떨어집니다. 텍스트 I/O와 마찬가지로 외부 바이너리 표현이 무엇인지 정확히 정의하는 것은 귀하에게 달려 있습니다. 내장 데이터 토토 꽁 머니의 대부분은 기계 독립적 이진 표현을 제공하려고합니다. 을 위한복잡한, 우리는 타입 용 바이너리 I/O 변환기에서 피기 백float8:

pg_function_info_v1 (complex_recv);

자료
complex_recv (pg_function_args)

    StringInfo buf = (stringInfo) pg_getarg_pointer (0);
    복잡한 *결과;

    결과 = (복합 *) palloc (sizeof (complex));
    결과- x = pq_getmsgfloat8 (buf);
    결과- y = pq_getmsgfloat8 (buf);
    pg_return_pointer (결과);

pg_function_info_v1 (complex_send);

자료
complex_send (pg_function_args)

    complex *complex = (복합체 *) pg_getarg_pointer (0);
    StringInfodata buf;

    pq_begintypsend (& buf);
    pq_sendfloat8 (& buf, complex- x);
    pq_sendfloat8 (& buf, complex- y);
    pg_return_bytea_p (pq_endtypsend (& buf));

I/O 함수를 작성하여 공유 라이브러리로 편집하면를 정의 할 수 있습니다.복잡한SQL 입력. 먼저 우리는 그것을 쉘 유형으로 선언합니다 :

토토 꽁 머니 생성 단지;

이것은 I/O 함수를 정의하면서 토토 꽁 머니을 참조 할 수있는 자리 표시 자 역할을합니다. 이제 우리는 I/O 함수를 정의 할 수 있습니다 :

함수 complex_in (cstring) 생성
    복잡한 반환
    처럼 'filename'
    언어 C 불변의 엄격;

함수 만들기 complex_out (complex)
    cstring을 반환합니다
    처럼 'filename'
    언어 C 불변의 엄격;

함수 만들기 complex_recv (내부)
   복잡한 반환
   처럼 'filename'
   언어 C 불변의 엄격;

함수 만들기 complex_send (complex)
   Bytea를 반환합니다
   처럼 'filename'
   언어 c 불변의 엄격한;

마지막으로 데이터 토토 꽁 머니의 전체 정의를 제공 할 수 있습니다.

유형 생성 단지 (
   내부 길이 = 16,
   입력 = complex_in,
   출력 = complex_out,
   수신 = complex_recv,
   send = complex_send,
   정렬 = 이중
);

새 기본 토토 꽁 머니을 정의 할 때PostgreSQL해당 토토 꽁 머니의 배열을 자동으로 제공합니다. 배열 토토 꽁 머니은 일반적으로 밑줄 문자가있는 기본 토토 꽁 머니과 동일한 이름을 갖습니다 (_) Prefended.

데이터 토토 꽁 머니이 존재하면 데이터 토토 꽁 머니에 유용한 작업을 제공하기 위해 추가 기능을 선언 할 수 있습니다. 그런 다음 연산자를 함수 꼭대기에 정의 할 수 있으며 필요한 경우 데이터 토토 꽁 머니의 인덱싱을 지원하기 위해 작업자 클래스를 작성할 수 있습니다. 이 추가 층은 다음 섹션에서 논의됩니다.

데이터 토토 꽁 머니의 내부 표현이 가변 길이 인 경우 내부 표현은 가변 길이 데이터의 표준 레이아웃을 따라야합니다. 처음 4 바이트는 A이어야합니다.char [4]직접 액세스하지 않은 필드 (관습 적으로 명명 된VL_LEN_). 사용해야합니다.set_varsize ()매크로이 필드에 기준 (길이 필드 자체 포함)의 총 크기를 저장하고varsize ()검색하려면. (이 매크로는 길이 필드가 플랫폼에 따라 인코딩 될 수 있기 때문에 존재합니다.)

자세한 내용은 설명을 참조하십시오.PostgreSQL :명령.

37.13.1. 토스트 고려 사항

데이터 토토 꽁 머니의 값이 크기가 크기가 다르면 (내부 형식) 일반적으로 데이터 토토 꽁 머니을 만드는 것이 바람직합니다토스트-abable (참조섹션 69.2). 값이 항상 너무 작아서 압축되거나 외부로 저장 되더라도이 작업을 수행해야합니다.토스트헤더 오버 헤드를 줄임으로써 작은 데이터의 공간을 절약 할 수 있습니다.

지원하기토스트스토리지, 데이터 토토 꽁 머니에서 작동하는 C 함수는 항상 사용하여 손에 든 구운 값을 풀려면 항상주의해야합니다PG_DETOAST_DATUM. (이 세부 사항은 관례 적으로 토토 꽁 머니 특정 정의로 숨겨져 있습니다getarg_datatype_pMacros.) 그런 다음를 실행할 때토토 꽁 머니 만들기명령, 내부 길이를 |변수이외의 적절한 스토리지 옵션을 선택하십시오일반.

데이터 정렬이 중요하지 않은 경우 (특정 함수 만 있거나 데이터 토토 꽁 머니이 바이트 정렬을 지정하기 때문에)의 일부를 피할 수 있습니다.pg_detoast_datum. 사용할 수 있습니다pg_detoast_datum_packed대신 (관습 적으로 agetarg_datatype_pp20116_20147varsize_any_exhdrandvardata_any잠재적으로 포장 된 데이텀에 액세스하려면. 다시, 데이터 토토 꽁 머니 정의가 정렬을 지정하더라도 이러한 매크로에 의해 반환 된 데이터는 정렬되지 않습니다. 정렬이 중요하다면 정규를 통과해야합니다​​PG_DETOAST_DATUM인터페이스.

Note

이전 코드가 자주 선언VL_LEN_ASint32대신 필드char [4]. 구조물 정의에 적어도 다른 필드가있는 한int32정렬. 그러나 잠재적으로 정렬되지 않은 데이텀으로 작업 할 때 그러한 구조물 정의를 사용하는 것은 위험합니다. 컴파일러는 데이텀이 실제로 정렬되었다고 가정하기위한 라이센스로 취할 수 있으며, 정렬에 대한 엄격한 아키텍처에 코어 덤프가 발생합니다.

|토스트지원은를 가질 가능성입니다.확장디스크에 저장된 형식보다 작업하기에 더 편리한 메모리 데이터 표현. 일반 또는flatvarlena 스토리지 형식은 궁극적으로 바이트 덩어리입니다. 예를 들어 포인터를 포함 할 수는 없습니다. 메모리의 다른 위치에 복사 될 수 있기 때문입니다. 복잡한 데이터 유형의 경우 평평한 형식은 작업하는 데 매우 비쌀 수 있으므로PostgreSQL확장플랫 형식은 계산에 더 적합한 표현으로, 데이터 토토 꽁 머니의 함수간에 해당 형식을 전달합니다..

확장 된 스토리지를 사용하려면 데이터 유형은에 주어진 규칙을 따르는 확장 된 형식을 정의해야합니다.src/include/utils/expededdatum.h, 그리고 함수 제공확장평면 바르라나 값은 확장 형식으로평평한확장 된 형식은 일반 Varlena 표현으로 되돌아갑니다. 그런 다음 데이터 유형의 모든 C 함수가 수신시 즉시 다른 표현을 수락 할 수 있는지 확인하십시오. 표준이기 때문에 데이터 유형에 대한 모든 기존 기능을 한 번에 수정할 필요는 없습니다.PG_DETOAST_DATUM매크로는 확장 입력을 일반 플랫 형식으로 변환하도록 정의됩니다. 따라서 Flat Varlena 형식에서 작동하는 기존 기능은 입력이 확장 된 상태에서 약간 비효율적으로 계속 작동합니다. 더 나은 성능이 중요하지 않으면 전환 할 필요가 없습니다.

c 확장 된 표현으로 작업하는 방법을 알고있는 기능은 일반적으로 두 가지 범주로 분류됩니다. 확장 된 형식 만 처리 할 수있는 것과 확장 또는 플랫 varlena 입력을 처리 할 수있는 것입니다. 전자는 쓰기가 더 쉽지만 단일 함수로 사용하기 위해 평평한 입력을 확장 된 양식으로 변환하는 것은 확장 된 형식으로 작동하는 것보다 비용이 많이들 수 있기 때문에 전반적으로 덜 효율적일 수 있습니다. 확장 된 형식 만 처리 해야하는 경우, 평면 입력을 확장 된 양식으로 변환하는 것은 인수를 가져 오는 매크로 내에 숨겨 질 수 있으므로 함수는 기존의 Varlena 입력으로 작업하는 것보다 더 복잡하지 않습니다. 두 유형의 입력을 처리하려면 외부, 짧은 헤더 및 압축 된 Varlena 입력을 해소하지만 확장되지 않은 입력을 해제하는 인수 가져 오기 기능을 작성하십시오. 이러한 함수는 Flat Varlena 형식의 Union에 대한 포인터를 반환하는 것으로 정의 될 수 있습니다. 발신자는를 사용할 수 있습니다.varatt_is_expanded_header ()매크로가받은 형식을 결정합니다.

the토스트인프라는 정기적 인 Varlena 값을 확장 값과 구별 할 수있을뿐만 아니라읽기 쓰기읽기 전용확장 된 값에 대한 포인터. c 확장 된 값 만 검사하기 만하면 또는 안전하고 내유 적으로 가시적으로 가시적 인 방식으로 만 변경하는 기능은 어떤 유형의 포인터를받을 필요가 없습니다. C 함수 입력 값의 수정 된 버전을 생성하는 기능은 읽기 쓰기 포인터를 수신하는 경우 확장 된 입력 값을 현장으로 수정할 수 있지만 읽기 전용 포인터를 수신하는 경우 입력을 수정해서는 안됩니다. 이 경우 값을 먼저 복사하여 수정할 새 값을 생성해야합니다. 새로운 확장 값을 구성한 C 함수는 항상 읽기 쓰기 포인터를 반환해야합니다. 또한, 읽기 쓰기 확장 값을 수정하는 C 함수는 현장에서 값을 정리하지 않으면 제정신 상태에 값을 남기도록주의를 기울여야합니다.

확장 된 값으로 작업하는 예는 표준 배열 인프라, 특히를 참조하십시오.src/backend/utils/adt/array_expanded.c.

정정 제출

문서에 올바르지 않은 내용이 있으면 일치하지 않습니다. 특정 기능에 대한 귀하의 경험 또는 추가 설명이 필요합니다. 사용이 양식문서 문제를보고하려면