pg_reorg version 1.1.0.
- Add wait-timeout option and use SET statement_timeout instead of NOWAIT. This can avoid infinite NOWAIT loops to reorganize heavily accessed tables. - Support native build with MSVC on Windows.
This commit is contained in:
		
							
								
								
									
										687
									
								
								bin/pgut/pgut-fe.c
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										687
									
								
								bin/pgut/pgut-fe.c
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,687 @@ | ||||
| /*------------------------------------------------------------------------- | ||||
|  * | ||||
|  * pgut-fe.c | ||||
|  * | ||||
|  * Copyright (c) 2009-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION | ||||
|  * | ||||
|  *------------------------------------------------------------------------- | ||||
|  */ | ||||
|  | ||||
| #define FRONTEND | ||||
| #include "pgut-fe.h" | ||||
|  | ||||
| #ifdef HAVE_GETOPT_H | ||||
| #include <getopt.h> | ||||
| #else | ||||
| #include <getopt_long.h> | ||||
| #endif | ||||
|  | ||||
| char	   *dbname = NULL; | ||||
| char	   *host = NULL; | ||||
| char	   *port = NULL; | ||||
| char	   *username = NULL; | ||||
| char	   *password = NULL; | ||||
| YesNo		prompt_password = DEFAULT; | ||||
|  | ||||
| PGconn	   *connection = NULL; | ||||
|  | ||||
| static bool parse_pair(const char buffer[], char key[], char value[]); | ||||
| static char *get_username(void); | ||||
|  | ||||
| /* | ||||
|  * the result is also available with the global variable 'connection'. | ||||
|  */ | ||||
| void | ||||
| reconnect(int elevel) | ||||
| { | ||||
| 	StringInfoData	buf; | ||||
| 	char		   *new_password; | ||||
|  | ||||
| 	disconnect(); | ||||
| 	initStringInfo(&buf); | ||||
| 	if (dbname && dbname[0]) | ||||
| 		appendStringInfo(&buf, "dbname=%s ", dbname); | ||||
| 	if (host && host[0]) | ||||
| 		appendStringInfo(&buf, "host=%s ", host); | ||||
| 	if (port && port[0]) | ||||
| 		appendStringInfo(&buf, "port=%s ", port); | ||||
| 	if (username && username[0]) | ||||
| 		appendStringInfo(&buf, "username=%s ", username); | ||||
| 	if (password && password[0]) | ||||
| 		appendStringInfo(&buf, "password=%s ", password); | ||||
|  | ||||
| 	connection = pgut_connect(buf.data, prompt_password, elevel); | ||||
|  | ||||
| 	/* update password */ | ||||
| 	if (connection) | ||||
| 	{ | ||||
| 		new_password = PQpass(connection); | ||||
| 		if (new_password && (!password || strcmp(new_password, password))) | ||||
| 		{ | ||||
| 			free(password); | ||||
| 			password = new_password; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	termStringInfo(&buf); | ||||
| } | ||||
|  | ||||
| void | ||||
| disconnect(void) | ||||
| { | ||||
| 	if (connection) | ||||
| 	{ | ||||
| 		pgut_disconnect(connection); | ||||
| 		connection = NULL; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static void | ||||
| option_from_env(pgut_option options[]) | ||||
| { | ||||
| 	size_t	i; | ||||
|  | ||||
| 	for (i = 0; options && options[i].type; i++) | ||||
| 	{ | ||||
| 		pgut_option	   *opt = &options[i]; | ||||
| 		char			name[256]; | ||||
| 		size_t			j; | ||||
| 		const char	   *s; | ||||
| 		const char	   *value; | ||||
|  | ||||
| 		if (opt->source > SOURCE_ENV || | ||||
| 			opt->allowed == SOURCE_DEFAULT || opt->allowed > SOURCE_ENV) | ||||
| 			continue; | ||||
|  | ||||
| 		for (s = opt->lname, j = 0; *s && j < lengthof(name) - 1; s++, j++) | ||||
| 		{ | ||||
| 			if (strchr("-_ ", *s)) | ||||
| 				name[j] = '_';	/* - to _ */ | ||||
| 			else | ||||
| 				name[j] = toupper(*s); | ||||
| 		} | ||||
| 		name[j] = '\0'; | ||||
|  | ||||
| 		if ((value = getenv(name)) != NULL) | ||||
| 			pgut_setopt(opt, value, SOURCE_ENV); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* compare two strings ignore cases and ignore -_ */ | ||||
| bool | ||||
| pgut_keyeq(const char *lhs, const char *rhs) | ||||
| { | ||||
| 	for (; *lhs && *rhs; lhs++, rhs++) | ||||
| 	{ | ||||
| 		if (strchr("-_ ", *lhs)) | ||||
| 		{ | ||||
| 			if (!strchr("-_ ", *rhs)) | ||||
| 				return false; | ||||
| 		} | ||||
| 		else if (ToLower(*lhs) != ToLower(*rhs)) | ||||
| 			return false; | ||||
| 	} | ||||
|  | ||||
| 	return *lhs == '\0' && *rhs == '\0'; | ||||
| } | ||||
|  | ||||
| void | ||||
| pgut_setopt(pgut_option *opt, const char *optarg, pgut_optsrc src) | ||||
| { | ||||
| 	const char	  *message; | ||||
|  | ||||
| 	if (opt == NULL) | ||||
| 	{ | ||||
| 		fprintf(stderr, "Try \"%s --help\" for more information.\n", PROGRAM_NAME); | ||||
| 		exit(EINVAL); | ||||
| 	} | ||||
|  | ||||
| 	if (opt->source > src) | ||||
| 	{ | ||||
| 		/* high prior value has been set already. */ | ||||
| 		return; | ||||
| 	} | ||||
| 	else if (src >= SOURCE_CMDLINE && opt->source >= src) | ||||
| 	{ | ||||
| 		/* duplicated option in command line */ | ||||
| 		message = "specified only once"; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		/* can be overwritten if non-command line source */ | ||||
| 		opt->source = src; | ||||
|  | ||||
| 		switch (opt->type) | ||||
| 		{ | ||||
| 			case 'b': | ||||
| 			case 'B': | ||||
| 				if (optarg == NULL) | ||||
| 				{ | ||||
| 					*((bool *) opt->var) = (opt->type == 'b'); | ||||
| 					return; | ||||
| 				} | ||||
| 				else if (parse_bool(optarg, (bool *) opt->var)) | ||||
| 				{ | ||||
| 					return; | ||||
| 				} | ||||
| 				message = "a boolean"; | ||||
| 				break; | ||||
| 			case 'f': | ||||
| 				((pgut_optfn) opt->var)(opt, optarg); | ||||
| 				return; | ||||
| 			case 'i': | ||||
| 				if (parse_int32(optarg, opt->var)) | ||||
| 					return; | ||||
| 				message = "a 32bit signed integer"; | ||||
| 				break; | ||||
| 			case 'u': | ||||
| 				if (parse_uint32(optarg, opt->var)) | ||||
| 					return; | ||||
| 				message = "a 32bit unsigned integer"; | ||||
| 				break; | ||||
| 			case 'I': | ||||
| 				if (parse_int64(optarg, opt->var)) | ||||
| 					return; | ||||
| 				message = "a 64bit signed integer"; | ||||
| 				break; | ||||
| 			case 'U': | ||||
| 				if (parse_uint64(optarg, opt->var)) | ||||
| 					return; | ||||
| 				message = "a 64bit unsigned integer"; | ||||
| 				break; | ||||
| 			case 's': | ||||
| 				if (opt->source != SOURCE_DEFAULT) | ||||
| 					free(*(char **) opt->var); | ||||
| 				*(char **) opt->var = pgut_strdup(optarg); | ||||
| 				return; | ||||
| 			case 't': | ||||
| 				if (parse_time(optarg, opt->var)) | ||||
| 					return; | ||||
| 				message = "a time"; | ||||
| 				break; | ||||
| 			case 'y': | ||||
| 			case 'Y': | ||||
| 				if (optarg == NULL) | ||||
| 				{ | ||||
| 					*(YesNo *) opt->var = (opt->type == 'y' ? YES : NO); | ||||
| 					return; | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					bool	value; | ||||
| 					if (parse_bool(optarg, &value)) | ||||
| 					{ | ||||
| 						*(YesNo *) opt->var = (value ? YES : NO); | ||||
| 						return; | ||||
| 					} | ||||
| 				} | ||||
| 				message = "a boolean"; | ||||
| 				break; | ||||
| 			default: | ||||
| 				ereport(ERROR, | ||||
| 					(errcode(EINVAL), | ||||
| 					 errmsg("invalid option type: %c", opt->type))); | ||||
| 				return;	/* keep compiler quiet */ | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (isprint(opt->sname)) | ||||
| 		ereport(ERROR, | ||||
| 			(errcode(EINVAL), | ||||
| 			 errmsg("option -%c, --%s should be %s: '%s'", | ||||
| 				opt->sname, opt->lname, message, optarg))); | ||||
| 	else | ||||
| 		ereport(ERROR, | ||||
| 			(errcode(EINVAL), | ||||
| 			 errmsg("option --%s should be %s: '%s'", | ||||
| 				opt->lname, message, optarg))); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Get configuration from configuration file. | ||||
|  */ | ||||
| void | ||||
| pgut_readopt(const char *path, pgut_option options[], int elevel) | ||||
| { | ||||
| 	FILE   *fp; | ||||
| 	char	buf[1024]; | ||||
| 	char	key[1024]; | ||||
| 	char	value[1024]; | ||||
|  | ||||
| 	if (!options) | ||||
| 		return; | ||||
|  | ||||
| 	if ((fp = pgut_fopen(path, "Rt")) == NULL) | ||||
| 		return; | ||||
|  | ||||
| 	while (fgets(buf, lengthof(buf), fp)) | ||||
| 	{ | ||||
| 		size_t		i; | ||||
|  | ||||
| 		for (i = strlen(buf); i > 0 && IsSpace(buf[i - 1]); i--) | ||||
| 			buf[i - 1] = '\0'; | ||||
|  | ||||
| 		if (parse_pair(buf, key, value)) | ||||
| 		{ | ||||
| 			for (i = 0; options[i].type; i++) | ||||
| 			{ | ||||
| 				pgut_option *opt = &options[i]; | ||||
|  | ||||
| 				if (pgut_keyeq(key, opt->lname)) | ||||
| 				{ | ||||
| 					if (opt->allowed == SOURCE_DEFAULT || | ||||
| 						opt->allowed > SOURCE_FILE) | ||||
| 						elog(elevel, "option %s cannot specified in file", opt->lname); | ||||
| 					else if (opt->source <= SOURCE_FILE) | ||||
| 						pgut_setopt(opt, value, SOURCE_FILE); | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| 			if (!options[i].type) | ||||
| 				elog(elevel, "invalid option \"%s\"", key); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	fclose(fp); | ||||
| } | ||||
|  | ||||
| static const char * | ||||
| skip_space(const char *str, const char *line) | ||||
| { | ||||
| 	while (IsSpace(*str)) { str++; } | ||||
| 	return str; | ||||
| } | ||||
|  | ||||
| static const char * | ||||
| get_next_token(const char *src, char *dst, const char *line) | ||||
| { | ||||
| 	const char *s; | ||||
| 	size_t		i; | ||||
| 	size_t		j; | ||||
|  | ||||
| 	if ((s = skip_space(src, line)) == NULL) | ||||
| 		return NULL; | ||||
|  | ||||
| 	/* parse quoted string */ | ||||
| 	if (*s == '\'') | ||||
| 	{ | ||||
| 		s++; | ||||
| 		for (i = 0, j = 0; s[i] != '\0'; i++) | ||||
| 		{ | ||||
| 			if (s[i] == '\\') | ||||
| 			{ | ||||
| 				i++; | ||||
| 				switch (s[i]) | ||||
| 				{ | ||||
| 					case 'b': | ||||
| 						dst[j] = '\b'; | ||||
| 						break; | ||||
| 					case 'f': | ||||
| 						dst[j] = '\f'; | ||||
| 						break; | ||||
| 					case 'n': | ||||
| 						dst[j] = '\n'; | ||||
| 						break; | ||||
| 					case 'r': | ||||
| 						dst[j] = '\r'; | ||||
| 						break; | ||||
| 					case 't': | ||||
| 						dst[j] = '\t'; | ||||
| 						break; | ||||
| 					case '0': | ||||
| 					case '1': | ||||
| 					case '2': | ||||
| 					case '3': | ||||
| 					case '4': | ||||
| 					case '5': | ||||
| 					case '6': | ||||
| 					case '7': | ||||
| 						{ | ||||
| 							int			k; | ||||
| 							long		octVal = 0; | ||||
|  | ||||
| 							for (k = 0; | ||||
| 								 s[i + k] >= '0' && s[i + k] <= '7' && k < 3; | ||||
| 									 k++) | ||||
| 								octVal = (octVal << 3) + (s[i + k] - '0'); | ||||
| 							i += k - 1; | ||||
| 							dst[j] = ((char) octVal); | ||||
| 						} | ||||
| 						break; | ||||
| 					default: | ||||
| 						dst[j] = s[i]; | ||||
| 						break; | ||||
| 				} | ||||
| 			} | ||||
| 			else if (s[i] == '\'') | ||||
| 			{ | ||||
| 				i++; | ||||
| 				/* doubled quote becomes just one quote */ | ||||
| 				if (s[i] == '\'') | ||||
| 					dst[j] = s[i]; | ||||
| 				else | ||||
| 					break; | ||||
| 			} | ||||
| 			else | ||||
| 				dst[j] = s[i]; | ||||
| 			j++; | ||||
| 		} | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		i = j = strcspn(s, "# \n\r\t\v"); | ||||
| 		memcpy(dst, s, j); | ||||
| 	} | ||||
|  | ||||
| 	dst[j] = '\0'; | ||||
| 	return s + i; | ||||
| } | ||||
|  | ||||
| static bool | ||||
| parse_pair(const char buffer[], char key[], char value[]) | ||||
| { | ||||
| 	const char *start; | ||||
| 	const char *end; | ||||
|  | ||||
| 	key[0] = value[0] = '\0'; | ||||
|  | ||||
| 	/* | ||||
| 	 * parse key | ||||
| 	 */ | ||||
| 	start = buffer; | ||||
| 	if ((start = skip_space(start, buffer)) == NULL) | ||||
| 		return false; | ||||
|  | ||||
| 	end = start + strcspn(start, "=# \n\r\t\v"); | ||||
|  | ||||
| 	/* skip blank buffer */ | ||||
| 	if (end - start <= 0) | ||||
| 	{ | ||||
| 		if (*start == '=') | ||||
| 			elog(WARNING, "syntax error in \"%s\"", buffer); | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	/* key found */ | ||||
| 	strncpy(key, start, end - start); | ||||
| 	key[end - start] = '\0'; | ||||
|  | ||||
| 	/* find key and value split char */ | ||||
| 	if ((start = skip_space(end, buffer)) == NULL) | ||||
| 		return false; | ||||
|  | ||||
| 	if (*start != '=') | ||||
| 	{ | ||||
| 		elog(WARNING, "syntax error in \"%s\"", buffer); | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	start++; | ||||
|  | ||||
| 	/* | ||||
| 	 * parse value | ||||
| 	 */ | ||||
| 	if ((end = get_next_token(start, value, buffer)) == NULL) | ||||
| 		return false; | ||||
|  | ||||
| 	if ((start = skip_space(end, buffer)) == NULL) | ||||
| 		return false; | ||||
|  | ||||
| 	if (*start != '\0' && *start != '#') | ||||
| 	{ | ||||
| 		elog(WARNING, "syntax error in \"%s\"", buffer); | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * execute - Execute a SQL and return the result. | ||||
|  */ | ||||
| PGresult * | ||||
| execute(const char *query, int nParams, const char **params) | ||||
| { | ||||
| 	return pgut_execute(connection, query, nParams, params); | ||||
| } | ||||
|  | ||||
| PGresult * | ||||
| execute_elevel(const char *query, int nParams, const char **params, int elevel) | ||||
| { | ||||
| 	return pgut_execute_elevel(connection, query, nParams, params, elevel); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * command - Execute a SQL and discard the result. | ||||
|  */ | ||||
| ExecStatusType | ||||
| command(const char *query, int nParams, const char **params) | ||||
| { | ||||
| 	return pgut_command(connection, query, nParams, params); | ||||
| } | ||||
|  | ||||
| static void | ||||
| set_elevel(pgut_option *opt, const char *arg) | ||||
| { | ||||
| 	pgut_log_level = parse_elevel(arg); | ||||
| } | ||||
|  | ||||
| static pgut_option default_options[] = | ||||
| { | ||||
| 	{ 'b', 'e', "echo"			, &pgut_echo }, | ||||
| 	{ 'f', 'E', "elevel"		, set_elevel }, | ||||
| 	{ 's', 'd', "dbname"		, &dbname }, | ||||
| 	{ 's', 'h', "host"			, &host }, | ||||
| 	{ 's', 'p', "port"			, &port }, | ||||
| 	{ 's', 'U', "username"		, &username }, | ||||
| 	{ 'y', 'w', "no-password"	, &prompt_password }, | ||||
| 	{ 'Y', 'W', "password"		, &prompt_password }, | ||||
| 	{ 0 } | ||||
| }; | ||||
|  | ||||
| static size_t | ||||
| option_length(const pgut_option opts[]) | ||||
| { | ||||
| 	size_t	len; | ||||
| 	for (len = 0; opts && opts[len].type; len++) { } | ||||
| 	return len; | ||||
| } | ||||
|  | ||||
| static pgut_option * | ||||
| option_find(int c, pgut_option opts1[], pgut_option opts2[]) | ||||
| { | ||||
| 	size_t	i; | ||||
|  | ||||
| 	for (i = 0; opts1 && opts1[i].type; i++) | ||||
| 		if (opts1[i].sname == c) | ||||
| 			return &opts1[i]; | ||||
| 	for (i = 0; opts2 && opts2[i].type; i++) | ||||
| 		if (opts2[i].sname == c) | ||||
| 			return &opts2[i]; | ||||
|  | ||||
| 	return NULL;	/* not found */ | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Returns the current user name. | ||||
|  */ | ||||
| static char * | ||||
| get_username(void) | ||||
| { | ||||
| 	char *ret; | ||||
|  | ||||
| #ifndef WIN32 | ||||
| 	struct passwd *pw; | ||||
|  | ||||
| 	pw = getpwuid(geteuid()); | ||||
| 	ret = (pw ? pw->pw_name : NULL); | ||||
| #else | ||||
| 	static char username[128];	/* remains after function execute */ | ||||
| 	DWORD		len = sizeof(username) - 1; | ||||
|  | ||||
| 	if (GetUserNameA(username, &len)) | ||||
| 		ret = username; | ||||
| 	else | ||||
| 	{ | ||||
| 		_dosmaperr(GetLastError()); | ||||
| 		ret = NULL; | ||||
| 	} | ||||
| #endif | ||||
|  | ||||
| 	if (ret == NULL) | ||||
| 		ereport(ERROR, | ||||
| 			(errcode_errno(), | ||||
| 			 errmsg("could not get current user name: "))); | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| static int | ||||
| option_has_arg(char type) | ||||
| { | ||||
| 	switch (type) | ||||
| 	{ | ||||
| 		case 'b': | ||||
| 		case 'B': | ||||
| 		case 'y': | ||||
| 		case 'Y': | ||||
| 			return no_argument; | ||||
| 		default: | ||||
| 			return required_argument; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static void | ||||
| option_copy(struct option dst[], const pgut_option opts[], size_t len) | ||||
| { | ||||
| 	size_t	i; | ||||
|  | ||||
| 	for (i = 0; i < len; i++) | ||||
| 	{ | ||||
| 		dst[i].name = opts[i].lname; | ||||
| 		dst[i].has_arg = option_has_arg(opts[i].type); | ||||
| 		dst[i].flag = NULL; | ||||
| 		dst[i].val = opts[i].sname; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static struct option * | ||||
| option_merge(const pgut_option opts1[], const pgut_option opts2[]) | ||||
| { | ||||
| 	struct option *result; | ||||
| 	size_t	len1 = option_length(opts1); | ||||
| 	size_t	len2 = option_length(opts2); | ||||
| 	size_t	n = len1 + len2; | ||||
|  | ||||
| 	result = pgut_newarray(struct option, n + 1); | ||||
| 	option_copy(result, opts1, len1); | ||||
| 	option_copy(result + len1, opts2, len2); | ||||
| 	memset(&result[n], 0, sizeof(pgut_option)); | ||||
|  | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| static char * | ||||
| longopts_to_optstring(const struct option opts[]) | ||||
| { | ||||
| 	size_t	len; | ||||
| 	char   *result; | ||||
| 	char   *s; | ||||
|  | ||||
| 	for (len = 0; opts[len].name; len++) { } | ||||
| 	result = pgut_malloc(len * 2 + 1); | ||||
|  | ||||
| 	s = result; | ||||
| 	for (len = 0; opts[len].name; len++) | ||||
| 	{ | ||||
| 		if (!isprint(opts[len].val)) | ||||
| 			continue; | ||||
| 		*s++ = opts[len].val; | ||||
| 		if (opts[len].has_arg != no_argument) | ||||
| 			*s++ = ':'; | ||||
| 	} | ||||
| 	*s = '\0'; | ||||
|  | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| int | ||||
| pgut_getopt(int argc, char **argv, pgut_option options[]) | ||||
| { | ||||
| 	int					c; | ||||
| 	int					optindex = 0; | ||||
| 	char			   *optstring; | ||||
| 	struct option	   *longopts; | ||||
| 	pgut_option		   *opt; | ||||
|  | ||||
| 	pgut_init(argc, argv); | ||||
|  | ||||
| 	/* Help message and version are handled at first. */ | ||||
| 	if (argc > 1) | ||||
| 	{ | ||||
| 		if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0) | ||||
| 		{ | ||||
| 			help(true); | ||||
| 			exit(1); | ||||
| 		} | ||||
| 		if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0) | ||||
| 		{ | ||||
| 			fprintf(stderr, "%s %s\n", PROGRAM_NAME, PROGRAM_VERSION); | ||||
| 			exit(1); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/* Merge default and user options. */ | ||||
| 	longopts = option_merge(default_options, options); | ||||
| 	optstring = longopts_to_optstring(longopts); | ||||
|  | ||||
| 	/* Assign named options */ | ||||
| 	while ((c = getopt_long(argc, argv, optstring, longopts, &optindex)) != -1) | ||||
| 	{ | ||||
| 		opt = option_find(c, default_options, options); | ||||
| 		pgut_setopt(opt, optarg, SOURCE_CMDLINE); | ||||
| 	} | ||||
|  | ||||
| 	/* Read environment variables */ | ||||
| 	option_from_env(options); | ||||
| 	(void) (dbname || | ||||
| 	(dbname = getenv("PGDATABASE")) || | ||||
| 	(dbname = getenv("PGUSER")) || | ||||
| 	(dbname = get_username())); | ||||
|  | ||||
| 	return optind; | ||||
| } | ||||
|  | ||||
| void | ||||
| help(bool details) | ||||
| { | ||||
| 	pgut_help(details); | ||||
|  | ||||
| 	if (details) | ||||
| 	{ | ||||
| 		printf("\nConnection options:\n"); | ||||
| 		printf("  -d, --dbname=DBNAME       database to connect\n"); | ||||
| 		printf("  -h, --host=HOSTNAME       database server host or socket directory\n"); | ||||
| 		printf("  -p, --port=PORT           database server port\n"); | ||||
| 		printf("  -U, --username=USERNAME   user name to connect as\n"); | ||||
| 		printf("  -w, --no-password         never prompt for password\n"); | ||||
| 		printf("  -W, --password            force password prompt\n"); | ||||
| 	} | ||||
|  | ||||
| 	printf("\nGeneric options:\n"); | ||||
| 	if (details) | ||||
| 	{ | ||||
| 		printf("  -e, --echo                echo queries\n"); | ||||
| 		printf("  -E, --elevel=LEVEL        set output message level\n"); | ||||
| 	} | ||||
| 	printf("  --help                    show this help, then exit\n"); | ||||
| 	printf("  --version                 output version information, then exit\n"); | ||||
|  | ||||
| 	if (details && (PROGRAM_URL || PROGRAM_EMAIL)) | ||||
| 	{ | ||||
| 		printf("\n"); | ||||
| 		if (PROGRAM_URL) | ||||
| 			printf("Read the website for details. <%s>\n", PROGRAM_URL); | ||||
| 		if (PROGRAM_EMAIL) | ||||
| 			printf("Report bugs to <%s>.\n", PROGRAM_EMAIL); | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										74
									
								
								bin/pgut/pgut-fe.h
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										74
									
								
								bin/pgut/pgut-fe.h
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,74 @@ | ||||
| /*------------------------------------------------------------------------- | ||||
|  * | ||||
|  * pgut-fe.h | ||||
|  * | ||||
|  * Copyright (c) 2009-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION | ||||
|  * | ||||
|  *------------------------------------------------------------------------- | ||||
|  */ | ||||
|  | ||||
| #ifndef PGUT_FE_H | ||||
| #define PGUT_FE_H | ||||
|  | ||||
| #include "pgut.h" | ||||
|  | ||||
| typedef enum pgut_optsrc | ||||
| { | ||||
| 	SOURCE_DEFAULT, | ||||
| 	SOURCE_ENV, | ||||
| 	SOURCE_FILE, | ||||
| 	SOURCE_CMDLINE, | ||||
| 	SOURCE_CONST | ||||
| } pgut_optsrc; | ||||
|  | ||||
| /* | ||||
|  * type: | ||||
|  *	b: bool (true) | ||||
|  *	B: bool (false) | ||||
|  *  f: pgut_optfn | ||||
|  *	i: 32bit signed integer | ||||
|  *	u: 32bit unsigned integer | ||||
|  *	I: 64bit signed integer | ||||
|  *	U: 64bit unsigned integer | ||||
|  *	s: string | ||||
|  *  t: time_t | ||||
|  *	y: YesNo (YES) | ||||
|  *	Y: YesNo (NO) | ||||
|  */ | ||||
| typedef struct pgut_option | ||||
| { | ||||
| 	char		type; | ||||
| 	char		sname;		/* short name */ | ||||
| 	const char *lname;		/* long name */ | ||||
| 	void	   *var;		/* pointer to variable */ | ||||
| 	pgut_optsrc	allowed;	/* allowed source */ | ||||
| 	pgut_optsrc	source;		/* actual source */ | ||||
| } pgut_option; | ||||
|  | ||||
| typedef void (*pgut_optfn) (pgut_option *opt, const char *arg); | ||||
|  | ||||
|  | ||||
| extern char	   *dbname; | ||||
| extern char	   *host; | ||||
| extern char	   *port; | ||||
| extern char	   *username; | ||||
| extern char	   *password; | ||||
| extern YesNo	prompt_password; | ||||
|  | ||||
| extern PGconn	   *connection; | ||||
|  | ||||
| extern void	pgut_help(bool details); | ||||
| extern void help(bool details); | ||||
|  | ||||
| extern void disconnect(void); | ||||
| extern void reconnect(int elevel); | ||||
| extern PGresult *execute(const char *query, int nParams, const char **params); | ||||
| extern PGresult *execute_elevel(const char *query, int nParams, const char **params, int elevel); | ||||
| extern ExecStatusType command(const char *query, int nParams, const char **params); | ||||
|  | ||||
| extern int pgut_getopt(int argc, char **argv, pgut_option options[]); | ||||
| extern void pgut_readopt(const char *path, pgut_option options[], int elevel); | ||||
| extern void pgut_setopt(pgut_option *opt, const char *optarg, pgut_optsrc src); | ||||
| extern bool pgut_keyeq(const char *lhs, const char *rhs); | ||||
|  | ||||
| #endif   /* PGUT_FE_H */ | ||||
							
								
								
									
										1394
									
								
								bin/pgut/pgut.c
									
									
									
									
									
								
							
							
						
						
									
										1394
									
								
								bin/pgut/pgut.c
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										146
									
								
								bin/pgut/pgut.h
									
									
									
									
									
								
							
							
						
						
									
										146
									
								
								bin/pgut/pgut.h
									
									
									
									
									
								
							| @ -11,23 +11,16 @@ | ||||
| #define PGUT_H | ||||
|  | ||||
| #include "c.h" | ||||
| #include <assert.h> | ||||
|  | ||||
| #ifndef WIN32 | ||||
| #include <sys/time.h> | ||||
| #include <unistd.h> | ||||
| #endif | ||||
|  | ||||
| #include "libpq-fe.h" | ||||
| #include "pqexpbuffer.h" | ||||
|  | ||||
| #include <assert.h> | ||||
| #include <sys/time.h> | ||||
|  | ||||
| #if !defined(C_H) && !defined(__cplusplus) | ||||
| #ifndef bool | ||||
| typedef char bool; | ||||
| #endif | ||||
| #ifndef true | ||||
| #define true	((bool) 1) | ||||
| #endif | ||||
| #ifndef false | ||||
| #define false	((bool) 0) | ||||
| #endif | ||||
| #endif | ||||
| #include "utils/elog.h" | ||||
|  | ||||
| #define INFINITE_STR		"INFINITE" | ||||
|  | ||||
| @ -38,40 +31,6 @@ typedef enum YesNo | ||||
| 	YES | ||||
| } YesNo; | ||||
|  | ||||
| typedef enum pgut_optsrc | ||||
| { | ||||
| 	SOURCE_DEFAULT, | ||||
| 	SOURCE_ENV, | ||||
| 	SOURCE_FILE, | ||||
| 	SOURCE_CMDLINE, | ||||
| 	SOURCE_CONST | ||||
| } pgut_optsrc; | ||||
|  | ||||
| /* | ||||
|  * type: | ||||
|  *	b: bool (true) | ||||
|  *	B: bool (false) | ||||
|  *  f: pgut_optfn | ||||
|  *	i: 32bit signed integer | ||||
|  *	u: 32bit unsigned integer | ||||
|  *	I: 64bit signed integer | ||||
|  *	U: 64bit unsigned integer | ||||
|  *	s: string | ||||
|  *  t: time_t | ||||
|  *	y: YesNo (YES) | ||||
|  *	Y: YesNo (NO) | ||||
|  */ | ||||
| typedef struct pgut_option | ||||
| { | ||||
| 	char		type; | ||||
| 	char		sname;		/* short name */ | ||||
| 	const char *lname;		/* long name */ | ||||
| 	void	   *var;		/* pointer to variable */ | ||||
| 	pgut_optsrc	allowed;	/* allowed source */ | ||||
| 	pgut_optsrc	source;		/* actual source */ | ||||
| } pgut_option; | ||||
|  | ||||
| typedef void (*pgut_optfn) (pgut_option *opt, const char *arg); | ||||
| typedef void (*pgut_atexit_callback)(bool fatal, void *userdata); | ||||
|  | ||||
| /* | ||||
| @ -82,52 +41,33 @@ extern const char  *PROGRAM_VERSION; | ||||
| extern const char  *PROGRAM_URL; | ||||
| extern const char  *PROGRAM_EMAIL; | ||||
|  | ||||
| extern void	pgut_help(bool details); | ||||
|  | ||||
| /* | ||||
|  * pgut framework variables and functions | ||||
|  */ | ||||
| extern const char  *dbname; | ||||
| extern const char  *host; | ||||
| extern const char  *port; | ||||
| extern const char  *username; | ||||
| extern char		   *password; | ||||
| extern bool			debug; | ||||
| extern bool			quiet; | ||||
| extern bool		interrupted; | ||||
| extern int		pgut_log_level; | ||||
| extern int		pgut_abort_level; | ||||
| extern bool		pgut_echo;	 | ||||
|  | ||||
| #ifndef PGUT_NO_PROMPT | ||||
| extern YesNo	prompt_password; | ||||
| #endif | ||||
|  | ||||
| extern PGconn	   *connection; | ||||
| extern bool			interrupted; | ||||
|  | ||||
| extern void help(bool details); | ||||
| extern int pgut_getopt(int argc, char **argv, pgut_option options[]); | ||||
| extern void pgut_readopt(const char *path, pgut_option options[], int elevel); | ||||
| extern void pgut_setopt(pgut_option *opt, const char *optarg, pgut_optsrc src); | ||||
| extern bool pgut_keyeq(const char *lhs, const char *rhs); | ||||
| extern void pgut_init(int argc, char **argv); | ||||
| extern void pgut_atexit_push(pgut_atexit_callback callback, void *userdata); | ||||
| extern void pgut_atexit_pop(pgut_atexit_callback callback, void *userdata); | ||||
| extern void pgut_putenv(const char *key, const char *value); | ||||
|  | ||||
| /* | ||||
|  * Database connections | ||||
|  */ | ||||
| extern PGconn *pgut_connect(int elevel); | ||||
| extern PGconn *pgut_connectdb(const char *conninfo, int elevel); | ||||
| extern PGconn *pgut_connect(const char *info, YesNo prompt, int elevel); | ||||
| extern void pgut_disconnect(PGconn *conn); | ||||
| extern PGresult *pgut_execute(PGconn* conn, const char *query, int nParams, const char **params, int elevel); | ||||
| extern ExecStatusType pgut_command(PGconn* conn, const char *query, int nParams, const char **params, int elevel); | ||||
| extern bool pgut_send(PGconn* conn, const char *query, int nParams, const char **params, int elevel); | ||||
| extern void pgut_disconnect_all(void); | ||||
| extern PGresult *pgut_execute(PGconn* conn, const char *query, int nParams, const char **params); | ||||
| PGresult *pgut_execute_elevel(PGconn* conn, const char *query, int nParams, const char **params, int elevel); | ||||
| extern ExecStatusType pgut_command(PGconn* conn, const char *query, int nParams, const char **params); | ||||
| extern bool pgut_commit(PGconn *conn); | ||||
| extern void pgut_rollback(PGconn *conn); | ||||
| extern bool pgut_send(PGconn* conn, const char *query, int nParams, const char **params); | ||||
| extern int pgut_wait(int num, PGconn *connections[], struct timeval *timeout); | ||||
|  | ||||
| extern PGconn *reconnect_elevel(int elevel); | ||||
| extern void reconnect(void); | ||||
| extern void disconnect(void); | ||||
| extern PGresult *execute_elevel(const char *query, int nParams, const char **params, int elevel); | ||||
| extern PGresult *execute(const char *query, int nParams, const char **params); | ||||
| extern void command(const char *query, int nParams, const char **params); | ||||
|  | ||||
| /* | ||||
|  * memory allocators | ||||
|  */ | ||||
| @ -139,37 +79,38 @@ extern char *strdup_trim(const char *str); | ||||
|  | ||||
| #define pgut_new(type)			((type *) pgut_malloc(sizeof(type))) | ||||
| #define pgut_newarray(type, n)	((type *) pgut_malloc(sizeof(type) * (n))) | ||||
| #define pgut_newvar(type, m, n)	((type *) pgut_malloc(offsetof(type, m) + (n))) | ||||
|  | ||||
| /* | ||||
|  * file operations | ||||
|  */ | ||||
| extern FILE *pgut_fopen(const char *path, const char *mode, bool missing_ok); | ||||
| extern void pgut_mkdir(const char *path); | ||||
| extern FILE *pgut_fopen(const char *path, const char *mode); | ||||
| extern bool pgut_mkdir(const char *path); | ||||
|  | ||||
| /* | ||||
|  * elog | ||||
|  */ | ||||
| #define LOG			(-4) | ||||
| #define INFO		(-3) | ||||
| #define NOTICE		(-2) | ||||
| #define WARNING		(-1) | ||||
| #define HELP		1 | ||||
| #define ERROR		2 | ||||
| #define FATAL		3 | ||||
| #define PANIC		4 | ||||
|  | ||||
| #define ERROR_SYSTEM			10	/* I/O or system error */ | ||||
| #define ERROR_NOMEM				11	/* memory exhausted */ | ||||
| #define ERROR_ARGS				12	/* some configurations are invalid */ | ||||
| #define ERROR_INTERRUPTED		13	/* interrupted by signal */ | ||||
| #define ERROR_PG_COMMAND		14	/* PostgreSQL query or command error */ | ||||
| #define ERROR_PG_CONNECT		15	/* PostgreSQL connection error */ | ||||
| #define E_PG_CONNECT	(-1)	/* PostgreSQL connection error */ | ||||
| #define E_PG_COMMAND	(-2)	/* PostgreSQL query or command error */ | ||||
|  | ||||
| #undef elog | ||||
| extern void | ||||
| elog(int elevel, const char *fmt, ...) | ||||
| __attribute__((format(printf, 2, 3))); | ||||
| #undef ereport | ||||
| #define ereport(elevel, rest) \ | ||||
| 	(pgut_errstart(elevel) ? (pgut_errfinish rest) : (void) 0) | ||||
|  | ||||
| extern void elog(int elevel, const char *fmt, ...) | ||||
| __attribute__((format(printf, 2, 3))); | ||||
| extern const char *format_elevel(int elevel); | ||||
| extern int parse_elevel(const char *value); | ||||
| extern int errcode_errno(void); | ||||
| extern bool log_required(int elevel, int log_min_level); | ||||
| extern bool pgut_errstart(int elevel); | ||||
| extern void pgut_errfinish(int dummy, ...); | ||||
| extern void pgut_error(int elevel, int code, const char *msg, const char *detail); | ||||
|  | ||||
| /* | ||||
|  * CHECK_FOR_INTERRUPTS | ||||
|  */ | ||||
| #undef CHECK_FOR_INTERRUPTS | ||||
| extern void CHECK_FOR_INTERRUPTS(void); | ||||
|  | ||||
| @ -209,6 +150,7 @@ extern void CHECK_FOR_INTERRUPTS(void); | ||||
| #define appendStringInfoChar	appendPQExpBufferChar | ||||
| #define appendBinaryStringInfo	appendBinaryPQExpBuffer | ||||
|  | ||||
| extern bool appendStringInfoVA(StringInfo str, const char *fmt, va_list args); | ||||
| extern int appendStringInfoFile(StringInfo str, FILE *fp); | ||||
| extern int appendStringInfoFd(StringInfo str, int fd); | ||||
|  | ||||
|  | ||||
		Reference in New Issue
	
	Block a user