コード例 #1
0
ファイル: common.c プロジェクト: GisKook/Gis
/*
 * 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;
}
コード例 #2
0
ファイル: common.c プロジェクト: sunyangkobe/cscd43
/*
 * 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:
			success = handleCopyOut(pset.db, pset.queryFout);
			break;

		case PGRES_COPY_IN:
			if (pset.cur_cmd_interactive && !QUIET())
				puts(gettext("Enter data to be copied followed by a newline.\n"
							 "End with a backslash and a period on a line by itself."));

			success = handleCopyIn(pset.db, pset.cur_cmd_source,
			  pset.cur_cmd_interactive ? get_prompt(PROMPT_COPY) : NULL);
			break;

		default:
			break;
	}

	/* may need this to recover from conn loss during COPY */
	if (!CheckConnection())
		return false;

	return success;
}
コード例 #3
0
ファイル: copy.c プロジェクト: colinet/sqlix
/*
 * 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;
}
コード例 #4
0
ファイル: common.c プロジェクト: PJMODOS/postgres
/*
 * 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,
										&copy_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),
									   &copy_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;
}
コード例 #5
0
ファイル: common.c プロジェクト: AllenDou/postgresql
/*
 * 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;
}
コード例 #6
0
/*
 * 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;
}