이 문서는 지원되지 않는 버전의 PostgreSQL을위한 것입니다.
당신은에 대해 같은 페이지를 보려고 할 수 있습니다PostgreSQL : 문서 : 17 : 36.10. C- 언어 사설 토토 사이트버전 또는 위에 나열된 다른 지원 버전 중 하나입니다.

35.9. 토토 커뮤니티 언어

사용자 정의 함수는 C (또는 언어로 작성할 수 있습니다."c함수"내부"기능 - 실제 코딩 규칙

현재 두 가지 다른 전화 규칙이 c"버전 1"전화pg_function_info_v1 ()매크로 기능을 요청합니다."버전 0") 함수. 언어함수 만들기isC두 경우 모두. 구식 기능입니다

35.9.1. 동적 로딩

처음로드 가능에서 사용자 정의 기능이 처음으로함수 만들기사용자 정의 c

다음 알고리즘은 공유 객체 파일을 찾는 데 사용됩니다.생성명령 :

  1. 이름이 절대 경로 인 경우 주어진 파일이로드됩니다.

  2. 이름이 문자열로 시작하면$ libdir, 그 부분은로 대체됩니다.토토 커뮤니티패키지 라이브러리 디렉토리 이름,

  3. 이름에 디렉토리 부분이 포함되어 있지 않으면 파일은 다음과 같습니다.dynamic_library_path.

  4. 그렇지 않으면 파일은 경로에서 발견되지 않았거나

이 시퀀스가 ​​작동하지 않으면 플랫폼 별 공유.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동안 만 호출됩니다

35.9.2. C- 언어의 기본 유형

토토 커뮤니티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

이제 우리는베이스를위한 가능한 모든 구조를 살펴 보았습니다.

35.9.3. 버전

우리는를 발표합니다."구식"전화

여기 몇 가지 예가 있습니다.

#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 결과를 반환하는 간단한 방법은 없습니다.

35.9.4. 버전

버전 -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소스에서

35.9.5. 글쓰기

