@@ -58,6 +58,8 @@ merge_non_data_file(parray *parent_chain, pgBackup *full_backup,
58
58
pgFile * tmp_file , const char * full_database_dir ,
59
59
const char * full_external_prefix );
60
60
61
+ static bool is_forward_compatible (parray * parent_chain );
62
+
61
63
/*
62
64
* Implementation of MERGE command.
63
65
*
@@ -532,19 +534,7 @@ merge_chain(parray *parent_chain, pgBackup *full_backup, pgBackup *dest_backup)
532
534
* If current program version differs from destination backup version,
533
535
* then in-place merge is not possible.
534
536
*/
535
- if ((parse_program_version (full_backup -> program_version ) ==
536
- parse_program_version (dest_backup -> program_version )) &&
537
- (parse_program_version (dest_backup -> program_version ) ==
538
- parse_program_version (PROGRAM_VERSION )))
539
- program_version_match = true;
540
- else
541
- elog (WARNING , "In-place merge is disabled because of program "
542
- "versions mismatch. Full backup version: %s, "
543
- "destination backup version: %s, "
544
- "current program version: %s" ,
545
- full_backup -> program_version ,
546
- dest_backup -> program_version ,
547
- PROGRAM_VERSION );
537
+ program_version_match = is_forward_compatible (parent_chain );
548
538
549
539
/* Forbid merge retry for failed merges between 2.4.0 and any
550
540
* older version. Several format changes makes it impossible
@@ -1398,3 +1388,58 @@ merge_non_data_file(parray *parent_chain, pgBackup *full_backup,
1398
1388
to_fullpath_tmp , to_fullpath , strerror (errno ));
1399
1389
1400
1390
}
1391
+
1392
+ /*
1393
+ * If file format in incremental chain is compatible
1394
+ * with current storage format.
1395
+ * If not, then in-place merge is not possible.
1396
+ *
1397
+ * Consider the following examples:
1398
+ * STORAGE_FORMAT_VERSION = 2.4.4
1399
+ * 2.3.3 \
1400
+ * 2.3.4 \ disable in-place merge, because
1401
+ * 2.4.1 / current STORAGE_FORMAT_VERSION > 2.3.3
1402
+ * 2.4.3 /
1403
+ *
1404
+ * 2.4.4 \ enable in_place merge, because
1405
+ * 2.4.5 / current STORAGE_FORMAT_VERSION == 2.4.4
1406
+ *
1407
+ * 2.4.5 \ enable in_place merge, because
1408
+ * 2.4.6 / current STORAGE_FORMAT_VERSION < 2.4.5
1409
+ *
1410
+ */
1411
+ bool
1412
+ is_forward_compatible (parray * parent_chain )
1413
+ {
1414
+ int i ;
1415
+ pgBackup * oldest_ver_backup = NULL ;
1416
+ uint32 oldest_ver_in_chain = parse_program_version (PROGRAM_VERSION );
1417
+
1418
+ for (i = 0 ; i < parray_num (parent_chain ); i ++ )
1419
+ {
1420
+ pgBackup * backup = (pgBackup * ) parray_get (parent_chain , i );
1421
+ uint32 current_version = parse_program_version (backup -> program_version );
1422
+
1423
+ if (!oldest_ver_backup )
1424
+ oldest_ver_backup = backup ;
1425
+
1426
+ if (current_version < oldest_ver_in_chain )
1427
+ {
1428
+ oldest_ver_in_chain = current_version ;
1429
+ oldest_ver_backup = backup ;
1430
+ }
1431
+ }
1432
+
1433
+ if (oldest_ver_in_chain < parse_program_version (STORAGE_FORMAT_VERSION ))
1434
+ {
1435
+ elog (WARNING , "In-place merge is disabled because of storage format incompatibility. "
1436
+ "Backup %s storage format version: %s, "
1437
+ "current storage format version: %s" ,
1438
+ base36enc (oldest_ver_backup -> start_time ),
1439
+ oldest_ver_backup -> program_version ,
1440
+ STORAGE_FORMAT_VERSION );
1441
+ return false;
1442
+ }
1443
+
1444
+ return true;
1445
+ }
0 commit comments