diff --git a/bin/pg_repack.c b/bin/pg_repack.c index 8b84f4f..ea3b732 100644 --- a/bin/pg_repack.c +++ b/bin/pg_repack.c @@ -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; diff --git a/bin/pgut/pgut-fe.c b/bin/pgut/pgut-fe.c index b622974..bcea19f 100644 --- a/bin/pgut/pgut-fe.c +++ b/bin/pgut/pgut-fe.c @@ -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; diff --git a/bin/pgut/pgut-fe.h b/bin/pgut/pgut-fe.h index 49e6cfb..7529587 100644 --- a/bin/pgut/pgut-fe.h +++ b/bin/pgut/pgut-fe.h @@ -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) */ diff --git a/bin/pgut/pgut.c b/bin/pgut/pgut.c index dca9853..5a86330 100644 --- a/bin/pgut/pgut.c +++ b/bin/pgut/pgut.c @@ -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) { diff --git a/bin/pgut/pgut.h b/bin/pgut/pgut.h index f5217e6..f0b0f99 100644 --- a/bin/pgut/pgut.h +++ b/bin/pgut/pgut.h @@ -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 */