📄 fe-exec.c
字号:
else newTuples = (PGresAttValue **) realloc(res->tuples, newSize * sizeof(PGresAttValue *)); if (!newTuples) return FALSE; /* malloc or realloc failed */ res->tupArrSize = newSize; res->tuples = newTuples; } res->tuples[res->ntups] = tup; res->ntups++; return TRUE;}/* * pqSaveMessageField - save one field of an error or notice message */voidpqSaveMessageField(PGresult *res, char code, const char *value){ PGMessageField *pfield; pfield = (PGMessageField *) pqResultAlloc(res, sizeof(PGMessageField) + strlen(value), TRUE); if (!pfield) return; /* out of memory? */ pfield->code = code; strcpy(pfield->contents, value); pfield->next = res->errFields; res->errFields = pfield;}/* * pqSaveParameterStatus - remember parameter status sent by backend */voidpqSaveParameterStatus(PGconn *conn, const char *name, const char *value){ pgParameterStatus *pstatus; pgParameterStatus *prev; if (conn->Pfdebug) fprintf(conn->Pfdebug, "pqSaveParameterStatus: '%s' = '%s'\n", name, value); /* * Forget any old information about the parameter */ for (pstatus = conn->pstatus, prev = NULL; pstatus != NULL; prev = pstatus, pstatus = pstatus->next) { if (strcmp(pstatus->name, name) == 0) { if (prev) prev->next = pstatus->next; else conn->pstatus = pstatus->next; free(pstatus); /* frees name and value strings too */ break; } } /* * Store new info as a single malloc block */ pstatus = (pgParameterStatus *) malloc(sizeof(pgParameterStatus) + strlen(name) +strlen(value) + 2); if (pstatus) { char *ptr; ptr = ((char *) pstatus) + sizeof(pgParameterStatus); pstatus->name = ptr; strcpy(ptr, name); ptr += strlen(name) + 1; pstatus->value = ptr; strcpy(ptr, value); pstatus->next = conn->pstatus; conn->pstatus = pstatus; } /* * Special hacks: remember client_encoding and standard_conforming_strings, * and convert server version to a numeric form. We keep the first two of * these in static variables as well, so that PQescapeString and * PQescapeBytea can behave somewhat sanely (at least in single- * connection-using programs). */ if (strcmp(name, "client_encoding") == 0) { conn->client_encoding = pg_char_to_encoding(value); static_client_encoding = conn->client_encoding; } else if (strcmp(name, "standard_conforming_strings") == 0) { conn->std_strings = (strcmp(value, "on") == 0); static_std_strings = conn->std_strings; } else if (strcmp(name, "server_version") == 0) { int cnt; int vmaj, vmin, vrev; cnt = sscanf(value, "%d.%d.%d", &vmaj, &vmin, &vrev); if (cnt < 2) conn->sversion = 0; /* unknown */ else { if (cnt == 2) vrev = 0; conn->sversion = (100 * vmaj + vmin) * 100 + vrev; } }}/* * PQsendQuery * Submit a query, but don't wait for it to finish * * Returns: 1 if successfully submitted * 0 if error (conn->errorMessage is set) */intPQsendQuery(PGconn *conn, const char *query){ if (!PQsendQueryStart(conn)) return 0; if (!query) { printfPQExpBuffer(&conn->errorMessage, libpq_gettext("command string is a null pointer\n")); return 0; } /* construct the outgoing Query message */ if (pqPutMsgStart('Q', false, conn) < 0 || pqPuts(query, conn) < 0 || pqPutMsgEnd(conn) < 0) { pqHandleSendFailure(conn); return 0; } /* remember we are using simple query protocol */ conn->queryclass = PGQUERY_SIMPLE; /* * Give the data a push. In nonblock mode, don't complain if we're unable * to send it all; PQgetResult() will do any additional flushing needed. */ if (pqFlush(conn) < 0) { pqHandleSendFailure(conn); return 0; } /* OK, it's launched! */ conn->asyncStatus = PGASYNC_BUSY; return 1;}/* * PQsendQueryParams * Like PQsendQuery, but use protocol 3.0 so we can pass parameters */intPQsendQueryParams(PGconn *conn, const char *command, int nParams, const Oid *paramTypes, const char *const * paramValues, const int *paramLengths, const int *paramFormats, int resultFormat){ if (!PQsendQueryStart(conn)) return 0; if (!command) { printfPQExpBuffer(&conn->errorMessage, libpq_gettext("command string is a null pointer\n")); return 0; } return PQsendQueryGuts(conn, command, "", /* use unnamed statement */ nParams, paramTypes, paramValues, paramLengths, paramFormats, resultFormat);}/* * PQsendPrepare * Submit a Parse message, but don't wait for it to finish * * Returns: 1 if successfully submitted * 0 if error (conn->errorMessage is set) */intPQsendPrepare(PGconn *conn, const char *stmtName, const char *query, int nParams, const Oid *paramTypes){ if (!PQsendQueryStart(conn)) return 0; if (!stmtName) { printfPQExpBuffer(&conn->errorMessage, libpq_gettext("statement name is a null pointer\n")); return 0; } if (!query) { printfPQExpBuffer(&conn->errorMessage, libpq_gettext("command string is a null pointer\n")); return 0; } /* This isn't gonna work on a 2.0 server */ if (PG_PROTOCOL_MAJOR(conn->pversion) < 3) { printfPQExpBuffer(&conn->errorMessage, libpq_gettext("function requires at least protocol version 3.0\n")); return 0; } /* construct the Parse message */ if (pqPutMsgStart('P', false, conn) < 0 || pqPuts(stmtName, conn) < 0 || pqPuts(query, conn) < 0) goto sendFailed; if (nParams > 0 && paramTypes) { int i; if (pqPutInt(nParams, 2, conn) < 0) goto sendFailed; for (i = 0; i < nParams; i++) { if (pqPutInt(paramTypes[i], 4, conn) < 0) goto sendFailed; } } else { if (pqPutInt(0, 2, conn) < 0) goto sendFailed; } if (pqPutMsgEnd(conn) < 0) goto sendFailed; /* construct the Sync message */ if (pqPutMsgStart('S', false, conn) < 0 || pqPutMsgEnd(conn) < 0) goto sendFailed; /* remember we are doing just a Parse */ conn->queryclass = PGQUERY_PREPARE; /* * Give the data a push. In nonblock mode, don't complain if we're unable * to send it all; PQgetResult() will do any additional flushing needed. */ if (pqFlush(conn) < 0) goto sendFailed; /* OK, it's launched! */ conn->asyncStatus = PGASYNC_BUSY; return 1;sendFailed: pqHandleSendFailure(conn); return 0;}/* * PQsendQueryPrepared * Like PQsendQuery, but execute a previously prepared statement, * using protocol 3.0 so we can pass parameters */intPQsendQueryPrepared(PGconn *conn, const char *stmtName, int nParams, const char *const * paramValues, const int *paramLengths, const int *paramFormats, int resultFormat){ if (!PQsendQueryStart(conn)) return 0; if (!stmtName) { printfPQExpBuffer(&conn->errorMessage, libpq_gettext("statement name is a null pointer\n")); return 0; } return PQsendQueryGuts(conn, NULL, /* no command to parse */ stmtName, nParams, NULL, /* no param types */ paramValues, paramLengths, paramFormats, resultFormat);}/* * Common startup code for PQsendQuery and sibling routines */static boolPQsendQueryStart(PGconn *conn){ if (!conn) return false; /* clear the error string */ resetPQExpBuffer(&conn->errorMessage); /* Don't try to send if we know there's no live connection. */ if (conn->status != CONNECTION_OK) { printfPQExpBuffer(&conn->errorMessage, libpq_gettext("no connection to the server\n")); return false; } /* Can't send while already busy, either. */ if (conn->asyncStatus != PGASYNC_IDLE) { printfPQExpBuffer(&conn->errorMessage, libpq_gettext("another command is already in progress\n")); return false; } /* initialize async result-accumulation state */ conn->result = NULL; conn->curTuple = NULL; /* ready to send command message */ return true;}/* * PQsendQueryGuts * Common code for protocol-3.0 query sending * PQsendQueryStart should be done already * * command may be NULL to indicate we use an already-prepared statement */static intPQsendQueryGuts(PGconn *conn, const char *command, const char *stmtName, int nParams, const Oid *paramTypes, const char *const * paramValues, const int *paramLengths, const int *paramFormats, int resultFormat){ int i; /* This isn't gonna work on a 2.0 server */ if (PG_PROTOCOL_MAJOR(conn->pversion) < 3) { printfPQExpBuffer(&conn->errorMessage, libpq_gettext("function requires at least protocol version 3.0\n")); return 0; } /* * We will send Parse (if needed), Bind, Describe Portal, Execute, Sync, * using specified statement name and the unnamed portal. */ if (command) { /* construct the Parse message */ if (pqPutMsgStart('P', false, conn) < 0 || pqPuts(stmtName, conn) < 0 || pqPuts(command, conn) < 0) goto sendFailed; if (nParams > 0 && paramTypes) { if (pqPutInt(nParams, 2, conn) < 0) goto sendFailed; for (i = 0; i < nParams; i++) { if (pqPutInt(paramTypes[i], 4, conn) < 0) goto sendFailed; } } else { if (pqPutInt(0, 2, conn) < 0) goto sendFailed; } if (pqPutMsgEnd(conn) < 0) goto sendFailed; } /* construct the Bind message */ if (pqPutMsgStart('B', false, conn) < 0 || pqPuts("", conn) < 0 || pqPuts(stmtName, conn) < 0) goto sendFailed; if (nParams > 0 && paramFormats) { if (pqPutInt(nParams, 2, conn) < 0) goto sendFailed; for (i = 0; i < nParams; i++) { if (pqPutInt(paramFormats[i], 2, conn) < 0) goto sendFailed; } } else { if (pqPutInt(0, 2, conn) < 0) goto sendFailed; } if (pqPutInt(nParams, 2, conn) < 0) goto sendFailed; for (i = 0; i < nParams; i++) { if (paramValues && paramValues[i]) { int nbytes; if (paramFormats && paramFormats[i] != 0) { /* binary parameter */ if (paramLengths) nbytes = paramLengths[i]; else { printfPQExpBuffer(&conn->errorMessage, libpq_gettext("length must be given for binary parameter\n")); goto sendFailed; } } else { /* text parameter, do not use paramLengths */ nbytes = strlen(paramValues[i]); } if (pqPutInt(nbytes, 4, conn) < 0 || pqPutnchar(paramValues[i], nbytes, conn) < 0) goto sendFailed; } else { /* take the param as NULL */ if (pqPutInt(-1, 4, conn) < 0) goto sendFailed; } } if (pqPutInt(1, 2, conn) < 0 || pqPutInt(resultFormat, 2, conn)) goto sendFailed; if (pqPutMsgEnd(conn) < 0) goto sendFailed; /* construct the Describe Portal message */ if (pqPutMsgStart('D', false, conn) < 0 || pqPutc('P', conn) < 0 || pqPuts("", conn) < 0 || pqPutMsgEnd(conn) < 0) goto sendFailed; /* construct the Execute message */ if (pqPutMsgStart('E', false, conn) < 0 || pqPuts("", conn) < 0 || pqPutInt(0, 4, conn) < 0 || pqPutMsgEnd(conn) < 0) goto sendFailed; /* construct the Sync message */ if (pqPutMsgStart('S', false, conn) < 0 || pqPutMsgEnd(conn) < 0) goto sendFailed; /* remember we are using extended query protocol */ conn->queryclass = PGQUERY_EXTENDED; /* * Give the data a push. In nonblock mode, don't complain if we're unable * to send it all; PQgetResult() will do any additional flushing needed. */ if (pqFlush(conn) < 0) goto sendFailed; /* OK, it's launched! */ conn->asyncStatus = PGASYNC_BUSY; return 1;sendFailed: pqHandleSendFailure(conn); return 0;}/* * pqHandleSendFailure: try to clean up after failure to send command. * * Primarily, what we want to accomplish here is to process an async * NOTICE message that the backend might have sent just before it died. * * NOTE: this routine should only be called in PGASYNC_IDLE state. */voidpqHandleSendFailure(PGconn *conn){ /* * Accept any available input data, ignoring errors. Note that if * pqReadData decides the backend has closed the channel, it will close * our side of the socket --- that's just what we want here.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -