2025 년 7 월 17 일 : | 토토 핫 18 베타 2 릴리스!
이 문서는 지원되지 않는 버전의 토토 핫 용입니다.
당신은에 대해 같은 페이지를 볼 수 있습니다PostgreSQL : 문서 : 17 : 36.10. 토토 핫 언어 사설 토토 사이트버전 또는 위에 나열된 다른 지원 버전 중 하나입니다.

31.9. 토토 핫 언어 기능

사용자 정의 함수는 C (또는 언어로 작성할 수 있습니다. C ++와 같은 C와 호환 될 수 있습니다). 그러한 기능은입니다 동적으로로드 가능한 객체 (공유라고도합니다 라이브러리) 및 주문형 서버에 의해로드됩니다. 역학 로딩 기능은 구별되는 것입니다"c 언어"함수"내부"함수 - 실제 코딩 컨벤션은 본질적으로 두 가지 모두 동일합니다. (따라서 표준 내부 기능 라이브러리는 풍부한 코딩 소스입니다. 사용자 정의 C 함수에 대한 예제.)

현재 두 가지 다른 전화 규칙이 c 기능. 최신"버전 1"전화 컨벤션은 A를 작성하여 표시됩니다.pg_function_info_v1 ()매크로 기능을 요청합니다. 아래 그림과 같이. 그러한 매크로의 부족은 구식을 나타냅니다 ("버전 0") 함수. 언어 지정된 이름함수 만들기isC두 경우 모두. 구식 기능 이식성 문제와 부족으로 인해 이제는 더 이상 사용되지 않습니다. 기능이지만 여전히 호환성을 위해 지원됩니다 이유.

31.9.1. 동적 로딩

처음으로 사용자 정의 기능이 처음입니다 로드 가능한 객체 파일은 세션에서 호출됩니다. 동적 로더 함수가 될 수 있도록 해당 객체 파일을 메모리에로드합니다. 라고 불리는. 그만큼함수 생성a 따라서 사용자 정의 C 함수는 두 가지 조각을 지정해야합니다 기능에 대한 정보 :로드 가능한 객체의 이름 파일 및 특정 함수의 C 이름 (링크 기호) 해당 객체 파일 내에서 호출하십시오. C 이름이 명시 적으로없는 경우 그런 다음 지정된 다음 SQL 기능과 동일하다고 가정합니다. 이름.

다음 알고리즘은 공유 객체를 찾는 데 사용됩니다. 에 주어진 이름을 기준으로 파일생성 기능명령 :

  1. If the name is an absolute path, the given file is 짐을 실은.

  2. 이름이 문자열로 시작하면$ libdir, 그 부분은로 대체됩니다.PostgreSQL패키지 라이브러리 빌드 타임에 결정된 디렉토리 이름

  3. 이름에 디렉토리 부분이없는 경우 파일 구성에 의해 지정된 경로에서 검색됩니다. 변하기 쉬운dynamic_library_path.

  4. 그렇지 않으면 (파일은 경로에서 발견되지 않았습니다. 비 변제 디렉토리 부분), 동적 로더가 포함되어 있습니다 주어진대로 이름을 가져 가려고 할 것입니다. 실패하다. (현재 작업에 의존하는 것은 신뢰할 수 없습니다 예배 규칙서.)

이 순서가 작동하지 않으면 플랫폼 별 공유 라이브러리 파일 이름 확장 (종종.so)는 주어진 이름과 이것에 추가됩니다 시퀀스가 다시 시도됩니다. 그것이 실패하면 부하가 있습니다 실패하다.

사용자 IDPostgreSQL서버는 파일로의 경로를 가로 질러야합니다. 당신은로드하려고합니다. 파일 또는 더 높은 수준의 디렉토리 제작 읽을 수 없거나/또는 실행할 수 없음Postgres사용자는 일반적인 실수입니다.

어쨌든에 나와있는 파일 이름은함수 만들기명령은 문자 그대로 기록됩니다 시스템이 카탈로그가되므로 파일을 다시로드 해야하는 경우 동일한 절차가 적용됩니다.

참고 : PostgreSQLC 함수를 자동으로 컴파일하지 않습니다. 대상 파일은 a에 참조되기 전에 컴파일해야합니다.기능 만들기명령. 보다섹션 31.9.6추가 정보.

처음으로 사용 된 후 동적으로로드 객체 파일은 메모리에 유지됩니다. 같은 미래의 전화 해당 파일의 함수에 대한 세션은 심볼 테이블 조회의 작은 오버 헤드. 강제 a 객체 파일의 새로 고침, 예를 들어 다시 컴파일 한 후 그만큼로드신선한 명령 또는 시작 세션.

공유 라이브러리를 상대적으로 찾는 것이 좋습니다 에게$ libdir또는 동적을 통한 도서관 경로. 이것은 새로운 경우 버전 업그레이드를 단순화합니다 설치는 다른 위치에 있습니다. 실제 디렉토리 저것$ libdirstand는 찾을 수 있습니다 명령과 함께PG_CONFIG --pkglibdir.

PostgreSQL릴리스 7.2, 객체 파일에 대한 정확한 절대 경로 만 지정함수 만들기. 이것 접근 방식은 이제 기능을 만들기 때문에 더 이상 사용되지 않습니다 불필요하게 정의 할 수 없습니다. 그냥 지정하는 것이 가장 좋습니다 경로 나 확장 상태가없는 공유 라이브러리 이름을 검색 메커니즘 대신 정보를 제공합니다.

31.9.2. C- 언어의 기본 유형 기능

토토 핫language functions를 작성하는 방법을 알고 있으려면 알아야합니다. 어떻게PostgreSQL내부 기본 데이터 유형 및 전달 방법을 나타내고 기능에서. 내부,PostgreSQL기본 유형을 a로 간주합니다."기억의 블로브". 사용자 정의 유형을 차례로 정의하는 함수는 길을 정의합니다. 저것PostgreSQL작동 할 수 있습니다 그것. 즉,PostgreSQL의지 디스크에서 데이터를 저장하고 검색하고 사용하십시오. 입력, 프로세스 및 출력에 대한 사용자 정의 함수 데이터.

기본 유형은 세 가지 내부 형식 중 하나를 가질 수 있습니다.

  • 통과 별 가치, 고정 길이

  • 참조로 통과, 고정 길이

  • 참조별로 전달, 가변 길이

바이 값 유형은 길이가 1, 2 또는 4 바이트 일 수 있습니다 (또한 8 바이트, ifsizeof (Datum)는 8입니다 기계). 당신은 당신의 유형을 정의하는 데주의해야합니다. 모든 아키텍처에서 크기 (바이트)가됩니다. 을 위한 예,Long유형은 위험합니다 일부 기계에서는 4 바이트이고 다른 기계의 8 바이트이기 때문에 반면int타입은 대부분의 유닉스에서 4 바이트입니다 기계. 의 합리적인 구현int4유닉스 머신의 타입 :

