libpq의 토토 결과 시스템은 등록된 토토 결과 핸들러에게 흥미로운 내용을 알리도록 설계되었습니다.libpq생성 또는 파괴와 같은 토토 결과PGconn그리고PGresult객체. 주요 사용 사례는 이를 통해 애플리케이션이 자신의 데이터를PGconn또는PGresult그리고 해당 데이터가 적절한 시기에 해제되었는지 확인하세요.
등록된 각 이벤트 핸들러는 다음과 같은 두 가지 데이터와 연결되어 있습니다.libpq불투명하게만무효 *포인터. 가 있습니다.통과토토 결과 핸들러가 등록될 때 애플리케이션에서 제공하는 포인터PGconn. 통과 포인터는의 수명 동안 변경되지 않습니다.PGconn그리고 모두PGresult10659_10752인스턴스 데이터시작하는 포인터NULL매번PGconn그리고PGresult. 이 포인터는를 사용하여 조작할 수 있습니다.PQinstanceData, PQsetInstanceData, PQresultInstanceData그리고PQresultSetInstanceData함수. 통과 포인터와 달리 a의 인스턴스 데이터는PGconn다음에 의해 자동으로 상속되지 않습니다.PGresult그것으로부터 생성되었습니다.libpq통과 및 인스턴스 데이터 포인터가 무엇을 가리키는지 알지 못하며(있는 경우) 이를 해제하려고 시도하지 않습니다. 이는 이벤트 핸들러의 책임입니다.
열거형PGEventId토토 결과 시스템이 처리하는 토토 결과 유형의 이름을 지정합니다. 모든 값의 이름은PGEVT. 각 이벤트 유형마다 이벤트 핸들러에 전달된 매개변수를 전달하는 해당 이벤트 정보 구조가 있습니다. 이벤트 유형은 다음과 같습니다.
PGEVT_REGISTER #등록 이벤트는 다음과 같은 경우에 발생합니다.PQregisterEventProc호출됩니다. 지금은 초기화하기에 가장 좋은 시기입니다.instanceData토토 결과 절차가 필요할 수 있습니다. 연결당 토토 결과 핸들러당 하나의 등록 토토 결과만 실행됩니다. 토토 결과 프로시저가 실패하면(0을 반환) 등록이 취소됩니다.
typedef 구조체
    PGconn *콘;
 PGEventRegister;
          때PGEVT_REGISTER토토 결과가 수신되었습니다.evtInfo포인터는 a로 캐스팅되어야 합니다.PGEvent등록 *. 이 구조에는PGconn그건 다음에 있어야 합니다CONNECTION_OK상태; 전화하면 보장됨PQregisterEventProc상품을 얻은 직후PGconn. 실패 코드를 반환할 때 모든 정리는 no로 수행되어야 합니다PGEVT_CONNDESTROY토토 결과가 전송됩니다.
PGEVT_CONNRESET #연결 재설정 토토 결과는 완료 시 시작됩니다.PQreset또는PQresetPoll. 두 경우 모두 재설정이 성공한 경우에만 이벤트가 시작됩니다. 이벤트 프로시저의 반환 값은 다음에서 무시됩니다.PostgreSQLv15 이상. 그러나 이전 버전에서는 성공(0이 아님)을 반환하는 것이 중요합니다. 그렇지 않으면 연결이 중단됩니다.
typedef 구조체
    PGconn *콘;
 PGEventConnReset;
          때PGEVT_CONNRESET토토 결과가 수신되었습니다.evtInfo포인터는 a로 캐스팅되어야 합니다.PGEventConnReset *. 포함되어 있지만PGconn방금 재설정되었으므로 모든 토토 결과 데이터는 변경되지 않습니다. 이 토토 결과는 연관된 모든 것을 재설정/다시 로드/재쿼리하는 데 사용되어야 합니다.인스턴스데이터. 토토 결과 프로시저가 처리에 실패하더라도 참고하세요PGEVT_CONNRESET, 여전히를 수신합니다.PGEVT_CONNDESTROY연결이 종료될 때의 토토 결과입니다.
