@@ -220,41 +220,63 @@ logicalrep_rel_att_by_name(LogicalRepRelation *remoterel, const char *attname)
220
220
}
221
221
222
222
/*
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.
224
225
*/
225
- static void
226
- logicalrep_report_missing_attrs (LogicalRepRelation * remoterel ,
227
- Bitmapset * missingatts )
226
+ static char *
227
+ logicalrep_get_attrs_str (LogicalRepRelation * remoterel , Bitmapset * atts )
228
228
{
229
- if (!bms_is_empty (missingatts ))
229
+ StringInfoData attsbuf ;
230
+ int attcnt = 0 ;
231
+ int i = -1 ;
232
+
233
+ Assert (!bms_is_empty (atts ));
234
+
235
+ initStringInfo (& attsbuf );
236
+
237
+ while ((i = bms_next_member (atts , i )) >= 0 )
230
238
{
231
- StringInfoData missingattsbuf ;
232
- int missingattcnt = 0 ;
233
- int i ;
239
+ attcnt ++ ;
240
+ if ( attcnt > 1 )
241
+ appendStringInfo ( & attsbuf , _ ( ", " )) ;
234
242
235
- initStringInfo (& missingattsbuf );
243
+ appendStringInfo (& attsbuf , _ ("\"%s\"" ), remoterel -> attnames [i ]);
244
+ }
236
245
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
+ return attsbuf .data ;
247
+ }
248
248
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
+ static void
255
+ logicalrep_report_missing_or_gen_attrs (LogicalRepRelation * remoterel ,
256
+ Bitmapset * missingatts ,
257
+ Bitmapset * generatedatts )
258
+ {
259
+ if (!bms_is_empty (missingatts ))
249
260
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 )));
258
280
}
259
281
260
282
/*
@@ -380,6 +402,7 @@ logicalrep_rel_open(LogicalRepRelId remoteid, LOCKMODE lockmode)
380
402
MemoryContext oldctx ;
381
403
int i ;
382
404
Bitmapset * missingatts ;
405
+ Bitmapset * generatedattrs = NULL ;
383
406
384
407
/* Release the no-longer-useful attrmap, if any. */
385
408
if (entry -> attrmap )
@@ -421,7 +444,7 @@ logicalrep_rel_open(LogicalRepRelId remoteid, LOCKMODE lockmode)
421
444
int attnum ;
422
445
Form_pg_attribute attr = TupleDescAttr (desc , i );
423
446
424
- if (attr -> attisdropped || attr -> attgenerated )
447
+ if (attr -> attisdropped )
425
448
{
426
449
entry -> attrmap -> attnums [i ] = -1 ;
427
450
continue ;
@@ -432,12 +455,20 @@ logicalrep_rel_open(LogicalRepRelId remoteid, LOCKMODE lockmode)
432
455
433
456
entry -> attrmap -> attnums [i ] = attnum ;
434
457
if (attnum >= 0 )
458
+ {
459
+ /* Remember which subscriber columns are generated. */
460
+ if (attr -> attgenerated )
461
+ generatedattrs = bms_add_member (generatedattrs , attnum );
462
+
435
463
missingatts = bms_del_member (missingatts , attnum );
464
+ }
436
465
}
437
466
438
- logicalrep_report_missing_attrs (remoterel , missingatts );
467
+ logicalrep_report_missing_or_gen_attrs (remoterel , missingatts ,
468
+ generatedattrs );
439
469
440
470
/* be tidy */
471
+ bms_free (generatedattrs );
441
472
bms_free (missingatts );
442
473
443
474
/*
0 commit comments