バージョンごとのドキュメント一覧

34.14. イベントシステム #

<title>Event System</title>

<application>libpq</application>'s event system is designed to notify registered event handlers about interesting <application>libpq</application> events, such as the creation or destruction of <structname>PGconn</structname> and <structname>PGresult</structname> objects. A principal use case is that this allows applications to associate their own data with a <structname>PGconn</structname> or <structname>PGresult</structname> and ensure that that data is freed at an appropriate time. libpqのイベントシステムは、PGconnおよびPGresultオブジェクトの作成と削除のような関心を引くlibpqイベントについて登録されたイベントハンドラに通知を行うため設計されています。 主たる使用状況は、アプリケーションがそれ自身のデータをPGconnまたはPGresultと提携させ、データが適切な時間に解放されることを保証するものです。

Each registered event handler is associated with two pieces of data, known to <application>libpq</application> only as opaque <literal>void *</literal> pointers. There is a <firstterm>pass-through</firstterm> pointer that is provided by the application when the event handler is registered with a <structname>PGconn</structname>. The pass-through pointer never changes for the life of the <structname>PGconn</structname> and all <structname>PGresult</structname>s generated from it; so if used, it must point to long-lived data. In addition there is an <firstterm>instance data</firstterm> pointer, which starts out <symbol>NULL</symbol> in every <structname>PGconn</structname> and <structname>PGresult</structname>. This pointer can be manipulated using the <xref linkend="libpq-PQinstanceData"/>, <xref linkend="libpq-PQsetInstanceData"/>, <xref linkend="libpq-PQresultInstanceData"/> and <xref linkend="libpq-PQresultSetInstanceData"/> functions. Note that unlike the pass-through pointer, instance data of a <structname>PGconn</structname> is not automatically inherited by <structname>PGresult</structname>s created from it. <application>libpq</application> does not know what pass-through and instance data pointers point to (if anything) and will never attempt to free them &mdash; that is the responsibility of the event handler. それぞれの登録されたイベントハンドラは、libpqからは不透明なvoid *ポインタとしてだけ知られる2つのデータの断片と提携します。 イベントハンドラがPGconnで登録された時にアプリケーションが提供する通過地点ポインタがあります。 通過地点ポインタはPGconnやそれから生成されたすべての(複数の)PGresultが有効な間決して変わることはありません。 したがって使用された場合、長期間生存しているデータを指し示します。 さらに、インスタンスデータポインタがあって、それはすべてのPGconnPGresultNULLから開始します。 ポインタは、PQinstanceDataPQsetInstanceDataPQresultInstanceDataおよびPQresultSetInstanceData関数を使って操作することができます。 通過地点ポインタとは異なり、PGconnのインスタンスデータはそれから作成されたPGresultにより自動的に継承されません。 libpqは通過地点とインスタンスデータポインタが(もしあったとしても)何を指し示すのか判らず、決して解放しようとは試みません。 それはイベントハンドラの責任です。

34.14.1. イベントの種類 #

<title>Event Types</title>

The enum <literal>PGEventId</literal> names the types of events handled by the event system. All its values have names beginning with <literal>PGEVT</literal>. For each event type, there is a corresponding event info structure that carries the parameters passed to the event handlers. The event types are: PGEventId列挙はイベントシステムにより処理されるイベントの種類に名前をつけます。 その値はすべてPGEVTで始まる名前を持っています。 それぞれのイベントの種類に対し、イベントハンドラに渡されるパラメータを運ぶ関連したイベント情報構造体があります。 イベントの種類を以下に示します。

PGEVT_REGISTER #

The register event occurs when <xref linkend="libpq-PQregisterEventProc"/> is called. It is the ideal time to initialize any <literal>instanceData</literal> an event procedure may need. Only one register event will be fired per event handler per connection. If the event procedure fails (returns zero), the registration is cancelled. 登録イベントはPQregisterEventProcが呼ばれたとき発生します。 イベントプロシージャが必要とするかもしれない任意のinstanceDataを初期化するために、これは理想的な機会です。 接続毎、イベントハンドラ毎でただ1つの登録イベントが発行されます。 イベントプロシージャが失敗する(ゼロが返される)と、登録はキャンセルされます。

typedef struct
{
    PGconn *conn;
} PGEventRegister;

