static awk_value_t * process_result(PGconn *conn, PGresult *res, awk_value_t *resp) { ExecStatusType rc; switch (rc = PQresultStatus(res)) { case PGRES_TUPLES_OK: { static unsigned long hnum = 0; char handle[64]; size_t sl; snprintf(handle, sizeof(handle), "TUPLES %d pgres%lu", PQntuples(res), hnum++); sl = strlen(handle); strhash_get(results, handle, sl, 1)->data = res; make_string_malloc(handle, sl, resp); } break; case PGRES_COMMAND_OK: case PGRES_EMPTY_QUERY: { char result[32]; int cnt; if (sscanf(PQcmdTuples(res), "%d", &cnt) != 1) cnt = 0; snprintf(result, sizeof(result), "OK %d", cnt); PQclear(res); make_string_malloc(result, strlen(result), resp); } break; case PGRES_COPY_IN: { char buf[100]; snprintf(buf, sizeof(buf), "COPY_IN %d %s", PQnfields(res), (PQbinaryTuples(res) ? "BINARY" : "TEXT")); make_string_malloc(buf, strlen(buf), resp); PQclear(res); } break; case PGRES_COPY_OUT: { char buf[100]; snprintf(buf, sizeof(buf), "COPY_OUT %d %s", PQnfields(res), (PQbinaryTuples(res) ? "BINARY" : "TEXT")); make_string_malloc(buf, strlen(buf), resp); PQclear(res); } break; default: /* error */ set_error(conn, rc, resp); set_ERRNO(PQresultErrorMessage(res)); PQclear(res); } return resp; }
int CPgsqlResultHandler::extractValueAsInt(const int columnIndex) { char * valuePoint = PQgetvalue(m_res, m_currentResultIndex, columnIndex); int result = 0; if (PQbinaryTuples(m_res) == 1) { int nbBytes = PQfsize(m_res, columnIndex); switch (nbBytes) { case 8: result = Poco::ByteOrder::fromNetwork(*((Poco::Int64 *)valuePoint)); break; default: case 4: result = Poco::ByteOrder::fromNetwork(*((Poco::Int32 *)valuePoint)); break; case 2: result = Poco::ByteOrder::fromNetwork(*((Poco::Int16 *)valuePoint)); break; } } else { result = atoi(valuePoint); } return result; }
/* * ProcessCopyResult: if command was a COPY FROM STDIN/TO STDOUT, handle it * * Note: Utility function for use by SendQuery() only. * * Returns true if the query executed successfully, false otherwise. */ static bool ProcessCopyResult(PGresult *results) { bool success = false; if (!results) return false; switch (PQresultStatus(results)) { case PGRES_TUPLES_OK: case PGRES_COMMAND_OK: case PGRES_EMPTY_QUERY: /* nothing to do here */ success = true; break; case PGRES_COPY_OUT: SetCancelConn(); success = handleCopyOut(pset.db, pset.queryFout); ResetCancelConn(); break; case PGRES_COPY_IN: SetCancelConn(); success = handleCopyIn(pset.db, pset.cur_cmd_source, PQbinaryTuples(results)); ResetCancelConn(); break; default: break; } /* may need this to recover from conn loss during COPY */ if (!CheckConnection()) return false; return success; }
/* * Execute a \copy command (frontend copy). We have to open a file, then * submit a COPY query to the backend and either feed it data from the * file or route its response into the file. */ bool do_copy(const char *args) { struct pqbuf query; FILE* copystream; struct copy_options *options; PGresult* result; bool success; struct stat st; /* parse options */ options = parse_slash_copy(args); if (!options) return false; /* prepare to read or write the target file */ if (options->file) canonicalize_path(options->file); if (options->from) { if (options->file) copystream = fopen(options->file, PG_BINARY_R); else if (!options->psql_inout) copystream = pset.cur_cmd_source; else copystream = stdin; } else { if (options->file) copystream = fopen(options->file, PG_BINARY_W); else if (!options->psql_inout) copystream = pset.queryFout; else copystream = stdout; } if (!copystream) { psql_error("%s: %s\n", options->file, strerror(errno)); free_copy_options(options); return false; } /* make sure the specified file is not a directory */ fstat(fileno(copystream), &st); if (S_ISDIR(st.st_mode)) { fclose(copystream); psql_error("%s: cannot copy from/to a directory\n", options->file); free_copy_options(options); return false; } /* build the command we will send to the backend */ init_pqbuf(&query); print_pqbuf(&query, "COPY "); append_pqbuf_str(&query, options->before_tofrom); if (options->from) append_pqbuf(&query, " FROM STDIN "); else append_pqbuf(&query, " TO STDOUT "); if (options->after_tofrom) append_pqbuf_str(&query, options->after_tofrom); result = PSQLexec(query.data, true); term_pqbuf(&query); switch (PQresultStatus(result)) { case PGRES_COPY_OUT: SetCancelConn(); success = handleCopyOut(pset.db, copystream); ResetCancelConn(); break; case PGRES_COPY_IN: SetCancelConn(); success = handleCopyIn(pset.db, copystream, PQbinaryTuples(result)); ResetCancelConn(); break; case PGRES_NONFATAL_ERROR: case PGRES_FATAL_ERROR: case PGRES_BAD_RESPONSE: success = false; psql_error("\\copy: %s", PQerrorMessage(pset.db)); break; default: success = false; psql_error("\\copy: unexpected response (%d)\n", PQresultStatus(result)); break; } PQclear(result); /* * Make sure we have pumped libpq dry of results; else it may still be in * ASYNC_BUSY state, leading to false readings in, eg, get_prompt(). */ while ((result = PQgetResult(pset.db)) != NULL) { success = false; psql_error("\\copy: unexpected response (%d)\n", PQresultStatus(result)); /* if still in COPY IN state, try to get out of it */ if (PQresultStatus(result) == PGRES_COPY_IN) PQputCopyEnd(pset.db, _("trying to exit copy mode")); PQclear(result); } if (options->file != NULL) { if (fclose(copystream) != 0) { psql_error("%s: %s\n", options->file, strerror(errno)); success = false; } } free_copy_options(options); return success; }
/* * ProcessResult: utility function for use by SendQuery() only * * When our command string contained a COPY FROM STDIN or COPY TO STDOUT, * PQexec() has stopped at the PGresult associated with the first such * command. In that event, we'll marshal data for the COPY and then cycle * through any subsequent PGresult objects. * * When the command string contained no such COPY command, this function * degenerates to an AcceptResult() call. * * Changes its argument to point to the last PGresult of the command string, * or NULL if that result was for a COPY TO STDOUT. (Returning NULL prevents * the command status from being printed, which we want in that case so that * the status line doesn't get taken as part of the COPY data.) * * Returns true on complete success, false otherwise. Possible failure modes * include purely client-side problems; check the transaction status for the * server-side opinion. */ static bool ProcessResult(PGresult **results) { bool success = true; bool first_cycle = true; for (;;) { ExecStatusType result_status; bool is_copy; PGresult *next_result; if (!AcceptResult(*results)) { /* * Failure at this point is always a server-side failure or a * failure to submit the command string. Either way, we're * finished with this command string. */ success = false; break; } result_status = PQresultStatus(*results); switch (result_status) { case PGRES_EMPTY_QUERY: case PGRES_COMMAND_OK: case PGRES_TUPLES_OK: is_copy = false; break; case PGRES_COPY_OUT: case PGRES_COPY_IN: is_copy = true; break; default: /* AcceptResult() should have caught anything else. */ is_copy = false; psql_error("unexpected PQresultStatus: %d\n", result_status); break; } if (is_copy) { /* * Marshal the COPY data. Either subroutine will get the * connection out of its COPY state, then call PQresultStatus() * once and report any error. * * If pset.copyStream is set, use that as data source/sink, * otherwise use queryFout or cur_cmd_source as appropriate. */ FILE *copystream = pset.copyStream; PGresult *copy_result; SetCancelConn(); if (result_status == PGRES_COPY_OUT) { if (!copystream) copystream = pset.queryFout; success = handleCopyOut(pset.db, copystream, ©_result) && success; /* * Suppress status printing if the report would go to the same * place as the COPY data just went. Note this doesn't * prevent error reporting, since handleCopyOut did that. */ if (copystream == pset.queryFout) { PQclear(copy_result); copy_result = NULL; } } else { if (!copystream) copystream = pset.cur_cmd_source; success = handleCopyIn(pset.db, copystream, PQbinaryTuples(*results), ©_result) && success; } ResetCancelConn(); /* * Replace the PGRES_COPY_OUT/IN result with COPY command's exit * status, or with NULL if we want to suppress printing anything. */ PQclear(*results); *results = copy_result; } else if (first_cycle) { /* fast path: no COPY commands; PQexec visited all results */ break; } /* * Check PQgetResult() again. In the typical case of a single-command * string, it will return NULL. Otherwise, we'll have other results * to process that may include other COPYs. We keep the last result. */ next_result = PQgetResult(pset.db); if (!next_result) break; PQclear(*results); *results = next_result; first_cycle = false; } /* may need this to recover from conn loss during COPY */ if (!first_cycle && !CheckConnection()) return false; return success; }
/* * ProcessResult: utility function for use by SendQuery() only * * When our command string contained a COPY FROM STDIN or COPY TO STDOUT, * PQexec() has stopped at the PGresult associated with the first such * command. In that event, we'll marshal data for the COPY and then cycle * through any subsequent PGresult objects. * * When the command string contained no affected COPY command, this function * degenerates to an AcceptResult() call. * * Changes its argument to point to the last PGresult of the command string, * or NULL if that result was for a COPY FROM STDIN or COPY TO STDOUT. * * Returns true on complete success, false otherwise. Possible failure modes * include purely client-side problems; check the transaction status for the * server-side opinion. */ static bool ProcessResult(PGresult **results) { PGresult *next_result; bool success = true; bool first_cycle = true; do { ExecStatusType result_status; bool is_copy; if (!AcceptResult(*results)) { /* * Failure at this point is always a server-side failure or a * failure to submit the command string. Either way, we're * finished with this command string. */ success = false; break; } result_status = PQresultStatus(*results); switch (result_status) { case PGRES_EMPTY_QUERY: case PGRES_COMMAND_OK: case PGRES_TUPLES_OK: is_copy = false; break; case PGRES_COPY_OUT: case PGRES_COPY_IN: is_copy = true; break; default: /* AcceptResult() should have caught anything else. */ is_copy = false; psql_error("unexpected PQresultStatus: %d\n", result_status); break; } if (is_copy) { /* * Marshal the COPY data. Either subroutine will get the * connection out of its COPY state, then call PQresultStatus() * once and report any error. */ SetCancelConn(); if (result_status == PGRES_COPY_OUT) success = handleCopyOut(pset.db, pset.queryFout) && success; else success = handleCopyIn(pset.db, pset.cur_cmd_source, PQbinaryTuples(*results)) && success; ResetCancelConn(); /* * Call PQgetResult() once more. In the typical case of a * single-command string, it will return NULL. Otherwise, we'll * have other results to process that may include other COPYs. */ PQclear(*results); *results = next_result = PQgetResult(pset.db); } else if (first_cycle) /* fast path: no COPY commands; PQexec visited all results */ break; else if ((next_result = PQgetResult(pset.db))) { /* non-COPY command(s) after a COPY: keep the last one */ PQclear(*results); *results = next_result; } first_cycle = false; } while (next_result); /* may need this to recover from conn loss during COPY */ if (!first_cycle && !CheckConnection()) return false; return success; }
/* * Execute a \copy command (frontend copy). We have to open a file, then * submit a COPY query to the backend and either feed it data from the * file or route its response into the file. */ bool do_copy(const char *args) { PQExpBufferData query; FILE *copystream; struct copy_options *options; PGresult *result; bool success; struct stat st; /* parse options */ options = parse_slash_copy(args); if (!options) return false; initPQExpBuffer(&query); printfPQExpBuffer(&query, "COPY "); appendPQExpBuffer(&query, "%s ", options->table); if (options->column_list) appendPQExpBuffer(&query, "%s ", options->column_list); if (options->from) appendPQExpBuffer(&query, "FROM STDIN"); else appendPQExpBuffer(&query, "TO STDOUT"); if (options->binary) appendPQExpBuffer(&query, " BINARY "); if (options->oids) appendPQExpBuffer(&query, " OIDS "); if (options->delim) emit_copy_option(&query, " DELIMITER ", options->delim); if (options->null) emit_copy_option(&query, " NULL AS ", options->null); if (options->csv_mode) appendPQExpBuffer(&query, " CSV"); if (options->header) appendPQExpBuffer(&query, " HEADER"); if (options->quote) emit_copy_option(&query, " QUOTE AS ", options->quote); if (options->escape) emit_copy_option(&query, " ESCAPE AS ", options->escape); if (options->force_quote_list) appendPQExpBuffer(&query, " FORCE QUOTE %s", options->force_quote_list); if (options->force_notnull_list) appendPQExpBuffer(&query, " FORCE NOT NULL %s", options->force_notnull_list); if (options->file) canonicalize_path(options->file); if (options->from) { if (options->file) copystream = fopen(options->file, PG_BINARY_R); else if (!options->psql_inout) copystream = pset.cur_cmd_source; else copystream = stdin; } else { if (options->file) copystream = fopen(options->file, options->binary ? PG_BINARY_W : "w"); else if (!options->psql_inout) copystream = pset.queryFout; else copystream = stdout; } if (!copystream) { psql_error("%s: %s\n", options->file, strerror(errno)); free_copy_options(options); return false; } /* make sure the specified file is not a directory */ fstat(fileno(copystream), &st); if (S_ISDIR(st.st_mode)) { fclose(copystream); psql_error("%s: cannot copy from/to a directory\n", options->file); free_copy_options(options); return false; } result = PSQLexec(query.data, true); termPQExpBuffer(&query); switch (PQresultStatus(result)) { case PGRES_COPY_OUT: SetCancelConn(); success = handleCopyOut(pset.db, copystream); ResetCancelConn(); break; case PGRES_COPY_IN: SetCancelConn(); success = handleCopyIn(pset.db, copystream, PQbinaryTuples(result)); ResetCancelConn(); break; case PGRES_NONFATAL_ERROR: case PGRES_FATAL_ERROR: case PGRES_BAD_RESPONSE: success = false; psql_error("\\copy: %s", PQerrorMessage(pset.db)); break; default: success = false; psql_error("\\copy: unexpected response (%d)\n", PQresultStatus(result)); break; } PQclear(result); /* * Make sure we have pumped libpq dry of results; else it may still be * in ASYNC_BUSY state, leading to false readings in, eg, get_prompt(). */ while ((result = PQgetResult(pset.db)) != NULL) { success = false; psql_error("\\copy: unexpected response (%d)\n", PQresultStatus(result)); /* if still in COPY IN state, try to get out of it */ if (PQresultStatus(result) == PGRES_COPY_IN) PQputCopyEnd(pset.db, _("trying to exit copy mode")); PQclear(result); } if (options->file != NULL) { if (fclose(copystream) != 0) { psql_error("%s: %s\n", options->file, strerror(errno)); success = false; } } free_copy_options(options); return success; }
int pg_createrowset(ClipMachine* mp,SQLROWSET* rs,ClipVar* ap,ClipVar* idname,const char* gen_idSQL){ PG_ROWSET* rowset = (PG_ROWSET*)rs; PG_STMT* stmt = rowset->stmt; PG_CONN* conn = rowset->conn; int i,mod; pg_bindpars(stmt,ap); if(!stmt->sql){ _clip_trap_err(mp,0,0,0,subsys,ER_NOSQL,er_nosql); return 1; } stmt->res = PQexec(conn->conn,stmt->sql); if(!stmt->res){ _clip_trap_err(mp,0,0,0,subsys,ER_BADSTATEMENT, PQresultErrorMessage(stmt->res)); return 1; } if(PQresultStatus(stmt->res)!=PGRES_TUPLES_OK){ _clip_trap_err(mp,0,0,0,subsys,ER_BADSELECT, PQresultErrorMessage(stmt->res)); return 1; } rowset->rowset_item = _clip_store_c_item(mp,rowset,_C_ITEM_TYPE_SQL,destroy_pg_rowset); rowset->binary = PQbinaryTuples(stmt->res); rowset->nfields = PQnfields(stmt->res); rowset->fields = calloc(1,rowset->nfields*sizeof(SQLFIELD)); rowset->id = -1; for(i=0;i<rowset->nfields;i++){ strncpy(rowset->fields[i].name,PQfname(stmt->res,i), MAXFIELDNAME); rowset->fields[i].name[MAXFIELDNAME] = 0; rowset->fields[i].type = PQftype(stmt->res,i); rowset->fields[i].ctype[0] = _pg_ctype(rowset->fields[i].type); rowset->fields[i].dec = 0; mod = PQfmod(stmt->res,i); switch(rowset->fields[i].type){ case PGT_BPCHAR: case PGT_CHAR: case PGT_VARCHAR: rowset->fields[i].len = mod-4; break; case PGT_TEXT: rowset->fields[i].len = 10; break; case PGT_NUMERIC: rowset->fields[i].len = (mod >> 16); rowset->fields[i].dec = (mod & 0xffff)-4; break; case PGT_DATE: rowset->fields[i].len = 8; break; default: rowset->fields[i].len = PQfsize(stmt->res,i); break; } rowset->fields[i].ops = 0; if(idname && idname->t.type == CHARACTER_t && idname->s.str.buf){ if(!strcasecmp(rowset->fields[i].name,idname->s.str.buf)){ rowset->id = i; } } else if(rowset->fields[i].type == PGT_OID){ rowset->id = i; } } rowset->lastrec = PQntuples(stmt->res); rowset->data = calloc(rowset->lastrec,sizeof(void*)); return 0; }