1
0
mirror of https://github.com/postgres/postgres.git synced 2025-12-21 05:21:08 +03:00

Message wording improvements

Use "row" instead of "tuple" for user-facing information for
logical replication conflicts.
This commit is contained in:
Peter Eisentraut
2025-08-25 22:59:00 +02:00
parent e76738e597
commit 9d115b9e11
9 changed files with 49 additions and 49 deletions

View File

@@ -609,10 +609,10 @@ ExecSimpleRelationInsert(ResultRelInfo *resultRelInfo,
conflictindexes, false);
/*
* Checks the conflict indexes to fetch the conflicting local tuple
* and reports the conflict. We perform this check here, instead of
* Checks the conflict indexes to fetch the conflicting local row and
* reports the conflict. We perform this check here, instead of
* performing an additional index scan before the actual insertion and
* reporting the conflict if any conflicting tuples are found. This is
* reporting the conflict if any conflicting rows are found. This is
* to avoid the overhead of executing the extra scan for each INSERT
* operation, even when no conflict arises, which could introduce
* significant overhead to replication, particularly in cases where

View File

@@ -54,7 +54,7 @@ static char *build_index_value_desc(EState *estate, Relation localrel,
/*
* Get the xmin and commit timestamp data (origin and timestamp) associated
* with the provided local tuple.
* with the provided local row.
*
* Return true if the commit timestamp data was found, false otherwise.
*/
@@ -88,12 +88,12 @@ GetTupleTransactionInfo(TupleTableSlot *localslot, TransactionId *xmin,
* This function is used to report a conflict while applying replication
* changes.
*
* 'searchslot' should contain the tuple used to search the local tuple to be
* 'searchslot' should contain the tuple used to search the local row to be
* updated or deleted.
*
* 'remoteslot' should contain the remote new tuple, if any.
*
* conflicttuples is a list of local tuples that caused the conflict and the
* conflicttuples is a list of local rows that caused the conflict and the
* conflict related information. See ConflictTupleInfo.
*
* The caller must ensure that all the indexes passed in ConflictTupleInfo are
@@ -189,9 +189,9 @@ errcode_apply_conflict(ConflictType type)
*
* The DETAIL line comprises of two parts:
* 1. Explanation of the conflict type, including the origin and commit
* timestamp of the existing local tuple.
* 2. Display of conflicting key, existing local tuple, remote new tuple, and
* replica identity columns, if any. The remote old tuple is excluded as its
* timestamp of the existing local row.
* 2. Display of conflicting key, existing local row, remote new row, and
* replica identity columns, if any. The remote old row is excluded as its
* information is covered in the replica identity columns.
*/
static void
@@ -291,7 +291,7 @@ errdetail_apply_conflict(EState *estate, ResultRelInfo *relinfo,
localslot, remoteslot, indexoid);
/*
* Next, append the key values, existing local tuple, remote tuple and
* Next, append the key values, existing local row, remote row, and
* replica identity columns after the message.
*/
if (val_desc)
@@ -309,7 +309,7 @@ errdetail_apply_conflict(EState *estate, ResultRelInfo *relinfo,
/*
* Helper function to build the additional details for conflicting key,
* existing local tuple, remote tuple, and replica identity columns.
* existing local row, remote row, and replica identity columns.
*
* If the return value is NULL, it indicates that the current user lacks
* permissions to view the columns involved.
@@ -351,7 +351,7 @@ build_tuple_value_details(EState *estate, ResultRelInfo *relinfo,
{
/*
* The 'modifiedCols' only applies to the new tuple, hence we pass
* NULL for the existing local tuple.
* NULL for the existing local row.
*/
desc = ExecBuildSlotValueDescription(relid, localslot, tupdesc,
NULL, 64);
@@ -361,12 +361,12 @@ build_tuple_value_details(EState *estate, ResultRelInfo *relinfo,
if (tuple_value.len > 0)
{
appendStringInfoString(&tuple_value, "; ");
appendStringInfo(&tuple_value, _("existing local tuple %s"),
appendStringInfo(&tuple_value, _("existing local row %s"),
desc);
}
else
{
appendStringInfo(&tuple_value, _("Existing local tuple %s"),
appendStringInfo(&tuple_value, _("Existing local row %s"),
desc);
}
}
@@ -393,11 +393,11 @@ build_tuple_value_details(EState *estate, ResultRelInfo *relinfo,
if (tuple_value.len > 0)
{
appendStringInfoString(&tuple_value, "; ");
appendStringInfo(&tuple_value, _("remote tuple %s"), desc);
appendStringInfo(&tuple_value, _("remote row %s"), desc);
}
else
{
appendStringInfo(&tuple_value, _("Remote tuple %s"), desc);
appendStringInfo(&tuple_value, _("Remote row %s"), desc);
}
}
}

View File

@@ -54,7 +54,7 @@ typedef enum
#define CONFLICT_NUM_TYPES (CT_MULTIPLE_UNIQUE_CONFLICTS + 1)
/*
* Information for the existing local tuple that caused the conflict.
* Information for the existing local row that caused the conflict.
*/
typedef struct ConflictTupleInfo
{
@@ -66,7 +66,7 @@ typedef struct ConflictTupleInfo
* the conflict */
RepOriginId origin; /* origin identifier of the modification */
TimestampTz ts; /* timestamp of when the modification on the
* conflicting local tuple occurred */
* conflicting local row occurred */
} ConflictTupleInfo;
extern bool GetTupleTransactionInfo(TupleTableSlot *localslot,

View File

@@ -365,10 +365,10 @@ $node_publisher->wait_for_catchup('tap_sub');
my $logfile = slurp_file($node_subscriber->logfile, $log_location);
ok( $logfile =~
qr/conflict detected on relation "public.tab_full_pk": conflict=update_missing.*\n.*DETAIL:.* Could not find the row to be updated.*\n.*Remote tuple \(1, quux\); replica identity \(a\)=\(1\)/m,
qr/conflict detected on relation "public.tab_full_pk": conflict=update_missing.*\n.*DETAIL:.* Could not find the row to be updated.*\n.*Remote row \(1, quux\); replica identity \(a\)=\(1\)/m,
'update target row is missing');
ok( $logfile =~
qr/conflict detected on relation "public.tab_full": conflict=update_missing.*\n.*DETAIL:.* Could not find the row to be updated.*\n.*Remote tuple \(26\); replica identity full \(25\)/m,
qr/conflict detected on relation "public.tab_full": conflict=update_missing.*\n.*DETAIL:.* Could not find the row to be updated.*\n.*Remote row \(26\); replica identity full \(25\)/m,
'update target row is missing');
ok( $logfile =~
qr/conflict detected on relation "public.tab_full_pk": conflict=delete_missing.*\n.*DETAIL:.* Could not find the row to be deleted.*\n.*Replica identity \(a\)=\(2\)/m,

View File

@@ -368,7 +368,7 @@ $node_publisher->wait_for_catchup('sub2');
my $logfile = slurp_file($node_subscriber1->logfile(), $log_location);
ok( $logfile =~
qr/conflict detected on relation "public.tab1_2_2": conflict=update_missing.*\n.*DETAIL:.* Could not find the row to be updated.*\n.*Remote tuple \(null, 4, quux\); replica identity \(a\)=\(4\)/,
qr/conflict detected on relation "public.tab1_2_2": conflict=update_missing.*\n.*DETAIL:.* Could not find the row to be updated.*\n.*Remote row \(null, 4, quux\); replica identity \(a\)=\(4\)/,
'update target row is missing in tab1_2_2');
ok( $logfile =~
qr/conflict detected on relation "public.tab1_1": conflict=delete_missing.*\n.*DETAIL:.* Could not find the row to be deleted.*\n.*Replica identity \(a\)=\(1\)/,
@@ -781,7 +781,7 @@ $node_publisher->wait_for_catchup('sub2');
$logfile = slurp_file($node_subscriber1->logfile(), $log_location);
ok( $logfile =~
qr/conflict detected on relation "public.tab2_1": conflict=update_missing.*\n.*DETAIL:.* Could not find the row to be updated.*\n.*Remote tuple \(pub_tab2, quux, 5\); replica identity \(a\)=\(5\)/,
qr/conflict detected on relation "public.tab2_1": conflict=update_missing.*\n.*DETAIL:.* Could not find the row to be updated.*\n.*Remote row \(pub_tab2, quux, 5\); replica identity \(a\)=\(5\)/,
'update target row is missing in tab2_1');
ok( $logfile =~
qr/conflict detected on relation "public.tab2_1": conflict=delete_missing.*\n.*DETAIL:.* Could not find the row to be deleted.*\n.*Replica identity \(a\)=\(1\)/,
@@ -802,8 +802,8 @@ $node_publisher->wait_for_catchup('sub_viaroot');
$logfile = slurp_file($node_subscriber1->logfile(), $log_location);
ok( $logfile =~
qr/conflict detected on relation "public.tab2_1": conflict=update_origin_differs.*\n.*DETAIL:.* Updating the row that was modified locally in transaction [0-9]+ at .*\n.*Existing local tuple \(yyy, null, 3\); remote tuple \(pub_tab2, quux, 3\); replica identity \(a\)=\(3\)/,
'updating a tuple that was modified by a different origin');
qr/conflict detected on relation "public.tab2_1": conflict=update_origin_differs.*\n.*DETAIL:.* Updating the row that was modified locally in transaction [0-9]+ at .*\n.*Existing local row \(yyy, null, 3\); remote row \(pub_tab2, quux, 3\); replica identity \(a\)=\(3\)/,
'updating a row that was modified by a different origin');
# The remaining tests no longer test conflict detection.
$node_subscriber1->append_conf('postgresql.conf',

View File

@@ -30,7 +30,7 @@ sub test_skip_lsn
# ERROR with its CONTEXT when retrieving this information.
my $contents = slurp_file($node_subscriber->logfile, $offset);
$contents =~
qr/conflict detected on relation "public.tbl".*\n.*DETAIL:.* Key already exists in unique index "tbl_pkey", modified by .*origin.* transaction \d+ at .*\n.*Key \(i\)=\(\d+\); existing local tuple .*; remote tuple .*\n.*CONTEXT:.* for replication target relation "public.tbl" in transaction \d+, finished at ([[:xdigit:]]+\/[[:xdigit:]]+)/m
qr/conflict detected on relation "public.tbl".*\n.*DETAIL:.* Key already exists in unique index "tbl_pkey", modified by .*origin.* transaction \d+ at .*\n.*Key \(i\)=\(\d+\); existing local row .*; remote row .*\n.*CONTEXT:.* for replication target relation "public.tbl" in transaction \d+, finished at ([[:xdigit:]]+\/[[:xdigit:]]+)/m
or die "could not get error-LSN";
my $lsn = $1;

View File

@@ -163,7 +163,7 @@ is($result, qq(32), 'The node_A data replicated to node_B');
$node_C->safe_psql('postgres', "UPDATE tab SET a = 33 WHERE a = 32;");
$node_B->wait_for_log(
qr/conflict detected on relation "public.tab": conflict=update_origin_differs.*\n.*DETAIL:.* Updating the row that was modified by a different origin ".*" in transaction [0-9]+ at .*\n.*Existing local tuple \(32\); remote tuple \(33\); replica identity \(a\)=\(32\)/
qr/conflict detected on relation "public.tab": conflict=update_origin_differs.*\n.*DETAIL:.* Updating the row that was modified by a different origin ".*" in transaction [0-9]+ at .*\n.*Existing local row \(32\); remote row \(33\); replica identity \(a\)=\(32\)/
);
$node_B->safe_psql('postgres', "DELETE FROM tab;");
@@ -179,7 +179,7 @@ is($result, qq(33), 'The node_A data replicated to node_B');
$node_C->safe_psql('postgres', "DELETE FROM tab WHERE a = 33;");
$node_B->wait_for_log(
qr/conflict detected on relation "public.tab": conflict=delete_origin_differs.*\n.*DETAIL:.* Deleting the row that was modified by a different origin ".*" in transaction [0-9]+ at .*\n.*Existing local tuple \(33\); replica identity \(a\)=\(33\)/
qr/conflict detected on relation "public.tab": conflict=delete_origin_differs.*\n.*DETAIL:.* Deleting the row that was modified by a different origin ".*" in transaction [0-9]+ at .*\n.*Existing local row \(33\); replica identity \(a\)=\(33\)/
);
# The remaining tests no longer test conflict detection.

View File

@@ -79,11 +79,11 @@ $node_publisher->safe_psql('postgres',
$node_subscriber->wait_for_log(
qr/conflict detected on relation \"public.conf_tab\": conflict=multiple_unique_conflicts.*
.*Key already exists in unique index \"conf_tab_pkey\".*
.*Key \(a\)=\(2\); existing local tuple \(2, 2, 2\); remote tuple \(2, 3, 4\).*
.*Key \(a\)=\(2\); existing local row \(2, 2, 2\); remote row \(2, 3, 4\).*
.*Key already exists in unique index \"conf_tab_b_key\".*
.*Key \(b\)=\(3\); existing local tuple \(3, 3, 3\); remote tuple \(2, 3, 4\).*
.*Key \(b\)=\(3\); existing local row \(3, 3, 3\); remote row \(2, 3, 4\).*
.*Key already exists in unique index \"conf_tab_c_key\".*
.*Key \(c\)=\(4\); existing local tuple \(4, 4, 4\); remote tuple \(2, 3, 4\)./,
.*Key \(c\)=\(4\); existing local row \(4, 4, 4\); remote row \(2, 3, 4\)./,
$log_offset);
pass('multiple_unique_conflicts detected during insert');
@@ -111,11 +111,11 @@ $node_publisher->safe_psql('postgres',
$node_subscriber->wait_for_log(
qr/conflict detected on relation \"public.conf_tab\": conflict=multiple_unique_conflicts.*
.*Key already exists in unique index \"conf_tab_pkey\".*
.*Key \(a\)=\(6\); existing local tuple \(6, 6, 6\); remote tuple \(6, 7, 8\).*
.*Key \(a\)=\(6\); existing local row \(6, 6, 6\); remote row \(6, 7, 8\).*
.*Key already exists in unique index \"conf_tab_b_key\".*
.*Key \(b\)=\(7\); existing local tuple \(7, 7, 7\); remote tuple \(6, 7, 8\).*
.*Key \(b\)=\(7\); existing local row \(7, 7, 7\); remote row \(6, 7, 8\).*
.*Key already exists in unique index \"conf_tab_c_key\".*
.*Key \(c\)=\(8\); existing local tuple \(8, 8, 8\); remote tuple \(6, 7, 8\)./,
.*Key \(c\)=\(8\); existing local row \(8, 8, 8\); remote row \(6, 7, 8\)./,
$log_offset);
pass('multiple_unique_conflicts detected during update');
@@ -139,9 +139,9 @@ $node_publisher->safe_psql('postgres',
$node_subscriber->wait_for_log(
qr/conflict detected on relation \"public.conf_tab_2_p1\": conflict=multiple_unique_conflicts.*
.*Key already exists in unique index \"conf_tab_2_p1_pkey\".*
.*Key \(a\)=\(55\); existing local tuple \(55, 2, 3\); remote tuple \(55, 2, 3\).*
.*Key \(a\)=\(55\); existing local row \(55, 2, 3\); remote row \(55, 2, 3\).*
.*Key already exists in unique index \"conf_tab_2_p1_a_b_key\".*
.*Key \(a, b\)=\(55, 2\); existing local tuple \(55, 2, 3\); remote tuple \(55, 2, 3\)./,
.*Key \(a, b\)=\(55, 2\); existing local row \(55, 2, 3\); remote row \(55, 2, 3\)./,
$log_offset);
pass('multiple_unique_conflicts detected on a leaf partition during insert');