이 문서는 지원되지 않는 버전의 PostgreSQL을위한 것입니다.
당신은에 대해 같은 페이지를 보려고 할 수 있습니다PostgreSQL : 문서 : 17 : 36.10. C- 언어 사설 토토 사이트버전 또는 위에 나열된 다른 지원 버전 중 하나입니다.

38.10. C- 언어 기능

메이저 토토 사이트자 정의 함수는 C (또는 C ++와 같은 C와 호환 될 수있는 언어)로 작성할 수 있습니다. 이러한 기능은 동적으로로드 가능한 객체 (공유 라이브러리라고도 함)로 컴파일되며 주문시 서버에서로드됩니다. 동적 로딩 기능은 구별되는 것입니다C 언어기능내부함수 - 실제 코딩 규칙은 본질적으로 두 가지 모두 동일합니다. (따라서 표준 내부 기능 라이브러리는 사용자 정의 C 함수에 대한 코딩 예제의 풍부한 소스입니다.)

현재 하나의 호출 컨벤션 만 C 함수에 사용됩니다 (버전 1). 해당 전화 컨벤션에 대한 지원은 A를 작성하여 표시됩니다.pg_function_info_v1 ()매크로 아래 그림과 같이 함수를 호출합니다.

38.10.1. 동적 로딩

특정로드 가능한 객체 파일의 사용자 정의 함수가 세션에서 호출되면 동적 로더는 해당 객체 파일을 메모리로로드하여 기능을 호출 할 수 있습니다. 그만큼기능 만들기사용자 정의 C 함수의 경우 함수에 대한 두 가지 정보를 지정해야합니다.로드 가능한 객체 파일의 이름과 해당 객체 파일 내에서 호출 할 특정 함수의 C 이름 (링크 기호). C 이름이 명시 적으로 지정되지 않은 경우 SQL 기능 이름과 동일하다고 가정합니다.

다음 알고리즘은에 주어진 이름에 따라 공유 객체 파일을 찾는 데 메이저 토토 사이트됩니다.함수 생성명령 :

  1. 이름이 절대 경로 인 경우 주어진 파일이로드됩니다.

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

  3. 이름에 디렉토리 부분이 포함되어 있지 않으면 구성 변수로 지정된 경로에서 파일이 검색됩니다dynamic_library_path.

  4. 그렇지 않으면 (파일은 경로에서 발견되지 않았거나, 고분자가 아닌 디렉토리 부분이 포함되어 있지 않음) 동적 로더는 주어진 이름을 가져 오려고 시도 할 가능성이 높습니다. (현재 작업 디렉토리에 의존하는 것은 신뢰할 수 없습니다.)

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

공유 라이브러리를 찾는 것이 좋습니다$ libdir또는 동적 라이브러리 경로를 통한. 새 설치가 다른 위치에 있으면 버전 업그레이드를 단순화합니다. 실제 디렉토리$ libdirstand는 명령으로 찾을 수 있습니다pg_config --pkglibdir.

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

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

Note

PostgreSQLC 함수를 자동으로 컴파일하지 않습니다. 객체 파일은 a에 참조되기 전에 컴파일해야합니다.함수 만들기명령. 보다섹션 38.10.5추가 정보는

동적으로로드 된 객체 파일이 호환되지 않는 서버에로드되지 않도록하려면PostgreSQL파일에 A가 포함되어 있는지 확인합니다매직 블록적절한 내용이 있습니다. 이를 통해 서버는 다른 주요 버전의 코드와 같은 명백한 비 호환성을 감지 할 수 있습니다.PostgreSQL. 매직 블록을 포함하려면 헤더를 포함한 후 모듈 소스 파일 중 하나 (그리고 하나만)로 작성하십시오.fmgr.h:

PG_MODULE_MAGIC;

처음으로 메이저 토토 사이트 된 후 동적으로로드 된 객체 파일이 메모리에 유지됩니다. 동일한 세션에서 해당 파일의 함수에 대한 향후 통화는 심볼 테이블 조회의 작은 오버 헤드 만 발생합니다. 객체 파일을 다시로드 해야하는 경우, 예를 들어 객체 파일을 다시 컴파일 한 후 새로운 세션을 시작하십시오.

선택적으로 동적으로로드 된 파일에는 초기화 및 최종화 기능이 포함될 수 있습니다. 파일에 이름 함수가 포함 된 경우_pg_init, 해당 함수는 파일을로드 한 후 즉시 호출됩니다. 함수는 매개 변수를 수신하지 않으며 void를 반환해야합니다. 파일에 이름 함수가 포함 된 경우_PG_FINI, 해당 함수는 파일을 내리기 직전에 호출됩니다. 마찬가지로, 함수는 매개 변수를 수신하지 않으며 void를 반환해야합니다. 참고_pg_fini프로세스 종료 중에는 파일을 내릴 때만 호출됩니다. (현재, 언로드는 장애가없고 결코 발생하지 않을 것이지만, 이것은 미래에 변할 수 있습니다.)

38.10.2. C-Language 함수의 기본 유형