PGEVT_CONNDESTROY #다음에 대한 응답으로 연결 파괴 이벤트가 시작됩니다.PQfinish. libpq에는 이 메모리를 관리할 수 있는 기능이 없으므로 해당 이벤트 데이터를 적절하게 정리하는 것은 이벤트 프로시저의 책임입니다. 정리하지 않으면 메모리 누수가 발생합니다.
typedef 구조체
    PGconn *콘;
 PGEventConnDestroy;
          때PGEVT_CONNDESTROY토토 결과가 수신되었습니다.evtInfo포인터는 a로 캐스팅되어야 합니다.PGEventConnDestroy *. 이 이벤트는 다음 날짜 이전에 시작됩니다.PQfinish다른 정리를 수행 중입니다. 실패를 표시할 방법이 없으므로 토토 결과 프로시저의 반환 값은 무시됩니다.PQfinish. 또한 토토 결과 프로시저 오류로 인해 원치 않는 메모리 정리 프로세스가 중단되어서는 안 됩니다.
PGEVT_RESULTCREATE #결과 생성 이벤트는 다음을 포함하여 결과를 생성하는 모든 쿼리 실행 함수에 대한 응답으로 시작됩니다.PQgetResult. 이 토토 결과는 결과가 성공적으로 생성된 후에만 시작됩니다.
typedef 구조체
    PGconn *콘;
    PGresult *결과;
 PGEventResultCreate;
          때PGEVT_RESULTCREATE토토 결과가 수신되었습니다.evtInfo포인터는 a로 캐스팅되어야 합니다.PGEventResultCreate *.콘은 결과를 생성하는 데 사용되는 연결입니다. 이곳은 무엇이든 초기화하기에 이상적인 장소입니다.인스턴스데이터결과와 연결되어야 합니다. 토토 결과 프로시저가 실패하면(0을 반환) 해당 토토 결과 프로시저는 결과의 남은 수명 동안 무시됩니다. 즉, 수신되지 않습니다.PGEVT_RESULTCOPY또는PGEVT_RESULTDESTROY이 결과 또는 여기에서 복사된 결과에 대한 토토 결과.
PGEVT_RESULTCOPY #다음에 대한 응답으로 결과 복사 이벤트가 시작됩니다.PQcopyResult. 이 토토 결과는 복사가 완료된 후에만 시작됩니다. 성공적으로 처리한 토토 결과 프로시저만PGEVT_RESULTCREATE또는PGEVT_RESULTCOPY소스 결과에 대한 토토 결과가 수신됩니다PGEVT_RESULTCOPY토토 결과.
typedef 구조체
    const PGresult *src;
    PGresult *dest;
 PGEventResultCopy;
          언제PGEVT_RESULTCOPY토토 결과가 수신되었습니다.evtInfo포인터는 a로 캐스팅되어야 합니다.PGEventResultCopy *.src결과는 다음 동안 복사된 것입니다.대상결과는 복사 대상입니다. 이 이벤트는 다음의 전체 복사본을 제공하는 데 사용될 수 있습니다.instanceData, 이후PQcopyResult그렇게 할 수 없습니다. 토토 결과 프로시저가 실패하면(0을 반환) 새 결과의 남은 수명 동안 해당 토토 결과 프로시저가 무시됩니다. 즉, 수신되지 않습니다.PGEVT_RESULTCOPY또는PGEVT_RESULTDESTROY해당 결과 또는 복사된 결과에 대한 토토 결과.
PGEVT_RESULTDESTROY #결과 삭제 이벤트는 다음에 대한 응답으로 시작됩니다.PQclear. libpq에는 이 메모리를 관리할 수 있는 기능이 없으므로 해당 이벤트 데이터를 적절하게 정리하는 것은 이벤트 프로시저의 책임입니다. 정리하지 않으면 메모리 누수가 발생합니다.
typedef 구조체
    PGresult *결과;
 PGEventResultDestroy;
          언제PGEVT_RESULTDESTROY토토 결과가 수신되었습니다.evtInfo포인터는 a로 캐스팅되어야 합니다.PGEventResultDestroy *. 이 이벤트는 다음 날짜 이전에 시작됩니다.PQclear다른 정리를 수행 중입니다. 실패를 표시할 방법이 없으므로 토토 결과 프로시저의 반환 값은 무시됩니다.PQclear. 또한 토토 결과 프로시저 오류로 인해 원치 않는 메모리 정리 프로세스가 중단되어서는 안 됩니다.
