Commit efc3a25b authored by Tom Lane's avatar Tom Lane

Update libpq to make new features of FE/BE protocol available to

client applications.  Some editorial work on libpq.sgml, too.
parent b8d601e7
This diff is collapsed.
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/lobj.sgml,v 1.28 2003/03/13 01:30:28 petere Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/lobj.sgml,v 1.29 2003/06/21 21:51:33 tgl Exp $
--> -->
<chapter id="largeObjects"> <chapter id="largeObjects">
...@@ -181,7 +181,8 @@ int lo_open(PGconn *conn, Oid lobjId, int mode); ...@@ -181,7 +181,8 @@ int lo_open(PGconn *conn, Oid lobjId, int mode);
<function>lo_open</function> returns a large object descriptor <function>lo_open</function> returns a large object descriptor
for later use in <function>lo_read</function>, <function>lo_write</function>, for later use in <function>lo_read</function>, <function>lo_write</function>,
<function>lo_lseek</function>, <function>lo_tell</function>, and <function>lo_lseek</function>, <function>lo_tell</function>, and
<function>lo_close</function>. <function>lo_close</function>. The descriptor is only valid for
the duration of the current transaction.
</para> </para>
</sect2> </sect2>
...@@ -256,6 +257,11 @@ int lo_close(PGconn *conn, int fd); ...@@ -256,6 +257,11 @@ int lo_close(PGconn *conn, int fd);
<function>lo_open</function>. On success, <function>lo_close</function> <function>lo_open</function>. On success, <function>lo_close</function>
returns zero. On error, the return value is negative. returns zero. On error, the return value is negative.
</para> </para>
<para>
Any large object descriptors that remain open at the end of a
transaction will be closed automatically.
</para>
</sect2> </sect2>
<sect2> <sect2>
...@@ -296,6 +302,14 @@ SELECT lo_export(image.raster, '/tmp/motd') FROM image ...@@ -296,6 +302,14 @@ SELECT lo_export(image.raster, '/tmp/motd') FROM image
WHERE name = 'beautiful image'; WHERE name = 'beautiful image';
</programlisting> </programlisting>
</para> </para>
<para>
These functions read and write files in the server's filesystem, using the
permissions of the database's owning user. Therefore, their use is restricted
to superusers. (In contrast, the client-side import and export functions
read and write files in the client's filesystem, using the permissions of
the client program. Their use is not restricted.)
</para>
</sect1> </sect1>
<sect1 id="lo-examplesect"> <sect1 id="lo-examplesect">
......
...@@ -97,6 +97,20 @@ EXPORTS ...@@ -97,6 +97,20 @@ EXPORTS
_pg_utf_mblen @ 93 _pg_utf_mblen @ 93
_PQunescapeBytea @ 94 _PQunescapeBytea @ 94
_PQfreemem @ 95 _PQfreemem @ 95
_PQtransactionStatus @ 96
_PQparameterStatus @ 97
_PQprotocolVersion @ 98
_PQsetErrorVerbosity @ 99
_PQsetNoticeReceiver @ 100
_PQexecParams @ 101
_PQsendQueryParams @ 102
_PQputCopyData @ 103
_PQputCopyEnd @ 104
_PQgetCopyData @ 105
_PQresultErrorField @ 106
_PQftable @ 107
_PQftablecol @ 108
_PQfformat @ 109
; Aliases for MS compatible names ; Aliases for MS compatible names
PQconnectdb = _PQconnectdb PQconnectdb = _PQconnectdb
...@@ -194,4 +208,17 @@ EXPORTS ...@@ -194,4 +208,17 @@ EXPORTS
pg_utf_mblen = _pg_utf_mblen pg_utf_mblen = _pg_utf_mblen
PQunescapeBytea = _PQunescapeBytea PQunescapeBytea = _PQunescapeBytea
PQfreemem = _PQfreemem PQfreemem = _PQfreemem
PQtransactionStatus = _PQtransactionStatus
PQparameterStatus = _PQparameterStatus
PQprotocolVersion = _PQprotocolVersion
PQsetErrorVerbosity = _PQsetErrorVerbosity
PQsetNoticeReceiver = _PQsetNoticeReceiver
PQexecParams = _PQexecParams
PQsendQueryParams = _PQsendQueryParams
PQputCopyData = _PQputCopyData
PQputCopyEnd = _PQputCopyEnd
PQgetCopyData = _PQgetCopyData
PQresultErrorField = _PQresultErrorField
PQftable = _PQftable
PQftablecol = _PQftablecol
PQfformat = _PQfformat
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.249 2003/06/20 04:09:12 tgl Exp $ * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.250 2003/06/21 21:51:33 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -176,6 +176,7 @@ static PQconninfoOption *conninfo_parse(const char *conninfo, ...@@ -176,6 +176,7 @@ static PQconninfoOption *conninfo_parse(const char *conninfo,
PQExpBuffer errorMessage); PQExpBuffer errorMessage);
static char *conninfo_getval(PQconninfoOption *connOptions, static char *conninfo_getval(PQconninfoOption *connOptions,
const char *keyword); const char *keyword);
static void defaultNoticeReceiver(void *arg, const PGresult *res);
static void defaultNoticeProcessor(void *arg, const char *message); static void defaultNoticeProcessor(void *arg, const char *message);
static int parseServiceInfo(PQconninfoOption *options, static int parseServiceInfo(PQconninfoOption *options,
PQExpBuffer errorMessage); PQExpBuffer errorMessage);
...@@ -1804,11 +1805,14 @@ makeEmptyPGconn(void) ...@@ -1804,11 +1805,14 @@ makeEmptyPGconn(void)
/* Zero all pointers and booleans */ /* Zero all pointers and booleans */
MemSet((char *) conn, 0, sizeof(PGconn)); MemSet((char *) conn, 0, sizeof(PGconn));
conn->noticeHook = defaultNoticeProcessor; conn->noticeHooks.noticeRec = defaultNoticeReceiver;
conn->noticeHooks.noticeProc = defaultNoticeProcessor;
conn->status = CONNECTION_BAD; conn->status = CONNECTION_BAD;
conn->asyncStatus = PGASYNC_IDLE; conn->asyncStatus = PGASYNC_IDLE;
conn->xactStatus = PQTRANS_IDLE;
conn->setenv_state = SETENV_STATE_IDLE; conn->setenv_state = SETENV_STATE_IDLE;
conn->client_encoding = PG_SQL_ASCII; conn->client_encoding = PG_SQL_ASCII;
conn->verbosity = PQERRORS_DEFAULT;
conn->notifyList = DLNewList(); conn->notifyList = DLNewList();
conn->sock = -1; conn->sock = -1;
#ifdef USE_SSL #ifdef USE_SSL
...@@ -1850,7 +1854,6 @@ makeEmptyPGconn(void) ...@@ -1850,7 +1854,6 @@ makeEmptyPGconn(void)
/* /*
* freePGconn * freePGconn
* - free the PGconn data structure * - free the PGconn data structure
*
*/ */
static void static void
freePGconn(PGconn *conn) freePGconn(PGconn *conn)
...@@ -1899,9 +1902,9 @@ freePGconn(PGconn *conn) ...@@ -1899,9 +1902,9 @@ freePGconn(PGconn *conn)
} }
/* /*
closePGconn * closePGconn
- properly close a connection to the backend * - properly close a connection to the backend
*/ */
static void static void
closePGconn(PGconn *conn) closePGconn(PGconn *conn)
{ {
...@@ -2662,6 +2665,41 @@ PQstatus(const PGconn *conn) ...@@ -2662,6 +2665,41 @@ PQstatus(const PGconn *conn)
return conn->status; return conn->status;
} }
PGTransactionStatusType
PQtransactionStatus(const PGconn *conn)
{
if (!conn || conn->status != CONNECTION_OK)
return PQTRANS_UNKNOWN;
if (conn->asyncStatus != PGASYNC_IDLE)
return PQTRANS_ACTIVE;
return conn->xactStatus;
}
const char *
PQparameterStatus(const PGconn *conn, const char *paramName)
{
const pgParameterStatus *pstatus;
if (!conn || !paramName)
return NULL;
for (pstatus = conn->pstatus; pstatus != NULL; pstatus = pstatus->next)
{
if (strcmp(pstatus->name, paramName) == 0)
return pstatus->value;
}
return NULL;
}
int
PQprotocolVersion(const PGconn *conn)
{
if (!conn)
return 0;
if (conn->status == CONNECTION_BAD)
return 0;
return PG_PROTOCOL_MAJOR(conn->pversion);
}
char * char *
PQerrorMessage(const PGconn *conn) PQerrorMessage(const PGconn *conn)
{ {
...@@ -2731,11 +2769,22 @@ PQsetClientEncoding(PGconn *conn, const char *encoding) ...@@ -2731,11 +2769,22 @@ PQsetClientEncoding(PGconn *conn, const char *encoding)
return (status); return (status);
} }
PGVerbosity
PQsetErrorVerbosity(PGconn *conn, PGVerbosity verbosity)
{
PGVerbosity old;
if (!conn)
return PQERRORS_DEFAULT;
old = conn->verbosity;
conn->verbosity = verbosity;
return old;
}
void void
PQtrace(PGconn *conn, FILE *debug_port) PQtrace(PGconn *conn, FILE *debug_port)
{ {
if (conn == NULL || if (conn == NULL)
conn->status == CONNECTION_BAD)
return; return;
PQuntrace(conn); PQuntrace(conn);
conn->Pfdebug = debug_port; conn->Pfdebug = debug_port;
...@@ -2744,7 +2793,6 @@ PQtrace(PGconn *conn, FILE *debug_port) ...@@ -2744,7 +2793,6 @@ PQtrace(PGconn *conn, FILE *debug_port)
void void
PQuntrace(PGconn *conn) PQuntrace(PGconn *conn)
{ {
/* note: better allow untrace even when connection bad */
if (conn == NULL) if (conn == NULL)
return; return;
if (conn->Pfdebug) if (conn->Pfdebug)
...@@ -2754,6 +2802,23 @@ PQuntrace(PGconn *conn) ...@@ -2754,6 +2802,23 @@ PQuntrace(PGconn *conn)
} }
} }
PQnoticeReceiver
PQsetNoticeReceiver(PGconn *conn, PQnoticeReceiver proc, void *arg)
{
PQnoticeReceiver old;
if (conn == NULL)
return NULL;
old = conn->noticeHooks.noticeRec;
if (proc)
{
conn->noticeHooks.noticeRec = proc;
conn->noticeHooks.noticeRecArg = arg;
}
return old;
}
PQnoticeProcessor PQnoticeProcessor
PQsetNoticeProcessor(PGconn *conn, PQnoticeProcessor proc, void *arg) PQsetNoticeProcessor(PGconn *conn, PQnoticeProcessor proc, void *arg)
{ {
...@@ -2762,22 +2827,35 @@ PQsetNoticeProcessor(PGconn *conn, PQnoticeProcessor proc, void *arg) ...@@ -2762,22 +2827,35 @@ PQsetNoticeProcessor(PGconn *conn, PQnoticeProcessor proc, void *arg)
if (conn == NULL) if (conn == NULL)
return NULL; return NULL;
old = conn->noticeHook; old = conn->noticeHooks.noticeProc;
if (proc) if (proc)
{ {
conn->noticeHook = proc; conn->noticeHooks.noticeProc = proc;
conn->noticeArg = arg; conn->noticeHooks.noticeProcArg = arg;
} }
return old; return old;
} }
/* /*
* The default notice/error message processor just prints the * The default notice message receiver just gets the standard notice text
* and sends it to the notice processor. This two-level setup exists
* mostly for backwards compatibility; perhaps we should deprecate use of
* PQsetNoticeProcessor?
*/
static void
defaultNoticeReceiver(void *arg, const PGresult *res)
{
(void) arg; /* not used */
(*res->noticeHooks.noticeProc) (res->noticeHooks.noticeProcArg,
PQresultErrorMessage(res));
}
/*
* The default notice message processor just prints the
* message on stderr. Applications can override this if they * message on stderr. Applications can override this if they
* want the messages to go elsewhere (a window, for example). * want the messages to go elsewhere (a window, for example).
* Note that simply discarding notices is probably a bad idea. * Note that simply discarding notices is probably a bad idea.
*/ */
static void static void
defaultNoticeProcessor(void *arg, const char *message) defaultNoticeProcessor(void *arg, const char *message)
{ {
......
This diff is collapsed.
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.96 2003/06/14 17:49:54 momjian Exp $ * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.97 2003/06/21 21:51:34 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -197,7 +197,7 @@ pqPutnchar(const char *s, size_t len, PGconn *conn) ...@@ -197,7 +197,7 @@ pqPutnchar(const char *s, size_t len, PGconn *conn)
} }
/* /*
* pgGetInt * pqGetInt
* read a 2 or 4 byte integer and convert from network byte order * read a 2 or 4 byte integer and convert from network byte order
* to local byte order * to local byte order
*/ */
...@@ -226,7 +226,7 @@ pqGetInt(int *result, size_t bytes, PGconn *conn) ...@@ -226,7 +226,7 @@ pqGetInt(int *result, size_t bytes, PGconn *conn)
break; break;
default: default:
snprintf(noticeBuf, sizeof(noticeBuf), snprintf(noticeBuf, sizeof(noticeBuf),
libpq_gettext("integer of size %lu not supported by pqGetInt\n"), libpq_gettext("integer of size %lu not supported by pqGetInt"),
(unsigned long) bytes); (unsigned long) bytes);
PGDONOTICE(conn, noticeBuf); PGDONOTICE(conn, noticeBuf);
return EOF; return EOF;
...@@ -239,7 +239,7 @@ pqGetInt(int *result, size_t bytes, PGconn *conn) ...@@ -239,7 +239,7 @@ pqGetInt(int *result, size_t bytes, PGconn *conn)
} }
/* /*
* pgPutInt * pqPutInt
* write an integer of 2 or 4 bytes, converting from host byte order * write an integer of 2 or 4 bytes, converting from host byte order
* to network byte order. * to network byte order.
*/ */
...@@ -264,7 +264,7 @@ pqPutInt(int value, size_t bytes, PGconn *conn) ...@@ -264,7 +264,7 @@ pqPutInt(int value, size_t bytes, PGconn *conn)
break; break;
default: default:
snprintf(noticeBuf, sizeof(noticeBuf), snprintf(noticeBuf, sizeof(noticeBuf),
libpq_gettext("integer of size %lu not supported by pqPutInt\n"), libpq_gettext("integer of size %lu not supported by pqPutInt"),
(unsigned long) bytes); (unsigned long) bytes);
PGDONOTICE(conn, noticeBuf); PGDONOTICE(conn, noticeBuf);
return EOF; return EOF;
...@@ -282,7 +282,7 @@ pqPutInt(int value, size_t bytes, PGconn *conn) ...@@ -282,7 +282,7 @@ pqPutInt(int value, size_t bytes, PGconn *conn)
* *
* Returns 0 on success, EOF if failed to enlarge buffer * Returns 0 on success, EOF if failed to enlarge buffer
*/ */
static int int
pqCheckOutBufferSpace(int bytes_needed, PGconn *conn) pqCheckOutBufferSpace(int bytes_needed, PGconn *conn)
{ {
int newsize = conn->outBufSize; int newsize = conn->outBufSize;
...@@ -748,7 +748,7 @@ pqSendSome(PGconn *conn, int len) ...@@ -748,7 +748,7 @@ pqSendSome(PGconn *conn, int len)
if (sent < 0) if (sent < 0)
{ {
/* /*
* Anything except EAGAIN or EWOULDBLOCK is trouble. If it's * Anything except EAGAIN/EWOULDBLOCK/EINTR is trouble. If it's
* EPIPE or ECONNRESET, assume we've lost the backend * EPIPE or ECONNRESET, assume we've lost the backend
* connection permanently. * connection permanently.
*/ */
...@@ -804,25 +804,17 @@ pqSendSome(PGconn *conn, int len) ...@@ -804,25 +804,17 @@ pqSendSome(PGconn *conn, int len)
if (len > 0) if (len > 0)
{ {
/* We didn't send it all, wait till we can send more */
/* /*
* if the socket is in non-blocking mode we may need to abort * We didn't send it all, wait till we can send more.
* here and return 1 to indicate that data is still pending. *
* If the connection is in non-blocking mode we don't wait,
* but return 1 to indicate that data is still pending.
*/ */
#ifdef USE_SSL if (pqIsnonblocking(conn))
/* can't do anything for our SSL users yet */
if (conn->ssl == NULL)
{ {
#endif result = 1;
if (pqIsnonblocking(conn)) break;
{
result = 1;
break;
}
#ifdef USE_SSL
} }
#endif
if (pqWait(FALSE, TRUE, conn)) if (pqWait(FALSE, TRUE, conn))
{ {
......
This diff is collapsed.
This diff is collapsed.
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: libpq-fe.h,v 1.93 2003/06/08 17:43:00 tgl Exp $ * $Id: libpq-fe.h,v 1.94 2003/06/21 21:51:34 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -88,6 +88,22 @@ typedef enum ...@@ -88,6 +88,22 @@ typedef enum
PGRES_FATAL_ERROR /* query failed */ PGRES_FATAL_ERROR /* query failed */
} ExecStatusType; } ExecStatusType;
typedef enum
{
PQTRANS_IDLE, /* connection idle */
PQTRANS_ACTIVE, /* command in progress */
PQTRANS_INTRANS, /* idle, within transaction block */
PQTRANS_INERROR, /* idle, within failed transaction */
PQTRANS_UNKNOWN /* cannot determine status */
} PGTransactionStatusType;
typedef enum
{
PQERRORS_TERSE, /* single-line error messages */
PQERRORS_DEFAULT, /* recommended style */
PQERRORS_VERBOSE /* all the facts, ma'am */
} PGVerbosity;
/* PGconn encapsulates a connection to the backend. /* PGconn encapsulates a connection to the backend.
* The contents of this struct are not supposed to be known to applications. * The contents of this struct are not supposed to be known to applications.
*/ */
...@@ -108,12 +124,13 @@ typedef struct pg_result PGresult; ...@@ -108,12 +124,13 @@ typedef struct pg_result PGresult;
*/ */
typedef struct pgNotify typedef struct pgNotify
{ {
char *relname; /* name of relation containing data */ char *relname; /* notification condition name */
int be_pid; /* process id of backend */ int be_pid; /* process ID of server process */
char *extra; /* notification parameter */
} PGnotify; } PGnotify;
/* PQnoticeProcessor is the function type for the notice-message callback. /* Function types for notice-handling callbacks */
*/ typedef void (*PQnoticeReceiver) (void *arg, const PGresult *res);
typedef void (*PQnoticeProcessor) (void *arg, const char *message); typedef void (*PQnoticeProcessor) (void *arg, const char *message);
/* Print options for PQprint() */ /* Print options for PQprint() */
...@@ -227,6 +244,10 @@ extern char *PQport(const PGconn *conn); ...@@ -227,6 +244,10 @@ extern char *PQport(const PGconn *conn);
extern char *PQtty(const PGconn *conn); extern char *PQtty(const PGconn *conn);
extern char *PQoptions(const PGconn *conn); extern char *PQoptions(const PGconn *conn);
extern ConnStatusType PQstatus(const PGconn *conn); extern ConnStatusType PQstatus(const PGconn *conn);
extern PGTransactionStatusType PQtransactionStatus(const PGconn *conn);
extern const char *PQparameterStatus(const PGconn *conn,
const char *paramName);
extern int PQprotocolVersion(const PGconn *conn);
extern char *PQerrorMessage(const PGconn *conn); extern char *PQerrorMessage(const PGconn *conn);
extern int PQsocket(const PGconn *conn); extern int PQsocket(const PGconn *conn);
extern int PQbackendPID(const PGconn *conn); extern int PQbackendPID(const PGconn *conn);
...@@ -238,42 +259,58 @@ extern int PQsetClientEncoding(PGconn *conn, const char *encoding); ...@@ -238,42 +259,58 @@ extern int PQsetClientEncoding(PGconn *conn, const char *encoding);
extern SSL *PQgetssl(PGconn *conn); extern SSL *PQgetssl(PGconn *conn);
#endif #endif
/* Set verbosity for PQerrorMessage and PQresultErrorMessage */
extern PGVerbosity PQsetErrorVerbosity(PGconn *conn, PGVerbosity verbosity);
/* Enable/disable tracing */ /* Enable/disable tracing */
extern void PQtrace(PGconn *conn, FILE *debug_port); extern void PQtrace(PGconn *conn, FILE *debug_port);
extern void PQuntrace(PGconn *conn); extern void PQuntrace(PGconn *conn);
/* Override default notice processor */ /* Override default notice handling routines */
extern PQnoticeReceiver PQsetNoticeReceiver(PGconn *conn,
PQnoticeReceiver proc,
void *arg);
extern PQnoticeProcessor PQsetNoticeProcessor(PGconn *conn, extern PQnoticeProcessor PQsetNoticeProcessor(PGconn *conn,
PQnoticeProcessor proc, PQnoticeProcessor proc,
void *arg); void *arg);
/* === in fe-exec.c === */ /* === in fe-exec.c === */
/* Quoting strings before inclusion in queries. */
extern size_t PQescapeString(char *to, const char *from, size_t length);
extern unsigned char *PQescapeBytea(const unsigned char *bintext, size_t binlen,
size_t *bytealen);
extern unsigned char *PQunescapeBytea(const unsigned char *strtext,
size_t *retbuflen);
extern void PQfreemem(void *ptr);
/* Simple synchronous query */ /* Simple synchronous query */
extern PGresult *PQexec(PGconn *conn, const char *query); extern PGresult *PQexec(PGconn *conn, const char *query);
extern PGnotify *PQnotifies(PGconn *conn); extern PGresult *PQexecParams(PGconn *conn,
/* Exists for backward compatibility. bjm 2003-03-24 */ const char *command,
#define PQfreeNotify(ptr) PQfreemem(ptr) int nParams,
const Oid *paramTypes,
const char * const *paramValues,
const int *paramLengths,
const int *paramFormats,
int resultFormat);
/* Interface for multiple-result or asynchronous queries */ /* Interface for multiple-result or asynchronous queries */
extern int PQsendQuery(PGconn *conn, const char *query); extern int PQsendQuery(PGconn *conn, const char *query);
extern int PQsendQueryParams(PGconn *conn,
const char *command,
int nParams,
const Oid *paramTypes,
const char * const *paramValues,
const int *paramLengths,
const int *paramFormats,
int resultFormat);
extern PGresult *PQgetResult(PGconn *conn); extern PGresult *PQgetResult(PGconn *conn);
/* Routines for managing an asynchronous query */ /* Routines for managing an asynchronous query */
extern int PQisBusy(PGconn *conn); extern int PQisBusy(PGconn *conn);
extern int PQconsumeInput(PGconn *conn); extern int PQconsumeInput(PGconn *conn);
/* LISTEN/NOTIFY support */
extern PGnotify *PQnotifies(PGconn *conn);
/* Routines for copy in/out */ /* Routines for copy in/out */
extern int PQputCopyData(PGconn *conn, const char *buffer, int nbytes);
extern int PQputCopyEnd(PGconn *conn, const char *errormsg);
extern int PQgetCopyData(PGconn *conn, char **buffer, int async);
/* Deprecated routines for copy in/out */
extern int PQgetline(PGconn *conn, char *string, int length); extern int PQgetline(PGconn *conn, char *string, int length);
extern int PQputline(PGconn *conn, const char *string); extern int PQputline(PGconn *conn, const char *string);
extern int PQgetlineAsync(PGconn *conn, char *buffer, int bufsize); extern int PQgetlineAsync(PGconn *conn, char *buffer, int bufsize);
...@@ -303,11 +340,15 @@ extern PGresult *PQfn(PGconn *conn, ...@@ -303,11 +340,15 @@ extern PGresult *PQfn(PGconn *conn,
extern ExecStatusType PQresultStatus(const PGresult *res); extern ExecStatusType PQresultStatus(const PGresult *res);
extern char *PQresStatus(ExecStatusType status); extern char *PQresStatus(ExecStatusType status);
extern char *PQresultErrorMessage(const PGresult *res); extern char *PQresultErrorMessage(const PGresult *res);
extern char *PQresultErrorField(const PGresult *res, int fieldcode);
extern int PQntuples(const PGresult *res); extern int PQntuples(const PGresult *res);
extern int PQnfields(const PGresult *res); extern int PQnfields(const PGresult *res);
extern int PQbinaryTuples(const PGresult *res); extern int PQbinaryTuples(const PGresult *res);
extern char *PQfname(const PGresult *res, int field_num); extern char *PQfname(const PGresult *res, int field_num);
extern int PQfnumber(const PGresult *res, const char *field_name); extern int PQfnumber(const PGresult *res, const char *field_name);
extern Oid PQftable(const PGresult *res, int field_num);
extern int PQftablecol(const PGresult *res, int field_num);
extern int PQfformat(const PGresult *res, int field_num);
extern Oid PQftype(const PGresult *res, int field_num); extern Oid PQftype(const PGresult *res, int field_num);
extern int PQfsize(const PGresult *res, int field_num); extern int PQfsize(const PGresult *res, int field_num);
extern int PQfmod(const PGresult *res, int field_num); extern int PQfmod(const PGresult *res, int field_num);
...@@ -322,6 +363,12 @@ extern int PQgetisnull(const PGresult *res, int tup_num, int field_num); ...@@ -322,6 +363,12 @@ extern int PQgetisnull(const PGresult *res, int tup_num, int field_num);
/* Delete a PGresult */ /* Delete a PGresult */
extern void PQclear(PGresult *res); extern void PQclear(PGresult *res);
/* For freeing other alloc'd results, such as PGnotify structs */
extern void PQfreemem(void *ptr);
/* Exists for backward compatibility. bjm 2003-03-24 */
#define PQfreeNotify(ptr) PQfreemem(ptr)
/* /*
* Make an empty PGresult with given status (some apps find this * Make an empty PGresult with given status (some apps find this
* useful). If conn is not NULL and status indicates an error, the * useful). If conn is not NULL and status indicates an error, the
...@@ -329,26 +376,33 @@ extern void PQclear(PGresult *res); ...@@ -329,26 +376,33 @@ extern void PQclear(PGresult *res);
*/ */
extern PGresult *PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status); extern PGresult *PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status);
/* Quoting strings before inclusion in queries. */
extern size_t PQescapeString(char *to, const char *from, size_t length);
extern unsigned char *PQescapeBytea(const unsigned char *bintext, size_t binlen,
size_t *bytealen);
extern unsigned char *PQunescapeBytea(const unsigned char *strtext,
size_t *retbuflen);
/* === in fe-print.c === */ /* === in fe-print.c === */
extern void extern void PQprint(FILE *fout, /* output stream */
PQprint(FILE *fout, /* output stream */ const PGresult *res,
const PGresult *res, const PQprintOpt *ps); /* option structure */
const PQprintOpt *ps); /* option structure */
/* /*
* really old printing routines * really old printing routines
*/ */
extern void extern void PQdisplayTuples(const PGresult *res,
PQdisplayTuples(const PGresult *res,
FILE *fp, /* where to send the output */ FILE *fp, /* where to send the output */
int fillAlign, /* pad the fields with spaces */ int fillAlign, /* pad the fields with spaces */
const char *fieldSep, /* field separator */ const char *fieldSep, /* field separator */
int printHeader, /* display headers? */ int printHeader, /* display headers? */
int quiet); int quiet);
extern void extern void PQprintTuples(const PGresult *res,
PQprintTuples(const PGresult *res,
FILE *fout, /* output stream */ FILE *fout, /* output stream */
int printAttName, /* print attribute names */ int printAttName, /* print attribute names */
int terseOutput, /* delimiter bars */ int terseOutput, /* delimiter bars */
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: libpq-int.h,v 1.74 2003/06/14 17:49:54 momjian Exp $ * $Id: libpq-int.h,v 1.75 2003/06/21 21:51:34 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -20,6 +20,9 @@ ...@@ -20,6 +20,9 @@
#ifndef LIBPQ_INT_H #ifndef LIBPQ_INT_H
#define LIBPQ_INT_H #define LIBPQ_INT_H
/* We assume libpq-fe.h has already been included. */
#include "postgres_fe.h"
#include <time.h> #include <time.h>
#include <sys/types.h> #include <sys/types.h>
#ifndef WIN32 #ifndef WIN32
...@@ -28,13 +31,10 @@ ...@@ -28,13 +31,10 @@
#if defined(WIN32) && (!defined(ssize_t)) #if defined(WIN32) && (!defined(ssize_t))
typedef int ssize_t; /* ssize_t doesn't exist in VC (atleast typedef int ssize_t; /* ssize_t doesn't exist in VC (at least
* not VC6) */ * not VC6) */
#endif #endif
/* We assume libpq-fe.h has already been included. */
#include "postgres_fe.h"
/* include stuff common to fe and be */ /* include stuff common to fe and be */
#include "getaddrinfo.h" #include "getaddrinfo.h"
#include "libpq/pqcomm.h" #include "libpq/pqcomm.h"
...@@ -78,7 +78,10 @@ union pgresult_data ...@@ -78,7 +78,10 @@ union pgresult_data
typedef struct pgresAttDesc typedef struct pgresAttDesc
{ {
char *name; /* type name */ char *name; /* column name */
Oid tableid; /* source table, if known */
int columnid; /* source column, if known */
int format; /* format code for value (text/binary) */
Oid typid; /* type id */ Oid typid; /* type id */
int typlen; /* type size */ int typlen; /* type size */
int atttypmod; /* type-specific modifier info */ int atttypmod; /* type-specific modifier info */
...@@ -91,7 +94,7 @@ typedef struct pgresAttDesc ...@@ -91,7 +94,7 @@ typedef struct pgresAttDesc
* *
* The value pointer always points to a null-terminated area; we add a * The value pointer always points to a null-terminated area; we add a
* null (zero) byte after whatever the backend sends us. This is only * null (zero) byte after whatever the backend sends us. This is only
* particularly useful for text tuples ... with a binary value, the * particularly useful for text values ... with a binary value, the
* value might have embedded nulls, so the application can't use C string * value might have embedded nulls, so the application can't use C string
* operators on it. But we add a null anyway for consistency. * operators on it. But we add a null anyway for consistency.
* Note that the value itself does not contain a length word. * Note that the value itself does not contain a length word.
...@@ -111,6 +114,23 @@ typedef struct pgresAttValue ...@@ -111,6 +114,23 @@ typedef struct pgresAttValue
* byte */ * byte */
} PGresAttValue; } PGresAttValue;
/* Typedef for message-field list entries */
typedef struct pgMessageField
{
struct pgMessageField *next; /* list link */
char code; /* field code */
char contents[1]; /* field value (VARIABLE LENGTH) */
} PGMessageField;
/* Fields needed for notice handling */
typedef struct
{
PQnoticeReceiver noticeRec; /* notice message receiver */
void *noticeRecArg;
PQnoticeProcessor noticeProc; /* notice message processor */
void *noticeProcArg;
} PGNoticeHooks;
struct pg_result struct pg_result
{ {
int ntups; int ntups;
...@@ -118,10 +138,10 @@ struct pg_result ...@@ -118,10 +138,10 @@ struct pg_result
PGresAttDesc *attDescs; PGresAttDesc *attDescs;
PGresAttValue **tuples; /* each PGresTuple is an array of PGresAttValue **tuples; /* each PGresTuple is an array of
* PGresAttValue's */ * PGresAttValue's */
int tupArrSize; /* size of tuples array allocated */ int tupArrSize; /* allocated size of tuples array */
ExecStatusType resultStatus; ExecStatusType resultStatus;
char cmdStatus[CMDSTATUS_LEN]; /* cmd status from the char cmdStatus[CMDSTATUS_LEN]; /* cmd status from the
* last query */ * query */
int binary; /* binary tuple values if binary == 1, int binary; /* binary tuple values if binary == 1,
* otherwise text */ * otherwise text */
...@@ -129,35 +149,23 @@ struct pg_result ...@@ -129,35 +149,23 @@ struct pg_result
* These fields are copied from the originating PGconn, so that * These fields are copied from the originating PGconn, so that
* operations on the PGresult don't have to reference the PGconn. * operations on the PGresult don't have to reference the PGconn.
*/ */
PQnoticeProcessor noticeHook; /* notice/error message processor */ PGNoticeHooks noticeHooks;
void *noticeArg;
int client_encoding; /* encoding id */ int client_encoding; /* encoding id */
/* /*
* Error information (all NULL if not an error result). errMsg is the * Error information (all NULL if not an error result). errMsg is the
* "overall" error message returned by PQresultErrorMessage. If we * "overall" error message returned by PQresultErrorMessage. If we
* got a field-ized error from the server then the additional fields * have per-field info then it is stored in a linked list.
* may be set.
*/ */
char *errMsg; /* error message, or NULL if no error */ char *errMsg; /* error message, or NULL if no error */
PGMessageField *errFields; /* message broken into fields */
char *errSeverity; /* severity code */
char *errCode; /* SQLSTATE code */
char *errPrimary; /* primary message text */
char *errDetail; /* detail text */
char *errHint; /* hint text */
char *errPosition; /* cursor position */
char *errContext; /* location information */
char *errFilename; /* source-code file name */
char *errLineno; /* source-code line number */
char *errFuncname; /* source-code function name */
/* All NULL attributes in the query result point to this null string */ /* All NULL attributes in the query result point to this null string */
char null_field[1]; char null_field[1];
/* /*
* Space management information. Note that attDescs and errMsg, if * Space management information. Note that attDescs and error stuff,
* not null, point into allocated blocks. But tuples points to a * if not null, point into allocated blocks. But tuples points to a
* separately malloc'd block, so that we can realloc it. * separately malloc'd block, so that we can realloc it.
*/ */
PGresult_data *curBlock; /* most recently allocated block */ PGresult_data *curBlock; /* most recently allocated block */
...@@ -245,18 +253,18 @@ struct pg_conn ...@@ -245,18 +253,18 @@ struct pg_conn
/* Optional file to write trace info to */ /* Optional file to write trace info to */
FILE *Pfdebug; FILE *Pfdebug;
/* Callback procedure for notice/error message processing */ /* Callback procedures for notice message processing */
PQnoticeProcessor noticeHook; PGNoticeHooks noticeHooks;
void *noticeArg;
/* Status indicators */ /* Status indicators */
ConnStatusType status; ConnStatusType status;
PGAsyncStatusType asyncStatus; PGAsyncStatusType asyncStatus;
char xact_status; /* status flag from latest ReadyForQuery */ PGTransactionStatusType xactStatus;
char copy_is_binary; /* 1 = copy binary, 0 = copy text */ /* note: xactStatus never changes to ACTIVE */
int copy_already_done; /* # bytes already returned in COPY OUT */
int nonblocking; /* whether this connection is using a int nonblocking; /* whether this connection is using a
* blocking socket to the backend or not */ * blocking socket to the backend or not */
char copy_is_binary; /* 1 = copy binary, 0 = copy text */
int copy_already_done; /* # bytes already returned in COPY OUT */
Dllist *notifyList; /* Notify msgs not yet handed to Dllist *notifyList; /* Notify msgs not yet handed to
* application */ * application */
...@@ -281,6 +289,7 @@ struct pg_conn ...@@ -281,6 +289,7 @@ struct pg_conn
char cryptSalt[2]; /* password salt received from backend */ char cryptSalt[2]; /* password salt received from backend */
pgParameterStatus *pstatus; /* ParameterStatus data */ pgParameterStatus *pstatus; /* ParameterStatus data */
int client_encoding; /* encoding id */ int client_encoding; /* encoding id */
PGVerbosity verbosity; /* error/notice message verbosity */
PGlobjfuncs *lobjfuncs; /* private state for large-object access PGlobjfuncs *lobjfuncs; /* private state for large-object access
* fns */ * fns */
...@@ -351,10 +360,12 @@ extern char *pqResultStrdup(PGresult *res, const char *str); ...@@ -351,10 +360,12 @@ extern char *pqResultStrdup(PGresult *res, const char *str);
extern void pqClearAsyncResult(PGconn *conn); extern void pqClearAsyncResult(PGconn *conn);
extern void pqSaveErrorResult(PGconn *conn); extern void pqSaveErrorResult(PGconn *conn);
extern PGresult *pqPrepareAsyncResult(PGconn *conn); extern PGresult *pqPrepareAsyncResult(PGconn *conn);
extern void pqInternalNotice(const PGNoticeHooks *hooks, const char *msgtext);
extern int pqAddTuple(PGresult *res, PGresAttValue *tup); extern int pqAddTuple(PGresult *res, PGresAttValue *tup);
extern void pqSaveMessageField(PGresult *res, char code,
const char *value);
extern void pqSaveParameterStatus(PGconn *conn, const char *name, extern void pqSaveParameterStatus(PGconn *conn, const char *name,
const char *value); const char *value);
extern const char *pqGetParameterStatus(PGconn *conn, const char *name);
extern void pqHandleSendFailure(PGconn *conn); extern void pqHandleSendFailure(PGconn *conn);
/* === in fe-protocol2.c === */ /* === in fe-protocol2.c === */
...@@ -364,6 +375,7 @@ extern PostgresPollingStatusType pqSetenvPoll(PGconn *conn); ...@@ -364,6 +375,7 @@ extern PostgresPollingStatusType pqSetenvPoll(PGconn *conn);
extern char *pqBuildStartupPacket2(PGconn *conn, int *packetlen, extern char *pqBuildStartupPacket2(PGconn *conn, int *packetlen,
const PQEnvironmentOption *options); const PQEnvironmentOption *options);
extern void pqParseInput2(PGconn *conn); extern void pqParseInput2(PGconn *conn);
extern int pqGetCopyData2(PGconn *conn, char **buffer, int async);
extern int pqGetline2(PGconn *conn, char *s, int maxlen); extern int pqGetline2(PGconn *conn, char *s, int maxlen);
extern int pqGetlineAsync2(PGconn *conn, char *buffer, int bufsize); extern int pqGetlineAsync2(PGconn *conn, char *buffer, int bufsize);
extern int pqEndcopy2(PGconn *conn); extern int pqEndcopy2(PGconn *conn);
...@@ -378,6 +390,7 @@ extern char *pqBuildStartupPacket3(PGconn *conn, int *packetlen, ...@@ -378,6 +390,7 @@ extern char *pqBuildStartupPacket3(PGconn *conn, int *packetlen,
const PQEnvironmentOption *options); const PQEnvironmentOption *options);
extern void pqParseInput3(PGconn *conn); extern void pqParseInput3(PGconn *conn);
extern int pqGetErrorNotice3(PGconn *conn, bool isError); extern int pqGetErrorNotice3(PGconn *conn, bool isError);
extern int pqGetCopyData3(PGconn *conn, char **buffer, int async);
extern int pqGetline3(PGconn *conn, char *s, int maxlen); extern int pqGetline3(PGconn *conn, char *s, int maxlen);
extern int pqGetlineAsync3(PGconn *conn, char *buffer, int bufsize); extern int pqGetlineAsync3(PGconn *conn, char *buffer, int bufsize);
extern int pqEndcopy3(PGconn *conn); extern int pqEndcopy3(PGconn *conn);
...@@ -393,6 +406,7 @@ extern PGresult *pqFunctionCall3(PGconn *conn, Oid fnid, ...@@ -393,6 +406,7 @@ extern PGresult *pqFunctionCall3(PGconn *conn, Oid fnid,
* for Get, EOF merely means the buffer is exhausted, not that there is * for Get, EOF merely means the buffer is exhausted, not that there is
* necessarily any error. * necessarily any error.
*/ */
extern int pqCheckOutBufferSpace(int bytes_needed, PGconn *conn);
extern int pqCheckInBufferSpace(int bytes_needed, PGconn *conn); extern int pqCheckInBufferSpace(int bytes_needed, PGconn *conn);
extern int pqGetc(char *result, PGconn *conn); extern int pqGetc(char *result, PGconn *conn);
extern int pqPutc(char c, PGconn *conn); extern int pqPutc(char c, PGconn *conn);
...@@ -423,10 +437,10 @@ extern ssize_t pqsecure_write(PGconn *, const void *ptr, size_t len); ...@@ -423,10 +437,10 @@ extern ssize_t pqsecure_write(PGconn *, const void *ptr, size_t len);
/* Note: PGDONOTICE macro will work if applied to either PGconn or PGresult */ /* Note: PGDONOTICE macro will work if applied to either PGconn or PGresult */
#define PGDONOTICE(conn,message) \ #define PGDONOTICE(conn,message) \
((*(conn)->noticeHook) ((conn)->noticeArg, (message))) pqInternalNotice(&(conn)->noticeHooks, (message))
/* /*
* this is so that we can check is a connection is non-blocking internally * this is so that we can check if a connection is non-blocking internally
* without the overhead of a function call * without the overhead of a function call
*/ */
#define pqIsnonblocking(conn) ((conn)->nonblocking) #define pqIsnonblocking(conn) ((conn)->nonblocking)
......
...@@ -97,4 +97,17 @@ EXPORTS ...@@ -97,4 +97,17 @@ EXPORTS
pg_utf_mblen @ 93 pg_utf_mblen @ 93
PQunescapeBytea @ 94 PQunescapeBytea @ 94
PQfreemem @ 95 PQfreemem @ 95
PQtransactionStatus @ 96
PQparameterStatus @ 97
PQprotocolVersion @ 98
PQsetErrorVerbosity @ 99
PQsetNoticeReceiver @ 100
PQexecParams @ 101
PQsendQueryParams @ 102
PQputCopyData @ 103
PQputCopyEnd @ 104
PQgetCopyData @ 105
PQresultErrorField @ 106
PQftable @ 107
PQftablecol @ 108
PQfformat @ 109
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment