mirror of
				https://github.com/postgres/postgres.git
				synced 2025-10-31 00:03:57 -04:00 
			
		
		
		
	Implement '\copy from -' to support reading copy data from the same
source the \copy came from. Also, fix prompting logic so that initial and per-line prompts appear for all cases of reading from an interactive terminal. Patch by Mark Feit, with some kibitzing by Tom Lane.
This commit is contained in:
		
							parent
							
								
									0f8a313508
								
							
						
					
					
						commit
						04cc4e18dd
					
				| @ -1,5 +1,5 @@ | ||||
| <!-- | ||||
| $PostgreSQL: pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.103 2004/01/20 19:49:34 tgl Exp $ | ||||
| $PostgreSQL: pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.104 2004/01/20 23:48:56 tgl Exp $ | ||||
| PostgreSQL documentation | ||||
| --> | ||||
| 
 | ||||
| @ -705,7 +705,7 @@ testdb=> | ||||
|         <term><literal>\copy <replaceable class="parameter">table</replaceable> | ||||
| 	[ ( <replaceable class="parameter">column_list</replaceable> ) ] | ||||
|         { <literal>from</literal> | <literal>to</literal> } | ||||
| 	<replaceable class="parameter">filename</replaceable> | stdin | stdout | ||||
| 	{ <replaceable class="parameter">filename</replaceable> | stdin | stdout | - } | ||||
|         [ <literal>with</literal> ]  | ||||
|             [ <literal>oids</literal> ]  | ||||
|             [ <literal>delimiter [as] </literal> '<replaceable class="parameter">character</replaceable>' ] | ||||
| @ -720,26 +720,41 @@ testdb=> | ||||
|         reading or writing the specified file, | ||||
|         <application>psql</application> reads or writes the file and | ||||
|         routes the data between the server and the local file system. | ||||
| 	This means that file accessibility and privileges are those | ||||
| 	of the local user, not the server, and no SQL superuser | ||||
| 	privileges are required. | ||||
|         This means that file accessibility and privileges are those of | ||||
|         the local user, not the server, and no SQL superuser | ||||
|         privileges are required. | ||||
| 	</para> | ||||
| 
 | ||||
| 	<para> | ||||
| 	The syntax of the command is similar to that of the | ||||
| 	<acronym>SQL</acronym> <command>COPY</command> command.  (See its | ||||
| 	description for the details.)  Note that, because of this, | ||||
| 	<acronym>SQL</acronym> <xref linkend="sql-copy" | ||||
| 	endterm="sql-copy-title"> command.  Note that, because of this, | ||||
| 	special parsing rules apply to the <command>\copy</command> | ||||
| 	command. In particular, the variable substitution rules and | ||||
| 	backslash escapes do not apply. | ||||
| 	</para> | ||||
| 
 | ||||
| 	<para> | ||||
| 	For <literal>\copy <replaceable | ||||
| 	class="parameter">table</replaceable> from <replaceable | ||||
| 	class="parameter">filename</replaceable></literal> operations, | ||||
| 	<application>psql</application> adds the option of using a | ||||
| 	hyphen instead of <replaceable | ||||
| 	class="parameter">filename</replaceable>.  This causes | ||||
| 	<literal>\copy</literal> to read rows from the same source that | ||||
| 	issued the command, continuing until <literal>\.</literal> is | ||||
| 	read or the stream reaches <acronym>EOF</>.  This option is | ||||
| 	useful for populating tables in-line within a SQL script file. | ||||
| 	In contrast, <literal>\copy from stdin</> always reads from | ||||
| 	<application>psql</application>'s standard input. | ||||
| 	</para> | ||||
| 
 | ||||
|         <tip> | ||||
|         <para> | ||||
| 	This operation is not as efficient as the <acronym>SQL</acronym> | ||||
| 	<command>COPY</command> command because all data must pass | ||||
| 	through the client/server connection. For large | ||||
| 	amounts of data the other technique may be preferable. | ||||
| 	amounts of data the <acronym>SQL</acronym> command may be preferable. | ||||
|         </para> | ||||
|         </tip> | ||||
| 
 | ||||
| @ -747,11 +762,12 @@ testdb=> | ||||
|         <para> | ||||
|         Note the difference in interpretation of | ||||
|         <literal>stdin</literal> and <literal>stdout</literal> between | ||||
|         client and server copies: in a client copy these always | ||||
| 	<literal>\copy</literal> and <command>COPY</command>. | ||||
| 	In <literal>\copy</literal> these always | ||||
|         refer to <application>psql</application>'s input and output | ||||
|         stream. On a server copy <literal>stdin</literal> comes from | ||||
|         wherever the <command>COPY</command> itself came from (for | ||||
|         example, a script run with the <option>-f</option> option), and | ||||
|         streams. In <command>COPY</command>, <literal>stdin</literal> comes | ||||
| 	from wherever the <command>COPY</command> itself came from (for | ||||
|         example, a script run with the <option>-f</option> option), while | ||||
|         <literal>stdout</literal> refers to the query output stream (see | ||||
|         <command>\o</command> meta-command below). | ||||
|         </para> | ||||
|  | ||||
| @ -3,7 +3,7 @@ | ||||
|  * | ||||
|  * Copyright (c) 2000-2003, PostgreSQL Global Development Group | ||||
|  * | ||||
|  * $PostgreSQL: pgsql/src/bin/psql/common.c,v 1.79 2004/01/09 21:12:20 momjian Exp $ | ||||
|  * $PostgreSQL: pgsql/src/bin/psql/common.c,v 1.80 2004/01/20 23:48:56 tgl Exp $ | ||||
|  */ | ||||
| #include "postgres_fe.h" | ||||
| #include "common.h" | ||||
| @ -513,12 +513,7 @@ ProcessCopyResult(PGresult *results) | ||||
| 			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); | ||||
| 			success = handleCopyIn(pset.db, pset.cur_cmd_source); | ||||
| 			break; | ||||
| 
 | ||||
| 		default: | ||||
|  | ||||
| @ -3,7 +3,7 @@ | ||||
|  * | ||||
|  * Copyright (c) 2000-2003, PostgreSQL Global Development Group | ||||
|  * | ||||
|  * $PostgreSQL: pgsql/src/bin/psql/copy.c,v 1.36 2004/01/09 21:12:20 momjian Exp $ | ||||
|  * $PostgreSQL: pgsql/src/bin/psql/copy.c,v 1.37 2004/01/20 23:48:56 tgl Exp $ | ||||
|  */ | ||||
| #include "postgres_fe.h" | ||||
| #include "copy.h" | ||||
| @ -23,6 +23,7 @@ | ||||
| 
 | ||||
| #include "settings.h" | ||||
| #include "common.h" | ||||
| #include "prompt.h" | ||||
| #include "stringutils.h" | ||||
| 
 | ||||
| #ifdef WIN32 | ||||
| @ -53,6 +54,7 @@ struct copy_options | ||||
| 	char	   *table; | ||||
| 	char	   *column_list; | ||||
| 	char	   *file;			/* NULL = stdin/stdout */ | ||||
| 	bool		in_dash;		/* true = use src stream not true stdin */ | ||||
| 	bool		from; | ||||
| 	bool		binary; | ||||
| 	bool		oids; | ||||
| @ -218,10 +220,25 @@ parse_slash_copy(const char *args) | ||||
| 
 | ||||
| 	if (strcasecmp(token, "stdin") == 0 || | ||||
| 		strcasecmp(token, "stdout") == 0) | ||||
| 	{ | ||||
| 		result->in_dash = false; | ||||
| 		result->file = NULL; | ||||
| 	} | ||||
| 	else if (strcmp(token, "-") == 0) | ||||
| 	{ | ||||
| 		/* Can't do this on output */ | ||||
| 		if (!result->from) | ||||
| 			goto error; | ||||
| 
 | ||||
| 		result->in_dash = true; | ||||
| 		result->file = NULL; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		result->in_dash = false; | ||||
| 		result->file = xstrdup(token); | ||||
| 	expand_tilde(&result->file); | ||||
| 		expand_tilde(&result->file); | ||||
| 	} | ||||
| 
 | ||||