PGEventProc #PGEventProc은 이벤트 프로시저, 즉 libpq에서 이벤트를 수신하는 사용자 콜백 함수에 대한 포인터에 대한 형식 정의입니다. 이벤트 프로시저의 서명은 다음과 같아야 합니다.
int eventproc(PGEventId evtId, void *evtInfo, void *passThrough)
그evtId매개변수는 다음을 나타냅니다.PGEVT토토 결과가 발생했습니다.evtInfo22219_22328통과매개변수는 다음에 제공된 포인터입니다.PQregisterEventProc토토 결과 프로시저가 등록되었을 때. 함수는 성공하면 0이 아닌 값을 반환하고, 실패하면 0을 반환해야 합니다.
특정 토토 결과 프로시저는 한 번만 등록될 수 있습니다.PGconn. 프로시저의 주소가 연관된 인스턴스 데이터를 식별하는 조회키로 사용되기 때문입니다.
Windows에서 함수는 두 개의 서로 다른 주소를 가질 수 있습니다. 하나는 DLL 외부에서 볼 수 있고 다른 하나는 DLL 내부에서 볼 수 있습니다. 이 주소 중 하나만 사용된다는 점에 주의해야 합니다.libpq의 토토 결과 절차 기능을 사용하지 않으면 혼란이 발생합니다. 작동하는 코드 작성을 위한 가장 간단한 규칙은 토토 결과 프로시저가 선언되었는지 확인하는 것입니다.정적. 프로시저의 주소를 자체 소스 파일 외부에서 사용할 수 있어야 하는 경우 주소를 반환하는 별도의 함수를 노출하세요.
PQregisterEventProc #libpq로 이벤트 콜백 프로시저를 등록합니다.
int PQregisterEventProc(PGconn *conn, PGEventProc proc,
                        const char *이름, void *passThrough);
          토토 결과 프로시저는 각각에 한 번씩 등록되어야 합니다.PGconn토토 결과를 수신하고 싶습니다. 연결에 등록할 수 있는 토토 결과 프로시저 수에는 메모리 외에는 제한이 없습니다. 이 함수는 성공하면 0이 아닌 값을 반환하고 실패하면 0을 반환합니다.
그proclibpq 이벤트가 시작되면 인수가 호출됩니다. 해당 메모리 주소는 조회에도 사용됩니다.instanceData.이름인수는 오류 메시지에서 토토 결과 프로시저를 참조하는 데 사용됩니다. 이 값은 될 수 없습니다.NULL또는 길이가 0인 문자열. 이름 문자열은PGconn, 따라서 통과된 것은 오래 지속될 필요가 없습니다.통과포인터가 다음에 전달되었습니다.proc이벤트가 발생할 때마다. 이 인수는 다음과 같습니다.NULL.
PQsetInstanceData #연결을 설정합니다콘'sinstanceData절차용proc에데이터. 성공하면 0이 아닌 값을 반환하고 실패하면 0을 반환합니다. (실패는 다음의 경우에만 가능합니다.proc다음에 제대로 등록되지 않았습니다.콘.)
int PQsetInstanceData(PGconn *conn, PGEventProc proc, void *data);
PQinstanceData #연결을 반환합니다.콘's인스턴스데이터프로시저와 연결됨proc또는NULL아무것도 없다면.
void *PQinstanceData(const PGconn *conn, PGEventProc proc);
PQresultSetInstanceData #결과를 설정합니다인스턴스데이터용proc에데이터. 성공하면 0이 아닌 값을 반환하고 실패하면 0을 반환합니다. (실패는 다음의 경우에만 가능합니다.proc결과에 제대로 등록되지 않았습니다.)
int PQresultSetInstanceData(PGresult *res, PGEventProc proc, void *data);
다음으로 표시되는 저장소를 조심하세요.데이터다음에 의해 설명되지 않습니다.PQresultMemorySize, 다음을 사용하여 할당되지 않은 경우PQresultAlloc. (그렇게 하면 결과가 삭제될 때 해당 저장소를 명시적으로 해제할 필요가 없기 때문에 권장됩니다.)
PQresultInstanceData #결과를 반환합니다인스턴스데이터다음과 연결됨proc또는NULL아무것도 없다면.
void *PQresultInstanceData(const PGresult *res, PGEventProc proc);
다음은 libpq 연결 및 결과와 관련된 개인 데이터를 관리하는 기본 예입니다.
/* libpq 이벤트에 필요한 헤더(참고: libpq-fe.h 포함) */
#include <libpq-events.h
/* 인스턴스 데이터 */
typedef 구조체
    int n;
    문자 *str;
 마이데이터;
