Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit8fcd802

Browse files
author
Amit Kapila
committed
Improve error message for replication of generated columns.
Currently, logical replication produces a generic error message whentargeting a subscriber-side table column that is either missing orgenerated. The error message can be misleading for generated columns.This patch introduces a specific error message to clarify the issue whengenerated columns are involved.Author: Shubham KhannaReviewed-by: Peter Smith, Vignesh C, Amit KapilaDiscussion:https://postgr.es/m/CAHv8RjJBvYtqU7OAofBizOmQOK2Q8h+w9v2_cQWxT_gO7er3Aw@mail.gmail.com
1 parentd0eb429 commit8fcd802

File tree

2 files changed

+103
-30
lines changed

2 files changed

+103
-30
lines changed

‎src/backend/replication/logical/relation.c

Lines changed: 61 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -220,41 +220,63 @@ logicalrep_rel_att_by_name(LogicalRepRelation *remoterel, const char *attname)
220220
}
221221

222222
/*
223-
* Report error with names of the missing local relation column(s), if any.
223+
* Returns a comma-separated string of attribute names based on the provided
224+
* relation and bitmap indicating which attributes to include.
224225
*/
225-
staticvoid
226-
logicalrep_report_missing_attrs(LogicalRepRelation*remoterel,
227-
Bitmapset*missingatts)
226+
staticchar*
227+
logicalrep_get_attrs_str(LogicalRepRelation*remoterel,Bitmapset*atts)
228228
{
229-
if (!bms_is_empty(missingatts))
229+
StringInfoDataattsbuf;
230+
intattcnt=0;
231+
inti=-1;
232+
233+
Assert(!bms_is_empty(atts));
234+
235+
initStringInfo(&attsbuf);
236+
237+
while ((i=bms_next_member(atts,i)) >=0)
230238
{
231-
StringInfoDatamissingattsbuf;
232-
intmissingattcnt=0;
233-
inti;
239+
attcnt++;
240+
if (attcnt>1)
241+
appendStringInfo(&attsbuf,_(", "));
234242

235-
initStringInfo(&missingattsbuf);
243+
appendStringInfo(&attsbuf,_("\"%s\""),remoterel->attnames[i]);
244+
}
236245

237-
i=-1;
238-
while ((i=bms_next_member(missingatts,i)) >=0)
239-
{
240-
missingattcnt++;
241-
if (missingattcnt==1)
242-
appendStringInfo(&missingattsbuf,_("\"%s\""),
243-
remoterel->attnames[i]);
244-
else
245-
appendStringInfo(&missingattsbuf,_(", \"%s\""),
246-
remoterel->attnames[i]);
247-
}
246+
returnattsbuf.data;
247+
}
248248

249+
/*
250+
* If attempting to replicate missing or generated columns, report an error.
251+
* Prioritize 'missing' errors if both occur though the prioritization is
252+
* arbitrary.
253+
*/
254+
staticvoid
255+
logicalrep_report_missing_or_gen_attrs(LogicalRepRelation*remoterel,
256+
Bitmapset*missingatts,
257+
Bitmapset*generatedatts)
258+
{
259+
if (!bms_is_empty(missingatts))
249260
ereport(ERROR,
250-
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
251-
errmsg_plural("logical replication target relation \"%s.%s\" is missing replicated column: %s",
252-
"logical replication target relation \"%s.%s\" is missing replicated columns: %s",
253-
missingattcnt,
254-
remoterel->nspname,
255-
remoterel->relname,
256-
missingattsbuf.data)));
257-
}
261+
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
262+
errmsg_plural("logical replication target relation \"%s.%s\" is missing replicated column: %s",
263+
"logical replication target relation \"%s.%s\" is missing replicated columns: %s",
264+
bms_num_members(missingatts),
265+
remoterel->nspname,
266+
remoterel->relname,
267+
logicalrep_get_attrs_str(remoterel,
268+
missingatts)));
269+
270+
if (!bms_is_empty(generatedatts))
271+
ereport(ERROR,
272+
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
273+
errmsg_plural("logical replication target relation \"%s.%s\" has incompatible generated column: %s",
274+
"logical replication target relation \"%s.%s\" has incompatible generated columns: %s",
275+
bms_num_members(generatedatts),
276+
remoterel->nspname,
277+
remoterel->relname,
278+
logicalrep_get_attrs_str(remoterel,
279+
generatedatts)));
258280
}
259281