/ * 4-byte 정수, 가치에 의해 통과 */
typedef int int4;

반면에 모든 크기의 고정 길이 유형이 회의 별 통과. 예를 들어 샘플이 있습니다 A 구현PostgreSQL유형 :

/ * 16 바이트 구조, 참조로 통과 */
typedef struct

    더블 X, y;
 가리키다;

전달할 때 그러한 유형에 대한 포인터 만 사용할 수 있습니다. 그리고PostgreSQL함수. 그러한 유형의 값을 반환하려면 권리를 할당하십시오. 를 가진 메모리의 양Palloc, 채우기 할당 된 메모리를하고 포인터를 반환합니다. (당신도 할 수도 있습니다 반환과 같은 유형의 입력 값을 반환합니다. 입력 값으로 포인터를 반환하여 직접 값.절대수정 그러나 추천 입력 값의 내용.)

마지막으로 모든 가변 길이 유형도 전달해야합니다 참조. 모든 가변 길이 유형은 길이로 시작해야합니다 정확히 4 바이트의 필드 및 그 안에 저장 될 모든 데이터 유형은 그 다음에 메모리에 위치해야합니다. 길이 필드. 길이 필드에는 총 길이가 포함됩니다 구조, 즉 길이 필드의 크기가 포함됩니다. 그 자체.

예를 들어, 유형을 정의 할 수 있습니다텍스트다음과 같이 :

typedef struct 
    int4 길이;
    숯 데이터 [1];
 텍스트;

분명히 여기에 선언 된 데이터 필드는 충분히 길지 않습니다. 가능한 모든 줄을 잡고 있습니다. 선언하는 것은 불가능하기 때문에 의 가변 크기 구조C, 우리는에 대한 지식에 의존합니다.C토토 핫는 범위 점검되지 않습니다 배열 구역. 우리는 필요한 금액을 할당합니다 공간에 배열이 선언 된 것처럼 배열에 액세스하십시오. 올바른 길이. (이것은 당신이 읽을 수있는 일반적인 트릭입니다. C.)에 관한 많은 교과서에서

가변 길이 유형을 조작 할 때 조심해야합니다 올바른 양의 메모리를 할당하고 길이를 설정하려면 필드가 올바르게. 예를 들어, 우리가 40 바이트를 저장하고 싶다면 에이텍스트구조, 우리는 a를 사용할 수 있습니다 다음과 같은 코드 조각 :

#include "postgres.h"
...
숯 버퍼 [40]; / * 소스 데이터 */
...
텍스트 *대상 = (텍스트 *) palloc (varhdrsz + 40);
대상- 길이 = varhdrsz + 40;
memcpy (대상- 데이터, 버퍼, 40);
...

varhdrsz|sizeof (int4)이지만 좋은 스타일로 간주됩니다 매크로 사용varhdrsz가변 길이 유형에 대한 오버 헤드 크기.

표 31-1어떤 c 유형이 어떤 SQL 유형에 해당하는지 지정합니다. 내장 유형의 유형을 사용하는 c-language 함수 작성토토 핫. 그만큼"" 정의열은 헤더 파일을 제공합니다 유형 정의를 얻으려면 포함해야합니다. (실제 정의는 나열된 파일. 사용자가 정의 된 것을 고수하는 것이 좋습니다 인터페이스.) 항상 포함해야합니다postgres.h먼저 모든 소스 파일에서 어쨌든 필요한 많은 것들을 선언합니다.

표 31-1. 내장 SQL의 동등한 C 유형 유형

SQL 유형 C 유형 정의
Abstime AbsoluteTime utils/nabstime.h
부울 bool postgres.h(아마도 토토 핫 내장)
Box Box* utils/geo_decls.h
BYTEA BYTEA* postgres.h
"char" char (토토 핫 내장)
캐릭터 BPCHAR* postgres.h
CID CommandId postgres.h
날짜 dateadt utils/date.h
smallint(int2) int2또는int16 postgres.h
int2vector int2vector* postgres.h
Integer(int4) int4또는int32 postgres.h
Real(float4) float4* postgres.h
이중 정밀도(float8) float8* postgres.h
간격 간격* utils/timestamp.h
LSEG lseg* utils/geo_decls.h
이름 이름 postgres.h
OID OID postgres.h
oidvector oidvector* postgres.h
PATH Path* utils/geo_decls.h
포인트 포인트* utils/geo_decls.h
Regproc Regproc postgres.h
Reltime RelativeTime utils/nabstime.h
텍스트 텍스트* postgres.h
TID ItemPointer Storage/itemptr.h
Time Timeadt utils/date.h
시간대가있는 시간 Timetzadt utils/date.h
타임 스탬프 타임 스탬프* utils/timestamp.h
TinterVal TimeInterval utils/nabstime.h
Varchar Varchar* postgres.h
xid TransactionId postgres.h

이제 우리는 가능한 모든 구조를 살펴 보았습니다. 기본 유형, 실제 기능의 몇 가지 예를 보여줄 수 있습니다.

31.9.3. C-Language Functions의 Conventions 버전 0 호출

우리는 발표"구식"컨벤션을 먼저 호출 -이 접근법은 지금 이루어졌지만 더 이상 사용되지 않으면 처음에 처리하는 것이 더 쉽습니다. 에서 버전 -0 메소드, C 함수의 인수 및 결과 정상적인 C 스타일로 방금 선언되지만 사용에주의를 기울입니다. 위와 같이 각 SQL 데이터 유형의 C 표현.

여기 몇 가지 예가 있습니다.

#include "postgres.h"
#include <string.h

/ * 가치 별 */

int
add_one (int arg)

    반환 Arg + 1;

/ * 참조로 고정 길이 */

float8 *
add_one_float8 (float8 *arg)

    float8 *result = (float8 *) palloc (sizeof (float8));

    *결과 = *arg + 1.0;

    반환 결과;

가리키다 *
MakePoint (point *pointx, point *pointy)

    지점 *new_point = (point *) palloc (sizeof (point));

    new_point- x = pointx- x;
    new_point- y = pointy- y;

    New_Point를 반환합니다.

/ * 참조적으로 가변 길이 */

텍스트 *
카피 텍스트 (텍스트 *t)

    /*
     * varsize는 바이트의 구조물의 총 크기입니다.
     */
    텍스트 *new_t = (텍스트 *) palloc (varsize (t));
    varatt_sizep (new_t) = varsize (t);
    /*
     * Vardata는 구조물의 데이터 영역에 대한 포인터입니다.
     */
    memcpy ((void *) vardata (new_t), / *대상 * /
           (void *) vardata (t), / *소스 * /
           varsize (t) -varhdrsz);    / * 얼마나 많은 바이트 */
    뉴 _t를 반환합니다.

