introduce option --parent-table (-I, stands for 'inheritance'), fix function repack_one_database(), introduce function repack.get_table_and_inheritors()

This commit is contained in:
Dmitry Ivanov
2017-03-20 23:04:41 +03:00
parent 7c8e272b54
commit 68dc592545
4 changed files with 117 additions and 38 deletions

View File

@ -109,7 +109,7 @@ const char *PROGRAM_VERSION = "unknown";
*/
#define SQL_XID_SNAPSHOT_80300 \
"SELECT repack.array_accum(l.virtualtransaction) " \
" FROM pg_locks AS l" \
" FROM pg_locks AS l" \
" LEFT JOIN pg_stat_activity AS a " \
" ON l.pid = a.procpid " \
" LEFT JOIN pg_database AS d " \
@ -174,7 +174,7 @@ typedef struct repack_index
{
Oid target_oid; /* target: OID */
const char *create_index; /* CREATE INDEX */
index_status_t status; /* Track parallel build statuses. */
index_status_t status; /* Track parallel build statuses. */
int worker_idx; /* which worker conn is handling */
} repack_index;
@ -238,6 +238,7 @@ static bool sqlstate_equals(PGresult *res, const char *state)
static bool analyze = true;
static bool alldb = false;
static bool noorder = false;
static SimpleStringList parent_table_list = {NULL, NULL};
static SimpleStringList table_list = {NULL, NULL};
static SimpleStringList schema_list = {NULL, NULL};
static char *orderby = NULL;
@ -265,6 +266,7 @@ static pgut_option options[] =
{
{ 'b', 'a', "all", &alldb },
{ 'l', 't', "table", &table_list },
{ 'l', 'I', "parent-table", &parent_table_list },
{ 'l', 'c', "schema", &schema_list },
{ 'b', 'n', "no-order", &noorder },
{ 'b', 'N', "dry-run", &dryrun },
@ -306,12 +308,16 @@ main(int argc, char *argv[])
if (r_index.head && table_list.head)
ereport(ERROR, (errcode(EINVAL),
errmsg("cannot specify --index (-i) and --table (-t)")));
if (r_index.head && parent_table_list.head)
ereport(ERROR, (errcode(EINVAL),
errmsg("cannot specify --index (-i) and --parent-table (-P)")));
else if (r_index.head && only_indexes)
ereport(ERROR, (errcode(EINVAL),
errmsg("cannot specify --index (-i) and --only-indexes (-x)")));
else if (only_indexes && !table_list.head)
else if (only_indexes && !(table_list.head || parent_table_list.head))
ereport(ERROR, (errcode(EINVAL),
errmsg("cannot repack all indexes of database, specify the table(s) via --table (-t)")));
errmsg("cannot repack all indexes of database, specify the table(s)"
"via --table (-t) or --parent-table (-P)")));
else if (alldb)
ereport(ERROR, (errcode(EINVAL),
errmsg("cannot repack specific index(es) in all databases")));
@ -336,7 +342,7 @@ main(int argc, char *argv[])
}
else
{
if (schema_list.head && table_list.head)
if (schema_list.head && (table_list.head || parent_table_list.head))
ereport(ERROR,
(errcode(EINVAL),
errmsg("cannot repack specific table(s) in schema, use schema.table notation instead")));
@ -346,7 +352,7 @@ main(int argc, char *argv[])
if (alldb)
{
if (table_list.head)
if (table_list.head || parent_table_list.head)
ereport(ERROR,
(errcode(EINVAL),
errmsg("cannot repack specific table(s) in all databases")));
@ -602,15 +608,17 @@ repack_one_database(const char *orderby, char *errbuf, size_t errsize)
SimpleStringListCell *cell;
const char **params = NULL;
int iparam = 0;
size_t num_parent_tables;
size_t num_tables;
size_t num_schemas;
size_t num_params;
num_parent_tables = simple_string_list_size(parent_table_list);
num_tables = simple_string_list_size(table_list);
num_schemas = simple_string_list_size(schema_list);
/* 1st param is the user-specified tablespace */
num_params = num_tables + num_schemas + 1;
num_params = num_parent_tables + num_tables + num_schemas + 1;
params = pgut_malloc(num_params * sizeof(char *));
initStringInfo(&sql);
@ -633,18 +641,42 @@ repack_one_database(const char *orderby, char *errbuf, size_t errsize)
" WHERE ");
params[iparam++] = tablespace;
if (num_tables)
if (num_tables || num_parent_tables)
{
appendStringInfoString(&sql, "(");
for (cell = table_list.head; cell; cell = cell->next)
/* standalone tables */
if (num_tables)
{
/* Construct table name placeholders to be used by PQexecParams */
appendStringInfo(&sql, "relid = $%d::regclass", iparam + 1);
params[iparam++] = cell->val;
if (cell->next)
appendStringInfoString(&sql, " OR ");
appendStringInfoString(&sql, "(");
for (cell = table_list.head; cell; cell = cell->next)
{
/* Construct table name placeholders to be used by PQexecParams */
appendStringInfo(&sql, "relid = $%d::regclass", iparam + 1);
params[iparam++] = cell->val;
if (cell->next)
appendStringInfoString(&sql, " OR ");
}
appendStringInfoString(&sql, ")");
}
if (num_tables && num_parent_tables)
appendStringInfoString(&sql, " OR ");
/* parent tables + inherited children */
if (num_parent_tables)
{
appendStringInfoString(&sql, "(");
for (cell = parent_table_list.head; cell; cell = cell->next)
{
/* Construct table name placeholders to be used by PQexecParams */
appendStringInfo(&sql,
"relid = ANY(repack.get_table_and_inheritors($%d::regclass))",
iparam + 1);
params[iparam++] = cell->val;
if (cell->next)
appendStringInfoString(&sql, " OR ");
}
appendStringInfoString(&sql, ")");
}
appendStringInfoString(&sql, ")");
}
else if (num_schemas)
{
@ -2008,7 +2040,7 @@ repack_all_indexes(char *errbuf, size_t errsize)
initStringInfo(&sql);
reconnect(ERROR);
assert(r_index.head || table_list.head);
assert(r_index.head || table_list.head || parent_table_list.head);
if (!preliminary_checks(errbuf, errsize))
goto cleanup;
@ -2023,6 +2055,8 @@ repack_all_indexes(char *errbuf, size_t errsize)
cell = r_index.head;
}
/* TODO: fix this also for parent_table_list */
else if (table_list.head)
{
appendStringInfoString(&sql,
@ -2087,6 +2121,7 @@ pgut_help(bool details)
printf("Options:\n");
printf(" -a, --all repack all databases\n");
printf(" -t, --table=TABLE repack specific table only\n");
printf(" -I, --parent-table=TABLE repack specific parent table and its inheritors\n");
printf(" -c, --schema=SCHEMA repack tables in specific schema only\n");
printf(" -s, --tablespace=TBLSPC move repacked tables to a new tablespace\n");
printf(" -S, --moveidx move repacked indexes to TBLSPC too\n");