When a <literal>PGEVT_REGISTER</literal> event is received, the <parameter>evtInfo</parameter> pointer should be cast to a <structname>PGEventRegister *</structname>. This structure contains a <structname>PGconn</structname> that should be in the <literal>CONNECTION_OK</literal> status; guaranteed if one calls <xref linkend="libpq-PQregisterEventProc"/> right after obtaining a good <structname>PGconn</structname>. When returning a failure code, all cleanup must be performed as no <literal>PGEVT_CONNDESTROY</literal> event will be sent. PGEVT_REGISTERイベントが受け取られると、evtInfoポインタはPGEventRegister *にキャストされなければなりません。 この構造体はCONNECTION_OK状態ではなくてはならないPGconnを含んでいます。 そしてそれは、効果のあるPGconnを取得した直後、PQregisterEventProcを呼び出せば、保証されます。 失敗コードを返すとき、PGEVT_CONNDESTROYイベントが送られないので、すべての消去が実行されなければなりません。

PGEVT_CONNRESET #

The connection reset event is fired on completion of <xref linkend="libpq-PQreset"/> or <function>PQresetPoll</function>. In both cases, the event is only fired if the reset was successful. The return value of the event procedure is ignored in <productname>PostgreSQL</productname> v15 and later. With earlier versions, however, it's important to return success (nonzero) or the connection will be aborted. 接続初期化イベントはPQresetまたはPQresetPollの完了時点で発行されます。 どちらの場合も、初期化が成功したときのみ発行されます。 PostgreSQLv15以降では、イベントプロシージャの返り値は無視されます。 しかし、以前のバージョンでは、成功(ゼロ以外)を返すことが重要です。 そうしないと接続は中断されます。

typedef struct
{
    PGconn *conn;
} PGEventConnReset;

When a <literal>PGEVT_CONNRESET</literal> event is received, the <parameter>evtInfo</parameter> pointer should be cast to a <structname>PGEventConnReset *</structname>. Although the contained <structname>PGconn</structname> was just reset, all event data remains unchanged. This event should be used to reset/reload/requery any associated <literal>instanceData</literal>. Note that even if the event procedure fails to process <literal>PGEVT_CONNRESET</literal>, it will still receive a <literal>PGEVT_CONNDESTROY</literal> event when the connection is closed. PGEVT_CONNRESETイベントが受け取られた時、evtInfoポインタはPGEventConnReset *にキャストされなければなりません。 含まれたPGconnは単に初期化されますが、すべてのイベントデータは変更されずに残ります。 このイベントはすべての関連したinstanceDataの初期化・再読み込み・再問い合わせに使用されなければなりません。 イベントプロシージャがPGEVT_CONNRESET処理に失敗したとしても、接続が閉じられた時PGEVT_CONNDESTROYイベントを依然として受け付けることに注意してください。

PGEVT_CONNDESTROY #

The connection destroy event is fired in response to <xref linkend="libpq-PQfinish"/>. It is the event procedure's responsibility to properly clean up its event data as libpq has no ability to manage this memory. Failure to clean up will lead to memory leaks. 接続破棄イベントはPQfinishに対応して発行されます。 libpqはこのメモリを管理する機能がありませんので、そのイベントデータを的確に消去するのはイベントプロシージャの責任です。 消去の失敗はメモリーリークに通じます。

typedef struct
{
    PGconn *conn;
} PGEventConnDestroy;

When a <literal>PGEVT_CONNDESTROY</literal> event is received, the <parameter>evtInfo</parameter> pointer should be cast to a <structname>PGEventConnDestroy *</structname>. This event is fired prior to <xref linkend="libpq-PQfinish"/> performing any other cleanup. The return value of the event procedure is ignored since there is no way of indicating a failure from <xref linkend="libpq-PQfinish"/>. Also, an event procedure failure should not abort the process of cleaning up unwanted memory. PGEVT_CONNDESTROYイベントが受け取られた時、evtInfoポインタはPGEventConnDestroy *にキャストされなければなりません。 このイベントはPQfinishが他のすべての消去を行う前に発行されます。 イベントプロシージャの戻り値は、PQfinishから失敗を示唆する方法がないので無視されます。 同時に、イベントプロシージャの失敗が不要なメモリ消去処理を中止してはなりません。

PGEVT_RESULTCREATE #

