| 토토 커뮤니티 9.3.25 문서화 | ||||
|---|---|---|---|---|
| PostgreSQL : 문서 : 9.3 : 토토 핫 기능 | Postgre토토 사이트 추천 : 문서 : 9.3 : 토토 사이트 추천 확장 | 35 장. 확장SQL | 다음 | |
토토 커뮤니티자 정의 함수는 C (또는 언어로 작성할 수 있습니다. C ++와 같은 C와 호환 될 수 있습니다). 그러한 기능은입니다 동적으로로드 가능한 객체 (공유라고도합니다 라이브러리) 및 주문형 서버에 의해로드됩니다. 역학 로딩 기능은 구별되는 것입니다"c 언어"기능"내부"functions — 실제 코딩 규칙 본질적으로 둘 다 동일합니다. (따라서 표준 내부 함수 라이브러리는 코딩 예제의 풍부한 소스입니다. 토토 커뮤니티자 정의 C 함수.)
현재 두 개의 다른 통화 규칙이 c 기능. 최신"버전 1"전화 컨벤션은 A를 작성하여 표시됩니다.pg_function_info_v1 ()매크로 기능을 요청합니다. 아래 그림과 같이. 그러한 매크로의 부족은 구식을 나타냅니다 ("버전 0") 함수. 언어 지정된 이름함수 만들기isC두 경우 모두. 구식 기능입니다 이제 이식성 문제와 부족으로 인해 더 이상 토토 커뮤니티되지 않습니다 기능이지만 여전히 호환성을 위해 지원됩니다 이유.
처음로드 가능한 토토 커뮤니티자 정의 기능 객체 파일은 세션에서 호출되며 동적 로더가로드됩니다. 기능을 호출 할 수 있도록 객체 파일을 메모리로. 그만큼함수 생성토토 커뮤니티자 정의 된 경우 c 따라서 함수는 기능 :로드 가능한 객체 파일의 이름과 C 이름 해당 개체 내에서 호출 할 특정 함수의 (링크 기호) 파일. C 이름이 명시 적으로 지정되지 않은 경우 가정됩니다. SQL 기능 이름과 동일합니다.
다음 알고리즘은 공유 객체 파일을 찾는 데 토토 커뮤니티됩니다. 에 주어진 이름에 따라생성 기능명령 :
이름이 절대 경로이면 해당 파일이 로드됩니다.
이름이 문자열로 시작하면$ libdir, 그 부분은로 대체됩니다.토토 커뮤니티패키지 라이브러리 디렉토리 이름, 빌드 시간에 결정됩니다.
이름에 디렉토리 부분이 포함되어 있지 않으면 파일은 구성 변수에 의해 지정된 경로에서 검색dynamic_library_path.
그렇지 않으면 파일은 경로에서 발견되지 않았거나 비 통신 디렉토리 부분), 동적 로더는 주어진 이름은 실패 할 가능성이 높습니다. (신뢰할 수 없습니다 현재 작업 디렉토리에 의존하려면.)
이 시퀀스가 작동하지 않으면 플랫폼 별 공유 라이브러리 파일 이름 확장 (종종.so) 주어진 이름에 추가 되며이 시퀀스는 다시 시도됩니다. 만약에 그것은 또한 실패하면 부하가 실패합니다.
공유 라이브러리를 찾는 것이 좋습니다$ libdir또는 동적 라이브러리를 통한 길. 새 설치가 있으면 버전 업그레이드를 단순화합니다 다른 위치에서. 실제 디렉토리$ libdirstand는 명령으로 찾을 수 있습니다PG_CONFIG --pkglibdir.
토토 커뮤니티자 IDPostgreSQL서버가 파일로가는 경로를 가로 질러 실행됩니다. 로드하려고합니다. 파일 또는 더 높은 수준의 디렉토리를 만들지 않습니다 읽기 가능 및/또는 실행 가능하지 않음Postgres토토 커뮤니티자는 일반적인 실수입니다.
어쨌든에 나와있는 파일 이름은함수 만들기명령은 문자 그대로 기록됩니다 시스템 카탈로그, 따라서 파일을 다시로드 해야하는 경우 절차가 적용됩니다.
참고 : PostgreSQL의지 C 기능을 자동으로 컴파일하지 마십시오. 객체 파일은이어야합니다 a에 참조되기 전에 편집생성 기능명령. 보다섹션 35.9.6추가 정보는
동적으로로드 된 객체 파일이로드되지 않도록 호환되지 않는 서버로PostgreSQL파일에 A가 포함되어 있는지 확인합니다"매직 블록"적절한 내용물. 이를 통해 서버는 명백한 것을 감지 할 수 있습니다 다른 전공에 대해 컴파일 된 코드와 같은 비 호환성 의 버전PostgreSQL. 마법 블록이 필요합니다PostgreSQL8.2. 마법 블록을 포함하려면 이것을 하나의 (그리고 하나만) 헤더가 포함 된 후 모듈 소스 파일fmgr.h:
#ifdef pg_module_magic PG_MODULE_MAGIC; #endif
the#ifdef테스트를 생략 할 수 있습니다 코드는 8.2 이전에 컴파일 할 필요가 없습니다PostgreSQL릴리스.
처음으로 토토 커뮤니티 된 후 동적으로로드 된 객체 파일은 메모리에 유지됩니다. 같은 세션에서 향후 전화 이 파일의 함수는 작은 오버 헤드 만 발생합니다. 기호 테이블 조회. 객체를 다시로드 해야하는 경우 예를 들어, 다시 컴파일 한 후에는 신선한 세션을 시작합니다.
선택적으로 동적으로로드 된 파일에는 초기화가 포함될 수 있습니다
및 마무리 기능. 파일에 이름 함수가 포함 된 경우_pg_init, 그 함수가 될 것입니다
파일을로드 한 직후에 호출됩니다. 함수는 No를받습니다
매개 변수 및 void를 반환해야합니다. 파일에 함수가 포함 된 경우
이름_pg_fini, 그 함수가 될 것입니다
파일을 내리기 직전에 호출됩니다. 마찬가지로,
함수는 매개 변수를 수신하지 않으며 void를 반환해야합니다. 참고_PG_fini동안 만 호출됩니다
프로세스 종료 중에는 파일의 언로드. (현재,
언로드는 비활성화되어 발생하지 않지만 이는 변경 될 수 있습니다.
미래.)
토토 커뮤니티language functions를 작성하는 방법을 알아하려면 방법을 알아야합니다PostgreSQL내부적으로 대표합니다 기본 데이터 유형 및 기능으로 전달할 수있는 방법. 내부,PostgreSQL기본 유형으로"기억의 블로브". 그만큼 유형을 차례로 정의하는 토토 커뮤니티자 정의 함수는 정의합니다. 그 방법PostgreSQLcan 그것에 작동합니다. 즉,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. 참조테이블 35-1.)
반면에, 모든 크기의 고정 길이 유형을 전달할 수 있습니다. 회의 별. 예를 들어 다음은 A의 샘플 구현이 있습니다.PostgreSQL유형 :
/ * 16 바이트 구조, 참조로 통과 */
typedef struct
더블 X, y;
가리키다;
그러한 유형에 대한 포인터 만 전달할 때 토토 커뮤니티할 수 있습니다. 에서PostgreSQL기능. 에게 그러한 유형의 값을 반환하고 적절한 양의 메모리를 할당하십시오. 와 함께Palloc, 할당 된 메모리를 채우고, 그리고 포인터를 반환하십시오. (또한, 당신이 그냥 반환하고 싶다면 동일한 데이터의 입력 인수 중 하나와 동일한 값 유형, 추가를 건너 뛸 수 있습니다Palloc및 포인터를 입력 값으로 반환합니다.)
마지막으로 모든 가변 길이 유형도 전달해야합니다 참조. 모든 가변 길이 유형은 불투명으로 시작해야합니다 정확히 4 바이트의 길이 필드.set_varsize; 이 필드를 직접 설정하지 마십시오! 모든 데이터 해당 유형 내에 저장하려면 메모리에 위치해야합니다. 그 길이 필드 바로 뒤에. 길이 필드에는 포함됩니다 구조의 총 길이, 즉 크기가 포함됩니다. 길이 필드 자체.
또 다른 중요한 요점은 초기화되지 않은 상태를 떠나는 것을 피하는 것입니다 데이터 유형 값 내 비트; 예를 들어, 제로를 조심하십시오 스트러크에 존재할 수있는 모든 정렬 패딩 바이트. 이것 없이는 데이터 유형의 논리적으로 동등한 상수 플래너에 의해 불평등 한 것으로 보이며 비효율적으로 이어질 수 있습니다. (틀린 것은 아니지만) 계획.
| 경고 |
|
절대수정 통과 참조 입력 값의 내용. 당신이 그렇게한다면 당신은입니다 포인터가 주어진 이후 온 디스크 데이터를 손상시킬 가능성이 있습니다. 디스크 버퍼를 직접 가리킬 수 있습니다. 이것에 대한 유일한 예외 규칙이 설명되어PostgreSQL : 문서 : 9.3 : 사용자 정의 토토 캔. |
예를 들어, 유형을 정의 할 수 있습니다텍스트다음과 같이 :
typedef struct
int32 길이;
숯 데이터 [1];
텍스트;
분명히, 여기에 선언 된 데이터 필드는 충분히 길지 않습니다. 가능한 모든 문자열을 고정하십시오. 선언하는 것은 불가능하기 때문에 가변 크기 구조에서C, 우리 지식에 의존C컴파일러는 배열 첨자 범위를 범합니다. 우리는 단지 할당됩니다 필요한 공간을 마치 마치 배열에 액세스합니다. 올바른 길이를 선언했습니다. (이것은 당신이 할 수있는 일반적인 트릭입니다 C.)에 대한 많은 교과서에서 읽으십시오.
가변 길이 유형을 조작 할 때 조심해야합니다 올바른 양의 메모리를 할당하고 길이 필드를 설정하십시오. 바르게. 예를 들어, 40 바이트를 A에 저장하고 싶다면텍스트구조, 코드를 토토 커뮤니티할 수 있습니다 이와 같은 조각 :
#include "postgres.h" ... 숯 버퍼 [40]; / * 소스 데이터 */ ... 텍스트 *대상 = (텍스트 *) palloc (varhdrsz + 40); set_varsize (대상, varhdrsz + 40); memcpy (대상- 데이터, 버퍼, 40); ...
varhdrszsizeof (int32)이지만 토토 커뮤니티하기에 좋은 스타일로 간주됩니다 매크로varhdrsz의 크기를 참조합니다 가변 길이 유형의 오버 헤드. 또한 길이 필드필수를 토토 커뮤니티하여 설정하십시오set_varsize간단한 것이 아니라 매크로 과제.
표 35-1쓸 때 어떤 c 유형이 어떤 SQL 유형에 해당하는지 지정합니다. 내장 유형의를 토토 커뮤니티하는 c- 언어 함수PostgreSQL. 그만큼"정의 안에"열이 포함되어야하는 헤더 파일을 제공합니다. 유형 정의를 얻으려면. (실제 정의는 a에있을 수 있습니다 나열된 파일에 포함 된 다른 파일. 그것은 토토 커뮤니티자가 정의 된 인터페이스를 고수하는 것이 좋습니다.) 당신은 항상 포함해야합니다postgres.h먼저 모든 소스 파일에서 여러 가지를 선언하기 때문에 어쨌든 당신은 필요합니다.
표 35-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) | int16 | postgres.h |
| int2vector | int2vector* | postgres.h |
| Integer (int4) | int32 | postgres.h |
| Real (float4) | float4* | postgres.h |
| 이중 정밀 (float8) | float8* | postgres.h |
| 간격 | 간격* | DataType/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 |
| 타임 스탬프 | 타임 스탬프* | DataType/Timestamp.h |
| TinterVal | TimeInterval | utils/nabstime.h |
| Varchar | Varchar* | postgres.h |
| xid | TransactionId | postgres.h |
이제 우리는베이스를위한 가능한 모든 구조를 살펴 보았습니다. 유형, 우리는 실제 기능의 몇 가지 예를 보여줄 수 있습니다.
우리는를 발표합니다."구식"전화 컨벤션 먼저 -이 접근법은 이제 더 이상 토토 커뮤니티되지 않았지만 처음에 처리하기가 더 쉽습니다. 버전 -0 메소드에서 C 함수의 인수와 결과는 정상으로 선언됩니다. C 스타일이지만 각 SQL의 C 표현을 토토 커뮤니티해야합니다. 위와 같이 데이터 유형.
다음은 몇 가지 예입니다:
#include "postgres.h"
#include <string.h
#include "utils/geo_decls.h"
#ifdef pg_module_magic
PG_MODULE_MAGIC;
#endif
/ * 가치 별 */
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));
set_varsize (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);
set_varsize (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"의 오버로드에 유의하세요.
CREATE FUNCTION 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이 방법. 또한 Null 결과를 반환하는 간단한 방법은 없습니다. 널 주장에 대처하기 위해 기능 엄격한 기능. 다음에 발표 된 버전 -1 컨벤션 이 반대 의견을 극복합니다.
버전 -1 컨벤션은 매크로에 의존하여 억제합니다 통과 논쟁과 결과의 복잡성의 대부분. c 버전 1 기능의 선언은 항상 :
Datum funcname (pg_function_args)
또한 매크로 호출 :
pg_function_info_v1 (funcname);
동일한 소스 파일에 나타나야합니다. (전통적으로, 그것은입니다 함수 자체 직전에 작성되었습니다.)이 매크로 호출은 아닙니다. 필요내부-언어 함수, 부터PostgreSQL그 모든 것을 가정합니다 내부 기능은 버전 -1 컨벤션을 토토 커뮤니티합니다. 그러나 그것은 동적으로로드 된 함수에 필요합니다.
버전 -1 함수에서 각 실제 인수는 a를 토토 커뮤니티하여 가져옵니다pg_getarg_xxx()매크로에 해당합니다
Argument의 데이터 유형 및 결과는 a를 토토 커뮤니티하여 반환됩니다.pg_return_xxx()반환 유형의 매크로.pg_getarg_xxx()숫자는 그 숫자로 인수합니다
카운트가 0에서 시작되는 기능 인수의 인수 중pg_return_xxx()실제 논쟁으로 취합니다
반품 가치.
여기서 우리는 Version-1에 코딩 된 위와 동일한 함수를 보여줍니다. 스타일:
#include "postgres.h"
#include <string.h
#include "fmgr.h"
#include "utils/geo_decls.h"
#ifdef pg_module_magic
PG_MODULE_MAGIC;
#endif
/ * 가치 별 */
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));
set_varsize (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);
set_varsize (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 코딩 규칙이 나타날 수 있습니다
무의미한 모호함이되기 위해. 그러나 그들은 숫자를 제공합니다
매크로가 불필요한 세부 사항을 숨길 수 있기 때문에 개선 사항. an
예를 들어 코딩에서add_one_float8, 더 이상 알 필요가 없습니다
저것float8는 추천 유형입니다.
또 다른 예는getarg매크로
가변 길이 유형의 경우보다 효율적으로"토스트"(압축 또는 외부인)
값.
버전 1 기능의 큰 개선은 더 나은 처리입니다.
널 입력 및 결과. 매크로PG_ARGISNULL (n)함수가 각 입력이 null인지 테스트 할 수 있습니다. (물론,
이렇게하는 것은 선언되지 않은 기능에서만 필요합니다"엄격한".)와 마찬가지로pg_getarg_xxx()매크로, 입력 인수는 0에서 시작됩니다. 메모
그 사람은 실행을 자제해야합니다pg_getarg_xxx()인수가 무효가 아님을 확인할 때까지. a
null 결과, 실행pg_return_null (); 이것은 엄격한 것과 모두에서 작동합니다
nampondrict 기능.
새로운 스타일 인터페이스에 제공된 다른 옵션은 2입니다
의 변형pg_getarg_xxx()매크로. 이 중 첫 번째,pg_getarg_xxx_copy (), a
글을 쓰는 데 안전한 지정된 인수의 사본. (그만큼
일반 매크로는 때때로 값으로 포인터를 반환합니다.
물리적으로 테이블에 저장되며, 작성해서는 안됩니다. 토토 커뮤니티
그만큼pg_getarg_xxx_copy ()매크로는 a
쓰기 가능한 결과.) 두 번째 변형은로 구성됩니다.pg_getarg_xxx_slice ()3 개를 차지하는 매크로
논쟁. 첫 번째는 기능 인수의 수입니다 (
위에). 두 번째와 세 번째는 오프셋과 길이입니다.
반환 할 세그먼트. 오프셋은 0에서 계산됩니다
음의 길이는 나머지 값이
반환. 이 매크로는 일부에 대한보다 효율적인 액세스를 제공합니다
스토리지 유형이있는 경우 큰 값"외부". (열의 저장 유형은 될 수 있습니다
토토 커뮤니티 지정Alter TableTableNameAlter ColumnColname스토리지 설정StorageType. StorageType중 하나입니다일반, 외부, 확장, 또는Main.)
마지막으로 버전 -1 기능 호출 규칙이이를 만듭니다 설정 결과를 반환 할 수 있습니다 (섹션 35.9.9) 및 구현 트리거 함수 (토토 사이트 : 문서 : 9.3 : 트리거) 및 절차 적 통화 처리기 (PostgreSQL : 문서 : 9.3 : 절차 언어 스포츠 토토 결과 작성). 버전 1 코드는 버전 -0보다 휴대가 가능합니다. 기능 통화 프로토콜에서 제한을 깨뜨리지 않기 때문에 C 표준. 자세한 내용은 참조src/backend/utils/fmgr/readme소스에서 분포.
보다 진보 된 주제로 돌아 가기 전에 논의해야합니다. 일부 코딩 규칙PostgreSQL토토 커뮤니티language functions. 함수를로드하는 것이 가능할 수 있습니다 C로 C 이외의 언어로 작성PostgreSQL, 이것은 일반적으로 어렵다 (경우 C ++, Fortran과 같은 다른 언어가 있기 때문에 전혀 가능합니다. 또는 Pascal은 종종 C와 동일한 통화 협약을 따르지 않습니다. 즉, 다른 언어는 인수와 반환 가치를 전달하지 않습니다. 같은 방식으로 함수 사이. 이러한 이유로 우리는 가정 할 것입니다 당신의 c- 언어 함수는 실제로 C로 작성되었습니다.
C 기능 작성 및 구축을위한 기본 규칙은 다음과 같습니다. 다음은 다음과 같습니다.
토토 커뮤니티PG_CONFIG-includeDir-ServerTO 어디서 찾기PostgreSQL서버 헤더 파일이 시스템에 설치됩니다 (또는 시스템 토토 커뮤니티자가 실행할 것임).
동적으로 코드를 컴파일하고 연결하십시오. 로드PostgreSQL항상 특별한 깃발이 필요합니다. 보다섹션 35.9.6특정 운영 체제.
a 정의하는 것을 잊지 마십시오."매직 블록"공유 라이브러리의 경우섹션 35.9.1.
메모리를 할당 할 때를 토토 커뮤니티하십시오.PostgreSQL기능Pallocandpfree해당 C 라이브러리 기능 대신Malloc및무료.
에 의해 할당 된 메모리Palloc의지
각 거래가 끝날 때 자동으로 해제되어 방지합니다.
메모리 누출.
항상 구조물의 바이트를 항상 0memset(또는 그와 함께 할당Palloc0처음에는). 당신이 할당하더라도
구조의 각 필드에 정렬 패딩이있을 수 있습니다.
(구조물의 구멍) 쓰레기 값을 포함하는 (구조). 이것 없이는
해시 인덱스 또는 해시 조인을 지원하기가 어렵습니다.
데이터 구조의 상당한 비트 만 선택하십시오.
해시를 계산하십시오. 플래너는 때때로 비교에 의존합니다
비트 타이어 평등을 통한 상수이므로 바람직하지 않은 계획을 얻을 수 있습니다.
논리적으로 동등한 값이 조금 같지 않은 경우 결과.
대부분의 내부PostgreSQL유형은postgres.h, 그동안 함수 관리자 인터페이스(PG_FUNCTION_ARGS등)fmgr.h, 따라서 최소한 다음을 포함해야 합니다. 두 개의 파일. 이식성을 위해 다음을 포함하는 것이 가장 좋습니다.postgres.h 첫 번째, 다른 시스템 또는 토토 커뮤니티자 헤더 파일. 포함postgres.h포함elog.h및palloc.h당신을 위해.
객체 파일 내에 정의 된 기호 이름은 충돌해서는 안됩니다. 서로 또는에 정의 된 기호와 함께PostgreSQL서버 실행 가능. 당신은해야 할 것입니다 오류 메시지가 이 효과.
토토 커뮤니티하기 전에PostgreSQLC로 작성된 확장 기능 파일을 생성하기 위해 특별한 방법으로 컴파일되고 연결되어야합니다. 서버에서 동적으로로드 할 수 있습니다. 정확히 말하면, a공유 라이브러리생성해야합니다.
이 섹션에 포함 된 것 이상의 정보는 귀하에게 운영 체제의 문서를 읽어야합니다 특히 C 컴파일러의 수동 페이지,CC및 링크 편집기,LD. 또한PostgreSQL소스 코드에는 여러 가지가 포함되어 있습니다 의 작업 예제Contrib디렉토리. 이 예제에 의존하면 모듈을 만듭니다. 의 가용성에 따라PostgreSQL소스 코드.
공유 라이브러리 생성은 일반적으로 연결과 유사합니다 실행 파일 : 먼저 소스 파일이 객체 파일로 컴파일됩니다. 그런 다음 객체 파일이 함께 연결됩니다. 객체 파일이 필요합니다 로 만들어집니다.위치 독립 코드 (PIC)는 개념적으로 의미합니다 그들은 기억의 임의의 위치에 배치 될 수 있습니다. 그들은 실행 파일에 의해로드됩니다. (객체 파일 실행 파일은 일반적으로 그런 식으로 컴파일되지 않습니다.) 링크 명령 공유 라이브러리에는 특수 플래그가 포함되어 있습니다. 실행 파일 연결 (적어도 이론적으로는 일부 시스템에서 연습은 훨씬 더 못생적입니다).
다음 예에서는 소스 코드가 파일foo.c그리고 우리는 공유를 만들 것입니다 도서관foo.so. 중간 물체 파일은라고합니다.foo.o그렇지 않으면 언급되었습니다. 공유 라이브러리에는 하나 이상의 객체가 포함될 수 있습니다 파일이지만 여기에만 토토 커뮤니티합니다.
생성 할 컴파일러 플래그PICis-fpic. 생성합니다 공유 라이브러리 컴파일러 플래그는-shared.
gcc -fpic -c foo.c gcc -shared -o foo.so foo.o
버전 3.0에서 적용 가능freebsd.
생성 할 시스템 컴파일러의 컴파일러 플래그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공유 라이브러리의 경우 대부분과 달리 기타 시스템.
PIC기본값입니다 특수 컴파일러 옵션이 필요합니다. 링커 옵션 공유 라이브러리 생산은-shared.
CC -C FOO.C ld -shared -o foo.so foo.o
생성 할 컴파일러 플래그PICis-fpic. 그만큼 공유 라이브러리를 생성하려는 컴파일러 플래그-shared. 완전한 예는 다음과 같습니다.
cc -fpic -c foo.c cc -shared -o foo.so foo.o
예는 다음과 같습니다. 개발자 도구가 있다고 가정합니다 설치.
CC -C foo.c CC -BUNDLE -FLAT_NAMESPACE- 정의 된 억제 -o foo.so foo.o
생성 할 컴파일러 플래그PICis-fpic. 을 위한ELF시스템, 컴파일러 깃발-shared공유 링크에 토토 커뮤니티됩니다 도서관. 이전 비 ELF 시스템에서ld -Bsharable토토 커뮤니티됩니다.
gcc -fpic -c foo.c gcc -shared -o foo.so foo.o
생성 할 컴파일러 플래그PICis-fpic. ld -Bsharable공유 링크에 토토 커뮤니티됩니다 도서관.
gcc -fPIC -c foo.c ld -Bshareable -o foo.so foo.o
생성 할 컴파일러 플래그PICis-kpic선 컴파일러 및-fpicwithGCC. 공유 라이브러리를 연결하려면 컴파일러를 연결합니다 옵션은입니다.-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
PIC기본값입니다 컴파일 명령은 일반적인 것입니다.LD특별 옵션과 함께 연결을 수행하는 데 토토 커뮤니티됩니다.
CC -C FOO.C ld -shared -expect_unresolved '*'-o foo.so foo.o
동일한 절차가 시스템 대신 GCC와 함께 토토 커뮤니티됩니다. 컴파일러; 특별한 옵션이 필요하지 않습니다.
생성 할 컴파일러 플래그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)에서 생략 할 수 있습니다함수 만들기명령, 일반적으로 최고의 휴대 성을 위해 생략.
다시 참조섹션 35.9.1서버가 공유를 찾을 것으로 예상되는 위치에 대한 정보 도서관 파일.
복합 유형에는 C 구조와 같은 고정 레이아웃이 없습니다. 복합 유형의 인스턴스에는 널 필드가 포함될 수 있습니다. 게다가, 상속 계층의 일부인 복합 유형은 같은 상속의 다른 구성원과는 다른 필드 계층. 그러므로,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 () */
#ifdef pg_module_magic
PG_MODULE_MAGIC;
#endif
부
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 () */
#ifdef pg_module_magic
PG_MODULE_MAGIC;
#endif
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입니다.getAttributeByNamea 반환Datum적절한 데이터로 변환 할 수있는 값
적절한 토토 커뮤니티으로 입력Datumgetxxx()매크로. 널 플래그가 있으면 반환 값은 의미가 없습니다.
설정되어 있습니다. 무엇이든 시도하기 전에 항상 널 깃발을 확인하십시오.
결과와 함께.
또한getAttributeBynum,
대상 속성을 대신 열 번호로 선택합니다.
이름.
다음 명령은 함수를 선언합니다c_overpaidsql :
함수 만들기 C_OVERPAID (EMP, Integer)는 부울을 반환합니다
처럼 '디렉토리/funcs ','c_overpaid '
언어 C 엄격한;
우리가 토토 커뮤니티한 통지엄격한그래서 우리 입력 인수가 무효인지 확인할 필요가 없었습니다.
c- 언어에서 행 또는 복합 유형 값을 반환하려면 기능, 매크로를 제공하는 특수 API를 토토 커뮤니티할 수 있으며 제작 복합 데이터의 복잡성 대부분을 숨기는 기능 유형. 이 API를 토토 커뮤니티하려면 소스 파일에는 다음을 포함해야합니다.
#include "funcapi.h"
복합 데이터 값을 구축 할 수있는 두 가지 방법이 있습니다.
(따라서 A"튜플") : 구축 할 수 있습니다
Datum 값의 배열 또는 C 문자열 배열에서
튜플의 입력 변환 함수로 전달 될 수 있습니다.
열 데이터 유형. 두 경우 모두 또는 먼저 얻어야합니다
a 구성tupledesc디스크립터
튜플 구조. Datums와 함께 일할 때를 통과합니다.tupledesctoBlessTupledesc그리고 전화heap_form_tuple각 행마다. c
끈, 당신은를 통과합니다tupledesctotupledescgetattinmetadata부르다BuildTupleFromCstrings각각
열. 튜플 세트를 반환하는 함수의 경우 설정
첫 번째 호출 중에 단계를 한 번 수행 할 수 있습니다.
기능.
필요한 것을 설정하기 위해 여러 도우미 기능을 토토 커뮤니티할 수 있습니다tupledesc. 권장하는 방법 이것은 대부분의 기능에서 복합 값을 반환하는 것입니다 :
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo,
Oid *resultTypeId,
TupleDesc *resultTupleDesc)
같은 전달fcinfo구조물이 통과되었습니다 호출 함수 자체에. (물론 이것은 당신을 요구합니다 버전 1 전화 컨벤션을 토토 커뮤니티하십시오.)resulttypeid|NULL또는 로컬 변수의 주소로 함수의 결과 유형 OID를받습니다.resultTupledesc지역의 주소 여야합니다tupledesc변수. 그것을 확인하십시오 결과는saptionfunc_composite; 그렇다면,resultTupledesc필요한tupledesc. (그렇지 않다면, 당신 라인을 따라 오류를보고 할 수 있습니다"함수 반환 레코드는 맥락에서 불가능합니다 유형 레코드 수락 ".)
팁 :
get_call_result_type실제 유형의 다형성 기능 결과를 해결할 수 있습니다. 그래서 스칼라 다형성 결과를 반환하는 기능에 유용합니다. 복합재를 반환하는 기능 만. 그만큼resultTypeid출력은 주로 유용합니다 다형성 스칼라를 반환하는 기능.
참고 :
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 문자열로 작업하려는 경우. 당신이 쓰는 경우 a 기능 반환 세트, 이러한 기능의 결과를 저장할 수 있습니다. 에서FUNCCALLCONTEXT구조 - 토토 커뮤니티 그만큼tuple_desc또는Attinmeta필드
Datums에서 작업 할 때 :
heappuple heap_form_tuple (tupledesc tupdesc, datum *값, bool *isnull)
aHeappuple토토 커뮤니티자 데이터가 주어졌습니다 데이텀 형태로.
C 문자열로 작업 할 때 토토 커뮤니티 :
Heaptuple buildtuplefflfflfffromcstrings (Attinmetadata *Attinmeta, char ** value)
aheappuple토토 커뮤니티자 데이터가 주어졌습니다 C 문자열 형태로.값는 C의 배열입니다 문자열, 리턴 행의 각 속성마다 하나씩. 각 C 문자열 입력 함수에 의해 예상되는 형식이어야합니다. 속성 데이터 유형. 중 하나의 널 값을 반환하기 위해 속성,의 해당 포인터값배열을 설정해야합니다null. 이 기능은 다시 호출해야합니다 당신이 반환하는 각 행.
일단 기능에서 돌아 오기 위해 튜플을 구축 한 후에는 A로 변환해야합니다.Datum. 토토 커뮤니티:
HeappupleGetDatum (Heptuple Tuple)
aheappuple유효한 자료. 이것Datum직접 반환 할 수 있습니다 당신은 단일 행만 반환하려고하거나 설정 함수의 현재 반환 값.
다음 섹션에 예제가 나타납니다.
반환을 지원하는 특별한 API도 있습니다. c- 언어 함수에서 세트 (다중 행). 세트 리턴 링 함수는 버전 -1 호출 규칙을 따라야합니다. 또한, 소스 파일 포함funcapi.h, AS 위에.
세트 리턴 기능 (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는 튜플을 반환 할 때 토토 커뮤니티합니다 (즉, 복합 데이터 유형)
* 그리고 당신이 튜플을 만들려고하는 경우에만 필요합니다.
* heap_form_tuple ()가 buildtuplefromcstrings ()를 토토 커뮤니티하지 않고. 주목하십시오
* 여기에 저장된 Tupledesc 포인터는 보통 통과해야합니다.
* FlessTupledesc () 먼저.
*/
tupledesc tuple_desc;
funcCallContext;
anSRF여러 기능을 토토 커뮤니티합니다 자동으로 조작하는 매크로FUNCCALLCONTEXT구조 (그리고 그것을 찾을 것으로 예상됩니다 을 통해fn_extra). 토토 커뮤니티:
srf_is_firstcall ()
첫 번째 또는 A가 호출되는지 확인하려면 후속 시간. 첫 번째 통화에서 (전용) 토토 커뮤니티 :
64692_64714
초기화하려면FUNCCALLCONTEXT. 첫 번째 토토 커뮤니티을 포함하여 모든 기능 호출에서 :
srf_percall_setup ()
토토 커뮤니티을 위해 올바르게 설정하려면FUNCCALLCONTEXT그리고 이전에 지우십시오 이전 패스에서 남은 반환 데이터.
함수가 반환 할 데이터가 있으면 다음을 토토 커뮤니티하십시오.
srf_return_next (funcctx, result)
발신자에게 반환합니다. (결과유형이어야합니다Datum, 단일 값 또는 위에서 설명한 대로 준비된 튜플입니다.) 마지막으로, 함수가 데이터 반환을 마쳤습니다. 다음을 토토 커뮤니티하세요.
srf_return_done (funcctx)
정리하고 끝내려면SRF.
SRF라고 불리는 것은 일시적인 컨텍스트입니다
통화 사이를 지우십시오. 이것은 당신이 전화 할 필요가 없다는 것을 의미합니다pfree할당 된 모든 것에 대해
토토 커뮤니티Palloc; 어쨌든 사라질 것입니다.
그러나, 데이터 구조를 할당하려면
전화, 다른 곳에 두어야합니다. 메모리 컨텍스트
참조multi_call_memory_ctxIS
까지 생존 해야하는 모든 데이터에 적합한 위치SRF가 끝났습니다. 대부분
사례, 이것은 당신이로 전환해야한다는 것을 의미합니다.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 불변의 엄격한;
이 방법에서는 함수의 출력 유형이 공식적으로 익명레코드타입.
디렉토리Contrib/TableFunc소스 분포의 모듈에는 더 많은 예가 포함됩니다 정리 함수.
c-language 함수는
다형성 유형Anylement, AnyArray, AnynonArray, AnyEnum및AnyRange. 보다섹션
35.2.5다형성에 대한 자세한 설명
기능. 기능 인수 또는 반환 유형이 다음과 같이 정의 된 경우
다형성 유형, 기능 저자는 미리 알 수 없습니다.
데이터 유형으로 호출되거나 반환해야합니다. 두 가지가 있습니다
에 제공된 루틴fmgr.h허용 a
버전 -1 C 기능의 실제 데이터 유형을 발견하는 기능
인수와 반환 될 것으로 예상되는 유형. 루틴은입니다
라고 불리는get_fn_expr_rettype (fmgrinfo
*flinfo)andget_fn_expr_argtype (fmgrinfo
*flinfo, int argnum). 결과 또는 인수 유형을 반환합니다
OID, 또는Invalidoid정보가있는 경우
토토 커뮤니티할 수 없습니다. 구조flinfoIS
일반적으로 액세스 됨fcinfo- flinfo.
매개 변수Argnum| 0 기반입니다.get_call_result_type도 토토 커뮤니티할 수 있습니다
대안으로get_fn_expr_rettype. 또한get_fn_expr_variadicVariadic 인수가 배열로 병합되었는지 여부. 이것
주로 유용합니다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 functions : 매개 변수를 가져갈 수 있습니다.
유형"Any". (이 유형 이름은해야합니다
SQL 예약 단어이기 때문에 두 번 인용하십시오.) 이것은 작동합니다.
좋다Anylement그렇지 않은 경우를 제외하고
다른 구속"Any"논쟁
동일한 유형도 기능의 결과를 결정하는 데 도움이되지 않습니다.
유형. c-language 함수는 또한 최종 매개 변수를
BEVariadic "Any". 이것은 하나 또는 일치합니다
모든 유형의 실제 인수 (반드시 같은 유형은 아닙니다).
이 주장은아님정상적인 variadic과 마찬가지로 배열로 모여
기능; 그들은 단지 함수로 별도로 전달됩니다. 그만큼PG_NARGS()매크로 및 방법
위에서 설명한 실제 수를 결정하는 데 토토 커뮤니티해야합니다.
이 기능을 토토 커뮤니티할 때 인수와 그 유형. 또한 토토 커뮤니티자
이러한 함수는를 토토 커뮤니티하고 싶을 수도 있습니다.variadic함수 호출의 키워드
함수가 배열 요소를 다음과 같이 처리 할 것이라고 기대합니다.
별도의 주장. 함수 자체는이를 구현해야합니다
원하는 경우, 토토 커뮤니티 후get_fn_expr_variadic실제를 감지합니다
인수는로 표시되었습니다.variadic.
일부 기능 호출은 계획 중에 단순화 될 수 있습니다. 함수와 관련된 속성. 예를 들어,int4mul (n, 1)그냥 단순화 될 수 있습니다n. 이러한 기능 별 최적화를 정의하려면 a 쓰기변환 함수를 배치하십시오 에서 OIDprotransform필드 기본 기능PG_PROC입력. 그만큼 변환 함수는 SQL 서명이 있어야합니다돌기 (내부) 내부 반환. 그만큼 인수, 실제로funcexpr *, 더미입니다 기본 기능에 대한 호출을 나타내는 노드. 변환이라면 표현 트리에 대한 기능의 연구는 단순화되었음을 증명합니다. 발현 트리는 가능한 모든 콘크리트 호출을 대체 할 수 있습니다 그로 인해 표현 된 표현식을 구축하고 반환합니다. 그렇지 않으면 반환 aNULL포인터 (아님SQL NULL).
우리는 그것을 보장하지 않습니다PostgreSQL1 차를 호출하지 않습니다 변환 함수가 단순화 될 수있는 경우 기능. 단순화 된 표현과 기본 기능에 대한 실제 호출.
현재이 시설은 SQL의 토토 커뮤니티자에게 노출되지 않습니다. 보안 문제로 인해 레벨이므로 토토 커뮤니티하기에만 실용적입니다. 내장 기능 최적화.
추가 인은 LWLOCKS 및 공유 메모리 할당을 예약 할 수 있습니다. 서버 시작시. 애드 인의 공유 라이브러리는 전진해야합니다 지정shared_preload_libraries. 공유 메모리는 다음과 같이 호출하여 예약됩니다.
void requestAdDinshMemsPace (int size)
에서_PG_INIT함수.
LWLOCKS는 다음과 같이 예약됩니다.
void requestAdDinlWlocks (int n)
From_pg_init.
가능한 경주 조건을 피하려면 각 백엔드가 토토 커뮤니티해야합니다
lwlockaddinshmeminitlock언제
공유 메모리 할당에 연결하고 초기화합니다.
여기에 표시 :
정적 mystruct *ptr = null;
if (! ptr)
bool 발견;
lwlockacquire (addinshmeminitlock, lw_excluction);
ptr = shmeminitstruct ( "나의 구조물 이름", 크기, & 발견);
if (! 찾았다)
SHMEM 영역의 내용을 초기화합니다.
다음을 토토 커뮤니티하여 요청 된 LWLOCKS를 획득하십시오.
ptr- mylockid = lwlockassign ();
lwlockrelease (addinshmeminitlock);비록PostgreSQL백엔드 C로 작성되었으며 C ++로 확장자를 작성할 수 있습니다. 가이드 라인이 따릅니다.
백엔드에서 액세스하는 모든 기능은 C 인터페이스를 제공해야합니다. 백엔드에; 이 C 함수는 C ++ 기능을 호출 할 수 있습니다. 을 위한 예,extern c연결이 필요합니다 백엔드 액세스 함수. 이것은 또한 어떤 것도 필요합니다 백엔드와 C ++ 사이의 포인터로 전달되는 기능 암호.
적절한 거래 방법을 토토 커뮤니티한 무료 메모리. 을 위한
예를 들어, 대부분의 백엔드 메모리는를 토토 커뮤니티하여 할당됩니다.palloc (), 토토 커뮤니티pfree ()그것을 제거하려면. C ++ 토토 커뮤니티삭제그러한 경우에는 실패합니다.
예외가 C 코드로 전파되는 것을 방지합니다 (토토 커뮤니티
All의 최상위 수준에서의 모든 블록extern
기음함수). C ++ 코드가 그렇지 않은 경우에도 필요합니다.
메모리 외과 같은 이벤트가 있기 때문에 예외를 명시 적으로 던지십시오
여전히 예외를 던질 수 있습니다. 모든 예외는 잡히야합니다
적절한 오류는 C 인터페이스로 다시 전달되었습니다. 가능하다면
와 함께 C ++ 컴파일-fno-exceptionsto
예외를 완전히 제거하십시오. 이 경우 확인해야합니다
C ++ 코드의 실패 (예 : null을 확인하여new ().
C ++ 코드에서 백엔드 기능을 호출하는 경우 C ++인지 확인하십시오.
콜 스택에는 일반 기존 데이터 구조 만 포함됩니다 (POD). 백엔드 오류로 인해 필요합니다
먼 생성longjmp ()POD 객체가없는 C ++ 통화 스택을 제대로 풀지 않습니다.
요약하면 C ++ 코드를 벽 뒤에 배치하는 것이 가장 좋습니다extern C백엔드, 예외, 메모리를 피하고 스택 누출을 통화하십시오.