diff options
Diffstat (limited to 'doc/src')
| -rw-r--r-- | doc/src/sgml/libpq.sgml | 745 |
1 files changed, 711 insertions, 34 deletions
diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml index deb052e5c49..2db369e906d 100644 --- a/doc/src/sgml/libpq.sgml +++ b/doc/src/sgml/libpq.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.260 2008/06/27 02:44:31 momjian Exp $ --> +<!-- $PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.261 2008/09/17 04:31:08 tgl Exp $ --> <chapter id="libpq"> <title><application>libpq</application> - C Library</title> @@ -2063,38 +2063,6 @@ PGresult *PQdescribePortal(PGconn *conn, const char *portalName); </para> </listitem> </varlistentry> - - <varlistentry> - <term> - <function>PQmakeEmptyPGresult</function> - <indexterm> - <primary>PQmakeEmptyPGresult</primary> - </indexterm> - </term> - - <listitem> - <para> - Constructs an empty <structname>PGresult</structname> object with the given status. - <synopsis> - PGresult *PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status); - </synopsis> - </para> - - <para> - This is <application>libpq</>'s internal function to allocate and - initialize an empty <structname>PGresult</structname> object. This - function returns NULL if memory could not be allocated. It is - exported because some applications find it useful to generate result - objects (particularly objects with error status) themselves. If - <parameter>conn</parameter> is not null and <parameter>status</> - indicates an error, the current error message of the specified - connection is copied into the <structname>PGresult</structname>. - Note that <function>PQclear</function> should eventually be called - on the object, just as with a <structname>PGresult</structname> - returned by <application>libpq</application> itself. - </para> - </listitem> - </varlistentry> </variablelist> </para> </sect2> @@ -4598,6 +4566,170 @@ char *pg_encoding_to_char(int <replaceable>encoding_id</replaceable>); </para> </listitem> </varlistentry> + + <varlistentry> + <term> + <function>PQmakeEmptyPGresult</function> + <indexterm> + <primary>PQmakeEmptyPGresult</primary> + </indexterm> + </term> + + <listitem> + <para> + Constructs an empty <structname>PGresult</structname> object with the given status. + <synopsis> + PGresult *PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status); + </synopsis> + </para> + + <para> + This is <application>libpq</>'s internal function to allocate and + initialize an empty <structname>PGresult</structname> object. This + function returns NULL if memory could not be allocated. It is + exported because some applications find it useful to generate result + objects (particularly objects with error status) themselves. If + <parameter>conn</parameter> is not null and <parameter>status</> + indicates an error, the current error message of the specified + connection is copied into the <structname>PGresult</structname>. + Also, if <parameter>conn</parameter> is not null, any event handlers + registered in the connection are copied into the + <structname>PGresult</structname> (but they don't get + <literal>PGEVT_RESULTCREATE</> calls). + Note that <function>PQclear</function> should eventually be called + on the object, just as with a <structname>PGresult</structname> + returned by <application>libpq</application> itself. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term> + <function>PQcopyResult</function> + <indexterm> + <primary>PQcopyResult</primary> + </indexterm> + </term> + + <listitem> + <para> + Makes a copy of a <structname>PGresult</structname> object. The copy is + not linked to the source result in any way and + <function>PQclear</function> must be called when the copy is no longer + needed. If the function fails, NULL is returned. + + <synopsis> + PGresult *PQcopyResult(const PGresult *src, int flags); + </synopsis> + </para> + + <para> + This is not intended to make an exact copy. The returned result is + always put into <literal>PGRES_TUPLES_OK</literal> status, and does not + copy any error message in the source. (It does copy the command status + string, however.) The <parameter>flags</parameter> argument determines + what else is copied. It is a bitwise OR of several flags. + <literal>PG_COPYRES_ATTRS</literal> specifies copying the source + result's attributes (column definitions). + <literal>PG_COPYRES_TUPLES</literal> specifies copying the source + result's tuples. (This implies copying the attributes, too.) + <literal>PG_COPYRES_NOTICEHOOKS</literal> specifies + copying the source result's notify hooks. + <literal>PG_COPYRES_EVENTS</literal> specifies copying the source + result's events. (But any instance data associated with the source + is not copied.) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term> + <function>PQsetResultAttrs</function> + <indexterm> + <primary>PQsetResultAttrs</primary> + </indexterm> + </term> + + <listitem> + <para> + Sets the attributes of a <structname>PGresult</structname> object. + <synopsis> + int PQsetResultAttrs(PGresult *res, int numAttributes, PGresAttDesc *attDescs); + </synopsis> + </para> + + <para> + The provided <parameter>attDescs</parameter> are copied into the result. + If the <parameter>attDescs</parameter> pointer is NULL or + <parameter>numAttributes</parameter> is less than one, the request is + ignored and the function succeeds. If <parameter>res</parameter> + already contains attributes, the function will fail. If the function + fails, the return value is zero. If the function succeeds, the return + value is non-zero. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term> + <function>PQsetvalue</function> + <indexterm> + <primary>PQsetvalue</primary> + </indexterm> + </term> + + <listitem> + <para> + Sets a tuple field value of a <structname>PGresult</structname> object. + <synopsis> + int PQsetvalue(PGresult *res, int tup_num, int field_num, char *value, int len); + </synopsis> + </para> + + <para> + The function will automatically grow the result's internal tuples array + as needed. However, the <parameter>tup_num</parameter> argument must be + less than or equal to <function>PQntuples</function>, meaning this + function can only grow the tuples array one tuple at a time. But any + field of any existing tuple can be modified in any order. If a value at + <parameter>field_num</parameter> already exists, it will be overwritten. + If <parameter>len</parameter> is <literal>-1</literal> or + <parameter>value</parameter> is <literal>NULL</literal>, the field value + will be set to an SQL <literal>NULL</literal>. The + <parameter>value</parameter> is copied into the result's private storage, + thus is no longer needed after the function + returns. If the function fails, the return value is zero. If the + function succeeds, the return value is non-zero. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term> + <function>PQresultAlloc</function> + <indexterm> + <primary>PQresultAlloc</primary> + </indexterm> + </term> + + <listitem> + <para> + Allocate subsidiary storage for a <structname>PGresult</structname> object. + <synopsis> + void *PQresultAlloc(PGresult *res, size_t nBytes); + </synopsis> + </para> + + <para> + Any memory allocated with this function will be freed when + <parameter>res</parameter> is cleared. If the function fails, + the return value is <literal>NULL</literal>. The result is + guaranteed to be adequately aligned for any type of data, + just as for <function>malloc</>. + </para> + </listitem> + </varlistentry> + </variablelist> </sect1> @@ -4711,6 +4843,551 @@ defaultNoticeProcessor(void *arg, const char *message) </sect1> + <sect1 id="libpq-events"> + <title>Event System</title> + + <para> + <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. + </para> + + <para> + Each registered event handler is associated with two pieces of data, + known to <application>libpq</application> only as opaque <literal>void *</> + pointers. There is a <firstterm>passthrough</> pointer that is provided + by the application when the event handler is registered with a + <structname>PGconn</>. The passthrough pointer never changes for the + life of the <structname>PGconn</> and all <structname>PGresult</>s + generated from it; so if used, it must point to long-lived data. + In addition there is an <firstterm>instance data</> pointer, which starts + out NULL in every <structname>PGconn</> and <structname>PGresult</>. + This pointer can be manipulated using the + <function>PQinstanceData</function>, + <function>PQsetInstanceData</function>, + <function>PQresultInstanceData</function> and + <function>PQsetResultInstanceData</function> functions. Note that + unlike the passthrough pointer, instance data of a <structname>PGconn</> + is not automatically inherited by <structname>PGresult</>s created from + it. <application>libpq</application> does not know what passthrough + and instance data pointers point to (if anything) and will never attempt + to free them — that is the responsibility of the event handler. + </para> + + <sect2 id="libpq-events-types"> + <title>Event Types</title> + + <para> + The enum <literal>PGEventId</> 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: + </para> + + <variablelist> + <varlistentry> + <term><literal>PGEVT_REGISTER</literal></term> + <listitem> + <para> + The register event occurs when <function>PQregisterEventProc</function> + 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, the registration is aborted. + + <synopsis> +typedef struct +{ + const PGconn *conn; +} PGEventRegister; + </synopsis> + + 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 + <function>PQregisterEventProc</function> right after obtaining a good + <structname>PGconn</structname>. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>PGEVT_CONNRESET</literal></term> + <listitem> + <para> + The connection reset event is fired on completion of + <function>PQreset</function> or <function>PQresetPoll</function>. In + both cases, the event is only fired if the reset was successful. If + the event procedure fails, the entire connection reset will fail; the + <structname>PGconn</structname> is put into + <literal>CONNECTION_BAD</literal> status and + <function>PQresetPoll</function> will return + <literal>PGRES_POLLING_FAILED</literal>. + + <synopsis> +typedef struct +{ + const PGconn *conn; +} PGEventConnReset; + </synopsis> + + 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>. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>PGEVT_CONNDESTROY</literal></term> + <listitem> + <para> + The connection destroy event is fired in response to + <function>PQfinish</function>. 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. + + <synopsis> +typedef struct +{ + const PGconn *conn; +} PGEventConnDestroy; + </synopsis> + + 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 <function>PQfinish</function> performing any other cleanup. + The return value of the event procedure is ignored since there is no + way of indicating a failure from <function>PQfinish</function>. Also, + an event procedure failure should not abort the process of cleaning up + unwanted memory. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>PGEVT_RESULTCREATE</literal></term> + <listitem> + <para> + The result creation event is fired in response to any query execution + function that generates a result, including + <function>PQgetResult</function>. This event will only be fired after + the result has been created successfully. + + <synopsis> +typedef struct +{ + const PGconn *conn; + PGresult *result; +} PGEventResultCreate; + </synopsis> + + 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 the event procedure fails, the result will be cleared and + the failure will be propagated. The event procedure must not try to + <function>PQclear</> the result object for itself. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>PGEVT_RESULTCOPY</literal></term> + <listitem> + <para> + The result copy event is fired in response to + <function>PQcopyResult</function>. This event will only be fired after + the copy is complete. + + <synopsis> +typedef struct +{ + const PGresult *src; + PGresult *dest; +} PGEventResultCopy; + </synopsis> + + 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 the event + procedure fails, the entire copy operation will fail and the + <parameter>dest</parameter> result will be cleared. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>PGEVT_RESULTDESTROY</literal></term> + <listitem> + <para> + The result destroy event is fired in response to a + <function>PQclear</function>. 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. + + <synopsis> +typedef struct +{ + const PGresult *result; +} PGEventResultDestroy; + </synopsis> + + 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 <function>PQclear</function> performing any other cleanup. + The return value of the event procedure is ignored since there is no + way of indicating a failure from <function>PQclear</function>. Also, + an event procedure failure should not abort the process of cleaning up + unwanted memory. + </para> + </listitem> + </varlistentry> + </variablelist> + </sect2> + + <sect2 id="libpq-events-proc"> + <title>Event Callback Procedure</title> + + <variablelist> + <varlistentry> + <term> + <literal>PGEventProc</literal> + <indexterm> + <primary>PGEventProc</primary> + </indexterm> + </term> + + <listitem> + <para> + <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 + + <synopsis> +int eventproc(PGEventId evtId, void *evtInfo, void *passThrough) + </synopsis> + + 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 <function>PQregisterEventProc</function> when the event + procedure was registered. The function should return a non-zero value + if it succeeds and zero if it fails. + </para> + + <para> + A particular event procedure can be registered only once in any + <structname>PGconn</>. This is because the address of the procedure + is used as a lookup key to identify the associated instance data. + </para> + </listitem> + </varlistentry> + </variablelist> + </sect2> + + <sect2 id="libpq-events-funcs"> + <title>Event Support Functions</title> + + <variablelist> + <varlistentry> + <term> + <function>PQregisterEventProc</function> + <indexterm> + <primary>PQregisterEventProc</primary> + </indexterm> + </term> + + <listitem> + <para> + Registers an event callback procedure with libpq. + + <synopsis> + int PQregisterEventProc(PGconn *conn, PGEventProc proc, + const char *name, void *passThrough); + </synopsis> + </para> + + <para> + An event procedure must be registered once on each + <structname>PGconn</> 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. + </para> + + <para> + 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 NULL or a zero-length string. The name string is + copied into the <structname>PGconn</>, 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 NULL. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term> + <function>PQsetInstanceData</function> + <indexterm> + <primary>PQsetInstanceData</primary> + </indexterm> + </term> + <listitem> + <para> + Sets the conn's instanceData for proc to data. This returns non-zero + for success and zero for failure. (Failure is only possible if + the proc has not been properly registered in the conn.) + + <synopsis> + int PQsetInstanceData(PGconn *conn, PGEventProc proc, void *data); + </synopsis> + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term> + <function>PQinstanceData</function> + <indexterm> + <primary>PQinstanceData</primary> + </indexterm> + </term> + <listitem> + <para> + Returns the conn's instanceData associated with proc, or NULL + if there is none. + + <synopsis> + void *PQinstanceData(const PGconn *conn, PGEventProc proc); + </synopsis> + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term> + <function>PQresultSetInstanceData</function> + <indexterm> + <primary>PQresultSetInstanceData</primary> + </indexterm> + </term> + <listitem> + <para> + Sets the result's instanceData for proc to data. This returns non-zero + for success and zero for failure. (Failure is only possible if the + proc has not been properly registered in the result.) + + <synopsis> + int PQresultSetInstanceData(PGresult *res, PGEventProc proc, void *data); + </synopsis> + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term> + <function>PQresultInstanceData</function> + <indexterm> + <primary>PQresultInstanceData</primary> + </indexterm> + </term> + <listitem> + <para> + Returns the result's instanceData associated with proc, or NULL + if there is none. + + <synopsis> + void *PQresultInstanceData(const PGresult *res, PGEventProc proc); + </synopsis> + </para> + </listitem> + </varlistentry> + </variablelist> + </sect2> + + <sect2 id="libpq-events-example"> + <title>Event Example</title> + + <para> + Here is a skeleton example of managing private data associated with + libpq connections and results. + </para> + + <programlisting> +/* required header for libpq events (note: includes libpq-fe.h) */ +#include <libpq-events.h> + +/* The 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"); + + if (PQstatus(conn) != CONNECTION_OK) + { + fprintf(stderr, "Connection to database failed: %s", + PQerrorMessage(conn)); + PQfinish(conn); + return 1; + } + + /* called once on any connection that should receive events. + * Sends a PGEVT_REGISTER to myEventProc. + */ + if (!PQregisterEventProc(conn, myEventProc, "mydata_proc", NULL)) + { + fprintf(stderr, "Cannot register PGEventProc\n"); + PQfinish(conn); + return 1; + } + + /* conn instanceData is available */ + data = PQinstanceData(conn, myEventProc); + + /* Sends a PGEVT_RESULTCREATE to myEventProc */ + res = PQexec(conn, "SELECT 1 + 1"); + + /* result instanceData is available */ + data = PQresultInstanceData(res, myEventProc); + + /* If PG_COPYRES_EVENTS is used, sends a PGEVT_RESULTCOPY to 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. + */ + data = PQresultInstanceData(res_copy, myEventProc); + + /* Both clears send a PGEVT_RESULTDESTROY to myEventProc */ + PQclear(res); + PQclear(res_copy); + + /* Sends a PGEVT_CONNDESTROY to 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 */ + 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) */ + PQsetResultInstanceData(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) */ + PQsetResultInstanceData(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. */ + default: + break; + } + + return TRUE; /* event processing succeeded */ +} +</programlisting> + </sect2> + </sect1> + <sect1 id="libpq-envars"> <title>Environment Variables</title> @@ -5263,7 +5940,7 @@ defaultNoticeProcessor(void *arg, const char *message) to inside <application>libpq</application>), you can use <function>PQinitSSL(int)</> to tell <application>libpq</application> that the <acronym>SSL</> library has already been initialized by your - application. + application. <!-- If this URL changes replace it with a URL to www.archive.org. --> See <ulink url="http://h71000.www7.hp.com/doc/83final/BA554_90007/ch04.html"></ulink> |