260282
/*
@@ -380,6 +402,7 @@ logicalrep_rel_open(LogicalRepRelId remoteid, LOCKMODE lockmode)
380402
MemoryContextoldctx;
381403
inti;
382404
Bitmapset*missingatts;
405+
Bitmapset*generatedattrs=NULL;
383406

384407
/* Release the no-longer-useful attrmap, if any. */
385408
if (entry->attrmap)
@@ -421,7 +444,7 @@ logicalrep_rel_open(LogicalRepRelId remoteid, LOCKMODE lockmode)
421444
intattnum;
422445
Form_pg_attributeattr=TupleDescAttr(desc,i);
423446

424-
if (attr->attisdropped||attr->attgenerated)
447+
if (attr->attisdropped)
425448
{
426449
entry->attrmap->attnums[i]=-1;
427450
continue;
@@ -432,12 +455,20 @@ logicalrep_rel_open(LogicalRepRelId remoteid, LOCKMODE lockmode)
432455

433456
entry->attrmap->attnums[i]=attnum;
434457
if (attnum >=0)
458+
{
459+
/* Remember which subscriber columns are generated. */
460+
if (attr->attgenerated)
461+
generatedattrs=bms_add_member(generatedattrs,attnum);
462+
435463
missingatts=bms_del_member(missingatts,attnum);
464+
}
436465
}
437466

438-
logicalrep_report_missing_attrs(remoterel,missingatts);
467+
logicalrep_report_missing_or_gen_attrs(remoterel,missingatts,
468+
generatedattrs);
439469

440470
/* be tidy */
471+
bms_free(generatedattrs);
441472
bms_free(missingatts);
442473

443474
/*

‎src/test/subscription/t/011_generated.pl

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,4 +326,46 @@ BEGIN
326326
$node_subscriber->safe_psql('postgres',"DROP SUBSCRIPTION sub1");
327327
$node_publisher->safe_psql('postgres',"DROP PUBLICATION pub1");
328328

329+
# =============================================================================
330+
# The following test verifies the expected error when replicating to a
331+
# generated subscriber column. Test the following combinations:
332+
# - regular -> generated
333+
# - generated -> generated
334+
# =============================================================================
335+
336+
# --------------------------------------------------
337+
# A "regular -> generated" or "generated -> generated" replication fails,
338+
# reporting an error that the generated column on the subscriber side cannot
339+
# be replicated.
340+
#
341+
# Test Case: regular -> generated and generated -> generated
342+
# Publisher table has regular column 'c2' and generated column 'c3'.
343+
# Subscriber table has generated columns 'c2' and 'c3'.
344+
# --------------------------------------------------
345+
346+
# Create table and publication. Insert data into the table.
347+
$node_publisher->safe_psql(
348+
'postgres',qq(
349+
CREATE TABLE t1(c1 int, c2 int, c3 int GENERATED ALWAYS AS (c1 * 2) STORED);
350+
CREATE PUBLICATION pub1 for table t1(c1, c2, c3);
351+
INSERT INTO t1 VALUES (1);
352+
));
353+
354+
# Create table and subscription.
355+
$node_subscriber->safe_psql(
356+
'postgres',qq(
357+
CREATE TABLE t1(c1 int, c2 int GENERATED ALWAYS AS (c1 + 2) STORED, c3 int GENERATED ALWAYS AS (c1 + 2) STORED);
358+
CREATE SUBSCRIPTION sub1 CONNECTION '$publisher_connstr' PUBLICATION pub1;
359+
));
360+
361+
# Verify that an error occurs.
362+
my$offset =-s$node_subscriber->logfile;
363+
$node_subscriber->wait_for_log(
364+
qr/ERROR: ( [A-Z0-9]:)? logical replication target relation "public.t1" has incompatible generated columns: "c2", "c3"/,
365+
$offset);
366+
367+
# cleanup
368+
$node_subscriber->safe_psql('postgres',"DROP SUBSCRIPTION sub1");
369+
$node_publisher->safe_psql('postgres',"DROP PUBLICATION pub1");
370+
329371
done_testing();

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp