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

📄 command.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * psql - the PostgreSQL interactive terminal * * Copyright (c) 2000-2005, PostgreSQL Global Development Group * * $PostgreSQL: pgsql/src/bin/psql/command.c,v 1.154.2.3 2006/03/04 04:30:51 momjian Exp $ */#include "postgres_fe.h"#include "command.h"#ifdef WIN32_CLIENT_ONLY		/* needed for BCC */#undef mkdir#endif#include <errno.h>#include <ctype.h>#ifdef HAVE_PWD_H#include <pwd.h>#endif#ifndef WIN32#include <sys/types.h>			/* for umask() */#include <sys/stat.h>			/* for stat() */#include <fcntl.h>				/* open() flags */#include <unistd.h>				/* for geteuid(), getpid(), stat() */#else#include <win32.h>#include <io.h>#include <fcntl.h>#include <direct.h>#ifndef WIN32_CLIENT_ONLY#include <sys/types.h>			/* for umask() */#include <sys/stat.h>			/* for stat() */#endif#endif#include "libpq-fe.h"#include "pqexpbuffer.h"#include "common.h"#include "copy.h"#include "describe.h"#include "help.h"#include "input.h"#include "large_obj.h"#include "mainloop.h"#include "print.h"#include "psqlscan.h"#include "settings.h"#include "variables.h"#include "mb/pg_wchar.h"/* functions for use in this file */static backslashResult exec_command(const char *cmd,			 PsqlScanState scan_state,			 PQExpBuffer query_buf);static bool do_edit(const char *filename_arg, PQExpBuffer query_buf);static bool do_connect(const char *new_dbname, const char *new_user);static bool do_shell(const char *command);/*---------- * HandleSlashCmds: * * Handles all the different commands that start with '\', * ordinarily called by MainLoop(). * * scan_state is a lexer working state that is set to continue scanning * just after the '\'.  The lexer is advanced past the command and all * arguments on return. * * 'query_buf' contains the query-so-far, which may be modified by * execution of the backslash command (for example, \r clears it). * query_buf can be NULL if there is no query so far. * * Returns a status code indicating what action is desired, see command.h. *---------- */backslashResultHandleSlashCmds(PsqlScanState scan_state,				PQExpBuffer query_buf){	backslashResult status = CMD_SKIP_LINE;	char	   *cmd;	char	   *arg;	psql_assert(scan_state);	/* Parse off the command name */	cmd = psql_scan_slash_command(scan_state);	/* And try to execute it */	status = exec_command(cmd, scan_state, query_buf);	if (status == CMD_UNKNOWN && strlen(cmd) > 1)	{		/*		 * If the command was not recognized, try to parse it as a one-letter		 * command with immediately following argument (a still-supported, but		 * no longer encouraged, syntax).		 */		char		new_cmd[2];		/* don't change cmd until we know it's okay */		new_cmd[0] = cmd[0];		new_cmd[1] = '\0';		psql_scan_slash_pushback(scan_state, cmd + 1);		status = exec_command(new_cmd, scan_state, query_buf);		if (status != CMD_UNKNOWN)		{			/* adjust cmd for possible messages below */			cmd[1] = '\0';		}	}	if (status == CMD_UNKNOWN)	{		if (pset.cur_cmd_interactive)			fprintf(stderr, _("Invalid command \\%s. Try \\? for help.\n"), cmd);		else			psql_error("invalid command \\%s\n", cmd);		status = CMD_ERROR;	}	if (status != CMD_ERROR)	{		/* eat any remaining arguments after a valid command */		/* note we suppress evaluation of backticks here */		while ((arg = psql_scan_slash_option(scan_state,											 OT_VERBATIM, NULL, false)))		{			psql_error("\\%s: extra argument \"%s\" ignored\n", cmd, arg);			free(arg);		}	}	else	{		/* silently throw away rest of line after an erroneous command */		while ((arg = psql_scan_slash_option(scan_state,											 OT_WHOLE_LINE, NULL, false)))			free(arg);	}	/* if there is a trailing \\, swallow it */	psql_scan_slash_command_end(scan_state);	free(cmd);	return status;}/* * Subroutine to actually try to execute a backslash command. */static backslashResultexec_command(const char *cmd,			 PsqlScanState scan_state,			 PQExpBuffer query_buf){	bool		success = true; /* indicate here if the command ran ok or								 * failed */	bool		quiet = QUIET();	backslashResult status = CMD_SKIP_LINE;	/*	 * \a -- toggle field alignment This makes little sense but we keep it	 * around.	 */	if (strcmp(cmd, "a") == 0)	{		if (pset.popt.topt.format != PRINT_ALIGNED)			success = do_pset("format", "aligned", &pset.popt, quiet);		else			success = do_pset("format", "unaligned", &pset.popt, quiet);	}	/* \C -- override table title (formerly change HTML caption) */	else if (strcmp(cmd, "C") == 0)	{		char	   *opt = psql_scan_slash_option(scan_state,												 OT_NORMAL, NULL, true);		success = do_pset("title", opt, &pset.popt, quiet);		free(opt);	}	/*----------	 * \c or \connect -- connect to new database or as different user	 *	 * \c foo bar  connect to db "foo" as user "bar"	 * \c foo [-]  connect to db "foo" as current user	 * \c - bar    connect to current db as user "bar"	 * \c		   connect to default db as default user	 *----------	 */	else if (strcmp(cmd, "c") == 0 || strcmp(cmd, "connect") == 0)	{		char	   *opt1,				   *opt2;		char		opt1q,					opt2q;		/*		 * Ideally we should treat the arguments as SQL identifiers.  But for		 * backwards compatibility with 7.2 and older pg_dump files, we have		 * to take unquoted arguments verbatim (don't downcase them). For now,		 * double-quoted arguments may be stripped of double quotes (as if SQL		 * identifiers).  By 7.4 or so, pg_dump files can be expected to		 * double-quote all mixed-case \connect arguments, and then we can get		 * rid of OT_SQLIDHACK.		 */		opt1 = psql_scan_slash_option(scan_state,									  OT_SQLIDHACK, &opt1q, true);		opt2 = psql_scan_slash_option(scan_state,									  OT_SQLIDHACK, &opt2q, true);		if (opt2)			/* gave username */			success = do_connect(!opt1q && (strcmp(opt1, "-") == 0 || strcmp(opt1, "") == 0) ? "" : opt1,								 !opt2q && (strcmp(opt2, "-") == 0 || strcmp(opt2, "") == 0) ? "" : opt2);		else if (opt1)			/* gave database name */			success = do_connect(!opt1q && (strcmp(opt1, "-") == 0 || strcmp(opt1, "") == 0) ? "" : opt1, "");		else			/* connect to default db as default user */			success = do_connect(NULL, NULL);		free(opt1);		free(opt2);	}	/* \cd */	else if (strcmp(cmd, "cd") == 0)	{		char	   *opt = psql_scan_slash_option(scan_state,												 OT_NORMAL, NULL, true);		char	   *dir;		if (opt)			dir = opt;		else		{#ifndef WIN32			struct passwd *pw;			pw = getpwuid(geteuid());			if (!pw)			{				psql_error("could not get home directory: %s\n", strerror(errno));				exit(EXIT_FAILURE);			}			dir = pw->pw_dir;#else							/* WIN32 */			/*			 * On Windows, 'cd' without arguments prints the current			 * directory, so if someone wants to code this here instead...			 */			dir = "/";#endif   /* WIN32 */		}		if (chdir(dir) == -1)		{			psql_error("\\%s: could not change directory to \"%s\": %s\n",					   cmd, dir, strerror(errno));			success = false;		}		if (pset.dirname)			pfree(pset.dirname);		pset.dirname = pg_strdup(dir);		canonicalize_path(pset.dirname);		if (opt)			free(opt);	}	/* \copy */	else if (pg_strcasecmp(cmd, "copy") == 0)	{		char	   *opt = psql_scan_slash_option(scan_state,												 OT_WHOLE_LINE, NULL, false);		success = do_copy(opt);		free(opt);	}	/* \copyright */	else if (strcmp(cmd, "copyright") == 0)		print_copyright();	/* \d* commands */	else if (cmd[0] == 'd')	{		char	   *pattern;		bool		show_verbose;		/* We don't do SQLID reduction on the pattern yet */		pattern = psql_scan_slash_option(scan_state,										 OT_NORMAL, NULL, true);		show_verbose = strchr(cmd, '+') ? true : false;		switch (cmd[1])		{			case '\0':			case '+':				if (pattern)					success = describeTableDetails(pattern, show_verbose);				else					/* standard listing of interesting things */					success = listTables("tvs", NULL, show_verbose);				break;			case 'a':				success = describeAggregates(pattern, show_verbose);				break;			case 'b':				success = describeTablespaces(pattern, show_verbose);				break;			case 'c':				success = listConversions(pattern);				break;			case 'C':				success = listCasts(pattern);				break;			case 'd':				success = objectDescription(pattern);				break;			case 'D':				success = listDomains(pattern);				break;			case 'f':				success = describeFunctions(pattern, show_verbose);				break;			case 'g':				/* no longer distinct from \du */				success = describeRoles(pattern);				break;			case 'l':				success = do_lo_list();				break;			case 'n':				success = listSchemas(pattern, show_verbose);				break;			case 'o':				success = describeOperators(pattern);				break;			case 'p':				success = permissionsList(pattern);				break;			case 'T':				success = describeTypes(pattern, show_verbose);				break;			case 't':			case 'v':			case 'i':			case 's':			case 'S':				success = listTables(&cmd[1], pattern, show_verbose);				break;			case 'u':				success = describeRoles(pattern);				break;			default:				status = CMD_UNKNOWN;		}		if (pattern)			free(pattern);	}	/*	 * \e or \edit -- edit the current query buffer (or a file and make it the	 * query buffer	 */	else if (strcmp(cmd, "e") == 0 || strcmp(cmd, "edit") == 0)	{		char	   *fname;		if (!query_buf)		{			psql_error("no query buffer\n");			status = CMD_ERROR;		}		else		{			fname = psql_scan_slash_option(scan_state,										   OT_NORMAL, NULL, true);			expand_tilde(&fname);			if (fname)				canonicalize_path(fname);			status = do_edit(fname, query_buf) ? CMD_NEWEDIT : CMD_ERROR;			free(fname);		}	}	/* \echo and \qecho */	else if (strcmp(cmd, "echo") == 0 || strcmp(cmd, "qecho") == 0)	{		char	   *value;		char		quoted;		bool		no_newline = false;		bool		first = true;		FILE	   *fout;		if (strcmp(cmd, "qecho") == 0)			fout = pset.queryFout;		else			fout = stdout;		while ((value = psql_scan_slash_option(scan_state,											   OT_NORMAL, &quoted, false)))		{			if (!quoted && strcmp(value, "-n") == 0)				no_newline = true;			else			{				if (first)					first = false;				else					fputc(' ', fout);				fputs(value, fout);			}			free(value);		}		if (!no_newline)			fputs("\n", fout);	}	/* \encoding -- set/show client side encoding */	else if (strcmp(cmd, "encoding") == 0)	{		char	   *encoding = psql_scan_slash_option(scan_state,													  OT_NORMAL, NULL, false);		if (!encoding)		{			/* show encoding */			puts(pg_encoding_to_char(pset.encoding));		}		else		{			/* set encoding */			if (PQsetClientEncoding(pset.db, encoding) == -1)				psql_error("%s: invalid encoding name or conversion procedure not found\n", encoding);			else			{				/* save encoding info into psql internal data */				pset.encoding = PQclientEncoding(pset.db);				pset.popt.topt.encoding = pset.encoding;				SetVariable(pset.vars, "ENCODING",							pg_encoding_to_char(pset.encoding));			}			free(encoding);		}	}	/* \f -- change field separator */	else if (strcmp(cmd, "f") == 0)	{		char	   *fname = psql_scan_slash_option(scan_state,												   OT_NORMAL, NULL, false);		success = do_pset("fieldsep", fname, &pset.popt, quiet);		free(fname);	}	/* \g means send query */	else if (strcmp(cmd, "g") == 0)	{		char	   *fname = psql_scan_slash_option(scan_state,												   OT_FILEPIPE, NULL, false);		if (!fname)			pset.gfname = NULL;		else		{			expand_tilde(&fname);			pset.gfname = pg_strdup(fname);		}		free(fname);		status = CMD_SEND;	}	/* help */	else if (strcmp(cmd, "h") == 0 || strcmp(cmd, "help") == 0)	{		char	   *opt = psql_scan_slash_option(scan_state,												 OT_WHOLE_LINE, NULL, false);		helpSQL(opt, pset.popt.topt.pager);		free(opt);	}	/* HTML mode */	else if (strcmp(cmd, "H") == 0 || strcmp(cmd, "html") == 0)	{		if (pset.popt.topt.format != PRINT_HTML)			success = do_pset("format", "html", &pset.popt, quiet);		else			success = do_pset("format", "aligned", &pset.popt, quiet);	}	/* \i is include file */	else if (strcmp(cmd, "i") == 0 || strcmp(cmd, "include") == 0)	{		char	   *fname = psql_scan_slash_option(scan_state,												   OT_NORMAL, NULL, true);		if (!fname)		{			psql_error("\\%s: missing required argument\n", cmd);			success = false;		}		else		{			expand_tilde(&fname);			success = (process_file(fname) == EXIT_SUCCESS);			free(fname);		}	}	/* \l is list databases */	else if (strcmp(cmd, "l") == 0 || strcmp(cmd, "list") == 0)		success = listAllDbs(false);	else if (strcmp(cmd, "l+") == 0 || strcmp(cmd, "list+") == 0)		success = listAllDbs(true);	/*	 * large object things	 */	else if (strncmp(cmd, "lo_", 3) == 0)	{		char	   *opt1,				   *opt2;

⌨️ 快捷键说明

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