사용자 정의 함수는 C (또는 메이저 토토 사이트로 작성할 수 있습니다. C ++와 같은 C와 호환 될 수 있습니다). 그러한 기능은입니다 동적으로로드 가능한 객체 (공유라고도합니다 라이브러리) 및 주문형 서버에 의해로드됩니다. 역학 로딩 기능은 구별되는 것입니다"c 메이저 토토 사이트"함수"내부"함수 --- 실제 코딩 컨벤션은 본질적으로 두 가지 모두 동일합니다. (따라서 표준 내부 기능 라이브러리는 풍부한 코딩 소스입니다. 사용자 정의 C 함수에 대한 예제.)
현재 두 개의 다른 전화 규칙이 c 기능. 최신"버전 1"전화 컨벤션은 A를 작성하여 표시됩니다.pg_function_info_v1 ()매크로 기능을 요청합니다. 아래 그림과 같이. 그러한 매크로의 부족은 구식을 나타냅니다 ( "버전 0") 함수. 지정된 언어 이름함수 만들기isCin 두 경우 모두. 구식 기능은 이제 이상으로 인해 더 이상 사용되지 않습니다 이식성 문제와 기능 부족 호환성 이유를 위해 여전히 지원됩니다.
처음으로 사용자 정의 메이저 토토 사이트이 처음입니다 로드 가능한 객체 파일은 백엔드 세션에서 호출됩니다. 동적 로더는 해당 객체 파일을 메모리에로드하여 메이저 토토 사이트을 호출 할 수 있습니다. 그만큼생성 메이저 토토 사이트사용자 정의 C 함수의 경우 | 함수에 대한 두 가지 정보를 지정합니다. 로드 가능한 객체 파일 및 C 이름 (링크 기호) 해당 객체 파일 내에서 호출 할 특정 기능. c 이름은 명시 적으로 지정되지 않으면 SQL 기능 이름과 동일합니다.
다음 알고리즘은 공유 객체를 찾는 데 사용됩니다. 에 주어진 이름을 기준으로 파일생성 메이저 토토 사이트명령 :
이름이 절대 경로 인 경우 주어진 파일은 짐을 실은.
이름이 문자열로 시작하면$ libdir, 그 부분은로 대체됩니다.PostgreSQL패키지 라이브러리 빌드 타임에 결정된 디렉토리 이름
이름에 디렉토리 부분이없는 경우 파일
구성에 의해 지정된 경로에서 검색됩니다.
변하기 쉬운dynamic_library_path
.
그렇지 않으면 (파일은 경로에서 발견되지 않았습니다. 비 변제 디렉토리 부분), 동적 로더가 포함되어 있습니다 주어진대로 이름을 가져 가려고 할 것입니다. 실패하다. (현재 작업에 의존하는 것은 신뢰할 수 없습니다 예배 규칙서.)
이 시퀀스가 작동하지 않으면 플랫폼 별 공유 라이브러리 파일 이름 확장 (종종.so)는 주어진 이름과 이것에 추가됩니다 시퀀스가 다시 시도됩니다. 그것이 실패하면 부하가 있습니다 실패하다.
참고 :사용자 IDPostgreSQL서버가 가능 해야하는대로 실행됩니다 로드하려는 파일로의 경로를 가로 지르려면. 만들기 파일 또는 더 높은 수준의 디렉토리는 읽을 수없고/또는 에 의해 실행되지 않음Postgres사용자는 일반적인 실수입니다.
어쨌든에 나와있는 파일 이름은함수 만들기명령은 문자 그대로 기록됩니다 시스템이 카탈로그가되므로 파일을 다시로드 해야하는 경우 동일한 절차가 적용됩니다.
참고 : 메이저 토토 사이트C 함수를 자동으로 컴파일하지 않습니다. 대상 파일은 a에 참조되기 전에 컴파일해야합니다.함수 생성명령. 보다섹션 9.5.8추가 정보.
참고 :처음으로 사용 된 후 a 동적으로로드 된 객체 파일은 메모리에 유지됩니다. 향후 같은 세션에서 함수에 대한 호출 파일은 심볼 테이블의 작은 오버 헤드 만 발생합니다. 조회. 객체 파일을 다시로드 해야하는 경우 예를 들어 다시 컴파일 한 후를 사용하십시오.로드신선한 세션을 지휘하거나 시작하십시오.
상대적으로 공유 라이브러리를 찾는 것이 좋습니다 에게$ libdir또는 동적을 통한 도서관 경로. 이것은 새로운 경우 버전 업그레이드를 단순화합니다 설치는 다른 위치에 있습니다. 실제 디렉토리 저것$ libdirstand는 찾을 수 있습니다 명령과 함께PG_CONFIG --pkglibdir.
참고 :전메이저 토토 사이트릴리스 7.2, 정확히 만 객체 파일에 대한 절대 경로는에 지정할 수 있습니다.함수 만들기. 이 접근법은입니다 메이저 토토 사이트 정의를 만들기 때문에 이제는 더 이상 사용되지 않습니다 불필요하게 포송 할 수 없습니다. 만 지정하는 것이 가장 좋습니다 경로 나 확장 상태가없는 공유 라이브러리 이름을 검색 메커니즘 대신 정보를 제공합니다.
표 9-1C 함수의 매개 변수에 필요한 C 유형을 제공합니다. 그것은에로드 될 것입니다PostgreSQL. 그만큼"" 정의열은 헤더 파일을 제공합니다 유형 정의를 얻으려면 포함해야합니다. (실제 정의는 나열된 파일. 사용자가 정의 된 것을 고수하는 것이 좋습니다 인터페이스.) 항상 포함해야합니다postgres.h먼저 모든 소스 파일에서 어쨌든 필요한 많은 것들을 선언합니다.
표 9-1. 내장에 대한 동등한 C 유형PostgreSQLtypes
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 |
내부,PostgreSQL기본 유형을 a로 간주합니다."Blob of 메모리". 사용자 정의 된 기능을 정의하는 기능 턴 유형은의 방식을 정의합니다.PostgreSQL작동 할 수 있습니다. 즉,PostgreSQL저장 및 디스크에서 데이터를 검색하고 사용자 정의 기능을 사용하십시오. 데이터를 입력, 처리 및 출력합니다. 기본 유형은 하나를 가질 수 있습니다 세 가지 내부 형식 :
통과 별 가치, 고정 길이
참조로 통과, 고정 길이
참조별로 전달, 가변 길이
바이 값 유형은 길이가 1, 2 또는 4 바이트 일 수 있습니다 (또한 8 바이트, ifsizeof (Datum)는 8입니다 기계). 당신은 당신의 유형을 정의하는 데주의해야합니다. 모든 아키텍처에서 크기 (바이트)가됩니다. 을 위한 예,Long유형은 위험합니다 일부 기계에서는 4 바이트이고 다른 기계의 8 바이트이기 때문에 반면int유형은 대부분의 유닉스에서 4 바이트입니다 기계. 의 합리적인 구현int4유닉스 머신의 타입은 다음과 같습니다.
/ * 4-byte 정수, 가치에 의해 통과 */ typedef int int4;
PostgreSQL자동으로 정수 유형이 실제로 그들이 광고하는 크기.
반면에, 모든 크기의 고정 길이 유형이 회의 별 통과. 예를 들어 샘플이 있습니다 A 구현PostgreSQL유형 :
/ * 16 바이트 구조, 참조로 통과 */ typedef struct 더블 X, y; 가리키다;
전달할 때 그러한 유형에 대한 포인터 만 사용할 수 있습니다. 그리고PostgreSQL함수. 그러한 유형의 값을 반환하려면 권리를 할당하십시오. 를 가진 메모리의 양palloc (), 채우기 할당 된 메모리에서 포인터를 반환하십시오. (또는 동일한 유형의 입력 값을 반환 할 수 있습니다. 포인터를 반환하여.절대a의 내용을 수정하십시오 그러나 추천 입력 값을 통과합니다.)
마지막으로 모든 가변 길이 유형도 지나쳐야합니다 참조. 모든 가변 길이 유형은 길이로 시작해야합니다 정확히 4 바이트의 필드 및 그 안에 저장 될 모든 데이터 유형은 그 다음에 메모리에 위치해야합니다. 길이 필드. 길이 필드는 총 길이입니다 구조 (즉, 길이 필드의 크기를 포함합니다. 그 자체). 텍스트 유형을 다음과 같이 정의 할 수 있습니다.
typedef struct int4 길이; 숯 데이터 [1]; 텍스트;
분명히 여기에 선언 된 데이터 필드는 충분히 길지 않습니다. 가능한 모든 줄을 잡고 있습니다. 선언하는 것은 불가능하기 때문에 의 가변 크기 구조C, 우리는에 대한 지식에 의존합니다.C컴파일러는 범위 점검되지 않습니다 배열 구역. 우리는 필요한 금액을 할당합니다 공간에 배열이 선언 된 것처럼 배열에 액세스하십시오. 올바른 길이. (이것이 당신에게 친숙한 트릭이 아니라면 입문으로 시간을 보내고 싶다C탐구하기 전에 교과서 프로그래밍 더 깊이PostgreSQL서버 프로그래밍.) 가변 길이 유형을 조작 할 때, 우리는해야합니다 올바른 양의 메모리를 할당하고 길이 필드가 올바르게. 예를 들어, 우리가 40을 저장하려는 경우 텍스트 구조의 바이트는 다음과 같은 코드 조각을 사용할 수 있습니다. 이것:
#include "postgres.h" ... 숯 버퍼 [40]; / * 소스 데이터 */ ... 텍스트 *대상 = (텍스트 *) palloc (varhdrsz + 40); 대상- 길이 = varhdrsz + 40; memcpy (대상- 데이터, 버퍼, 40); ...
varhdrszsizeof (int4)이지만 좋은 스타일로 간주됩니다 매크로 사용varhdrsz가변 길이 유형에 대한 오버 헤드 크기.
이제 우리는 가능한 모든 구조를 살펴 보았습니다. 기본 유형, 실제 메이저 토토 사이트의 몇 가지 예를 보여줄 수 있습니다.
우리는를 발표합니다."구식"컨벤션을 먼저 호출합니다 더 이상 사용되지 않으면 처음에 처리하는 것이 더 쉽습니다. 에서 버전 -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 (int4)은 int4를 반환합니다 처럼 'pgroot/튜토리얼/funcs 언어 c (isstrict)와 함께; - SQL 기능 이름의 과부하 참고 add_one () 함수 add_one (float8)을 생성합니다 처럼 'pgroot/튜토리얼/funcs ', 'add_one_float8' 언어 C (isstrict); 함수 makepoint (점, 점)를 반환합니다 처럼 'pgroot/튜토리얼/funcs 언어 c (isstrict)와 함께; 함수 CopyText (텍스트)를 작성합니다 텍스트를 반환합니다 처럼 'pgroot/튜토리얼/funcs 언어 c (isstrict)와 함께; CONCIT CONCAT_TEXT (텍스트, 텍스트) 텍스트를 반환합니다 처럼 'pgroot/튜토리얼/funcs 언어 c (isstrict);
여기pgroot에 대한 전체 경로PostgreSQL소스 트리. (더 나은 스타일은 그냥 사용하는 것입니다'funcs'inas조항, 추가 후pgroot/튜토리얼검색 경로로. 어쨌든 우리는 생략 할 수 있습니다 공유 라이브러리의 시스템 별 확장, 일반적으로.so또는.SL.)
함수를 다음으로 지정했음을 알 수 있습니다."엄격한", 시스템은해야합니다 입력 값이 NULL 인 경우 자동으로 NULL 결과를 가정합니다. 이렇게함으로써, 우리는 메이저 토토 사이트 코드. 이것 없이는 널 값을 확인해야합니다 예를 들어, 각각에 대한 널 포인터를 확인하여 명시 적으로 통과 참조 주장. (패스 별 값 주장의 경우, 우리 확인 방법조차 없습니다!)
이 호출 대회는 사용하기가 간단하지만 매우 휴대 성; 일부 아키텍처에는 문제가 있습니다 INT보다 작은 데이터 유형을 이런 식으로 전달합니다. 또한 아무도 없습니다 널 결과를 반환하거나 널에 대처하는 간단한 방법 기능을 엄격하게 만드는 것 외에 다른 방식으로 논쟁. 그만큼 다음에 발표 된 버전 -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()
반품을위한 매크로
유형.
여기서 우리는 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가변 길이 유형에 대한 매크로는 다루어야 할 필요성을 숨 깁니다.
페치"토스트"(압축 또는
외부) 값. 구식CopyText
andconcat_text
위에 표시된 기능은 다음과 같습니다
토스트 된 값이있을 때 실제로 잘못되었습니다.
전화하지 마십시오pg_detoast_datum ()
on
그들의 입력. (구식 스타일의 핸들러는 동적으로로드되었습니다
기능은 현재이 세부 사항을 처리하지만 그렇게합니다.
버전 -1의 경우보다 덜 효율적입니다
기능.)
버전 -1 메이저 토토 사이트의 큰 개선이 더 좋습니다
널 입력 및 결과 처리. 매크로PG_ARGISNULL (n)
함수를 테스트 할 수 있습니다
각 입력이 무효인지 여부 (물론, 이것을하는 것은
선언되지 않은 기능에 필요"엄격한"). 와 마찬가지로pg_getarg_xxx()
매크로, 입력 인수
0에서 시작합니다. 하나는 자제해야합니다
실행pg_getarg_xxx()
하나가 확인할 때까지
논쟁은 무효가 아닙니다. 널 결과를 반환하려면 executepg_return_null ()
; 이것은 작동합니다
엄격한 메이저 토토 사이트과 기적 메이저 토토 사이트.
새로운 스타일 인터페이스에 제공된 다른 옵션은 2입니다
의 변형pg_getarg_xxx()
매크로. 이 중 첫 번째,pg_getarg_xxx_copy ()
반환 보장 a
작성하기에 안전한 지정된 매개 변수의 사본.
(일반 매크로는 때때로 값에 대한 포인터를 반환합니다.
그것은 물리적으로 테이블에 저장되어 있으므로
작성. 사용 사용pg_getarg_xxx_copy ()
매크로는 a
쓰기 가능한 결과.)
두 번째 변형은로 구성됩니다.pg_getarg_xxx_slice ()
매크로
세 가지 매개 변수. 첫 번째는 매개 변수의 수입니다 (AS
위에). 두 번째와 세 번째는 오프셋과 길이입니다.
반환 할 세그먼트. 오프셋은 0에서 계산됩니다
음의 길이는 나머지 값이
반환. 이 루틴은 부품에 대한보다 효율적인 액세스를 제공합니다
스토리지 유형이있는 경우 큰 값
"외부". (열의 저장 유형을 지정할 수 있습니다
사용Alter TableTableNameAlter ColumnColname스토리지 설정StorageType. 스토리지 유형은 중 하나입니다.일반, 외부, 확장또는Main.)
버전 -1 메이저 토토 사이트 호출 규칙을 통해 가능합니다 반품"set"결과 및 구현 트리거 메이저 토토 사이트 및 절차 적 통화 처리기. 버전 1 코드는 버전 -0보다 휴대가 가능합니다. 메이저 토토 사이트 통화 프로토콜에서 ANSI C 제한을 중단하지 않습니다. 자세한 내용은 참조src/backend/utils/fmgr/readme소스에서 분포.
복합 유형은 C와 같은 고정 레이아웃이 없습니다. 구조. 복합 유형의 인스턴스는 null을 포함 할 수 있습니다 전지. 또한 AN의 일부인 복합 유형 상속 계층 구조는 다른 필드와 다른 필드를 가질 수 있습니다 동일한 상속 계층의 구성원. 그러므로,PostgreSQL제공 a 복합 유형의 필드에 액세스하기위한 절차 인터페이스 C. as에서PostgreSQL행 세트를 처리하면 각 행이 귀하에게 전달됩니다. 유형의 불투명 구조로 메이저 토토 사이트튜플. 우리가 함수를 작성하고 싶다고 가정 해 봅시다 쿼리 답변
이름, c_overpaid (EMP, 1500)를 초과 지불로 선택하십시오 emp에서 여기서 name = 'bill'또는 name = 'sam';
위의 쿼리에서 정의 할 수 있습니다c_overpaid
as :
#include "postgres.h" #include "executor/executor.h"/ * for getAttributeByName () */ 부 c_overpaid (tupletableslot *t, / *현재 행의 행 * / int32 한도) bool isnull; INT32 급여; Salary = DatumgetInt32 (getAttributeByName (t, "Salary", & isnull)); if (isnull) 반환 (거짓); 반품 급여 한도; / * 버전 -1 코딩에서 위는 다음과 같습니다. */ pg_function_info_v1 (c_overpaid); 자료 c_overpaid (pg_function_args) tupleTablesLot *t = (tupleTablesLot *) pg_getarg_pointer (0); int32 한계 = pg_getarg_int32 (1); bool isnull; INT32 급여; Salary = DatumgetInt32 (getAttributeByName (t, "Salary", & isnull)); if (isnull) pg_return_bool (false); / * 또는 널 급여에 대해 pg_return_null ()를 선호 할 수 있습니다 */ pg_return_bool (급여 한도);
getAttributeByName
메이저 토토 사이트시스템 기능
현재 행에서 속성을 반환합니다. 세 가지가 있습니다
인수 : 유형의 주장tupletableslot*이름, 이름으로 전달되었습니다
원하는 속성 및 반환 매개 변수의
속성이 null인지 여부.getAttributeByName
a 반환Datum적절한 데이터로 변환 할 수있는 값
적절한 사용으로 입력Datumgetxxx()
매크로.
다음 명령은PostgreSQLc_overpaid
메이저 토토 사이트 :
함수 만들기 c_overpaid (emp, int4) Bool을 반환합니다 처럼 'pgroot/튜토리얼/funcs ' 언어 C;
테이블 함수 API는 생성에 도움이됩니다 사용자 정의 C 언어 테이블 함수 (섹션 9.7). 테이블 기능 하나로 구성된 행을 생성하는 기능입니다. 기본 (스칼라) 데이터 유형 또는 복합 (다중 열) 데이터 유형. API는 두 가지 주요 구성 요소로 분할됩니다. 복합 데이터 유형을 반환하고 반환 지원 다중 행 (반환 함수 설정 또는SRFs).
테이블 함수 API는 매크로 및 기능에 의존합니다. Composite Data를 구축하는 대부분의 복잡성을 억제하십시오 유형 및 여러 결과를 반환합니다. 테이블 함수가 있어야합니다 위에서 설명한 버전 -1 통화 규칙을 따르십시오. ~ 안에 추가, 소스 파일에는 다음을 포함해야합니다.
#include "funcapi.h"
테이블 함수 API가 복합 재구성을 지원합니다 데이터 유형 (또는 행)은부터 시작합니다.AttinMetadata구조. 이 구조 필요한 개별 속성 정보 배열을 보유해야합니다 Raw C 문자열에서 행을 만듭니다. 또한 포인터를 저장합니다 그만큼tupledesc. 정보 여기에서 운반 된 것은에서 파생됩니다.tupledesc이지만 피하기 위해 여기에 저장됩니다 테이블 함수로의 호출마다 중복 CPU 사이클. 에서 세트를 반환하는 함수의 경우,AttinMetadata구조를 계산해야합니다 첫 번째 전화 중에 한 번, 나중에 재사용을 위해 저장되었습니다. 전화.
typedef struct attinmetadata / * 전체 tupledesc */ tupledesc tupdesc; / * 속성 유형 입력 함수 finfo */ fmgrinfo *Attinfuncs; / * 속성 유형 typelem 배열 */ oid *attelems; / * 속성 TypMod 배열 */ int32 *atttypmods; attinmetadata;
이 구조를 채우는 데 도움이됩니다 메이저 토토 사이트과 매크로를 사용할 수 있습니다. 사용
tupledesc relationnamegetTupledesc (const char *relname)
atupledesc기반 a 지정된 관계, 또는
tupledesc typegetTupledesc (Oid typeoid, list *colaliases)
atupledesc기반 a OID를 입력하십시오. 이것은 A를 얻는 데 사용될 수 있습니다.tupledesc베이스 (스칼라) 또는 복합재의 경우 (관계) 유형. 그 다음에
Attinmetadata *tupledescgetattinmetadata (tupledesc tupdesc)
포인터를 반환합니다AttinMetadata, 초기화 주어진tupledesc. AttinMetadata함께 사용할 수 있습니다 올바르게 형성된 튜플을 생성하는 C 줄로. 그만큼 메타 데이터는 중복 작업을 피하기 위해 여기에 저장됩니다 여러 통화.
튜플을 반환하려면 그만큼tupledesc. 사용할 수 있습니다
tupletableslot *tupledescgetSlot (tupledesc tupdesc)
이 튜플 슬롯을 초기화하거나 다른 슬롯을 얻으려면 (사용자 제공) 수단. A를 만들려면 튜플 슬롯이 필요합니다Datum함수에 의한 반환. 그만큼 각 통화에서 동일한 슬롯이 재사용 될 수 있습니다.
건설 후AttinMetadata구조,
Heappuple buildtupleffffflfflflings (Attinmetadata *Attinmeta, char ** value)
a를 구축하는 데 사용할 수 있습니다.HeappupleC 문자열 양식의 사용자 데이터가 주어졌습니다.
"값"은 C 문자열의 배열이며 각 속성마다 하나씩
리턴 튜플. 각 C 문자열은 양식에 있어야합니다
속성 데이터 유형의 입력 함수에 의해 예상됩니다. ~ 안에
속성 중 하나에 대해 널 값을 반환하기 위해
해당 포인터에서값
배열을 설정해야합니다NULL. 이 기능을 호출해야합니다
다시 튜플마다 다시 돌아옵니다.
튜플 빌딩tupledescgetattinmetadata
andBuildTupleFromCstrings
는 편리합니다
기능이 자연스럽게 반환 할 값을 계산하는 경우
텍스트 문자열로. 코드가 자연스럽게 값을 계산하는 경우
데이텀 세트로서 대신 기본을 사용해야합니다heap_formtuple
루틴으로
변환Datum직접 a
튜플. 당신은 여전히가 필요할 것입니다.tupledesc및 Atupletableslot하지만AttinMetadata.
일단 기능에서 돌아 오기 위해 튜플을 만들면, 튜플은 A로 변환되어야합니다.Datum. 사용
tuplegetDatum (tupletableslot *슬롯, 무거운 튜플)
aDatum튜플과 a 슬롯. 이것Datum반환 할 수 있습니다 단일 행 만 반환하려는 경우 직접 설정 퇴치에서 현재 반환 값으로 사용 기능.
예가 아래에 나타납니다.
세트 리턴 메이저 토토 사이트 (SRF)는 일반적으로 각각에 대해 한 번 호출됩니다 반환 된 항목. 그만큼SRF그러므로 그것이 무엇인지 기억하기에 충분한 상태를 절약해야합니다. 각 통화에서 다음 항목을 수행하고 반환합니다. 테이블 함수 API 제공FUNCCALLCONTEXT제어를 돕는 구조 이 과정.fcinfo- flinfo- fn_extra보유하는 데 사용됩니다 포인터FUNCCALLCONTEXT통화 전체.
typedef struct /* * 우리가 전에 전화를 한 횟수. * * call_cntr은 srf_firstcall_init ()에 의해 당신을 위해 0으로 초기화됩니다. * srf_return_next ()가 호출 될 때마다 당신을 위해 증분합니다. */ UINT32 CALL_CNTR; /* * 선택적 최대 통화 수 * * max_calls는 편의를 위해서만 여기에 있으며 선택 사항입니다. * 설정하지 않으면 언제 * 기능이 완료되었습니다. */ UINT32 MAX_CALLS; /* * 결과 슬롯에 대한 선택적 포인터 * * 슬롯은 튜플을 반환 할 때 사용합니다 (즉, 복합 데이터 유형) *베이스 (즉, 스칼라) 데이터 유형을 반환 할 때는 필요하지 않습니다. */ tupletableslot *슬롯; /* * MISC 사용자 제공 컨텍스트 정보에 대한 선택적 포인터 * * user_fctx는 자신의 구조물에 대한 포인터로 사용하기위한 것입니다. * 기능에 대한 호출 간의 임의의 컨텍스트 정보. */ void *user_fctx; /* * 속성 유형 입력 배열을 포함하는 구조에 대한 선택적 포인터 * metainfo * * Attinmeta는 튜플을 반환 할 때 사용합니다 (즉, 복합 데이터 유형) *베이스 (즉, 스칼라) 데이터 유형을 반환 할 때는 필요하지 않습니다. 그것 * BuildTupleFromCstrings ()를 사용하여 생성하려는 경우에만 필요합니다. * 리턴 튜플. */ Attinmetadata *Attinmeta; /* * 여러 통화를 위해 살아야하는 구조에 사용되는 메모리 컨텍스트 * * multi_call_memory_ctx는 SRF_FIRSTCALL_INIT ()에 의해 설정되어 사용됩니다. * 청소용 srf_return_done ()에 의해. 가장 적절한 메모리입니다 * 여러 통화에서 재사용 할 메모리에 대한 컨텍스트 * SRF. */ MemoryContext multi_call_memory_ctx; 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.
SRFis is a
통화간에 지워질 일시적인 컨텍스트. 이것
당신이 필요하지 않다는 것을 의미합니다pfree
당신이 모든 것Palloc
; 어쨌든 사라질 것입니다. 그러나 if
당신은 전반적으로 살기 위해 모든 데이터 구조를 할당하려고합니다.
전화, 다른 곳에 두어야합니다. 기억
컨텍스트가 참조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를 구축] [슬롯 획득] funcctx- 슬롯 = 슬롯; [Endif Returning Composite] [사용자 정의 코드] 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 (testpassbyval); 자료 TestPassByVal (pg_function_args) funccallcontext *funcctx; int call_cntr; int max_calls; tupledesc tupdesc; tupletableslot *슬롯; 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"); / *이 tupdesc와 함께 튜플 슬롯을 할당 */ 슬롯 = tupledescgetSlot (tupdesc); / * 함수 컨텍스트에 슬롯 할당 */ funcctx- 슬롯 = 슬롯; /* * RAW에서 튜플을 생산하는 데 필요한 속성 메타 데이터 생성 * C 문자열 */ Attinmeta = tupledescgetattinmetadata (tupdesc); funcctx- attinmeta = Attinmeta; MemoryContexTswitchto (OldContext); / * 함수의 모든 호출에서 수행 된 작업 */ funcctx = srf_percall_setup (); call_cntr = funcctx- call_cntr; max_calls = funcctx- max_calls; 슬롯 = funcctx- 슬롯; 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, 값); / * 튜플을 데이텀으로 만듭니다 */ 결과 = tuplegetDatum (슬롯, 튜플); / * 정리 (실제로 필요하지 않습니다) */ pfree (값 [0]); pfree (값 [1]); pfree (값 [2]); pfree (값); srf_return_next (funcctx, 결과); else / * 더 이상 남지 않을 때하십시오 * / srf_return_done (funcctx);
지원 SQL 코드
생성 유형 __testpassByval AS (f1 int4, f2 int4, f3 int4); 함수 TestPassByval (int4, int4)을 생성하거나 교체하십시오 'module_pathname', 'testpassbyval'language 'c'불변의 엄격;
참조Contrib/TableFunc더 많은 것 테이블 메이저 토토 사이트의 예.
이제 우리는 더 어려운 글쓰기 작업으로 돌아갑니다. 메이저 토토 사이트 기능 프로그래밍. 경고 :이 섹션 의이 부분 매뉴얼은 당신을 프로그래머로 만들지 않을 것입니다. 당신은 좋은 것이 있어야합니다 에 대한 이해C(포인터 사용 포함) 쓰기를 시도하기 전에CPostgreSQL. 그럴 수도 있습니다 이외의 언어로 작성된 기능을로드 할 수 있습니다.CinPostgreSQL, 이것은 종종 어렵다 (언제 전혀 가능합니다)과 같은 다른 메이저 토토 사이트이기 때문에FortranandPascal종종 같은 것을 따르지 않습니다전화 컨벤션asC. 즉, 다른 언어는 통과하지 않습니다 같은 방식으로 함수 사이의 인수 및 반환 값. 이러한 이유로 우리는 귀하의 프로그래밍 언어가 함수는로 작성됩니다.C.
건축을위한 기본 규칙C함수는 다음과 같습니다.
usepg_config
-includedir-serverPostgreSQL서버 헤더 파일입니다
시스템에 설치 (또는 사용자가
실행 중). 이 옵션은PostgreSQL7.2. 을 위한PostgreSQL7.1 사용해야합니다
옵션-includedir
.
(PG_CONFIGa
알 수없는 옵션이 발생하는 경우 0이 아닌 상태입니다.)
7.1 이전에 출시되면 추측해야하지만
그것은 현재의 전화 규칙이 이전에있었습니다
소개, 당신이 그들을 지원하고 싶을 것 같지는 않습니다.
릴리스.
메모리를 할당 할 때를 사용하십시오.PostgreSQL루틴Palloc
andpfree
해당 대신C도서관 루틴Malloc
및무료
. 에 의해 할당 된 메모리Palloc
가 해방됩니다
각 트랜잭션이 끝날 때 자동으로 방지합니다
메모리 누출.
항상 구조물의 바이트를 항상 0memset
또는bzero
. 여러 루틴 (해시 등
액세스 방법, 해시 조인 및 정렬 알고리즘) 계산
당신의 구조에 포함 된 원시 비트의 기능. 심지어
구조의 모든 필드를 초기화하면
정렬 패딩의 여러 바이트가 되십시오 (구멍에
쓰레기 값을 포함 할 수있는 구조)
대부분의 내부PostgreSQL유형은postgres.h관리자 인터페이스 (pg_function_args등)fmgr.h이므로 AT를 포함시켜야합니다 최소한이 두 파일. 휴대 할 수있는 이유로 가장 좋습니다 포함하다postgres.h 첫 번째시스템 또는 사용자 헤더 파일. 포함Postgres.h포함elog.h및Palloc.h당신을 위해.
객체 파일 내에 정의 된 기호 이름은 안됩니다 서로 충돌하거나에 정의 된 기호와 충돌PostgreSQL서버 실행 파일. 당신은 당신의 함수의 이름을 바꿔야합니다 이 효과에 오류 메시지가 표시되는 경우 변수
객체 코드를 컴파일하고 연결하여 동적으로로드PostgreSQL항상 특별해야합니다 깃발. 보다섹션 9.5.8특정 운영 체제.
사용하기 전에PostgreSQL확장 기능이 작성되었습니다 C, 그들은 특별한 생산 방법으로 편집하고 연결되어야합니다. 서버에서 동적으로로드 할 수있는 파일. 장차 ~ 가 되는 정확한, A64999_65015생성.
자세한 내용은 문서를 읽어야합니다 운영 체제, 특히 C의 수동 페이지 컴파일러,CC및 링크 편집기,LD. 또한PostgreSQL소스 코드에는 여러 가지가 포함되어 있습니다 의 작업 예제Contrib디렉토리. 이 예에 의존하면 의 가용성에 따라 모듈PostgreSQL소스 코드.
공유 생성 라이브러리는 일반적으로 실행 파일 연결과 유사합니다 소스 파일은 객체 파일로 컴파일 된 다음 객체 파일은 함께 연결됩니다. 객체 파일은 있어야합니다 생성위치 독립 코드(PIC), 개념적으로 임의의 위치에 배치 할 수 있음을 의미합니다. 실행 파일에 의해로드 될 때 메모리. (객체 파일 실행 파일을위한 의도는 일반적으로 그런 식으로 컴파일되지 않습니다.) 공유 라이브러리를 연결하라는 명령에는 특수 플래그가 포함됩니다. 실행 파일 연결과 구별됩니다. --- 적어도 이것은입니다 이론. 일부 시스템에서는 연습이 훨씬 추악합니다.
다음 예에서는 소스 코드가 파일에서foo.c그리고 우리는 a 공유 도서관foo.so. 그만큼 중간 객체 파일은입니다.foo.o66676_66792
생성 할 컴파일러 플래그PICis-fpic
. 링커 플래그는 공유를 생성합니다
도서관은-shared
.
gcc -fpic -c foo.c ld -shared -o foo.so foo.o
버전 4.0에서 적용 가능BSD/OS.
생성 할 컴파일러 플래그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
and
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
. 일부 플랫폼에서
상황-fpic
사용해야합니다
만약에-fpic
작동하지 않습니다. 나타내다
자세한 내용은 GCC 매뉴얼에. 컴파일러 플래그
공유 라이브러리를 만들려면-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 -bsharable -o foo.so foo.o
생성 할 컴파일러 플래그PICis-kpic
태양 컴파일러와-fpic
withGCC. 공유 라이브러리를 연결하기 위해
컴파일러 옵션은-g
컴파일러 또는 대안 적으로-shared
withGCC.
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
동일한 절차가 시스템 컴파일러; 특별한 옵션이 필요하지 않습니다.
생성 할 컴파일러 플래그PICis-K
PIC
SCO 컴파일러와-fpic
withGCC. 공유 라이브러리를 연결하기 위해
컴파일러 옵션은-g
SCO 컴파일러 및-shared
withGCC.
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) 할 수 있습니다 에서 생략메이저 토토 사이트 생성명령은 일반적으로 생략되어야합니다 이식성.
다시 참조섹션 9.5.1서버가 공유를 찾을 예정인 위치 정보 도서관 파일.