* pqRowProcessor * Add the received row to the current async result (conn->result). * Returns 1 if OK, 0 if error occurred. * * On error, *errmsgp can be set to an error string to be returned. * If it is left NULL, the error is presumed to be "out of memory". * * In single-row mode, we create a new result holding just the current row, * stashing the previous result in conn->next_result
| 1139 | * (column descriptions) to be carried forward to each result row. |
| 1140 | */ |
| 1141 | int |
| 1142 | pqRowProcessor(PGconn *conn, const char **errmsgp) |
| 1143 | { |
| 1144 | PGresult *res = conn->result; |
| 1145 | int nfields = res->numAttributes; |
| 1146 | const PGdataValue *columns = conn->rowBuf; |
| 1147 | PGresAttValue *tup; |
| 1148 | int i; |
| 1149 | |
| 1150 | /* |
| 1151 | * In single-row mode, make a new PGresult that will hold just this one |
| 1152 | * row; the original conn->result is left unchanged so that it can be used |
| 1153 | * again as the template for future rows. |
| 1154 | */ |
| 1155 | if (conn->singleRowMode) |
| 1156 | { |
| 1157 | /* Copy everything that should be in the result at this point */ |
| 1158 | res = PQcopyResult(res, |
| 1159 | PG_COPYRES_ATTRS | PG_COPYRES_EVENTS | |
| 1160 | PG_COPYRES_NOTICEHOOKS); |
| 1161 | if (!res) |
| 1162 | return 0; |
| 1163 | } |
| 1164 | |
| 1165 | /* |
| 1166 | * Basically we just allocate space in the PGresult for each field and |
| 1167 | * copy the data over. |
| 1168 | * |
| 1169 | * Note: on malloc failure, we return 0 leaving *errmsgp still NULL, which |
| 1170 | * caller will take to mean "out of memory". This is preferable to trying |
| 1171 | * to set up such a message here, because evidently there's not enough |
| 1172 | * memory for gettext() to do anything. |
| 1173 | */ |
| 1174 | tup = (PGresAttValue *) |
| 1175 | pqResultAlloc(res, nfields * sizeof(PGresAttValue), true); |
| 1176 | if (tup == NULL) |
| 1177 | goto fail; |
| 1178 | |
| 1179 | for (i = 0; i < nfields; i++) |
| 1180 | { |
| 1181 | int clen = columns[i].len; |
| 1182 | |
| 1183 | if (clen < 0) |
| 1184 | { |
| 1185 | /* null field */ |
| 1186 | tup[i].len = NULL_LEN; |
| 1187 | tup[i].value = res->null_field; |
| 1188 | } |
| 1189 | else |
| 1190 | { |
| 1191 | bool isbinary = (res->attDescs[i].format != 0); |
| 1192 | char *val; |
| 1193 | |
| 1194 | val = (char *) pqResultAlloc(res, clen + 1, isbinary); |
| 1195 | if (val == NULL) |
| 1196 | goto fail; |
| 1197 | |
| 1198 | /* copy and zero-terminate the data (even if it's binary) */ |
no test coverage detected