The result creation event is fired in response to any query execution function that generates a result, including <xref linkend="libpq-PQgetResult"/>. This event will only be fired after the result has been created successfully. 結果作成イベントは、PQgetResultを含み、結果を生成する任意の問い合わせ実行関数に対応して発行されます。 このイベントは結果が成功裏に作成されたときのみ発行されます。

typedef struct
{
    PGconn *conn;
    PGresult *result;
} PGEventResultCreate;

When a <literal>PGEVT_RESULTCREATE</literal> event is received, the <parameter>evtInfo</parameter> pointer should be cast to a <structname>PGEventResultCreate *</structname>. The <parameter>conn</parameter> is the connection used to generate the result. This is the ideal place to initialize any <literal>instanceData</literal> that needs to be associated with the result. If an event procedure fails (returns zero), that event procedure will be ignored for the remaining lifetime of the result; that is, it will not receive <literal>PGEVT_RESULTCOPY</literal> or <literal>PGEVT_RESULTDESTROY</literal> events for this result or results copied from it. PGEVT_RESULTCREATEイベントが受け取られた時、evtInfoポインタはPGEventResultCreate *にキャストされなければなりません。 connは結果を生成するために使われた接続です。 これは、結果と関連しなければならないすべてのinstanceDataを初期化するために、理想的な場所です。 イベントプロシージャが失敗する(ゼロが返される)と、そのイベントプロシージャは結果の残りの存在期間中無視されます。 つまり、この結果またはそこからコピーされた結果に対して、PGEVT_RESULTCOPYまたはPGEVT_RESULTDESTROYイベントを受け取りません。

PGEVT_RESULTCOPY #

The result copy event is fired in response to <xref linkend="libpq-PQcopyResult"/>. This event will only be fired after the copy is complete. Only event procedures that have successfully handled the <literal>PGEVT_RESULTCREATE</literal> or <literal>PGEVT_RESULTCOPY</literal> event for the source result will receive <literal>PGEVT_RESULTCOPY</literal> events. 結果コピーイベントはPQcopyResultの応答として発行されます。 このイベントはコピーが完了した後にのみ発行されます。 元の結果に対するPGEVT_RESULTCREATEもしくはPGEVT_RESULTCOPYイベントを成功裏に処理したイベントプロシージャのみ、PGEVT_RESULTCOPYイベントを受け取ります。

typedef struct
{
    const PGresult *src;
    PGresult *dest;
} PGEventResultCopy;

When a <literal>PGEVT_RESULTCOPY</literal> event is received, the <parameter>evtInfo</parameter> pointer should be cast to a <structname>PGEventResultCopy *</structname>. The <parameter>src</parameter> result is what was copied while the <parameter>dest</parameter> result is the copy destination. This event can be used to provide a deep copy of <literal>instanceData</literal>, since <literal>PQcopyResult</literal> cannot do that. If an event procedure fails (returns zero), that event procedure will be ignored for the remaining lifetime of the new result; that is, it will not receive <literal>PGEVT_RESULTCOPY</literal> or <literal>PGEVT_RESULTDESTROY</literal> events for that result or results copied from it. PGEVT_RESULTCOPYイベントが受け取られた時、evtInfoポインタはPGEventResultCopy *にキャストされなければなりません。 srcは結果のコピー元で、dest結果はコピー先です。 このイベントはinstanceDataのディープコピーを提供するために使用されます。 PQcopyResultではこれを行うことができないためです。 もしイベントプロシージャが失敗する(ゼロが返される)と、そのイベントプロシージャは新しい結果の残りの存在期間中無視されます。 つまり、その結果またはそこからコピーされた結果のPGEVT_RESULTCOPYまたはPGEVT_RESULTDESTROYイベントを受け取りません。

PGEVT_RESULTDESTROY #

The result destroy event is fired in response to a <xref linkend="libpq-PQclear"/>. It is the event procedure's responsibility to properly clean up its event data as libpq has no ability to manage this memory. Failure to clean up will lead to memory leaks. 結果破棄イベントはPQclearに対応して発行されます。 libpqはこのメモリを管理する機能がありませんので、そのイベントデータを的確に消去するのはイベントプロシージャの責任です。 消去の失敗はメモリーリークに通じます。

typedef struct
{
    PGresult *result;
} PGEventResultDestroy;