보다 진보 된 주제로 돌아 가기 전에 논의해야합니다.토토 커뮤니티c-language functions. 함수를로드하는 것이 가능할 수 있습니다토토 커뮤니티, 이것은 일반적으로 어렵다 (경우

C 기능 작성 및 구축을위한 기본 규칙은 다음과 같습니다.

  • usePG_CONFIG-includeDir-ServerTO토토 커뮤니티서버 헤더 파일이 시스템에 설치되어 있습니다 (또는 시스템

  • 동적으로 코드를 컴파일하고 연결하십시오.토토 커뮤니티항상섹션

  • a 정의하는 것을 잊지 마십시오."매직 블록"공유 라이브러리의 경우섹션 35.9.1.

  • 메모리를 할당 할 때를 사용하십시오.토토 커뮤니티기능Pallocpfree해당 C 라이브러리 기능 대신Malloc무료.Palloc의지

  • 항상 구조물의 바이트를 항상 0memset(또는 그와 함께 할당Palloc0처음에는). 당신이 할당하더라도

  • 대부분의 내부토토 커뮤니티유형은postgres.hpg_function_args등)fmgr.h, 적어도 이것들을 포함시켜야합니다.postgres.h 첫 번째, 다른 시스템 또는postgres.h포함elog.hPalloc.h당신을 위해.

  • 객체 파일 내에 정의 된 기호 이름은 충돌해서는 안됩니다.토토 커뮤니티서버 실행 가능. 당신은해야 할 것입니다

35.9.6. 컴파일 및

사용하기 전에토토 커뮤니티C로 작성된 확장 기능공유 라이브러리만들어야합니다.

이 섹션에 포함 된 것 이상의 정보는 귀하에게CC및 링크 편집기,LD. 또한토토 커뮤니티소스 코드에는 여러 가지가 포함되어 있습니다Contrib디렉토리. 이 예제에 의존하면 모듈을 만듭니다.토토 커뮤니티소스 코드.

공유 라이브러리 생성은 일반적으로 링크와 유사합니다위치 독립 코드 (PIC)는 개념적으로 의미합니다

다음 예에서는 소스 코드가foo.c그리고 우리는 공유를 만들 것입니다.so. 중간 물체foo.o

freebsd

생성 할 컴파일러 플래그PICis-fpic. 생성합니다-shared.

gcc -fpic -c foo.c

버전 3.0에서 적용 가능freebsd.

hp-ux

생성 할 시스템 컴파일러의 컴파일러 플래그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공유 라이브러리의 경우 대부분과 달리

irix

PIC기본값입니다-shared.

CC -C foo.c
Linux

생성 할 컴파일러 플래그PICis-fpic. 그만큼-shared. 완전한 예는 다음과 같습니다.

cc -fpic -c foo.c
Mac OS X

여기 예입니다. 개발자 도구가 있다고 가정합니다

CC -C foo.c
netbsd

생성 할 컴파일러 플래그PICis-fpic. 을 위한ELF시스템, 컴파일러-shared공유 링크에 사용됩니다ld사용됩니다.

gcc -fpic -c foo.c
OpenBSD

생성 할 컴파일러 플래그PICis-fpic. ld -Bsharable공유 링크에 사용됩니다

gcc -fpic -c foo.c
Solaris

생성 할 컴파일러 플래그PICis-kpic-fpicwithGCC. 공유 라이브러리를 연결하려면 컴파일러를 연결합니다-g컴파일러 또는-sharedwithGCC.

cc -kpic -c foo.c

또는

gcc -fpic -c foo.c
TRU64 UNIX

PIC기본값입니다LD특별 옵션이있는 링크를 수행하는 데 사용됩니다.

CC -C foo.c

동일한 절차가 시스템 대신 GCC와 함께 사용됩니다.

unixware

생성 할 컴파일러 플래그PICis-K PIC-fpicwithGCC. 공유 라이브러리를 연결하려면 컴파일러를 연결합니다-gSCO 컴파일러와-sharedwithGCC.

CC -K PIC -C FOO.C

또는

gcc -fpic -c foo.c

팁 :이것이 너무 복잡하다면, 당신은해야합니다gnu libtool,

결과 공유 라이브러리 파일을로드 할 수 있습니다토토 커뮤니티. 지정할 때함수 만들기명령,.so또는.SL)에서 생략 할 수 있습니다함수 만들기명령. 일반적으로

다시 참조섹션서버가 공유를 찾을 예정인 위치 정보

35.9.7.

복합 유형에는 C 구조와 같은 고정 레이아웃이 없습니다.토토 커뮤니티복합 필드에 액세스하기위한 함수 인터페이스를 제공합니다

쿼리에 응답하기 위해 함수를 작성하고 싶다고 가정 해 봅시다 :

이름, C_overpaid (EMP, 1500)를 초과 지불로 선택하십시오

Call Concentions 버전 0 사용, 우리는 정의 할 수 있습니다c_overpaidas :

#include "postgres.h"

버전 -1 코딩에서 위는 다음과 같습니다.

#include "postgres.h"

getAttributeByName토토 커뮤니티시스템 기능HeappupleHeader함수, 이름으로 전달되었습니다getAttributeByName반환 aDatum적절한 데이터로 변환 할 수있는 값Datumgetxxx()매크로. 널 플래그가 있으면 반환 값은 의미가 없습니다.

또한getAttributeBynum,

다음 명령은 함수를 선언합니다c_overpaidsql :

함수 생성 C_OVERPAID (EMP, Integer)는 부울을 반환합니다디렉토리/funcs ','c_overpaid '

우리가 사용한 통지엄격한그래서 우리

35.9.8.

c- 언어에서 행 또는 복합 유형 값을 반환하려면

#include "funcapi.h"