텍스트 *
concat_text (text *arg1, text *arg2)

    int32 new_text_size = varsize (arg1) + varsize (arg2) - varhdrsz;
    텍스트 *new_text = (텍스트 *) palloc (new_text_size);

    varatt_sizep (new_text) = new_text_size;
    memcpy (vardata (new_text), vardata (arg1), varsize (arg1) -varhdrsz);
    memcpy (vardata (new_text) + (varsize (arg1) -varhdrsz),
           vardata (arg2), varsize (arg2) -varhdrsz);
    new_text를 반환합니다.

위의 코드가 파일에서 준비되었다고 가정funcs.c공유로 컴파일했습니다 객체, 우리는 함수를 정의 할 수 있습니다PostgreSQL다음과 같은 명령과 함께 :

함수 생성 add_one (정수) 정수를 반환합니다
     처럼 '디렉토리/funcs ','add_one '
     언어 C 엄격한;

- SQL 기능 이름 "add_one"의 과부하 참고
기능 Add_one (이중 정밀)을 작성하십시오. 이중 정밀도를 반환합니다
     처럼 '디렉토리/funcs ','add_one_float8 '
     언어 C 엄격한;

함수 makepoint (점, 점)를 반환합니다
     처럼 '디렉토리/funcs ','makepoint '
     언어 C 엄격한;

함수 CopyText (텍스트)를 작성합니다 텍스트를 반환합니다
     처럼 '디렉토리/funcs ','CoppyText '
     언어 C 엄격한;

CONCIT CONCAT_TEXT (텍스트, 텍스트) 텍스트를 반환합니다
     처럼 '디렉토리/funcs ','concat_text ',
     언어 C 엄격한;

여기,디렉토리공유 라이브러리 파일의 디렉토리 (예 :PostgreSQL튜토리얼 디렉토리, 여기에는이 섹션에 사용 된 예제에 대한 코드가 포함되어 있습니다). (더 나은 스타일은 그냥 사용하는 것입니다'funcs'inas조항, 추가 후디렉토리검색 경로로. 어느 쪽이든 사례, 우리는 공유에 대한 시스템 별 확장을 생략 할 수 있습니다. 도서관, 일반적으로.so또는.SL.)

함수를로 지정했음을 알 수 있습니다."엄격한", 시스템은해야한다는 것을 의미합니다 입력 값이 NULL 인 경우 자동으로 NULL 결과를 가정합니다. 이렇게함으로써, 우리는 기능 코드. 이것 없이는 널 값을 확인해야합니다 명시 적으로, 각각에 대한 널 포인터를 확인함으로써 통과 참조 주장. (패스 별 값 주장의 경우, 우리 확인 방법조차 없습니다!)

이 호출 규칙은 사용하기가 간단하지만 매우 휴대 성; 일부 아키텍처에는 문제가 있습니다 보다 작은 데이터 유형 전달int이 방법. 또한 간단한 방법은 없습니다 귀무 결과를 반환하거나 어떤 널 주장에 대처하기 위해 기능을 엄격하게 만드는 것 외에. 버전 -1 다음에 제시된 컨벤션은 이러한 반대 의견을 극복합니다.

31.9.4. C-Language Functions의 Conventions 버전 1 호출

버전 1 호출 컨벤션은 매크로에 의존합니다 통과 된 주장의 복잡성을 억제하고 결과. 버전 -1 기능의 C 선언은 다음과 같습니다 언제나

Datum funcname (pg_function_args)

또한 매크로 호출

pg_function_info_v1 (funcname);

동일한 소스 파일에 나타나야합니다. (전통적으로, 그것은입니다 함수 자체 직전에 작성되었습니다.)이 매크로 호출은 필요하지 않음내부-언어 기능, 이후PostgreSQL모든 내부 기능이 버전 -1을 사용한다고 가정합니다 협약. 그러나 동적으로로드되는 데 필요합니다 기능.

버전 -1 함수에서는 각 실제 인수가 가져옵니다 a 사용pg_getarg_xxx()매크로에 해당합니다 인수의 데이터 유형 및 결과는 a를 사용하여 반환됩니다.pg_return_xxx()반환 유형의 매크로.pg_getarg_xxx()그 주장으로 간주합니다 가져 오는 기능 인수 수, 여기서 계산 0에서 시작합니다.pg_return_xxx()인수로 간주합니다 반품 할 실제 가치.

여기서 우리는 Version-1에 코딩 된 위와 동일한 함수를 보여줍니다. 스타일:

#include "postgres.h"
#include <string.h
#include "fmgr.h"

/ * 가치 별 */

pg_function_info_v1 (add_one);

자료
add_one (pg_function_args)

    int32 arg = pg_getarg_int32 (0);

    pg_return_int32 (arg + 1);

/ * 참조로 고정 길이 */

pg_function_info_v1 (add_one_float8);

자료
add_one_float8 (pg_function_args)

    /* float8의 매크로는 통과 참조 특성을 숨 깁니다. */
    float8 arg = pg_getarg_float8 (0);

    pg_return_float8 (arg + 1.0);

pg_function_info_v1 (makepoint);

자료
makepoint (pg_function_args)

    /* 여기서, 포인트의 추론 특성은 숨겨져 있지 않습니다. */
    point *pointx = pg_getarg_point_p (0);
    point *pointy = pg_getarg_point_p (1);
    지점 *new_point = (point *) palloc (sizeof (point));

    new_point- x = pointx- x;
    new_point- y = pointy- y;

    pg_return_point_p (new_point);

/ * 참조적으로 가변 길이 */

pg_function_info_v1 (CopyText);

자료
CopyText (pg_function_args)

    텍스트 *t = pg_getarg_text_p (0);
    /*
     * varsize는 바이트의 구조물의 총 크기입니다.
     */
    텍스트 *new_t = (텍스트 *) palloc (varsize (t));
    varatt_sizep (new_t) = varsize (t);
    /*
     * Vardata는 구조물의 데이터 영역에 대한 포인터입니다.
     */
    memcpy ((void *) vardata (new_t), / *대상 * /
           (void *) vardata (t), / *소스 * /
           varsize (t) -varhdrsz);    / * 얼마나 많은 바이트 */
    pg_return_text_p (new_t);

pg_function_info_v1 (concat_text);

자료
concat_text (pg_function_args)

    텍스트 *arg1 = pg_getarg_text_p (0);
    텍스트 *arg2 = pg_getarg_text_p (1);
    int32 new_text_size = varsize (arg1) + varsize (arg2) - varhdrsz;
    텍스트 *new_text = (텍스트 *) palloc (new_text_size);

    varatt_sizep (new_text) = new_text_size;
    memcpy (vardata (new_text), vardata (arg1), varsize (arg1) -varhdrsz);
    memcpy (vardata (new_text) + (varsize (arg1) -varhdrsz),
           vardata (arg2), varsize (arg2) -varhdrsz);
    pg_return_text_p (new_text);

the기능 생성명령은입니다 버전 -0 등가와 동일합니다.

