home *** CD-ROM | disk | FTP | other *** search
- /* ----------------------------------------------------------------
- * FILE
- * fe-pqexec.c
- *
- * DESCRIPTION
- * support for executing POSTGRES commands and functions
- * from a frontend application.
- *
- * SUPPORT ROUTINES
- * read_initstr, read_remark, EstablishComm, process_portal,
- * StringPointerSet
- *
- * INTERFACE ROUTINES
- * PQdb - Return the current database being accessed.
- * PQsetdb - Make the specified database the current database.
- * PQreset - Reset the communication port with the backend.
- * PQfinish - Close communication ports with the backend.
- * PQFlushI - Used for flushing out "poll" queries by the monitor.
- *
- * >> PQfn - Send a function call to the POSTGRES backend.
- * >> PQexec - Send a query to the POSTGRES backend
- *
- * NOTES
- * These routines are NOT compiled into the postgres backend,
- * rather they end up in libpq.a.
- *
- * IDENTIFICATION
- * $Header: /private/postgres/src/lib/libpq/RCS/fe-pqexec.c,v 1.27 1992/08/07 00:38:18 mao Exp $
- * ----------------------------------------------------------------
- */
-
- #include "tmp/c.h"
-
- #include "tmp/simplelists.h"
- #include "tmp/libpq-fe.h"
- #include "tmp/fastpath.h"
- #include "utils/fmgr.h"
- #include "utils/exception.h"
-
- RcsId ("$Header: /private/postgres/src/lib/libpq/RCS/fe-pqexec.c,v 1.27 1992/08/07 00:38:18 mao Exp $");
-
- /* ----------------------------------------------------------------
- * Declare Global Variables.
- *
- * The Values of the first four varialbes can be changed by setting
- * the approriate environment variables.
- *
- * PQhost: PGHOST
- * PQdatabase: PGDATABASE
- * PQport: PGPORT
- * PQtty: PGTTY
- * ----------------------------------------------------------------
- */
-
- #define DefaultHost "localhost"
- #define DefaultPort "4321"
- #define DefaultTty "/dev/null"
- #define DefaultOption ""
- #define DefaultVacuum "~/bin/vacuumd"
-
- char *PQhost; /* the machine on which POSTGRES backend
- is running */
- char *PQport = NULL; /* the communication port with the
- POSTGRES backend */
- char *PQtty; /* the tty on PQhost backend message
- is displayed */
- char *PQoption; /* the optional arguments to POSTGRES
- backend */
- char PQdatabase[17] = {0}; /* the POSTGRES database to access */
- int PQportset = 0; /* 1 if the communication with backend
- is set */
- int PQxactid = 0; /* the transaction id of the current
- transaction */
- /*char *PQinitstr = NULL; /* the initialization string passed
- to backend (obsolete 2/21/91 -mer) */
-
- extern char *getenv();
-
- /* ----------------------------------------------------------------
- * PQ utility routines
- * ----------------------------------------------------------------
- */
-
- /* ----------------
- * read_initstr
- *
- * This is now a misnomer. PQinistr is no longer used and this routine
- * really just initializes the PQ global variables if they need it.
- *
- * Read in the initialization string to be passed to the POSTGRES backend.
- * The initstr has the format of
- *
- * USER,DATABASE,TTY,OPTION\n
- *
- * If the variables do not have values yet, read in the values from the
- * environment variables. If the environment variable does not have a
- * value, use the default value.
- * ----------------
- */
-
- void
- read_initstr()
- {
- char *envDB;
-
- if (PQdatabase[0] == NULL)
- {
- if ((envDB = getenv ("PGDATABASE")) == NULL)
- libpq_raise(&ProtocolError,
- form((int)"Fatal Error -- No database is specified."));
- else
- {
- PQdatabase[16] = '\0';
- strncpy(PQdatabase, envDB, 16);
- }
- }
- if ((PQhost == NULL) && ((PQhost = getenv("PGHOST")) == NULL))
- PQhost = DefaultHost;
-
- if ((PQtty == NULL) && ((PQtty = getenv("PGTTY")) == NULL))
- PQtty = DefaultTty;
-
- /*
- * As of release 4, PQoption is no longer taken from the environment
- * var PGOPTION if it's not already defined. This change was made
- * in order to be consistent with the documentation and to make frew
- * happy.
- *
- * In general, users shouldn't be screwing around with PQoption, in
- * any case.
- */
-
- if (PQoption == NULL)
- PQoption = DefaultOption;
-
- if (PQport == NULL) {
- if (getenv("PGPORT") == NULL)
- PQport = DefaultPort;
- else PQport = getenv("PGPORT");
- }
-
- /* The function of PQinitstr is now done via a message to the postmaster
- *
- * PQinitstr = addValues(initstr_length);
- *
- * sprintf(PQinitstr, "%s,%s,%s,%s\n",
- * getenv("USER"), PQdatabase, PQtty, PQoption);
- */
- }
-
- /* ----------------
- * read_remark - Read and discard remarks.
- * ----------------
- */
- void
- read_remark(id)
- char id[];
- {
- char remarks[remark_length];
- char errormsg[error_msg_length];
-
- while (id[0] == 'R') {
- pq_getstr(remarks, remark_length);
- if (pq_getnchar(id, 0, 1) == EOF)
- return;
- }
- while(id[0] == 'N') {
- pq_getstr(errormsg,error_msg_length);
- fprintf(stderr,"%s",&errormsg[0]+4);
- if (pq_getnchar(id, 0, 1) == EOF)
- return;
- }
- }
-
- /* ----------------
- * EstablishComm
- * ----------------
- */
- static
- void
- EstablishComm()
- {
- if (!PQportset) {
- read_initstr();
-
- if (pq_connect(PQdatabase, getenv("USER"), PQoption, PQhost, PQtty,
- (char *) NULL, (short)atoi(PQport) ) == -1 ) {
- libpq_raise(&ProtocolError,
- form((int)"Failed to connect to backend (host=%s, port=%s)",
- PQhost, PQport));
- }
-
- pq_flush();
- PQportset = 1;
- }
- }
-
- /* ----------------
- * process_portal
- *
- * Process portal queries.
- * Return values are the same as PQexec().
- * ----------------
- */
-
- char *
- process_portal(rule_p)
- int rule_p;
- {
- char pname[portal_name_length];
- char id[2];
- char errormsg[error_msg_length];
- char command[command_length];
- char PQcommand[portal_name_length+1];
- static char retbuf[portal_name_length + 1];
-
- /* Read in the portal name. */
- pq_getstr(pname, portal_name_length);
- pqdebug("Portal name = %s", pname);
-
- /*
- * This for loop is necessary so that NOTICES out of portal processing
- * stuff are handled properly.
- */
-
- for (;;) {
- /* Read in the identifier following the portal name. */
- pq_getnchar(id, 0, 1);
- read_remark(id);
- pqdebug("Identifier is: %c", (char *)id[0]);
-
- switch (id[0]) {
- case 'E':
- /* An error, return 0. */
- pq_getstr(errormsg, error_msg_length);
- pqdebug("%s error encountered.", errormsg);
- /* get past gunk at front of errmsg */
- fprintf(stderr,"%s", &errormsg[0] + 4);
- strcpy(retbuf, "R");
- return(retbuf);
-
- case 'N': /* print notice and go back to processing return values */
- /*
- * If we get an EOF (i.e. backend quickdies) return an R to the fe
- */
- if (pq_getstr(errormsg, error_msg_length) == EOF)
- return ("R");
- pqdebug("%s notice encountered.", errormsg);
- /* get past gunk at front of errmsg */
- fprintf(stderr,"%s", &errormsg[0] + 4);
- break;
-
- case 'T':
- /* Tuples are returned, dump data into a portal buffer. */
- if (dump_data(pname, rule_p) == -1)
- {
- return("R");
- }
- sprintf(PQcommand, "P%s", pname);
- strcpy(retbuf, PQcommand);
- return(retbuf);
-
- /* Pending data inquiry - return nothing */
- case 'C':
- /*
- * Portal query command (e.g., retrieve, close),
- * no tuple returned.
- */
- PQxactid = pq_getint (4);
- pqdebug("Transaction Id is: %d", (char *)PQxactid);
- pq_getstr(command, command_length);
- pqdebug("Query command: %s", command);
-
- /* Process the portal commands. */
- if (strcmp(command, "retrieve") == 0) {
- /* Allocate a portal buffer, if portal table is full, error. */
- pbuf_setup(pname);
- return
- "Cretrieve";
- }
- else if (strcmp (command, "close") == 0)
- return
- "Cclose";
- else {
- sprintf(retbuf, "C%s", command);
- return
- retbuf;
- }
-
- default:
- {
- char s[45];
-
- PQreset();
- sprintf(s, "Unexpected identifier in process_portal: %c", id[0]);
- libpq_raise(&ProtocolError, form ((int)s));
- }
- }
- }
- }
-
- /* ----------------
- * StringPointerSet
- * ----------------
- */
- static
- void
- StringPointerSet(stringInOutP, newString, environmentString, defaultString)
- String *stringInOutP;
- String newString;
- String environmentString;
- String defaultString;
- {
- Assert(PointerIsValid(stringInOutP));
- Assert(!PointerIsValid(*stringInOutP));
- Assert(PointerIsValid(environmentString));
-
- if (PointerIsValid(newString)) {
- *stringInOutP = newString;
- } else {
- *stringInOutP = getenv(environmentString);
-
- if (!PointerIsValid(*stringInOutP)) {
- *stringInOutP = defaultString;
- }
- }
- }
-
- /* ----------------------------------------------------------------
- * PQ interface routines
- * ----------------------------------------------------------------
- */
-
- /* --------------------------------
- * PQdb - Return the current database being accessed.
- * --------------------------------
- */
- char *
- PQdb()
- {
- return PQdatabase;
- }
-
- /* ----------------
- * PQsetdb - Make the specified database the current database.
- * ----------------
- */
- void
- PQsetdb(dbname)
- char *dbname;
- {
- PQreset();
- PQdatabase[16] = '\0';
- strncpy(PQdatabase, dbname, 16);
- }
-
- /* ----------------
- * PQreset - Reset the communication port with the backend.
- * ----------------
- */
- void
- PQreset()
- {
- pq_close();
- PQportset = 0;
- /*
- * if (PQinitstr != NULL)
- * pq_free(PQinitstr);
- *
- * PQinitstr = NULL;
- */
- }
-
- /* ----------------
- * PQfinish - Close communication ports with the backend.
- * ----------------
- */
- void
- PQfinish()
- {
- if (!PQportset)
- return;
-
- pq_putnchar("X", 1); /* exiting */
- pq_flush();
- pq_close();
-
- PQportset = 0;
- }
-
- /* ----------------
- * PQFlushI - Used for flushing out "poll" queries by the monitor.
- * ----------------
- */
- int
- PQFlushI(i_count)
- int i_count;
- {
- int i;
- char holder[1];
-
- for (i = 0; i < i_count; i++) {
- pq_getnchar(holder, 0, 1);
- if (holder[0] != 'I')
- fprintf(stderr, "PQFlushI: read bad protocol entity");
- pq_getint(4); /* throw this away */
- }
- }
-
- /* ----------------
- * PQfn - Send a function call to the POSTGRES backend.
- *
- * fnid : function id
- * result_buf : pointer to result buffer (&int if integer)
- * result_len : length of return value.
- * actual_result_len: actual length returned. (differs from result_len for
- * varlena structures.
- * result_type : If the result is an integer, this must be 1,
- * If result is opaque, this must be 2.
- * args : pointer to a NULL terminated arg array.
- * (length, if integer, and result-pointer)
- * nargs : # of arguments in args array.
- * ----------------
- */
- char *
- PQfn(fnid, result_buf, result_len, actual_result_len,
- result_type, args, nargs)
- int fnid;
- int *result_buf; /* can't use void, dec compiler barfs */
- int result_len;
- int *actual_result_len;
- int result_type;
- PQArgBlock *args;
- int nargs;
- {
- char id[2];
- char errormsg[error_msg_length];
- char command[command_length];
- char PQcommand[command_length+1];
- void EstablishComm();
- int actual_len;
- short i;
-
- if (!PQportset)
- EstablishComm();
-
- pq_putnchar("F", 1); /* function */
- pq_putint(PQxactid, 4); /* transaction id ? */
- pq_putint(fnid, 4); /* function id */
- pq_putint(result_len, 4); /* length of return value */
- pq_putint(nargs, 4); /* # of args */
-
- for (i=0; i < nargs; ++i) { /* len.int4 + contents */
- pq_putint(args[i].len, 4);
- if (args[i].isint)
- pq_putint(args[i].u.integer, 4);
- else if (args[i].len == VAR_LENGTH_ARG) {
- pq_putstr((char *)args[i].u.ptr);
- } else
- pq_putnchar((char *)args[i].u.ptr, args[i].len);
- }
-
- pq_flush();
-
- /* process return value from the backend */
-
- id[0] = '?';
-
- pq_getnchar(id, 0, 1);
- while (id[0] == 'E') {
- int len;
- char buf[1024];
-
- if ((len = pq_getint(4)) >= sizeof(buf))
- len = sizeof(buf) - 1;
- pq_getstr(buf,len);
-
- fprintf(stderr, "Error: %s",buf);
- if (pq_getnchar(id, 0, 1) == EOF)
- return ((char *) NULL);
- }
-
- read_remark(id);
- fnid = pq_getint(4);
- pqdebug("The Identifier is: %c", (char *)id[0]);
-
- /* Read in the transaction id. */
- pqdebug("The Transaction Id is: %d", (char *)PQxactid);
-
- if (id[0] == 'V')
- pq_getnchar(id, 0, 1);
- for (;;) {
- switch (id[0]) {
- case 'G': /* PQFN: simple return value */
- actual_len = pq_getint(4);
- pqdebug2("LENGTH act/usr %ld/%ld\n", (char*)actual_len, (char*)result_len);
- if ((actual_len != VAR_LENGTH_RESULT) &&
- (actual_len < 0 || actual_len > result_len)) {
- pqdebug("RESET CALLED FROM CASE G", (char *)0);
- PQreset();
- libpq_raise(&ProtocolError, form ((int)"Buffer Too Small: %s", id));
- }
- if (result_type == 1)
- *(int *)result_buf = pq_getint(4);
- else if (actual_len == VAR_LENGTH_RESULT) {
- pq_getstr((char *)result_buf,MAX_STRING_LENGTH);
- } else
- pq_getnchar((char *)result_buf, 0, actual_len);
- if (actual_result_len != NULL)
- *actual_result_len = actual_len;
- if ((result_type != 2) && /* not a binary result */
- (actual_len != result_len)) /* if wouldn't overflow the buf */
- ((char *)result_buf)[actual_len] = 0; /* add a \0 */
- pq_getnchar(id, 0, 1);
- return("G");
-
- case 'E': /* print error and go back to processing return values */
- pq_getstr(errormsg, error_msg_length);
- pqdebug("%s error encountered.", errormsg);
- fprintf(stderr,"%s", errormsg);
- if (pq_getnchar(id, 0, 1) == EOF)
- return((char *) NULL);
- break;
-
- case 'N': /* print notice and go back to processing return values */
- pq_getstr(errormsg, error_msg_length);
- pqdebug("%s notice encountered.", errormsg);
- fprintf(stderr,"%s", errormsg);
- pq_getnchar(id, 0, 1);
- if (pq_getnchar(id, 0, 1) == EOF)
- return((char *) NULL);
- break;
-
- case '0': /* PQFN: no return value */
- return("V");
-
- default:
- /* The backend violates the protocol. */
- pqdebug("RESET CALLED FROM CASE G", (char *)0);
- pqdebug("Protocol Error, bad form, got '%c'", (char *)id[0]);
- PQreset();
- libpq_raise(&ProtocolError, form((int)"Unexpected identifier: %s", id));
- return(NULL);
- }
- }
- }
-
- /*
- * PQfsread, PQfswrite -- special-purpose versions of PQfn for file
- * system (POSTGRES large object) read and
- * write routines.
- *
- * We need these special versions because the user expects a standard
- * unix file system interface, and postgres wants to use varlenas
- * all over the place.
- */
-
- int
- PQfsread(fd, buf, nbytes)
- int fd;
- char *buf;
- int nbytes;
- {
- int fnid;
- char id[2];
- char errormsg[error_msg_length];
- char command[command_length];
- char PQcommand[command_length+1];
- void EstablishComm();
- int actual_len;
- short i;
-
- if (!PQportset)
- EstablishComm();
-
- pq_putnchar("F", 1); /* function */
- pq_putint(PQxactid, 4); /* transaction id? */
- pq_putint(F_LOREAD, 4); /* function id */
-
- /* size of return value -- += sizeof(int) because we expect a varlena */
- pq_putint(nbytes + sizeof(int), 4);
-
- pq_putint(2, 4); /* nargs */
-
- /* now put arguments */
- pq_putint(4, 4); /* length of fd */
- pq_putint(fd, 4);
-
- pq_putint(4, 4); /* length of nbytes */
- pq_putint(nbytes, 4);
-
- pq_flush();
-
- /* process return value from the backend */
-
- id[0] = '?';
-
- pq_getnchar(id, 0, 1);
- while (id[0] == 'E') {
- int len;
- char buf[1024];
-
- if ((len = pq_getint(4)) >= sizeof(buf))
- len = sizeof(buf) - 1;
- pq_getstr(buf,len);
-
- fprintf(stderr, "Error: %s",buf);
- if (pq_getnchar(id, 0, 1) == EOF)
- return (-1);
- }
-
- read_remark(id);
- fnid = pq_getint(4);
- pqdebug("The Identifier is: %c", (char *)id[0]);
-
- /* Read in the transaction id. */
- pqdebug("The Transaction Id is: %d", (char *)PQxactid);
-
- if (id[0] == 'V')
- pq_getnchar(id, 0, 1);
- for (;;) {
- switch (id[0]) {
- case 'G':
-
- /*
- * We know exactly what the return stream looks like, here:
- * it's a length, followed by a varlena (which includes the
- * length again...).
- */
-
- nbytes = actual_len = pq_getint(4);
- #if 0
- /* fe/be does NOT transmit varlenas this way */
- nbytes = pq_getint(4);
- nbytes -= sizeof(long); /* compensate for varlena vl->len */
- #endif
-
- if (nbytes > 0)
- pq_getnchar((char *)buf, 0, nbytes);
- pq_getnchar(id, 0, 1);
- return(nbytes);
-
- case 'E': /* print error and go back to processing return values */
- pq_getstr(errormsg, error_msg_length);
- pqdebug("%s error encountered.", errormsg);
- fprintf(stderr,"%s", errormsg);
- pq_getnchar(id, 0, 1);
- break;
-
- case 'N': /* print notice and go back to processing return values */
- pq_getstr(errormsg, error_msg_length);
- pqdebug("%s notice encountered.", errormsg);
- fprintf(stderr,"%s", errormsg);
- pq_getnchar(id, 0, 1);
- break;
-
- default:
- /* The backend violates the protocol. */
- pqdebug("RESET CALLED FROM CASE G", (char *)0);
- pqdebug("Protocol Error, bad form, got '%c'", (char *)id[0]);
- PQreset();
- libpq_raise(&ProtocolError, form((int)"Unexpected identifier: %s", id));
- return(-1);
- }
- }
- }
-
- int
- PQfswrite(fd, buf, nbytes)
- int fd;
- char *buf;
- int nbytes;
- {
- int fnid;
- char id[2];
- char errormsg[error_msg_length];
- char command[command_length];
- char PQcommand[command_length+1];
- void EstablishComm();
- int actual_len;
- short i;
-
- if (!PQportset)
- EstablishComm();
-
- pq_putnchar("F", 1); /* function */
- pq_putint(PQxactid, 4); /* transaction id ? */
- pq_putint(F_LOWRITE, 4); /* function id */
- pq_putint(4, 4); /* length of return value */
- pq_putint(2, 4); /* # of args */
-
- /* now put arguments */
- pq_putint(4, 4); /* size of fd */
- pq_putint(fd, 4);
- /*
- * The method of transmitting varlenas is:
- * Send vl_len-4
- * Send data consisting of vl_len-4 bytes.
- */
- pq_putint(nbytes, 4); /* size of varlena */
- #if 0
- /* The fe/be protocol does NOT transmit varlenas this way */
- pq_putint(nbytes + 4, 4); /* vl_len */
- #endif
- pq_putnchar(buf, nbytes); /* vl_dat */
-
- pq_flush();
-
- /* process return value from the backend */
- id[0] = '?';
-
- pq_getnchar(id, 0, 1);
- while (id[0] == 'E') {
- int len;
- char buf[1024];
-
- if ((len = pq_getint(4)) >= sizeof(buf))
- len = sizeof(buf) - 1;
- pq_getstr(buf,len);
-
- fprintf(stderr, "Error: %s",buf);
- if (pq_getnchar(id, 0, 1) == EOF)
- return (-1);
- }
-
- read_remark(id);
- fnid = pq_getint(4);
- pqdebug("The Identifier is: %c", (char *)id[0]);
-
- /* Read in the transaction id. */
- pqdebug("The Transaction Id is: %d", (char *)PQxactid);
-
- if (id[0] == 'V')
- pq_getnchar(id, 0, 1);
-
- for (;;) {
- switch (id[0]) {
- case 'G': /* PQFN: simple return value */
- actual_len = pq_getint(4);
- if (actual_len != 4)
- libpq_raise(&ProtocolError,
- form((int) "wanted 4 bytes in PQfswrite, got %d\n",
- actual_len));
- nbytes = pq_getint(4);
- pq_getnchar(id, 0, 1);
- return (nbytes);
-
- case 'E': /* print error and go back to processing return values */
- pq_getstr(errormsg, error_msg_length);
- pqdebug("%s error encountered.", errormsg);
- fprintf(stderr,"%s", errormsg);
- pq_getnchar(id, 0, 1);
- break;
-
- case 'N': /* print notice and go back to processing return values */
- pq_getstr(errormsg, error_msg_length);
- pqdebug("%s notice encountered.", errormsg);
- fprintf(stderr,"%s", errormsg);
- pq_getnchar(id, 0, 1);
- break;
-
- default:
- /* The backend violates the protocol. */
- pqdebug("RESET CALLED FROM CASE G", (char *)0);
- pqdebug("Protocol Error, bad form, got '%c'", (char *)id[0]);
- PQreset();
- libpq_raise(&ProtocolError, form((int)"Unexpected identifier: %s", id));
- return(NULL);
- }
- }
- }
-
- /* ----------------
- * PQexec - Send a query to the POSTGRES backend
- *
- * The return value is a string.
- * If there is an error: return "E error-message".
- * If tuples are fetched from the backend, return "P portal-name".
- * If a query is executed successfully but no tuples fetched,
- * return "C query-command".
- * ----------------
- */
-
- char *
- PQexec(query)
- char *query;
- {
- char id[2];
- char errormsg[error_msg_length];
- char command[command_length];
- char PQcommand[command_length+1];
- void EstablishComm();
-
- /* If the communication is not established, establish it. */
- if (!PQportset)
- EstablishComm();
-
- /* Send a query to backend. */
- pq_putnchar("Q", 1);
- pq_putint(PQxactid, 4);
- pq_putstr(query);
- pqdebug("The query sent to the backend: %s", query);
- pq_flush();
-
- /* forever (or at least until we get something besides a notice) */
- for (;;) {
-
- /* Process return values from the backend.
- * The code in this function is the implementation of
- * the communication protocol.
- */
- id[0] = '?';
-
- /* Get the identifier. */
- pq_getnchar(id,0,1);
-
- read_remark(id);
- pqdebug("The Identifier is: %c", (char *)id[0]);
-
- /* Read in the transaction id. */
- PQxactid = pq_getint(4);
- pqdebug("The Transaction Id is: %d", (char *)PQxactid);
-
- switch (id[0]) {
- case 'I':
- return("I");
-
- case 'E':
- /* An error, return 0. */
- pq_getstr(errormsg, error_msg_length);
- pqdebug("%s error encountered.", errormsg);
- fprintf(stderr,"%s", errormsg);
- /* PQportset = 0;
- EstablishComm(); */
- return("R");
-
- case 'N': /* print notice and go back to processing return values */
- /*
- * If we get an EOF (i.e. backend quickdies) return an R to the fe
- */
- if (pq_getstr(errormsg, error_msg_length) == EOF)
- return ("R");
- pqdebug("%s notice encountered.", errormsg);
- fprintf(stderr,"%s", errormsg);
- break;
-
- case 'A': {
- char relname[16];
- extern int PQAsyncNotifyWaiting;
- int pid;
- PQAsyncNotifyWaiting = 0;
-
- /* Asynchronized portal. */
- /* No tuple transfer at this stage. */
- pqdebug("%s portal encountered.", "Asynchronized");
- /* Processed the same way as synchronized portal. */
- /* return
- process_portal(1);*/
- pq_getstr(relname,16);
- pid =pq_getint(4);
- PQappendNotify(relname,pid);
- }
- break;
- case 'P':
- /* Synchronized (normal) portal. */
- return
- process_portal(0);
-
- case 'C':
- /* Query executed successfully. */
- pq_getstr (command, command_length);
- pqdebug ("Query command: %s", command);
- sprintf (PQcommand, "C%s", command);
- return
- PQcommand;
-
- case 'B':
- /* Copy command began successfully - it is sending stuff back... */
- return "BCOPY";
-
- case 'D':
- /* Copy command began successfully - it is waiting to receive... */
- return "DCOPY";
-
- default:
- /* The backend violates the protocol. */
- if (id[0] == '?')
- libpq_raise(&ProtocolError,
- form((int)"No response from the backend, exiting...\n"));
- else
- libpq_raise(&ProtocolError,
- form((int)"Unexpected response from the backend, exiting...\n"));
- exit(1);
- }
- }
- }
-
- int
- PQendcopy()
-
- {
- char id[2];
- char errormsg[error_msg_length];
-
- for (;;)
- {
- id[0] = '?';
-
- pq_getnchar(id,0,1);
-
- switch(id[0])
- {
- case 'N':
-
- pq_getstr(errormsg, error_msg_length);
- pqdebug("%s notice encountered.", errormsg);
- fprintf(stderr,"%s", errormsg);
- break;
-
- case 'E':
-
- pq_getstr(errormsg, error_msg_length);
- pqdebug("%s notice encountered.", errormsg);
- fprintf(stderr,"%s", errormsg);
- return(0);
-
- case 'Z': /* backend finished the copy */
- return(1);
-
- default:
- /* The backend violates the protocol. */
- if (id[0] == '?')
- libpq_raise(&ProtocolError,
- form((int)"No response from the backend, exiting...\n"));
- else
- libpq_raise(&ProtocolError,
- form((int)"Unexpected response from the backend, exiting...\n"));
- exit(1);
- }
- }
- }
-