* Attempt to read an Error or Notice response message. * This is possible in several places, so we break it out as a subroutine. * Entry: 'E' or 'N' message type and length have already been consumed. * Exit: returns 0 if successfully consumed message. * returns EOF if not enough data. */
| 1031 | * returns EOF if not enough data. |
| 1032 | */ |
| 1033 | int |
| 1034 | pqGetErrorNotice3(PGconn *conn, bool isError) |
| 1035 | { |
| 1036 | PGresult *res = NULL; |
| 1037 | bool have_position = false; |
| 1038 | PQExpBufferData workBuf; |
| 1039 | char id; |
| 1040 | |
| 1041 | /* If in pipeline mode, set error indicator for it */ |
| 1042 | if (isError && conn->pipelineStatus != PQ_PIPELINE_OFF) |
| 1043 | conn->pipelineStatus = PQ_PIPELINE_ABORTED; |
| 1044 | |
| 1045 | /* |
| 1046 | * If this is an error message, pre-emptively clear any incomplete query |
| 1047 | * result we may have. We'd just throw it away below anyway, and |
| 1048 | * releasing it before collecting the error might avoid out-of-memory. |
| 1049 | */ |
| 1050 | if (isError) |
| 1051 | pqClearAsyncResult(conn); |
| 1052 | |
| 1053 | /* |
| 1054 | * Since the fields might be pretty long, we create a temporary |
| 1055 | * PQExpBuffer rather than using conn->workBuffer. workBuffer is intended |
| 1056 | * for stuff that is expected to be short. We shouldn't use |
| 1057 | * conn->errorMessage either, since this might be only a notice. |
| 1058 | */ |
| 1059 | initPQExpBuffer(&workBuf); |
| 1060 | |
| 1061 | /* |
| 1062 | * Make a PGresult to hold the accumulated fields. We temporarily lie |
| 1063 | * about the result status, so that PQmakeEmptyPGresult doesn't uselessly |
| 1064 | * copy conn->errorMessage. |
| 1065 | * |
| 1066 | * NB: This allocation can fail, if you run out of memory. The rest of the |
| 1067 | * function handles that gracefully, and we still try to set the error |
| 1068 | * message as the connection's error message. |
| 1069 | */ |
| 1070 | res = PQmakeEmptyPGresult(conn, PGRES_EMPTY_QUERY); |
| 1071 | if (res) |
| 1072 | res->resultStatus = isError ? PGRES_FATAL_ERROR : PGRES_NONFATAL_ERROR; |
| 1073 | |
| 1074 | /* |
| 1075 | * Read the fields and save into res. |
| 1076 | * |
| 1077 | * While at it, save the SQLSTATE in conn->last_sqlstate, and note whether |
| 1078 | * we saw a PG_DIAG_STATEMENT_POSITION field. |
| 1079 | */ |
| 1080 | for (;;) |
| 1081 | { |
| 1082 | if (pqGetc(&id, conn)) |
| 1083 | goto fail; |
| 1084 | if (id == '\0') |
| 1085 | break; /* terminator found */ |
| 1086 | if (pqGets(&workBuf, conn)) |
| 1087 | goto fail; |
| 1088 | pqSaveMessageField(res, id, workBuf.data); |
| 1089 | if (id == PG_DIAG_SQLSTATE) |
| 1090 | strlcpy(conn->last_sqlstate, workBuf.data, |
no test coverage detected