Skip to content

Commit cba77dd

Browse files
committed
[PBCKP-235] Pg15 compatibility
Author: Daniel Shelepanov <[email protected]>
1 parent e05a8c3 commit cba77dd

File tree

9 files changed

+302
-112
lines changed

9 files changed

+302
-112
lines changed

.travis.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ notifications:
2626

2727
# Default MODE is basic, i.e. all tests with PG_PROBACKUP_TEST_BASIC=ON
2828
env:
29-
- PG_VERSION=15 PG_BRANCH=master PTRACK_PATCH_PG_BRANCH=master
29+
- PG_VERSION=16 PG_BRANCH=master PTRACK_PATCH_PG_BRANCH=master
30+
- PG_VERSION=15 PG_BRANCH=REL_15_STABLE PTRACK_PATCH_PG_BRANCH=REL_15_STABLE
3031
- PG_VERSION=14 PG_BRANCH=REL_14_STABLE PTRACK_PATCH_PG_BRANCH=REL_14_STABLE
3132
- PG_VERSION=13 PG_BRANCH=REL_13_STABLE PTRACK_PATCH_PG_BRANCH=REL_13_STABLE
3233
- PG_VERSION=12 PG_BRANCH=REL_12_STABLE PTRACK_PATCH_PG_BRANCH=REL_12_STABLE