| 	token = strtokx(NULL, whitespace, NULL, NULL, | ||||
| 					0, false, pset.encoding); | ||||
| @ -362,8 +379,10 @@ do_copy(const char *args) | ||||
| 	{ | ||||
| 		if (options->file) | ||||
| 			copystream = fopen(options->file, "r"); | ||||
| 		else if (options->in_dash) | ||||
|  			copystream = pset.cur_cmd_source; | ||||
| 		else | ||||
| 			copystream = stdin; | ||||
|  			copystream = stdin; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| @ -401,7 +420,7 @@ do_copy(const char *args) | ||||
| 			success = handleCopyOut(pset.db, copystream); | ||||
| 			break; | ||||
| 		case PGRES_COPY_IN: | ||||
| 			success = handleCopyIn(pset.db, copystream, NULL); | ||||
| 			success = handleCopyIn(pset.db, copystream); | ||||
| 			break; | ||||
| 		case PGRES_NONFATAL_ERROR: | ||||
| 		case PGRES_FATAL_ERROR: | ||||
| @ -416,7 +435,7 @@ do_copy(const char *args) | ||||
| 
 | ||||
| 	PQclear(result); | ||||
| 
 | ||||
| 	if (copystream != stdout && copystream != stdin) | ||||
|  	if (options->file != NULL) | ||||
| 		fclose(copystream); | ||||
| 	free_copy_options(options); | ||||
| 	return success; | ||||
| @ -486,13 +505,12 @@ handleCopyOut(PGconn *conn, FILE *copystream) | ||||
|  * conn should be a database connection that you just called COPY FROM on | ||||
|  * (and which gave you PGRES_COPY_IN back); | ||||
|  * copystream is the file stream you want the input to come from | ||||
|  * prompt is something to display to request user input (only makes sense | ||||
|  *	 if stdin is an interactive tty) | ||||
|  */ | ||||
| 
 | ||||
| bool | ||||
| handleCopyIn(PGconn *conn, FILE *copystream, const char *prompt) | ||||
| handleCopyIn(PGconn *conn, FILE *copystream) | ||||
| { | ||||
| 	const char *prompt; | ||||
| 	bool		copydone = false; | ||||
| 	bool		firstload; | ||||
| 	bool		linedone; | ||||
| @ -503,10 +521,17 @@ handleCopyIn(PGconn *conn, FILE *copystream, const char *prompt) | ||||
| 	int			ret; | ||||
| 	unsigned int linecount = 0; | ||||
| 
 | ||||
| 	if (prompt)					/* disable prompt if not interactive */ | ||||
| 	/* Prompt if interactive input */ | ||||
| 	if (isatty(fileno(copystream))) | ||||
| 	{ | ||||
| 		if (!isatty(fileno(copystream))) | ||||
| 			prompt = NULL; | ||||
| 		if (!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.")); | ||||
| 		prompt = get_prompt(PROMPT_COPY); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		prompt = NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	while (!copydone) | ||||
|  | ||||
| @ -3,7 +3,7 @@ | ||||
|  * | ||||
|  * Copyright (c) 2000-2003, PostgreSQL Global Development Group | ||||
|  * | ||||
|  * $PostgreSQL: pgsql/src/bin/psql/copy.h,v 1.14 2003/11/29 19:52:06 pgsql Exp $ | ||||
|  * $PostgreSQL: pgsql/src/bin/psql/copy.h,v 1.15 2004/01/20 23:48:56 tgl Exp $ | ||||
|  */ | ||||
| #ifndef COPY_H | ||||
| #define COPY_H | ||||
| @ -17,6 +17,6 @@ bool		do_copy(const char *args); | ||||
| /* lower level processors for copy in/out streams */ | ||||
| 
 | ||||
| bool		handleCopyOut(PGconn *conn, FILE *copystream); | ||||
| bool		handleCopyIn(PGconn *conn, FILE *copystream, const char *prompt); | ||||
| bool		handleCopyIn(PGconn *conn, FILE *copystream); | ||||
| 
 | ||||
| #endif | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user