메이저 토토 사이트자 정의 함수는 C(또는 C++와 같이 C와 호환될 수 있는 언어)로 작성될 수 있습니다. 이러한 함수는 동적으로 로드 가능한 개체(공유 라이브러리라고도 함)로 컴파일되고 요청 시 서버에 의해 로드됩니다. 동적 로딩 기능이 차별화됩니다.“C 언어”함수“내부”함수 — 실제 코딩 규칙은 본질적으로 두 가지 모두 동일합니다. (따라서 표준 내부 함수 라이브러리는 메이저 토토 사이트자 정의 C 함수에 대한 풍부한 코딩 예제 소스입니다.)
현재 C 함수에는 하나의 호출 규칙만 메이저 토토 사이트됩니다(“버전 1”). 해당 호출 규칙에 대한 지원은 다음을 작성하여 표시됩니다.PG_FUNCTION_INFO_V1()아래 그림과 같이 함수에 대한 매크로 호출.
특정 로드 가능한 개체 파일의 메이저 토토 사이트자 정의 함수가 세션에서 처음 호출될 때 동적 로더는 함수가 호출될 수 있도록 해당 개체 파일을 메모리에 로드합니다. 그만큼함수 생성메이저 토토 사이트자 정의 C 함수의 경우 함수에 대해 두 가지 정보, 즉 로드 가능한 개체 파일의 이름과 해당 개체 파일 내에서 호출할 특정 함수의 C 이름(링크 기호)을 지정해야 합니다. C 이름이 명시적으로 지정되지 않으면 SQL 함수 이름과 동일한 것으로 간주됩니다.
다음 알고리즘은 다음에 제공된 이름을 기반으로 공유 개체 파일을 찾는 데 메이저 토토 사이트됩니다.함수 생성명령:
이름이 절대 경로이면 해당 파일이 로드됩니다.
이름이 문자열로 시작하는 경우$libdir, 해당 부분은로 대체됩니다.포스트그레SQL빌드 시 결정되는 패키지 라이브러리 디렉토리 이름.
이름에 디렉토리 부분이 포함되어 있지 않으면 구성 변수에 지정된 경로에서 파일을 검색합니다.dynamic_library_path.
그렇지 않으면(파일이 경로에서 발견되지 않았거나 절대 디렉토리가 아닌 부분이 포함되어 있는 경우) 동적 로더는 주어진 이름을 메이저 토토 사이트하려고 시도할 것이며 실패할 가능성이 높습니다. (현재 작업 디렉터리에 의존하는 것은 신뢰할 수 없습니다.)
이 순서가 작동하지 않으면 플랫폼별 공유 라이브러리 파일 이름 확장자(종종.so)가 지정된 이름에 추가되고 이 시퀀스가 다시 시도됩니다. 이것도 실패하면 로드가 실패합니다.
다음 중 하나를 기준으로 공유 라이브러리를 찾는 것이 좋습니다.$libdir또는 동적 라이브러리 경로를 통해. 이렇게 하면 새 설치가 다른 위치에 있는 경우 버전 업그레이드가 단순화됩니다. 실제 디렉터리는$libdir는 명령으로 찾을 수 있음을 의미합니다.pg_config --pkglibdir.
메이저 토토 사이트자 ID는PostgreSQL서버는 로드하려는 파일의 경로를 통과할 수 있어야 실행됩니다. 파일 또는 더 높은 수준의 디렉터리를 읽을 수 없거나 실행할 수 없게 만듭니다.포스트그레메이저 토토 사이트자는 흔히 저지르는 실수입니다.
어쨌든, 다음에 주어진 파일 이름은함수 생성명령은 시스템 카탈로그에 문자 그대로 기록되므로 파일을 다시 로드해야 하는 경우 동일한 절차가 적용됩니다.
PostgreSQLC 함수를 자동으로 컴파일하지 않습니다. 객체 파일은 a에서 참조되기 전에 컴파일되어야 합니다.함수 생성명령. 참조섹션 38.10.5추가 정보를 확인하세요.
동적으로 로드된 개체 파일이 호환되지 않는 서버에 로드되지 않도록 하려면,포스트그레SQL파일에 다음이 포함되어 있는지 확인합니다.“마법 블록”적절한 내용으로. 이를 통해 서버는 다른 주요 버전에 대해 컴파일된 코드와 같은 명백한 비호환성을 감지할 수 있습니다.PostgreSQL. 매직 블록을 포함하려면 헤더를 포함시킨 후 모듈 소스 파일 중 하나에 이것을 작성하십시오.fmgr.h:
PG_MODULE_MAGIC;
처음 메이저 토토 사이트된 후 동적으로 로드된 개체 파일은 메모리에 유지됩니다. 해당 파일의 함수에 대한 동일한 세션의 향후 호출은 기호 테이블 조회의 작은 오버헤드만 발생시킵니다. 예를 들어 개체 파일을 다시 컴파일한 후 개체 파일을 강제로 다시 로드해야 하는 경우 새 세션을 시작하세요.
선택적으로 동적으로 로드된 파일에는 초기화 및 종료 기능이 포함될 수 있습니다. 파일에라는 함수가 포함되어 있는 경우_PG_init, 해당 함수는 파일을 로드한 후 즉시 호출됩니다. 이 함수는 매개변수를 받지 않으며 void를 반환해야 합니다. 파일에라는 함수가 포함되어 있는 경우_PG_fini, 해당 함수는 파일을 언로드하기 직전에 호출됩니다. 마찬가지로 함수는 매개변수를 받지 않으며 void를 반환해야 합니다. 참고하세요_PG_fini프로세스 종료 중에는 호출되지 않고 파일을 언로드하는 동안에만 호출됩니다. (현재 언로드는 비활성화되어 있으며 절대 발생하지 않지만 향후 변경될 수 있습니다.)
C 언어 함수를 작성하는 방법을 알려면 방법을 알아야 합니다.포스트그레SQL내부적으로 기본 데이터 유형과 해당 유형이 함수 간에 전달될 수 있는 방법을 나타냅니다. 내부적으로는,PostgreSQL기본 유형을 다음과 같이 간주“기억의 덩어리”. 유형에 대해 정의하는 메이저 토토 사이트자 정의 함수는 다음과 같은 방식을 정의합니다.포스트그레SQL작동할 수 있습니다. 즉,PostgreSQL디스크의 데이터만 저장 및 검색하고 메이저 토토 사이트자 정의 함수를 메이저 토토 사이트하여 데이터를 입력, 처리 및 출력합니다.
기본 유형은 세 가지 내부 형식 중 하나를 가질 수 있습니다.
값 전달, 고정 길이
참조로 전달, 고정 길이
참조로 전달, 가변 길이
값 기준 유형은 길이가 1, 2 또는 4바이트만 될 수 있습니다. (경우에 따라 8바이트도 가능합니다.크기(데이텀)컴퓨터에서는 8입니다). 모든 아키텍처에서 동일한 크기(바이트)가 되도록 유형을 정의할 때 주의해야 합니다. 예를 들어,긴type은 일부 시스템에서는 4바이트이고 다른 시스템에서는 8바이트이므로 위험합니다.int유형은 대부분의 Unix 시스템에서 4바이트입니다. 의 합리적인 구현int4Unix 시스템의 유형은 다음과 같습니다:
/* 4바이트 정수, 값으로 전달됨 */ typedef int int4;
(실제 PostgreSQL C 코드는 이 유형을 호출합니다.int32, C에서는 다음과 같은 규칙이 있기 때문입니다.int의미XXXX 비트. 따라서 C 유형도 참고하세요.int8크기는 1바이트입니다. SQL 유형int8명함int64C에서. 또한 참조표 38.1.)
반면에 모든 크기의 고정 길이 유형은 참조로 전달될 수 있습니다. 예를 들어, 다음은 a의 샘플 구현입니다.포스트그레SQL유형:
/* 참조로 전달된 16바이트 구조 */
typedef 구조체
이중 x, y;
포인트;
해당 유형에 대한 포인터만 내부 및 외부로 전달할 때 메이저 토토 사이트할 수 있습니다.포스트그레SQL함수. 이러한 유형의 값을 반환하려면 다음을 메이저 토토 사이트하여 올바른 양의 메모리를 할당하십시오.팔록, 할당된 메모리를 채우고 이에 대한 포인터를 반환합니다. (또한 동일한 데이터 유형의 입력 인수 중 하나와 동일한 값을 반환하려는 경우 추가 항목을 건너뛸 수 있습니다.팔록그리고 입력 값에 대한 포인터를 반환하면 됩니다.)
마지막으로 모든 가변 길이 유형도 참조로 전달되어야 합니다. 모든 가변 길이 유형은 정확히 4바이트의 불투명 길이 필드로 시작해야 하며, 이는 다음으로 설정됩니다.SET_VARSIZE; 이 필드를 직접 설정하지 마십시오! 해당 유형 내에 저장될 모든 데이터는 해당 길이 필드 바로 뒤에 있는 메모리에 위치해야 합니다. 길이 필드에는 구조체의 전체 길이가 포함됩니다. 즉, 길이 필드 자체의 크기가 포함됩니다.
또 다른 중요한 점은 데이터 유형 값 내에 초기화되지 않은 비트를 남기지 않는 것입니다. 예를 들어 구조체에 있을 수 있는 정렬 패딩 바이트를 0으로 만드는 데 주의하세요. 이것이 없으면 데이터 유형의 논리적으로 동일한 상수가 플래너에 의해 동일하지 않은 것으로 간주되어 비효율적인(잘못된 것은 아니지만) 계획으로 이어질 수 있습니다.
절대로참조별 입력 값의 내용을 수정합니다. 그렇게 하면 제공된 포인터가 디스크 버퍼를 직접 가리킬 수 있으므로 디스크의 데이터가 손상될 가능성이 있습니다. 이 규칙의 유일한 예외는 다음에서 설명됩니다.스포츠 토토 사이트 PostgreSQL : 문서 : 11 : 38.11. 사용자 정의 골재.
예를 들어, 유형을 정의할 수 있습니다.텍스트다음과 같습니다:
typedef 구조체
int32 길이;
문자 데이터[FLEXIBLE_ARRAY_MEMBER];
텍스트;
그[FLEXIBLE_ARRAY_MEMBER]표기법은 데이터 부분의 실제 길이가 이 선언에 의해 지정되지 않았음을 의미합니다.
가변 길이 유형을 조작할 때 올바른 메모리 양을 할당하고 길이 필드를 올바르게 설정하도록 주의해야 합니다. 예를 들어, 40바이트를텍스트구조, 다음과 같은 코드 조각을 메이저 토토 사이트할 수 있습니다:
#include "postgres.h" ... 문자 버퍼[40]; /* 소스 데이터 */ ... 텍스트 *목적지 = (텍스트 *) palloc(VARHDRSZ + 40); SET_VARSIZE(목적지, VARHDRSZ + 40); memcpy(대상-데이터, 버퍼, 40); ...
VARHDRSZ다음과 같습니다크기(int32), 하지만 매크로를 메이저 토토 사이트하는 것이 좋은 스타일로 간주됩니다.VARHDRSZ가변 길이 유형의 오버헤드 크기를 나타냅니다. 또한 길이 필드반드시다음을 메이저 토토 사이트하여 설정SET_VARSIZE단순 할당이 아닌 매크로입니다.
표 38.1다음에 내장된 여러 SQL 데이터 유형에 해당하는 C 유형을 표시합니다.포스트그레SQL.“다음에 정의됨”열은 유형 정의를 얻기 위해 포함되어야 하는 헤더 파일을 제공합니다. (실제 정의는 나열된 파일에 포함된 다른 파일에 있을 수 있습니다. 메이저 토토 사이트자는 정의된 인터페이스를 고수하는 것이 좋습니다.) 항상 포함해야 합니다.postgres.h서버 코드의 소스 파일에서 첫 번째입니다. 어쨌든 필요한 여러 가지 항목을 선언하고 다른 헤더를 먼저 포함하면 이식성 문제가 발생할 수 있기 때문입니다.
표 38.1. 내장 SQL 유형과 동등한 C 유형
| SQL 유형 | C타입 | 다음에 정의됨 |
|---|---|---|
절대 |
절대시간 |
utils/nabstime.h |
부울 |
부울 |
postgres.h(어쩌면 컴파일러 내장) |
상자 |
박스* |
utils/geo_decls.h |
바이테아 |
바이테아* |
postgres.h |
"문자" |
문자 |
(컴파일러 내장) |
문자 |
BpChar* |
postgres.h |
시드 |
CommandId |
postgres.h |
날짜 |
날짜ADT |
utils/date.h |
플로트4 (진짜) |
플로트4 |
postgres.h |
float8 (배정밀도) |
float8 |
postgres.h |
int2 (작은int) |
int16 |
postgres.h |
int4 (정수) |
int32 |
postgres.h |
int8 (비긴트) |
int64 |
postgres.h |
간격 |
간격* |
데이터 유형/타임스탬프.h |
lseg |
LSEG* |
utils/geo_decls.h |
이름 |
이름 |
postgres.h |
숫자 |
숫자 |
utils/numeric.h |
oid |
오이드 |
postgres.h |
oidVector |
oidVector* |
postgres.h |
경로 |
경로* |
utils/geo_decls.h |
점 |
포인트* |
utils/geo_decls.h |
regproc |
등록 절차 |
postgres.h |
상대시간 |
상대시간 |
utils/nabstime.h |
텍스트 |
텍스트* |
postgres.h |
tid |
ItemPointer |
저장소/itempr.h |
시간 |
TimeADT |
utils/date.h |
시간대 포함 시간 |
TimeTzADT |
utils/date.h |
타임스탬프 |
타임스탬프 |
데이터 유형/타임스탬프.h |
시간대가 포함된 타임스탬프 |
TimestampTz |
데이터 유형/타임스탬프.h |
틴트 간격 |
TimeInterval |
utils/nabstime.h |
varchar |
VarChar* |
postgres.h |
xid |
거래 ID |
postgres.h |
이제 기본 유형에 대해 가능한 모든 구조를 검토했으므로 실제 함수의 몇 가지 예를 보여줄 수 있습니다.
버전 1 호출 규칙은 매크로를 메이저 토토 사이트하여 인수 및 결과 전달의 복잡성을 대부분 억제합니다. 버전 1 함수의 C 선언은 항상 다음과 같습니다.
데이텀 기능 이름(PG_FUNCTION_ARGS)
추가로, 매크로 호출은:
PG_FUNCTION_INFO_V1(기능 이름);
동일한 소스 파일에 나타나야 합니다. (통상적으로 함수 자체 바로 앞에 작성합니다.) 이 매크로 호출은 다음과 같은 경우에는 필요하지 않습니다.내부-언어 함수, 이후포스트그레SQL모든 내부 함수가 버전 1 규칙을 메이저 토토 사이트한다고 가정합니다. 그러나 동적으로 로드되는 함수에는 필요합니다.
버전-1 함수에서 각 실제 인수는 다음을 메이저 토토 사이트하여 가져옵니다.PG_GETARG_35494_35640xxx()PG_ARGISNULL(); 아래를 참조하세요.) 결과는 다음을 메이저 토토 사이트하여 반환됩니다.PG_RETURN_반환 유형에 대한 매크로입니다.xxx()PG_GETARG_가져올 함수 인수의 수를 인수로 취하며, 여기서 개수는 0부터 시작합니다.xxx()PG_RETURN_반환할 실제 값을 인수로 메이저 토토 사이트합니다.xxx()
다음은 버전-1 호출 규칙을 메이저 토토 사이트하는 몇 가지 예입니다:
#include "postgres.h"
#include <문자열.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(인수 + 1);
/* 참고로 고정 길이 */
PG_FUNCTION_INFO_V1(add_one_float8);
데이텀
add_one_float8(PG_FUNCTION_ARGS)
/* FLOAT8의 매크로는 참조에 의한 전달 특성을 숨깁니다. */
float8 인수 = PG_GETARG_FLOAT8(0);
PG_RETURN_FLOAT8(arg + 1.0);
PG_FUNCTION_INFO_V1(메이크포인트);
데이텀
메이크포인트(PG_FUNCTION_ARGS)
/* 여기서 Point의 참조별 전달 특성은 숨겨지지 않습니다. */
포인트 *pointx = PG_GETARG_POINT_P(0);
포인트 *pointy = PG_GETARG_POINT_P(1);
Point *new_point = (Point *) palloc(sizeof(Point));
new_point-x = 포인트x-x;
new_point-y = 뾰족한-y;
PG_RETURN_POINT_P(new_point);
/* 참고로, 가변 길이 */
PG_FUNCTION_INFO_V1(텍스트 복사);
데이텀
카피텍스트(PG_FUNCTION_ARGS)
텍스트 *t = PG_GETARG_TEXT_PP(0);
/*
* VARSIZE_ANY_EXHDR은 바이트 단위의 구조체 크기에서
* 헤더의 VARHDRSZ 또는 VARHDRSZ_SHORT. 다음을 메이저 토토 사이트하여 복사본을 구성합니다.
* 전체 길이 헤더.
*/
텍스트 *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;
text *new_text = (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다음과 같은 명령으로:
CREATE FUNCTION add_one(integer) RETURNS 정수
그대로 '디렉토리/funcs', 'add_one'
언어 C 엄격;
-- SQL 함수 이름 "add_one"의 오버로드에 유의하세요.
CREATE FUNCTION add_one(이중 정밀도) 반환 이중 정밀도
그대로 '디렉토리/funcs', 'add_one_float8'
언어 C 엄격;
CREATE FUNCTION makepoint(point, point) RETURNS 포인트
그대로 '디렉토리/funcs', 'makepoint'
언어 C 엄격;
CREATE FUNCTION copytext(text) 텍스트를 반환합니다.
그대로 '디렉토리/funcs', '복사본문'
언어 C 엄격;
CREATE FUNCTION concat_text(text, text) 텍스트를 반환합니다.
그대로 '디렉토리/funcs', 'concat_text'
언어 C 엄격;
여기,디렉토리공유 라이브러리 파일의 디렉토리를 나타냅니다(예:PostgreSQLtutorial 디렉터리(이 섹션에서 메이저 토토 사이트된 예제의 코드가 포함되어 있음)). (더 나은 스타일은 그냥 메이저 토토 사이트하는 것입니다.'기능'에서AS절, 추가 후디렉토리검색 경로에. 어쨌든 공유 라이브러리에 대한 시스템별 확장은 일반적으로 생략할 수 있습니다..so.)
함수를 다음과 같이 지정했음을 주목하세요“엄격”는 입력 값이 null인 경우 시스템이 자동으로 null 결과를 가정해야 함을 의미합니다. 이렇게 하면 함수 코드에서 null 입력을 확인할 필요가 없습니다. 이것이 없으면 다음을 메이저 토토 사이트하여 명시적으로 null 값을 확인해야 합니다.PG_ARGISNULL().
매크로PG_ARGISNULL(함수에서 각 입력이 null인지 테스트할 수 있습니다. (물론 이렇게 하는 것은 선언되지 않은 함수에서만 필요합니다.“엄격”.) 마찬가지로n)PG_GETARG_매크로, 입력 인수는 0부터 시작하여 계산됩니다. 실행을 삼가해야 합니다.xxx()PG_GETARG_인수가 null이 아니라는 것을 확인할 때까지. null 결과를 반환하려면 다음을 실행하세요.xxx()PG_RETURN_NULL(); 이는 엄격한 함수와 엄격하지 않은 함수 모두에서 작동합니다.
언뜻 보면 버전 1 코딩 규칙은 일반 메이저 토토 사이트에 비해 무의미한 모호함으로 보일 수 있습니다.C호출 규칙. 그러나 이를 통해 우리는 다음을 처리할 수 있습니다.NULL인수/반환 값 가능 및“구운”(압축 또는 라인 외부) 값.
버전-1 인터페이스에서 제공하는 다른 옵션은 다음의 두 가지 변형입니다.PG_GETARG_매크로. 그 중 첫 번째는,xxx()PG_GETARG_, 쓰기에 안전한 지정된 인수의 복사본을 반환하도록 보장합니다. (일반 매크로는 테이블에 물리적으로 저장되어 있어서 기록해서는 안 되는 값에 대한 포인터를 반환하는 경우가 있습니다.xxx_COPY()PG_GETARG_매크로는 쓰기 가능한 결과를 보장합니다.) 두 번째 변형은 다음으로 구성됩니다.xxx_COPY()PG_GETARG_3개의 인수를 취하는 매크로입니다. 첫 번째는 (위와 같이) 함수 인수의 번호입니다. 두 번째와 세 번째는 반환할 세그먼트의 오프셋과 길이입니다. 오프셋은 0부터 계산되며 음수 길이는 값의 나머지 부분이 반환되도록 요청합니다. 이러한 매크로는 저장 유형이 있는 경우 큰 값의 일부에 대한 보다 효율적인 액세스를 제공합니다.“외부”. (열의 저장 유형은 다음을 메이저 토토 사이트하여 지정할 수 있습니다.xxx_SLICE()테이블 변경. 테이블 이름열 변경열이름저장소 설정저장소 유형저장 유형다음 중 하나입니다.일반, 외부, 확장또는메인.)
마지막으로 버전-1 함수 호출 규칙을 메이저 토토 사이트하면 설정된 결과를 반환할 수 있습니다. (섹션 38.10.8) 및 트리거 함수 구현(토토 꽁 머니 : 문서 : 11 : 39 장. 트리거) 및 절차적 언어 호출 핸들러(PostgreSQL : 문서 : 11 : 56 장. 절차 적 언어 젠 토토 작성). 자세한 내용은 참조src/backend/utils/fmgr/README소스 배포판에서.
더 고급 주제로 전환하기 전에 다음을 위한 몇 가지 코딩 규칙에 대해 논의해야 합니다.포스트그레SQLC 언어 함수. C 이외의 언어로 작성된 함수를 로드하는 것이 가능할 수도 있지만PostgreSQL, C++, FORTRAN 또는 Pascal과 같은 다른 언어는 C와 동일한 호출 규칙을 따르지 않는 경우가 많기 때문에 이는 일반적으로 어렵습니다(가능한 경우). 즉, 다른 언어는 함수 간에 인수와 반환 값을 동일한 방식으로 전달하지 않습니다. 이러한 이유로 우리는 귀하의 C 언어 함수가 실제로 C로 작성되었다고 가정합니다.
C 함수 작성 및 구축을 위한 기본 규칙은 다음과 같습니다:
메이저 토토 사이트pg_config --includedir-서버어디가 있는지 알아내기 위해PostgreSQL서버 헤더 파일이 귀하의 시스템(또는 귀하의 메이저 토토 사이트자가 실행될 시스템)에 설치되어 있습니다.
동적으로 로드될 수 있도록 코드 컴파일 및 링크PostgreSQL항상 특수 플래그가 필요합니다. 참조섹션 38.10.5귀하의 특정 운영 체제에서 이를 수행하는 방법에 대한 자세한 설명을 참조하세요.
정의하는 것을 기억하세요“마법 블록”에 설명된 대로 공유 라이브러리의 경우섹션 38.10.1.
메모리를 할당할 때 다음을 메이저 토토 사이트하십시오.PostgreSQL함수팔록그리고프리해당 C 라이브러리 함수 대신malloc그리고무료. 에 의해 할당된 메모리팔록각 트랜잭션이 끝나면 자동으로 해제되어 메모리 누수를 방지합니다.
항상 다음을 메이저 토토 사이트하여 구조의 바이트를 0으로 만듭니다.memset(또는 할당palloc0먼저). 구조의 각 필드에 할당하더라도 가비지 값을 포함하는 정렬 패딩(구조의 구멍)이 있을 수 있습니다. 이것이 없으면 해시 인덱스나 해시 조인을 지원하기가 어렵습니다. 해시를 계산하려면 데이터 구조의 중요한 부분만 선택해야 하기 때문입니다. 또한 플래너는 비트별 동일성을 통해 상수를 비교하는 경우도 있으므로 논리적으로 동일한 값이 비트별로 동일하지 않으면 바람직하지 않은 계획 결과를 얻을 수 있습니다.
대부분의 내부PostgreSQL유형은 다음에서 선언됩니다.postgres.h, 함수 관리자 인터페이스(PG_FUNCTION_ARGS등)이 포함됨fmgr.h, 따라서 최소한 이 두 파일을 포함해야 합니다. 이식성을 위해 다음을 포함하는 것이 가장 좋습니다.postgres.h 첫 번째, 다른 시스템 또는 메이저 토토 사이트자 헤더 파일 앞에 위치합니다. 포함postgres.h또한 포함됩니다elog.h그리고palloc.h당신을 위해.
객체 파일 내에 정의된 기호 이름은 서로 충돌하거나 다음에 정의된 기호와 충돌해서는 안 됩니다.PostgreSQL서버 실행 가능. 이 결과에 대한 오류 메시지가 나타나면 함수나 변수의 이름을 바꿔야 합니다.
귀하가 귀하를 메이저 토토 사이트하기 전에PostgreSQLC로 작성된 확장 함수는 서버에서 동적으로 로드할 수 있는 파일을 생성하기 위해 특별한 방법으로 컴파일하고 링크해야 합니다. 정확히 말하자면, 가공유 라이브러리생성되어야 합니다.
이 섹션에 포함된 것 이상의 정보를 보려면 운영 체제의 문서, 특히 C 컴파일러의 매뉴얼 페이지를 읽어야 합니다.cc및 링크 편집기,ld. 게다가,PostgreSQL소스 코드에는 다음의 몇 가지 작업 예제가 포함되어 있습니다.기여디렉토리. 이러한 예에 의존한다면 모듈의 가용성에 따라 달라지게 됩니다.PostgreSQL그러나 소스 코드는 있습니다.
공유 라이브러리 생성은 일반적으로 실행 파일을 연결하는 것과 유사합니다. 먼저 소스 파일이 개체 파일로 컴파일된 다음 개체 파일이 함께 연결됩니다. 개체 파일은 다음과 같이 생성되어야 합니다.위치 독립적 코드 (사진),이것은 개념적으로 실행 파일에 의해 로드될 때 메모리의 임의 위치에 배치될 수 있음을 의미합니다. (실행 파일용 개체 파일은 일반적으로 그런 방식으로 컴파일되지 않습니다.) 공유 라이브러리를 연결하는 명령에는 실행 파일 연결과 구별하기 위한 특수 플래그가 포함되어 있습니다(적어도 이론상으로는 - 일부 시스템에서는 실행이 훨씬 더 추악합니다).
다음 예에서는 소스 코드가 파일에 있다고 가정합니다.foo.c그리고 공유 라이브러리를 만들겠습니다foo.so. 중간 개체 파일이 호출됩니다.foo.o별도의 언급이 없는 한. 공유 라이브러리에는 둘 이상의 개체 파일이 포함될 수 있지만 여기서는 하나만 메이저 토토 사이트합니다.
생성할 컴파일러 플래그사진is-fPIC. 공유 라이브러리를 생성하기 위한 컴파일러 플래그는 다음과 같습니다.-공유.
gcc -fPIC -c foo.c gcc -shared -o foo.so foo.o
이 내용은 버전 3.0부터 적용됩니다.FreeBSD.
생성할 시스템 컴파일러의 컴파일러 플래그사진이다+z. 메이저 토토 사이트시GCC그것은-fPIC. 공유 라이브러리의 링커 플래그는 다음과 같습니다.-b. 그래서:
cc +z -c foo.c
또는:
gcc -fPIC -c foo.c
그리고 나서:
ld -b -o foo.sl foo.o
HP-UX확장 프로그램을 메이저 토토 사이트합니다.sl대부분의 다른 시스템과 달리 공유 라이브러리용.
생성할 컴파일러 플래그사진is-fPIC. 공유 라이브러리를 생성하는 컴파일러 플래그는 다음과 같습니다.-공유. 전체 예는 다음과 같습니다.
cc -fPIC -c foo.c cc -shared -o foo.so foo.o
여기에 예가 있습니다. 개발자 도구가 설치되어 있다고 가정합니다.
cc -c foo.c cc -bundle -Flat_namespace -undefine 억제 -o foo.so foo.o
생성할 컴파일러 플래그PICis-fPIC. 에 대한엘프시스템, 플래그가 있는 컴파일러-공유공유 라이브러리를 연결하는 데 메이저 토토 사이트됩니다. ELF가 아닌 이전 시스템에서는,ld -B공유 가능메이저 토토 사이트됩니다.
gcc -fPIC -c foo.c gcc -shared -o foo.so foo.o
생성할 컴파일러 플래그사진이다-fPIC. ld -B공유 가능공유 라이브러리를 연결하는 데 메이저 토토 사이트됩니다.
gcc -fPIC -c foo.c ld -Bshareable -o foo.so foo.o
생성할 컴파일러 플래그사진is-KPICSun 컴파일러와-fPIC와GCC. 공유 라이브러리를 연결하기 위한 컴파일러 옵션은 다음과 같습니다.-G컴파일러 또는 대안으로-공유와GCC.
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서버가 공유 라이브러리 파일을 찾을 것으로 예상하는 위치에 대해.
복합 유형에는 C 구조와 같은 고정 레이아웃이 없습니다. 복합 유형의 인스턴스에는 null 필드가 포함될 수 있습니다. 또한 상속 계층의 일부인 복합 유형은 동일한 상속 계층의 다른 멤버와 다른 필드를 가질 수 있습니다. 그러므로포스트그레SQLC에서 복합 유형의 필드에 액세스하기 위한 함수 인터페이스를 제공합니다.
질문에 응답하는 함수를 작성한다고 가정해 보겠습니다:
SELECT 이름, c_overpaid(emp, 1500) AS 초과 지불
엠프에서
WHERE 이름 = 'Bill' OR 이름 = 'Sam';
버전 1 호출 규칙을 메이저 토토 사이트하여 정의할 수 있습니다.c_과다지급다음과 같이:
#include "postgres.h"
#include "executor/executor.h" /* for GetAttributeByName() */
PG_MODULE_MAGIC;
PG_FUNCTION_INFO_V1(c_초과지불);
데이텀
c_과다지급(PG_FUNCTION_ARGS)
HeapTupleHeader t = PG_GETARG_HEAPTUPLEHEADER(0);
int32 제한 = PG_GETARG_INT32(1);
bool은 null입니다.
기준 급여;
급여 = GetAttributeByName(t, "급여", &isnull);
만약 (isnull)
PG_RETURN_BOOL(거짓);
/* 대안으로, null 급여에 대해 PG_RETURN_NULL()을 수행하는 것을 선호할 수도 있습니다. */
PG_RETURN_BOOL(DatumGetInt32(급여) 한도);
GetAttributeByName이것은PostgreSQL지정된 행에서 속성을 반환하는 시스템 함수입니다. 여기에는 세 가지 인수가 있습니다: 유형의 인수HeapTupleHeader함수, 원하는 속성의 이름, 속성이 null인지 여부를 알려주는 반환 매개변수에 전달됩니다.GetAttributeByName반환데이텀적절한 데이터 유형을 메이저 토토 사이트하여 적절한 데이터 유형으로 변환할 수 있는 값데이텀겟매크로. null 플래그가 설정된 경우 반환 값은 의미가 없습니다. 결과에 대해 어떤 작업을 시도하기 전에 항상 null 플래그를 확인하세요.XXX()
또한 있습니다GetAttributeByNum, 이름 대신 열 번호로 대상 속성을 선택합니다.
다음 명령은 함수를 선언합니다.c_과잉 지불SQL에서:
CREATE FUNCTION c_overpaid(emp, 정수) RETURNS 부울
그대로 '디렉토리/funcs', 'c_overpaid'
언어 C 엄격;
우리가 메이저 토토 사이트한 공지사항STRICT그래서 입력 인수가 NULL인지 확인할 필요가 없었습니다.
C 언어 함수에서 행 또는 복합 유형 값을 반환하려면 복합 데이터 유형 구축의 복잡성 대부분을 숨기는 매크로 및 함수를 제공하는 특수 API를 메이저 토토 사이트할 수 있습니다. 이 API를 메이저 토토 사이트하려면 소스 파일에 다음이 포함되어야 합니다.
#include "funcapi.h"
복합 데이터 값을 구축할 수 있는 두 가지 방법이 있습니다(이후로“튜플”): Datum 값 배열 또는 튜플 열 데이터 유형의 입력 변환 함수에 전달될 수 있는 C 문자열 배열에서 이를 빌드할 수 있습니다. 두 경우 모두 먼저 a를 얻거나 구성해야 합니다.TupleDesc60555_60633TupleDesc에BlessTupleDesc그리고 전화하세요heap_form_tuple각 행에 대해. C 문자열로 작업할 때 다음을 전달합니다.TupleDesc에TupleDescGetAttInMetadata그리고 전화하세요BuildTupleFromCStrings각 행에 대해. 튜플 세트를 반환하는 함수의 경우 함수의 첫 번째 호출 중에 설정 단계를 모두 한 번 수행할 수 있습니다.
필요한 설정을 위해 여러 도우미 기능을 메이저 토토 사이트할 수 있습니다.TupleDesc. 복합 값을 반환하는 대부분의 함수에서 이를 수행하는 권장 방법은 다음을 호출하는 것입니다.
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo,
Oid *resultTypeId,
TupleDesc *resultTupleDesc)
동일한 내용 전달fcinfo구조체가 호출 함수 자체에 전달되었습니다. (물론 이를 위해서는 버전 1 호출 규칙을 메이저 토토 사이트해야 합니다.)결과유형Id다음과 같이 지정할 수 있습니다.NULL또는 함수의 결과 유형 OID를 수신하기 위한 지역 변수의 주소로.resultTupleDesc현지 주소여야 합니다TupleDesc변수. 결과가 다음과 같은지 확인하세요.TYPEFUNC_COMPOSITE; 그렇다면,resultTupleDesc필요한 내용이 채워졌습니다TupleDesc. (그렇지 않은 경우 다음 라인에 따라 오류를 보고할 수 있습니다.“유형 레코드를 허용할 수 없는 컨텍스트에서 호출된 레코드를 반환하는 함수”.)
get_call_result_type다형성 함수 결과의 실제 유형을 확인할 수 있습니다. 따라서 합성을 반환하는 함수뿐만 아니라 스칼라 다형성 결과를 반환하는 함수에 유용합니다.결과유형Id출력은 주로 다형성 스칼라를 반환하는 함수에 유용합니다.
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)
을 얻으려면TupleDesc명명된 관계의 행 유형에 대해, 그리고:
TupleDesc TypeGetTupleDesc(Oid typeoid, List *colaliases)
을 얻으려면TupleDescOID 유형을 기반으로 합니다. 이것은 다음을 얻는 데 메이저 토토 사이트될 수 있습니다.TupleDesc기본 또는 복합 유형의 경우. 반환하는 함수에서는 작동하지 않습니다.기록그러나 다형성 유형을 확인할 수 없습니다.
일단 당신은TupleDesc, 전화:
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Datum으로 작업할 계획인 경우 또는:
AttInMetadata *TupleDescGetAttInMetadata(TupleDesc tupdesc)
C 문자열로 작업할 계획이라면. 집합을 반환하는 함수를 작성하는 경우 이러한 함수의 결과를FuncCallContext구조 — 메이저 토토 사이트tuple_desc또는아틴메타필드 각각.
데이텀으로 작업할 때 다음을 메이저 토토 사이트하십시오:
HeapTuple heap_form_tuple(TupleDesc tupdesc, Datum *values, bool *isnull)
빌드하다힙튜플Datum 형식으로 메이저 토토 사이트자 데이터가 제공되었습니다.
C 문자열로 작업할 때 다음을 메이저 토토 사이트하십시오:
HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
빌드하다힙튜플C 문자열 형식으로 메이저 토토 사이트자 데이터가 제공되었습니다.값는 반환 행의 각 속성에 대해 하나씩 C 문자열의 배열입니다. 각 C 문자열은 속성 데이터 유형의 입력 함수에서 예상하는 형식이어야 합니다. 속성 중 하나에 대해 null 값을 반환하려면 해당 포인터가값배열은 다음으로 설정되어야 합니다.NULL. 이 함수는 반환하는 각 행에 대해 다시 호출해야 합니다.
함수에서 반환할 튜플을 만든 후에는 a로 변환해야 합니다.데이텀. 메이저 토토 사이트:
HeapTupleGetDatum(HeapTuple 튜플)
변환하려면힙튜플유효한 데이터로 변환합니다. 이데이텀단일 행만 반환하려는 경우 직접 반환하거나 집합 반환 함수에서 현재 반환 값으로 메이저 토토 사이트할 수 있습니다.
다음 섹션에 예가 나와 있습니다.
C 언어 함수에는 세트(여러 행)를 반환하는 두 가지 옵션이 있습니다. 한 가지 방법으로,ValuePerCall모드에서는 집합 반환 함수가 반복적으로 호출되고(매번 동일한 인수 전달) 반환할 행이 더 이상 없을 때까지 호출할 때마다 새 행 하나를 반환하고 NULL을 반환하여 이를 알립니다. 집합 반환 함수(SRF67183_67338구현화모드에서 SRF는 전체 결과를 포함하는 tuplestore 객체를 채우고 반환합니다. 그러면 전체 결과에 대해 단 한 번의 호출만 발생하며 호출 간 상태는 필요하지 않습니다.
ValuePerCall 모드를 메이저 토토 사이트할 때 쿼리 실행이 완료될 것이라고 보장할 수 없다는 점을 기억하는 것이 중요합니다. 즉, 다음과 같은 옵션으로 인해 발생합니다.한도, 실행 프로그램은 모든 행을 가져오기 전에 set-returning 함수에 대한 호출을 중지할 수 있습니다. 이는 마지막 호출에서 정리 작업을 수행하는 것이 안전하지 않다는 것을 의미합니다. 그런 일이 일어나지 않을 수도 있기 때문입니다. 파일 설명자와 같은 외부 리소스에 액세스해야 하는 함수에는 Materialize 모드를 메이저 토토 사이트하는 것이 좋습니다.
이 섹션의 나머지 부분에서는 ValuePerCall 모드를 메이저 토토 사이트하는 SRF에 일반적으로 메이저 토토 사이트되는(필수는 아니지만) 도우미 매크로 세트를 문서화합니다. Materialize 모드에 대한 추가 세부정보는 다음에서 확인할 수 있습니다.src/backend/utils/fmgr/README. 또한,기여모듈포스트그레SQL소스 배포에는 ValuePerCall 및 Materialize 모드를 모두 메이저 토토 사이트하는 SRF의 많은 예가 포함되어 있습니다.
여기에 설명된 ValuePerCall 지원 매크로를 메이저 토토 사이트하려면 다음을 포함하십시오.funcapi.h. 이 매크로는 구조와 함께 작동합니다.FuncCallContext호출 전반에 걸쳐 저장해야 하는 상태가 포함되어 있습니다. 호출 SRF 내에서,fcinfo-flinfo-fn_extra포인터를 보유하는 데 메이저 토토 사이트됩니다.FuncCallContext통화 전반에 걸쳐. 매크로는 처음 메이저 토토 사이트할 때 해당 필드를 자동으로 채우고 이후 메이저 토토 사이트 시 동일한 포인터를 찾을 것으로 예상합니다.
typedef 구조체 FuncCallContext
/*
* 이전에 전화를 받은 횟수
*
* call_cntr은 SRF_FIRSTCALL_INIT()에 의해 0으로 초기화됩니다.
* SRF_RETURN_NEXT()가 호출될 때마다 증가됩니다.
*/
uint64 call_cntr;
/*
* 선택사항 최대 통화 수
*
* max_calls는 단지 편의를 위한 것이며 설정은 선택 사항입니다.
* 설정되지 않은 경우, 언제 실행되는지 알 수 있는 대체 수단을 제공해야 합니다.
* 기능이 완료되었습니다.
*/
uint64 max_calls;
/*
* 결과 슬롯에 대한 선택적 포인터
*
* 이는 더 이상 메이저 토토 사이트되지 않으며 이전 버전과의 호환성을 위해서만 제공됩니다.
* 더 이상 메이저 토토 사이트되지 않는 TupleDescGetSlot()을 메이저 토토 사이트하는 메이저 토토 사이트자 정의 SRF.
*/
TupleTableSlot *슬롯;
/*
* 기타 메이저 토토 사이트자 제공 컨텍스트 정보에 대한 선택적 포인터
*
* user_fctx는 보유할 자신의 데이터에 대한 포인터로 메이저 토토 사이트됩니다.
* 함수 호출 사이의 임의 컨텍스트 정보.
*/
무효 *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_form_tuple(). 참고하세요
* 여기에 저장된 TupleDesc 포인터는 일반적으로 다음을 통해 실행되어야 합니다.
* BlessTupleDesc() 먼저.
*/
TupleDesc tuple_desc;
FuncCallContext;
다음에 의해 메이저 토토 사이트되는 매크로SRF이 인프라를 메이저 토토 사이트하는 방법은 다음과 같습니다.
SRF_IS_FIRSTCALL()
이를 메이저 토토 사이트하여 함수가 처음 호출되는지 아니면 후속 호출되는지 결정합니다. 첫 번째 통화에서만(만) 다음으로 전화하세요.
SRF_FIRSTCALL_INIT()
초기화하려면FuncCallContext. 첫 번째를 포함하여 모든 함수 호출에서 다음을 호출합니다.
SRF_PERCALL_SETUP()
메이저 토토 사이트을 설정하려면FuncCallContext.
함수에 현재 호출에서 반환할 데이터가 있는 경우 다음을 메이저 토토 사이트하세요.
SRF_RETURN_NEXT(funcctx, 결과)
발신자에게 반환합니다. (결과유형이어야 합니다.데이텀, 단일 값 또는 위에서 설명한 대로 준비된 튜플.) 마지막으로 함수가 데이터 반환을 마치면 다음을 메이저 토토 사이트하세요.
SRF_RETURN_DONE(funcctx)
정리하고 끝내기 위해SRF.
다음일 때 현재인 메모리 컨텍스트SRF이라고 불리는 것은 호출 사이에 지워지는 임시 컨텍스트입니다. 즉, 전화할 필요가 없습니다.프리다음을 메이저 토토 사이트하여 할당한 모든 것에팔록; 어쨌든 사라질 것입니다. 그러나 호출 전반에 걸쳐 데이터 구조를 할당하려면 해당 데이터 구조를 다른 곳에 배치해야 합니다. 에서 참조하는 메모리 컨텍스트multi_call_memory_ctx다음까지 생존해야 하는 모든 데이터에 적합한 위치입니다.SRF실행이 완료되었습니다. 대부분의 경우 이는 다음으로 전환해야 함을 의미합니다.multi_call_memory_ctx첫 번째 호출 설정을 수행하는 동안. 메이저 토토 사이트funcctx-user_fctx그러한 교차 호출 데이터 구조에 대한 포인터를 보유합니다. (귀하가 할당한 데이터multi_call_memory_ctx쿼리가 끝나면 자동으로 사라지므로 해당 데이터를 수동으로 해제할 필요도 없습니다.)
함수에 대한 실제 인수는 호출 사이에 변경되지 않은 채로 남아 있지만, 인수 값을 삭제하면(일반적으로 다음에서 투명하게 수행됩니다.PG_GETARG_매크로) 임시 컨텍스트에서 삭제된 복사본은 각 주기에서 해제됩니다. 따라서 해당 값에 대한 참조를 유지하는 경우xxxuser_fctx, 이를 다음 중 하나에 복사해야 합니다.multi_call_memory_ctx삭제 후 또는 해당 컨텍스트에서만 값을 삭제하도록 하세요.
완전한 의사 코드 예는 다음과 같습니다:
데이텀
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, 결과);
그렇지 않으면
/* 여기서는 항목 반품이 완료되었으므로 해당 사실만 보고하세요. */
/* (여기에 정리 코드를 넣으려는 유혹을 참으세요.) */
SRF_RETURN_DONE(funcctx);
간단한 예제의 완전한 예SRF복합 유형을 반환하는 방법은 다음과 같습니다:
PG_FUNCTION_INFO_V1(재합성);
데이텀
재합성(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) != TYPEFUNC_COMPOSITE)
ereport(오류,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("컨텍스트에서 호출된 레코드를 반환하는 함수 "
"유형 기록을 받아들일 수 없습니다.")));
/*
* 나중에 원시에서 튜플을 생성하는 데 필요한 속성 메타데이터를 생성합니다.
* 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 **값;
HeapTuple 튜플;
데이텀 결과;
/*
* 반환된 튜플을 구축하기 위한 값 배열을 준비합니다.
* 이것은 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(values[1], 16, "%d", 2 * PG_GETARG_INT32(1));
snprintf(값[2], 16, "%d", 3 * PG_GETARG_INT32(1));
/* 튜플 만들기 */
tuple = BuildTupleFromCStrings(attinmeta, 값);
/* 튜플을 데이텀으로 만듭니다 */
결과 = HeapTupleGetDatum(tuple);
/* 정리(실제로는 필요하지 않음) */
pfree(값[0]);
pfree(값[1]);
pfree(값[2]);
pfree(값);
SRF_RETURN_NEXT(funcctx, 결과);
else /* 더 이상 남지 않았을 때 수행 */
SRF_RETURN_DONE(funcctx);
SQL에서 이 함수를 선언하는 한 가지 방법은 다음과 같습니다:
CREATE TYPE __retcomposite AS (f1 정수, f2 정수, f3 정수);
CREATE OR REPLACE FUNCTION retcomposite(정수, 정수)
SETOF __retcomposite를 반환합니다.
그대로 '파일 이름', '재합성'
언어 C 불변 STRICT;
다른 방법은 OUT 매개변수를 메이저 토토 사이트하는 것입니다:
함수 생성 또는 교체 retcomposite(IN 정수, IN 정수,
OUT f1 정수, OUT f2 정수, OUT f3 정수)
SETOF 레코드를 반환합니다.
그대로 '파일 이름', '재합성'
언어 C 불변 STRICT;
이 메소드에서 함수의 출력 유형은 공식적으로 익명입니다.기록유형.
C 언어 함수는 다형성 유형을 허용하고 반환하도록 선언될 수 있습니다.모든 요소, 모든 배열, anynonarray, anyenum및아무범위. 참조섹션 38.2.580559_80830fmgr.h버전 1 C 함수가 인수의 실제 데이터 유형과 반환할 것으로 예상되는 유형을 검색할 수 있도록 합니다. 루틴이 호출됩니다.get_fn_expr_rettype(FmgrInfo *flinfo)그리고get_fn_expr_argtype(FmgrInfo *flinfo, int argnum). 결과 또는 인수 유형 OID를 반환합니다. 또는InvalidOid정보를 메이저 토토 사이트할 수 없는 경우. 구조플린포일반적으로 다음과 같이 액세스됩니다.fcinfo-flinfo. 매개변수argnum0부터 시작합니다.get_call_result_type또한 다음의 대안으로 메이저 토토 사이트할 수 있습니다.get_fn_expr_rettype. 도 있습니다get_fn_expr_variadic, 가변 인수가 배열로 병합되었는지 확인하는 데 메이저 토토 사이트할 수 있습니다. 이는 주로 다음에 유용합니다.VARIADIC "모든"함수, 이러한 병합은 일반 배열 유형을 메이저 토토 사이트하는 가변 함수에 대해 항상 발생했기 때문입니다.
예를 들어, 모든 유형의 단일 요소를 받아들이고 해당 유형의 1차원 배열을 반환하는 함수를 작성한다고 가정해 보겠습니다.
PG_FUNCTION_INFO_V1(make_array);
데이텀
make_array(PG_FUNCTION_ARGS)
배열 유형 *결과;
Oid element_type = get_fn_expr_argtype(fcinfo-flinfo, 0);
데이텀 요소;
bool은 null입니다.
int16 타이플렌;
bool 유형;
문자 유형 정렬;
int ndims;
int 어둡게[MAXDIM];
int lbs[MAXDIM];
if (!OidIsValid(element_type))
elog(ERROR, "입력의 데이터 유형을 결정할 수 없습니다.");
/* 제공된 요소를 가져옵니다. NULL인 경우에 주의하세요. */
isnull = PG_ARGISNULL(0);
만약 (isnull)
요소 = (데이텀) 0;
그렇지 않으면
요소 = PG_GETARG_DATUM(0);
/* 우리는 하나의 차원을 가지고 있습니다 */
ndims = 1;
/* 그리고 하나의 요소 */
희미함[0] = 1;
/* 하한은 1입니다 */
파운드[0] = 1;
/* 요소 유형에 대한 필수 정보 얻기 */
get_typlenbyvalalign(element_type, &typlen, &typbyval, &typalign);
/* 이제 배열을 빌드합니다 */
결과 = constructor_md_array(&element, &isnull, ndims, 희미함, lbs,
요소 유형, typlen, typbyval, typalign);
PG_RETURN_ARRAYTYPE_P(결과);
다음 명령은 함수를 선언합니다.make_arraySQL에서:
CREATE FUNCTION make_array(anyelement) 임의의 배열을 반환합니다.
그대로 '디렉토리/funcs', 'make_array'
언어 C는 변경할 수 없습니다.
C 언어 함수에만 메이저 토토 사이트할 수 있는 다형성의 변형이 있습니다. 해당 함수는 유형의 매개변수를 취하도록 선언될 수 있습니다."아무거나". (이 유형 이름은 SQL 예약어이기도 하므로 큰따옴표로 묶어야 합니다.) 이는 다음과 같이 작동합니다.모든 요소다른 것을 제한하지 않는다는 점을 제외하고"아무거나"인수는 동일한 유형이어야 하며 함수의 결과 유형을 결정하는 데 도움이 되지 않습니다. C 언어 함수는 최종 매개변수를 다음과 같이 선언할 수도 있습니다.VARIADIC "모든". 이는 모든 유형(반드시 동일한 유형일 필요는 없음)의 하나 이상의 실제 인수와 일치합니다. 이러한 주장은 다음과 같습니다.아님일반 가변 함수에서 발생하는 것처럼 배열로 수집됩니다. 그들은 단지 함수에 별도로 전달될 것입니다.PG_NARGS()84517_84709VARIADIC함수가 배열 요소를 별도의 인수로 처리할 것이라는 기대와 함께 함수 호출에 키워드를 추가합니다. 함수 자체는 원하는 경우 다음을 메이저 토토 사이트한 후 해당 동작을 구현해야 합니다.get_fn_expr_variadic실제 인수가 다음으로 표시되었음을 감지합니다.VARIADIC.
일부 함수 호출은 함수에 특정한 속성을 기반으로 계획하는 동안 단순화될 수 있습니다. 예를 들어,int4mul(n, 1)다음과 같이 단순화될 수 있습니다.n. 이러한 함수별 최적화를 정의하려면 다음을 작성하세요.변환 함수그리고 OID를 다음 위치에 배치프로트랜폼주요 기능의 필드pg_proc항목. 변환 함수에는 SQL 서명이 있어야 합니다.protransform(내부) 내부 반환. 실제로 논쟁은FuncExpr *은 기본 함수에 대한 호출을 나타내는 더미 노드입니다. 식 트리에 대한 변환 함수의 연구를 통해 단순화된 식 트리가 표현된 모든 가능한 구체적인 호출을 대체할 수 있음이 입증되면 해당 단순화된 식을 작성하고 반환합니다. 그렇지 않으면 a를 반환합니다.NULL포인터 (아님SQL null).
우리는 그것을 보장하지 않습니다포스트그레SQL변환 함수가 단순화될 수 있는 경우 기본 함수를 호출하지 않습니다. 단순화된 표현식과 기본 함수에 대한 실제 호출 간의 엄격한 동등성을 확인하세요.
현재 이 기능은 보안 문제로 인해 SQL 수준에서 메이저 토토 사이트자에게 노출되지 않으므로 내장 기능을 최적화하는 데에만 실용적입니다.
추가 기능은 서버 시작 시 LWLocks 및 공유 메모리 할당을 예약할 수 있습니다. 추가 기능의 공유 라이브러리는 다음에 지정하여 미리 로드해야 합니다.shared_preload_libraries. 공유 메모리는 다음을 호출하여 예약됩니다.
void RequestAddinShmemSpace(int 크기)
당신으로부터_PG_init함수.
LWLock은 다음을 호출하여 예약됩니다.
void RequestNamedLWLockTranche(const char *tranche_name, int num_lwlocks)
에서_PG_init. 이렇게 하면 다음의 배열이 보장됩니다.num_lwlocksLWLocks는 이름으로 메이저 토토 사이트 가능tranche_name. 메이저 토토 사이트GetNamedLWLockTranche이 배열에 대한 포인터를 얻으려면.
가능한 경쟁 조건을 방지하려면 각 백엔드에서 LWLock을 메이저 토토 사이트해야 합니다.AddinShmemInitLock여기에 표시된 대로 공유 메모리 할당에 연결하고 초기화할 때:
정적 mystruct *ptr = NULL;
만약 (!ptr)
부울이 발견되었습니다.
LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE);
ptr = ShmemInitStruct("내 구조체 이름", 크기, &found);
만약 (!발견)
shmem 영역의 내용을 초기화합니다.
다음을 메이저 토토 사이트하여 요청된 LWLock을 획득합니다.
ptr-locks = GetNamedLWLockTranche("내 트랜치 이름");
LWLockRelease(AddinShmemInitLock);
비록PostgreSQL백엔드는 C로 작성되었습니다. 다음 지침을 따르면 C++로 확장을 작성할 수 있습니다.
백엔드에서 액세스하는 모든 기능은 백엔드에 C 인터페이스를 제공해야 합니다. 그런 다음 이러한 C 함수는 C++ 함수를 호출할 수 있습니다. 예를 들어,외부 C89493_89650
적절한 할당 해제 방법을 메이저 토토 사이트하여 메모리를 확보하십시오. 예를 들어 대부분의 백엔드 메모리는 다음을 메이저 토토 사이트하여 할당됩니다.팔록(), 그러니 메이저 토토 사이트하세요pfree()해제합니다. C++ 메이저 토토 사이트삭제이러한 경우에는 실패합니다.
예외가 C 코드로 전파되는 것을 방지합니다(모두의 최상위 수준에서 포괄적 블록을 메이저 토토 사이트합니다.외부 C함수). 이는 C++ 코드가 명시적으로 예외를 발생시키지 않는 경우에도 필요합니다. 메모리 부족과 같은 이벤트는 여전히 예외를 발생시킬 수 있기 때문입니다. 모든 예외를 포착하고 적절한 오류를 C 인터페이스로 다시 전달해야 합니다. 가능하다면 다음을 메이저 토토 사이트하여 C++를 컴파일하세요.-fno-예외예외를 완전히 제거합니다. 그러한 경우에는 C++ 코드에서 오류가 있는지 확인해야 합니다(예:에서 반환된 NULL 확인).신규().
C++ 코드에서 백엔드 함수를 호출하는 경우 C++ 호출 스택에 일반 기존 데이터 구조만 포함되어 있는지 확인하세요(POD). 백엔드 오류로 인해 먼 거리가 생성되기 때문에 이는 필요합니다.longjmp()POD가 아닌 개체가 포함된 C++ 호출 스택을 제대로 풀지 않습니다.
요약하자면 C++ 코드를 벽 뒤에 배치하는 것이 가장 좋습니다.외부 C백엔드와 인터페이스하고 예외, 메모리 및 호출 스택 누출을 방지하는 함수입니다.