Allow multiple --table options to be specified on the command-line.

Per Issue #18. SimpleStringList code borrowed from pg_dump and a
pending patch to add similar functionality to pg_restore,
clusterdb, vacuumdb, and reindexdb.

The error handling in reorg_one_table() could still be much improved,
so that an error processing a single table doesn't cause pg_reorg to
necessarily bail out and skip further tables, but I'll leave that for
another day.
This commit is contained in:
Josh Kupershmidt 2012-11-06 22:07:46 -07:00 committed by Daniele Varrazzo
parent ad00eb181d
commit ad75dcfbb1
5 changed files with 83 additions and 16 deletions

View File

@ -125,12 +125,12 @@ static bool sqlstate_equals(PGresult *res, const char *state)
return strcmp(PQresultErrorField(res, PG_DIAG_SQLSTATE), state) == 0;
}
static bool analyze = true;
static bool alldb = false;
static bool noorder = false;
static char *table = NULL;
static char *orderby = NULL;
static int wait_timeout = 60; /* in seconds */
static bool analyze = true;
static bool alldb = false;
static bool noorder = false;
static SimpleStringList table_list = {NULL, NULL};
static char *orderby = NULL;
static int wait_timeout = 60; /* in seconds */
/* buffer should have at least 11 bytes */
static char *
@ -143,7 +143,7 @@ utoa(unsigned int value, char *buffer)
static pgut_option options[] =
{
{ 'b', 'a', "all", &alldb },
{ 's', 't', "table", &table },
{ 'l', 't', "table", &table_list },
{ 'b', 'n', "no-order", &noorder },
{ 's', 'o', "order-by", &orderby },
{ 'i', 'T', "wait-timeout", &wait_timeout },
@ -154,7 +154,8 @@ static pgut_option options[] =
int
main(int argc, char *argv[])
{
int i;
int i;
SimpleStringListCell *cell;
i = pgut_getopt(argc, argv, options);
@ -170,7 +171,7 @@ main(int argc, char *argv[])
if (alldb)
{
if (table)
if (table_list.head != NULL)
ereport(ERROR,
(errcode(EINVAL),
errmsg("cannot repack a specific table in all databases")));
@ -178,10 +179,17 @@ main(int argc, char *argv[])
}
else
{
if (!repack_one_database(orderby, table))
if (table_list.head != NULL)
{
for (cell = table_list.head; cell; cell = cell->next)
{
repack_one_database(orderby, cell->val);
}
}
else if (!repack_one_database(orderby, NULL))
ereport(ERROR,
(errcode(ENOENT),
errmsg("%s is not installed", PROGRAM_NAME)));
(errcode(ENOENT),
errmsg("%s is not installed", PROGRAM_NAME)));
}
return 0;

View File

@ -144,9 +144,12 @@ pgut_setopt(pgut_option *opt, const char *optarg, pgut_optsrc src)
/* high prior value has been set already. */
return;
}
else if (src >= SOURCE_CMDLINE && opt->source >= src)
else if (src >= SOURCE_CMDLINE && opt->source >= src && opt->type != 'l')
{
/* duplicated option in command line */
/* duplicated option in command line -- don't worry if the option
* type is 'l' i.e. SimpleStringList, since we are allowed to have
* multiples of these.
*/
message = "specified only once";
}
else
@ -177,6 +180,10 @@ pgut_setopt(pgut_option *opt, const char *optarg, pgut_optsrc src)
return;
message = "a 32bit signed integer";
break;
case 'l':
message = "a List";
simple_string_list_append(opt->var, optarg);
return;
case 'u':
if (parse_uint32(optarg, opt->var))
return;

View File

@ -25,13 +25,14 @@ typedef enum pgut_optsrc
* type:
* b: bool (true)
* B: bool (false)
* f: pgut_optfn
* f: pgut_optfn
* i: 32bit signed integer
* l: StringList
* u: 32bit unsigned integer
* I: 64bit signed integer
* U: 64bit unsigned integer
* s: string
* t: time_t
* t: time_t
* y: YesNo (YES)
* Y: YesNo (NO)
*/

View File

@ -384,6 +384,40 @@ parse_time(const char *value, time_t *time)
return true;
}
/* Append the given string `val` to the `list` */
void
simple_string_list_append(SimpleStringList *list, const char *val)
{
SimpleStringListCell *cell;
/* this calculation correctly accounts for the null trailing byte */
cell = (SimpleStringListCell *)
pgut_malloc(sizeof(SimpleStringListCell) + strlen(val));
cell->next = NULL;
strcpy(cell->val, val);
if (list->tail)
list->tail->next = cell;
else
list->head = cell;
list->tail = cell;
}
/* Test whether `val` is in the given `list` */
bool
simple_string_list_member(SimpleStringList *list, const char *val)
{
SimpleStringListCell *cell;
for (cell = list->head; cell; cell = cell->next)
{
if (strcmp(cell->val, val) == 0)
return true;
}
return false;
}
static char *
prompt_for_password(void)
{

View File

@ -171,6 +171,23 @@ extern bool parse_time(const char *value, time_t *time);
#define ToLower(c) (tolower((unsigned char)(c)))
#define ToUpper(c) (toupper((unsigned char)(c)))
/* linked list of string values and helper functions, stolen from pg_dump. */
typedef struct SimpleStringListCell
{
struct SimpleStringListCell *next;
char val[1]; /* VARIABLE LENGTH FIELD */
} SimpleStringListCell;
typedef struct SimpleStringList
{
SimpleStringListCell *head;
SimpleStringListCell *tail;
} SimpleStringList;
extern void simple_string_list_append(SimpleStringList *list, const char *val);
extern bool simple_string_list_member(SimpleStringList *list, const char *val);
/*
* socket operations
*/