⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 copy.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * psql - the PostgreSQL interactive terminal * * Copyright (c) 2000-2005, PostgreSQL Global Development Group * * $PostgreSQL: pgsql/src/bin/psql/copy.c,v 1.58 2005/10/15 02:49:40 momjian Exp $ */#include "postgres_fe.h"#include "copy.h"#include <errno.h>#include <signal.h>#include <sys/stat.h>#ifndef WIN32#include <unistd.h>				/* for isatty */#else#include <io.h>					/* I think */#endif#include "libpq-fe.h"#include "pqexpbuffer.h"#include "pqsignal.h"#include "settings.h"#include "common.h"#include "prompt.h"#include "stringutils.h"#if defined(WIN32) && (!defined(__MINGW32__))#define __S_ISTYPE(mode, mask)	(((mode) & S_IFMT) == (mask))#define S_ISDIR(mode)	 __S_ISTYPE((mode), S_IFDIR)#endif/* * parse_slash_copy * -- parses \copy command line * * The documented preferred syntax is: *	\copy tablename [(columnlist)] from|to filename *		[ with ] [ oids ] [ delimiter [as] char ] [ null [as] string ] * (binary is not here yet) * * The pre-7.3 syntax was: *	\copy tablename [(columnlist)] [with oids] from|to filename *		[ [using] delimiters char ] [ with null as string ] * * The actual accepted syntax is a rather unholy combination of these, * plus some undocumented flexibility (for instance, the clauses after * WITH can appear in any order).  The accepted syntax matches what * the backend grammar actually accepts (see backend/parser/gram.y). * * table name can be double-quoted and can have a schema part. * column names can be double-quoted. * filename, char, and string can be single-quoted like SQL literals. * * returns a malloc'ed structure with the options, or NULL on parsing error */struct copy_options{	char	   *table;	char	   *column_list;	char	   *file;			/* NULL = stdin/stdout */	bool		psql_inout;		/* true = use psql stdin/stdout */	bool		from;	bool		binary;	bool		oids;	bool		csv_mode;	bool		header;	char	   *delim;	char	   *null;	char	   *quote;	char	   *escape;	char	   *force_quote_list;	char	   *force_notnull_list;};static voidfree_copy_options(struct copy_options * ptr){	if (!ptr)		return;	free(ptr->table);	free(ptr->column_list);	free(ptr->file);	free(ptr->delim);	free(ptr->null);	free(ptr->quote);	free(ptr->escape);	free(ptr->force_quote_list);	free(ptr->force_notnull_list);	free(ptr);}/* concatenate "more" onto "var", freeing the original value of *var */static voidxstrcat(char **var, const char *more){	char	   *newvar;	newvar = pg_malloc(strlen(*var) + strlen(more) + 1);	strcpy(newvar, *var);	strcat(newvar, more);	free(*var);	*var = newvar;}static struct copy_options *parse_slash_copy(const char *args){	struct copy_options *result;	char	   *line;	char	   *token;	const char *whitespace = " \t\n\r";	if (args)		line = pg_strdup(args);	else	{		psql_error("\\copy: arguments required\n");		return NULL;	}	result = pg_calloc(1, sizeof(struct copy_options));	token = strtokx(line, whitespace, ".,()", "\"",					0, false, pset.encoding);	if (!token)		goto error;#ifdef NOT_USED	/* this is not implemented yet */	if (pg_strcasecmp(token, "binary") == 0)	{		result->binary = true;		token = strtokx(NULL, whitespace, ".,()", "\"",						0, false, pset.encoding);		if (!token)			goto error;	}#endif	result->table = pg_strdup(token);	token = strtokx(NULL, whitespace, ".,()", "\"",					0, false, pset.encoding);	if (!token)		goto error;	/*	 * strtokx() will not have returned a multi-character token starting with	 * '.', so we don't need strcmp() here.  Likewise for '(', etc, below.	 */	if (token[0] == '.')	{		/* handle schema . table */		xstrcat(&result->table, token);		token = strtokx(NULL, whitespace, ".,()", "\"",						0, false, pset.encoding);		if (!token)			goto error;		xstrcat(&result->table, token);		token = strtokx(NULL, whitespace, ".,()", "\"",						0, false, pset.encoding);		if (!token)			goto error;	}	if (token[0] == '(')	{		/* handle parenthesized column list */		result->column_list = pg_strdup(token);		for (;;)		{			token = strtokx(NULL, whitespace, ".,()", "\"",							0, false, pset.encoding);			if (!token || strchr(".,()", token[0]))				goto error;			xstrcat(&result->column_list, token);			token = strtokx(NULL, whitespace, ".,()", "\"",							0, false, pset.encoding);			if (!token)				goto error;			xstrcat(&result->column_list, token);			if (token[0] == ')')				break;			if (token[0] != ',')				goto error;		}		token = strtokx(NULL, whitespace, ".,()", "\"",						0, false, pset.encoding);		if (!token)			goto error;	}	/*	 * Allows old COPY syntax for backward compatibility 2002-06-19	 */	if (pg_strcasecmp(token, "with") == 0)	{		token = strtokx(NULL, whitespace, NULL, NULL,						0, false, pset.encoding);		if (!token || pg_strcasecmp(token, "oids") != 0)			goto error;		result->oids = true;		token = strtokx(NULL, whitespace, NULL, NULL,						0, false, pset.encoding);		if (!token)			goto error;	}	if (pg_strcasecmp(token, "from") == 0)		result->from = true;	else if (pg_strcasecmp(token, "to") == 0)		result->from = false;	else		goto error;	token = strtokx(NULL, whitespace, NULL, "'",					'\\', true, pset.encoding);	if (!token)		goto error;	if (pg_strcasecmp(token, "stdin") == 0 ||		pg_strcasecmp(token, "stdout") == 0)	{		result->psql_inout = false;		result->file = NULL;	}	else if (pg_strcasecmp(token, "pstdin") == 0 ||			 pg_strcasecmp(token, "pstdout") == 0)	{		result->psql_inout = true;		result->file = NULL;	}	else	{		result->psql_inout = false;		result->file = pg_strdup(token);		expand_tilde(&result->file);	}	token = strtokx(NULL, whitespace, NULL, NULL,					0, false, pset.encoding);	/*	 * Allows old COPY syntax for backward compatibility 2002-06-19	 */	if (token && pg_strcasecmp(token, "using") == 0)	{		token = strtokx(NULL, whitespace, NULL, NULL,						0, false, pset.encoding);		if (!(token && pg_strcasecmp(token, "delimiters") == 0))			goto error;	}	if (token && pg_strcasecmp(token, "delimiters") == 0)	{		token = strtokx(NULL, whitespace, NULL, "'",						'\\', false, pset.encoding);		if (!token)			goto error;		result->delim = pg_strdup(token);		token = strtokx(NULL, whitespace, NULL, NULL,						0, false, pset.encoding);	}	if (token)	{		/*		 * WITH is optional.  Also, the backend will allow WITH followed by		 * nothing, so we do too.		 */		if (pg_strcasecmp(token, "with") == 0)			token = strtokx(NULL, whitespace, NULL, NULL,							0, false, pset.encoding);		while (token)		{			bool		fetch_next;			fetch_next = true;			/* someday allow BINARY here */			if (pg_strcasecmp(token, "oids") == 0)				result->oids = true;			else if (pg_strcasecmp(token, "csv") == 0)				result->csv_mode = true;			else if (pg_strcasecmp(token, "header") == 0)				result->header = true;			else if (pg_strcasecmp(token, "delimiter") == 0)			{				token = strtokx(NULL, whitespace, NULL, "'",								'\\', false, pset.encoding);				if (token && pg_strcasecmp(token, "as") == 0)					token = strtokx(NULL, whitespace, NULL, "'",									'\\', false, pset.encoding);				if (token)					result->delim = pg_strdup(token);				else					goto error;			}			else if (pg_strcasecmp(token, "null") == 0)			{				token = strtokx(NULL, whitespace, NULL, "'",								'\\', false, pset.encoding);				if (token && pg_strcasecmp(token, "as") == 0)					token = strtokx(NULL, whitespace, NULL, "'",									'\\', false, pset.encoding);				if (token)					result->null = pg_strdup(token);				else					goto error;			}			else if (pg_strcasecmp(token, "quote") == 0)			{				token = strtokx(NULL, whitespace, NULL, "'",								'\\', false, pset.encoding);				if (token && pg_strcasecmp(token, "as") == 0)					token = strtokx(NULL, whitespace, NULL, "'",									'\\', false, pset.encoding);				if (token)					result->quote = pg_strdup(token);				else					goto error;			}			else if (pg_strcasecmp(token, "escape") == 0)			{				token = strtokx(NULL, whitespace, NULL, "'",								'\\', false, pset.encoding);				if (token && pg_strcasecmp(token, "as") == 0)					token = strtokx(NULL, whitespace, NULL, "'",									'\\', false, pset.encoding);				if (token)					result->escape = pg_strdup(token);				else					goto error;			}			else if (pg_strcasecmp(token, "force") == 0)			{				token = strtokx(NULL, whitespace, ",", "\"",								0, false, pset.encoding);				if (pg_strcasecmp(token, "quote") == 0)				{					/* handle column list */					fetch_next = false;					for (;;)					{						token = strtokx(NULL, whitespace, ",", "\"",										0, false, pset.encoding);						if (!token || strchr(",", token[0]))							goto error;						if (!result->force_quote_list)							result->force_quote_list = pg_strdup(token);						else							xstrcat(&result->force_quote_list, token);						token = strtokx(NULL, whitespace, ",", "\"",										0, false, pset.encoding);						if (!token || token[0] != ',')							break;						xstrcat(&result->force_quote_list, token);					}				}				else if (pg_strcasecmp(token, "not") == 0)				{					token = strtokx(NULL, whitespace, ",", "\"",									0, false, pset.encoding);					if (pg_strcasecmp(token, "null") != 0)						goto error;					/* handle column list */					fetch_next = false;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -