Some quick notes about extending libpq for new protocol - Mailing list pgsql-hackers
From | Tom Lane |
---|---|
Subject | Some quick notes about extending libpq for new protocol |
Date | |
Msg-id | 9481.1054574376@sss.pgh.pa.us Whole thread Raw |
Responses |
Re: [INTERFACES] Some quick notes about extending libpq for new protocol
Re: [INTERFACES] Some quick notes about extending libpq for new |
List | pgsql-hackers |
Here are my notes about what to do to extend libpq's API to support the new features of the 3.0 frontend/backend protocol. Not very polished but I trust you can follow it. Any objections? regards, tom lane LIBPQ updates for new protocol ------------------------------ Needed: * Access to individual fields of an error/notice result; also some setting to determine how verbose PQerrorMessage is char *PQerrorField(conn, char fieldcode)char *PQresultErrorField(const PGresult *res, char fieldcode) fieldcode is as per the protocol spec. NULL is returned if no such field in current result (this includes case where current result isn't an error). Errors generated internally by libpq will have severity, primary message, and SQLSTATE, but typically no other fields. Seems there is no alternative for Notice except to invent a new callback level :-(. PQnoticeProcessor API doesn't get the job done. typedef PQnoticeReceiver (PGconn *conn, PGresult *res, void *arg);PQsetNoticeReceiver(conn, function, arg) res will be a NONFATAL_ERROR result from which PQresultErrorField() calls may be used to extract the individual fields. Default version just gets PQresultErrorMessage() and passes it to connection's noticeProcessor. PQsetErrorVerbosity(conn, PQERRORS_TERSE/DEFAULT/VERBOSE) TERSE: single-line error (severity, primary text, and position only) DEFAULT: above plus any detail, hint, or context fields (backwards compatible) VERBOSE: all available data * Transaction status inquiry; also access to ParameterStatus. (Provide way to get at server version unconditionally, so that apps do not need fallback code) enum PQtransactionStatus(conn)Returns PQTRANS_UNKNOWN, IDLE, INTRANS, INERRORUNKNOWN is returned if on pre-3.0 protocol orbad connection const char *PQparameterStatus(conn, const char *paramName) returns NULL if param not available, sets errmsg const char *PQserverVersion(conn) uses paramstatus if possible, else does query int PQprotocolVersion(conn) returns protocol major version (2 or 3) * Representation of binary results? seems to just need some notes? Old way is not too incompatibleexcept for endianness issues. * Extended query support: for the moment I'm just going to provide an extension to allow access to out-of-line parameters and binary format. Later maybe add some stuff to support separate Parse, Bind, Execute steps. PQexecParams(conn, const char *query, int nParams, Oid *paramTypes, -- may be NULL to leave all unspecified char **paramValues, int *paramLengths, -- may be NULL if all text int *paramFormats, --NULL means all text int resultFormat) -- zero or one a NULL value of param[i] means that param is NULL, else it is pointer to either null-terminated C string (if text) or binary value of length paramLengths[i] (if binary). Note paramLengths is not examined for text-format params. Semantics similar to PQexec, but cannot put multiple commands into query string. Note we don't allow per-column result format selection, since we don't have a good way to tell the number of result columns. For asynchronous processing, also add PQsendQueryParams, with same parameters but behaves similarly to PQsendQuery; follow with PQgetResult. Each of these sends Parse/Bind/DescribePortal/Execute/Sync using unnamed stmt and portal. Will fail on old-protocol connections. * Better COPY API COPY OUT and COPY IN PGresults now carry #cols and format info.(only if new-protocol conn, else return "zero cols") PQexec will cope with getting out of pre-existing COPY state (bydiscarding data or sending CopyDone) PQputline/PQputnbytes reject if not in COPY IN state, else theywrap the data as a CopyData message and send it. It is uptoapplication to send valid data for the COPY operation. int PQputCopyData(conn, const char *buffer, int nbytes, bool async)Functionally similar to PQputnbytes,but preferred fornew codingReturns 1: data sent or queued 0: data not sent, try again later (only if async is true) -1: trouble,use PQerrorMessage to find out whyDo NOT send "\." as terminator. int PQputCopyEnd(conn, const char *error, bool async)Ends a COPY IN successfully if error is NULL, else makes it failwithgiven null-terminated string as the error message.Same return conventions as PQputCopyData. After successfulcompletion,call PQgetResult to check success or failure of COPYcommand. (If doing async COPY, can wait in theusual way forPQgetResult to be ready.) PQgetCopyData(conn, char **buffer, bool async) returns a malloc'd chunk of data if successfulCases got some data return value is # bytes received data not yet avail (only in async case) return is 0, *buffer is NULL endof copy in operation (incl. error detected) return is -1, *buffer is NULL now call PQgetResultThe returnedbuffer will be null-terminated, but this is onlyhelpful for text copy. The returned data always corresponds toonedata row. PQendcopy: deprecated, but equivalent to PQputCopyEnd (if COPY IN state) followed by synchronous GetResult. * Better FunctionCall API? nah, just deprecate in favor of invoking the function viaPQexecParams(). * Access to Notification param field add a third field to PGnotify struct * Access to source table's OID and column number in RowDescription, also per-column format codes Oid PQftable(const PGresult *res, int col)int PQftablecol(const PGresult *res, int col)int PQfformat(const PGresult *res,int col) PQbinaryTuples is now deprecated in favor of looking at PQfformat. PQbinaryTuples will return true only if all columns of the result are binary format.
pgsql-hackers by date: