1
0
mirror of https://github.com/postgrespro/pg_probackup.git synced 2024-11-24 08:52:38 +02:00

Merge branch 'release_2_5_5'

This commit is contained in:
Mikhail A. Kulagin 2022-02-17 01:42:18 +03:00
commit 1d7a459058
8 changed files with 295 additions and 48 deletions

View File

@ -4176,7 +4176,7 @@ pg_probackup restore -B <replaceable>backup_dir</replaceable> --instance <replac
pg_probackup checkdb
[-B <replaceable>backup_dir</replaceable>] [--instance <replaceable>instance_name</replaceable>] [-D <replaceable>data_dir</replaceable>]
[--help] [-j <replaceable>num_threads</replaceable>] [--progress]
[--skip-block-validation] [--amcheck] [--heapallindexed]
[--skip-block-validation] [--amcheck [--checkunique] [--heapallindexed]]
[<replaceable>connection_options</replaceable>] [<replaceable>logging_options</replaceable>]
</programlisting>
<para>
@ -4195,17 +4195,24 @@ pg_probackup checkdb
extension or the <application>amcheck_next</application> extension
installed in the database to check its indexes. For databases
without <application>amcheck</application>, index verification will be skipped.
Additional options <option>--checkunique</option> and <option>--heapallindexed</option>
are effective depending on the version of <application>amcheck</application> installed.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--skip-block-validation</option></term>
<term><option>--checkunique</option></term>
<listitem>
<para>
Skip validation of data files. You can use this flag only
together with the <option>--amcheck</option> flag, so that only logical
verification of indexes is performed.
Verifies unique constraints during logical verification of indexes.
You can use this flag only together with the <option>--amcheck</option> flag when
the <application>amcheck</application> extension is
installed in the database.
</para>
<para>
This verification is only possible if it is supported by the version of the
<application>amcheck</application> extension you are using.
</para>
</listitem>
</varlistentry>
@ -4219,12 +4226,24 @@ pg_probackup checkdb
<option>--amcheck</option> flag.
</para>
<para>
This check is only possible if you are using the
<application>amcheck</application> extension of version 2.0 or higher, or
the <application>amcheck_next</application> extension of any version.
This check is only possible if it is supported by the version of the
<application>amcheck</application> extension you are using or
if the <application>amcheck_next</application> extension is used instead.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--skip-block-validation</option></term>
<listitem>
<para>
Skip validation of data files. You can use this flag only
together with the <option>--amcheck</option> flag, so that only logical
verification of indexes is performed.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
<para>

View File

