bool executeAsyncQuery(std::string const& sql, int type = 0) { int result = 0; if (type == 1) { result = PQsendQueryParams(conn_,sql.c_str(), 0, 0, 0, 0, 0, 1); } else { result = PQsendQuery(conn_, sql.c_str()); } if (result != 1) { std::string err_msg = "Postgis Plugin: "; err_msg += status(); err_msg += "in executeAsyncQuery Full sql was: '"; err_msg += sql; err_msg += "'\n"; clearAsyncResult(PQgetResult(conn_)); close(); throw mapnik::datasource_exception(err_msg); } pending_ = true; return result; }
bool pgut_send(PGconn* conn, const char *query, int nParams, const char **params) { int res; CHECK_FOR_INTERRUPTS(); /* write query to elog if debug */ if (pgut_echo) echo_query(query, nParams, params); if (conn == NULL) { ereport(ERROR, (errcode(E_PG_COMMAND), errmsg("not connected"))); return false; } if (nParams == 0) res = PQsendQuery(conn, query); else res = PQsendQueryParams(conn, query, nParams, NULL, params, NULL, NULL, 0); if (res != 1) { ereport(ERROR, (errcode(E_PG_COMMAND), errmsg("query failed: %s", PQerrorMessage(conn)), errdetail("query was: %s", query))); return false; } return true; }
ngx_int_t ngx_postgres_upstream_send_query(ngx_http_request_t *r, ngx_connection_t *pgxc, ngx_postgres_upstream_peer_data_t *pgdt) { ngx_postgres_loc_conf_t *pglcf; ngx_int_t pgrc; u_char *query; dd("entering"); pglcf = ngx_http_get_module_loc_conf(r, ngx_postgres_module); query = ngx_pnalloc(r->pool, pgdt->query.len + 1); if (query == NULL) { dd("returning NGX_ERROR"); return NGX_ERROR; } (void) ngx_cpystrn(query, pgdt->query.data, pgdt->query.len + 1); dd("sending query: %s", query); if (pglcf->output_binary) { pgrc = PQsendQueryParams(pgdt->pgconn, (const char *) query, 0, NULL, NULL, NULL, NULL, /* binary */ 1); } else { pgrc = PQsendQuery(pgdt->pgconn, (const char *) query); } if (pgrc == 0) { dd("sending query failed"); ngx_log_error(NGX_LOG_ERR, pgxc->log, 0, "postgres: sending query failed: %s", PQerrorMessage(pgdt->pgconn)); dd("returning NGX_ERROR"); return NGX_ERROR; } /* set result timeout */ ngx_add_timer(pgxc->read, r->upstream->conf->read_timeout); dd("query sent successfully"); pgxc->log->action = "waiting for result from PostgreSQL database"; pgdt->state = state_db_get_result; dd("returning NGX_DONE"); return NGX_DONE; }
static int do_select(const char* s, our_data_t* data) { PGconn* conn = data->conn; /* if there's an error return it now */ if (PQsendQueryParams(conn, s, 0, NULL, NULL, NULL, NULL, 1) == 0) { ei_x_buff x; ei_x_new_with_version(&x); encode_error(&x, conn); driver_output(data->port, x.buff, x.index); ei_x_free(&x); } /* else wait for ready_output to get results */ return 0; }
CAMLprim value PQsendQueryParams_stub( value v_conn, value v_query, value v_params, value v_binary_params) { PGconn *conn = get_conn(v_conn); const char *query = String_val(v_query); size_t nparams = Wosize_val(v_params); const char * const *params = copy_params_shallow(v_params, nparams); int *lengths, *formats, res; copy_binary_params(v_params, v_binary_params, nparams, &formats, &lengths); res = (nparams == 0) ? PQsendQuery(conn, query) : PQsendQueryParams( conn, query, nparams, NULL, params, lengths, formats, 0); free_binary_params(formats, lengths); free_params_shallow(params, nparams); return Val_int(res); }
bool pgut_send(PGconn* conn, const char *query, int nParams, const char **params) { int res; int i; if (interrupted && !in_cleanup) ereport(FATAL, (errcode(ERROR_INTERRUPTED), errmsg("interrupted"))); /* write query to elog with DEBUG level */ if (strchr(query, '\n')) elog(DEBUG, "(query)\n%s", query); else elog(DEBUG, "(query) %s", query); for (i = 0; i < nParams; i++) elog(DEBUG, "\t(param:%d) = %s", i, params[i] ? params[i] : "(null)"); if (conn == NULL) { ereport(ERROR, (errcode(ERROR_PG_CONNECT), errmsg("not connected"))); return false; } if (nParams == 0) res = PQsendQuery(conn, query); else res = PQsendQueryParams(conn, query, nParams, NULL, params, NULL, NULL, 0); if (res != 1) { ereport(ERROR, (errcode(ERROR_PG_COMMAND), errmsg("query failed: %squery was: %s", PQerrorMessage(conn), query))); return false; } return true; }
void pg_statement_send( VALUE conn, VALUE cmd, VALUE par) { struct pgconn_data *c; int res; Data_Get_Struct( conn, struct pgconn_data, c); pg_check_conninvalid( c); if (NIL_P( par)) res = PQsendQuery( c->conn, pgconn_destring( c, cmd, NULL)); else { char **v; int len; v = params_to_strings( conn, par, &len); res = PQsendQueryParams( c->conn, pgconn_destring( c, cmd, NULL), len, NULL, (const char **) v, NULL, NULL, 0); free_strings( v, len); } if (res <= 0) pg_raise_connexec( c); }
/* Initiates the non-blocking capture of a consistent snapshot of the database, * using the exported snapshot context->repl.snapshot_name. */ int snapshot_start(client_context_t context) { if (!context->repl.snapshot_name || context->repl.snapshot_name[0] == '\0') { client_error(context, "snapshot_name must be set in client context"); return EINVAL; } int err = 0; check(err, exec_sql(context, "BEGIN")); check(err, exec_sql(context, "SET TRANSACTION ISOLATION LEVEL REPEATABLE READ")); PQExpBuffer query = createPQExpBuffer(); appendPQExpBuffer(query, "SET TRANSACTION SNAPSHOT '%s'", context->repl.snapshot_name); check(err, exec_sql(context, query->data)); destroyPQExpBuffer(query); Oid argtypes[] = { 25, 16 }; // 25 == TEXTOID, 16 == BOOLOID const char *args[] = { "%", context->allow_unkeyed ? "t" : "f" }; if (!PQsendQueryParams(context->sql_conn, "SELECT bottledwater_export(table_pattern := $1, allow_unkeyed := $2)", 2, argtypes, args, NULL, NULL, 1)) { // The final 1 requests results in binary format client_error(context, "Could not dispatch snapshot fetch: %s", PQerrorMessage(context->sql_conn)); return EIO; } if (!PQsetSingleRowMode(context->sql_conn)) { client_error(context, "Could not activate single-row mode"); return EIO; } // Invoke the begin-transaction callback with xid==0 to indicate start of snapshot begin_txn_cb begin_txn = context->repl.frame_reader->on_begin_txn; void *cb_context = context->repl.frame_reader->cb_context; if (begin_txn) { check(err, begin_txn(cb_context, context->repl.start_lsn, 0)); } return 0; }
static awk_value_t * do_pg_sendqueryparams(int nargs, awk_value_t *result) { PGconn *conn; awk_value_t command; int nParams; const char **paramValues; int res; if (do_lint && (nargs > 4)) lintwarn(ext_id, _("pg_sendqueryparams: called with too many arguments")); if (!(conn = find_handle(conns, 0))) { set_ERRNO(_("pg_sendqueryparams called with unknown connection handle")); RET_NUM(0); } if ((nParams = get_params(nargs, 2, ¶mValues)) < 0) { set_ERRNO(_("pg_sendqueryparams called with negative nParams")); RET_NUM(0); } if (!get_argument(1, AWK_STRING, &command)) { set_ERRNO(_("pg_sendqueryparams 2nd argument should be a string")); RET_NUM(0); } res = PQsendQueryParams(conn, command.str_value.str, nParams, NULL, paramValues, NULL, NULL, 0); if (paramValues) free(paramValues); if (!res) /* connection is probably bad */ set_ERRNO(PQerrorMessage(conn)); RET_NUM(res); }
static int BufferedWriterSendQuery(BufferedWriter *self, PGconn *conn, char *queueName, char *logfile, bool verbose) { const char *params[8]; char max_dup_errors[MAXINT8LEN + 1]; if (self->base.max_dup_errors < -1) self->base.max_dup_errors = DEFAULT_MAX_DUP_ERRORS; snprintf(max_dup_errors, MAXINT8LEN, INT64_FORMAT, self->base.max_dup_errors); /* async query send */ params[0] = queueName; params[1] = self->base.output; params[2] = ON_DUPLICATE_NAMES[self->base.on_duplicate]; params[3] = max_dup_errors; params[4] = self->base.dup_badfile; params[5] = logfile; params[6] = verbose ? "true" : "no"; params[7] = (self->base.truncate ? "true" : "no"); return PQsendQueryParams(conn, "SELECT * FROM pg_bulkload(ARRAY[" "'TYPE=TUPLE'," "'INPUT=' || $1," "'WRITER=BUFFERED'," "'OUTPUT=' || $2," "'ON_DUPLICATE_KEEP=' || $3," "'DUPLICATE_ERRORS=' || $4," "'DUPLICATE_BADFILE=' || $5," "'LOGFILE=' || $6," "'VERBOSE=' || $7," "'TRUNCATE=' || $8])", 8, NULL, params, NULL, NULL, 0); }
static void plx_send_query(PlxFn *plx_fn, PlxConn *plx_conn, char *sql, char **args, int nargs, int *arg_lens, int *arg_fmts) { if (!PQsendQueryParams(plx_conn->pq_conn, (const char *) sql, nargs, NULL, (const char * const*) args, arg_lens, arg_fmts, plx_fn->is_binary)) { delete_plx_conn(plx_conn); plx_error(plx_fn, "failed to send query %s %s", sql, PQerrorMessage(plx_conn->pq_conn)); } wait_for_flush(plx_fn, plx_conn->pq_conn); }
Result PreparedStatement::execute() { PGconn *conn = m_conn.lock().get(); boost::shared_ptr<PGresult> result, next; int nParams = (int)m_params.size(); Oid *paramTypes = NULL; int *paramLengths = NULL, *paramFormats = NULL; const char **params = NULL; if (nParams) { if (m_name.empty()) paramTypes = &m_paramTypes[0]; params = &m_params[0]; paramLengths = &m_paramLengths[0]; paramFormats = &m_paramFormats[0]; } const char *api = NULL; #ifndef WINDOWS SchedulerSwitcher switcher(m_scheduler); #endif if (m_name.empty()) { #ifndef WINDOWS if (m_scheduler) { api = "PQsendQueryParams"; if (!PQsendQueryParams(conn, m_command.c_str(), nParams, paramTypes, params, paramLengths, paramFormats, m_resultFormat)) throwException(conn); flush(conn, m_scheduler); next.reset(nextResult(conn, m_scheduler), &PQclear); while (next) { result = next; next.reset(nextResult(conn, m_scheduler), &PQclear); if (next) { ExecStatusType status = PQresultStatus(next.get()); MORDOR_LOG_VERBOSE(g_log) << conn << "PQresultStatus(" << next.get() << "): " << PQresStatus(status); switch (status) { case PGRES_COMMAND_OK: case PGRES_TUPLES_OK: break; default: throwException(next.get()); MORDOR_NOTREACHED(); } } } } else #endif { api = "PQexecParams"; result.reset(PQexecParams(conn, m_command.c_str(), nParams, paramTypes, params, paramLengths, paramFormats, m_resultFormat), &PQclear); } } else { #ifndef WINDOWS if (m_scheduler) { api = "PQsendQueryPrepared"; if (!PQsendQueryPrepared(conn, m_name.c_str(), nParams, params, paramLengths, paramFormats, 1)) throwException(conn); flush(conn, m_scheduler); next.reset(nextResult(conn, m_scheduler), &PQclear); while (next) { result = next; next.reset(nextResult(conn, m_scheduler), &PQclear); if (next) { ExecStatusType status = PQresultStatus(next.get()); MORDOR_LOG_VERBOSE(g_log) << conn << "PQresultStatus(" << next.get() << "): " << PQresStatus(status); switch (status) { case PGRES_COMMAND_OK: case PGRES_TUPLES_OK: break; default: throwException(next.get()); MORDOR_NOTREACHED(); } } } } else #endif { api = "PQexecPrepared"; result.reset(PQexecPrepared(conn, m_name.c_str(), nParams, params, paramLengths, paramFormats, m_resultFormat), &PQclear); } } if (!result) throwException(conn); ExecStatusType status = PQresultStatus(result.get()); MORDOR_ASSERT(api); MORDOR_LOG_VERBOSE(g_log) << conn << " " << api << "(\"" << m_command << m_name << "\", " << nParams << "), PQresultStatus(" << result.get() << "): " << PQresStatus(status); switch (status) { case PGRES_COMMAND_OK: case PGRES_TUPLES_OK: return Result(result); default: throwException(result.get()); MORDOR_NOTREACHED(); } }
static int pgasp_handler (request_rec * r) { char cursor_string[256]; pgasp_config* config = (pgasp_config*) ap_get_module_config(r->server->module_config, &pgasp_module ) ; pgasp_dir_config* dir_config = (pgasp_dir_config*) ap_get_module_config(r->per_dir_config, &pgasp_module ) ; apr_table_t * GET = NULL, *GETargs = NULL; apr_array_header_t * POST; PGconn * pgc; PGresult * pgr; int i, j, allowed_to_serve, filename_length = 0; int field_count, tuple_count; char * requested_file; char *basename; params_t params; /* PQexecParams doesn't seem to like zero-length strings, so we feed it a dummy */ const char * dummy_get = "nothing"; const char * dummy_user = "******"; const char * cursor_values[2] = { r -> args ? apr_pstrdup(r->pool, r -> args) : dummy_get, r->user ? r->user : dummy_user }; int cursor_value_lengths[2] = { strlen(cursor_values[0]), strlen(cursor_values[1]) }; int cursor_value_formats[2] = { 0, 0 }; if (!r -> handler || strcmp (r -> handler, "pgasp-handler") ) return DECLINED; if (!r -> method || (strcmp (r -> method, "GET") && strcmp (r -> method, "POST")) ) return DECLINED; if (config->is_enabled != true) return OK; /* pretending we have responded, may return DECLINED in the future */ requested_file = apr_pstrdup (r -> pool, r -> path_info /*filename*/); i = strlen(requested_file) - 1; while (i > 0) { if (requested_file[i] == '.') filename_length = i; if (requested_file[i] == '/') break; i--; } if (i >= 0) { requested_file += i+1; /* now pointing to foo.pgasp instead of /var/www/.../foo.pgasp */ if (filename_length > i) filename_length -= i+1; } allowed_to_serve = false; for (i = 0; i < config->allowed_count; i++) { if (!strcmp(config->allowed[i], requested_file)) { allowed_to_serve = true; break; } } if (config->allowed_count == 0) allowed_to_serve = true; if (!allowed_to_serve) { ap_set_content_type(r, "text/plain"); ap_rprintf(r, "Hello there\nThis is PGASP\nEnabled: %s\n", config->is_enabled ? "On" : "Off"); ap_rprintf(r, "Requested: %s\n", requested_file); ap_rprintf(r, "Allowed: %s\n", allowed_to_serve ? "Yes" : "No"); return OK; /* pretending we have served the file, may return HTTP_FORDIDDEN in the future */ } if (filename_length == 0) { basename = requested_file; } else { basename = apr_pstrndup(r->pool, requested_file, filename_length); } ap_args_to_table(r, &GETargs); if (OK != ap_parse_form_data(r, NULL, &POST, -1, (~((apr_size_t)0)))) { __(r->server, " ** ap_parse_form_data is NOT OK"); } GET = (NULL == GET) ? GETargs : apr_table_overlay(r->pool, GETargs, GET); // move all POST parameters into GET table { ap_form_pair_t *pair; char *buffer; apr_off_t len; apr_size_t size; while (NULL != (pair = apr_array_pop(POST))) { apr_brigade_length(pair->value, 1, &len); size = (apr_size_t) len; buffer = apr_palloc(r->pool, size + 1); apr_brigade_flatten(pair->value, buffer, &size); buffer[len] = 0; apr_table_setn(GET, apr_pstrdup(r->pool, pair->name), buffer); //should name and value be ap_unescape_url() -ed? // __(r->server, "POST[%s]: %s", pair->name, buffer); } } params.r = r; params.args = NULL; apr_table_do(tab_args, ¶ms, GET, NULL); params.args = apr_pstrcat(r->pool, "&", params.args, "&", NULL); cursor_values[0] = params.args; cursor_value_lengths[0] = strlen(cursor_values[0]); /* set response content type according to configuration or to default value */ ap_set_content_type(r, dir_config->content_type_set ? dir_config->content_type : "text/html"); /* now connecting to Postgres, getting function output, and printing it */ pgc = pgasp_pool_open (r->server); if (PQstatus(pgc) != CONNECTION_OK) { spit_pg_error ("connect"); pgasp_pool_close(r->server, pgc); return OK; } /* removing extention (.pgasp or other) from file name, and adding "f_" for function name, i.e. foo.pgasp becomes psp_foo() */ snprintf(cursor_string, sizeof(cursor_string), "select * from f_%s($1::varchar)", basename); /* passing GET as first (and only) parameter */ if (0 == PQsendQueryParams (pgc, cursor_string, 1, NULL, cursor_values, cursor_value_lengths, cursor_value_formats, 0)) { spit_pg_error ("sending async query with params"); return clean_up_connection(r->server); } if (0 == PQsetSingleRowMode(pgc)) { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, r->server, "can not fall into single raw mode to fetch data"); } while (NULL != (pgr = PQgetResult(pgc))) { if (PQresultStatus(pgr) != PGRES_TUPLES_OK && PQresultStatus(pgr) != PGRES_SINGLE_TUPLE) { spit_pg_error ("fetch data"); return clean_up_connection(r->server); } /* the following counts and for-loop may seem excessive as it's just 1 row/1 field, but might need it in the future */ field_count = PQnfields(pgr); tuple_count = PQntuples(pgr); for (i = 0; i < tuple_count; i++) { for (j = 0; j < field_count; j++) ap_rprintf(r, "%s", PQgetvalue(pgr, i, j)); ap_rprintf(r, "\n"); } PQclear (pgr); } pgasp_pool_close(r->server, pgc); return OK; }
/* * Runs a query, which returns pieces of files from the remote source data * directory, and overwrites the corresponding parts of target files with * the received parts. The result set is expected to be of format: * * path text -- path in the data directory, e.g "base/1/123" * begin int4 -- offset within the file * chunk bytea -- file content * */ static void receiveFileChunks(const char *sql) { PGresult *res; if (PQsendQueryParams(conn, sql, 0, NULL, NULL, NULL, NULL, 1) != 1) { fprintf(stderr, "could not send query: %s\n", PQerrorMessage(conn)); exit(1); } if (verbose) fprintf(stderr, "getting chunks: %s\n", sql); if (PQsetSingleRowMode(conn) != 1) { fprintf(stderr, "could not set libpq connection to single row mode\n"); exit(1); } if (verbose) fprintf(stderr, "sent query\n"); while ((res = PQgetResult(conn)) != NULL) { char *filename; int filenamelen; int chunkoff; int chunksize; char *chunk; switch(PQresultStatus(res)) { case PGRES_SINGLE_TUPLE: break; case PGRES_TUPLES_OK: continue; /* final zero-row result */ default: fprintf(stderr, "unexpected result while fetching remote files: %s\n", PQresultErrorMessage(res)); exit(1); } /* sanity check the result set */ if (!(PQnfields(res) == 3 && PQntuples(res) == 1)) { fprintf(stderr, "unexpected result set size while fetching remote files\n"); exit(1); } if (!(PQftype(res, 0) == TEXTOID && PQftype(res, 1) == INT4OID && PQftype(res, 2) == BYTEAOID)) { fprintf(stderr, "unexpected data types in result set while fetching remote files: %u %u %u\n", PQftype(res, 0), PQftype(res, 1), PQftype(res, 2)); exit(1); } if (!(PQfformat(res, 0) == 1 && PQfformat(res, 1) == 1 && PQfformat(res, 2) == 1)) { fprintf(stderr, "unexpected result format while fetching remote files\n"); exit(1); } if (!(!PQgetisnull(res, 0, 0) && !PQgetisnull(res, 0, 1) && !PQgetisnull(res, 0, 2) && PQgetlength(res, 0, 1) == sizeof(int32))) { fprintf(stderr, "unexpected result set while fetching remote files\n"); exit(1); } /* Read result set to local variables */ memcpy(&chunkoff, PQgetvalue(res, 0, 1), sizeof(int32)); chunkoff = ntohl(chunkoff); chunksize = PQgetlength(res, 0, 2); filenamelen = PQgetlength(res, 0, 0); filename = pg_malloc(filenamelen + 1); memcpy(filename, PQgetvalue(res, 0, 0), filenamelen); filename[filenamelen] = '\0'; chunk = PQgetvalue(res, 0, 2); if (verbose) fprintf(stderr, "received chunk for file \"%s\", off %d, len %d\n", filename, chunkoff, chunksize); open_target_file(filename, false); write_file_range(chunk, chunkoff, chunksize); } }
int pgQueryThread::Execute() { wxMutexLocker lock(m_queriesLock); PGresult *result = NULL; wxMBConv &conv = *(m_conn->conv); wxString &query = m_queries[m_currIndex]->m_query; int &resultToRetrieve = m_queries[m_currIndex]->m_resToRetrieve; long &rowsInserted = m_queries[m_currIndex]->m_rowsInserted; Oid &insertedOid = m_queries[m_currIndex]->m_insertedOid; // using the alias for the pointer here, in order to save the result back // in the pgBatchQuery object pgSet *&dataSet = m_queries[m_currIndex]->m_resultSet; int &rc = m_queries[m_currIndex]->m_returnCode; pgParamsArray *params = m_queries[m_currIndex]->m_params; bool useCallable = m_queries[m_currIndex]->m_useCallable; pgError &err = m_queries[m_currIndex]->m_err; wxCharBuffer queryBuf = query.mb_str(conv); if (PQstatus(m_conn->conn) != CONNECTION_OK) { rc = pgQueryResultEvent::PGQ_CONN_LOST; err.msg_primary = _("Connection to the database server lost"); return(RaiseEvent(rc)); } if (!queryBuf && !query.IsEmpty()) { rc = pgQueryResultEvent::PGQ_STRING_INVALID; m_conn->SetLastResultError(NULL, _("the query could not be converted to the required encoding.")); err.msg_primary = _("Query string is empty"); return(RaiseEvent(rc)); } // Honour the parameters (if any) if (params && params->GetCount() > 0) { int pCount = params->GetCount(); int ret = 0, idx = 0; Oid *pOids = (Oid *)malloc(pCount * sizeof(Oid)); const char **pParams = (const char **)malloc(pCount * sizeof(const char *)); int *pLens = (int *)malloc(pCount * sizeof(int)); int *pFormats = (int *)malloc(pCount * sizeof(int)); // modes are used only by enterprisedb callable statement #if defined (__WXMSW__) || (EDB_LIBPQ) int *pModes = (int *)malloc(pCount * sizeof(int)); #endif for (; idx < pCount; idx++) { pgParam *param = (*params)[idx]; pOids[idx] = param->m_type; pParams[idx] = (const char *)param->m_val; pLens[idx] = param->m_len; pFormats[idx] = param->GetFormat(); #if defined (__WXMSW__) || (EDB_LIBPQ) pModes[idx] = param->m_mode; #endif } if (useCallable) { #if defined (__WXMSW__) || (EDB_LIBPQ) wxLogInfo(wxString::Format( _("using an enterprisedb callable statement (queryid:%ld, threadid:%ld)"), (long)m_currIndex, (long)GetId())); wxString stmt = wxString::Format(wxT("pgQueryThread-%ld-%ld"), this->GetId(), m_currIndex); PGresult *res = PQiPrepareOut(m_conn->conn, stmt.mb_str(wxConvUTF8), queryBuf, pCount, pOids, pModes); if( PQresultStatus(res) != PGRES_COMMAND_OK) { rc = pgQueryResultEvent::PGQ_ERROR_PREPARE_CALLABLE; err.SetError(res, &conv); PQclear(res); goto return_with_error; } ret = PQiSendQueryPreparedOut(m_conn->conn, stmt.mb_str(wxConvUTF8), pCount, pParams, pLens, pFormats, 1); if (ret != 1) { rc = pgQueryResultEvent::PGQ_ERROR_EXECUTE_CALLABLE; m_conn->SetLastResultError(NULL, _("Failed to run PQsendQuery in pgQueryThread")); err.msg_primary = wxString(PQerrorMessage(m_conn->conn), conv); PQclear(res); res = NULL; goto return_with_error; } PQclear(res); res = NULL; #else rc = -1; wxASSERT_MSG(false, _("the program execution flow must not reach to this point in pgQueryThread")); goto return_with_error; #endif } else { // assumptions: we will need the results in text format only ret = PQsendQueryParams(m_conn->conn, queryBuf, pCount, pOids, pParams, pLens, pFormats, 0); if (ret != 1) { rc = pgQueryResultEvent::PGQ_ERROR_SEND_QUERY; m_conn->SetLastResultError(NULL, _("Failed to run PQsendQueryParams in pgQueryThread")); err.msg_primary = _("Failed to run PQsendQueryParams in pgQueryThread.\n") + wxString(PQerrorMessage(m_conn->conn), conv); goto return_with_error; } } goto continue_without_error; return_with_error: { free(pOids); free(pParams); free(pLens); free(pFormats); #if defined (__WXMSW__) || (EDB_LIBPQ) free(pModes); #endif return (RaiseEvent(rc)); } } else { // use the PQsendQuery api in case, we don't have any parameters to // pass to the server if (!PQsendQuery(m_conn->conn, queryBuf)) { rc = pgQueryResultEvent::PGQ_ERROR_SEND_QUERY; err.msg_primary = _("Failed to run PQsendQueryParams in pgQueryThread.\n") + wxString(PQerrorMessage(m_conn->conn), conv); return(RaiseEvent(rc)); } } continue_without_error: int resultsRetrieved = 0; PGresult *lastResult = 0; while (true) { // This is a 'joinable' thread, it is not advisable to call 'delete' // function on this. // Hence - it does not make sense to use the function 'testdestroy' here. // We introduced the 'CancelExecution' function for the same purpose. // // Also, do not raise event when the query execution is cancelled to // avoid the bugs introduced to handle events by the event handler, // which is missing or being deleted. // // It will be responsibility of the compononent, using the object of // pgQueryThread, to take the required actions to take care of the // issue. if (m_cancelled) { m_conn->CancelExecution(); rc = pgQueryResultEvent::PGQ_EXECUTION_CANCELLED; err.msg_primary = _("Execution Cancelled"); if (lastResult) { PQclear(lastResult); lastResult = NULL; } AppendMessage(_("Query-thread execution cancelled...\nthe query is:")); AppendMessage(query); return rc; } if ((rc = PQconsumeInput(m_conn->conn)) != 1) { if (rc == 0) { err.msg_primary = wxString(PQerrorMessage(m_conn->conn), conv); } if (PQstatus(m_conn->conn) == CONNECTION_BAD) { err.msg_primary = _("Connection to the database server lost"); rc = pgQueryResultEvent::PGQ_CONN_LOST; } else { rc = pgQueryResultEvent::PGQ_ERROR_CONSUME_INPUT; } return(RaiseEvent(rc)); } if (PQisBusy(m_conn->conn)) { Yield(); this->Sleep(10); continue; } // if resultToRetrieve is given, the nth result will be returned, // otherwise the last result set will be returned. // all others are discarded PGresult *res = PQgetResult(m_conn->conn); if (!res) break; if((PQresultStatus(res) == PGRES_NONFATAL_ERROR) || (PQresultStatus(res) == PGRES_FATAL_ERROR) || (PQresultStatus(res) == PGRES_BAD_RESPONSE)) { result = res; err.SetError(res, &conv); // Wait for the execution to be finished // We need to fetch all the results, before sending the error // message do { if (PQconsumeInput(m_conn->conn) != 1) { if (m_cancelled) { rc = pgQueryResultEvent::PGQ_EXECUTION_CANCELLED; // Release the result as the query execution has been cancelled by the // user if (result) PQclear(result); return rc; } goto out_of_consume_input_loop; } if ((res = PQgetResult(m_conn->conn)) == NULL) { goto out_of_consume_input_loop; } // Release the temporary results PQclear(res); res = NULL; if (PQisBusy(m_conn->conn)) { Yield(); this->Sleep(10); } } while (true); break; } #if defined (__WXMSW__) || (EDB_LIBPQ) // there should be 2 results in the callable statement - the first is the // dummy, the second contains our out params. if (useCallable) { PQclear(res); result = PQiGetOutResult(m_conn->conn); } #endif if (PQresultStatus(res) == PGRES_COPY_IN) { rc = PGRES_COPY_IN; PQputCopyEnd(m_conn->conn, "not supported by pgadmin"); } if (PQresultStatus(res) == PGRES_COPY_OUT) { int copyRc; char *buf; int copyRows = 0; int lastCopyRc = 0; rc = PGRES_COPY_OUT; AppendMessage(_("query returned copy data:\n")); while((copyRc = PQgetCopyData(m_conn->conn, &buf, 1)) >= 0) { if (buf != NULL) { if (copyRows < 100) { wxString str(buf, conv); wxCriticalSectionLocker cs(m_criticalSection); m_queries[m_currIndex]->m_message.Append(str); } else if (copyRows == 100) AppendMessage(_("Query returned more than 100 copy rows, discarding the rest...\n")); PQfreemem(buf); } if (copyRc > 0) copyRows++; if (m_cancelled) { m_conn->CancelExecution(); rc = pgQueryResultEvent::PGQ_EXECUTION_CANCELLED; return -1; } if (lastCopyRc == 0 && copyRc == 0) { Yield(); this->Sleep(10); } if (copyRc == 0) { if (!PQconsumeInput(m_conn->conn)) { if (PQstatus(m_conn->conn) == CONNECTION_BAD) { err.msg_primary = _("Connection to the database server lost"); rc = pgQueryResultEvent::PGQ_CONN_LOST; } else { rc = pgQueryResultEvent::PGQ_ERROR_CONSUME_INPUT; err.msg_primary = wxString(PQerrorMessage(m_conn->conn), conv); } return(RaiseEvent(rc)); } } lastCopyRc = copyRc; } res = PQgetResult(m_conn->conn); if (!res) break; } resultsRetrieved++; if (resultsRetrieved == resultToRetrieve) { result = res; insertedOid = PQoidValue(res); if (insertedOid && insertedOid != (Oid) - 1) AppendMessage(wxString::Format(_("query inserted one row with oid %d.\n"), insertedOid)); else AppendMessage(wxString::Format(wxPLURAL("query result with %d row will be returned.\n", "query result with %d rows will be returned.\n", PQntuples(result)), PQntuples(result))); continue; } if (lastResult) { if (PQntuples(lastResult)) AppendMessage(wxString::Format(wxPLURAL("query result with %d row discarded.\n", "query result with %d rows discarded.\n", PQntuples(lastResult)), PQntuples(lastResult))); PQclear(lastResult); } lastResult = res; } out_of_consume_input_loop: if (!result) result = lastResult; err.SetError(result, &conv); AppendMessage(wxT("\n")); rc = PQresultStatus(result); if (rc == PGRES_TUPLES_OK) { dataSet = new pgSet(result, m_conn, conv, m_conn->needColQuoting); dataSet->MoveFirst(); } else if (rc == PGRES_COMMAND_OK) { char *s = PQcmdTuples(result); if (*s) rowsInserted = atol(s); } else if (rc == PGRES_FATAL_ERROR || rc == PGRES_NONFATAL_ERROR || rc == PGRES_BAD_RESPONSE) { if (result) { AppendMessage(wxString(PQresultErrorMessage(result), conv)); PQclear(result); result = NULL; } else { AppendMessage(wxString(PQerrorMessage(m_conn->conn), conv)); } return(RaiseEvent(rc)); } insertedOid = PQoidValue(result); if (insertedOid == (Oid) - 1) insertedOid = 0; return(RaiseEvent(1)); }
/*---- * Runs a query, which returns pieces of files from the remote source data * directory, and overwrites the corresponding parts of target files with * the received parts. The result set is expected to be of format: * * path text -- path in the data directory, e.g "base/1/123" * begin int8 -- offset within the file * chunk bytea -- file content *---- */ static void receiveFileChunks(const char *sql) { PGresult *res; if (PQsendQueryParams(conn, sql, 0, NULL, NULL, NULL, NULL, 1) != 1) pg_fatal("could not send query: %s", PQerrorMessage(conn)); pg_log(PG_DEBUG, "getting file chunks\n"); if (PQsetSingleRowMode(conn) != 1) pg_fatal("could not set libpq connection to single row mode\n"); while ((res = PQgetResult(conn)) != NULL) { char *filename; int filenamelen; int64 chunkoff; char chunkoff_str[32]; int chunksize; char *chunk; switch (PQresultStatus(res)) { case PGRES_SINGLE_TUPLE: break; case PGRES_TUPLES_OK: PQclear(res); continue; /* final zero-row result */ default: pg_fatal("unexpected result while fetching remote files: %s", PQresultErrorMessage(res)); } /* sanity check the result set */ if (PQnfields(res) != 3 || PQntuples(res) != 1) pg_fatal("unexpected result set size while fetching remote files\n"); if (PQftype(res, 0) != TEXTOID || PQftype(res, 1) != INT8OID || PQftype(res, 2) != BYTEAOID) { pg_fatal("unexpected data types in result set while fetching remote files: %u %u %u\n", PQftype(res, 0), PQftype(res, 1), PQftype(res, 2)); } if (PQfformat(res, 0) != 1 && PQfformat(res, 1) != 1 && PQfformat(res, 2) != 1) { pg_fatal("unexpected result format while fetching remote files\n"); } if (PQgetisnull(res, 0, 0) || PQgetisnull(res, 0, 1)) { pg_fatal("unexpected null values in result while fetching remote files\n"); } if (PQgetlength(res, 0, 1) != sizeof(int64)) pg_fatal("unexpected result length while fetching remote files\n"); /* Read result set to local variables */ memcpy(&chunkoff, PQgetvalue(res, 0, 1), sizeof(int64)); chunkoff = pg_recvint64(chunkoff); chunksize = PQgetlength(res, 0, 2); filenamelen = PQgetlength(res, 0, 0); filename = pg_malloc(filenamelen + 1); memcpy(filename, PQgetvalue(res, 0, 0), filenamelen); filename[filenamelen] = '\0'; chunk = PQgetvalue(res, 0, 2); /* * If a file has been deleted on the source, remove it on the target * as well. Note that multiple unlink() calls may happen on the same * file if multiple data chunks are associated with it, hence ignore * unconditionally anything missing. If this file is not a relation * data file, then it has been already truncated when creating the * file chunk list at the previous execution of the filemap. */ if (PQgetisnull(res, 0, 2)) { pg_log(PG_DEBUG, "received null value for chunk for file \"%s\", file has been deleted\n", filename); remove_target_file(filename, true); pg_free(filename); PQclear(res); continue; } /* * Separate step to keep platform-dependent format code out of * translatable strings. */ snprintf(chunkoff_str, sizeof(chunkoff_str), INT64_FORMAT, chunkoff); pg_log(PG_DEBUG, "received chunk for file \"%s\", offset %s, size %d\n", filename, chunkoff_str, chunksize); open_target_file(filename, false); write_target_range(chunk, chunkoff, chunksize); pg_free(filename); PQclear(res); } }
int pgsql_query_send_async(char *query, char *connect_info, IDL_VPTR *resultVptr) { /* connection info */ int query_status; PGconn *conn=NULL; PGresult *res=NULL; PGcancel *cancel_obj; /* Information about each field */ field_info *fi; /* Structure definition info */ idl_tag_info *ti; //UCHAR *dataPtr; char *dataPtr; /* temporary pointer to tag data */ UCHAR *tptr; /* loop variables */ long long row; int tag; /* binary or ascii? Only need ascii for file output */ int binary; int estatus; int verbose=0; /* We must reset this each time */ cancel_query = 0; /* Attempt to establish the connection */ conn = PQconnectdb(connect_info); if (PQstatus(conn) != CONNECTION_OK) { pgsql_query_error("Could not establish connection", PQerrorMessage(conn)); PQfinish(conn); return(MYPG_CONNECT_FAILURE); } /* send the query and return the results */ if (kw.file_there) binary = 0; else binary = 1; if (kw.verbose_there) if (kw.verbose) verbose = 1; if (verbose) IDL_Message(IDL_M_NAMED_GENERIC, IDL_MSG_INFO, "Querying database (^C to cancel)"); if (! PQsendQueryParams(conn, query, 0, NULL, NULL, NULL, NULL, binary) ) { prepExit(conn, res); return(MYPG_DISPATCH_ERROR); } if (! (cancel_obj = PQgetCancel(conn)) ) { IDL_Message(IDL_M_NAMED_GENERIC, IDL_MSG_INFO, "Cancel object is NULL"); return(MYPG_CANCEL_FAILURE); } /* Only allow SIGINT after this point, since it calls cancel */ pgsql_sigint_register(); /* note this is a busy loop. I tried sleeping, but it really slows down the job */ PQconsumeInput(conn); //Try to collect the results while (PQisBusy(conn)) // while not ready ... { if (cancel_query) { char errbuf[256]; IDL_Message(IDL_M_NAMED_GENERIC, IDL_MSG_INFO, "Canceling query at user request"); if (!PQcancel(cancel_obj, errbuf, 256) ) { estatus = MYPG_CANCEL_FAILURE; IDL_Message(IDL_M_NAMED_GENERIC, IDL_MSG_INFO, errbuf); } else estatus = MYPG_QUERY_CANCELLED; pgsql_sigint_unregister(); /* This will call PQfinish and PQclear clear the memory */ prepExit(conn, res); return(estatus); } PQconsumeInput(conn); //...retry } /* No signal handling beyond this point */ pgsql_sigint_unregister(); if (verbose) IDL_Message(IDL_M_NAMED_GENERIC, IDL_MSG_INFO, "Getting result"); res = PQgetResult(conn); /* Success? */ query_status = pgsql_query_checkstatus(res); if (query_status != MYPG_SUCCESS) { prepExit(conn, res); return(query_status); } /* See if the user input a file to write to */ if (kw.file_there) { int write_status; write_status = pgsql_write_file(res); prepExit(conn, res); return(write_status); } /* Get information for each returned field */ fi = pgsql_get_field_info(res); /* Copy into output keywords, if they exist */ pgsql_copy_info(fi); /* Get info to make struct and copy data */ ti = pgsql_get_idl_tag_info(fi->tagdefs); /* Create the output structure */ if (verbose) IDL_Message(IDL_M_NAMED_GENERIC, IDL_MSG_INFO, "Creating output struct"); dataPtr = IDL_MakeTempStructVector(ti->sdef, (IDL_MEMINT) fi->nTuples, resultVptr, IDL_TRUE); /* Copy into output variable */ if (verbose) IDL_Message(IDL_M_NAMED_GENERIC, IDL_MSG_INFO, "Copying data"); for (row=0; row< fi->nTuples; row++) for (tag = 0; tag < fi->nFields; tag++) { tptr = ( (*resultVptr)->value.s.arr->data + row*( (*resultVptr)->value.arr->elt_len) + ti->tagOffsets[tag]); pgsql_store_binary(ti->tagDesc[tag]->type, fi->field_isarray[tag], PQgetvalue(res, row, tag), tptr); } if (verbose) IDL_Message(IDL_M_NAMED_GENERIC, IDL_MSG_INFO, "Cleaning up"); pgsql_freemem(fi, ti); PQclear(res); PQfinish(conn); if (verbose) IDL_Message(IDL_M_NAMED_GENERIC, IDL_MSG_INFO, "Done"); return(MYPG_SUCCESS); }
static int dbd_pgsql_pselect_internal(apr_pool_t *pool, apr_dbd_t *sql, apr_dbd_results_t **results, apr_dbd_prepared_t *statement, int seek, const char **values, const int *len, const int *fmt) { PGresult *res; int rv; int ret = 0; if (seek) { /* synchronous query */ if (TXN_IGNORE_ERRORS(sql->trans)) { PGresult *res = PQexec(sql->conn, "SAVEPOINT APR_DBD_TXN_SP"); if (res) { int ret = PQresultStatus(res); PQclear(res); if (!dbd_pgsql_is_success(ret)) { sql->trans->errnum = ret; return PGRES_FATAL_ERROR; } } else { sql->trans->errnum = ret; return PGRES_FATAL_ERROR; } } if (statement->prepared) { res = PQexecPrepared(sql->conn, statement->name, statement->nargs, values, len, fmt, 0); } else { res = PQexecParams(sql->conn, statement->name, statement->nargs, 0, values, len, fmt, 0); } if (res) { ret = PQresultStatus(res); if (dbd_pgsql_is_success(ret)) { ret = 0; } else { PQclear(res); } } else { ret = PGRES_FATAL_ERROR; } if (ret != 0) { if (TXN_IGNORE_ERRORS(sql->trans)) { PGresult *res = PQexec(sql->conn, "ROLLBACK TO SAVEPOINT APR_DBD_TXN_SP"); if (res) { int ret = PQresultStatus(res); PQclear(res); if (!dbd_pgsql_is_success(ret)) { sql->trans->errnum = ret; return PGRES_FATAL_ERROR; } } else { sql->trans->errnum = ret; return PGRES_FATAL_ERROR; } } else if (TXN_NOTICE_ERRORS(sql->trans)){ sql->trans->errnum = ret; } return ret; } else { if (TXN_IGNORE_ERRORS(sql->trans)) { PGresult *res = PQexec(sql->conn, "RELEASE SAVEPOINT APR_DBD_TXN_SP"); if (res) { int ret = PQresultStatus(res); PQclear(res); if (!dbd_pgsql_is_success(ret)) { sql->trans->errnum = ret; return PGRES_FATAL_ERROR; } } else { sql->trans->errnum = ret; return PGRES_FATAL_ERROR; } } } if (!*results) { *results = apr_pcalloc(pool, sizeof(apr_dbd_results_t)); } (*results)->res = res; (*results)->ntuples = PQntuples(res); (*results)->sz = PQnfields(res); (*results)->random = seek; (*results)->pool = pool; apr_pool_cleanup_register(pool, res, clear_result, apr_pool_cleanup_null); } else { if (TXN_IGNORE_ERRORS(sql->trans)) { PGresult *res = PQexec(sql->conn, "SAVEPOINT APR_DBD_TXN_SP"); if (res) { int ret = PQresultStatus(res); PQclear(res); if (!dbd_pgsql_is_success(ret)) { sql->trans->errnum = ret; return PGRES_FATAL_ERROR; } } else { sql->trans->errnum = ret; return PGRES_FATAL_ERROR; } } if (statement->prepared) { rv = PQsendQueryPrepared(sql->conn, statement->name, statement->nargs, values, len, fmt, 0); } else { rv = PQsendQueryParams(sql->conn, statement->name, statement->nargs, 0, values, len, fmt, 0); } if (rv == 0) { if (TXN_IGNORE_ERRORS(sql->trans)) { PGresult *res = PQexec(sql->conn, "ROLLBACK TO SAVEPOINT APR_DBD_TXN_SP"); if (res) { int ret = PQresultStatus(res); PQclear(res); if (!dbd_pgsql_is_success(ret)) { sql->trans->errnum = ret; return PGRES_FATAL_ERROR; } } else { sql->trans->errnum = ret; return PGRES_FATAL_ERROR; } } else if (TXN_NOTICE_ERRORS(sql->trans)){ sql->trans->errnum = 1; } return 1; } else { if (TXN_IGNORE_ERRORS(sql->trans)) { PGresult *res = PQexec(sql->conn, "RELEASE SAVEPOINT APR_DBD_TXN_SP"); if (res) { int ret = PQresultStatus(res); PQclear(res); if (!dbd_pgsql_is_success(ret)) { sql->trans->errnum = ret; return PGRES_FATAL_ERROR; } } else { sql->trans->errnum = ret; return PGRES_FATAL_ERROR; } } } if (!*results) { *results = apr_pcalloc(pool, sizeof(apr_dbd_results_t)); } (*results)->random = seek; (*results)->handle = sql->conn; (*results)->pool = pool; } return ret; }
/*---- * Runs a query, which returns pieces of files from the remote source data * directory, and overwrites the corresponding parts of target files with * the received parts. The result set is expected to be of format: * * path text -- path in the data directory, e.g "base/1/123" * begin int4 -- offset within the file * chunk bytea -- file content *---- */ static void receiveFileChunks(const char *sql) { PGresult *res; if (PQsendQueryParams(conn, sql, 0, NULL, NULL, NULL, NULL, 1) != 1) pg_fatal("could not send query: %s", PQerrorMessage(conn)); pg_log(PG_DEBUG, "getting file chunks\n"); if (PQsetSingleRowMode(conn) != 1) pg_fatal("could not set libpq connection to single row mode\n"); while ((res = PQgetResult(conn)) != NULL) { char *filename; int filenamelen; int chunkoff; int chunksize; char *chunk; switch (PQresultStatus(res)) { case PGRES_SINGLE_TUPLE: break; case PGRES_TUPLES_OK: PQclear(res); continue; /* final zero-row result */ default: pg_fatal("unexpected result while fetching remote files: %s", PQresultErrorMessage(res)); } /* sanity check the result set */ if (PQnfields(res) != 3 || PQntuples(res) != 1) pg_fatal("unexpected result set size while fetching remote files\n"); if (PQftype(res, 0) != TEXTOID && PQftype(res, 1) != INT4OID && PQftype(res, 2) != BYTEAOID) { pg_fatal("unexpected data types in result set while fetching remote files: %u %u %u\n", PQftype(res, 0), PQftype(res, 1), PQftype(res, 2)); } if (PQfformat(res, 0) != 1 && PQfformat(res, 1) != 1 && PQfformat(res, 2) != 1) { pg_fatal("unexpected result format while fetching remote files\n"); } if (PQgetisnull(res, 0, 0) || PQgetisnull(res, 0, 1)) { pg_fatal("unexpected null values in result while fetching remote files\n"); } if (PQgetlength(res, 0, 1) != sizeof(int32)) pg_fatal("unexpected result length while fetching remote files\n"); /* Read result set to local variables */ memcpy(&chunkoff, PQgetvalue(res, 0, 1), sizeof(int32)); chunkoff = ntohl(chunkoff); chunksize = PQgetlength(res, 0, 2); filenamelen = PQgetlength(res, 0, 0); filename = pg_malloc(filenamelen + 1); memcpy(filename, PQgetvalue(res, 0, 0), filenamelen); filename[filenamelen] = '\0'; chunk = PQgetvalue(res, 0, 2); /* * It's possible that the file was deleted on remote side after we * created the file map. In this case simply ignore it, as if it was * not there in the first place, and move on. */ if (PQgetisnull(res, 0, 2)) { pg_log(PG_DEBUG, "received null value for chunk for file \"%s\", file has been deleted\n", filename); pg_free(filename); PQclear(res); continue; } pg_log(PG_DEBUG, "received chunk for file \"%s\", offset %d, size %d\n", filename, chunkoff, chunksize); open_target_file(filename, false); write_target_range(chunk, chunkoff, chunksize); pg_free(filename); PQclear(res); } }