src/backup.c

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1030,12 +1030,20 @@ pg_start_backup(const char *label, bool smooth, pgBackup *backup,
10301030
uint32 lsn_lo;
10311031
params[0] = label;
10321032

1033+
#if PG_VERSION_NUM >= 150000
1034+
elog(INFO, "wait for pg_backup_start()");
1035+
#else
10331036
elog(INFO, "wait for pg_start_backup()");
1037+
#endif
10341038

10351039
/* 2nd argument is 'fast'*/
10361040
params[1] = smooth ? "false" : "true";
10371041
res = pgut_execute(conn,
1042+
#if PG_VERSION_NUM >= 150000
1043+
"SELECT pg_catalog.pg_backup_start($1, $2)",
1044+
#else
10381045
"SELECT pg_catalog.pg_start_backup($1, $2, false)",
1046+
#endif
10391047
2,
10401048
params);
10411049

@@ -1575,6 +1583,14 @@ pg_stop_backup_send(PGconn *conn, int server_version, bool is_started_on_replica
15751583
" labelfile,"
15761584
" spcmapfile"
15771585
" FROM pg_catalog.pg_stop_backup(false, false)",
1586+
stop_backup_on_master_after15_query[] =
1587+
"SELECT"
1588+
" pg_catalog.txid_snapshot_xmax(pg_catalog.txid_current_snapshot()),"
1589+
" current_timestamp(0)::timestamptz,"
1590+
" lsn,"
1591+
" labelfile,"
1592+
" spcmapfile"
1593+
" FROM pg_catalog.pg_backup_stop(false)",
15781594
/*
15791595
* In case of backup from replica we do not trust minRecPoint
15801596
* and stop_backup LSN, so we use latest replayed LSN as STOP LSN.
@@ -1586,12 +1602,26 @@ pg_stop_backup_send(PGconn *conn, int server_version, bool is_started_on_replica
15861602
" pg_catalog.pg_last_wal_replay_lsn(),"
15871603
" labelfile,"
15881604
" spcmapfile"
1589-
" FROM pg_catalog.pg_stop_backup(false, false)";
1605+
" FROM pg_catalog.pg_stop_backup(false, false)",
1606+
stop_backup_on_replica_after15_query[] =
1607+
"SELECT"
1608+
" pg_catalog.txid_snapshot_xmax(pg_catalog.txid_current_snapshot()),"
1609+
" current_timestamp(0)::timestamptz,"
1610+
" pg_catalog.pg_last_wal_replay_lsn(),"
1611+
" labelfile,"
1612+
" spcmapfile"
1613+
" FROM pg_catalog.pg_backup_stop(false)";
15901614

15911615
const char * const stop_backup_query =
1592-
is_started_on_replica ?
1616+
server_version >= 150000 ?
1617+
(is_started_on_replica ?
1618+
stop_backup_on_replica_after15_query :
1619+
stop_backup_on_master_after15_query
1620+
) :
1621+
(is_started_on_replica ?
15931622
stop_backup_on_replica_query :
1594-
stop_backup_on_master_query;
1623+
stop_backup_on_master_query
1624+
);
15951625
bool sent = false;
15961626

15971627
/* Make proper timestamp format for parse_time(recovery_time) */
@@ -1606,7 +1636,11 @@ pg_stop_backup_send(PGconn *conn, int server_version, bool is_started_on_replica
16061636
*/
16071637
sent = pgut_send(conn, stop_backup_query, 0, NULL, WARNING);
16081638
if (!sent)
1639+
#if PG_VERSION_NUM >= 150000
1640+
elog(ERROR, "Failed to send pg_backup_stop query");
1641+
#else
16091642
elog(ERROR, "Failed to send pg_stop_backup query");
1643+
#endif
16101644

16111645
/* After we have sent pg_stop_backup, we don't need this callback anymore */
16121646
pgut_atexit_pop(backup_stopbackup_callback, &stop_callback_params);
@@ -1652,7 +1686,11 @@ pg_stop_backup_consume(PGconn *conn, int server_version,
16521686
if (interrupted)
16531687
{
16541688
pgut_cancel(conn);
1689+
#if PG_VERSION_NUM >= 150000
1690+
elog(ERROR, "interrupted during waiting for pg_backup_stop");
1691+
#else
16551692
elog(ERROR, "interrupted during waiting for pg_stop_backup");
1693+
#endif
16561694
}
16571695

16581696
if (pg_stop_backup_timeout == 1)
@@ -1665,7 +1703,11 @@ pg_stop_backup_consume(PGconn *conn, int server_version,
16651703
if (pg_stop_backup_timeout > timeout)
16661704
{
16671705
pgut_cancel(conn);
1706+
#if PG_VERSION_NUM >= 150000
1707+
elog(ERROR, "pg_backup_stop doesn't answer in %d seconds, cancel it", timeout);
1708+
#else
16681709
elog(ERROR, "pg_stop_backup doesn't answer in %d seconds, cancel it", timeout);
1710+
#endif
16691711
}
16701712
}
16711713
else
@@ -1677,7 +1719,11 @@ pg_stop_backup_consume(PGconn *conn, int server_version,
16771719

16781720
/* Check successfull execution of pg_stop_backup() */
16791721
if (!query_result)
1722+
#if PG_VERSION_NUM >= 150000
1723+
elog(ERROR, "pg_backup_stop() failed");
1724+
#else
16801725
elog(ERROR, "pg_stop_backup() failed");
1726+
#endif
16811727
else
16821728
{
16831729
switch (PQresultStatus(query_result))

src/parsexlog.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,13 @@
2929
* RmgrNames is an array of resource manager names, to make error messages
3030
* a bit nicer.
3131
*/
32+
#if PG_VERSION_NUM >= 150000
33+
#define PG_RMGR(symname,name,redo,desc,identify,startup,cleanup,mask,decode) \
34+
name,
35+
#else
3236
#define PG_RMGR(symname,name,redo,desc,identify,startup,cleanup,mask) \
3337
name,
38+
#endif
3439

3540
static const char *RmgrNames[RM_MAX_ID + 1] = {
3641
#include "access/rmgrlist.h"
@@ -1764,7 +1769,12 @@ extractPageInfo(XLogReaderState *record, XLogReaderData *reader_data,
17641769

17651770
/* Is this a special record type that I recognize? */
17661771

1767-
if (rmid == RM_DBASE_ID && rminfo == XLOG_DBASE_CREATE)
1772+
if (rmid == RM_DBASE_ID
1773+
#if PG_VERSION_NUM >= 150000
1774+
&& (rminfo == XLOG_DBASE_CREATE_WAL_LOG || rminfo == XLOG_DBASE_CREATE_FILE_COPY))
1775+
#else
1776+
&& rminfo == XLOG_DBASE_CREATE)
1777+
#endif
17681778
{
17691779
/*
17701780
* New databases can be safely ignored. They would be completely
@@ -1818,13 +1828,21 @@ extractPageInfo(XLogReaderState *record, XLogReaderData *reader_data,
18181828
RmgrNames[rmid], info);
18191829
}
18201830

1831+
#if PG_VERSION_NUM >= 150000
1832+
for (block_id = 0; block_id <= record->record->max_block_id; block_id++)
1833+
#else
18211834
for (block_id = 0; block_id <= record->max_block_id; block_id++)
1835+
#endif
18221836
{
18231837
RelFileNode rnode;
18241838
ForkNumber forknum;
18251839
BlockNumber blkno;
18261840

1841+
#if PG_VERSION_NUM >= 150000
1842+
if (!XLogRecGetBlockTagExtended(record, block_id, &rnode, &forknum, &blkno, NULL))
1843+
#else
18271844
if (!XLogRecGetBlockTag(record, block_id, &rnode, &forknum, &blkno))
1845+
#endif
18281846
continue;
18291847

18301848
/* We only care about the main fork; others are copied as is */

src/stream.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,11 +260,18 @@ StreamLog(void *arg)
260260
ctl.synchronous = false;
261261
ctl.mark_done = false;
262262

263+
#if PG_VERSION_NUM >= 150000
264+
ctl.walmethod = CreateWalDirectoryMethod(
265+
stream_arg->basedir,
266+
PG_COMPRESSION_NONE,
267+
0,
268+
false);
269+
#else /* PG_VERSION_NUM >= 100000 && PG_VERSION_NUM < 150000 */
263270
ctl.walmethod = CreateWalDirectoryMethod(
264271
stream_arg->basedir,
265-
// (instance_config.compress_alg == NONE_COMPRESS) ? 0 : instance_config.compress_level,
266272
0,
267273
false);
274+
#endif /* PG_VERSION_NUM >= 150000 */
268275
ctl.replication_slot = replication_slot;
269276
ctl.stop_socket = PGINVALID_SOCKET;
270277
ctl.do_sync = false; /* We sync all files at the end of backup */

tests/archive.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -330,9 +330,14 @@ def test_pgpro434_4(self):
330330
with open(log_file, 'r') as f:
331331
log_content = f.read()
332332

333-
self.assertIn(
334-
"ERROR: pg_stop_backup doesn't answer in 60 seconds, cancel it",
335-
log_content)
333+
if self.get_version(node) < 150000:
334+
self.assertIn(
335+
"ERROR: pg_stop_backup doesn't answer in 60 seconds, cancel it",
336+
log_content)
337+
else:
338+
self.assertIn(
339+
"ERROR: pg_backup_stop doesn't answer in 60 seconds, cancel it",
340+
log_content)
336341

337342
log_file = os.path.join(node.logs_dir, 'postgresql.log')
338343
with open(log_file, 'r') as f:

tests/auth_test.py

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -51,16 +51,29 @@ def test_backup_via_unprivileged_user(self):
5151
1, 0,
5252
"Expecting Error due to missing grant on EXECUTE.")
5353
except ProbackupException as e:
54-
self.assertIn(
55-
"ERROR: query failed: ERROR: permission denied "
56-
"for function pg_start_backup", e.message,
57-
'\n Unexpected Error Message: {0}\n CMD: {1}'.format(
58-
repr(e.message), self.cmd))
59-
60-
node.safe_psql(
61-
"postgres",
62-
"GRANT EXECUTE ON FUNCTION"
63-
" pg_start_backup(text, boolean, boolean) TO backup;")
54+
if self.get_version(node) < 150000:
55+
self.assertIn(
56+
"ERROR: query failed: ERROR: permission denied "
57+
"for function pg_start_backup", e.message,
58+
'\n Unexpected Error Message: {0}\n CMD: {1}'.format(
59+
repr(e.message), self.cmd))
60+
else:
61+
self.assertIn(
62+
"ERROR: query failed: ERROR: permission denied "
63+
"for function pg_backup_start", e.message,
64+
'\n Unexpected Error Message: {0}\n CMD: {1}'.format(
65+
repr(e.message), self.cmd))
66+
67+
if self.get_version(node) < 150000:
68+
node.safe_psql(
69+
"postgres",
70+
"GRANT EXECUTE ON FUNCTION"
71+
" pg_start_backup(text, boolean, boolean) TO backup;")
72+
else:
73+
node.safe_psql(
74+
"postgres",
75+
"GRANT EXECUTE ON FUNCTION"
76+
" pg_backup_start(text, boolean) TO backup;")
6477

6578
node.safe_psql(
6679
'postgres',
@@ -92,11 +105,18 @@ def test_backup_via_unprivileged_user(self):
92105
1, 0,
93106
"Expecting Error due to missing grant on EXECUTE.")
94107
except ProbackupException as e:
95-
self.assertIn(
96-
"ERROR: query failed: ERROR: permission denied "
97-
"for function pg_stop_backup", e.message,
98-
'\n Unexpected Error Message: {0}\n CMD: {1}'.format(
99-
repr(e.message), self.cmd))
108+
if self.get_version(node) < 150000:
109+
self.assertIn(
110+
"ERROR: query failed: ERROR: permission denied "
111+
"for function pg_stop_backup", e.message,
112+
'\n Unexpected Error Message: {0}\n CMD: {1}'.format(
113+
repr(e.message), self.cmd))
114+
else:
115+
self.assertIn(
116+
"ERROR: query failed: ERROR: permission denied "
117+
"for function pg_backup_stop", e.message,
118+
'\n Unexpected Error Message: {0}\n CMD: {1}'.format(
119+
repr(e.message), self.cmd))
100120

101121
node.safe_psql(
102122
"postgres",

tests/helpers/ptrack_helpers.py

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -446,21 +446,37 @@ def simple_bootstrap(self, node, role) -> None:
446446
'postgres',
447447
'CREATE ROLE {0} WITH LOGIN REPLICATION'.format(role))
448448

449-
# PG >= 10
450-
node.safe_psql(
451-
'postgres',
452-
'GRANT USAGE ON SCHEMA pg_catalog TO {0}; '
453-
'GRANT EXECUTE ON FUNCTION pg_catalog.current_setting(text) TO {0}; '
454-
'GRANT EXECUTE ON FUNCTION pg_catalog.pg_is_in_recovery() TO {0}; '
455-
'GRANT EXECUTE ON FUNCTION pg_catalog.pg_start_backup(text, boolean, boolean) TO {0}; '
456-
'GRANT EXECUTE ON FUNCTION pg_catalog.pg_stop_backup(boolean, boolean) TO {0}; '
457-
'GRANT EXECUTE ON FUNCTION pg_catalog.pg_create_restore_point(text) TO {0}; '
458-
'GRANT EXECUTE ON FUNCTION pg_catalog.pg_switch_wal() TO {0}; '
459-
'GRANT EXECUTE ON FUNCTION pg_catalog.pg_last_wal_replay_lsn() TO {0}; '
460-
'GRANT EXECUTE ON FUNCTION pg_catalog.txid_current() TO {0}; '
461-
'GRANT EXECUTE ON FUNCTION pg_catalog.txid_current_snapshot() TO {0}; '
462-
'GRANT EXECUTE ON FUNCTION pg_catalog.txid_snapshot_xmax(txid_snapshot) TO {0}; '
463-
'GRANT EXECUTE ON FUNCTION pg_catalog.pg_control_checkpoint() TO {0};'.format(role))
449+
if self.get_version(node) < 150000:
450+
node.safe_psql(
451+
'postgres',
452+
'GRANT USAGE ON SCHEMA pg_catalog TO {0}; '
453+
'GRANT EXECUTE ON FUNCTION pg_catalog.current_setting(text) TO {0}; '
454+
'GRANT EXECUTE ON FUNCTION pg_catalog.pg_is_in_recovery() TO {0}; '
455+
'GRANT EXECUTE ON FUNCTION pg_catalog.pg_start_backup(text, boolean, boolean) TO {0}; '
456+
'GRANT EXECUTE ON FUNCTION pg_catalog.pg_stop_backup(boolean, boolean) TO {0}; '
457+
'GRANT EXECUTE ON FUNCTION pg_catalog.pg_create_restore_point(text) TO {0}; '
458+
'GRANT EXECUTE ON FUNCTION pg_catalog.pg_switch_wal() TO {0}; '
459+
'GRANT EXECUTE ON FUNCTION pg_catalog.pg_last_wal_replay_lsn() TO {0}; '
460+
'GRANT EXECUTE ON FUNCTION pg_catalog.txid_current() TO {0}; '
461+
'GRANT EXECUTE ON FUNCTION pg_catalog.txid_current_snapshot() TO {0}; '
462+
'GRANT EXECUTE ON FUNCTION pg_catalog.txid_snapshot_xmax(txid_snapshot) TO {0}; '
463+
'GRANT EXECUTE ON FUNCTION pg_catalog.pg_control_checkpoint() TO {0};'.format(role))
464+
# >= 15
465+
else:
466+
node.safe_psql(
467+
'postgres',
468+
'GRANT USAGE ON SCHEMA pg_catalog TO {0}; '
469+
'GRANT EXECUTE ON FUNCTION pg_catalog.current_setting(text) TO {0}; '
470+
'GRANT EXECUTE ON FUNCTION pg_catalog.pg_is_in_recovery() TO {0}; '
471+
'GRANT EXECUTE ON FUNCTION pg_catalog.pg_backup_start(text, boolean) TO {0}; '
472+
'GRANT EXECUTE ON FUNCTION pg_catalog.pg_backup_stop(boolean) TO {0}; '
473+
'GRANT EXECUTE ON FUNCTION pg_catalog.pg_create_restore_point(text) TO {0}; '
474+
'GRANT EXECUTE ON FUNCTION pg_catalog.pg_switch_wal() TO {0}; '
475+
'GRANT EXECUTE ON FUNCTION pg_catalog.pg_last_wal_replay_lsn() TO {0}; '
476+
'GRANT EXECUTE ON FUNCTION pg_catalog.txid_current() TO {0}; '
477+
'GRANT EXECUTE ON FUNCTION pg_catalog.txid_current_snapshot() TO {0}; '
478+
'GRANT EXECUTE ON FUNCTION pg_catalog.txid_snapshot_xmax(txid_snapshot) TO {0}; '
479+
'GRANT EXECUTE ON FUNCTION pg_catalog.pg_control_checkpoint() TO {0};'.format(role))
464480

465481
def create_tblspace_in_node(self, node, tblspc_name, tblspc_path=None, cfs=False):
466482
res = node.execute(

0 commit comments

Comments
 (0)