Ejemplo n.º 1
0
Archivo: copy.c Proyecto: 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;
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
0
/*
 * Execute a \copy command (frontend copy). We have to open a file (or execute
 * a command), 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;
    bool		success;
    
    /* parse options */
    options = parse_slash_copy(args);
    
    if (!options)
        return false;
    
    /* prepare to read or write the target file */
    if (options->file && !options->program)
        canonicalize_path(options->file);
    
    if (options->from)
    {
        if (options->file)
        {
            if (options->program)
            {
                fflush(stdout);
                fflush(stderr);
                errno = 0;
                copystream = popen(options->file, PG_BINARY_R);
            }
            else
                copystream = fopen(options->file, PG_BINARY_R);
        }
        else if (!options->psql_inout)
            copystream = pset.cur_cmd_source;
        else
            copystream = stdin;
    }
    else
    {
        if (options->file)
        {
            if (options->program)
            {
                fflush(stdout);
                fflush(stderr);
                errno = 0;
#ifndef WIN32
                pqsignal(SIGPIPE, SIG_IGN);
#endif
                copystream = popen(options->file, PG_BINARY_W);
            }
            else
                copystream = fopen(options->file, PG_BINARY_W);
        }
        else if (!options->psql_inout)
            copystream = pset.queryFout;
        else
            copystream = stdout;
    }
    
    if (!copystream)
    {
        if (options->program)
            psql_error("could not execute command \"%s\": %s\n",
                       options->file, strerror(errno));
        else
            psql_error("%s: %s\n",
                       options->file, strerror(errno));
        free_copy_options(options);
        return false;
    }
    
    if (!options->program)
    {
        struct stat st;
        int			result;
        
        /* make sure the specified file is not a directory */
        if ((result = fstat(fileno(copystream), &st)) < 0)
            psql_error("could not stat file \"%s\": %s\n",
                       options->file, strerror(errno));
        
        if (result == 0 && S_ISDIR(st.st_mode))
            psql_error("%s: cannot copy from/to a directory\n",
                       options->file);
        
        if (result < 0 || S_ISDIR(st.st_mode))
        {
            fclose(copystream);
            free_copy_options(options);
            return false;
        }
    }
    
    /* build the command we will send to the backend */
    initPQExpBuffer(&query);
    printfPQExpBuffer(&query, "COPY ");
    appendPQExpBufferStr(&query, options->before_tofrom);
    if (options->from)
        appendPQExpBufferStr(&query, " FROM STDIN ");
    else
        appendPQExpBufferStr(&query, " TO STDOUT ");
    if (options->after_tofrom)
        appendPQExpBufferStr(&query, options->after_tofrom);
    
    /* run it like a user command, but with copystream as data source/sink */
    pset.copyStream = copystream;
    success = SendQuery(query.data);
    pset.copyStream = NULL;
    termPQExpBuffer(&query);
    
    if (options->file != NULL)
    {
        if (options->program)
        {
            int			pclose_rc = pclose(copystream);
            
            if (pclose_rc != 0)
            {
                if (pclose_rc < 0)
                    psql_error("could not close pipe to external command: %s\n",
                               strerror(errno));
                else
                {
                    char	   *reason = wait_result_to_str(pclose_rc);
                    
                    psql_error("%s: %s\n", options->file,
                               reason ? reason : "");
                    if (reason)
                        free(reason);
                }
                success = false;
            }
#ifndef WIN32
            pqsignal(SIGPIPE, SIG_DFL);
#endif
        }
        else
        {
            if (fclose(copystream) != 0)
            {
                psql_error("%s: %s\n", options->file, strerror(errno));
                success = false;
            }
        }
    }
    free_copy_options(options);
    return success;
}
Ejemplo n.º 4
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;
	FILE	   *save_file;
	FILE	  **override_file;
	struct copy_options *options;
	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)
	{
		override_file = &pset.cur_cmd_source;

		if (options->file)
			copystream = fopen(options->file, PG_BINARY_R);
		else if (!options->psql_inout)
			copystream = pset.cur_cmd_source;
		else
			copystream = stdin;
	}
	else
	{
		override_file = &pset.queryFout;

		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 */
	initPQExpBuffer(&query);
	printfPQExpBuffer(&query, "COPY ");
	appendPQExpBufferStr(&query, options->before_tofrom);
	if (options->from)
		appendPQExpBuffer(&query, " FROM STDIN ");
	else
		appendPQExpBuffer(&query, " TO STDOUT ");
	if (options->after_tofrom)
		appendPQExpBufferStr(&query, options->after_tofrom);

	/* Run it like a user command, interposing the data source or sink. */
	save_file = *override_file;
	*override_file = copystream;
	success = SendQuery(query.data);
	*override_file = save_file;
	termPQExpBuffer(&query);

	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;
}