@@ -58,6 +58,8 @@ merge_non_data_file(parray *parent_chain, pgBackup *full_backup,
5858 pgFile * tmp_file , const char * full_database_dir ,
5959 const char * full_external_prefix );
6060
61+ static bool is_forward_compatible (parray * parent_chain );
62+
6163/*
6264 * Implementation of MERGE command.
6365 *
@@ -532,19 +534,7 @@ merge_chain(parray *parent_chain, pgBackup *full_backup, pgBackup *dest_backup)
532534 * If current program version differs from destination backup version,
533535 * then in-place merge is not possible.
534536 */
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 );
548538
549539 /* Forbid merge retry for failed merges between 2.4.0 and any
550540 * older version. Several format changes makes it impossible
@@ -1398,3 +1388,58 @@ merge_non_data_file(parray *parent_chain, pgBackup *full_backup,
13981388 to_fullpath_tmp , to_fullpath , strerror (errno ));
13991389
14001390}
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