@ -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 */
@ -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 "
@ -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
@ -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);
@ -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;
}
@ -473,38 +526,46 @@ static bool
amcheck_one_index(check_indexes_arg *arguments,
pg_indexEntry *ind)
{
PGresult *res;
char *params[2];
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;
params[0] = palloc(64);
/* first argument is index oid */
sprintf(params[0], "%u", ind->indexrelid);
/* second argument is heapallindexed */
params[1] = heapallindexed ? "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);
#define INDEXRELID 0
#define HEAPALLINDEXED 1
#define CHECKUNIQUE 2
/* first argument is index oid */
params[INDEXRELID] = palloc(64);
sprintf(params[INDEXRELID], "%u", ind->indexrelid);
/* second argument is heapallindexed */
params[HEAPALLINDEXED] = heapallindexed ? "true" : "false";
/* third optional argument is checkunique */
params[CHECKUNIQUE] = checkunique ? "true" : "false";
#undef CHECKUNIQUE
#undef HEAPALLINDEXED
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);
params_count = ind->checkunique_is_supported ?
3 :
( ind->heapallindexed_is_supported ? 2 : 1 );
res = pgut_execute_parallel(arguments->conn_arg.conn,
/*
* 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,
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)
{
@ -512,7 +573,7 @@ amcheck_one_index(check_indexes_arg *arguments,
arguments->thread_num, arguments->conn_opt.pgdatabase,
ind->namespace, ind->name, PQresultErrorMessage(res));
pfree(params[0]);
pfree(params[INDEXRELID]);
pfree(query);
PQclear(res);
return false;
@ -522,7 +583,8 @@ amcheck_one_index(check_indexes_arg *arguments,
arguments->thread_num,
arguments->conn_opt.pgdatabase, ind->namespace, ind->name);
pfree(params[0]);
pfree(params[INDEXRELID]);
#undef INDEXRELID
pfree(query);
PQclear(res);
return true;

View File

@ -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);
@ -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"));
@ -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"));

View File

@ -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 */
@ -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 },
@ -596,6 +598,16 @@ main(int argc, char *argv[])
instance_config.pgdata == NULL)
elog(ERROR, "required parameter not specified: --instance");
/* Check checkdb command options consistency */
if (backup_subcmd == CHECKDB_CMD &&
!need_amcheck)
{
if (heapallindexed)
elog(ERROR, "--heapallindexed can only be used with --amcheck option");
if (checkunique)
elog(ERROR, "--checkunique can only be used with --amcheck option");
}
/* Usually checkdb for file logging requires log_directory
* to be specified explicitly, but if backup_dir and instance name are provided,
* checkdb can use the usual default values or values from config

View File

@ -3,7 +3,7 @@
* pg_probackup.h: Backup/Recovery manager for PostgreSQL.
*
* Portions Copyright (c) 2009-2013, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
* Portions Copyright (c) 2015-2021, Postgres Professional
* Portions Copyright (c) 2015-2022, Postgres Professional
*
*-------------------------------------------------------------------------
*/
@ -338,7 +338,7 @@ typedef enum ShowFormat
#define BYTES_INVALID (-1) /* file didn`t changed since previous backup, DELTA backup do not rely on it */
#define FILE_NOT_FOUND (-2) /* file disappeared during backup */
#define BLOCKNUM_INVALID (-1)
#define PROGRAM_VERSION "2.5.4"
#define PROGRAM_VERSION "2.5.5"
/* update when remote agent API or behaviour changes */
#define AGENT_PROTOCOL_VERSION 20501
@ -829,6 +829,7 @@ extern ShowFormat show_format;
/* checkdb options */
extern bool heapallindexed;
extern bool checkunique;
extern bool skip_block_validation;
/* current settings */

View File