When a <literal>PGEVT_RESULTDESTROY</literal> event is received, the <parameter>evtInfo</parameter> pointer should be cast to a <structname>PGEventResultDestroy *</structname>. This event is fired prior to <xref linkend="libpq-PQclear"/> performing any other cleanup. The return value of the event procedure is ignored since there is no way of indicating a failure from <xref linkend="libpq-PQclear"/>. Also, an event procedure failure should not abort the process of cleaning up unwanted memory. PGEVT_RESULTDESTROYが受け取られた時、evtInfoポインタはPGEventResultDestroy *にキャストされなければなりません。 このイベントはPQclearがその他の消去を行う以前に起動されなければなりません。 イベントプロシージャの戻り値は、PQclearから失敗を示唆する方法がないので無視されます。 同時に、イベントプロシージャの失敗が不要なメモリ消去処理を中止してはなりません。

34.14.2. イベントコールバックプロシージャ #

<title>Event Callback Procedure</title>
PGEventProc #

<literal>PGEventProc</literal> is a typedef for a pointer to an event procedure, that is, the user callback function that receives events from libpq. The signature of an event procedure must be PGEventProcはイベントプロシージャへのポインタに対するtypedefです。 つまり、libpqからイベントを受け取るユーザコールバック関数です。 イベントプロシージャのシグネチャは以下でなければなりません。

int eventproc(PGEventId evtId, void *evtInfo, void *passThrough)

The <parameter>evtId</parameter> parameter indicates which <literal>PGEVT</literal> event occurred. The <parameter>evtInfo</parameter> pointer must be cast to the appropriate structure type to obtain further information about the event. The <parameter>passThrough</parameter> parameter is the pointer provided to <xref linkend="libpq-PQregisterEventProc"/> when the event procedure was registered. The function should return a non-zero value if it succeeds and zero if it fails. evtIdパラメータはどのPGEVTイベントが発生したかを示します。 evtInfoポインタは、イベントに対する追加情報を入手するため適切な構造体型にキャストされなければなりません。 passThroughパラメータは、イベントプロシージャが登録された時、PQregisterEventProcに提供されるポインタです。 関数は成功した場合非ゼロを、失敗した場合ゼロを返さなければなりません。

A particular event procedure can be registered only once in any <structname>PGconn</structname>. This is because the address of the procedure is used as a lookup key to identify the associated instance data. 特定のイベントプロシージャは任意のPGconnにおいて一回だけ登録できます。 これは、プロシージャのアドレスが関連するインスタンスデータを特定する検索キーとして用いられるからです。

注意

On Windows, functions can have two different addresses: one visible from outside a DLL and another visible from inside the DLL. One should be careful that only one of these addresses is used with <application>libpq</application>'s event-procedure functions, else confusion will result. The simplest rule for writing code that will work is to ensure that event procedures are declared <literal>static</literal>. If the procedure's address must be available outside its own source file, expose a separate function to return the address. Windowsにおいて、関数は2つの異なるアドレスを持つことができます。 外部から可視のDLLと内部から可視のDLLです。 libpqのイベントプロシージャ関数ではこれらのアドレスのうちの1つだけが使用されることに注意してください。 さもないと、混乱が起きます。 正常に機能するコードを書く最も単純な規則は、イベントプロシージャがstaticとして宣言されることを確実にすることです。 もし、プロシージャのアドレスがそれ自身のファイルの外部から有効とならなければならない場合、アドレスを返すため別の関数を公開します。

34.14.3. イベントサポート関数 #

<title>Event Support Functions</title>
PQregisterEventProc #

Registers an event callback procedure with libpq. libpqでイベントコールバックプロシージャを登録します。

int PQregisterEventProc(PGconn *conn, PGEventProc proc,
                        const char *name, void *passThrough);

An event procedure must be registered once on each <structname>PGconn</structname> you want to receive events about. There is no limit, other than memory, on the number of event procedures that can be registered with a connection. The function returns a non-zero value if it succeeds and zero if it fails. そのイベントを取得したいそれぞれのPGconnで1回イベントプロシージャは登録されなければなりません。 一つの接続に登録できるイベントプロシージャの数には、メモリ以外の制限はありません。 関数は成功した場合非ゼロ、失敗の場合ゼロを返します。