언뜻보기에 버전 1 코딩 규칙이 나타날 수 있습니다 무의미한 모호함이되기 위해. 그러나 그들은 제안합니다 매크로가 불필요하게 숨길 수 있기 때문에 개선 횟수 세부 사항. 예를 들어 코딩에서add_one_float8, 우리는 더 이상 알 필요가 없습니다 저것float8는 추천 유형입니다. 또 다른 예는GETARG가변 길이 유형의 매크로는보다 효율적입니다 페치"토스트"(압축 또는 외부) 값.

버전 -1 기능의 큰 개선이 더 좋습니다 널 입력 및 결과 처리. 매크로PG_ARGISNULL (n)함수를 테스트 할 수 있습니다 각 입력이 무효인지 여부. (물론, 이것을하는 것은 전용입니다 선언되지 않은 기능에 필요"엄격한".)와 마찬가지로pg_getarg_xxx()매크로, 입력 인수 0에서 시작합니다. 하나는 자제해야합니다 실행pg_getarg_xxx()하나가 확인할 때까지 논쟁은 무효가 아닙니다. 널 결과를 반환하려면 executepg_return_null (); 이것은 작동합니다 엄격한 기능과 기적 기능.

새로운 스타일 인터페이스에 제공된 다른 옵션은 2입니다 의 변형pg_getarg_xxx()매크로. 이 중 첫 번째,pg_getarg_xxx_copy (), 반품을 보장합니다 글을 쓰는 데 안전한 지정된 인수의 사본. (일반 매크로는 때때로 값에 대한 포인터를 반환합니다. 물리적으로 테이블에 저장되어 있어야합니다. 에게. 사용 사용pg_getarg_xxx_copy ()매크로는 a 쓰기 가능한 결과.) 두 번째 변형은로 구성됩니다.pg_getarg_xxx_slice ()매크로 three arguments. 첫 번째는 함수의 수입니다 인수 (위와 같이). The second and third are the offset and 반환 할 세그먼트의 길이. 오프셋이 계산됩니다 zero, and a negative length requests that the remainder of the 가치를 반환합니다. 이 매크로는보다 효율적인 액세스를 제공합니다 저장소가있는 경우 큰 값의 일부로 유형"외부". (스토리지 유형 열의 열은를 사용하여 지정할 수 있습니다.ALTER 테이블TableNameAlter ColumnColname스토리지 설정StorageType. StorageType중 하나입니다일반, 외부, 확장또는Main.)

마지막으로 버전 -1 기능 호출 규칙이이를 만듭니다 설정 결과를 반환 할 수 있습니다 (섹션 31.9.10) 및 트리거 함수 구현 (PostgreSQL : 문서 : 8.0 : 메이저 토토 사이트) 및 절차 적 통화 처리기 (45 장). 버전 1 코드도 더 많습니다 버전 -0보다 휴대용 제한을 깨뜨리지 않기 때문입니다 C 표준의 기능 호출 프로토콜 자세한 내용은 보다src/backend/utils/fmgr/readmein 소스 분포.

31.9.5. 쓰기 코드

보다 진보 된 주제로 돌아 가기 전에 에 대한 몇 가지 코딩 규칙에 대해 토론하십시오.PostgreSQLc-language functions. 그 동안 언어로 작성된 기능을로드 할 수 있습니다. C보다PostgreSQL,이 다른 이유는 일반적으로 (전혀 가능할 때) 어렵습니다. C ++, Fortran 또는 Pascal과 같은 언어는 종종 C와 동일한 통화 협약 인수와 반환 값이 같은 방식. 이러한 이유로, 우리는 당신의 c- 언어라고 가정 할 것입니다 기능은 실제로 C로 작성됩니다.

C 기능 작성 및 구축을위한 기본 규칙은 다음과 같습니다. 다음은 다음과 같습니다.

  • usePG_CONFIG -includedir-serverPostgreSQL서버 헤더 파일입니다 시스템에 설치 (또는 사용자가 실행 중). 이 옵션은PostgreSQL7.2. 을 위한PostgreSQL7.1 사용해야합니다 옵션-includedir. (PG_CONFIG0이 아닌 상태로 종료됩니다 알 수없는 옵션이 발생하는 경우.) 이전에 릴리스를 위해 7.1 당신은 추측해야 할 것이지만, 그 이후로 현재 전화 규칙이 소개되었을 가능성은 거의 없습니다 그 릴리스를 지원하고 싶다.

  • 메모리를 할당 할 때를 사용하십시오.PostgreSQL기능Pallocandpfree해당 C 라이브러리 대신 기능Mallocand무료. 에 의해 할당 된 메모리Palloc가 해제됩니다 각 트랜잭션이 끝날 때 자동으로 방지합니다 메모리 누출.

  • 항상 구조물의 바이트를 항상 0memset. 이것 없이는 그렇지 않습니다 해시 인덱스 또는 해시 조인을 지원하기가 어렵습니다. 데이터의 상당한 비트 만 선택해야합니다. 해시를 계산하는 구조. 모든 것을 초기화하더라도 구조의 필드, 정렬 패딩이있을 수 있습니다 쓰레기를 포함 할 수있는 (구조물의 구멍) 값.

  • 대부분의 내부PostgreSQL유형은postgres.h관리자 인터페이스 (pg_function_args등)fmgr.h이므로 AT를 포함시켜야합니다 최소한이 두 파일. 휴대 할 수있는 이유로 가장 좋습니다 포함하다postgres.h 첫 번째시스템 또는 사용자 헤더 파일. 포함postgres.h포함elog.handPalloc.h당신을 위해.

  • 객체 파일 내에 정의 된 기호 이름은 안됩니다 서로 충돌하거나에 정의 된 기호와 충돌PostgreSQL서버 실행 파일. 당신은 당신의 함수의 이름을 바꿔야합니다 이 효과에 오류 메시지가 표시되는 경우 변수

  • 코드를 컴파일하고 연결하여 동적으로로드PostgreSQL항상 특별해야합니다 깃발. 보다섹션 31.9.6특정 운영 체제.

31.9.6. 컴파일 동적으로로드 된 함수 연결

사용하기 전에PostgreSQL확장 기능이 작성되었습니다 C, 그들은 특별한 생산 방법으로 편집하고 연결되어야합니다. 서버에서 동적으로로드 할 수있는 파일. 장차 ~ 가 되는 정확한, A공유 도서관생성.

이 섹션에 포함 된 것 이상의 정보는 귀하에게 운영 체제의 문서를 읽어야합니다 특히 C 컴파일러의 수동 페이지,CC및 링크 편집기,ld. 또한PostgreSQL소스 코드에는 여러 가지가 포함되어 있습니다 의 작업 예제Contrib디렉토리. 이 예에 의존하면 의 가용성에 따라 모듈PostgreSQL소스 코드.

