토토 커뮤니티 9.3.25 문서 | ||||
---|---|---|---|---|
PostgreSQL : 문서 : 9.3 : 토토 핫 기능 | Postgre토토 사이트 추천 : 문서 : 9.3 : 토토 사이트 추천 확장 | 제 35 장.SQL | 다음 |
사용자 정의 함수는 C (또는 언어로 작성할 수 있습니다."c함수"내부"기능 - 실제 코딩 규칙
현재 두 가지 다른 전화 규칙이 c"버전 1"전화pg_function_info_v1 ()매크로 기능을 요청합니다."버전 0") 함수. 언어함수 만들기isC두 경우 모두. 구식 기능입니다
처음로드 가능에서 사용자 정의 기능이 처음으로함수 만들기사용자 정의 c
다음 알고리즘은 공유 객체 파일을 찾는 데 사용됩니다.생성명령 :
이름이 절대 경로 인 경우 주어진 파일이로드됩니다.
이름이 문자열로 시작하면$ libdir, 그 부분은로 대체됩니다.토토 커뮤니티패키지 라이브러리 디렉토리 이름,
이름에 디렉토리 부분이 포함되어 있지 않으면 파일은 다음과 같습니다.dynamic_library_path.
그렇지 않으면 파일은 경로에서 발견되지 않았거나
이 시퀀스가 작동하지 않으면 플랫폼 별 공유.so)
공유 라이브러리를 찾는 것이 좋습니다$ libdir또는 동적 라이브러리를 통한$ libdirstand는 명령으로 찾을 수 있습니다pg_config --pkglibdir.
사용자 ID토토 커뮤니티서버는 파일로 경로를 가로 질러야합니다.Postgres사용자는 일반적인 실수입니다.
어쨌든에 주어진 파일 이름함수 만들기명령은 문자 그대로 기록됩니다
참고 : 토토 커뮤니티의지생성명령. 보다섹션추가 정보는
동적으로로드 된 객체 파일이로드되지 않도록토토 커뮤니티파일에 A가 포함되어 있는지 확인합니다"매직 블록"적절한토토 커뮤니티. 마법토토 커뮤니티8.2. 마법 블록을 포함하려면 이것을 하나의 (그리고 하나만)fmgr.h:
#ifdef pg_module_magic
the#ifdef테스트를 생략 할 수 있습니다토토 커뮤니티릴리스.
처음으로 사용 된 후 동적으로로드 된 객체
선택적으로, 동적으로로드 된 파일에는 초기화가 포함될 수 있습니다_pg_init
, 그 함수가 될 것입니다_pg_fini
, 그 함수가 될 것입니다_pg_fini
동안 만 호출됩니다
토토 커뮤니티language functions를 작성하는 방법을 알아하려면 방법을 알아야합니다토토 커뮤니티내부적으로 대표합니다토토 커뮤니티a"기억의 블로브". 그만큼토토 커뮤니티can토토 커뮤니티디스크에서 데이터를 저장하고 검색하고 사용합니다.
기본 유형은 세 가지 내부 형식 중 하나를 가질 수 있습니다.
통과 별 가치, 고정 길이
참조로 통과, 고정 길이
참조별로 전달, 가변 길이
바이 값 유형은 길이가 1, 2 또는 4 바이트 일 수 있습니다 (또한 8sizeof (Datum)는 8입니다Long타입은 4이기 때문에 위험합니다int타입은 대부분의 Unix 시스템에서 4 바이트입니다. 합리적int4유닉스에 입력하십시오
/ * 4-byte 정수, 가치에 따라 통과 */
(실제 PostgreSQL C 코드는이 유형을 호출int32, C의 협약이기 때문에intxx평균xx 비트. 그러므로 cint8크기는 1 바이트입니다. SQL 유형int8int64in테이블.)
반면에, 모든 크기의 고정 길이 유형을 전달할 수 있습니다.토토 커뮤니티유형 :
/ * 16 바이트 구조, 참조로 통과 */
그러한 유형에 대한 포인터 만 전달할 때 사용할 수 있습니다.토토 커뮤니티기능. 에게Palloc, 할당 된 메모리를 채우고,Palloc및
마지막으로 모든 가변 길이 유형도 지나쳐야합니다set_varsize; 이 필드를 직접 설정하지 마십시오!
또 다른 중요한 요점은 초기화되지 않은 것을 피하는 것입니다
경고 |
절대수정섹션 35.10. |
예를 들어, 유형을 정의 할 수 있습니다텍스트다음과 같이 :
typedef struct
분명히 여기에 선언 된 데이터 필드는 충분히 길지 않습니다.C, 우리C컴파일러는 배열 첨자 범위를 범합니다. 우리는 단지 할당됩니다
가변 길이 유형을 조작 할 때 조심해야합니다텍스트구조, 코드를 사용할 수 있습니다
#include "postgres.h"
varhdrsz|sizeof (int32)이지만 사용하기에 좋은 스타일로 간주됩니다varhdrsz크기를 참조합니다필수를 사용하여 설정하십시오set_varsize매크로, 단순하지 않습니다
표 35-1쓸 때 어떤 c 유형에 해당하는지 지정합니다.토토 커뮤니티. 그만큼"정의열이 포함되어야하는 헤더 파일을 제공합니다.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 |
정수 (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 |
이제 우리는베이스를위한 가능한 모든 구조를 살펴 보았습니다.
우리는를 발표합니다."구식"전화
여기 몇 가지 예가 있습니다.
#include "postgres.h"
위의 코드가 파일에서 준비되었다고 가정funcs.c공유로 컴파일했습니다토토 커뮤니티다음과 같은 명령과 함께 :
함수 생성 add_one (정수) 정수를 반환합니다디렉토리/funcs ','add_one '디렉토리/funcs ','add_one_float8 '디렉토리/funcs ','makepoint '디렉토리/funcs ','CopyText '디렉토리/funcs ','concat_text '
여기,디렉토리토토 커뮤니티튜토리얼 디렉토리'funcs'inas조항, 추가 후디렉토리검색 경로로. 어쨌든 우리.so또는.SL.)
함수를로 지정했음을 알 수 있습니다."엄격한", 시스템이 있어야한다는 의미입니다
이 호출 규칙은 사용하기가 간단하지만int이 방법. 또한 Null 결과를 반환하는 간단한 방법은 없습니다.
버전 -1 통화 컨벤션은 매크로에 의존하여 억제합니다
Datum funcname (pg_function_args)
또한 매크로 호출 :
pg_function_info_v1 (funcname);
동일한 소스 파일에 나타나야합니다. (전통적으로, 그것은입니다내부-언어 함수,토토 커뮤니티모든 것을 가정합니다
버전 -1 기능에서 각 실제 인수는 A를 사용하여 가져옵니다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)
함수가 각 입력이 null인지 테스트 할 수 있습니다. (물론,"엄격한".)와 마찬가지로pg_getarg_xxx()
매크로, 입력 인수는 0에서 시작됩니다. 메모pg_getarg_xxx()
인수가 무효가 아님을 확인할 때까지. apg_return_null ()
; 이것은 엄격한 것과 모두에서 작동합니다
새로운 스타일 인터페이스에 제공된 다른 옵션은 2입니다pg_getarg_xxx()
매크로. 이 중 첫 번째,pg_getarg_xxx_copy ()
, apg_getarg_xxx_copy ()
매크로는 apg_getarg_xxx_slice ()
3을 가져가는 매크로"외부". (열의 저장 유형은 될 수 있습니다Alter TableTableNameAlter ColumnColname스토리지 설정StorageType. StorageType중 하나입니다일반, 외부, 확장또는Main.)
마지막으로, 버전 -1 기능 호출 규칙이이를 만듭니다섹션 35.9.9) 및 구현토토 사이트 : 문서 : 9.3 : 트리거) 및PostgreSQL : 문서 : 9.3 : 절차 언어 스포츠 토토 결과 작성). 버전 1 코드는 버전 -0보다 휴대가 가능합니다.src/backend/utils/fmgr/readme소스에서
보다 진보 된 주제로 돌아 가기 전에 논의해야합니다.토토 커뮤니티c-language functions. 함수를로드하는 것이 가능할 수 있습니다토토 커뮤니티, 이것은 일반적으로 어렵다 (경우
C 기능 작성 및 구축을위한 기본 규칙은 다음과 같습니다.
usePG_CONFIG-includeDir-ServerTO토토 커뮤니티서버 헤더 파일이 시스템에 설치되어 있습니다 (또는 시스템
동적으로 코드를 컴파일하고 연결하십시오.토토 커뮤니티항상섹션
a 정의하는 것을 잊지 마십시오."매직 블록"공유 라이브러리의 경우섹션 35.9.1.
메모리를 할당 할 때를 사용하십시오.토토 커뮤니티기능Palloc
및pfree
해당 C 라이브러리 기능 대신Malloc
및무료
.Palloc
의지
항상 구조물의 바이트를 항상 0memset
(또는 그와 함께 할당Palloc0
처음에는). 당신이 할당하더라도
대부분의 내부토토 커뮤니티유형은postgres.hpg_function_args등)fmgr.h, 적어도 이것들을 포함시켜야합니다.postgres.h 첫 번째, 다른 시스템 또는postgres.h포함elog.h및Palloc.h당신을 위해.
객체 파일 내에 정의 된 기호 이름은 충돌해서는 안됩니다.토토 커뮤니티서버 실행 가능. 당신은해야 할 것입니다
사용하기 전에토토 커뮤니티C로 작성된 확장 기능공유 라이브러리만들어야합니다.
이 섹션에 포함 된 것 이상의 정보는 귀하에게CC및 링크 편집기,LD. 또한토토 커뮤니티소스 코드에는 여러 가지가 포함되어 있습니다Contrib디렉토리. 이 예제에 의존하면 모듈을 만듭니다.토토 커뮤니티소스 코드.
공유 라이브러리 생성은 일반적으로 링크와 유사합니다위치 독립 코드 (PIC)는 개념적으로 의미합니다
다음 예에서는 소스 코드가foo.c그리고 우리는 공유를 만들 것입니다.so. 중간 물체foo.o
생성 할 컴파일러 플래그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. 그만큼-shared. 완전한 예는 다음과 같습니다.
cc -fpic -c foo.c
여기 예입니다. 개발자 도구가 있다고 가정합니다
CC -C foo.c
생성 할 컴파일러 플래그PICis-fpic. 을 위한ELF시스템, 컴파일러-shared공유 링크에 사용됩니다ld사용됩니다.
gcc -fpic -c foo.c
생성 할 컴파일러 플래그PICis-fpic. ld -Bsharable공유 링크에 사용됩니다
gcc -fpic -c foo.c
생성 할 컴파일러 플래그PICis-kpic-fpicwithGCC. 공유 라이브러리를 연결하려면 컴파일러를 연결합니다-g컴파일러 또는-sharedwithGCC.
cc -kpic -c foo.c
또는
gcc -fpic -c foo.c
PIC기본값입니다LD특별 옵션이있는 링크를 수행하는 데 사용됩니다.
CC -C foo.c
동일한 절차가 시스템 대신 GCC와 함께 사용됩니다.
생성 할 컴파일러 플래그PICis-K PIC-fpicwithGCC. 공유 라이브러리를 연결하려면 컴파일러를 연결합니다-gSCO 컴파일러와-sharedwithGCC.
CC -K PIC -C FOO.C
또는
gcc -fpic -c foo.c
팁 :이것이 너무 복잡하다면, 당신은해야합니다gnu libtool,
결과 공유 라이브러리 파일을로드 할 수 있습니다토토 커뮤니티. 지정할 때함수 만들기명령,.so또는.SL)에서 생략 할 수 있습니다함수 만들기명령. 일반적으로
다시 참조섹션서버가 공유를 찾을 예정인 위치 정보
복합 유형에는 C 구조와 같은 고정 레이아웃이 없습니다.토토 커뮤니티복합 필드에 액세스하기위한 함수 인터페이스를 제공합니다
쿼리에 응답하기 위해 함수를 작성하고 싶다고 가정 해 봅시다 :
이름, C_overpaid (EMP, 1500)를 초과 지불로 선택하십시오
Call Concentions 버전 0 사용, 우리는 정의 할 수 있습니다c_overpaid
as :
#include "postgres.h"
버전 -1 코딩에서 위는 다음과 같습니다.
#include "postgres.h"
getAttributeByName
토토 커뮤니티시스템 기능HeappupleHeader함수, 이름으로 전달되었습니다getAttributeByName
반환 aDatum적절한 데이터로 변환 할 수있는 값Datumgetxxx()
매크로. 널 플래그가 있으면 반환 값은 의미가 없습니다.
또한getAttributeBynum
,
다음 명령은 함수를 선언합니다c_overpaid
sql :
함수 생성 C_OVERPAID (EMP, Integer)는 부울을 반환합니다디렉토리/funcs ','c_overpaid '
우리가 사용한 통지엄격한그래서 우리
c- 언어에서 행 또는 복합 유형 값을 반환하려면
#include "funcapi.h"
복합 데이터 값을 구축 할 수있는 두 가지 방법이 있습니다."튜플") : 구축 할 수 있습니다tupledesc디스크립터tupledesctoBlessTupledesc
그리고 전화heap_form_tuple
각 행에 대해. ctupledesctotupledescgetattinmetadata
BuildTupleFromCstrings
각각
필요한 것을 설정하기 위해 여러 도우미 기능을 사용할 수 있습니다tupledesc. 권장하는 방법
saptuncclass get_call_result_type (functioncallinfo fcinfo,
같은 통과fcinfo구조물이 통과되었습니다resultTypeid|NULL또는 로컬 변수의 주소로resultTupledesc지역의 주소 여야합니다tupledesc변수. 그것을 확인하십시오saptionfunc_composite; 그렇다면,resultTupledesctupledesc. (그렇지 않다면, 당신"함수 반환 레코드는 맥락에서 불가능합니다.)
팁 :
get_call_result_type
실제 유형의 다형성 기능 결과를 해결할 수 있습니다. 그래서resultTypeid출력은 주로 유용합니다
참고 :
get_call_result_type
형제 자매get_expr_result_type
,get_func_result_type
레코드및get_func_result_type
다형성을 해결할 수 없습니다get_call_result_type
.
획득하기위한 구식, 현재 배제 함수tupledescs는 :
tupledesc relationnamegetTupledesc (const char *relname)
atupledesc행 유형의 경우
tupledesc typegetTupledesc (Oid typeoid, list *colaliases)
atupledesc유형을 기준으로합니다tupledesc베이스 또는 복합 유형의 경우. 그것은 할 것입니다레코드그러나 해결할 수 없습니다
일단 당신이 atupledesc, 호출 :
tupledesc blesstupledesc (tupledesc tupdesc)
Datums와 함께 일할 계획 인 경우 :
Attinmetadata *tupledescgetattinmetadata (tupledesc tupdesc)
C 문자열로 작업하려는 경우. 당신이 쓰는 경우 aFUNCCALLCONTEXT구조 - 사용tuple_desc또는Attinmeta필드
Datums에서 작업 할 때 :
heappuple heap_form_tuple (tupledesc tupdesc, datum *값, bool *isnull)
aHeappuple사용자 데이터가 주어졌습니다
C 문자열로 작업 할 때 :
Heappuple buildtupleffflflfflflings (Attinmetadata *Attinmeta, char ** value)
aHeappuple사용자 데이터가 주어졌습니다값c값배열을 설정해야합니다NULL. 이 기능은 다시 호출해야합니다
일단 기능에서 돌아 오기 위해 튜플을 구축 한 후에는Datum. 사용:
HeappupleGetDatum (Heptuple Tuple)
변환Heappuple유효한Datum직접 반환 할 수 있습니다
다음 섹션에 예제가 나타납니다.
반품 지원을 제공하는 특별한 API도 있습니다.funcapi.h, AS
세트 리턴 기능 (SRF)는 반환되는 각 항목마다 한 번 호출됩니다.SRF따라서 저장해야합니다FUNCCALLCONTEXT이를 제어하기 위해 제공됩니다fcinfo-> flinfo-> fn_extraaFUNCCALLCONTEXT가로 질러
typedef struct
anSRF여러 기능을 사용합니다FUNCCALLCONTEXT구조 (그리고 그것을 찾을 것으로 예상됩니다fn_extra). 사용:
SRF_IS_FIRSTCALL ()
첫 번째 또는 A가 호출되는지 확인하려면
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_ctxISSRF가 끝났습니다. 대부분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 (retcomposite);
SQL 에서이 기능을 선언하는 한 가지 방법은 다음과 같습니다.
유형 생성 __retcomposite as (F1 Integer, F2 Integer, F3 Integer);filename','retcomposite '
다른 방법은 매개 변수를 사용하는 것입니다 :
함수 retcomposite 생성 또는 교체 (정수, 정수,filename','retcomposite '
이 방법에서는 함수의 출력 유형이레코드타입.
디렉토리Contrib/TableFunc소스 분포의 모듈에는 더 많은 예가 포함됩니다
C- 언어 함수는Anylement, AnyArray, AnynonArray, AnyEnum및AnyRange. 보다섹션다형성에 대한 자세한 설명fmgr.h허용 aget_fn_expr_rettype (fmgrinfo및get_fn_expr_argtype (fmgrinfo. 결과 또는 인수 유형을 반환합니다Invalidoid정보가있는 경우flinfoISfcinfo-> flinfo.Argnum| 0 기반입니다.get_call_result_type
도 사용할 수 있습니다get_fn_expr_rettype
. 또한get_fn_expr_variadic
Variadic "Any"함수, 그러한 병합은 항상 발생했기 때문입니다
예를 들어, 우리가 수락 할 함수를 작성하고 싶다고 가정합니다.
pg_function_info_v1 (make_array);
다음 명령은 함수를 선언합니다make_array
sql :
함수 생성 make_array (Anylement)는 anyArray를 반환합니다디렉토리/funcs ','make_array '
이용 가능한 다형성의 변형이 있습니다."Any". (이 유형 이름은해야합니다Anylement그렇지 않은 경우를 제외하고"Any"논쟁Variadic "Any". 이것은 하나 또는 일치합니다아님정상적인 variadic과 마찬가지로 배열로 모여pg_nargs ()
매크로 및 방법variadic함수 호출의 키워드get_fn_expr_variadic
실제를 감지합니다variadic.
계획 중에 일부 함수 호출을 단순화 할 수 있습니다.int4mul (n, 1)그냥 단순화 될 수 있습니다n. 이러한 기능 별 최적화를 정의하려면변환 함수를 배치하십시오원형 변형필드PG_PROC입력. 그만큼돌기 (내부) 내부 반환. 그만큼funcexpr *, 더미입니다NULL포인터아님SQL NULL).
우리는 그것을 보장하지 않습니다토토 커뮤니티기본을 결코 호출하지 않습니다
현재이 시설은 SQL의 사용자에게 노출되지 않습니다.
애드 인은 LWLOCKS 및 공유 메모리 할당을 예약 할 수 있습니다.shared_preload_libraries.
void requestAdDinshMemsPace (int size)
에서_pg_init
기능.
LWLOCKS는 다음과 같이 예약됩니다.
void requestAdDinlWlocks (int n)
From_pg_init
.
가능한 경주 조건을 피하려면 각 백엔드가 사용해야합니다addinshmeminitlock
언제
정적 mystruct *ptr = null;
비록토토 커뮤니티백엔드
백엔드에서 액세스하는 모든 기능은 C 인터페이스를 제공해야합니다.extern c연결이 필요합니다
적절한 거래 방법을 사용한 무료 메모리. 을 위한palloc ()
, 사용pfree ()
그것을 자유롭게하려면. C ++ 사용삭제
그러한 경우 실패합니다.
C 코드로 전파되는 예외를 방지합니다 (사용extern함수). C ++ 코드가 그렇지 않은 경우에도 필요합니다.-fno-exceptionstonew ()
.
C ++ 코드에서 백엔드 기능을 호출하는 경우 C ++인지 확인하십시오.POD). 백엔드 오류로 인해 필요합니다longjmp ()
요약하면 C ++ 코드를 벽 뒤에 배치하는 것이 가장 좋습니다extern c