사용자 정의 함수는 C (또는 언어로 작성할 수 있습니다."c기능"내부"함수 - 실제 코딩
현재 두 가지 다른 전화 규칙이 c"버전 1"전화 컨벤션은 A를 작성하여 표시됩니다.pg_function_info_v1 ()매크로 기능을 요청합니다."버전 0") 함수. 언어기능 생성isC두 경우 모두. 구식 기능
처음으로 사용자 정의 기능이 처음입니다기능 생성a
다음 알고리즘은 공유 객체를 찾는 데 사용됩니다.생성명령 :
이름이 절대 경로 인 경우 주어진 파일은
이름에 디렉토리 부분이없는 경우 파일dynamic_library_path.
그렇지 않으면 (파일은 경로에서 발견되지 않았습니다.
이 시퀀스가 작동하지 않으면 플랫폼 별 공유.so)는 주어진 이름과 이것에 추가됩니다
사용자 IDPostgreSQL서버가 파일로의 경로를 가로 질러야합니다.Postgres사용자는 일반적인 실수입니다.
어쨌든에 나와있는 파일 이름은기능 생성명령은 문자 그대로 기록됩니다
참고 : PostgreSQLC 함수를 자동으로 컴파일하지 않습니다. 대상기능 생성명령. 보다섹션 31.9.6
처음으로 사용 된 후 동적으로로드로드신선한 명령 또는 시작
공유 라이브러리를 상대적으로 찾는 것이 좋습니다$ libdir또는 동적을 통한$ libdirstand는 찾을 수 있습니다PG_CONFIG.
전PostgreSQL릴리스기능 생성. 이것
토토 핫language functions를 작성하는 방법을 알기 위해서는 알아야합니다.PostgreSQL내부PostgreSQL기본 유형을 a로 간주합니다."기억의 블로브". 사용자 정의PostgreSQL작동 할 수 있습니다PostgreSQL의지
기본 유형은 세 가지 내부 형식 중 하나를 가질 수 있습니다.
통과 별 가치, 고정 길이
참조로 통과, 고정 길이
참조별로 전달, 가변 길이
바이 값 유형은 길이가 1, 2 또는 4 바이트 일 수 있습니다 (또한sizeof (Datum)는 8입니다Long유형은 위험합니다int타입은 대부분의 유닉스에서 4 바이트입니다int4유닉스 머신의 타입은 다음과 같습니다.
/ * 4-byte 정수, 가치에 따라 통과 */
반면에, 모든 크기의 고정 길이 유형이PostgreSQL유형 :
/ * 16 바이트 구조, 참조로 통과 */
전달할 때 그러한 유형에 대한 포인터 만 사용할 수 있습니다.PostgreSQL기능. 그러한 유형의 값을 반환하려면 권리를 할당하십시오.Palloc, 채우기Never수정
마지막으로 모든 가변 길이 유형도 지나쳐야합니다
예를 들어, 유형을 정의 할 수 있습니다텍스트다음과 같이 :
typedef struct
분명히 여기에 선언 된 데이터 필드는 충분히 길지 않습니다.C, 우리는에 대한 지식에 의존합니다.C컴파일러는 범위 점검되지 않습니다
가변 길이 유형을 조작 할 때 조심해야합니다텍스트구조, 우리는 a를 사용할 수 있습니다
#include "postgres.h"
varhdrsz|sizeof (int4)그러나 좋은 스타일로 간주됩니다varhdrsz
표 31-1어떤 c 유형이 어떤 SQL 유형에 해당하는지 지정합니다.PostgreSQL. 그만큼"" 정의열은 헤더 파일을 제공합니다Postgres.h먼저 모든 소스 파일에서
표 31-1. 내장 SQL의 동등한 C 유형
SQL 유형 | C 유형 | 정의 |
---|---|---|
Abstime | AbsoluteTime | utils/nabstime.h |
부울 | bool | Postgres.h(아마도 |
Box | Box* | utils/geo_decls.h |
BYTEA | BYTEA* | Postgres.h |
"char" | char | (컴파일러 내장) |
캐릭터 | BPCHAR* | Postgres.h |
CID | CommandId | Postgres.h |
날짜 | dateadt | utils/date.h |
smallint (int2) | int2또는int16 | Postgres.h |
int2vector | int2vector* | Postgres.h |
정수 (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 |
이제 우리는 가능한 모든 구조를 살펴 보았습니다.
우리는 발표"구식"컨벤션을 먼저 호출 -이 접근법은 지금이지만
여기 몇 가지 예가 있습니다.
#include "postgres.h"
위의 코드가 파일에서 준비되었다고 가정funcs.c그리고 공유로 편집되었습니다PostgreSQL다음과 같은 명령과 함께 :
함수 생성 add_one (정수) 정수를 반환합니다디렉토리/funcs ','add_one '디렉토리/funcs ','add_one_float8 '디렉토리/funcs ','makepoint '디렉토리/funcs ','CoppyText '디렉토리/funcs ','concat_text ',
여기,디렉토리PostgreSQL튜토리얼 디렉토리,'funcs'inas조항, 추가 후디렉토리검색 경로로. 어느 쪽이든.so또는.SL.)
함수를로 지정했음을 알 수 있습니다."엄격한", 시스템이 있어야한다는 것을 의미합니다
이 호출 대회는 사용하기가 간단하지만int이 방법. 또한 간단한 방법은 없습니다
버전 -1 컨벤션은 매크로에 의존합니다
Datum funcname (pg_function_args)
또한 매크로 호출
pg_function_info_v1 (funcname);
동일한 소스 파일에 나타나야합니다. (전통적으로, 그것은입니다내부-언어PostgreSQL모든 내부 기능이 버전 -1을 사용한다고 가정합니다
버전 -1 함수에서는 각 실제 인수가 가져옵니다pg_getarg_xxx()
매크로에 해당합니다pg_return_xxx()
반환 유형의 매크로.pg_getarg_xxx()
그 주장으로 취합니다pg_return_xxx()
그 주장으로 간주합니다
여기서 우리는 Version-1에 코딩 된 위와 동일한 함수를 보여줍니다.
#include "postgres.h"
the기능 생성명령은입니다
언뜻보기에 버전 -1 코딩 규칙이 나타날 수 있습니다add_one_float8
, 우리는 더 이상 알 필요가 없습니다float8는 추천 유형입니다.getarg가변 길이 유형의 매크로는보다 효율적입니다"토스트"(압축 또는
버전 -1 기능의 큰 개선이 더 좋습니다PG_ARGISNULL (n)
함수를 테스트 할 수 있습니다"엄격한".)와 마찬가지로pg_getarg_xxx()
매크로, 입력 인수pg_getarg_xxx()
하나가 확인할 때까지pg_return_null ()
; 이것은 작동합니다
새로운 스타일 인터페이스에 제공된 다른 옵션은 2입니다pg_getarg_xxx()
매크로. 이 중 첫 번째,pg_getarg_xxx_copy ()
, 반환을 보장합니다pg_getarg_xxx_copy ()
매크로는 apg_getarg_xxx_slice ()
매크로"외부". (스토리지 유형ALTERTableNameAlter ColumnColname스토리지 설정StorageType. StorageType일반, 외부,
확장또는Main.)
마지막으로, 버전 -1 기능 호출 규칙이이를 만듭니다섹션 31.9.10) 및PostgreSQL : 문서 : 8.0 : 메이저 토토 사이트) 및 절차 적 통화 처리기 (45 장). 버전 1 코드도 더 많습니다src/backend/utils/fmgr/readmein
보다 진보 된 주제로 돌아 가기 전에PostgreSQL토토 핫language functions. 그 동안PostgreSQL,이
C 기능 작성 및 구축을위한 기본 규칙은 다음과 같습니다.
usePG_CONFIGPostgreSQL서버 헤더 파일입니다PostgreSQL7.2. 을 위한PostgreSQL7.1 사용해야합니다-includedir. (PG_CONFIG0이 아닌 상태로 종료됩니다
메모리를 할당 할 때를 사용하십시오.PostgreSQL기능Palloc
andpfree
해당 C 라이브러리 대신Malloc
and무료
. 에 의해 할당 된 메모리Palloc
가 해제됩니다
항상 구조물의 바이트를 항상 0memset
. 이것 없이는 그렇지 않습니다
대부분의 내부PostgreSQL유형은Postgres.hpg_function_args등)fmgr.h이므로 AT를 포함시켜야합니다Postgres.h 첫 번째Postgres.h포함elog.handPalloc.h당신을 위해.
객체 파일 내에 정의 된 기호 이름은 안됩니다PostgreSQL서버
코드를 컴파일하고 연결하여PostgreSQL항상 특별해야합니다섹션 31.9.6
사용하기 전에PostgreSQL확장 기능이 작성되었습니다공유 도서관
이 섹션에 포함 된 것 이상의 정보는 귀하에게CC및 링크 편집기,LD. 또한PostgreSQL소스 코드에는 여러 가지가 포함되어 있습니다Contrib디렉토리. 이 예에 의존하면PostgreSQL소스 코드.
공유 생성위치 독립 코드 (PIC),그것은 개념적으로 그들이 할 수 있음을 의미합니다
다음 예에서는 소스 코드가foo.c그리고 우리는 a.so. 그만큼foo.o33464_33577
생성 할 컴파일러 플래그PICis-fpic.-shared.
gcc -fpic -c foo.c
버전 4.0에서 적용 가능BSD/OS.
생성 할 컴파일러 플래그PICis-fpic.-shared.
gcc -fpic -c foo.c
버전 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
생성 할 컴파일러 플래그PICis-fpic.-fpic-fpic작동하지 않습니다. GCC를 참조하십시오-shared. 에이
CC -FPIC -C FOO.C
여기 예입니다. 개발자 도구가 있다고 가정합니다
CC -C foo.c
생성 할 컴파일러 플래그PICis-fpic.ELF시스템, the-sharedisld -Bsharableis
gcc -fpic -c foo.c
생성 할 컴파일러 플래그PICis-fpic. ld -Bsharable링크에 사용됩니다
gcc -fpic -c foo.c
생성 할 컴파일러 플래그PICis-kpicSUN 컴파일러와-fpicwithGCC. 공유 링크-g컴파일러 또는 대안-sharedwithGCC.
cc -kpic -c foo.c
또는
gcc -fpic -c foo.c
PIC기본값입니다.LD특수 옵션과 함께 사용하는 데 사용됩니다
CC -C foo.c
동일한 절차가 GCC 대신 GCC와 함께 사용됩니다.
생성 할 컴파일러 플래그PICis-K PICSCO 컴파일러와-fpicwithGCC. 공유 링크-gSCO 컴파일러와-sharedwithGCC.
CC -K PIC -C FOO.C
또는
gcc -fpic -c foo.c
팁 :이것이 당신에게 너무 복잡하다면, 당신gnu libtool,
결과 공유 라이브러리 파일을로드 할 수 있습니다PostgreSQL. 지정할 때기능 생성명령, 공유 라이브러리 파일의 이름을 알려야합니다..so또는.SL) 할 수 있습니다기능 생성명령은 일반적으로 최선을 위해 생략해야합니다
다시 참조섹션서버가 공유를 찾을 것으로 예상되는 위치에 대해
배포에 대해 생각하고 있다면PostgreSQL확장 모듈, 설정 aPostgreSQL설치는 확장에 대한 빌드 인프라를 제공합니다.PGXS이므로 간단합니다PostgreSQL; 그것은 단순히 공통을 자동화합니다
확장에 인프라를 사용하려면 작성해야합니다.PGXSmakefile. 다음은 다음과 같습니다ISBN_ISSN공유 라이브러리, SQL로 구성됩니다
modules = isbn_issn
마지막 두 줄은 항상 동일해야합니다. 일찍만들기규칙.
다음 변수를 설정할 수 있습니다.
소스 파일에서 빌드 할 공유 개체 목록
random files to inter접두사/share/contrib
random files to inter접두사/share/contrib
아래에 설치할 무작위 파일접두사/doc/contrib
스크립트 파일 (바이너리 아님)에 설치할접두사/bin
스크립트 파일 (바이너리 아님)에 설치할접두사/bin
회귀 테스트 사례 목록 (접미사없이)
또는이 두 가지 중 하나 :
빌드 할 바이너리 프로그램 (객체를 목록에OBJS)
빌드 할 공유 객체 (을 목록에서 목록OBJS)
다음도 설정할 수 있습니다 :
제거 할 추가 파일만들기
에 추가됩니다CPPFLAGS
에 추가됩니다프로그램링크
에 추가됩니다module_big링크 라인
이 makefile으로MakeFilein만들기컴파일하고 나중에설치모듈을 설치하려면. 그만큼PostgreSQL해당 설치PG_CONFIG명령을 찾았습니다
복합 유형은 C와 같은 고정 레이아웃이 없습니다.PostgreSQL함수를 제공합니다
쿼리에 응답하기 위해 함수를 작성하고 싶다고 가정 해
이름, C_overpaid (EMP, 1500)를 초과 지불로 선택하십시오
Call Concentions 버전 0 사용, 정의 할 수 있습니다c_overpaid
as :
#include "postgres.h"
버전 -1 코딩에서 위는 다음과 같습니다.
#include "postgres.h"
getAttributeByName
PostgreSQL시스템 기능HeappupleHeader이름, 이름으로 전달되었습니다getAttributeByName
a 반환Datum적절한 데이터로 변환 할 수있는 값Datumgetxxx()
매크로. 귀무인이
또한getAttributeBynum
42669_42743
다음 명령은 함수를 선언합니다c_overpaid
sql :
함수 만들기 C_OVERPAID (EMP, Integer)는 부울을 반환합니다디렉토리/funcs ','c_overpaid '
우리가 사용한 통지엄격한
c- 언어에서 행 또는 복합 유형 값을 반환하려면
#include "funcapi.h"
복합 데이터 값을 구축 할 수있는 두 가지 방법이 있습니다."튜플") : 할 수 있습니다tupledesc튜플 구조에 대한 디스크립터. Datums와 함께 일할 때tupledesctoBlessTupledesc
, 그리고 전화heap_formtuple
각 행마다. 언제tupledesctotupledescgetattinmetadata
, 그리고 전화BuildTupleFromCstrings
각각
설정을위한 여러 도우미 기능이 제공됩니다tupledesc. 원한다면
tupledesc relationnamegetTupledesc (const char *relname)
atupledesc명명 된
tupledesc typegetTupledesc (Oid typeoid, list *colaliases)
atupledesc기준 atupledesc베이스 또는 복합 유형의 경우. 언제레코드, 예상tupledesc
일단 당신이 atupledesc,
tupledesc blesstupledesc (tupledesc tupdesc)
Datums와 함께 일할 계획이라면
Attinmetadata *tupledescgetattinmetadata (tupledesc tupdesc)
C 문자열로 작업하려는 경우. 당신이 쓰는 경우 aFUNCCALLCONTEXT구조 - 사용tuple_desc또는Attinmeta필드
Datums에서 작업 할 때
heappuple heap_formtuple (tupledesc tupdesc, datum *값, char *nulls)
aheappuple주어진 사용자
C 문자열로 작업 할 때 사용
Heatpuple buildtupleffflflflfffffflings (AttinMetadata *AttinMeta, char ** value)
aheappuple주어진 사용자값is값배열을 설정해야합니다NULL. 이 기능은 있어야합니다
일단 당신의 기능에서 돌아 오기 위해 튜플을 만들면, 그것은Datum. 사용
HeappupleGetDatum (Heappuple Tuple)
변환heappupleaDatum반환 할 수 있습니다
다음 섹션에 예제가 나타납니다.
지원을 제공하는 특별한 API도 있습니다.funcapi.h, 위와 같이.
세트 퇴행 함수 (SRF) 각 항목마다 한 번 호출됩니다SRF필수FUNCCALLCONTEXT제어를 돕기 위해 제공됩니다fcinfo-> flinfo-> fn_extraaFUNCCALLCONTEXT가로 질러
typedef struct
anSRF몇 가지를 사용합니다FUNCCALLCONTEXT구조 (및fn_extra).
srf_is_firstcall ()
첫 번째 기능이 호출되는지 확인하려면
SRF_FIRSTCALL_INIT ()
초기화하려면FUNCCALLCONTEXT. 모든 기능 호출에서
srf_percall_setup ()
사용을 위해 올바르게 설정하려면FUNCCALLCONTEXT이전에 지우십시오
함수가 반환 할 데이터가 있으면
srf_return_next (funcctx, result)
발신자에게 반환합니다. (결과유형이어야합니다Datum
srf_return_done (funcctx)
정리하고 끝내려면SRF.
|SRF라고 불리는 것은 일시적인 컨텍스트입니다pfree
Palloc
; 그것은 할 것입니다multi_call_memory_ctx는 적합한 위치입니다SRF가 끝났습니다. 대부분의 경우multi_call_memory_ctx
완전한 의사 코드 예제는 다음과 같습니다.
Datum필요에 따른 추가 선언if (srf_is_firstcall ())사용자 코드 복합재를 반환하는 경우 tupledesc 빌드 및 아마도 AttinMetadata Endif 리턴 컴포지트 사용자 코드MemoryContexTswitchto (OldContext);사용자 코드funcctx = srf_percall_setup ();사용자 코드/ * 이것은 우리가 끝났는지 테스트 할 수있는 한 가지 방법 일뿐입니다. */사용자 코드 결과 기준 획득srf_return_next (funcctx, result);사용자 코드srf_return_done (funcctx);
간단한 완전한 예SRF복합 유형 모양을 반환합니다
pg_function_info_v1 (testpassbyval);
이 기능을 선언하는 SQL 코드는 다음과 같습니다.
유형 생성 __testpassByval AS (f1 Integer, F2 Integer, F3 Integer);filename','TestPassByval '
디렉토리Contrib/TableFuncin
토토 핫 언어 함수는 수락 및 반환으로 선언 될 수 있습니다AnylementandAnyArray. 보다섹션다형성에 대한 자세한 설명fmgr.h버전 -1 C 함수를 허용합니다get_fn_expr_rettype (fmgrinfo *flinfo)andget_fn_expr_argtype (fmgrinfo *flinfo, int. 결과 또는 인수 유형 OID를 반환합니다.Invalidoid정보가 아닌 경우flinfoISfcinfo-> flinfo. 매개 변수Argnum기반이 0입니다.
예를 들어, 우리가 수락 할 함수를 작성하고 싶다고 가정합니다.
pg_function_info_v1 (make_array);
다음 명령은 함수를 선언합니다make_array
sql :
함수 생성 make_array (Anylement)는 anyArray를 반환합니다디렉토리/funcs ','make_array '
사용에 주목하십시오엄격한; 이것은