@ -211,6 +211,7 @@ class CheckdbTest(ProbackupTest, unittest.TestCase):
# Clean after yourself
gdb.kill()
node.stop()
self.del_test_dir(module_name, fname)
# @unittest.skip("skip")
@ -349,6 +350,7 @@ class CheckdbTest(ProbackupTest, unittest.TestCase):
log_file_content)
# Clean after yourself
node.stop()
self.del_test_dir(module_name, fname)
# @unittest.skip("skip")
@ -445,6 +447,98 @@ class CheckdbTest(ProbackupTest, unittest.TestCase):
e.message)
# Clean after yourself
node.stop()
self.del_test_dir(module_name, fname)
def test_checkdb_checkunique(self):
"""Test checkunique parameter of amcheck.bt_index_check function"""
fname = self.id().split('.')[3]
backup_dir = os.path.join(self.tmp_path, module_name, fname, 'backup')
node = self.make_simple_node(
base_dir=os.path.join(module_name, fname, 'node'),
initdb_params=['--data-checksums'])
node.slow_start()
try:
node.safe_psql(
"postgres",
"create extension amcheck")
except QueryException as e:
node.safe_psql(
"postgres",
"create extension amcheck_next")
# Part of https://commitfest.postgresql.org/32/2976/ patch test
node.safe_psql(
"postgres",
"CREATE TABLE bttest_unique(a varchar(50), b varchar(1500), c bytea, d varchar(50)); "
"ALTER TABLE bttest_unique SET (autovacuum_enabled = false); "
"CREATE UNIQUE INDEX bttest_unique_idx ON bttest_unique(a,b); "
"UPDATE pg_catalog.pg_index SET indisunique = false "
"WHERE indrelid = (SELECT oid FROM pg_catalog.pg_class WHERE relname = 'bttest_unique'); "
"INSERT INTO bttest_unique "
" SELECT i::text::varchar, "
" array_to_string(array( "
" SELECT substr('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', ((random()*(36-1)+1)::integer), 1) "
" FROM generate_series(1,1300)),'')::varchar, "
" i::text::bytea, i::text::varchar "
" FROM generate_series(0,1) AS i, generate_series(0,30) AS x; "
"UPDATE pg_catalog.pg_index SET indisunique = true "
"WHERE indrelid = (SELECT oid FROM pg_catalog.pg_class WHERE relname = 'bttest_unique'); "
"DELETE FROM bttest_unique WHERE ctid::text='(0,2)'; "
"DELETE FROM bttest_unique WHERE ctid::text='(4,2)'; "
"DELETE FROM bttest_unique WHERE ctid::text='(4,3)'; "
"DELETE FROM bttest_unique WHERE ctid::text='(9,3)';")
# run without checkunique option (error will not detected)
output = self.checkdb_node(
options=[
'--amcheck',
'--skip-block-validation',
'-d', 'postgres', '-p', str(node.port)])
self.assertIn(
'INFO: checkdb --amcheck finished successfully',
output)
self.assertIn(
'All checked indexes are valid',
output)
# run with checkunique option
try:
self.checkdb_node(
options=[
'--amcheck',
'--skip-block-validation',
'--checkunique',
'-d', 'postgres', '-p', str(node.port)])
if (ProbackupTest.enterprise and
(self.get_version(node) >= 111300 and self.get_version(node) < 120000
or self.get_version(node) >= 120800 and self.get_version(node) < 130000
or self.get_version(node) >= 130400)):
# we should die here because exception is what we expect to happen
self.assertEqual(
1, 0,
"Expecting Error because of index corruption\n"
" Output: {0} \n CMD: {1}".format(
repr(self.output), self.cmd))
else:
self.assertRegex(
self.output,
r"WARNING: Extension 'amcheck(|_next)' version [\d.]* in schema 'public' do not support 'checkunique' parameter")
except ProbackupException as e:
self.assertIn(
"ERROR: checkdb --amcheck finished with failure. Not all checked indexes are valid. All databases were amchecked.",
e.message,
"\n Unexpected Error Message: {0}\n CMD: {1}".format(
repr(e.message), self.cmd))
self.assertIn(
"Amcheck failed in database 'postgres' for index: 'public.bttest_unique_idx': ERROR: index \"bttest_unique_idx\" is corrupted. There are tuples violating UNIQUE constraint",
e.message)
# Clean after yourself
node.stop()
self.del_test_dir(module_name, fname)
# @unittest.skip("skip")
@ -502,6 +596,7 @@ class CheckdbTest(ProbackupTest, unittest.TestCase):
# Clean after yourself
gdb.kill()
node.stop()
self.del_test_dir(module_name, fname)
# @unittest.skip("skip")
@ -563,12 +658,15 @@ class CheckdbTest(ProbackupTest, unittest.TestCase):
'GRANT SELECT ON TABLE pg_catalog.pg_namespace TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.current_setting(text) TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.set_config(text, text, boolean) TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.texteq(text, text) TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.nameeq(name, name) TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.namene(name, name) TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.int8(integer) TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.oideq(oid, oid) TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.charne("char", "char") TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.pg_is_in_recovery() TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.string_to_array(text, text) TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.array_position(anyarray, anyelement) TO backup; '
'GRANT EXECUTE ON FUNCTION bt_index_check(regclass, bool) TO backup;' # amcheck-next function
)
# PG 9.6
@ -588,6 +686,7 @@ class CheckdbTest(ProbackupTest, unittest.TestCase):
'GRANT SELECT ON TABLE pg_catalog.pg_namespace TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.current_setting(text) TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.set_config(text, text, boolean) TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.texteq(text, text) TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.nameeq(name, name) TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.namene(name, name) TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.int8(integer) TO backup; '
@ -595,6 +694,8 @@ class CheckdbTest(ProbackupTest, unittest.TestCase):
'GRANT EXECUTE ON FUNCTION pg_catalog.charne("char", "char") TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.pg_is_in_recovery() TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.pg_control_system() TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.string_to_array(text, text) TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.array_position(anyarray, anyelement) TO backup; '
# 'GRANT EXECUTE ON FUNCTION bt_index_check(regclass) TO backup; '
'GRANT EXECUTE ON FUNCTION bt_index_check(regclass, bool) TO backup;'
)
@ -615,13 +716,16 @@ class CheckdbTest(ProbackupTest, unittest.TestCase):
'GRANT SELECT ON TABLE pg_catalog.pg_namespace TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.current_setting(text) TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.set_config(text, text, boolean) TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.texteq(text, text) TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.nameeq(name, name) TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.namene(name, name) TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.int8(integer) TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.oideq(oid, oid) TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.charne("char", "char") TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.pg_is_in_recovery() TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.pg_control_system() TO backup;'
'GRANT EXECUTE ON FUNCTION pg_catalog.pg_control_system() TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.string_to_array(text, text) TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.array_position(anyarray, anyelement) TO backup;'
)
if ProbackupTest.enterprise:
# amcheck-1.1
@ -633,7 +737,45 @@ class CheckdbTest(ProbackupTest, unittest.TestCase):
node.safe_psql(
'backupdb',
'GRANT EXECUTE ON FUNCTION bt_index_check(regclass) TO backup')
# >= 11
# >= 11 < 14
elif self.get_version(node) > 110000 and self.get_version(node) < 140000:
node.safe_psql(
'backupdb',
'CREATE ROLE backup WITH LOGIN; '
'GRANT CONNECT ON DATABASE backupdb to backup; '
'GRANT USAGE ON SCHEMA pg_catalog TO backup; '
'GRANT USAGE ON SCHEMA public TO backup; '
'GRANT SELECT ON TABLE pg_catalog.pg_proc TO backup; '
'GRANT SELECT ON TABLE pg_catalog.pg_extension TO backup; '
'GRANT SELECT ON TABLE pg_catalog.pg_database TO backup; '
'GRANT SELECT ON TABLE pg_catalog.pg_am TO backup; '
'GRANT SELECT ON TABLE pg_catalog.pg_class TO backup; '
'GRANT SELECT ON TABLE pg_catalog.pg_index TO backup; '
'GRANT SELECT ON TABLE pg_catalog.pg_namespace TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.current_setting(text) TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.set_config(text, text, boolean) TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.texteq(text, text) TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.nameeq(name, name) TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.namene(name, name) TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.int8(integer) TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.oideq(oid, oid) TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.charne("char", "char") TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.pg_is_in_recovery() TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.pg_control_system() TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.string_to_array(text, text) TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.array_position(anyarray, anyelement) TO backup; '
'GRANT EXECUTE ON FUNCTION bt_index_check(regclass) TO backup; '
'GRANT EXECUTE ON FUNCTION bt_index_check(regclass, bool) TO backup;'
)
# checkunique parameter
if ProbackupTest.enterprise:
if (self.get_version(node) >= 111300 and self.get_version(node) < 120000
or self.get_version(node) >= 120800 and self.get_version(node) < 130000
or self.get_version(node) >= 130400):
node.safe_psql(
"backupdb",
"GRANT EXECUTE ON FUNCTION bt_index_check(regclass, bool, bool) TO backup")
# >= 14
else:
node.safe_psql(
'backupdb',
@ -650,6 +792,7 @@ class CheckdbTest(ProbackupTest, unittest.TestCase):
'GRANT SELECT ON TABLE pg_catalog.pg_namespace TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.current_setting(text) TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.set_config(text, text, boolean) TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.texteq(text, text) TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.nameeq(name, name) TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.namene(name, name) TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.int8(integer) TO backup; '
@ -657,9 +800,16 @@ class CheckdbTest(ProbackupTest, unittest.TestCase):
'GRANT EXECUTE ON FUNCTION pg_catalog.charne("char", "char") TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.pg_is_in_recovery() TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.pg_control_system() TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.string_to_array(text, text) TO backup; '
'GRANT EXECUTE ON FUNCTION pg_catalog.array_position(anycompatiblearray, anycompatible) TO backup; '
'GRANT EXECUTE ON FUNCTION bt_index_check(regclass) TO backup; '
'GRANT EXECUTE ON FUNCTION bt_index_check(regclass, bool) TO backup;'
)
# checkunique parameter
if ProbackupTest.enterprise:
node.safe_psql(
"backupdb",
"GRANT EXECUTE ON FUNCTION bt_index_check(regclass, bool, bool) TO backup")
if ProbackupTest.enterprise:
node.safe_psql(
@ -700,4 +850,5 @@ class CheckdbTest(ProbackupTest, unittest.TestCase):
repr(e.message), self.cmd))
# Clean after yourself
node.stop()
self.del_test_dir(module_name, fname)

View File

@ -107,7 +107,7 @@ pg_probackup - utility to manage backup/recovery of PostgreSQL database.
pg_probackup checkdb [-B backup-path] [--instance=instance_name]
[-D pgdata-path] [--progress] [-j num-threads]
[--amcheck] [--skip-block-validation]
[--heapallindexed]
[--heapallindexed] [--checkunique]
[--help]
pg_probackup show -B backup-path

View File

@ -1 +1 @@
pg_probackup 2.5.4
pg_probackup 2.5.5