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

📄 tab-complete.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
" UNION ALL SELECT 'PUBLIC'"/* the silly-looking length condition is just to eat up the current word */#define Query_for_table_owning_index \"SELECT pg_catalog.quote_ident(c1.relname) "\"  FROM pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_index i"\" WHERE c1.oid=i.indrelid and i.indexrelid=c2.oid"\"       and (%d = length('%s'))"\"       and pg_catalog.quote_ident(c2.relname)='%s'"\"       and pg_catalog.pg_table_is_visible(c2.oid)"/* the silly-looking length condition is just to eat up the current word */#define Query_for_index_of_table \"SELECT pg_catalog.quote_ident(c2.relname) "\"  FROM pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_index i"\" WHERE c1.oid=i.indrelid and i.indexrelid=c2.oid"\"       and (%d = length('%s'))"\"       and pg_catalog.quote_ident(c1.relname)='%s'"\"       and pg_catalog.pg_table_is_visible(c2.oid)"/* the silly-looking length condition is just to eat up the current word */#define Query_for_list_of_tables_for_trigger \"SELECT pg_catalog.quote_ident(relname) "\"  FROM pg_catalog.pg_class"\" WHERE (%d = length('%s'))"\"   AND oid IN "\"       (SELECT tgrelid FROM pg_catalog.pg_trigger "\"         WHERE pg_catalog.quote_ident(tgname)='%s')"/* * This is a list of all "things" in Pgsql, which can show up after CREATE or * DROP; and there is also a query to get a list of them. */typedef struct{	const char *name;	const char *query;			/* simple query, or NULL */	const SchemaQuery *squery;	/* schema query, or NULL */} pgsql_thing_t;static const pgsql_thing_t words_after_create[] = {	{"AGGREGATE", NULL, &Query_for_list_of_aggregates},	{"CAST", NULL, NULL},		/* Casts have complex structures for names, so								 * skip it */	/*	 * CREATE CONSTRAINT TRIGGER is not supported here because it is designed	 * to be used only by pg_dump.	 */	{"CONVERSION", "SELECT pg_catalog.quote_ident(conname) FROM pg_catalog.pg_conversion WHERE substring(pg_catalog.quote_ident(conname),1,%d)='%s'"},	{"DATABASE", Query_for_list_of_databases},	{"DOMAIN", NULL, &Query_for_list_of_domains},	{"FUNCTION", NULL, &Query_for_list_of_functions},	{"GROUP", Query_for_list_of_roles},	{"LANGUAGE", Query_for_list_of_languages},	{"INDEX", NULL, &Query_for_list_of_indexes},	{"OPERATOR", NULL, NULL},	/* Querying for this is probably not such a								 * good idea. */	{"ROLE", Query_for_list_of_roles},	{"RULE", "SELECT pg_catalog.quote_ident(rulename) FROM pg_catalog.pg_rules WHERE substring(pg_catalog.quote_ident(rulename),1,%d)='%s'"},	{"SCHEMA", Query_for_list_of_schemas},	{"SEQUENCE", NULL, &Query_for_list_of_sequences},	{"TABLE", NULL, &Query_for_list_of_tables},	{"TABLESPACE", Query_for_list_of_tablespaces},	{"TEMP", NULL, NULL},		/* for CREATE TEMP TABLE ... */	{"TRIGGER", "SELECT pg_catalog.quote_ident(tgname) FROM pg_catalog.pg_trigger WHERE substring(pg_catalog.quote_ident(tgname),1,%d)='%s'"},	{"TYPE", NULL, &Query_for_list_of_datatypes},	{"UNIQUE", NULL, NULL},		/* for CREATE UNIQUE INDEX ... */	{"USER", Query_for_list_of_roles},	{"VIEW", NULL, &Query_for_list_of_views},	{NULL, NULL, NULL}			/* end of list */};/* Forward declaration of functions */static char **psql_completion(char *text, int start, int end);static char *create_command_generator(const char *text, int state);static char *complete_from_query(const char *text, int state);static char *complete_from_schema_query(const char *text, int state);static char *_complete_from_query(int is_schema_query,					 const char *text, int state);static char *complete_from_const(const char *text, int state);static char *complete_from_list(const char *text, int state);static PGresult *exec_query(const char *query);static char *previous_word(int point, int skip);#if 0static char *quote_file_name(char *text, int match_type, char *quote_pointer);static char *dequote_file_name(char *text, char quote_char);#endif/* Initialize the readline library for our purposes. */voidinitialize_readline(void){	rl_readline_name = (char *) pset.progname;	rl_attempted_completion_function = (void *) psql_completion;	rl_basic_word_break_characters = "\t\n@$><=;|&{( ";	completion_max_records = 1000;	/*	 * There is a variable rl_completion_query_items for this but apparently	 * it's not defined everywhere.	 */}/* The completion function. Acc. to readline spec this gets passed the text   entered to far and its start and end in the readline buffer. The return value   is some partially obscure list format that can be generated by the readline   libraries completion_matches() function, so we don't have to worry about it.*/static char **psql_completion(char *text, int start, int end){	/* This is the variable we'll return. */	char	  **matches = NULL;	/* These are going to contain some scannage of the input line. */	char	   *prev_wd,			   *prev2_wd,			   *prev3_wd,			   *prev4_wd,			   *prev5_wd;	static const char *const sql_commands[] = {		"ABORT", "ALTER", "ANALYZE", "BEGIN", "CHECKPOINT", "CLOSE", "CLUSTER", "COMMENT",		"COMMIT", "COPY", "CREATE", "DEALLOCATE", "DECLARE", "DELETE FROM", "DROP", "END", "EXECUTE",		"EXPLAIN", "FETCH", "GRANT", "INSERT", "LISTEN", "LOAD", "LOCK", "MOVE", "NOTIFY",		"PREPARE", "REINDEX", "RELEASE", "RESET", "REVOKE", "ROLLBACK", "SAVEPOINT",		"SELECT", "SET", "SHOW", "START", "TRUNCATE", "UNLISTEN", "UPDATE", "VACUUM", NULL	};	static const char *const backslash_commands[] = {		"\\a", "\\connect", "\\C", "\\cd", "\\copy", "\\copyright",		"\\d", "\\da", "\\db", "\\dc", "\\dC", "\\dd", "\\dD", "\\df",		"\\dg", "\\di", "\\dl", "\\dn", "\\do", "\\dp", "\\ds", "\\dS",		"\\dt", "\\dT", "\\dv", "\\du",		"\\e", "\\echo", "\\encoding",		"\\f", "\\g", "\\h", "\\help", "\\H", "\\i", "\\l",		"\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink",		"\\o", "\\p", "\\pset", "\\q", "\\qecho", "\\r", "\\set", "\\t", "\\T",		"\\timing", "\\unset", "\\x", "\\w", "\\z", "\\!", NULL	};	(void) end;					/* not used */#ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER	rl_completion_append_character = ' ';#endif	/* Clear a few things. */	completion_charp = NULL;	completion_charpp = NULL;	completion_info_charp = NULL;	/*	 * Scan the input line before our current position for the last four	 * words. According to those we'll make some smart decisions on what the	 * user is probably intending to type. TODO: Use strtokx() to do this.	 */	prev_wd = previous_word(start, 0);	prev2_wd = previous_word(start, 1);	prev3_wd = previous_word(start, 2);	prev4_wd = previous_word(start, 3);	prev5_wd = previous_word(start, 4);	/* If a backslash command was started, continue */	if (text[0] == '\\')		COMPLETE_WITH_LIST(backslash_commands);	/* If no previous word, suggest one of the basic sql commands */	else if (!prev_wd)		COMPLETE_WITH_LIST(sql_commands);/* CREATE or DROP but not ALTER (TABLE|DOMAIN|GROUP) sth DROP */	/* complete with something you can create or drop */	else if (pg_strcasecmp(prev_wd, "CREATE") == 0 ||			 (pg_strcasecmp(prev_wd, "DROP") == 0 &&			  pg_strcasecmp(prev3_wd, "TABLE") != 0 &&			  pg_strcasecmp(prev3_wd, "DOMAIN") != 0 &&			  pg_strcasecmp(prev3_wd, "GROUP") != 0))		matches = completion_matches(text, create_command_generator);/* ALTER */	/*	 * complete with what you can alter (TABLE, GROUP, USER, ...) unless we're	 * in ALTER TABLE sth ALTER	 */	else if (pg_strcasecmp(prev_wd, "ALTER") == 0 &&			 pg_strcasecmp(prev3_wd, "TABLE") != 0)	{		static const char *const list_ALTER[] =		{"AGGREGATE", "CONVERSION", "DATABASE", "DOMAIN", "FUNCTION",			"GROUP", "INDEX", "LANGUAGE", "OPERATOR", "ROLE", "SCHEMA", "SEQUENCE", "TABLE",		"TABLESPACE", "TRIGGER", "TYPE", "USER", NULL};		COMPLETE_WITH_LIST(list_ALTER);	}	/* ALTER AGGREGATE,FUNCTION <name> */	else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&			 (pg_strcasecmp(prev2_wd, "AGGREGATE") == 0 ||			  pg_strcasecmp(prev2_wd, "FUNCTION") == 0))	{		static const char *const list_ALTERAGG[] =		{"OWNER TO", "RENAME TO", "SET SCHEMA", NULL};		COMPLETE_WITH_LIST(list_ALTERAGG);	}	/* ALTER CONVERSION,SCHEMA <name> */	else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&			 (pg_strcasecmp(prev2_wd, "CONVERSION") == 0 ||			  pg_strcasecmp(prev2_wd, "SCHEMA") == 0))	{		static const char *const list_ALTERGEN[] =		{"OWNER TO", "RENAME TO", NULL};		COMPLETE_WITH_LIST(list_ALTERGEN);	}	/* ALTER DATABASE <name> */	else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&			 pg_strcasecmp(prev2_wd, "DATABASE") == 0)	{		static const char *const list_ALTERDATABASE[] =		{"RESET", "SET", "OWNER TO", "RENAME TO", "CONNECTION LIMIT", NULL};		COMPLETE_WITH_LIST(list_ALTERDATABASE);	}	/* ALTER INDEX <name> */	else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&			 pg_strcasecmp(prev2_wd, "INDEX") == 0)	{		static const char *const list_ALTERINDEX[] =		{"SET TABLESPACE", "OWNER TO", "RENAME TO", NULL};		COMPLETE_WITH_LIST(list_ALTERINDEX);	}	/* ALTER LANGUAGE <name> */	else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&			 pg_strcasecmp(prev2_wd, "LANGUAGE") == 0)		COMPLETE_WITH_CONST("RENAME TO");	/* ALTER USER,ROLE <name> */	else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&			 (pg_strcasecmp(prev2_wd, "USER") == 0 ||			  pg_strcasecmp(prev2_wd, "ROLE") == 0))	{		static const char *const list_ALTERUSER[] =		{"ENCRYPTED", "UNENCRYPTED", "CREATEDB", "NOCREATEDB", "CREATEUSER",			"NOCREATEUSER", "CREATEROLE", "NOCREATEROLE", "INHERIT", "NOINHERIT",			"LOGIN", "NOLOGIN", "CONNECTION LIMIT", "VALID UNTIL", "RENAME TO",		"SUPERUSER", "NOSUPERUSER", "SET", "RESET", NULL};		COMPLETE_WITH_LIST(list_ALTERUSER);	}	/* complete ALTER USER,ROLE <name> ENCRYPTED,UNENCRYPTED with PASSWORD */	else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 &&			 (pg_strcasecmp(prev3_wd, "ROLE") == 0 || pg_strcasecmp(prev3_wd, "USER") == 0) &&			 (pg_strcasecmp(prev_wd, "ENCRYPTED") == 0 || pg_strcasecmp(prev_wd, "UNENCRYPTED") == 0))	{		COMPLETE_WITH_CONST("PASSWORD");	}	/* ALTER DOMAIN <name> */	else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&			 pg_strcasecmp(prev2_wd, "DOMAIN") == 0)	{		static const char *const list_ALTERDOMAIN[] =		{"ADD", "DROP", "OWNER TO", "SET", NULL};		COMPLETE_WITH_LIST(list_ALTERDOMAIN);	}	/* ALTER DOMAIN <sth> DROP */	else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 &&			 pg_strcasecmp(prev3_wd, "DOMAIN") == 0 &&			 pg_strcasecmp(prev_wd, "DROP") == 0)	{		static const char *const list_ALTERDOMAIN2[] =		{"CONSTRAINT", "DEFAULT", "NOT NULL", NULL};		COMPLETE_WITH_LIST(list_ALTERDOMAIN2);	}	/* ALTER DOMAIN <sth> SET */	else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 &&			 pg_strcasecmp(prev3_wd, "DOMAIN") == 0 &&			 pg_strcasecmp(prev_wd, "SET") == 0)	{		static const char *const list_ALTERDOMAIN3[] =		{"DEFAULT", "NOT NULL", "SCHEMA", NULL};		COMPLETE_WITH_LIST(list_ALTERDOMAIN3);	}	/* ALTER SEQUENCE <name> */	else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&			 pg_strcasecmp(prev2_wd, "SEQUENCE") == 0)	{		static const char *const list_ALTERSEQUENCE[] =		{"INCREMENT", "MINVALUE", "MAXVALUE", "RESTART", "NO", "CACHE", "CYCLE",		"SET SCHEMA", NULL};		COMPLETE_WITH_LIST(list_ALTERSEQUENCE);	}	/* ALTER SEQUENCE <name> NO */	else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 &&			 pg_strcasecmp(prev3_wd, "SEQUENCE") == 0 &&			 pg_strcasecmp(prev_wd, "NO") == 0)	{		static const char *const list_ALTERSEQUENCE2[] =		{"MINVALUE", "MAXVALUE", "CYCLE", NULL};		COMPLETE_WITH_LIST(list_ALTERSEQUENCE2);	}	/* ALTER TRIGGER <name>, add ON */	else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&			 pg_strcasecmp(prev2_wd, "TRIGGER") == 0)		COMPLETE_WITH_CONST("ON");	else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 &&			 pg_strcasecmp(prev3_wd, "TRIGGER") == 0)	{		completion_info_charp = prev2_wd;		COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_trigger);	}	/*	 * If we have ALTER TRIGGER <sth> ON, then add the correct tablename	 */	else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 &&			 pg_strcasecmp(prev3_wd, "TRIGGER") == 0 &&			 pg_strcasecmp(prev_wd, "ON") == 0)		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);	/* ALTER TRIGGER <name> ON <name> */	else if (pg_strcasecmp(prev4_wd, "TRIGGER") == 0 &&			 pg_strcasecmp(prev2_wd, "ON") == 0)		COMPLETE_WITH_CONST("RENAME TO");	/*	 * If we detect ALTER TABLE <name>, suggest either ADD, DROP, ALTER,	 * RENAME, CLUSTER ON or OWNER	 */	else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&			 pg_strcasecmp(prev2_wd, "TABLE") == 0)	{		static const char *const list_ALTER2[] =		{"ADD", "ALTER", "CLUSTER ON", "DROP", "RENAME", "OWNER TO",		"SET", NULL};		COMPLETE_WITH_LIST(list_ALTER2);	}	/* If we have TABLE <sth> ALTER|RENAME, provide list of columns */	else if (pg_strcasecmp(prev3_wd, "TABLE") == 0 &&			 (pg_strcasecmp(prev_wd, "ALTER") == 0 ||			  pg_strcasecmp(prev_wd, "RENAME") == 0))		COMPLETE_WITH_ATTR(prev2_wd);	/* ALTER TABLE xxx RENAME yyy */	else if (pg_strcasecmp(prev4_wd, "TABLE") == 0 &&			 pg_strcasecmp(prev2_wd, "RENAME") == 0 &&			 pg_strcasecmp(prev_wd, "TO") != 0)		COMPLETE_WITH_CONST("TO");	/* If we have TABLE <sth> DROP, provide COLUMN or CONSTRAINT */	else if (pg_strcasecmp(prev3_wd, "TABLE") == 0 &&			 pg_strcasecmp(prev_wd, "DROP") == 0)	{		static const char *const list_TABLEDROP[] =		{"COLUMN", "CONSTRAINT", NULL};		COMPLETE_WITH_LIST(list_TABLEDROP);	}	/* If we have TABLE <sth> DROP COLUMN, provide list of columns */	else if (pg_strcasecmp(prev4_wd, "TABLE") == 0 &&			 pg_strcasecmp(prev2_wd, "DROP") == 0 &&			 pg_strcasecmp(prev_wd, "COLUMN") == 0)		COMPLETE_WITH_ATTR(prev3_wd);	/* ALTER TABLE ALTER [COLUMN] <foo> */	else if ((pg_strcasecmp(prev3_wd, "ALTER") == 0 &&

⌨️ 快捷键说明

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