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