c-language functions를 작성하는 방법을 알아하려면 방법을 알아야합니다.PostgreSQL내부적으로 기본 데이터 유형과 함수와의 전달 방법을 나타냅니다. 내부,PostgreSQL기본 유형을 a로 간주합니다.메모리의 얼룩. 유형을 정의하는 메이저 토토 사이트자 정의 함수는 턴으로 정의합니다.PostgreSQL작동 할 수 있습니다. 즉,postgresql디스크에서 데이터를 저장하고 검색하고 사용자 정의 기능을 사용하여 데이터를 입력, 프로세스 및 출력합니다.

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

  • 통과 별 가치, 고정 길이

  • 참조 별 통과, 고정 길이

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

바이 값 유형은 길이가 1, 2 또는 4 바이트 일 수 있습니다 (또한 8 바이트, ifsizeof (Datum)는 컴퓨터에서 8입니다). 모든 아키텍처에서 동일한 크기 (바이트)가되도록 유형을 정의해야합니다. 예를 들어,Long유형은 일부 기계에서 4 바이트이고 다른 기계의 8 바이트이기 때문에 위험합니다.int유형은 대부분의 Unix 시스템에서 4 바이트입니다. 의 합리적인 구현int4유닉스 머신의 타입은 다음과 같습니다.

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

(실제 PostgreSQL C 코드는이 유형을 호출int32, C의 협약이기 때문에intxx평균xx 비트. 따라서 C 유형도 참고int8크기는 1 바이트입니다. SQL 유형int8int64in C 참조표 38.1.)

반면에, 모든 크기의 고정 길이 유형을 회의별로 전달할 수 있습니다. 예를 들어 다음은 A의 샘플 구현이 있습니다.PostgreSQL유형 :

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

    더블 X, y;
 가리키다;

그러한 유형에 대한 포인터만을 통과 할 때만 메이저 토토 사이트할 수 있습니다PostgreSQL기능. 그러한 유형의 값을 반환하려면에 적절한 양의 메모리를 할당하십시오.Palloc, 할당 된 메모리를 채우고 포인터를 반환하십시오. (또한 동일한 데이터 유형의 입력 인수 중 하나와 동일한 값을 반환하려면 추가를 건너 뛸 수 있습니다Palloc포인터를 입력 값으로 반환합니다.)

마지막으로 모든 가변 길이 유형도 참조로 전달해야합니다. 모든 가변 길이 유형은 정확히 4 바이트의 불투명 길이 필드로 시작해야하며, 이에 따라 설정됩니다.set_varsize; 이 필드를 직접 설정하지 마십시오! 해당 유형 내에 저장 될 모든 데이터는 해당 길이 필드 바로 뒤에 메모리에 위치해야합니다. 길이 필드에는 구조의 총 길이, 즉 길이 필드 자체의 크기가 포함됩니다.

또 다른 중요한 요점은 데이터 유형 값 내에 초기화되지 않은 비트를 남기지 않는 것입니다. 예를 들어, 스트러크에 존재할 수있는 정렬 패딩 바이트를 제로화하십시오. 이것이 없으면, 데이터 유형의 논리적으로 동등한 상수가 플래너에 의해 불평등 한 것으로 보일 수 있으며, 비효율적 인 (잘못된 것은 아니지만) 계획을 초래할 수 있습니다..

경고

절대Pass-by-Reference 입력 값의 내용을 수정하십시오. 그렇게한다면, 당신이 주어진 포인터가 디스크 버퍼를 직접 가리킬 수 있기 때문에, 당신은 온 디스크 데이터를 손상시킬 가능성이 높습니다. 이 규칙에 대한 유일한 예외는에 설명되어 있습니다.스포츠 토토 사이트 PostgreSQL : 문서 : 11 : 38.11. 사용자 정의 골재.

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

typedef struct 
    int32 길이;
    char 데이터 [flexible_array_member];
 텍스트;

the[Flexible_array_member]표기법은 데이터 부분의 실제 길이 가이 선언에 의해 지정되지 않았 음을 의미합니다.

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

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

varhdrsz|sizeof (int32), 그러나 매크로를 메이저 토토 사이트하는 것은 좋은 스타일로 간주됩니다varhdrsz가변 길이 유형에 대한 오버 헤드 크기를 참조합니다. 또한 길이 필드필수set_varsize간단한 과제가 아닌 매크로.

표 38.1많은 내장 SQL 데이터 유형에 해당하는 C 유형을 보여줍니다PostgreSQL. 그만큼정의열은 유형 정의를 얻기 위해 포함되어야하는 헤더 파일을 제공합니다. (실제 정의는 나열된 파일에 포함 된 다른 파일에있을 수 있습니다. 메이저 토토 사이트자는 정의 된 인터페이스를 고수하는 것이 좋습니다.) 항상 포함해야합니다.postgres.h서버 코드의 모든 소스 파일에서 먼저, 어쨌든 필요한 다수의 것들을 선언하고 다른 헤더를 먼저 포함시킬 수 있기 때문에.