공유 생성 라이브러리는 일반적으로 실행 파일 연결과 유사합니다 소스 파일은 객체 파일로 컴파일 된 다음 객체 파일은 함께 연결됩니다. 객체 파일은 있어야합니다 생성위치 독립 코드(PIC),개념적으로 그들이 할 수 있음을 의미합니다 로드 될 때 메모리의 임의의 위치에 배치 실행 파일에 의해. (실행 파일을위한 객체 파일은 다음과 같습니다 일반적으로 그런 식으로 컴파일되지 않습니다.) 공유를 연결하라는 명령 라이브러리에는 링크와 구별되는 특수 플래그가 포함되어 있습니다 실행 파일 (적어도 이론적으로 - 일부 시스템에서 연습은 훨씬 더 못생적입니다).

다음 예에서는 소스 코드가 파일에서foo.c그리고 우리는 a 공유 도서관foo.so. 그만큼 중간 객체 파일은입니다.foo.o47659_47775

BSD/OS

생성 할 토토 핫 플래그PICis-fpic. 공유 라이브러리 생성 링커 플래그는입니다.-shared.

gcc -fpic -c foo.c
ld -shared -o foo.so foo.o

버전 4.0에서 적용 가능BSD/OS.

freebsd

생성 할 토토 핫 플래그PICis-fpic. 공유 라이브러리를 만들려면 토토 핫 플래그는입니다.-shared.

gcc -fpic -c foo.c
gcc -shared -o foo.so foo.o

버전 3.0에서 적용 가능freebsd.

HP-UX

생성 할 시스템 토토 핫의 토토 핫 플래그PICis+z. 사용시GCCit '-fpic. 공유 라이브러리의 링커 플래그 이다-B. 그래서

CC +Z -C foo.c

또는

gcc -fpic -c foo.c

and

ld -B -O Foo.sl foo.o

hp-ux확대.SL공유 대부분의 다른 시스템과 달리 라이브러리.

irix

PIC기본값입니다. 특수 토토 핫 옵션이 필요하지 않습니다. 링커 공유 라이브러리를 생산하는 옵션-shared.

CC -C foo.c
ld -shared -o foo.so foo.o
Linux

생성 할 토토 핫 플래그PICis-fpic. 어떤 상황에서는 일부 플랫폼에서-fpic-fpic작동하지 않습니다. GCC를 참조하십시오 자세한 내용은 설명서. 컴파일러 플래그를 작성합니다 공유 도서관은-shared. 에이 완전한 예는 다음과 같이 보입니다.

cc -fpic -c foo.c
cc -shared -o foo.so foo.o
MacOS X

여기 예입니다. 개발자 도구가 있다고 가정합니다 설치.

CC -C foo.c 
CC -BUNDLE -FLAT_NAMESPACE- 정의 된 억제 -o foo.so foo.o
netbsd

생성 할 토토 핫 플래그PICis-fpic. 을 위한ELF시스템, the 플래그를 가진 컴파일러-sharedIS 공유 라이브러리를 연결하는 데 사용됩니다. 더 오래된 비 엘프 시스템,ld -Bsharableis 사용된.

gcc -fpic -c foo.c
gcc -shared -o foo.so foo.o
OpenBSD

생성 할 토토 핫 플래그PICis-fpic. ld -Bsharable링크에 사용됩니다 공유 도서관.

gcc -fpic -c foo.c
ld -bsharable -o foo.so foo.o
Solaris

생성 할 토토 핫 플래그PICis-kpic썬 토토 핫와-fpicwithGCC. 공유 링크 라이브러리, 토토 핫 옵션은입니다.-g컴파일러 또는 대안-sharedwithGCC.

cc -kpic -c foo.c
cc -g -o foo.so foo.o

또는

gcc -fpic -c foo.c
gcc -g -o foo.so foo.o
TRU64 UNIX

PIC기본값입니다. 따라서 컴파일 명령은 일반적인 명령입니다.ld특수 옵션과 함께 사용됩니다 링크 :

CC -C foo.c
ld -shared -expect_unresolved '*'-o foo.so foo.o

동일한 절차가 GCC 대신 GCC와 함께 사용됩니다. 시스템 컴파일러; 특별한 옵션이 필요하지 않습니다.

unixware

생성 할 토토 핫 플래그PICis-K PICSCO 토토 핫와-fpicwithGCC. 공유 링크 라이브러리, 토토 핫 옵션은입니다.-gSCO 토토 핫와-sharedwithGCC.

CC -K PIC -C FOO.C
cc -g -o foo.so foo.o

또는

gcc -fpic -c foo.c
gcc -shared -o foo.so foo.o

팁 :이것이 당신에게 너무 복잡하다면, 당신 사용을 고려해야합니다GNU Libtool, 유니폼 뒤에 플랫폼 차이를 숨 깁니다 인터페이스.

결과 공유 라이브러리 파일을로드 할 수 있습니다PostgreSQL. 지정할 때 파일 이름함수 만들기명령, 공유 라이브러리 파일의 이름을 알려야합니다. 중간 객체 파일이 아닙니다. 시스템의 경우에 유의하십시오 표준 공유 라이브러리 확장 (일반적으로.so또는.SL) 할 수 있습니다 에서 생략함수 생성명령, 일반적으로 최선을 위해 생략해야합니다 이식성.

다시 참조섹션 31.9.1서버가 공유를 찾을 것으로 예상되는 위치에 대해 도서관 파일.

31.9.7. 확장 건물 하부 구조

배포에 대해 생각하고 있다면PostgreSQL확장 모듈, 설정 a 그들을위한 휴대용 빌드 시스템은 상당히 어려울 수 있습니다. 따라서PostgreSQL설치는 확장에 대한 빌드 인프라를 제공합니다. 라고 불리는PGXS이므로 간단합니다 확장 모듈은 이미 간단하게 구축 할 수 있습니다 설치된 서버. 이 인프라는 의도되지 않습니다 사용될 수있는 범용 빌드 시스템 프레임 워크가 되려면 모든 소프트웨어를 구축하여PostgreSQL; 그것은 단순히 공통을 자동화합니다 간단한 서버 확장 모듈에 대한 규칙을 작성하십시오. 자세한 내용 복잡한 패키지에는 자신의 빌드를 작성해야합니다 체계.

확장에 인프라를 사용하려면 작성해야합니다. 간단한 makefile. 그 makefile에서는 일부를 설정해야합니다 변수와 마지막으로 글로벌 포함PGXSmakefile. 다음은 다음과 같습니다 지명 된 확장 모듈 빌드isbn_issn공유 라이브러리, SQL로 구성됩니다 스크립트 및 문서 텍스트 파일 :

modules = isbn_issn
data_built = isbn_issn.sql
문서 = readme.isbn_issn

pgxs : = $ (shell pg_config --pgxs)
$ (pgxs) 포함

마지막 두 줄은 항상 동일해야합니다. 일찍 파일, 변수를 할당하거나 사용자 정의 추가만들기규칙.

다음 변수를 설정할 수 있습니다.

모듈

소스 파일에서 빌드 할 공유 개체 목록 같은 줄기로 (이 목록에 접미사를 포함하지 않음)

데이터