/* PGEventProc */
static int myEventProc(PGEventId evtId, void *evtInfo, void *passThrough);
정수
메인(공허)
    마이데이터 *데이터;
    PGresult *res;
    PGconn *콘 =
        PQconnectdb("dbname=postgres 옵션=-csearch_path=");
    if (PQstatus(conn) != CONNECTION_OK)
        /* PQerrorMessage의 결과에는 후행 개행 문자가 포함됩니다 */
        fprintf(stderr, "%s", PQerrorMessage(conn));
        PQfinish(콘);
        1을 반환합니다.
    /* 이벤트를 수신해야 하는 모든 연결에서 한 번 호출됩니다.
     * myEventProc에 PGEVT_REGISTER를 보냅니다.
     */
    if (!PQregisterEventProc(conn, myEventProc, "mydata_proc", NULL))
        fprintf(stderr, "PGEventProc를 등록할 수 없습니다\n");
        PQfinish(콘);
        1을 반환합니다.
    /* conn 인스턴스 데이터를 사용할 수 있습니다 */
    데이터 = PQinstanceData(conn, myEventProc);
    /* myEventProc에 PGEVT_RESULTCREATE를 보냅니다 */
    res = PQexec(conn, "SELECT 1 + 1");
    /* 결과 인스턴스 데이터를 사용할 수 있습니다 */
    데이터 = PQresultInstanceData(res, myEventProc);
    /* PG_COPYRES_EVENTS가 사용되면 PGEVT_RESULTCOPY를 myEventProc에 보냅니다. */
    res_copy = PQcopyResult(res, PG_COPYRES_TUPLES | PG_COPYRES_EVENTS);
    /* PG_COPYRES_EVENTS가 있는 경우 결과 인스턴스 데이터를 사용할 수 있습니다.
     * PQcopyResult 호출 중에 사용됩니다.
     */
    데이터 = PQresultInstanceData(res_copy, myEventProc);
    /* 두 지우기 모두 myEventProc에 PGEVT_RESULTDESTROY를 보냅니다. */
    PQclear(res);
    PQclear(res_copy);
    /* myEventProc에 PGEVT_CONNDESTROY를 보냅니다 */
    PQfinish(콘);
    0을 반환합니다.
정적 정수
myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
    스위치(evtId)
        PGEVT_REGISTER:
            PGEventRegister *e = (PGEventRegister *)evtInfo;
            mydata *data = get_mydata(e-conn);
            /* 앱별 데이터를 연결과 연결 */
            PQsetInstanceData(e-conn, myEventProc, data);
            부서지다;
        사례 PGEVT_CONNRESET:
            PGEventConnReset *e = (PGEventConnReset *)evtInfo;
            mydata *data = PQinstanceData(e-conn, myEventProc);
            만약 (데이터)
              memset(data, 0, sizeof(mydata));
            부서지다;
        사례 PGEVT_CONNDESTROY:
            PGEventConnDestroy *e = (PGEventConnDestroy *)evtInfo;
            mydata *data = PQinstanceData(e-conn, myEventProc);
            /* conn이 파괴되기 때문에 무료 인스턴스 데이터 */
            만약 (데이터)
              free_mydata(데이터);
            부서지다;
        PGEVT_RESULTCREATE:
            PGEventResultCreate *e = (PGEventResultCreate *)evtInfo;
            mydata *conn_data = PQinstanceData(e-conn, myEventProc);
            mydata *res_data = dup_mydata(conn_data);
            /* 앱별 데이터를 결과와 연결합니다(conn에서 복사) */
            PQresultSetInstanceData(e-result, myEventProc, res_data);
            부서지다;
        사례 PGEVT_RESULTCOPY:
            PGEventResultCopy *e = (PGEventResultCopy *)evtInfo;
            mydata *src_data = PQresultInstanceData(e-src, myEventProc);
            mydata *dest_data = dup_mydata(src_data);
            /* 앱별 데이터를 결과와 연결(결과에서 복사) */
            PQresultSetInstanceData(e-dest, myEventProc, dest_data);
            부서지다;
        사례 PGEVT_RESULTDESTROY:
            PGEventResultDestroy *e = (PGEventResultDestroy *)evtInfo;
            mydata *data = PQresultInstanceData(e-result, myEventProc);
            /* 결과가 삭제되므로 무료 인스턴스 데이터 */
            만약 (데이터)
              free_mydata(데이터);
            부서지다;
        /* 알 수 없는 이벤트 ID, true를 반환합니다. */
        기본값:
            휴식;
    사실을 반환; /* 이벤트 처리 성공 */
  문서에 올바르지 않은 내용이 있으면 일치하지 않습니다. 특정 기능에 대한 경험이 있거나 추가 설명이 필요한 경우 이용해주세요이 양식문서 문제를 보고합니다.