Header And Logo

PostgreSQL
| The world's most advanced open source database.

fe-protocol2.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * fe-protocol2.c
00004  *    functions that are specific to frontend/backend protocol version 2
00005  *
00006  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00007  * Portions Copyright (c) 1994, Regents of the University of California
00008  *
00009  *
00010  * IDENTIFICATION
00011  *    src/interfaces/libpq/fe-protocol2.c
00012  *
00013  *-------------------------------------------------------------------------
00014  */
00015 #include "postgres_fe.h"
00016 
00017 #include <ctype.h>
00018 #include <fcntl.h>
00019 
00020 #include "libpq-fe.h"
00021 #include "libpq-int.h"
00022 
00023 
00024 #ifdef WIN32
00025 #include "win32.h"
00026 #else
00027 #include <unistd.h>
00028 #include <netinet/in.h>
00029 #ifdef HAVE_NETINET_TCP_H
00030 #include <netinet/tcp.h>
00031 #endif
00032 #include <arpa/inet.h>
00033 #endif
00034 
00035 
00036 static int  getRowDescriptions(PGconn *conn);
00037 static int  getAnotherTuple(PGconn *conn, bool binary);
00038 static int  pqGetErrorNotice2(PGconn *conn, bool isError);
00039 static void checkXactStatus(PGconn *conn, const char *cmdTag);
00040 static int  getNotify(PGconn *conn);
00041 
00042 
00043 /*
00044  *      pqSetenvPoll
00045  *
00046  * Polls the process of passing the values of a standard set of environment
00047  * variables to the backend.
00048  */
00049 PostgresPollingStatusType
00050 pqSetenvPoll(PGconn *conn)
00051 {
00052     PGresult   *res;
00053 
00054     if (conn == NULL || conn->status == CONNECTION_BAD)
00055         return PGRES_POLLING_FAILED;
00056 
00057     /* Check whether there are any data for us */
00058     switch (conn->setenv_state)
00059     {
00060             /* These are reading states */
00061         case SETENV_STATE_CLIENT_ENCODING_WAIT:
00062         case SETENV_STATE_OPTION_WAIT:
00063         case SETENV_STATE_QUERY1_WAIT:
00064         case SETENV_STATE_QUERY2_WAIT:
00065             {
00066                 /* Load waiting data */
00067                 int         n = pqReadData(conn);
00068 
00069                 if (n < 0)
00070                     goto error_return;
00071                 if (n == 0)
00072                     return PGRES_POLLING_READING;
00073 
00074                 break;
00075             }
00076 
00077             /* These are writing states, so we just proceed. */
00078         case SETENV_STATE_CLIENT_ENCODING_SEND:
00079         case SETENV_STATE_OPTION_SEND:
00080         case SETENV_STATE_QUERY1_SEND:
00081         case SETENV_STATE_QUERY2_SEND:
00082             break;
00083 
00084             /* Should we raise an error if called when not active? */
00085         case SETENV_STATE_IDLE:
00086             return PGRES_POLLING_OK;
00087 
00088         default:
00089             printfPQExpBuffer(&conn->errorMessage,
00090                               libpq_gettext(
00091                                             "invalid setenv state %c, "
00092                                  "probably indicative of memory corruption\n"
00093                                             ),
00094                               conn->setenv_state);
00095             goto error_return;
00096     }
00097 
00098     /* We will loop here until there is nothing left to do in this call. */
00099     for (;;)
00100     {
00101         switch (conn->setenv_state)
00102         {
00103                 /*
00104                  * The _CLIENT_ENCODING_SEND code is slightly different from
00105                  * _OPTION_SEND below (e.g., no getenv() call), which is why a
00106                  * different state is used.
00107                  */
00108             case SETENV_STATE_CLIENT_ENCODING_SEND:
00109                 {
00110                     char        setQuery[100];  /* note length limit in
00111                                                  * sprintf below */
00112                     const char *val = conn->client_encoding_initial;
00113 
00114                     if (val)
00115                     {
00116                         if (pg_strcasecmp(val, "default") == 0)
00117                             sprintf(setQuery, "SET client_encoding = DEFAULT");
00118                         else
00119                             sprintf(setQuery, "SET client_encoding = '%.60s'",
00120                                     val);
00121 #ifdef CONNECTDEBUG
00122                         fprintf(stderr,
00123                                 "Sending client_encoding with %s\n",
00124                                 setQuery);
00125 #endif
00126                         if (!PQsendQuery(conn, setQuery))
00127                             goto error_return;
00128 
00129                         conn->setenv_state = SETENV_STATE_CLIENT_ENCODING_WAIT;
00130                     }
00131                     else
00132                         conn->setenv_state = SETENV_STATE_OPTION_SEND;
00133                     break;
00134                 }
00135 
00136             case SETENV_STATE_OPTION_SEND:
00137                 {
00138                     /*
00139                      * Send SET commands for stuff directed by Environment
00140                      * Options.  Note: we assume that SET commands won't start
00141                      * transaction blocks, even in a 7.3 server with
00142                      * autocommit off.
00143                      */
00144                     char        setQuery[100];  /* note length limit in
00145                                                  * sprintf below */
00146 
00147                     if (conn->next_eo->envName)
00148                     {
00149                         const char *val;
00150 
00151                         if ((val = getenv(conn->next_eo->envName)))
00152                         {
00153                             if (pg_strcasecmp(val, "default") == 0)
00154                                 sprintf(setQuery, "SET %s = DEFAULT",
00155                                         conn->next_eo->pgName);
00156                             else
00157                                 sprintf(setQuery, "SET %s = '%.60s'",
00158                                         conn->next_eo->pgName, val);
00159 #ifdef CONNECTDEBUG
00160                             fprintf(stderr,
00161                                   "Use environment variable %s to send %s\n",
00162                                     conn->next_eo->envName, setQuery);
00163 #endif
00164                             if (!PQsendQuery(conn, setQuery))
00165                                 goto error_return;
00166 
00167                             conn->setenv_state = SETENV_STATE_OPTION_WAIT;
00168                         }
00169                         else
00170                             conn->next_eo++;
00171                     }
00172                     else
00173                     {
00174                         /* No more options to send, so move on to querying */
00175                         conn->setenv_state = SETENV_STATE_QUERY1_SEND;
00176                     }
00177                     break;
00178                 }
00179 
00180             case SETENV_STATE_CLIENT_ENCODING_WAIT:
00181                 {
00182                     if (PQisBusy(conn))
00183                         return PGRES_POLLING_READING;
00184 
00185                     res = PQgetResult(conn);
00186 
00187                     if (res)
00188                     {
00189                         if (PQresultStatus(res) != PGRES_COMMAND_OK)
00190                         {
00191                             PQclear(res);
00192                             goto error_return;
00193                         }
00194                         PQclear(res);
00195                         /* Keep reading until PQgetResult returns NULL */
00196                     }
00197                     else
00198                     {
00199                         /* Query finished, so send the next option */
00200                         conn->setenv_state = SETENV_STATE_OPTION_SEND;
00201                     }
00202                     break;
00203                 }
00204 
00205             case SETENV_STATE_OPTION_WAIT:
00206                 {
00207                     if (PQisBusy(conn))
00208                         return PGRES_POLLING_READING;
00209 
00210                     res = PQgetResult(conn);
00211 
00212                     if (res)
00213                     {
00214                         if (PQresultStatus(res) != PGRES_COMMAND_OK)
00215                         {
00216                             PQclear(res);
00217                             goto error_return;
00218                         }
00219                         PQclear(res);
00220                         /* Keep reading until PQgetResult returns NULL */
00221                     }
00222                     else
00223                     {
00224                         /* Query finished, so send the next option */
00225                         conn->next_eo++;
00226                         conn->setenv_state = SETENV_STATE_OPTION_SEND;
00227                     }
00228                     break;
00229                 }
00230 
00231             case SETENV_STATE_QUERY1_SEND:
00232                 {
00233                     /*
00234                      * Issue query to get information we need.  Here we must
00235                      * use begin/commit in case autocommit is off by default
00236                      * in a 7.3 server.
00237                      *
00238                      * Note: version() exists in all protocol-2.0-supporting
00239                      * backends.  In 7.3 it would be safer to write
00240                      * pg_catalog.version(), but we can't do that without
00241                      * causing problems on older versions.
00242                      */
00243                     if (!PQsendQuery(conn, "begin; select version(); end"))
00244                         goto error_return;
00245 
00246                     conn->setenv_state = SETENV_STATE_QUERY1_WAIT;
00247                     return PGRES_POLLING_READING;
00248                 }
00249 
00250             case SETENV_STATE_QUERY1_WAIT:
00251                 {
00252                     if (PQisBusy(conn))
00253                         return PGRES_POLLING_READING;
00254 
00255                     res = PQgetResult(conn);
00256 
00257                     if (res)
00258                     {
00259                         char       *val;
00260 
00261                         if (PQresultStatus(res) == PGRES_COMMAND_OK)
00262                         {
00263                             /* ignore begin/commit command results */
00264                             PQclear(res);
00265                             continue;
00266                         }
00267 
00268                         if (PQresultStatus(res) != PGRES_TUPLES_OK ||
00269                             PQntuples(res) != 1)
00270                         {
00271                             PQclear(res);
00272                             goto error_return;
00273                         }
00274 
00275                         /*
00276                          * Extract server version and save as if
00277                          * ParameterStatus
00278                          */
00279                         val = PQgetvalue(res, 0, 0);
00280                         if (val && strncmp(val, "PostgreSQL ", 11) == 0)
00281                         {
00282                             char       *ptr;
00283 
00284                             /* strip off PostgreSQL part */
00285                             val += 11;
00286 
00287                             /*
00288                              * strip off platform part (scribbles on result,
00289                              * naughty naughty)
00290                              */
00291                             ptr = strchr(val, ' ');
00292                             if (ptr)
00293                                 *ptr = '\0';
00294 
00295                             pqSaveParameterStatus(conn, "server_version",
00296                                                   val);
00297                         }
00298 
00299                         PQclear(res);
00300                         /* Keep reading until PQgetResult returns NULL */
00301                     }
00302                     else
00303                     {
00304                         /* Query finished, move to next */
00305                         conn->setenv_state = SETENV_STATE_QUERY2_SEND;
00306                     }
00307                     break;
00308                 }
00309 
00310             case SETENV_STATE_QUERY2_SEND:
00311                 {
00312                     const char *query;
00313 
00314                     /*
00315                      * pg_client_encoding does not exist in pre-7.2 servers.
00316                      * So we need to be prepared for an error here.  Do *not*
00317                      * start a transaction block, except in 7.3 servers where
00318                      * we need to prevent autocommit-off from starting a
00319                      * transaction anyway.
00320                      */
00321                     if (conn->sversion >= 70300 &&
00322                         conn->sversion < 70400)
00323                         query = "begin; select pg_catalog.pg_client_encoding(); end";
00324                     else
00325                         query = "select pg_client_encoding()";
00326                     if (!PQsendQuery(conn, query))
00327                         goto error_return;
00328 
00329                     conn->setenv_state = SETENV_STATE_QUERY2_WAIT;
00330                     return PGRES_POLLING_READING;
00331                 }
00332 
00333             case SETENV_STATE_QUERY2_WAIT:
00334                 {
00335                     if (PQisBusy(conn))
00336                         return PGRES_POLLING_READING;
00337 
00338                     res = PQgetResult(conn);
00339 
00340                     if (res)
00341                     {
00342                         const char *val;
00343 
00344                         if (PQresultStatus(res) == PGRES_COMMAND_OK)
00345                         {
00346                             /* ignore begin/commit command results */
00347                             PQclear(res);
00348                             continue;
00349                         }
00350 
00351                         if (PQresultStatus(res) == PGRES_TUPLES_OK &&
00352                             PQntuples(res) == 1)
00353                         {
00354                             /* Extract client encoding and save it */
00355                             val = PQgetvalue(res, 0, 0);
00356                             if (val && *val)    /* null should not happen, but */
00357                                 pqSaveParameterStatus(conn, "client_encoding",
00358                                                       val);
00359                         }
00360                         else
00361                         {
00362                             /*
00363                              * Error: presumably function not available, so
00364                              * use PGCLIENTENCODING or SQL_ASCII as the
00365                              * fallback.
00366                              */
00367                             val = getenv("PGCLIENTENCODING");
00368                             if (val && *val)
00369                                 pqSaveParameterStatus(conn, "client_encoding",
00370                                                       val);
00371                             else
00372                                 pqSaveParameterStatus(conn, "client_encoding",
00373                                                       "SQL_ASCII");
00374                         }
00375 
00376                         PQclear(res);
00377                         /* Keep reading until PQgetResult returns NULL */
00378                     }
00379                     else
00380                     {
00381                         /* Query finished, so we're done */
00382                         conn->setenv_state = SETENV_STATE_IDLE;
00383                         return PGRES_POLLING_OK;
00384                     }
00385                     break;
00386                 }
00387 
00388             default:
00389                 printfPQExpBuffer(&conn->errorMessage,
00390                                   libpq_gettext("invalid state %c, "
00391                                "probably indicative of memory corruption\n"),
00392                                   conn->setenv_state);
00393                 goto error_return;
00394         }
00395     }
00396 
00397     /* Unreachable */
00398 
00399 error_return:
00400     conn->setenv_state = SETENV_STATE_IDLE;
00401     return PGRES_POLLING_FAILED;
00402 }
00403 
00404 
00405 /*
00406  * parseInput: if appropriate, parse input data from backend
00407  * until input is exhausted or a stopping state is reached.
00408  * Note that this function will NOT attempt to read more data from the backend.
00409  */
00410 void
00411 pqParseInput2(PGconn *conn)
00412 {
00413     char        id;
00414 
00415     /*
00416      * Loop to parse successive complete messages available in the buffer.
00417      */
00418     for (;;)
00419     {
00420         /*
00421          * Quit if in COPY_OUT state: we expect raw data from the server until
00422          * PQendcopy is called.  Don't try to parse it according to the normal
00423          * protocol.  (This is bogus.  The data lines ought to be part of the
00424          * protocol and have identifying leading characters.)
00425          */
00426         if (conn->asyncStatus == PGASYNC_COPY_OUT)
00427             return;
00428 
00429         /*
00430          * OK to try to read a message type code.
00431          */
00432         conn->inCursor = conn->inStart;
00433         if (pqGetc(&id, conn))
00434             return;
00435 
00436         /*
00437          * NOTIFY and NOTICE messages can happen in any state besides COPY
00438          * OUT; always process them right away.
00439          *
00440          * Most other messages should only be processed while in BUSY state.
00441          * (In particular, in READY state we hold off further parsing until
00442          * the application collects the current PGresult.)
00443          *
00444          * However, if the state is IDLE then we got trouble; we need to deal
00445          * with the unexpected message somehow.
00446          */
00447         if (id == 'A')
00448         {
00449             if (getNotify(conn))
00450                 return;
00451         }
00452         else if (id == 'N')
00453         {
00454             if (pqGetErrorNotice2(conn, false))
00455                 return;
00456         }
00457         else if (conn->asyncStatus != PGASYNC_BUSY)
00458         {
00459             /* If not IDLE state, just wait ... */
00460             if (conn->asyncStatus != PGASYNC_IDLE)
00461                 return;
00462 
00463             /*
00464              * Unexpected message in IDLE state; need to recover somehow.
00465              * ERROR messages are displayed using the notice processor;
00466              * anything else is just dropped on the floor after displaying a
00467              * suitable warning notice.  (An ERROR is very possibly the
00468              * backend telling us why it is about to close the connection, so
00469              * we don't want to just discard it...)
00470              */
00471             if (id == 'E')
00472             {
00473                 if (pqGetErrorNotice2(conn, false /* treat as notice */ ))
00474                     return;
00475             }
00476             else
00477             {
00478                 pqInternalNotice(&conn->noticeHooks,
00479                         "message type 0x%02x arrived from server while idle",
00480                                  id);
00481                 /* Discard the unexpected message; good idea?? */
00482                 conn->inStart = conn->inEnd;
00483                 break;
00484             }
00485         }
00486         else
00487         {
00488             /*
00489              * In BUSY state, we can process everything.
00490              */
00491             switch (id)
00492             {
00493                 case 'C':       /* command complete */
00494                     if (pqGets(&conn->workBuffer, conn))
00495                         return;
00496                     if (conn->result == NULL)
00497                     {
00498                         conn->result = PQmakeEmptyPGresult(conn,
00499                                                            PGRES_COMMAND_OK);
00500                         if (!conn->result)
00501                             return;
00502                     }
00503                     strncpy(conn->result->cmdStatus, conn->workBuffer.data,
00504                             CMDSTATUS_LEN);
00505                     checkXactStatus(conn, conn->workBuffer.data);
00506                     conn->asyncStatus = PGASYNC_READY;
00507                     break;
00508                 case 'E':       /* error return */
00509                     if (pqGetErrorNotice2(conn, true))
00510                         return;
00511                     conn->asyncStatus = PGASYNC_READY;
00512                     break;
00513                 case 'Z':       /* backend is ready for new query */
00514                     conn->asyncStatus = PGASYNC_IDLE;
00515                     break;
00516                 case 'I':       /* empty query */
00517                     /* read and throw away the closing '\0' */
00518                     if (pqGetc(&id, conn))
00519                         return;
00520                     if (id != '\0')
00521                         pqInternalNotice(&conn->noticeHooks,
00522                                          "unexpected character %c following empty query response (\"I\" message)",
00523                                          id);
00524                     if (conn->result == NULL)
00525                         conn->result = PQmakeEmptyPGresult(conn,
00526                                                            PGRES_EMPTY_QUERY);
00527                     conn->asyncStatus = PGASYNC_READY;
00528                     break;
00529                 case 'K':       /* secret key data from the backend */
00530 
00531                     /*
00532                      * This is expected only during backend startup, but it's
00533                      * just as easy to handle it as part of the main loop.
00534                      * Save the data and continue processing.
00535                      */
00536                     if (pqGetInt(&(conn->be_pid), 4, conn))
00537                         return;
00538                     if (pqGetInt(&(conn->be_key), 4, conn))
00539                         return;
00540                     break;
00541                 case 'P':       /* synchronous (normal) portal */
00542                     if (pqGets(&conn->workBuffer, conn))
00543                         return;
00544                     /* We pretty much ignore this message type... */
00545                     break;
00546                 case 'T':       /* row descriptions (start of query results) */
00547                     if (conn->result == NULL)
00548                     {
00549                         /* First 'T' in a query sequence */
00550                         if (getRowDescriptions(conn))
00551                             return;
00552                         /* getRowDescriptions() moves inStart itself */
00553                         continue;
00554                     }
00555                     else
00556                     {
00557                         /*
00558                          * A new 'T' message is treated as the start of
00559                          * another PGresult.  (It is not clear that this is
00560                          * really possible with the current backend.) We stop
00561                          * parsing until the application accepts the current
00562                          * result.
00563                          */
00564                         conn->asyncStatus = PGASYNC_READY;
00565                         return;
00566                     }
00567                     break;
00568                 case 'D':       /* ASCII data tuple */
00569                     if (conn->result != NULL)
00570                     {
00571                         /* Read another tuple of a normal query response */
00572                         if (getAnotherTuple(conn, FALSE))
00573                             return;
00574                         /* getAnotherTuple() moves inStart itself */
00575                         continue;
00576                     }
00577                     else
00578                     {
00579                         pqInternalNotice(&conn->noticeHooks,
00580                                          "server sent data (\"D\" message) without prior row description (\"T\" message)");
00581                         /* Discard the unexpected message; good idea?? */
00582                         conn->inStart = conn->inEnd;
00583                         return;
00584                     }
00585                     break;
00586                 case 'B':       /* Binary data tuple */
00587                     if (conn->result != NULL)
00588                     {
00589                         /* Read another tuple of a normal query response */
00590                         if (getAnotherTuple(conn, TRUE))
00591                             return;
00592                         /* getAnotherTuple() moves inStart itself */
00593                         continue;
00594                     }
00595                     else
00596                     {
00597                         pqInternalNotice(&conn->noticeHooks,
00598                                          "server sent binary data (\"B\" message) without prior row description (\"T\" message)");
00599                         /* Discard the unexpected message; good idea?? */
00600                         conn->inStart = conn->inEnd;
00601                         return;
00602                     }
00603                     break;
00604                 case 'G':       /* Start Copy In */
00605                     conn->asyncStatus = PGASYNC_COPY_IN;
00606                     break;
00607                 case 'H':       /* Start Copy Out */
00608                     conn->asyncStatus = PGASYNC_COPY_OUT;
00609                     break;
00610 
00611                     /*
00612                      * Don't need to process CopyBothResponse here because it
00613                      * never arrives from the server during protocol 2.0.
00614                      */
00615                 default:
00616                     printfPQExpBuffer(&conn->errorMessage,
00617                                       libpq_gettext(
00618                                                     "unexpected response from server; first received character was \"%c\"\n"),
00619                                       id);
00620                     /* build an error result holding the error message */
00621                     pqSaveErrorResult(conn);
00622                     /* Discard the unexpected message; good idea?? */
00623                     conn->inStart = conn->inEnd;
00624                     conn->asyncStatus = PGASYNC_READY;
00625                     return;
00626             }                   /* switch on protocol character */
00627         }
00628         /* Successfully consumed this message */
00629         conn->inStart = conn->inCursor;
00630     }
00631 }
00632 
00633 /*
00634  * parseInput subroutine to read a 'T' (row descriptions) message.
00635  * We build a PGresult structure containing the attribute data.
00636  * Returns: 0 if completed message, EOF if error or not enough data
00637  * received yet.
00638  *
00639  * Note that if we run out of data, we have to suspend and reprocess
00640  * the message after more data is received.  Otherwise, conn->inStart
00641  * must get advanced past the processed data.
00642  */
00643 static int
00644 getRowDescriptions(PGconn *conn)
00645 {
00646     PGresult   *result;
00647     int         nfields;
00648     const char *errmsg;
00649     int         i;
00650 
00651     result = PQmakeEmptyPGresult(conn, PGRES_TUPLES_OK);
00652     if (!result)
00653     {
00654         errmsg = NULL;          /* means "out of memory", see below */
00655         goto advance_and_error;
00656     }
00657 
00658     /* parseInput already read the 'T' label. */
00659     /* the next two bytes are the number of fields  */
00660     if (pqGetInt(&(result->numAttributes), 2, conn))
00661         goto EOFexit;
00662     nfields = result->numAttributes;
00663 
00664     /* allocate space for the attribute descriptors */
00665     if (nfields > 0)
00666     {
00667         result->attDescs = (PGresAttDesc *)
00668             pqResultAlloc(result, nfields * sizeof(PGresAttDesc), TRUE);
00669         if (!result->attDescs)
00670         {
00671             errmsg = NULL;      /* means "out of memory", see below */
00672             goto advance_and_error;
00673         }
00674         MemSet(result->attDescs, 0, nfields * sizeof(PGresAttDesc));
00675     }
00676 
00677     /* get type info */
00678     for (i = 0; i < nfields; i++)
00679     {
00680         int         typid;
00681         int         typlen;
00682         int         atttypmod;
00683 
00684         if (pqGets(&conn->workBuffer, conn) ||
00685             pqGetInt(&typid, 4, conn) ||
00686             pqGetInt(&typlen, 2, conn) ||
00687             pqGetInt(&atttypmod, 4, conn))
00688             goto EOFexit;
00689 
00690         /*
00691          * Since pqGetInt treats 2-byte integers as unsigned, we need to
00692          * coerce the result to signed form.
00693          */
00694         typlen = (int) ((int16) typlen);
00695 
00696         result->attDescs[i].name = pqResultStrdup(result,
00697                                                   conn->workBuffer.data);
00698         if (!result->attDescs[i].name)
00699         {
00700             errmsg = NULL;      /* means "out of memory", see below */
00701             goto advance_and_error;
00702         }
00703         result->attDescs[i].tableid = 0;
00704         result->attDescs[i].columnid = 0;
00705         result->attDescs[i].format = 0;
00706         result->attDescs[i].typid = typid;
00707         result->attDescs[i].typlen = typlen;
00708         result->attDescs[i].atttypmod = atttypmod;
00709     }
00710 
00711     /* Success! */
00712     conn->result = result;
00713 
00714     /* Advance inStart to show that the "T" message has been processed. */
00715     conn->inStart = conn->inCursor;
00716 
00717     /*
00718      * We could perform additional setup for the new result set here, but for
00719      * now there's nothing else to do.
00720      */
00721 
00722     /* And we're done. */
00723     return 0;
00724 
00725 advance_and_error:
00726 
00727     /*
00728      * Discard the failed message.  Unfortunately we don't know for sure where
00729      * the end is, so just throw away everything in the input buffer. This is
00730      * not very desirable but it's the best we can do in protocol v2.
00731      */
00732     conn->inStart = conn->inEnd;
00733 
00734     /*
00735      * Replace partially constructed result with an error result. First
00736      * discard the old result to try to win back some memory.
00737      */
00738     pqClearAsyncResult(conn);
00739 
00740     /*
00741      * If preceding code didn't provide an error message, assume "out of
00742      * memory" was meant.  The advantage of having this special case is that
00743      * freeing the old result first greatly improves the odds that gettext()
00744      * will succeed in providing a translation.
00745      */
00746     if (!errmsg)
00747         errmsg = libpq_gettext("out of memory for query result");
00748 
00749     printfPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
00750 
00751     /*
00752      * XXX: if PQmakeEmptyPGresult() fails, there's probably not much we can
00753      * do to recover...
00754      */
00755     conn->result = PQmakeEmptyPGresult(conn, PGRES_FATAL_ERROR);
00756     conn->asyncStatus = PGASYNC_READY;
00757 
00758 EOFexit:
00759     if (result && result != conn->result)
00760         PQclear(result);
00761     return EOF;
00762 }
00763 
00764 /*
00765  * parseInput subroutine to read a 'B' or 'D' (row data) message.
00766  * We fill rowbuf with column pointers and then call the row processor.
00767  * Returns: 0 if completed message, EOF if error or not enough data
00768  * received yet.
00769  *
00770  * Note that if we run out of data, we have to suspend and reprocess
00771  * the message after more data is received.  Otherwise, conn->inStart
00772  * must get advanced past the processed data.
00773  */
00774 static int
00775 getAnotherTuple(PGconn *conn, bool binary)
00776 {
00777     PGresult   *result = conn->result;
00778     int         nfields = result->numAttributes;
00779     const char *errmsg;
00780     PGdataValue *rowbuf;
00781 
00782     /* the backend sends us a bitmap of which attributes are null */
00783     char        std_bitmap[64]; /* used unless it doesn't fit */
00784     char       *bitmap = std_bitmap;
00785     int         i;
00786     size_t      nbytes;         /* the number of bytes in bitmap  */
00787     char        bmap;           /* One byte of the bitmap */
00788     int         bitmap_index;   /* Its index */
00789     int         bitcnt;         /* number of bits examined in current byte */
00790     int         vlen;           /* length of the current field value */
00791 
00792     /* Resize row buffer if needed */
00793     rowbuf = conn->rowBuf;
00794     if (nfields > conn->rowBufLen)
00795     {
00796         rowbuf = (PGdataValue *) realloc(rowbuf,
00797                                          nfields * sizeof(PGdataValue));
00798         if (!rowbuf)
00799         {
00800             errmsg = NULL;      /* means "out of memory", see below */
00801             goto advance_and_error;
00802         }
00803         conn->rowBuf = rowbuf;
00804         conn->rowBufLen = nfields;
00805     }
00806 
00807     /* Save format specifier */
00808     result->binary = binary;
00809 
00810     /*
00811      * If it's binary, fix the column format indicators.  We assume the
00812      * backend will consistently send either B or D, not a mix.
00813      */
00814     if (binary)
00815     {
00816         for (i = 0; i < nfields; i++)
00817             result->attDescs[i].format = 1;
00818     }
00819 
00820     /* Get the null-value bitmap */
00821     nbytes = (nfields + BITS_PER_BYTE - 1) / BITS_PER_BYTE;
00822     /* malloc() only for unusually large field counts... */
00823     if (nbytes > sizeof(std_bitmap))
00824     {
00825         bitmap = (char *) malloc(nbytes);
00826         if (!bitmap)
00827         {
00828             errmsg = NULL;      /* means "out of memory", see below */
00829             goto advance_and_error;
00830         }
00831     }
00832 
00833     if (pqGetnchar(bitmap, nbytes, conn))
00834         goto EOFexit;
00835 
00836     /* Scan the fields */
00837     bitmap_index = 0;
00838     bmap = bitmap[bitmap_index];
00839     bitcnt = 0;
00840 
00841     for (i = 0; i < nfields; i++)
00842     {
00843         /* get the value length */
00844         if (!(bmap & 0200))
00845             vlen = NULL_LEN;
00846         else if (pqGetInt(&vlen, 4, conn))
00847             goto EOFexit;
00848         else
00849         {
00850             if (!binary)
00851                 vlen = vlen - 4;
00852             if (vlen < 0)
00853                 vlen = 0;
00854         }
00855         rowbuf[i].len = vlen;
00856 
00857         /*
00858          * rowbuf[i].value always points to the next address in the data
00859          * buffer even if the value is NULL.  This allows row processors to
00860          * estimate data sizes more easily.
00861          */
00862         rowbuf[i].value = conn->inBuffer + conn->inCursor;
00863 
00864         /* Skip over the data value */
00865         if (vlen > 0)
00866         {
00867             if (pqSkipnchar(vlen, conn))
00868                 goto EOFexit;
00869         }
00870 
00871         /* advance the bitmap stuff */
00872         bitcnt++;
00873         if (bitcnt == BITS_PER_BYTE)
00874         {
00875             bitmap_index++;
00876             bmap = bitmap[bitmap_index];
00877             bitcnt = 0;
00878         }
00879         else
00880             bmap <<= 1;
00881     }
00882 
00883     /* Release bitmap now if we allocated it */
00884     if (bitmap != std_bitmap)
00885         free(bitmap);
00886     bitmap = NULL;
00887 
00888     /* Advance inStart to show that the "D" message has been processed. */
00889     conn->inStart = conn->inCursor;
00890 
00891     /* Process the collected row */
00892     errmsg = NULL;
00893     if (pqRowProcessor(conn, &errmsg))
00894         return 0;               /* normal, successful exit */
00895 
00896     goto set_error_result;      /* pqRowProcessor failed, report it */
00897 
00898 advance_and_error:
00899 
00900     /*
00901      * Discard the failed message.  Unfortunately we don't know for sure where
00902      * the end is, so just throw away everything in the input buffer. This is
00903      * not very desirable but it's the best we can do in protocol v2.
00904      */
00905     conn->inStart = conn->inEnd;
00906 
00907 set_error_result:
00908 
00909     /*
00910      * Replace partially constructed result with an error result. First
00911      * discard the old result to try to win back some memory.
00912      */
00913     pqClearAsyncResult(conn);
00914 
00915     /*
00916      * If preceding code didn't provide an error message, assume "out of
00917      * memory" was meant.  The advantage of having this special case is that
00918      * freeing the old result first greatly improves the odds that gettext()
00919      * will succeed in providing a translation.
00920      */
00921     if (!errmsg)
00922         errmsg = libpq_gettext("out of memory for query result");
00923 
00924     printfPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
00925 
00926     /*
00927      * XXX: if PQmakeEmptyPGresult() fails, there's probably not much we can
00928      * do to recover...
00929      */
00930     conn->result = PQmakeEmptyPGresult(conn, PGRES_FATAL_ERROR);
00931     conn->asyncStatus = PGASYNC_READY;
00932 
00933 EOFexit:
00934     if (bitmap != NULL && bitmap != std_bitmap)
00935         free(bitmap);
00936     return EOF;
00937 }
00938 
00939 
00940 /*
00941  * Attempt to read an Error or Notice response message.
00942  * This is possible in several places, so we break it out as a subroutine.
00943  * Entry: 'E' or 'N' message type has already been consumed.
00944  * Exit: returns 0 if successfully consumed message.
00945  *       returns EOF if not enough data.
00946  */
00947 static int
00948 pqGetErrorNotice2(PGconn *conn, bool isError)
00949 {
00950     PGresult   *res = NULL;
00951     PQExpBufferData workBuf;
00952     char       *startp;
00953     char       *splitp;
00954 
00955     /*
00956      * Since the message might be pretty long, we create a temporary
00957      * PQExpBuffer rather than using conn->workBuffer.  workBuffer is intended
00958      * for stuff that is expected to be short.
00959      */
00960     initPQExpBuffer(&workBuf);
00961     if (pqGets(&workBuf, conn))
00962         goto failure;
00963 
00964     /*
00965      * Make a PGresult to hold the message.  We temporarily lie about the
00966      * result status, so that PQmakeEmptyPGresult doesn't uselessly copy
00967      * conn->errorMessage.
00968      */
00969     res = PQmakeEmptyPGresult(conn, PGRES_EMPTY_QUERY);
00970     if (!res)
00971         goto failure;
00972     res->resultStatus = isError ? PGRES_FATAL_ERROR : PGRES_NONFATAL_ERROR;
00973     res->errMsg = pqResultStrdup(res, workBuf.data);
00974     if (!res->errMsg)
00975         goto failure;
00976 
00977     /*
00978      * Break the message into fields.  We can't do very much here, but we can
00979      * split the severity code off, and remove trailing newlines. Also, we use
00980      * the heuristic that the primary message extends only to the first
00981      * newline --- anything after that is detail message.  (In some cases it'd
00982      * be better classed as hint, but we can hardly be expected to guess that
00983      * here.)
00984      */
00985     while (workBuf.len > 0 && workBuf.data[workBuf.len - 1] == '\n')
00986         workBuf.data[--workBuf.len] = '\0';
00987     splitp = strstr(workBuf.data, ":  ");
00988     if (splitp)
00989     {
00990         /* what comes before the colon is severity */
00991         *splitp = '\0';
00992         pqSaveMessageField(res, PG_DIAG_SEVERITY, workBuf.data);
00993         startp = splitp + 3;
00994     }
00995     else
00996     {
00997         /* can't find a colon?  oh well... */
00998         startp = workBuf.data;
00999     }
01000     splitp = strchr(startp, '\n');
01001     if (splitp)
01002     {
01003         /* what comes before the newline is primary message */
01004         *splitp++ = '\0';
01005         pqSaveMessageField(res, PG_DIAG_MESSAGE_PRIMARY, startp);
01006         /* the rest is detail; strip any leading whitespace */
01007         while (*splitp && isspace((unsigned char) *splitp))
01008             splitp++;
01009         pqSaveMessageField(res, PG_DIAG_MESSAGE_DETAIL, splitp);
01010     }
01011     else
01012     {
01013         /* single-line message, so all primary */
01014         pqSaveMessageField(res, PG_DIAG_MESSAGE_PRIMARY, startp);
01015     }
01016 
01017     /*
01018      * Either save error as current async result, or just emit the notice.
01019      * Also, if it's an error and we were in a transaction block, assume the
01020      * server has now gone to error-in-transaction state.
01021      */
01022     if (isError)
01023     {
01024         pqClearAsyncResult(conn);
01025         conn->result = res;
01026         resetPQExpBuffer(&conn->errorMessage);
01027         appendPQExpBufferStr(&conn->errorMessage, res->errMsg);
01028         if (conn->xactStatus == PQTRANS_INTRANS)
01029             conn->xactStatus = PQTRANS_INERROR;
01030     }
01031     else
01032     {
01033         if (res->noticeHooks.noticeRec != NULL)
01034             (*res->noticeHooks.noticeRec) (res->noticeHooks.noticeRecArg, res);
01035         PQclear(res);
01036     }
01037 
01038     termPQExpBuffer(&workBuf);
01039     return 0;
01040 
01041 failure:
01042     if (res)
01043         PQclear(res);
01044     termPQExpBuffer(&workBuf);
01045     return EOF;
01046 }
01047 
01048 /*
01049  * checkXactStatus - attempt to track transaction-block status of server
01050  *
01051  * This is called each time we receive a command-complete message.  By
01052  * watching for messages from BEGIN/COMMIT/ROLLBACK commands, we can do
01053  * a passable job of tracking the server's xact status.  BUT: this does
01054  * not work at all on 7.3 servers with AUTOCOMMIT OFF.  (Man, was that
01055  * feature ever a mistake.)  Caveat user.
01056  *
01057  * The tags known here are all those used as far back as 7.0; is it worth
01058  * adding those from even-older servers?
01059  */
01060 static void
01061 checkXactStatus(PGconn *conn, const char *cmdTag)
01062 {
01063     if (strcmp(cmdTag, "BEGIN") == 0)
01064         conn->xactStatus = PQTRANS_INTRANS;
01065     else if (strcmp(cmdTag, "COMMIT") == 0)
01066         conn->xactStatus = PQTRANS_IDLE;
01067     else if (strcmp(cmdTag, "ROLLBACK") == 0)
01068         conn->xactStatus = PQTRANS_IDLE;
01069     else if (strcmp(cmdTag, "START TRANSACTION") == 0)  /* 7.3 only */
01070         conn->xactStatus = PQTRANS_INTRANS;
01071 
01072     /*
01073      * Normally we get into INERROR state by detecting an Error message.
01074      * However, if we see one of these tags then we know for sure the server
01075      * is in abort state ...
01076      */
01077     else if (strcmp(cmdTag, "*ABORT STATE*") == 0)      /* pre-7.3 only */
01078         conn->xactStatus = PQTRANS_INERROR;
01079 }
01080 
01081 /*
01082  * Attempt to read a Notify response message.
01083  * This is possible in several places, so we break it out as a subroutine.
01084  * Entry: 'A' message type and length have already been consumed.
01085  * Exit: returns 0 if successfully consumed Notify message.
01086  *       returns EOF if not enough data.
01087  */
01088 static int
01089 getNotify(PGconn *conn)
01090 {
01091     int         be_pid;
01092     int         nmlen;
01093     PGnotify   *newNotify;
01094 
01095     if (pqGetInt(&be_pid, 4, conn))
01096         return EOF;
01097     if (pqGets(&conn->workBuffer, conn))
01098         return EOF;
01099 
01100     /*
01101      * Store the relation name right after the PQnotify structure so it can
01102      * all be freed at once.  We don't use NAMEDATALEN because we don't want
01103      * to tie this interface to a specific server name length.
01104      */
01105     nmlen = strlen(conn->workBuffer.data);
01106     newNotify = (PGnotify *) malloc(sizeof(PGnotify) + nmlen + 1);
01107     if (newNotify)
01108     {
01109         newNotify->relname = (char *) newNotify + sizeof(PGnotify);
01110         strcpy(newNotify->relname, conn->workBuffer.data);
01111         /* fake up an empty-string extra field */
01112         newNotify->extra = newNotify->relname + nmlen;
01113         newNotify->be_pid = be_pid;
01114         newNotify->next = NULL;
01115         if (conn->notifyTail)
01116             conn->notifyTail->next = newNotify;
01117         else
01118             conn->notifyHead = newNotify;
01119         conn->notifyTail = newNotify;
01120     }
01121 
01122     return 0;
01123 }
01124 
01125 
01126 /*
01127  * PQgetCopyData - read a row of data from the backend during COPY OUT
01128  *
01129  * If successful, sets *buffer to point to a malloc'd row of data, and
01130  * returns row length (always > 0) as result.
01131  * Returns 0 if no row available yet (only possible if async is true),
01132  * -1 if end of copy (consult PQgetResult), or -2 if error (consult
01133  * PQerrorMessage).
01134  */
01135 int
01136 pqGetCopyData2(PGconn *conn, char **buffer, int async)
01137 {
01138     bool        found;
01139     int         msgLength;
01140 
01141     for (;;)
01142     {
01143         /*
01144          * Do we have a complete line of data?
01145          */
01146         conn->inCursor = conn->inStart;
01147         found = false;
01148         while (conn->inCursor < conn->inEnd)
01149         {
01150             char        c = conn->inBuffer[conn->inCursor++];
01151 
01152             if (c == '\n')
01153             {
01154                 found = true;
01155                 break;
01156             }
01157         }
01158         if (!found)
01159             goto nodata;
01160         msgLength = conn->inCursor - conn->inStart;
01161 
01162         /*
01163          * If it's the end-of-data marker, consume it, exit COPY_OUT mode, and
01164          * let caller read status with PQgetResult().
01165          */
01166         if (msgLength == 3 &&
01167             strncmp(&conn->inBuffer[conn->inStart], "\\.\n", 3) == 0)
01168         {
01169             conn->inStart = conn->inCursor;
01170             conn->asyncStatus = PGASYNC_BUSY;
01171             return -1;
01172         }
01173 
01174         /*
01175          * Pass the line back to the caller.
01176          */
01177         *buffer = (char *) malloc(msgLength + 1);
01178         if (*buffer == NULL)
01179         {
01180             printfPQExpBuffer(&conn->errorMessage,
01181                               libpq_gettext("out of memory\n"));
01182             return -2;
01183         }
01184         memcpy(*buffer, &conn->inBuffer[conn->inStart], msgLength);
01185         (*buffer)[msgLength] = '\0';    /* Add terminating null */
01186 
01187         /* Mark message consumed */
01188         conn->inStart = conn->inCursor;
01189 
01190         return msgLength;
01191 
01192 nodata:
01193         /* Don't block if async read requested */
01194         if (async)
01195             return 0;
01196         /* Need to load more data */
01197         if (pqWait(TRUE, FALSE, conn) ||
01198             pqReadData(conn) < 0)
01199             return -2;
01200     }
01201 }
01202 
01203 
01204 /*
01205  * PQgetline - gets a newline-terminated string from the backend.
01206  *
01207  * See fe-exec.c for documentation.
01208  */
01209 int
01210 pqGetline2(PGconn *conn, char *s, int maxlen)
01211 {
01212     int         result = 1;     /* return value if buffer overflows */
01213 
01214     if (conn->sock < 0 ||
01215         conn->asyncStatus != PGASYNC_COPY_OUT)
01216     {
01217         *s = '\0';
01218         return EOF;
01219     }
01220 
01221     /*
01222      * Since this is a purely synchronous routine, we don't bother to maintain
01223      * conn->inCursor; there is no need to back up.
01224      */
01225     while (maxlen > 1)
01226     {
01227         if (conn->inStart < conn->inEnd)
01228         {
01229             char        c = conn->inBuffer[conn->inStart++];
01230 
01231             if (c == '\n')
01232             {
01233                 result = 0;     /* success exit */
01234                 break;
01235             }
01236             *s++ = c;
01237             maxlen--;
01238         }
01239         else
01240         {
01241             /* need to load more data */
01242             if (pqWait(TRUE, FALSE, conn) ||
01243                 pqReadData(conn) < 0)
01244             {
01245                 result = EOF;
01246                 break;
01247             }
01248         }
01249     }
01250     *s = '\0';
01251 
01252     return result;
01253 }
01254 
01255 /*
01256  * PQgetlineAsync - gets a COPY data row without blocking.
01257  *
01258  * See fe-exec.c for documentation.
01259  */
01260 int
01261 pqGetlineAsync2(PGconn *conn, char *buffer, int bufsize)
01262 {
01263     int         avail;
01264 
01265     if (conn->asyncStatus != PGASYNC_COPY_OUT)
01266         return -1;              /* we are not doing a copy... */
01267 
01268     /*
01269      * Move data from libpq's buffer to the caller's. We want to accept data
01270      * only in units of whole lines, not partial lines.  This ensures that we
01271      * can recognize the terminator line "\\.\n".  (Otherwise, if it happened
01272      * to cross a packet/buffer boundary, we might hand the first one or two
01273      * characters off to the caller, which we shouldn't.)
01274      */
01275 
01276     conn->inCursor = conn->inStart;
01277 
01278     avail = bufsize;
01279     while (avail > 0 && conn->inCursor < conn->inEnd)
01280     {
01281         char        c = conn->inBuffer[conn->inCursor++];
01282 
01283         *buffer++ = c;
01284         --avail;
01285         if (c == '\n')
01286         {
01287             /* Got a complete line; mark the data removed from libpq */
01288             conn->inStart = conn->inCursor;
01289             /* Is it the endmarker line? */
01290             if (bufsize - avail == 3 && buffer[-3] == '\\' && buffer[-2] == '.')
01291                 return -1;
01292             /* No, return the data line to the caller */
01293             return bufsize - avail;
01294         }
01295     }
01296 
01297     /*
01298      * We don't have a complete line. We'd prefer to leave it in libpq's
01299      * buffer until the rest arrives, but there is a special case: what if the
01300      * line is longer than the buffer the caller is offering us?  In that case
01301      * we'd better hand over a partial line, else we'd get into an infinite
01302      * loop. Do this in a way that ensures we can't misrecognize a terminator
01303      * line later: leave last 3 characters in libpq buffer.
01304      */
01305     if (avail == 0 && bufsize > 3)
01306     {
01307         conn->inStart = conn->inCursor - 3;
01308         return bufsize - 3;
01309     }
01310     return 0;
01311 }
01312 
01313 /*
01314  * PQendcopy
01315  *
01316  * See fe-exec.c for documentation.
01317  */
01318 int
01319 pqEndcopy2(PGconn *conn)
01320 {
01321     PGresult   *result;
01322 
01323     if (conn->asyncStatus != PGASYNC_COPY_IN &&
01324         conn->asyncStatus != PGASYNC_COPY_OUT)
01325     {
01326         printfPQExpBuffer(&conn->errorMessage,
01327                           libpq_gettext("no COPY in progress\n"));
01328         return 1;
01329     }
01330 
01331     /*
01332      * make sure no data is waiting to be sent, abort if we are non-blocking
01333      * and the flush fails
01334      */
01335     if (pqFlush(conn) && pqIsnonblocking(conn))
01336         return 1;
01337 
01338     /* non blocking connections may have to abort at this point. */
01339     if (pqIsnonblocking(conn) && PQisBusy(conn))
01340         return 1;
01341 
01342     /* Return to active duty */
01343     conn->asyncStatus = PGASYNC_BUSY;
01344     resetPQExpBuffer(&conn->errorMessage);
01345 
01346     /* Wait for the completion response */
01347     result = PQgetResult(conn);
01348 
01349     /* Expecting a successful result */
01350     if (result && result->resultStatus == PGRES_COMMAND_OK)
01351     {
01352         PQclear(result);
01353         return 0;
01354     }
01355 
01356     /*
01357      * Trouble. For backwards-compatibility reasons, we issue the error
01358      * message as if it were a notice (would be nice to get rid of this
01359      * silliness, but too many apps probably don't handle errors from
01360      * PQendcopy reasonably).  Note that the app can still obtain the error
01361      * status from the PGconn object.
01362      */
01363     if (conn->errorMessage.len > 0)
01364     {
01365         /* We have to strip the trailing newline ... pain in neck... */
01366         char        svLast = conn->errorMessage.data[conn->errorMessage.len - 1];
01367 
01368         if (svLast == '\n')
01369             conn->errorMessage.data[conn->errorMessage.len - 1] = '\0';
01370         pqInternalNotice(&conn->noticeHooks, "%s", conn->errorMessage.data);
01371         conn->errorMessage.data[conn->errorMessage.len - 1] = svLast;
01372     }
01373 
01374     PQclear(result);
01375 
01376     /*
01377      * The worst case is that we've lost sync with the backend entirely due to
01378      * application screwup of the copy in/out protocol. To recover, reset the
01379      * connection (talk about using a sledgehammer...)
01380      */
01381     pqInternalNotice(&conn->noticeHooks,
01382                    "lost synchronization with server, resetting connection");
01383 
01384     /*
01385      * Users doing non-blocking connections need to handle the reset
01386      * themselves, they'll need to check the connection status if we return an
01387      * error.
01388      */
01389     if (pqIsnonblocking(conn))
01390         PQresetStart(conn);
01391     else
01392         PQreset(conn);
01393 
01394     return 1;
01395 }
01396 
01397 
01398 /*
01399  * PQfn - Send a function call to the POSTGRES backend.
01400  *
01401  * See fe-exec.c for documentation.
01402  */
01403 PGresult *
01404 pqFunctionCall2(PGconn *conn, Oid fnid,
01405                 int *result_buf, int *actual_result_len,
01406                 int result_is_int,
01407                 const PQArgBlock *args, int nargs)
01408 {
01409     bool        needInput = false;
01410     ExecStatusType status = PGRES_FATAL_ERROR;
01411     char        id;
01412     int         i;
01413 
01414     /* PQfn already validated connection state */
01415 
01416     if (pqPutMsgStart('F', false, conn) < 0 ||  /* function call msg */
01417         pqPuts(" ", conn) < 0 ||    /* dummy string */
01418         pqPutInt(fnid, 4, conn) != 0 || /* function id */
01419         pqPutInt(nargs, 4, conn) != 0)  /* # of args */
01420     {
01421         pqHandleSendFailure(conn);
01422         return NULL;
01423     }
01424 
01425     for (i = 0; i < nargs; ++i)
01426     {                           /* len.int4 + contents     */
01427         if (pqPutInt(args[i].len, 4, conn))
01428         {
01429             pqHandleSendFailure(conn);
01430             return NULL;
01431         }
01432 
01433         if (args[i].isint)
01434         {
01435             if (pqPutInt(args[i].u.integer, 4, conn))
01436             {
01437                 pqHandleSendFailure(conn);
01438                 return NULL;
01439             }
01440         }
01441         else
01442         {
01443             if (pqPutnchar((char *) args[i].u.ptr, args[i].len, conn))
01444             {
01445                 pqHandleSendFailure(conn);
01446                 return NULL;
01447             }
01448         }
01449     }
01450 
01451     if (pqPutMsgEnd(conn) < 0 ||
01452         pqFlush(conn))
01453     {
01454         pqHandleSendFailure(conn);
01455         return NULL;
01456     }
01457 
01458     for (;;)
01459     {
01460         if (needInput)
01461         {
01462             /* Wait for some data to arrive (or for the channel to close) */
01463             if (pqWait(TRUE, FALSE, conn) ||
01464                 pqReadData(conn) < 0)
01465                 break;
01466         }
01467 
01468         /*
01469          * Scan the message. If we run out of data, loop around to try again.
01470          */
01471         conn->inCursor = conn->inStart;
01472         needInput = true;
01473 
01474         if (pqGetc(&id, conn))
01475             continue;
01476 
01477         /*
01478          * We should see V or E response to the command, but might get N
01479          * and/or A notices first. We also need to swallow the final Z before
01480          * returning.
01481          */
01482         switch (id)
01483         {
01484             case 'V':           /* function result */
01485                 if (pqGetc(&id, conn))
01486                     continue;
01487                 if (id == 'G')
01488                 {
01489                     /* function returned nonempty value */
01490                     if (pqGetInt(actual_result_len, 4, conn))
01491                         continue;
01492                     if (result_is_int)
01493                     {
01494                         if (pqGetInt(result_buf, 4, conn))
01495                             continue;
01496                     }
01497                     else
01498                     {
01499                         if (pqGetnchar((char *) result_buf,
01500                                        *actual_result_len,
01501                                        conn))
01502                             continue;
01503                     }
01504                     if (pqGetc(&id, conn))      /* get the last '0' */
01505                         continue;
01506                 }
01507                 if (id == '0')
01508                 {
01509                     /* correctly finished function result message */
01510                     status = PGRES_COMMAND_OK;
01511                 }
01512                 else
01513                 {
01514                     /* The backend violates the protocol. */
01515                     printfPQExpBuffer(&conn->errorMessage,
01516                                   libpq_gettext("protocol error: id=0x%x\n"),
01517                                       id);
01518                     pqSaveErrorResult(conn);
01519                     conn->inStart = conn->inCursor;
01520                     return pqPrepareAsyncResult(conn);
01521                 }
01522                 break;
01523             case 'E':           /* error return */
01524                 if (pqGetErrorNotice2(conn, true))
01525                     continue;
01526                 status = PGRES_FATAL_ERROR;
01527                 break;
01528             case 'A':           /* notify message */
01529                 /* handle notify and go back to processing return values */
01530                 if (getNotify(conn))
01531                     continue;
01532                 break;
01533             case 'N':           /* notice */
01534                 /* handle notice and go back to processing return values */
01535                 if (pqGetErrorNotice2(conn, false))
01536                     continue;
01537                 break;
01538             case 'Z':           /* backend is ready for new query */
01539                 /* consume the message and exit */
01540                 conn->inStart = conn->inCursor;
01541                 /* if we saved a result object (probably an error), use it */
01542                 if (conn->result)
01543                     return pqPrepareAsyncResult(conn);
01544                 return PQmakeEmptyPGresult(conn, status);
01545             default:
01546                 /* The backend violates the protocol. */
01547                 printfPQExpBuffer(&conn->errorMessage,
01548                                   libpq_gettext("protocol error: id=0x%x\n"),
01549                                   id);
01550                 pqSaveErrorResult(conn);
01551                 conn->inStart = conn->inCursor;
01552                 return pqPrepareAsyncResult(conn);
01553         }
01554         /* Completed this message, keep going */
01555         conn->inStart = conn->inCursor;
01556         needInput = false;
01557     }
01558 
01559     /*
01560      * We fall out of the loop only upon failing to read data.
01561      * conn->errorMessage has been set by pqWait or pqReadData. We want to
01562      * append it to any already-received error message.
01563      */
01564     pqSaveErrorResult(conn);
01565     return pqPrepareAsyncResult(conn);
01566 }
01567 
01568 
01569 /*
01570  * Construct startup packet
01571  *
01572  * Returns a malloc'd packet buffer, or NULL if out of memory
01573  */
01574 char *
01575 pqBuildStartupPacket2(PGconn *conn, int *packetlen,
01576                       const PQEnvironmentOption *options)
01577 {
01578     StartupPacket *startpacket;
01579 
01580     *packetlen = sizeof(StartupPacket);
01581     startpacket = (StartupPacket *) malloc(sizeof(StartupPacket));
01582     if (!startpacket)
01583         return NULL;
01584 
01585     MemSet(startpacket, 0, sizeof(StartupPacket));
01586 
01587     startpacket->protoVersion = htonl(conn->pversion);
01588 
01589     strncpy(startpacket->user, conn->pguser, SM_USER);
01590     strncpy(startpacket->database, conn->dbName, SM_DATABASE);
01591     strncpy(startpacket->tty, conn->pgtty, SM_TTY);
01592 
01593     if (conn->pgoptions)
01594         strncpy(startpacket->options, conn->pgoptions, SM_OPTIONS);
01595 
01596     return (char *) startpacket;
01597 }