표 38.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
float4 (Real) float4 postgres.h
float8 (이중 정밀) float8 postgres.h
int2 (smallint) int16 postgres.h
int4 (Integer) int32 postgres.h
int8 (bigint) int64 postgres.h
간격 간격* DataType/Timestamp.h
LSEG lseg* utils/geo_decls.h
이름 이름 postgres.h
숫자 숫자 utils/numeric.h
OID OID postgres.h
OIDVECTOR oidvector* postgres.h
PATH Path* utils/geo_decls.h
포인트 포인트* utils/geo_decls.h
Regproc Regrocedure postgres.h
Reltime RelativeTime utils/nabstime.h
텍스트 텍스트* postgres.h
TID ItemPointer Storage/itemptr.h
Time Timeadt utils/date.h
시간대가있는 시간 Timetzadt utils/date.h
타임 스탬프 타임 스탬프 DataType/Timestamp.h
시간대가있는 타임 스탬프 Timestamptz DataType/Timestamp.h
TinterVal TimeInterval utils/nabstime.h
Varchar Varchar* postgres.h
xid TransactionId postgres.h

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

38.10.3. 버전 1 전화 규칙

버전 -1 컨벤션은 거대에 의존하여 인수와 결과를 통과하는 복잡성의 대부분을 억제합니다. 버전 -1 기능의 C 선언은 항상 :

Datum funcname (pg_function_args)

또한 매크로 호출 :

pg_function_info_v1 (funcname);

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

버전 -1 함수에서 각 실제 인수는 a를 메이저 토토 사이트하여 가져옵니다pg_getarg_xxx()인수의 데이터 유형에 해당하는 매크로. (비 스트릭 함수에서는 인수 null-sness에 대한 이전 점검이 필요합니다PG_ARGISNULL (); 아래를 참조하십시오.) 결과는 a를 사용하여 반환됩니다.pg_return_xxx()반환 유형의 매크로.pg_getarg_xxx()카운트가 0에서 시작되는 기능 인수의 수를 인수로 간주합니다.pg_return_xxx()반품 할 실제 값을 인수로 간주합니다.

버전 -1 통화 규칙을 사용하는 몇 가지 예는 다음과 같습니다.

#include "postgres.h"
#include <string.h
#include "fmgr.h"
#include "utils/geo_decls.h"

PG_MODULE_MAGIC;

/ * 가치 별 */

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_pp (0);

    /*
     * varsize_any_exhdr은 구조물의 크기입니다.
     * 헤더의 varhdrsz 또는 varhdrsz_short.  a로 사본을 구성하십시오
     * 전장 헤더.
     */
    텍스트 *new_t = (텍스트 *) palloc (varsize_any_exhdr (t) + varhdrsz);
    set_varsize (new_t, varsize_any_exhdr (t) + varhdrsz);

    /*
     * Vardata는 새로운 구조물의 데이터 영역에 대한 포인터입니다.  출처
     * 짧은 기준 일 수 있으므로 Vardata_any를 통해 데이터를 검색하십시오.
     */
    memcpy ((void *) vardata (new_t), / *대상 * /
           (void *) vardata_any (t), / *소스 * /
           varsize_any_exhdr (t));   / * 얼마나 많은 바이트 */
    pg_return_text_p (new_t);

pg_function_info_v1 (concat_text);

