Skip to content

[PGPRO-5612] Support for checkunique parameter of amcheck.bt_index_ch… #456

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Feb 16, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,22 @@ env:
- PG_VERSION=10 PG_BRANCH=REL_10_STABLE
- PG_VERSION=9.6 PG_BRANCH=REL9_6_STABLE
- PG_VERSION=9.5 PG_BRANCH=REL9_5_STABLE
- PG_VERSION=15 PG_BRANCH=master MODE=checkdb
- PG_VERSION=14 PG_BRANCH=REL_14_STABLE MODE=checkdb
- PG_VERSION=13 PG_BRANCH=REL_13_STABLE MODE=checkdb
- PG_VERSION=12 PG_BRANCH=REL_12_STABLE MODE=checkdb
- PG_VERSION=11 PG_BRANCH=REL_11_STABLE MODE=checkdb
- PG_VERSION=10 PG_BRANCH=REL_10_STABLE MODE=checkdb
- PG_VERSION=9.6 PG_BRANCH=REL9_6_STABLE MODE=checkdb
- PG_VERSION=9.5 PG_BRANCH=REL9_5_STABLE MODE=checkdb
- PG_VERSION=15 PG_BRANCH=master MODE=option
- PG_VERSION=14 PG_BRANCH=REL_14_STABLE MODE=option
- PG_VERSION=13 PG_BRANCH=REL_13_STABLE MODE=option
- PG_VERSION=12 PG_BRANCH=REL_12_STABLE MODE=option
- PG_VERSION=11 PG_BRANCH=REL_11_STABLE MODE=option
- PG_VERSION=10 PG_BRANCH=REL_10_STABLE MODE=option
- PG_VERSION=9.6 PG_BRANCH=REL9_6_STABLE MODE=option
- PG_VERSION=9.5 PG_BRANCH=REL9_5_STABLE MODE=option
# - PG_VERSION=13 PG_BRANCH=REL_13_STABLE PTRACK_PATCH_PG_BRANCH=off MODE=archive
# - PG_VERSION=13 PG_BRANCH=REL_13_STABLE PTRACK_PATCH_PG_BRANCH=REL_13_STABLE MODE=backup
# - PG_VERSION=13 PG_BRANCH=REL_13_STABLE PTRACK_PATCH_PG_BRANCH=REL_13_STABLE MODE=catchup
Expand Down
111 changes: 84 additions & 27 deletions src/checkdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ typedef struct pg_indexEntry
char *name;
char *namespace;
bool heapallindexed_is_supported;
bool checkunique_is_supported;
/* schema where amcheck extension is located */
char *amcheck_nspname;
/* lock for synchronization of parallel threads */
Expand Down Expand Up @@ -351,10 +352,14 @@ get_index_list(const char *dbname, bool first_db_with_amcheck,
{
PGresult *res;
char *amcheck_nspname = NULL;
char *amcheck_extname = NULL;
char *amcheck_extversion = NULL;
int i;
bool heapallindexed_is_supported = false;
bool checkunique_is_supported = false;
parray *index_list = NULL;

/* Check amcheck extension version */
res = pgut_execute(db_conn, "SELECT "
"extname, nspname, extversion "
"FROM pg_catalog.pg_namespace n "
Expand All @@ -379,24 +384,68 @@ get_index_list(const char *dbname, bool first_db_with_amcheck,
return NULL;
}

amcheck_extname = pgut_malloc(strlen(PQgetvalue(res, 0, 0)) + 1);
strcpy(amcheck_extname, PQgetvalue(res, 0, 0));
amcheck_nspname = pgut_malloc(strlen(PQgetvalue(res, 0, 1)) + 1);
strcpy(amcheck_nspname, PQgetvalue(res, 0, 1));
amcheck_extversion = pgut_malloc(strlen(PQgetvalue(res, 0, 2)) + 1);
strcpy(amcheck_extversion, PQgetvalue(res, 0, 2));
PQclear(res);

/* heapallindexed_is_supported is database specific */
if (strcmp(PQgetvalue(res, 0, 2), "1.0") != 0 &&
strcmp(PQgetvalue(res, 0, 2), "1") != 0)
/* TODO this is wrong check, heapallindexed supported also in 1.1.1, 1.2 and 1.2.1... */
if (strcmp(amcheck_extversion, "1.0") != 0 &&
strcmp(amcheck_extversion, "1") != 0)
heapallindexed_is_supported = true;

elog(INFO, "Amchecking database '%s' using extension '%s' "
"version %s from schema '%s'",
dbname, PQgetvalue(res, 0, 0),
PQgetvalue(res, 0, 2), PQgetvalue(res, 0, 1));
dbname, amcheck_extname,
amcheck_extversion, amcheck_nspname);

if (!heapallindexed_is_supported && heapallindexed)
elog(WARNING, "Extension '%s' version %s in schema '%s'"
"do not support 'heapallindexed' option",
PQgetvalue(res, 0, 0), PQgetvalue(res, 0, 2),
PQgetvalue(res, 0, 1));
amcheck_extname, amcheck_extversion,
amcheck_nspname);

#ifndef PGPRO_EE
/*
* Will support when the vanilla patch will commited https://commitfest.postgresql.org/32/2976/
*/
checkunique_is_supported = false;
#else
/*
* Check bt_index_check function signature to determine support of checkunique parameter
* This can't be exactly checked by checking extension version,
* For example, 1.1.1 and 1.2.1 supports this parameter, but 1.2 doesn't (PGPROEE-12.4.1)
*/
res = pgut_execute(db_conn, "SELECT "
" oid "
"FROM pg_catalog.pg_proc "
"WHERE "
" pronamespace = $1::regnamespace "
"AND proname = 'bt_index_check' "
"AND 'checkunique' = ANY(proargnames) "
"AND (pg_catalog.string_to_array(proargtypes::text, ' ')::regtype[])[pg_catalog.array_position(proargnames, 'checkunique')] = 'bool'::regtype",
1, (const char **) &amcheck_nspname);

if (PQresultStatus(res) != PGRES_TUPLES_OK)
{
PQclear(res);
elog(ERROR, "Cannot check 'checkunique' option is supported in bt_index_check function %s: %s",
dbname, PQerrorMessage(db_conn));
}

checkunique_is_supported = PQntuples(res) >= 1;
PQclear(res);
#endif

if (!checkunique_is_supported && checkunique)
elog(WARNING, "Extension '%s' version %s in schema '%s' "
"do not support 'checkunique' parameter",
amcheck_extname, amcheck_extversion,
amcheck_nspname);

/*
* In order to avoid duplicates, select global indexes
Expand Down Expand Up @@ -453,6 +502,7 @@ get_index_list(const char *dbname, bool first_db_with_amcheck,
strcpy(ind->namespace, namespace); /* enough buffer size guaranteed */

ind->heapallindexed_is_supported = heapallindexed_is_supported;
ind->checkunique_is_supported = checkunique_is_supported;
ind->amcheck_nspname = pgut_malloc(strlen(amcheck_nspname) + 1);
strcpy(ind->amcheck_nspname, amcheck_nspname);
pg_atomic_clear_flag(&ind->lock);
Expand All @@ -464,6 +514,9 @@ get_index_list(const char *dbname, bool first_db_with_amcheck,
}

PQclear(res);
free(amcheck_extversion);
free(amcheck_nspname);
free(amcheck_extname);

return index_list;
}
Expand All @@ -473,38 +526,42 @@ static bool
amcheck_one_index(check_indexes_arg *arguments,
pg_indexEntry *ind)
{
PGresult *res;
char *params[2];
char *query = NULL;
PGresult *res;
char* params[3];
static const char* queries[] = {
"SELECT %s.bt_index_check(index => $1)",
"SELECT %s.bt_index_check(index => $1, heapallindexed => $2)",
"SELECT %s.bt_index_check(index => $1, heapallindexed => $2, checkunique => $3)",
};
int params_count;
char* query = NULL;

if (interrupted)
elog(ERROR, "Interrupted");

params[0] = palloc(64);

/* first argument is index oid */
sprintf(params[0], "%u", ind->indexrelid);
/* second argument is heapallindexed */
params[1] = heapallindexed ? "true" : "false";
/* third optional argument is checkunique */
params[2] = checkunique ? "true" : "false";

if (interrupted)
elog(ERROR, "Interrupted");

if (ind->heapallindexed_is_supported)
{
query = palloc(strlen(ind->amcheck_nspname)+strlen("SELECT .bt_index_check($1, $2)")+1);
sprintf(query, "SELECT %s.bt_index_check($1, $2)", ind->amcheck_nspname);
params_count = ind->checkunique_is_supported ?
3 :
( ind->heapallindexed_is_supported ? 2 : 1 );

res = pgut_execute_parallel(arguments->conn_arg.conn,
arguments->conn_arg.cancel_conn,
query, 2, (const char **)params, true, true, true);
}
else
{
query = palloc(strlen(ind->amcheck_nspname)+strlen("SELECT .bt_index_check($1)")+1);
sprintf(query, "SELECT %s.bt_index_check($1)", ind->amcheck_nspname);
/*
* Prepare query text with schema name
* +1 for \0 and -2 for %s
*/
query = palloc(strlen(ind->amcheck_nspname) + strlen(queries[params_count - 1]) + 1 - 2);
sprintf(query, queries[params_count - 1], ind->amcheck_nspname);

res = pgut_execute_parallel(arguments->conn_arg.conn,
res = pgut_execute_parallel(arguments->conn_arg.conn,
arguments->conn_arg.cancel_conn,
query, 1, (const char **)params, true, true, true);
}
query, params_count, (const char **)params, true, true, true);

if (PQresultStatus(res) != PGRES_TUPLES_OK)
{
Expand Down
6 changes: 4 additions & 2 deletions src/help.c
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ help_pg_probackup(void)
printf(_("\n %s checkdb [-B backup-path] [--instance=instance_name]\n"), PROGRAM_NAME);
printf(_(" [-D pgdata-path] [--progress] [-j num-threads]\n"));
printf(_(" [--amcheck] [--skip-block-validation]\n"));
printf(_(" [--heapallindexed]\n"));
printf(_(" [--heapallindexed] [--checkunique]\n"));
printf(_(" [--help]\n"));

printf(_("\n %s show -B backup-path\n"), PROGRAM_NAME);
Expand Down Expand Up @@ -601,7 +601,7 @@ help_checkdb(void)
printf(_("\n%s checkdb [-B backup-path] [--instance=instance_name]\n"), PROGRAM_NAME);
printf(_(" [-D pgdata-path] [-j num-threads] [--progress]\n"));
printf(_(" [--amcheck] [--skip-block-validation]\n"));
printf(_(" [--heapallindexed]\n\n"));
printf(_(" [--heapallindexed] [--checkunique]\n\n"));

printf(_(" -B, --backup-path=backup-path location of the backup storage area\n"));
printf(_(" --instance=instance_name name of the instance\n"));
Expand All @@ -616,6 +616,8 @@ help_checkdb(void)
printf(_(" using 'amcheck' or 'amcheck_next' extensions\n"));
printf(_(" --heapallindexed also check that heap is indexed\n"));
printf(_(" can be used only with '--amcheck' option\n"));
printf(_(" --checkunique also check unique constraints\n"));
printf(_(" can be used only with '--amcheck' option\n"));

printf(_("\n Logging options:\n"));
printf(_(" --log-level-console=log-level-console\n"));
Expand Down
2 changes: 2 additions & 0 deletions src/pg_probackup.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ static parray *exclude_relative_paths_list = NULL;
/* checkdb options */
bool need_amcheck = false;
bool heapallindexed = false;
bool checkunique = false;
bool amcheck_parent = false;

/* delete options */
Expand Down Expand Up @@ -240,6 +241,7 @@ static ConfigOption cmd_options[] =
/* checkdb options */
{ 'b', 195, "amcheck", &need_amcheck, SOURCE_CMD_STRICT },
{ 'b', 196, "heapallindexed", &heapallindexed, SOURCE_CMD_STRICT },
{ 'b', 198, "checkunique", &checkunique, SOURCE_CMD_STRICT },
{ 'b', 197, "parent", &amcheck_parent, SOURCE_CMD_STRICT },
/* delete options */
{ 'b', 145, "wal", &delete_wal, SOURCE_CMD_STRICT },
Expand Down
1 change: 1 addition & 0 deletions src/pg_probackup.h
Original file line number Diff line number Diff line change
Expand Up @@ -829,6 +829,7 @@ extern ShowFormat show_format;

/* checkdb options */
extern bool heapallindexed;
extern bool checkunique;
extern bool skip_block_validation;

/* current settings */
Expand Down
Loading