random files to into에 설치할접두사/share/contrib

data_built

random files to into에 설치할접두사/share/contrib먼저 건설해야

DOCS

아래에 설치할 무작위 파일prefix/doc/contrib

스크립트

스크립트 파일 (바이너리 아님)에 설치할접두사/bin

scripts_built

스크립트 파일 (바이너리 아님)에 설치할접두사/bin첫 번째 구축

회귀

회귀 테스트 사례 목록 (접미사없이)

또는이 두 가지 중 하나 :

프로그램

빌드 할 바이너리 프로그램 (객체를 목록에OBJS)

module_big

빌드 할 공유 객체 (rest 객체 파일OBJS)

다음도 설정할 수 있습니다 :

EXTRA_CLEAN

제거 할 추가 파일만들기 깨끗한

PG_CPPFLAGS

에 추가됩니다CPPFLAGS

PG_LIBS

에 추가됩니다프로그램링크 선

SHLIB_LINK

에 추가됩니다module_big링크 라인

이 makefile을로 넣으십시오.makefilein 확장을 보유하는 디렉토리. 그런 다음 할 수 있습니다make컴파일하고 나중에설치모듈을 설치하려면. 그만큼 Extension은 컴파일되어토토 핫해당 설치 첫 번째PG_CONFIG명령을 찾았습니다 당신의 길에서.

31.9.8. C-Language 함수의 복합 유형 인수

복합 유형은 C와 같은 고정 레이아웃이 없습니다. 구조. 복합 유형의 인스턴스는 null을 포함 할 수 있습니다 전지. 또한 AN의 일부인 복합 유형 상속 계층 구조는 다른 필드와 다른 필드를 가질 수 있습니다 동일한 상속 계층의 구성원. 그러므로,PostgreSQL함수를 제공합니다 C에서 복합 유형의 필드에 액세스하기위한 인터페이스

쿼리에 응답하기 위해 함수를 쓰고 싶다고 가정 해 봅시다

이름, c_overpaid (EMP, 1500)를 초과 지불로 선택하십시오
    emp에서
    여기서 name = 'bill'또는 name = 'sam';

Call Concentions 버전 0 사용c_overpaidas :

#include "postgres.h"
#include "executor/executor.h"/ * for getAttributeByName () */

부
c_overpaid (HeptupleHeader t, / * 현재 행의 행 * /
           int32 한도)

    bool isnull;
    INT32 급여;

    Salary = DatumgetInt32 (getAttributeByName (t, "Salary", & isnull));
    if (isnull)
        거짓을 반환합니다.
    반품 급여 한도;

버전 -1 코딩에서 위는 다음과 같습니다.

#include "postgres.h"
#include "executor/executor.h"/ * for getAttributeByName () */

pg_function_info_v1 (c_overpaid);

자료
c_overpaid (pg_function_args)

    heptupleHeader t = pg_getarg_heaptupleHeader (0);
    int32 한계 = pg_getarg_int32 (1);
    bool isnull;
    데이텀 급여;

    급여 = getAttributeByName (t, "Salary", & isnull);
    if (isnull)
        pg_return_bool (false);
    /* 또는 널 급여에 대해 pg_return_null ()을 선호 할 수 있습니다. */

    pg_return_bool (Datumgetint32 (Salary) 한도);

getAttributeByNamePostgreSQL시스템 기능 지정된 행에서 속성을 반환합니다. 세 가지가 있습니다 인수 : 유형의 주장HeappupleHeader이름, 이름으로 전달되었습니다 원하는 속성 및 반환 매개 변수의 속성이 null인지 여부.getAttributeByName반환Datum적절한 데이터로 변환 할 수있는 값 적절한 사용으로 입력Datumgetxxx()매크로. 귀무인이 깃발이 설정되어 있습니다. 시도하기 전에 항상 널 플래그를 확인하십시오 결과와 함께.

또한getAttributeBynum63290_63366

다음 명령이 함수를 선언합니다c_overpaidsql :

함수 만들기 C_OVERPAID (EMP, Integer)는 부울을 반환합니다
    처럼 '디렉토리/funcs ','c_overpaid '
    언어 C 엄격한;

우리가 사용한 통지엄격한우리는 입력 인수가 널.

31.9.9. C-language의 반환 행 (복합 유형) 기능

c- 언어에서 행 또는 복합 유형 값을 반환하려면 기능, 매크로를 제공하는 특수 API를 사용할 수 있으며 구성 복합재의 복잡성의 대부분을 숨기는 기능 데이터 유형. 이 API를 사용하려면 소스 파일에는 다음을 포함해야합니다.

#include "funcapi.h"

복합 데이터 값을 구축 할 수있는 두 가지 방법이 있습니다. (따라서 A"튜플") : 할 수 있습니다 Datum 값의 배열 또는 C의 배열에서 빌드하십시오. 입력 변환 기능으로 전달할 수있는 문자열 튜플의 열 데이터 유형. 두 경우 모두 먼저 필요합니다 a를 얻거나 구성하려면tupledesc튜플 구조에 대한 설명자. Datums와 함께 일할 때 당신은 통과합니다tupledesctoBlessTupledesc그리고 전화heap_formtuple각 행마다. 언제 C 문자열로 작업하면 통과합니다.tupledesctotupledescgetattinmetadata, 그리고 전화BuildTupleFromCstrings각각 열. 함수가 튜플 세트를 반환하는 경우 첫 번째 호출 중에 설정 단계를 모두 한 번 수행 할 수 있습니다. 기능.

설정을위한 여러 도우미 기능이 있습니다 초기의tupledesc. 원한다면 명명 된 복합 유형을 사용하면 정보를 가져올 수 있습니다. 시스템이 카탈로그합니다. 사용

tupledesc relationnamegetTupledesc (const char *relname)

atupledesc명명 된 관계, 또는

tupledesc typegetTupledesc (Oid typeoid, list *colaliases)

atupledesc기준 a OID를 입력하십시오. 이것은 A를 얻는 데 사용될 수 있습니다.tupledesc베이스 또는 복합 유형의 경우. 언제 반환되는 함수 작성레코드, 예상tupledesc방문객.

일단 당신이 atupledesc, 부르다

tupledesc blesstupledesc (tupledesc tupdesc)

Datums와 함께 일할 계획이라면

Attinmetadata *tupledescgetattinmetadata (tupledesc tupdesc)

C 문자열로 작업하려는 경우. 당신이 쓰는 경우 a 기능 반환 세트,이 결과를 저장할 수 있습니다. 의 함수FUNCCALLCONTEXT구조 - 사용tuple_desc또는Attinmeta필드

Datums에서 작업 할 때

heappuple heap_formtuple (tupledesc tupdesc, datum *값, char *nulls)

aHeappuple주어진 사용자 데이텀 형식의 데이터.

C 문자열로 작업 할 때 사용

Heaptuple buildtupleffflfflfffflflings (attinmetadata *attinmeta, char ** value)