자료
concat_text (pg_function_args)

    텍스트 *arg1 = pg_getarg_text_pp (0);
    텍스트 *arg2 = pg_getarg_text_pp (1);
    int32 arg1_size = varsize_any_exhdr (arg1);
    int32 arg2_size = varsize_any_exhdr (arg2);
    int32 new_text_size = arg1_size + arg2_size + varhdrsz;
    텍스트 *new_text = (텍스트 *) palloc (new_text_size);

    set_varsize (new_text, new_text_size);
    memcpy (vardata (new_text), vardata_any (arg1), arg1_size);
    memcpy (vardata (new_text) + arg1_size, vardata_any (arg2), arg2_size);
    pg_return_text_p (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 ','CopyText '
     언어 C 엄격한;

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

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

함수를로 지정했음을 알 수 있습니다.엄격한, 즉 입력 값이 null 인 경우 시스템이 자동으로 널 결과를 가정해야합니다. 이렇게하면 함수 코드에서 널 입력을 확인하지 않아도됩니다. 이것 없이는 메이저 토토 사이트 명시 적으로 널 값을 확인해야합니다.PG_ARGISNULL ().

매크로PG_ARGISNULL (n)함수가 각 입력이 null인지 테스트 할 수 있습니다. (물론이 작업을 수행하는 것은 선언되지 않은 기능에서만 필요합니다엄격한.)와 마찬가지로pg_getarg_xxx()매크로, 입력 인수는 0에서 시작됩니다. 실행을 자제해야합니다pg_getarg_xxx()인수가 무효가 아님을 확인할 때까지. 널 결과를 반환하려면 executepg_return_null (); 이것은 엄격한 기능과 nompollict 기능 모두에서 작동합니다.

언뜻보기에, 버전 -1 코딩 규칙은 평범한 메이저 토토 사이트에 비해 무의미한 모호한 것으로 보일 수 있습니다C전화 컨벤션. 그러나 그들은 우리가 처리 할 수있게합니다NULLABLE 인수/반환 값 및토스트(압축 또는 외부인) 값.

버전 -1 인터페이스에서 제공하는 기타 옵션은의 두 가지 변형입니다.pg_getarg_xxx()매크로. 이 중 첫 번째,pg_getarg_xxx_copy (), 글을 쓰는 데 안전한 지정된 인수의 사본을 반환하도록 보장합니다. (일반 매크로는 때때로 테이블에 물리적으로 저장된 값에 대한 포인터를 반환합니다.pg_getarg_xxx_copy ()매크로는 쓰기 가능한 결과를 보장합니다.) 두 번째 변형은로 구성됩니다.pg_getarg_xxx_slice ()세 가지 인수를하는 매크로. 첫 번째는 함수 인수의 수입니다 (위와 같이). 두 번째와 세 번째는 반환 할 세그먼트의 오프셋 및 길이입니다. 오프셋은 0에서 계산되며 음의 길이는 나머지 값을 반환하도록 요청합니다. 이 매크로는 스토리지 유형이있는 경우 큰 값의 일부에보다 효율적인 액세스를 제공합니다외부. (a 열의 저장 유형은를 메이저 토토 사이트하여 지정할 수 있습니다Alter TableTableNameAlter ColumnColname스토리지 설정StorageType. StorageType중 하나입니다일반, 외부, 확장또는Main.)

마지막으로, 버전 -1 기능 호출 규칙을 통해 설정 결과를 반환 할 수 있습니다 (섹션 38.10.8) 및 트리거 함수 구현 (토토 꽁 머니 : 문서 : 11 : 39 장. 트리거) 및 절차 적 통화 처리기 (PostgreSQL : 문서 : 11 : 56 장. 절차 적 언어 젠 토토 작성). 자세한 내용은 참조src/backend/utils/fmgr/readme소스 분포에서.

38.10.4. 쓰기 코드

보다 진보 된 주제로 돌아 가기 전에 몇 가지 코딩 규칙에 대해 논의해야합니다PostgreSQLc-language functions. c 이외의 언어로 작성된 함수를로드 할 수는 있지만PostgreSQL이러한 이유로, 우리는 귀하의 C- 언어 기능이 실제로 C로 작성되었다고 가정합니다.

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

  • usePG_CONFIG-includeDir-Server​​PostgreSQL서버 헤더 파일이 시스템에 설치되어 있습니다 (또는 사용자가 실행중인 시스템)..

  • 동적으로로드 할 수 있도록 코드를 컴파일하고 연결합니다PostgreSQL항상 특별한 플래그가 필요합니다. 보다섹션 38.10.5특정 운영 체제를 위해 수행하는 방법에 대한 자세한 설명.

  • a 정의하는 것을 잊지 마십시오.매직 블록공유 라이브러리의 경우섹션 38.10.1.

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

  • 항상 구조물의 바이트를 항상 0memset(또는와 함께 할당Palloc0처음에는). 구조물의 각 필드에 할당하더라도 쓰레기 값을 포함하는 정렬 패딩 (구조의 구멍)이있을 수 있습니다. 이 없으면 해시 인덱스 또는 해시 조인을 지원하기가 어렵습니다. 해시 계산을 위해 데이터 구조의 상당한 비트 만 선택해야하므로 해시 조인. 플래너는 때때로 비트 와이즈 평등을 통해 상수를 비교하는 데 의존하므로 논리적으로 동등한 값이 비슷하지 않으면 바람직하지 않은 계획 결과를 얻을 수 있습니다..

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

  • 객체 파일 내에 정의 된 기호 이름은 서로 충돌해서는 안됩니다.PostgreSQL서버 실행 가능. 이 효과에 오류 메시지를 받으면 함수 또는 변수의 이름을 바꿔야합니다.

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

메이저 토토 사이트하기 전에PostgreSQL확장 기능 C로 작성된 확장 기능은 서버에서 동적으로로드 할 수있는 파일을 생성하기 위해 특별한 방법으로 컴파일하고 연결되어야합니다. 정확히 말하면, a공유 도서관만들어야합니다.

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

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

다음 예에서는 소스 코드가 파일에 있다고 가정합니다foo.c공유 라이브러리를 만들 것입니다foo.so. 중간 객체 파일이 호출됩니다.foo.o51026_51134

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

그리고 다음 :

ld -b -o foo.sl foo.o

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

Linux

생성 할 컴파일러 플래그PICis-fpic. 공유 라이브러리를 만들기위한 컴파일러 플래그는입니다.-shared. 완전한 예는 다음과 같습니다.

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

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

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

생성 할 컴파일러 플래그PICis-fpic. 을 위한ELF시스템, 플래그가있는 컴파일러-shared공유 라이브러리를 연결하는 데 메이저 토토 사이트됩니다. 이전 비 ELF 시스템에서ld -Bsharable메이저 토토 사이트됩니다.

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-kpicSUN 컴파일러와-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

이것이 너무 복잡하다면 메이저 토토 사이트을 고려해야합니다gnu libtool, 균일 한 인터페이스 뒤에 플랫폼 차이를 숨 깁니다.

결과 공유 라이브러리 파일을로드 할 수 있습니다PostgreSQL. 파일 이름을 지정할 때기능 생성명령, 중간 객체 파일이 아닌 공유 라이브러리 파일의 이름을 지정해야합니다. 시스템의 표준 공유-라이브러리 확장 (일반적으로.so또는.SL)에서 생략 할 수 있습니다기능 생성명령, 일반적으로 최상의 휴대 성을 위해 생략해야합니다.

다시 참조섹션 38.10.1서버가 공유 라이브러리 파일을 찾을 예정인 위치에 대한 정보.

38.10.6. 복합 유형 인수

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

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

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

버전 1 호출 규칙을 사용하여 정의 할 수 있습니다c_overpaidas :

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

PG_MODULE_MAGIC;

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()매크로. 널 플래그가 설정된 경우 리턴 값은 의미가 없습니다. 결과로 무엇이든하려고하기 전에 항상 널 플래그를 확인하십시오.

또한GetAttributeBynum, 이름 대신 열 번호로 대상 속성을 선택합니다.

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

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

우리가 메이저 토토 사이트한 통지엄격한입력 인수가 무효인지 확인할 필요가 없었습니다.

38.10.7. 반환 행 (복합 유형)

c-language 함수에서 행 또는 복합 유형 값을 반환하려면 매크로와 함수를 제공하는 특수 API를 사용하여 복합 데이터 유형을 구축하는 대부분의 복잡성을 숨길 수 있습니다. 이 API를 사용하려면 소스 파일에는 다음을 포함해야합니다.

#include "funcapi.h"

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

필요한 것을 설정하기 위해 여러 도우미 기능을 사용할 수 있습니다tupledesc. 복합 값을 반환하는 대부분의 기능 에서이 작업을 수행하는 권장 방법은 다음과 같습니다.

saperfuncclass get_call_result_type (functioncallinfo fcinfo,
                                   oid *resulttypeid,
                                   tupledesc *resulttupledesc)

같은 통과fcinfo구조는 호출 함수 자체로 전달되었습니다. (물론 이것은 버전 -1 통화 컨벤션을 사용해야합니다.)resulttypeid|NULL또는 함수의 결과 유형을 수신하기위한 로컬 변수의 주소로서resultTupledesc지역의 주소 여야합니다tupledesc변수. 결과가인지 확인하십시오.saptionfunc_composite; 그렇다면,resultTupledesc필요한 것으로 채워졌습니다tupledesc. (그렇지 않은 경우의 선을 따라 오류를보고 할 수 있습니다.유형 레코드를 허용 할 수없는 상황에서 호출 된 기능 반환 레코드.)

get_call_result_type다형성 기능 결과의 실제 유형을 해결할 수 있습니다. 따라서 복합재를 반환하는 기능뿐만 아니라 스칼라 다형성 결과를 반환하는 기능에 유용합니다. 그만큼resulttypeid출력은 주로 다형성 스칼라를 반환하는 기능에 유용합니다.

note

get_call_result_type형제가 있습니다get_expr_result_type, 표현식 트리로 표시되는 함수 호출에 대한 예상 출력 유형을 해결하는 데 사용할 수 있습니다. 기능 자체 외부에서 결과 유형을 결정하려고 할 때 사용할 수 있습니다. 또한get_func_result_type, 기능의 OID 만 사용할 수있을 때 사용할 수 있습니다. 그러나 이러한 기능은 반환으로 선언 된 기능을 다룰 수 없습니다레코드get_func_result_type다형성 유형을 해결할 수 없으므로 우선적으로 메이저 토토 사이트해야합니다get_call_result_type.

획득하기위한 구식, 현재 홍보 함수tupledescs는 다음과 같습니다.

tupledesc relationnamegetTupledesc (const char *relname)

atupledesc지명 관계의 행 유형의 경우 :

tupledesc typegetTupledesc (Oid typeoid, list *colaliases)

atupledesc유형 OID를 기준으로합니다. 이것은 A를 얻는 데 사용될 수 있습니다.tupledesc베이스 또는 복합 유형의 경우. 반환하는 함수에 대해서는 작동하지 않습니다레코드그러나 다형성 유형을 해결할 수 없습니다.

일단 당신이 atupledesc, 전화 :

tupledesc blesstupledesc (tupledesc tupdesc)

Datums와 함께 일할 계획 인 경우 :

Attinmetadata *tupledescgetattinmetadata (tupledesc tupdesc)

C 스트링으로 작업하려는 경우. 기능 반환 세트를 작성하는 경우에서 이러한 기능의 결과를 저장할 수 있습니다.FUNCCALLCONTEXT구조 - 메이저 토토 사이트tuple_desc또는Attinmeta필드

Datums와 함께 작업 할 때 :

heappuple heap_form_tuple (tupledesc tupdesc, datum *값, bool *isnull)

aheappupleDatum 형식의 사용자 데이터가 주어졌습니다.

C 문자열로 작업 할 때 메이저 토토 사이트 :

Heatpuple buildtuplefromcstrings (Attinmetadata *Attinmeta, char ** value)

aHeappupleC 문자열 양식의 메이저 토토 사이트자 데이터가 주어졌습니다.는 반환 행의 각 속성마다 하나의 C 문자열 배열입니다. 각 C 문자열은 속성 데이터 유형의 입력 함수에 의해 예상되는 형식이어야합니다. 속성 중 하나에 대해 널 값을 반환하기 위해의 해당 포인터는입니다.배열을 설정해야합니다NULL. 이 기능은 반환하는 각 행마다 다시 호출해야합니다.

기능에서 돌아 오기 위해 튜플을 구축 한 후에는 A로 변환해야합니다Datum. 메이저 토토 사이트:

HeappupleGetDatum (Heptuple Tuple)

변환heappuple유효한 데이텀으로. 이것Datum단일 행 만 반환하려는 경우 직접 반환 할 수 있습니다.

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

38.10.8. 반환 세트

c-language functions에는 세트를 반환하기위한 두 가지 옵션 (다중 행)이 있습니다. 하나의 방법으로Valuepercall모드, 모드, 정리 함수는 반복적으로 호출되고 (매번 같은 인수를 전달) 각 호출에 하나의 새 행을 반환합니다. 정해진 함수 (SRF) 그러므로 전화를 걸어 충분한 상태를 저장 해야하는 일을 기억하고 각 통화에서 올바른 다음 항목을 반환해야합니다. 다른 방법에서는실체화모드, SRF는 전체 결과를 포함하는 Tuplestore 객체를 채우고 반환합니다. 그런 다음 전체 결과에 대해 하나의 호출 만 발생하며 전화 간 상태가 필요하지 않습니다.

ValuePercall 모드를 메이저 토토 사이트할 때 쿼리가 완성 된 것으로 보장되지 않는다는 것을 기억하는 것이 중요합니다. 즉,과 같은 옵션으로 인해Limit, 집행자는 모든 행을 가져 오기 전에 설정 함수에 대한 호출을 중단 할 수 있습니다. 이것은 마지막 통화에서 정리 활동을 수행하는 것이 안전하지 않다는 것을 의미합니다. 파일 설명자와 같은 외부 리소스에 대한 액세스가 필요한 함수에 대해서도 실체화 모드를 사용하는 것이 좋습니다.

이 섹션의 나머지 부분은 Valuepercall 모드를 사용하여 SRF에 일반적으로 사용되는 (사용되지 않아도)의 도우미 매크로 세트를 문서화합니다. 실체화 모드에 대한 추가 세부 사항은에서 찾을 수 있습니다.src/backend/utils/fmgr/readme. 또한,Contrib모듈의PostgreSQL소스 분포는 Valuepercall과 INSATERIZE MODE를 모두 사용하는 SRF의 많은 예를 포함합니다.

여기에 설명 된 ValuePercall 지원 매크로를 사용하려면 포함funcapi.h. 이 매크로는 구조와 함께 작동합니다FUNCCALLCONTEXT통화에 걸쳐 저장 해야하는 상태가 포함되어 있습니다. 호출 SRF 내에서fcinfo- flinfo- fn_extra포인터를 보유하는 데 메이저 토토 사이트됩니다FUNCCALLCONTEXT통화 전체. 매크로는 처음 사용하면 해당 필드를 자동으로 채우고 후속 용도에서 동일한 포인터를 찾을 것으로 예상됩니다.

typedef struct funccallcontext

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

    /*
     * 선택적 최대 통화 수
     *
     * max_calls는 편의를 위해서만 여기에 있으며 선택 사항입니다.
     * 설정하지 않으면 언제
     * 기능이 완료되었습니다.
     */
    UINT64 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는 튜플을 반환 할 때 사용합니다 (즉, 복합 데이터 유형)
     * 그리고 당신이 튜플을 만들려고하는 경우에만 필요합니다.
     * heap_form_tuple ()가 buildtuplefromcstrings ()를 사용하지 않고.  주목하십시오
     * 여기에 저장된 Tupledesc 포인터는 보통 통과해야합니다.
     * FlessTupledesc () 먼저.
     */
    tupledesc tuple_desc;

 funcCallContext;

매크로는 AN에서 사용합니다SRF이 인프라 사용 사용은 다음과 같습니다.

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첫 번째 집합을 수행하는 동안. 메이저 토토 사이트funcctx- user_fctx그러한 교차 데이터 구조에 대한 포인터를 보유합니다. (당신이 할당하는 데이터multi_call_memory_ctx쿼리가 종료되면 자동으로 사라질 것이므로 수동으로 해당 데이터를 자유롭게 해제 할 필요가 없습니다.)

경고

함수에 대한 실제 인수는 통화간에 변경되지 않은 상태로 유지되지만 인수 값 (일반적으로 투명하게 수행됩니다pg_getarg_xxx매크로) 일시적 컨텍스트에서는 각주기마다 용해 된 사본이 해제됩니다. 따라서, 당신이 당신의 그러한 값에 대해 언급하면user_fctx, 당신은 그것들을에 복사해야합니다multi_call_memory_ctx고발 후, 또는 해당 맥락에서만 값을 해제하는지 확인하십시오.

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

Datum
my_set_returning_function (pg_function_args)

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

        MemoryContext OldContext;

        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 (retcomposite);

자료
retComposite (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);

        / * 결과 유형에 대한 튜플 디스크립터 구축 */
        if (get_call_result_type (fcinfo, null, & tupdesc)! = saperfunc_composite)
            Ereport (오류,
                    (errcode (errcode_feature_not_supported),
                     errmsg ( "컨텍스트에서 호출 된 기능 반환 레코드"
                            "유형 레코드를 허용 할 수 없음"));

        /*
         * 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 에서이 기능을 선언하는 한 가지 방법은 다음과 같습니다.

유형 생성 __retcomposite as (f1 Integer, F2 Integer, F3 Integer);

기능 retcomposite 생성 또는 교체 (정수, 정수)
    __retcomposite를 설정합니다
    처럼 'filename','retcomposite '
    언어 c 불변의 엄격한;

다른 방법은 매개 변수를 메이저 토토 사이트하는 것입니다 :

함수 retcomposite 생성 또는 교체 (정수, 정수,
    Out F1 Integer, Out F2 Integer, Out F3 Integer)
    Setof 레코드를 반환합니다
    처럼 'filename','retcomposite '
    언어 c 불변의 엄격한;

이 방법에서 함수의 출력 유형은 공식적으로 익명입니다레코드타입.

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

c-language 함수는 다형성 유형을 수락하고 반환하도록 선언 할 수 있습니다Anylement, AnyArray, AnynonArray, AnyEnumAnyRange. 보다섹션 38.2.5다형성 기능에 대한 자세한 설명. 함수 인수 또는 반환 유형이 다형성 유형으로 정의되면 기능 저자는 어떤 데이터 유형을 호출하거나 반환 해야하는지 미리 알 수 없습니다. 에 제공된 두 가지 루틴이 있습니다.fmgr.h버전 -1 C 함수가 인수의 실제 데이터 유형과 반환 될 것으로 예상되는 유형을 발견 할 수 있도록합니다. 루틴은라고합니다.get_fn_expr_rettype (fmgrinfo *flinfo)get_fn_expr_argtype (fmgrinfo *flinfo, int argnum). 결과 또는 인수 유형 OID를 반환합니다.invalidoid정보를 메이저 토토 사이트할 수없는 경우. 구조flinfo일반적으로에 액세스됩니다.fcinfo- flinfo. 매개 변수argnum는 0에 기반을두고 있습니다.get_call_result_type대안으로 메이저 토토 사이트할 수 있습니다get_fn_expr_rettype. 또한get_fn_expr_variadic, 이것은 변수 인수가 배열에 병합되었는지 여부를 찾는 데 메이저 토토 사이트할 수 있습니다. 이것은 주로 유용합니다Variadic "Any"함수, 이러한 병합은 일반적인 배열 유형을 취하는 변수 함수에 대해 항상 발생했기 때문에

예를 들어, 모든 유형의 단일 요소를 수락하기 위해 함수를 작성하고 해당 유형의 1 차원 배열을 반환한다고 가정합니다.

pg_function_info_v1 (make_array);
자료
make_array (pg_function_args)

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

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

    / * 제공된 요소를 가져 오십시오.
    isnull = pg_argisnull (0);
    if (isnull)
        요소 = (Datum) 0;
    또 다른
        요소 = pg_getarg_datum (0);

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

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

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

    pg_return_arraytype_p (결과);

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

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

c-language 함수에만 메이저 토토 사이트할 수있는 다형성의 변형이 있습니다."Any". (이 유형 이름은 SQL 예약 단어이기 때문에이 유형 이름이 두 배로 인용되어야합니다.) 이것은와 같습니다.Anylement다른 제한을 제외하고"Any"인수는 동일한 유형이거나 기능의 결과 유형을 결정하는 데 도움이되지 않습니다. c-language 함수는 또한 최종 매개 변수를 선언 할 수 있습니다Variadic "Any". 이것은 모든 유형의 하나 이상의 실제 인수와 일치합니다 (반드시 같은 유형은 아닙니다). 이 주장은not정상적인 변수 함수와 마찬가지로 배열로 수집해야합니다. 그들은 단지 함수로 별도로 전달됩니다. 그만큼pg_nargs ()매크로 및 위에서 설명한 방법을 사용 하여이 기능을 사용할 때 실제 인수 수와 해당 유형을 결정해야합니다. 또한 이러한 기능을 가진 사용자는를 사용하고 싶을 수도 있습니다.variadic함수 호출의 키워드 기능이 배열 요소를 별도의 인수로 취급 할 것으로 기대합니다. 함수 자체는 원하는 경우 해당 동작을 구현해야합니다.get_fn_expr_variadic실제 인수에 표시되어 있음을 감지합니다.variadic.

38.10.10. 기능 변환

함수와 관련된 속성을 기반으로 계획 중에 일부 함수 호출을 단순화 할 수 있습니다. 예를 들어,int4mul (n, 1)그냥 단순화 될 수 있습니다n. 이러한 기능 별 최적화를 정의하려면 A를 작성하십시오.변환 기능protransform기본 함수 필드PG_PROC입력. 변환 기능에는 SQL 서명이 있어야합니다돌기 (내부) 내부 반환. 논쟁, 실제로funcexpr *, 기본 함수에 대한 호출을 나타내는 더미 노드입니다. 표현 트리에 대한 변환 함수의 연구가 단순화 된 발현 트리가 표현 된 모든 가능한 콘크리트 호출을 대체 할 수 있음을 증명하는 경우, 표현식을 단순화하고 반환합니다. 그렇지 않으면 반환 aNULL포인터 (notSQL NULL).

우리는 그것을 보장하지 않습니다PostgreSQL변환 함수가 단순화 될 수있는 경우 기본 함수를 절대 호출하지 않습니다. 단순화 된 표현식과 기본 기능에 대한 실제 호출 사이의 엄격한 동등성을 보장합니다.

현재이 시설은 보안 문제로 인해 SQL 수준의 사용자에게 노출되지 않으므로 내장 기능을 최적화하는 데만 사용하는 것이 실용적입니다..

38.10.11. 공유 메모리 및 LWLOCKS

애드 인은 서버 시작에 LWLOCKS 및 공유 메모리 할당을 예약 할 수 있습니다. Add-in의 공유 라이브러리는를 지정하여 사전로드해야합니다.shared_preload_libraries. 공유 메모리는 다음과 같이 호출하여 예약됩니다.

void requestAdDinshMemsPace (int size)

에서_pg_init함수.

lwlocks는 다음과 같이 예약됩니다.

void requestNamedlwlocktranche (const char *tranche_name, int num_lwlocks)

From_pg_init. 이것은 배열을 보장합니다.num_lwlockslwlocks는 이름으로 사용할 수 있습니다tranche_name. 메이저 토토 사이트getNamedLwlocktranche이 배열에 대한 포인터를 얻으려면

가능한 경주 조건을 피하기 위해 각 백엔드는 lwlock을 메이저 토토 사이트해야합니다addinshmeminitlock여기에 표시된대로 공유 메모리 할당을 연결하고 초기화 할 때 :

정적 mystruct *ptr = null;

if (! ptr)

        bool 발견;

        lwlockacquire (addinshmeminitlock, lw_excluction);
        ptr = shmeminitstruct ( "나의 구조물 이름", 크기, & 발견);
        if (! 찾았다)

                SHMEM 영역의 내용을 초기화합니다.
                다음을 사용하여 요청 된 LWLOCKS를 획득하십시오.
                ptr- locks = getNamedLwlocktranche ( "내 트랜치 이름");

        lwlockrelease (addinshmeminitlock);

38.10.12. 확장 성을 위해 C ++ 사용

비록PostgreSQL백엔드는 C로 작성되었습니다.이 지침이 다음과 같이 C ++로 확장을 쓸 수 있습니다.

  • 백엔드에서 액세스하는 모든 기능은 백엔드에 C 인터페이스를 제시해야합니다. 이 C 함수는 C ++ 기능을 호출 할 수 있습니다. 예를 들어,extern C백엔드 액세스 함수에는 연결이 필요합니다. 이것은 백엔드와 C ++ 코드 사이의 포인터로 전달되는 모든 기능에도 필요합니다.

  • 적절한 거래 방법을 사용한 무료 메모리. 예를 들어, 대부분의 백엔드 메모리는를 사용하여 할당됩니다.palloc ()이 있으니pfree ()그것을 자유롭게하려면. C ++ 메이저 토토 사이트삭제그러한 경우 실패합니다.

  • C 코드로 전파되는 예외를 방지합니다 (모두 최상위 수준의 캐치 볼 블록 메이저 토토 사이트extern C함수). 메모리 외과 같은 이벤트는 여전히 예외를 제외 할 수 있기 때문에 C ++ 코드가 예외를 명시 적으로 던지지 않더라도 필요합니다. 모든 예외는 잡히고 적절한 오류는 C 인터페이스로 전달됩니다. 가능하면 C ++를로 컴파일하십시오.-fno-exceptions예외를 완전히 제거하기 위해; 이 경우 C ++ 코드에서 실패를 확인해야합니다 (예 :new ().

  • C ++ 코드에서 백엔드 기능을 호출하는 경우 C ++ 통화 스택에 일반 이전 데이터 구조 만 포함되어 있는지 확인하십시오 (POD). 백엔드 오류가 먼 것을 생성하기 때문에 필요합니다longjmp ()POD 객체가없는 C ++ 호출 스택을 제대로 풀지 않습니다.

요약하면 C ++ 코드를 벽 뒤에 배치하는 것이 가장 좋습니다extern c백엔드를 인터페이스하고 예외, 메모리 및 호출 스택 누설을 피하는 기능.