The <parameter>proc</parameter> argument will be called when a libpq event is fired. Its memory address is also used to lookup <literal>instanceData</literal>. The <parameter>name</parameter> argument is used to refer to the event procedure in error messages. This value cannot be <symbol>NULL</symbol> or a zero-length string. The name string is copied into the <structname>PGconn</structname>, so what is passed need not be long-lived. The <parameter>passThrough</parameter> pointer is passed to the <parameter>proc</parameter> whenever an event occurs. This argument can be <symbol>NULL</symbol>. libpqイベントが発行されたときproc引数が呼ばれます。 そのメモリアドレスはinstanceDataを検索するのにも使用されます。 name引数はエラーメッセージ内でイベントプロシージャを参照するために使用されます。 この値はNULLもしくは空文字列であってはなりません。 このname文字列はPGconnにコピーされますので、渡されたものは長寿命である必要がありません。 passThroughポインタはイベントが発生した時はいつでもprocに渡されます。 この引数はNULLであっても構いません。

PQsetInstanceData #

Sets the connection <parameter>conn</parameter>'s <literal>instanceData</literal> for procedure <parameter>proc</parameter> to <parameter>data</parameter>. This returns non-zero for success and zero for failure. (Failure is only possible if <parameter>proc</parameter> has not been properly registered in <parameter>conn</parameter>.) procプロシージャに対するconn接続のinstanceDatadataに設定します。 成功の場合非ゼロ、失敗の場合ゼロが返ります。 (connprocが正しく登録されていない場合のみ失敗する可能性があります。)

int PQsetInstanceData(PGconn *conn, PGEventProc proc, void *data);

PQinstanceData #

Returns the connection <parameter>conn</parameter>'s <literal>instanceData</literal> associated with procedure <parameter>proc</parameter>, or <symbol>NULL</symbol> if there is none. procプロシージャに関連したconn接続のinstanceData、または存在しなければNULLを返します。

void *PQinstanceData(const PGconn *conn, PGEventProc proc);

PQresultSetInstanceData #

Sets the result's <literal>instanceData</literal> for <parameter>proc</parameter> to <parameter>data</parameter>. This returns non-zero for success and zero for failure. (Failure is only possible if <parameter>proc</parameter> has not been properly registered in the result.) procに対する結果のinstanceDatadataに設定します。 成功の場合非ゼロ、失敗の場合ゼロが返ります。 (結果でproc正しく登録されていない場合のみ失敗する可能性があります。)

int PQresultSetInstanceData(PGresult *res, PGEventProc proc, void *data);

Beware that any storage represented by <parameter>data</parameter> will not be accounted for by <xref linkend="libpq-PQresultMemorySize"/>, unless it is allocated using <xref linkend="libpq-PQresultAlloc"/>. (Doing so is recommendable because it eliminates the need to free such storage explicitly when the result is destroyed.) dataで示された領域は、PQresultAllocを使って割り当てたのでない限り、PQresultMemorySizeでは考慮されないことに注意してください。 (結果を破棄する時に、領域を明示的に解放する必要がなくなりますので、PQresultAllocを使って割り当てるのがお勧めです。)

PQresultInstanceData #

Returns the result's <literal>instanceData</literal> associated with <parameter>proc</parameter>, or <symbol>NULL</symbol> if there is none. procに関連した結果のinstanceData、または存在しなければNULLを返します。

void *PQresultInstanceData(const PGresult *res, PGEventProc proc);

34.14.4. イベント事例 #

<title>Event Example</title>

Here is a skeleton example of managing private data associated with libpq connections and results. 以下にlibpq接続と結果に関連したプライベートデータを管理する例の大枠を示します。



/* required header for libpq events (note: includes libpq-fe.h) */

/* libpqイベントに必要なヘッダ(覚書:libpq-fe.hのインクルード) */
#include <libpq-events.h>


/* The instanceData */

/* instanceData */
typedef struct
{
    int n;
    char *str;
} mydata;

/* PGEventProc */
static int myEventProc(PGEventId evtId, void *evtInfo, void *passThrough);