aheappuple주어진 사용자 C 문자열 형태의 데이터.is C Strings의 배열, 리턴 행의 각 속성마다 하나씩. 각 C 문자열은 입력에 의해 예상되는 형식이어야합니다. 속성 데이터 유형의 함수. 널을 반환하기 위해 속성 중 하나에 대한 값, 해당 포인터 그만큼배열을 설정해야합니다NULL. 이 기능은 있어야합니다 당신이 돌아 오는 각 행에 대해 다시 호출.

일단 기능에서 돌아 오기 위해 튜플을 만들면 it A로 변환해야합니다.Datum. 사용

HeappupleGetDatum (Heptuple Tuple)

aHeappuplea 유효한 데이텀. 이것Datum반환 할 수 있습니다 단일 행 만 반환하려는 경우 직접 설정 퇴치에서 현재 반환 값으로 사용 기능.

다음 섹션에 예제가 나타납니다.

31.9.10. C-language에서 반환 세트 기능

지원을 제공하는 특별한 API도 있습니다. C-Language 함수의 반환 세트 (다중 행). 에이 설정 퇴행 기능은 버전 -1 호출을 따라야합니다 규칙. 또한 소스 파일은 포함해야합니다.funcapi.h, 위와 같이.

세트 리턴 기능 (SRF) 각 항목마다 한 번 호출됩니다 보고. 그만큼SRF필수 그러므로 그것이하고있는 일을 기억하기에 충분한 상태를 절약하고 각 통화에서 다음 항목을 반환하십시오. 구조FUNCCALLCONTEXT제어를 돕기 위해 제공됩니다 이 과정. 함수 내에서fcinfo- flinfo- fn_extraa 포인터에 대한FUNCCALLCONTEXT가로 질러 전화.

typedef struct

    /*
     * 우리가 전에 전화를 한 횟수
     * 
     * call_cntr은 srf_firstcall_init ()에 의해 당신을 위해 0으로 초기화됩니다.
     * srf_return_next ()가 호출 될 때마다 당신을 위해 증분합니다.
     */
    UINT32 CALL_CNTR;

    /*
     * 선택적 최대 통화 수
     *
     * max_calls는 편의를 위해서만 여기에 있으며 선택 사항입니다.
     * 설정하지 않으면 언제
     * 기능이 완료되었습니다.
     */
    UINT32 MAX_CALLS;

    /*
     * 결과 슬롯에 대한 선택적 포인터
     * 
     * 이것은 더 이상 사용되지 않으며 거꾸로 호환성을 위해서만 존재합니다.
     * 더 이상 사용되지 않은 tupledescgetSlot ()를 사용하는 사용자 정의 SRF.
     */
    tupletableslot *슬롯;

    /*
     * 기타 사용자 제공 컨텍스트 정보에 대한 선택적 포인터
     * 
     * user_fctx는 자신의 데이터에 대한 포인터로 사용하기위한 것입니다.
     * 기능의 호출 사이의 임의의 컨텍스트 정보.
     */
    void *user_fctx;

    /*
     * 구조물 포함 속성 유형 입력 메타 데이터에 대한 선택적 포인터
     * 
     * Attinmeta는 튜플을 반환 할 때 사용합니다 (즉, 복합 데이터 유형)
     * 기본 데이터 유형을 반환 할 때 사용되지 않습니다. 필요합니다
     * BuildTupleFromCstrings ()를 사용하여 반품을 작성하려는 경우
     * 튜플.
     */
    Attinmetadata *Attinmeta;

    /*
     * 여러 통화를 위해 살아야하는 구조에 사용되는 메모리 컨텍스트
     *
     * multi_call_memory_ctx는 SRF_FIRSTCALL_INIT ()에 의해 설정되어 사용됩니다.
     * 청소용 srf_return_done ()에 의해. 가장 적절한 메모리입니다
     * 여러 통화에서 재사용 할 메모리에 대한 컨텍스트
     * SRF.
     */
    MemoryContext multi_call_memory_ctx;

    /*
     * 튜플 설명을 포함하는 구조에 대한 선택적 포인터
     *
     * tuple_desc는 튜플을 반환 할 때 사용합니다 (즉, 복합 데이터 유형)
     * 그리고 당신이 튜플을 만들려고하는 경우에만 필요합니다.
     * buildTupleFromCStrings ()가 아닌 heap_formTuple ().  주목하십시오
     * 여기에 저장된 Tupledesc 포인터는 보통 통과해야합니다.
     * FlessTupledesc () 먼저.
     */
    tupledesc tuple_desc;

 funcCallContext;

anSRF몇 가지를 사용합니다 자동으로 조작하는 함수와 매크로FUNCCALLCONTEXT구조 (및 를 통해 찾을 것으로 예상fn_extra). 사용

SRF_IS_FIRSTCALL ()

첫 번째 기능이 호출되는지 확인하려면 또는 후속 시간. 첫 번째 통화 (전용)에서

srf_firstcall_init ()

초기화하려면FUNCCALLCONTEXT. 모든 기능 호출에서 첫 번째, 사용

srf_percall_setup ()

사용을 위해 올바르게 설정하려면FUNCCALLCONTEXT이전에 지우십시오 이전 패스에서 남은 반환 데이터.

함수가 반환 할 데이터가 있으면

srf_return_next (funcctx, result)

발신자에게 반환하려면. (결과유형이어야합니다Datum, 단일 위에서 설명한대로 준비한 값 또는 튜플.) 마지막으로, 언제 귀하의 기능은 데이터 반환 데이터를 완료했습니다. 사용

srf_return_done (funcctx)

정리하고 끝내려면SRF.

SRF는 일시적인 컨텍스트입니다 통화간에 지워집니다. 이것은 당신이 필요하지 않다는 것을 의미합니다 전화하려면pfree사용 할당Palloc; 그것은 할 것입니다 어쨌든 가십시오. 그러나 데이터를 할당하려면 전화를 가로 질러 살 수있는 구조, 당신은 그들을 어딘가에 두어야합니다. 또 다른. 에 의해 언급 된 메모리 컨텍스트multi_call_memory_ctx는 적합한 위치입니다 까지 생존 해야하는 모든 데이터의 경우SRF가 끝났습니다. 대부분의 경우 이것은 당신이로 전환해야한다는 것을 의미합니다.multi_call_memory_ctx일차 설정.

완전한 의사 코드 예제는 다음과 같습니다.