복합 데이터 값을 구축 할 수있는 두 가지 방법이 있습니다."튜플") : 구축 할 수 있습니다tupledesc디스크립터tupledesctoBlessTupledesc그리고 전화heap_form_tuple각 행에 대해. ctupledesctotupledescgetattinmetadataBuildTupleFromCstrings각각

필요한 것을 설정하기 위해 여러 도우미 기능을 사용할 수 있습니다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직접 반환 할 수 있습니다

다음 섹션에 예제가 나타납니다.

35.9.9. 반환 세트

반품 지원을 제공하는 특별한 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소스 분포의 모듈에는 더 많은 예가 포함됩니다

35.9.10.

C- 언어 함수는Anylement, AnyArray, AnynonArray, AnyEnumAnyRange. 보다섹션다형성에 대한 자세한 설명fmgr.h허용 aget_fn_expr_rettype (fmgrinfoget_fn_expr_argtype (fmgrinfo. 결과 또는 인수 유형을 반환합니다Invalidoid정보가있는 경우flinfoISfcinfo-> flinfo.Argnum| 0 기반입니다.get_call_result_type도 사용할 수 있습니다get_fn_expr_rettype. 또한get_fn_expr_variadicVariadic "Any"함수, 그러한 병합은 항상 발생했기 때문입니다

예를 들어, 우리가 수락 할 함수를 작성하고 싶다고 가정합니다.

pg_function_info_v1 (make_array);

다음 명령은 함수를 선언합니다make_arraysql :

함수 생성 make_array (Anylement)는 anyArray를 반환합니다디렉토리/funcs ','make_array '

이용 가능한 다형성의 변형이 있습니다."Any". (이 유형 이름은해야합니다Anylement그렇지 않은 경우를 제외하고"Any"논쟁Variadic "Any". 이것은 하나 또는 일치합니다아님정상적인 variadic과 마찬가지로 배열로 모여pg_nargs ()​​매크로 및 방법variadic함수 호출의 키워드get_fn_expr_variadic실제를 감지합니다variadic.

35.9.11. 기능 변환

계획 중에 일부 함수 호출을 단순화 할 수 있습니다.int4mul (n, 1)그냥 단순화 될 수 있습니다n. 이러한 기능 별 최적화를 정의하려면변환 함수를 배치하십시오원형 변형필드PG_PROC입력. 그만큼돌기 (내부) 내부 반환. 그만큼funcexpr *, 더미입니다NULL포인터아님SQL NULL).

우리는 그것을 보장하지 않습니다토토 커뮤니티기본을 결코 호출하지 않습니다

현재이 시설은 SQL의 사용자에게 노출되지 않습니다.

35.9.12. 공유

애드 인은 LWLOCKS 및 공유 메모리 할당을 예약 할 수 있습니다.shared_preload_libraries.

void requestAdDinshMemsPace (int size)

에서_pg_init기능.

LWLOCKS는 다음과 같이 예약됩니다.

void requestAdDinlWlocks (int n)

From_pg_init.

가능한 경주 조건을 피하려면 각 백엔드가 사용해야합니다addinshmeminitlock언제

정적 mystruct *ptr = null;

35.9.13.

비록토토 커뮤니티백엔드

  • 백엔드에서 액세스하는 모든 기능은 C 인터페이스를 제공해야합니다.extern c연결이 필요합니다

  • 적절한 거래 방법을 사용한 무료 메모리. 을 위한palloc (), 사용pfree ()그것을 자유롭게하려면. C ++ 사용삭제그러한 경우 실패합니다.

  • C 코드로 전파되는 예외를 방지합니다 (사용extern함수). C ++ 코드가 그렇지 않은 경우에도 필요합니다.-fno-exceptionstonew ().

  • C ++ 코드에서 백엔드 기능을 호출하는 경우 C ++인지 확인하십시오.POD). 백엔드 오류로 인해 필요합니다longjmp ()

요약하면 C ++ 코드를 벽 뒤에 배치하는 것이 가장 좋습니다extern c