int
main(void)
{
    mydata *data;
    PGresult *res;
    PGconn *conn =
        PQconnectdb("dbname=postgres options=-csearch_path=");

    if (PQstatus(conn) != CONNECTION_OK)
    {
        /* PQerrorMessage's result includes a trailing newline */
        fprintf(stderr, "%s", PQerrorMessage(conn));
        PQfinish(conn);
        return 1;
    }


    /* called once on any connection that should receive events.
     * Sends a PGEVT_REGISTER to myEventProc.
     */

    /* イベントを受け取るべきすべての接続で1回呼ばれる
     * myEventProcにPGEVT_REGISTERを送る
     */
    if (!PQregisterEventProc(conn, myEventProc, "mydata_proc", NULL))
    {
        fprintf(stderr, "Cannot register PGEventProc\n");
        PQfinish(conn);
        return 1;
    }


    /* conn instanceData is available */

    /* conn instanceDataが有効 */
    data = PQinstanceData(conn, myEventProc);


    /* Sends a PGEVT_RESULTCREATE to myEventProc */

    /* myEventProcにPGEVT_RESULTCREATEを送る */
    res = PQexec(conn, "SELECT 1 + 1");


    /* result instanceData is available */

    /* 結果 instanceDataが有効 */
    data = PQresultInstanceData(res, myEventProc);


    /* If PG_COPYRES_EVENTS is used, sends a PGEVT_RESULTCOPY to myEventProc */

    /* PG_COPYRES_EVENTSが使われた場合、PGEVT_RESULTCOPYをmyEventProcに送る */
    res_copy = PQcopyResult(res, PG_COPYRES_TUPLES | PG_COPYRES_EVENTS);


    /* result instanceData is available if PG_COPYRES_EVENTS was
     * used during the PQcopyResult call.
     */

    /* PQcopyResult呼び出しの過程でPG_COPYRES_EVENTSが使用された場合、
     * 結果 instanceDataが有効
     */
    data = PQresultInstanceData(res_copy, myEventProc);


    /* Both clears send a PGEVT_RESULTDESTROY to myEventProc */

    /* 双方のclearがPGEVT_RESULTDESTROYをmyEventProcに送る */
    PQclear(res);
    PQclear(res_copy);


    /* Sends a PGEVT_CONNDESTROY to myEventProc */

    /* PGEVT_CONNDESTROYをmyEventProcに送る */
    PQfinish(conn);

    return 0;
}

static int
myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
{
    switch (evtId)
    {
        case PGEVT_REGISTER:
        {
            PGEventRegister *e = (PGEventRegister *)evtInfo;
            mydata *data = get_mydata(e->conn);


            /* associate app specific data with connection */

            /* アプリ特有のデータを接続に関連付ける */
            PQsetInstanceData(e->conn, myEventProc, data);
            break;
        }

        case PGEVT_CONNRESET:
        {
            PGEventConnReset *e = (PGEventConnReset *)evtInfo;
            mydata *data = PQinstanceData(e->conn, myEventProc);

            if (data)
              memset(data, 0, sizeof(mydata));
            break;
        }

        case PGEVT_CONNDESTROY:
        {
            PGEventConnDestroy *e = (PGEventConnDestroy *)evtInfo;
            mydata *data = PQinstanceData(e->conn, myEventProc);


            /* free instance data because the conn is being destroyed */

            /* connが破棄されたのでインスタンスデータを解放 */
            if (data)
              free_mydata(data);
            break;
        }

        case PGEVT_RESULTCREATE:
        {
            PGEventResultCreate *e = (PGEventResultCreate *)evtInfo;
            mydata *conn_data = PQinstanceData(e->conn, myEventProc);
            mydata *res_data = dup_mydata(conn_data);


            /* associate app specific data with result (copy it from conn) */

            /* アプリ特有のデータを結果と(connから複写して)関連付ける */
            PQresultSetInstanceData(e->result, myEventProc, res_data);
            break;
        }

        case PGEVT_RESULTCOPY:
        {
            PGEventResultCopy *e = (PGEventResultCopy *)evtInfo;
            mydata *src_data = PQresultInstanceData(e->src, myEventProc);
            mydata *dest_data = dup_mydata(src_data);


            /* associate app specific data with result (copy it from a result) */

            /* アプリ特有のデータを結果と(結果から複写して)関連付ける */
            PQresultSetInstanceData(e->dest, myEventProc, dest_data);
            break;
        }

        case PGEVT_RESULTDESTROY:
        {
            PGEventResultDestroy *e = (PGEventResultDestroy *)evtInfo;
            mydata *data = PQresultInstanceData(e->result, myEventProc);


            /* free instance data because the result is being destroyed */

            /* 結果が破棄されたためインスタンスデータを解放 */
            if (data)
              free_mydata(data);
            break;
        }


        /* unknown event ID, just return true. */

        /* 未知のイベント識別子。単にtrueを返す */
        default:
            break;
    }


    return true; /* event processing succeeded */

    return true; /* イベント処理成功 */
}