Datum
my_set_returning_function (pg_function_args)

    funccallcontext *funcctx;
    데이텀 결과;
    MemoryContext OldContext;필요에 따른 추가 선언if (srf_is_firstcall ())

        funcctx = srf_firstcall_init ();
        OldContext = MemoryContexTswitchto (funcctx- multi_call_memory_ctx);
        / * 일회성 설정 코드가 여기에 나타납니다 : */사용자 코드
        복합재를 반환하는 경우
            tupledesc 빌드 및 아마도 AttinMetadata
        endif 리턴 컴포지트
        사용자 코드MemoryContexTswitchto (OldContext);

    / * 매번 설정 코드가 나타납니다. */사용자 코드funcctx = srf_percall_setup ();사용자 코드/ * 이것은 우리가 끝났는지 테스트 할 수있는 한 가지 방법 일뿐입니다. */
    if (funcctx- call_cntr <funcctx- max_calls)

        / * 여기서 우리는 다른 항목을 반환하고 싶습니다 : */사용자 코드
        결과 기준 획득srf_return_next (funcctx, result);

    또 다른

        / * 여기서 우리는 반환 품목을 완료하고 청소하면됩니다 : */사용자 코드srf_return_done (funcctx);

간단한 완전한 예SRF복합 유형 모양을 반환합니다 좋다:

pg_function_info_v1 (testpassbyval);

자료
TestPassByVal (pg_function_args)

    funccallcontext *funcctx;
    int call_cntr;
    int max_calls;
    tupledesc tupdesc;
    Attinmetadata *Attinmeta;

     / * 기능의 첫 번째 호출에서만 수행 된 작업 */
     if (srf_is_firstcall ())

        MemoryContext OldContext;

        / * 크로스 콜 지속성을위한 함수 컨텍스트 생성 */
        funcctx = srf_firstcall_init ();

        / * 여러 기능 호출에 적합한 메모리 컨텍스트로 전환 */
        OldContext = MemoryContexTswitchto (funcctx- multi_call_memory_ctx);

        / * 반환 할 튜플의 총 수 */
        funcctx- max_calls = pg_getarg_uint32 (0);

        / * __testpassByval 튜플에 대한 튜플 설명 구축 */
        tupdesc = relationnamegetTupledesc ( "__ testpassbyval");

        /*
         * RAW에서 튜플을 생산하는 데 필요한 속성 메타 데이터 생성
         * C 문자열
         */
        Attinmeta = tupledescgetattinmetadata (tupdesc);
        funcctx- attinmeta = Attinmeta;

        MemoryContexTswitchto (OldContext);

    / * 함수의 모든 호출에서 수행 된 작업 */
    funcctx = srf_percall_setup ();

    call_cntr = funcctx- call_cntr;
    max_calls = funcctx- max_calls;
    Attinmeta = funcctx- attinmeta;

    if (call_cntr <max_calls) / * 보내기에 남은 것이 더있을 때 * /

        char ** 값;
        핵심 튜플;
        데이텀 결과;

        /*
         * 반환 된 튜플을 구축하기위한 값 배열 준비.
         * 이것은 C 줄 배열이어야합니다.
         * 나중에 유형 입력 함수에 의해 처리됩니다.
         */
        값 = (char **) palloc (3 *sizeof (char *));
        값 [0] = (char *) palloc (16 * sizeof (char));
        값 [1] = (char *) palloc (16 * sizeof (char));
        값 [2] = (char *) palloc (16 * sizeof (char));

        snprintf (값 [0], 16, "%d", 1 * pg_getarg_int32 (1));
        snprintf (값 [1], 16, "%d", 2 * pg_getarg_int32 (1));
        snprintf (값 [2], 16, "%d", 3 * pg_getarg_int32 (1));

        / * 튜플 구축 */
        튜플 = buildTupleFromCstrings (AttinMeta, 값);

        / * 튜플을 데이텀으로 만듭니다 */
        결과 = HeptupleGetDatum (튜플);

        / * 정리 (정말로 필요하지 않습니다) */
        pfree (값 [0]);
        pfree (값 [1]);
        pfree (값 [2]);
        pfree (값);

        srf_return_next (funcctx, 결과);

    else / * 더 이상 남지 않을 때하십시오 * /

        srf_return_done (funcctx);

이 기능을 선언하는 SQL 코드는 다음과 같습니다.

유형 생성 __testpassByval AS (F1 Integer, F2 Integer, F3 Integer);

기능 testpassbyval (정수, 정수)을 만들거나 교체하십시오
    처럼 'filename','TestPassbyval '
    언어 c 불변의 엄격한;

디렉토리Contrib/TableFuncin 소스 분포에는 더 많은 세트 리턴 링의 예가 포함되어 있습니다 기능.

31.9.11. 다형성 논증 및 반환 유형

c-language 함수는 수락 및 반환으로 선언 될 수 있습니다 다형성 유형AnylementAnyArray. 보다섹션 31.2.5다형성에 대한 자세한 설명 기능. 기능 인수 또는 반환 유형이 정의 된 경우 다형성 유형으로서 기능 저자는 알 수 없습니다 호출 할 데이터 유형을 전진 시키거나 반품. 에 제공된 두 가지 루틴이 있습니다.fmgr.h버전 -1 C 함수를 허용합니다 인수의 실제 데이터 유형과 유형을 발견하십시오. 돌아올 것으로 예상됩니다. 루틴은라고합니다.get_fn_expr_rettype (fmgrinfo *flinfo)andget_fn_expr_argtype (fmgrinfo *flinfo, int Argnum). 결과 또는 인수 유형 OID를 반환합니다.Invalidoid정보가 아닌 경우 사용 가능. 구조flinfoIS 일반적으로 액세스 됨fcinfo- flinfo. 매개 변수Argnumis Zero 기반입니다.

예를 들어, 우리가 수락 할 함수를 작성하고 싶다고 가정합니다. 모든 유형의 단일 요소 및 1 차원 배열을 반환합니다. 그 유형의 :

pg_function_info_v1 (make_array);
자료
make_array (pg_function_args)

    ArrayType *결과;
    OID Element_Type = get_fn_expr_argtype (fcinfo- flinfo, 0);
    데이텀 요소;
    int16 typlen;
    부리 타자 발;
    숯 타입자;
    int ndims;
    int dims [maxdim];
    int lbs [maxdim];

    if (! oidisvalid (element_type))
        elog (오류, "입력의 데이터 유형을 결정할 수 없음");

    / * 제공된 요소 가져 오기 */
    요소 = pg_getarg_datum (0);

    / * 우리는 하나의 차원이 있습니다 */
    ndims = 1;
    / * 및 하나의 요소 */
    희미한 [0] = 1;
    / * 그리고 하한은 1 */
    lbs [0] = 1;

    / * 요소 유형에 대한 필수 정보 받기 */
    get_typlenbyvalalign (element_type, & typlen, & typbyval, & typalign);

    / * 이제 배열을 빌드 */
    result = construct_md_array (& element, ndims, dims, lbs,
                                element_type, typlen, typbyval, typalign);

    pg_return_arraytype_p (결과);

다음 명령은 함수를 선언합니다make_arraysql :

함수 생성 make_array (Anylement)는 anyArray를 반환합니다
    처럼 '디렉토리/funcs ','make_array '
    언어 C 엄격한;

사용에 주목하십시오엄격한; 이것은 코드가 널에 대한 테스트를 귀찮게하지 않기 때문에 필수 입력.