From 91bcea20aa150d38ada10fcdfb3ffa682c75630d Mon Sep 17 00:00:00 2001
From: Zhijie Hou <houzj.fnst@fujitsu.com>
Date: Thu, 28 Aug 2025 12:55:49 +0800
Subject: [PATCH v3] PG13 Fix replica identity check for INSERT ON CONFLICT

This commit enforces proper checks for INSERT ON CONFLICT DO UPDATE command to
determine if it can be executed with current replica identity. Previously, only
the executability of the INSERT command was validated, missing checks for the
UPDATE operations that can occur within this command. To fix it, validate the
executability of the UPDATE operation as part of the ON CONFLICT DO UPDATE
command.
---
 src/backend/catalog/system_constraints.sql | 218 ++++++++++++++++++
 src/backend/catalog/system_fk_info.h       | 253 +++++++++++++++++++++
 src/backend/executor/execMain.c            |  23 +-
 src/backend/executor/execPartition.c       |   9 +-
 src/backend/executor/nodeModifyTable.c     |   3 +-
 src/include/executor/executor.h            |   2 +
 src/test/regress/expected/publication.out  |  23 ++
 src/test/regress/sql/publication.sql       |  26 +++
 8 files changed, 553 insertions(+), 4 deletions(-)
 create mode 100644 src/backend/catalog/system_constraints.sql
 create mode 100644 src/backend/catalog/system_fk_info.h

diff --git a/src/backend/catalog/system_constraints.sql b/src/backend/catalog/system_constraints.sql
new file mode 100644
index 00000000000..854de5c80fb
--- /dev/null
+++ b/src/backend/catalog/system_constraints.sql
@@ -0,0 +1,218 @@
+ALTER TABLE pg_proc ADD PRIMARY KEY USING INDEX pg_proc_oid_index;
+
+ALTER TABLE pg_proc ADD UNIQUE USING INDEX pg_proc_proname_args_nsp_index;
+
+ALTER TABLE pg_type ADD PRIMARY KEY USING INDEX pg_type_oid_index;
+
+ALTER TABLE pg_type ADD UNIQUE USING INDEX pg_type_typname_nsp_index;
+
+ALTER TABLE pg_attribute ADD UNIQUE USING INDEX pg_attribute_relid_attnam_index;
+
+ALTER TABLE pg_attribute ADD PRIMARY KEY USING INDEX pg_attribute_relid_attnum_index;
+
+ALTER TABLE pg_class ADD PRIMARY KEY USING INDEX pg_class_oid_index;
+
+ALTER TABLE pg_class ADD UNIQUE USING INDEX pg_class_relname_nsp_index;
+
+ALTER TABLE pg_attrdef ADD UNIQUE USING INDEX pg_attrdef_adrelid_adnum_index;
+
+ALTER TABLE pg_attrdef ADD PRIMARY KEY USING INDEX pg_attrdef_oid_index;
+
+ALTER TABLE pg_constraint ADD UNIQUE USING INDEX pg_constraint_conrelid_contypid_conname_index;
+
+ALTER TABLE pg_constraint ADD PRIMARY KEY USING INDEX pg_constraint_oid_index;
+
+ALTER TABLE pg_inherits ADD PRIMARY KEY USING INDEX pg_inherits_relid_seqno_index;
+
+ALTER TABLE pg_index ADD PRIMARY KEY USING INDEX pg_index_indexrelid_index;
+
+ALTER TABLE pg_operator ADD PRIMARY KEY USING INDEX pg_operator_oid_index;
+
+ALTER TABLE pg_operator ADD UNIQUE USING INDEX pg_operator_oprname_l_r_n_index;
+
+ALTER TABLE pg_opfamily ADD UNIQUE USING INDEX pg_opfamily_am_name_nsp_index;
+
+ALTER TABLE pg_opfamily ADD PRIMARY KEY USING INDEX pg_opfamily_oid_index;
+
+ALTER TABLE pg_opclass ADD UNIQUE USING INDEX pg_opclass_am_name_nsp_index;
+
+ALTER TABLE pg_opclass ADD PRIMARY KEY USING INDEX pg_opclass_oid_index;
+
+ALTER TABLE pg_am ADD UNIQUE USING INDEX pg_am_name_index;
+
+ALTER TABLE pg_am ADD PRIMARY KEY USING INDEX pg_am_oid_index;
+
+ALTER TABLE pg_amop ADD UNIQUE USING INDEX pg_amop_fam_strat_index;
+
+ALTER TABLE pg_amop ADD UNIQUE USING INDEX pg_amop_opr_fam_index;
+
+ALTER TABLE pg_amop ADD PRIMARY KEY USING INDEX pg_amop_oid_index;
+
+ALTER TABLE pg_amproc ADD UNIQUE USING INDEX pg_amproc_fam_proc_index;
+
+ALTER TABLE pg_amproc ADD PRIMARY KEY USING INDEX pg_amproc_oid_index;
+
+ALTER TABLE pg_language ADD UNIQUE USING INDEX pg_language_name_index;
+
+ALTER TABLE pg_language ADD PRIMARY KEY USING INDEX pg_language_oid_index;
+
+ALTER TABLE pg_largeobject_metadata ADD PRIMARY KEY USING INDEX pg_largeobject_metadata_oid_index;
+
+ALTER TABLE pg_largeobject ADD PRIMARY KEY USING INDEX pg_largeobject_loid_pn_index;
+
+ALTER TABLE pg_aggregate ADD PRIMARY KEY USING INDEX pg_aggregate_fnoid_index;
+
+ALTER TABLE pg_statistic ADD PRIMARY KEY USING INDEX pg_statistic_relid_att_inh_index;
+
+ALTER TABLE pg_statistic_ext ADD PRIMARY KEY USING INDEX pg_statistic_ext_oid_index;
+
+ALTER TABLE pg_statistic_ext ADD UNIQUE USING INDEX pg_statistic_ext_name_index;
+
+ALTER TABLE pg_statistic_ext_data ADD PRIMARY KEY USING INDEX pg_statistic_ext_data_stxoid_inh_index;
+
+ALTER TABLE pg_rewrite ADD PRIMARY KEY USING INDEX pg_rewrite_oid_index;
+
+ALTER TABLE pg_rewrite ADD UNIQUE USING INDEX pg_rewrite_rel_rulename_index;
+
+ALTER TABLE pg_trigger ADD UNIQUE USING INDEX pg_trigger_tgrelid_tgname_index;
+
+ALTER TABLE pg_trigger ADD PRIMARY KEY USING INDEX pg_trigger_oid_index;
+
+ALTER TABLE pg_event_trigger ADD UNIQUE USING INDEX pg_event_trigger_evtname_index;
+
+ALTER TABLE pg_event_trigger ADD PRIMARY KEY USING INDEX pg_event_trigger_oid_index;
+
+ALTER TABLE pg_description ADD PRIMARY KEY USING INDEX pg_description_o_c_o_index;
+
+ALTER TABLE pg_cast ADD PRIMARY KEY USING INDEX pg_cast_oid_index;
+
+ALTER TABLE pg_cast ADD UNIQUE USING INDEX pg_cast_source_target_index;
+
+ALTER TABLE pg_enum ADD PRIMARY KEY USING INDEX pg_enum_oid_index;
+
+ALTER TABLE pg_enum ADD UNIQUE USING INDEX pg_enum_typid_label_index;
+
+ALTER TABLE pg_enum ADD UNIQUE USING INDEX pg_enum_typid_sortorder_index;
+
+ALTER TABLE pg_namespace ADD UNIQUE USING INDEX pg_namespace_nspname_index;
+
+ALTER TABLE pg_namespace ADD PRIMARY KEY USING INDEX pg_namespace_oid_index;
+
+ALTER TABLE pg_conversion ADD UNIQUE USING INDEX pg_conversion_default_index;
+
+ALTER TABLE pg_conversion ADD UNIQUE USING INDEX pg_conversion_name_nsp_index;
+
+ALTER TABLE pg_conversion ADD PRIMARY KEY USING INDEX pg_conversion_oid_index;
+
+ALTER TABLE pg_database ADD UNIQUE USING INDEX pg_database_datname_index;
+
+ALTER TABLE pg_database ADD PRIMARY KEY USING INDEX pg_database_oid_index;
+
+ALTER TABLE pg_db_role_setting ADD PRIMARY KEY USING INDEX pg_db_role_setting_databaseid_rol_index;
+
+ALTER TABLE pg_tablespace ADD PRIMARY KEY USING INDEX pg_tablespace_oid_index;
+
+ALTER TABLE pg_tablespace ADD UNIQUE USING INDEX pg_tablespace_spcname_index;
+
+ALTER TABLE pg_authid ADD UNIQUE USING INDEX pg_authid_rolname_index;
+
+ALTER TABLE pg_authid ADD PRIMARY KEY USING INDEX pg_authid_oid_index;
+
+ALTER TABLE pg_auth_members ADD PRIMARY KEY USING INDEX pg_auth_members_role_member_index;
+
+ALTER TABLE pg_auth_members ADD UNIQUE USING INDEX pg_auth_members_member_role_index;
+
+ALTER TABLE pg_shdescription ADD PRIMARY KEY USING INDEX pg_shdescription_o_c_index;
+
+ALTER TABLE pg_ts_config ADD UNIQUE USING INDEX pg_ts_config_cfgname_index;
+
+ALTER TABLE pg_ts_config ADD PRIMARY KEY USING INDEX pg_ts_config_oid_index;
+
+ALTER TABLE pg_ts_config_map ADD PRIMARY KEY USING INDEX pg_ts_config_map_index;
+
+ALTER TABLE pg_ts_dict ADD UNIQUE USING INDEX pg_ts_dict_dictname_index;
+
+ALTER TABLE pg_ts_dict ADD PRIMARY KEY USING INDEX pg_ts_dict_oid_index;
+
+ALTER TABLE pg_ts_parser ADD UNIQUE USING INDEX pg_ts_parser_prsname_index;
+
+ALTER TABLE pg_ts_parser ADD PRIMARY KEY USING INDEX pg_ts_parser_oid_index;
+
+ALTER TABLE pg_ts_template ADD UNIQUE USING INDEX pg_ts_template_tmplname_index;
+
+ALTER TABLE pg_ts_template ADD PRIMARY KEY USING INDEX pg_ts_template_oid_index;
+
+ALTER TABLE pg_extension ADD PRIMARY KEY USING INDEX pg_extension_oid_index;
+
+ALTER TABLE pg_extension ADD UNIQUE USING INDEX pg_extension_name_index;
+
+ALTER TABLE pg_foreign_data_wrapper ADD PRIMARY KEY USING INDEX pg_foreign_data_wrapper_oid_index;
+
+ALTER TABLE pg_foreign_data_wrapper ADD UNIQUE USING INDEX pg_foreign_data_wrapper_name_index;
+
+ALTER TABLE pg_foreign_server ADD PRIMARY KEY USING INDEX pg_foreign_server_oid_index;
+
+ALTER TABLE pg_foreign_server ADD UNIQUE USING INDEX pg_foreign_server_name_index;
+
+ALTER TABLE pg_user_mapping ADD PRIMARY KEY USING INDEX pg_user_mapping_oid_index;
+
+ALTER TABLE pg_user_mapping ADD UNIQUE USING INDEX pg_user_mapping_user_server_index;
+
+ALTER TABLE pg_foreign_table ADD PRIMARY KEY USING INDEX pg_foreign_table_relid_index;
+
+ALTER TABLE pg_policy ADD PRIMARY KEY USING INDEX pg_policy_oid_index;
+
+ALTER TABLE pg_policy ADD UNIQUE USING INDEX pg_policy_polrelid_polname_index;
+
+ALTER TABLE pg_replication_origin ADD PRIMARY KEY USING INDEX pg_replication_origin_roiident_index;
+
+ALTER TABLE pg_replication_origin ADD UNIQUE USING INDEX pg_replication_origin_roname_index;
+
+ALTER TABLE pg_default_acl ADD UNIQUE USING INDEX pg_default_acl_role_nsp_obj_index;
+
+ALTER TABLE pg_default_acl ADD PRIMARY KEY USING INDEX pg_default_acl_oid_index;
+
+ALTER TABLE pg_init_privs ADD PRIMARY KEY USING INDEX pg_init_privs_o_c_o_index;
+
+ALTER TABLE pg_seclabel ADD PRIMARY KEY USING INDEX pg_seclabel_object_index;
+
+ALTER TABLE pg_shseclabel ADD PRIMARY KEY USING INDEX pg_shseclabel_object_index;
+
+ALTER TABLE pg_collation ADD UNIQUE USING INDEX pg_collation_name_enc_nsp_index;
+
+ALTER TABLE pg_collation ADD PRIMARY KEY USING INDEX pg_collation_oid_index;
+
+ALTER TABLE pg_parameter_acl ADD UNIQUE USING INDEX pg_parameter_acl_parname_index;
+
+ALTER TABLE pg_parameter_acl ADD PRIMARY KEY USING INDEX pg_parameter_acl_oid_index;
+
+ALTER TABLE pg_partitioned_table ADD PRIMARY KEY USING INDEX pg_partitioned_table_partrelid_index;
+
+ALTER TABLE pg_range ADD PRIMARY KEY USING INDEX pg_range_rngtypid_index;
+
+ALTER TABLE pg_range ADD UNIQUE USING INDEX pg_range_rngmultitypid_index;
+
+ALTER TABLE pg_transform ADD PRIMARY KEY USING INDEX pg_transform_oid_index;
+
+ALTER TABLE pg_transform ADD UNIQUE USING INDEX pg_transform_type_lang_index;
+
+ALTER TABLE pg_sequence ADD PRIMARY KEY USING INDEX pg_sequence_seqrelid_index;
+
+ALTER TABLE pg_publication ADD PRIMARY KEY USING INDEX pg_publication_oid_index;
+
+ALTER TABLE pg_publication ADD UNIQUE USING INDEX pg_publication_pubname_index;
+
+ALTER TABLE pg_publication_namespace ADD PRIMARY KEY USING INDEX pg_publication_namespace_oid_index;
+
+ALTER TABLE pg_publication_namespace ADD UNIQUE USING INDEX pg_publication_namespace_pnnspid_pnpubid_index;
+
+ALTER TABLE pg_publication_rel ADD PRIMARY KEY USING INDEX pg_publication_rel_oid_index;
+
+ALTER TABLE pg_publication_rel ADD UNIQUE USING INDEX pg_publication_rel_prrelid_prpubid_index;
+
+ALTER TABLE pg_subscription ADD PRIMARY KEY USING INDEX pg_subscription_oid_index;
+
+ALTER TABLE pg_subscription ADD UNIQUE USING INDEX pg_subscription_subname_index;
+
+ALTER TABLE pg_subscription_rel ADD PRIMARY KEY USING INDEX pg_subscription_rel_srrelid_srsubid_index;
+
diff --git a/src/backend/catalog/system_fk_info.h b/src/backend/catalog/system_fk_info.h
new file mode 100644
index 00000000000..a90119b4cf4
--- /dev/null
+++ b/src/backend/catalog/system_fk_info.h
@@ -0,0 +1,253 @@
+/*-------------------------------------------------------------------------
+ *
+ * system_fk_info.h
+ *    Data about the foreign-key relationships in the system catalogs
+ *
+ * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ *  ******************************
+ *  *** DO NOT EDIT THIS FILE! ***
+ *  ******************************
+ *
+ *  It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SYSTEM_FK_INFO_H
+#define SYSTEM_FK_INFO_H
+
+typedef struct SysFKRelationship
+{
+	Oid			fk_table;		/* referencing catalog */
+	Oid			pk_table;		/* referenced catalog */
+	const char *fk_columns;		/* referencing column name(s) */
+	const char *pk_columns;		/* referenced column name(s) */
+	bool		is_array;		/* if true, last fk_column is an array */
+	bool		is_opt;			/* if true, fk_column can be zero */
+} SysFKRelationship;
+
+static const SysFKRelationship sys_fk_relationships[] = {
+	{ /* pg_proc */ 1255, /* pg_namespace */ 2615, "{pronamespace}", "{oid}", false, false},
+	{ /* pg_proc */ 1255, /* pg_authid */ 1260, "{proowner}", "{oid}", false, false},
+	{ /* pg_proc */ 1255, /* pg_language */ 2612, "{prolang}", "{oid}", false, false},
+	{ /* pg_proc */ 1255, /* pg_type */ 1247, "{provariadic}", "{oid}", false, true},
+	{ /* pg_proc */ 1255, /* pg_proc */ 1255, "{prosupport}", "{oid}", false, true},
+	{ /* pg_proc */ 1255, /* pg_type */ 1247, "{prorettype}", "{oid}", false, false},
+	{ /* pg_proc */ 1255, /* pg_type */ 1247, "{proargtypes}", "{oid}", true, false},
+	{ /* pg_proc */ 1255, /* pg_type */ 1247, "{proallargtypes}", "{oid}", true, false},
+	{ /* pg_proc */ 1255, /* pg_type */ 1247, "{protrftypes}", "{oid}", true, false},
+	{ /* pg_type */ 1247, /* pg_namespace */ 2615, "{typnamespace}", "{oid}", false, false},
+	{ /* pg_type */ 1247, /* pg_authid */ 1260, "{typowner}", "{oid}", false, false},
+	{ /* pg_type */ 1247, /* pg_class */ 1259, "{typrelid}", "{oid}", false, true},
+	{ /* pg_type */ 1247, /* pg_proc */ 1255, "{typsubscript}", "{oid}", false, true},
+	{ /* pg_type */ 1247, /* pg_type */ 1247, "{typelem}", "{oid}", false, true},
+	{ /* pg_type */ 1247, /* pg_type */ 1247, "{typarray}", "{oid}", false, true},
+	{ /* pg_type */ 1247, /* pg_proc */ 1255, "{typinput}", "{oid}", false, false},
+	{ /* pg_type */ 1247, /* pg_proc */ 1255, "{typoutput}", "{oid}", false, false},
+	{ /* pg_type */ 1247, /* pg_proc */ 1255, "{typreceive}", "{oid}", false, true},
+	{ /* pg_type */ 1247, /* pg_proc */ 1255, "{typsend}", "{oid}", false, true},
+	{ /* pg_type */ 1247, /* pg_proc */ 1255, "{typmodin}", "{oid}", false, true},
+	{ /* pg_type */ 1247, /* pg_proc */ 1255, "{typmodout}", "{oid}", false, true},
+	{ /* pg_type */ 1247, /* pg_proc */ 1255, "{typanalyze}", "{oid}", false, true},
+	{ /* pg_type */ 1247, /* pg_type */ 1247, "{typbasetype}", "{oid}", false, true},
+	{ /* pg_type */ 1247, /* pg_collation */ 3456, "{typcollation}", "{oid}", false, true},
+	{ /* pg_attribute */ 1249, /* pg_class */ 1259, "{attrelid}", "{oid}", false, false},
+	{ /* pg_attribute */ 1249, /* pg_type */ 1247, "{atttypid}", "{oid}", false, true},
+	{ /* pg_attribute */ 1249, /* pg_collation */ 3456, "{attcollation}", "{oid}", false, true},
+	{ /* pg_class */ 1259, /* pg_namespace */ 2615, "{relnamespace}", "{oid}", false, false},
+	{ /* pg_class */ 1259, /* pg_type */ 1247, "{reltype}", "{oid}", false, true},
+	{ /* pg_class */ 1259, /* pg_type */ 1247, "{reloftype}", "{oid}", false, true},
+	{ /* pg_class */ 1259, /* pg_authid */ 1260, "{relowner}", "{oid}", false, false},
+	{ /* pg_class */ 1259, /* pg_am */ 2601, "{relam}", "{oid}", false, true},
+	{ /* pg_class */ 1259, /* pg_tablespace */ 1213, "{reltablespace}", "{oid}", false, true},
+	{ /* pg_class */ 1259, /* pg_class */ 1259, "{reltoastrelid}", "{oid}", false, true},
+	{ /* pg_class */ 1259, /* pg_class */ 1259, "{relrewrite}", "{oid}", false, true},
+	{ /* pg_attrdef */ 2604, /* pg_class */ 1259, "{adrelid}", "{oid}", false, false},
+	{ /* pg_attrdef */ 2604, /* pg_attribute */ 1249, "{adrelid, adnum}", "{attrelid, attnum}", false, false},
+	{ /* pg_constraint */ 2606, /* pg_namespace */ 2615, "{connamespace}", "{oid}", false, false},
+	{ /* pg_constraint */ 2606, /* pg_class */ 1259, "{conrelid}", "{oid}", false, true},
+	{ /* pg_constraint */ 2606, /* pg_type */ 1247, "{contypid}", "{oid}", false, true},
+	{ /* pg_constraint */ 2606, /* pg_class */ 1259, "{conindid}", "{oid}", false, true},
+	{ /* pg_constraint */ 2606, /* pg_constraint */ 2606, "{conparentid}", "{oid}", false, true},
+	{ /* pg_constraint */ 2606, /* pg_class */ 1259, "{confrelid}", "{oid}", false, true},
+	{ /* pg_constraint */ 2606, /* pg_operator */ 2617, "{conpfeqop}", "{oid}", true, false},
+	{ /* pg_constraint */ 2606, /* pg_operator */ 2617, "{conppeqop}", "{oid}", true, false},
+	{ /* pg_constraint */ 2606, /* pg_operator */ 2617, "{conffeqop}", "{oid}", true, false},
+	{ /* pg_constraint */ 2606, /* pg_operator */ 2617, "{conexclop}", "{oid}", true, false},
+	{ /* pg_constraint */ 2606, /* pg_attribute */ 1249, "{conrelid, conkey}", "{attrelid, attnum}", true, true},
+	{ /* pg_constraint */ 2606, /* pg_attribute */ 1249, "{confrelid, confkey}", "{attrelid, attnum}", true, false},
+	{ /* pg_inherits */ 2611, /* pg_class */ 1259, "{inhrelid}", "{oid}", false, false},
+	{ /* pg_inherits */ 2611, /* pg_class */ 1259, "{inhparent}", "{oid}", false, false},
+	{ /* pg_index */ 2610, /* pg_class */ 1259, "{indexrelid}", "{oid}", false, false},
+	{ /* pg_index */ 2610, /* pg_class */ 1259, "{indrelid}", "{oid}", false, false},
+	{ /* pg_index */ 2610, /* pg_collation */ 3456, "{indcollation}", "{oid}", true, true},
+	{ /* pg_index */ 2610, /* pg_opclass */ 2616, "{indclass}", "{oid}", true, false},
+	{ /* pg_index */ 2610, /* pg_attribute */ 1249, "{indrelid, indkey}", "{attrelid, attnum}", true, true},
+	{ /* pg_operator */ 2617, /* pg_namespace */ 2615, "{oprnamespace}", "{oid}", false, false},
+	{ /* pg_operator */ 2617, /* pg_authid */ 1260, "{oprowner}", "{oid}", false, false},
+	{ /* pg_operator */ 2617, /* pg_type */ 1247, "{oprleft}", "{oid}", false, true},
+	{ /* pg_operator */ 2617, /* pg_type */ 1247, "{oprright}", "{oid}", false, false},
+	{ /* pg_operator */ 2617, /* pg_type */ 1247, "{oprresult}", "{oid}", false, true},
+	{ /* pg_operator */ 2617, /* pg_operator */ 2617, "{oprcom}", "{oid}", false, true},
+	{ /* pg_operator */ 2617, /* pg_operator */ 2617, "{oprnegate}", "{oid}", false, true},
+	{ /* pg_operator */ 2617, /* pg_proc */ 1255, "{oprcode}", "{oid}", false, true},
+	{ /* pg_operator */ 2617, /* pg_proc */ 1255, "{oprrest}", "{oid}", false, true},
+	{ /* pg_operator */ 2617, /* pg_proc */ 1255, "{oprjoin}", "{oid}", false, true},
+	{ /* pg_opfamily */ 2753, /* pg_am */ 2601, "{opfmethod}", "{oid}", false, false},
+	{ /* pg_opfamily */ 2753, /* pg_namespace */ 2615, "{opfnamespace}", "{oid}", false, false},
+	{ /* pg_opfamily */ 2753, /* pg_authid */ 1260, "{opfowner}", "{oid}", false, false},
+	{ /* pg_opclass */ 2616, /* pg_am */ 2601, "{opcmethod}", "{oid}", false, false},
+	{ /* pg_opclass */ 2616, /* pg_namespace */ 2615, "{opcnamespace}", "{oid}", false, false},
+	{ /* pg_opclass */ 2616, /* pg_authid */ 1260, "{opcowner}", "{oid}", false, false},
+	{ /* pg_opclass */ 2616, /* pg_opfamily */ 2753, "{opcfamily}", "{oid}", false, false},
+	{ /* pg_opclass */ 2616, /* pg_type */ 1247, "{opcintype}", "{oid}", false, false},
+	{ /* pg_opclass */ 2616, /* pg_type */ 1247, "{opckeytype}", "{oid}", false, true},
+	{ /* pg_am */ 2601, /* pg_proc */ 1255, "{amhandler}", "{oid}", false, false},
+	{ /* pg_amop */ 2602, /* pg_opfamily */ 2753, "{amopfamily}", "{oid}", false, false},
+	{ /* pg_amop */ 2602, /* pg_type */ 1247, "{amoplefttype}", "{oid}", false, false},
+	{ /* pg_amop */ 2602, /* pg_type */ 1247, "{amoprighttype}", "{oid}", false, false},
+	{ /* pg_amop */ 2602, /* pg_operator */ 2617, "{amopopr}", "{oid}", false, false},
+	{ /* pg_amop */ 2602, /* pg_am */ 2601, "{amopmethod}", "{oid}", false, false},
+	{ /* pg_amop */ 2602, /* pg_opfamily */ 2753, "{amopsortfamily}", "{oid}", false, true},
+	{ /* pg_amproc */ 2603, /* pg_opfamily */ 2753, "{amprocfamily}", "{oid}", false, false},
+	{ /* pg_amproc */ 2603, /* pg_type */ 1247, "{amproclefttype}", "{oid}", false, false},
+	{ /* pg_amproc */ 2603, /* pg_type */ 1247, "{amprocrighttype}", "{oid}", false, false},
+	{ /* pg_amproc */ 2603, /* pg_proc */ 1255, "{amproc}", "{oid}", false, false},
+	{ /* pg_language */ 2612, /* pg_authid */ 1260, "{lanowner}", "{oid}", false, false},
+	{ /* pg_language */ 2612, /* pg_proc */ 1255, "{lanplcallfoid}", "{oid}", false, true},
+	{ /* pg_language */ 2612, /* pg_proc */ 1255, "{laninline}", "{oid}", false, true},
+	{ /* pg_language */ 2612, /* pg_proc */ 1255, "{lanvalidator}", "{oid}", false, true},
+	{ /* pg_largeobject_metadata */ 2995, /* pg_authid */ 1260, "{lomowner}", "{oid}", false, false},
+	{ /* pg_largeobject */ 2613, /* pg_largeobject_metadata */ 2995, "{loid}", "{oid}", false, false},
+	{ /* pg_aggregate */ 2600, /* pg_proc */ 1255, "{aggfnoid}", "{oid}", false, false},
+	{ /* pg_aggregate */ 2600, /* pg_proc */ 1255, "{aggtransfn}", "{oid}", false, false},
+	{ /* pg_aggregate */ 2600, /* pg_proc */ 1255, "{aggfinalfn}", "{oid}", false, true},
+	{ /* pg_aggregate */ 2600, /* pg_proc */ 1255, "{aggcombinefn}", "{oid}", false, true},
+	{ /* pg_aggregate */ 2600, /* pg_proc */ 1255, "{aggserialfn}", "{oid}", false, true},
+	{ /* pg_aggregate */ 2600, /* pg_proc */ 1255, "{aggdeserialfn}", "{oid}", false, true},
+	{ /* pg_aggregate */ 2600, /* pg_proc */ 1255, "{aggmtransfn}", "{oid}", false, true},
+	{ /* pg_aggregate */ 2600, /* pg_proc */ 1255, "{aggminvtransfn}", "{oid}", false, true},
+	{ /* pg_aggregate */ 2600, /* pg_proc */ 1255, "{aggmfinalfn}", "{oid}", false, true},
+	{ /* pg_aggregate */ 2600, /* pg_operator */ 2617, "{aggsortop}", "{oid}", false, true},
+	{ /* pg_aggregate */ 2600, /* pg_type */ 1247, "{aggtranstype}", "{oid}", false, false},
+	{ /* pg_aggregate */ 2600, /* pg_type */ 1247, "{aggmtranstype}", "{oid}", false, true},
+	{ /* pg_statistic */ 2619, /* pg_class */ 1259, "{starelid}", "{oid}", false, false},
+	{ /* pg_statistic */ 2619, /* pg_operator */ 2617, "{staop1}", "{oid}", false, true},
+	{ /* pg_statistic */ 2619, /* pg_operator */ 2617, "{staop2}", "{oid}", false, true},
+	{ /* pg_statistic */ 2619, /* pg_operator */ 2617, "{staop3}", "{oid}", false, true},
+	{ /* pg_statistic */ 2619, /* pg_operator */ 2617, "{staop4}", "{oid}", false, true},
+	{ /* pg_statistic */ 2619, /* pg_operator */ 2617, "{staop5}", "{oid}", false, true},
+	{ /* pg_statistic */ 2619, /* pg_collation */ 3456, "{stacoll1}", "{oid}", false, true},
+	{ /* pg_statistic */ 2619, /* pg_collation */ 3456, "{stacoll2}", "{oid}", false, true},
+	{ /* pg_statistic */ 2619, /* pg_collation */ 3456, "{stacoll3}", "{oid}", false, true},
+	{ /* pg_statistic */ 2619, /* pg_collation */ 3456, "{stacoll4}", "{oid}", false, true},
+	{ /* pg_statistic */ 2619, /* pg_collation */ 3456, "{stacoll5}", "{oid}", false, true},
+	{ /* pg_statistic */ 2619, /* pg_attribute */ 1249, "{starelid, staattnum}", "{attrelid, attnum}", false, false},
+	{ /* pg_statistic_ext */ 3381, /* pg_class */ 1259, "{stxrelid}", "{oid}", false, false},
+	{ /* pg_statistic_ext */ 3381, /* pg_namespace */ 2615, "{stxnamespace}", "{oid}", false, false},
+	{ /* pg_statistic_ext */ 3381, /* pg_authid */ 1260, "{stxowner}", "{oid}", false, false},
+	{ /* pg_statistic_ext */ 3381, /* pg_attribute */ 1249, "{stxrelid, stxkeys}", "{attrelid, attnum}", true, false},
+	{ /* pg_statistic_ext_data */ 3429, /* pg_statistic_ext */ 3381, "{stxoid}", "{oid}", false, false},
+	{ /* pg_rewrite */ 2618, /* pg_class */ 1259, "{ev_class}", "{oid}", false, false},
+	{ /* pg_trigger */ 2620, /* pg_class */ 1259, "{tgrelid}", "{oid}", false, false},
+	{ /* pg_trigger */ 2620, /* pg_trigger */ 2620, "{tgparentid}", "{oid}", false, true},
+	{ /* pg_trigger */ 2620, /* pg_proc */ 1255, "{tgfoid}", "{oid}", false, false},
+	{ /* pg_trigger */ 2620, /* pg_class */ 1259, "{tgconstrrelid}", "{oid}", false, true},
+	{ /* pg_trigger */ 2620, /* pg_class */ 1259, "{tgconstrindid}", "{oid}", false, true},
+	{ /* pg_trigger */ 2620, /* pg_constraint */ 2606, "{tgconstraint}", "{oid}", false, true},
+	{ /* pg_trigger */ 2620, /* pg_attribute */ 1249, "{tgrelid, tgattr}", "{attrelid, attnum}", true, false},
+	{ /* pg_event_trigger */ 3466, /* pg_authid */ 1260, "{evtowner}", "{oid}", false, false},
+	{ /* pg_event_trigger */ 3466, /* pg_proc */ 1255, "{evtfoid}", "{oid}", false, false},
+	{ /* pg_description */ 2609, /* pg_class */ 1259, "{classoid}", "{oid}", false, false},
+	{ /* pg_cast */ 2605, /* pg_type */ 1247, "{castsource}", "{oid}", false, false},
+	{ /* pg_cast */ 2605, /* pg_type */ 1247, "{casttarget}", "{oid}", false, false},
+	{ /* pg_cast */ 2605, /* pg_proc */ 1255, "{castfunc}", "{oid}", false, true},
+	{ /* pg_enum */ 3501, /* pg_type */ 1247, "{enumtypid}", "{oid}", false, false},
+	{ /* pg_namespace */ 2615, /* pg_authid */ 1260, "{nspowner}", "{oid}", false, false},
+	{ /* pg_conversion */ 2607, /* pg_namespace */ 2615, "{connamespace}", "{oid}", false, false},
+	{ /* pg_conversion */ 2607, /* pg_authid */ 1260, "{conowner}", "{oid}", false, false},
+	{ /* pg_conversion */ 2607, /* pg_proc */ 1255, "{conproc}", "{oid}", false, false},
+	{ /* pg_depend */ 2608, /* pg_class */ 1259, "{classid}", "{oid}", false, false},
+	{ /* pg_depend */ 2608, /* pg_class */ 1259, "{refclassid}", "{oid}", false, false},
+	{ /* pg_database */ 1262, /* pg_authid */ 1260, "{datdba}", "{oid}", false, false},
+	{ /* pg_database */ 1262, /* pg_tablespace */ 1213, "{dattablespace}", "{oid}", false, false},
+	{ /* pg_db_role_setting */ 2964, /* pg_database */ 1262, "{setdatabase}", "{oid}", false, true},
+	{ /* pg_db_role_setting */ 2964, /* pg_authid */ 1260, "{setrole}", "{oid}", false, true},
+	{ /* pg_tablespace */ 1213, /* pg_authid */ 1260, "{spcowner}", "{oid}", false, false},
+	{ /* pg_auth_members */ 1261, /* pg_authid */ 1260, "{roleid}", "{oid}", false, false},
+	{ /* pg_auth_members */ 1261, /* pg_authid */ 1260, "{member}", "{oid}", false, false},
+	{ /* pg_auth_members */ 1261, /* pg_authid */ 1260, "{grantor}", "{oid}", false, false},
+	{ /* pg_shdepend */ 1214, /* pg_database */ 1262, "{dbid}", "{oid}", false, true},
+	{ /* pg_shdepend */ 1214, /* pg_class */ 1259, "{classid}", "{oid}", false, false},
+	{ /* pg_shdepend */ 1214, /* pg_class */ 1259, "{refclassid}", "{oid}", false, false},
+	{ /* pg_shdescription */ 2396, /* pg_class */ 1259, "{classoid}", "{oid}", false, false},
+	{ /* pg_ts_config */ 3602, /* pg_namespace */ 2615, "{cfgnamespace}", "{oid}", false, false},
+	{ /* pg_ts_config */ 3602, /* pg_authid */ 1260, "{cfgowner}", "{oid}", false, false},
+	{ /* pg_ts_config */ 3602, /* pg_ts_parser */ 3601, "{cfgparser}", "{oid}", false, false},
+	{ /* pg_ts_config_map */ 3603, /* pg_ts_config */ 3602, "{mapcfg}", "{oid}", false, false},
+	{ /* pg_ts_config_map */ 3603, /* pg_ts_dict */ 3600, "{mapdict}", "{oid}", false, false},
+	{ /* pg_ts_dict */ 3600, /* pg_namespace */ 2615, "{dictnamespace}", "{oid}", false, false},
+	{ /* pg_ts_dict */ 3600, /* pg_authid */ 1260, "{dictowner}", "{oid}", false, false},
+	{ /* pg_ts_dict */ 3600, /* pg_ts_template */ 3764, "{dicttemplate}", "{oid}", false, false},
+	{ /* pg_ts_parser */ 3601, /* pg_namespace */ 2615, "{prsnamespace}", "{oid}", false, false},
+	{ /* pg_ts_parser */ 3601, /* pg_proc */ 1255, "{prsstart}", "{oid}", false, false},
+	{ /* pg_ts_parser */ 3601, /* pg_proc */ 1255, "{prstoken}", "{oid}", false, false},
+	{ /* pg_ts_parser */ 3601, /* pg_proc */ 1255, "{prsend}", "{oid}", false, false},
+	{ /* pg_ts_parser */ 3601, /* pg_proc */ 1255, "{prsheadline}", "{oid}", false, true},
+	{ /* pg_ts_parser */ 3601, /* pg_proc */ 1255, "{prslextype}", "{oid}", false, false},
+	{ /* pg_ts_template */ 3764, /* pg_namespace */ 2615, "{tmplnamespace}", "{oid}", false, false},
+	{ /* pg_ts_template */ 3764, /* pg_proc */ 1255, "{tmplinit}", "{oid}", false, true},
+	{ /* pg_ts_template */ 3764, /* pg_proc */ 1255, "{tmpllexize}", "{oid}", false, false},
+	{ /* pg_extension */ 3079, /* pg_authid */ 1260, "{extowner}", "{oid}", false, false},
+	{ /* pg_extension */ 3079, /* pg_namespace */ 2615, "{extnamespace}", "{oid}", false, false},
+	{ /* pg_extension */ 3079, /* pg_class */ 1259, "{extconfig}", "{oid}", true, false},
+	{ /* pg_foreign_data_wrapper */ 2328, /* pg_authid */ 1260, "{fdwowner}", "{oid}", false, false},
+	{ /* pg_foreign_data_wrapper */ 2328, /* pg_proc */ 1255, "{fdwhandler}", "{oid}", false, true},
+	{ /* pg_foreign_data_wrapper */ 2328, /* pg_proc */ 1255, "{fdwvalidator}", "{oid}", false, true},
+	{ /* pg_foreign_server */ 1417, /* pg_authid */ 1260, "{srvowner}", "{oid}", false, false},
+	{ /* pg_foreign_server */ 1417, /* pg_foreign_data_wrapper */ 2328, "{srvfdw}", "{oid}", false, false},
+	{ /* pg_user_mapping */ 1418, /* pg_authid */ 1260, "{umuser}", "{oid}", false, true},
+	{ /* pg_user_mapping */ 1418, /* pg_foreign_server */ 1417, "{umserver}", "{oid}", false, false},
+	{ /* pg_foreign_table */ 3118, /* pg_class */ 1259, "{ftrelid}", "{oid}", false, false},
+	{ /* pg_foreign_table */ 3118, /* pg_foreign_server */ 1417, "{ftserver}", "{oid}", false, false},
+	{ /* pg_policy */ 3256, /* pg_class */ 1259, "{polrelid}", "{oid}", false, false},
+	{ /* pg_policy */ 3256, /* pg_authid */ 1260, "{polroles}", "{oid}", true, true},
+	{ /* pg_default_acl */ 826, /* pg_authid */ 1260, "{defaclrole}", "{oid}", false, false},
+	{ /* pg_default_acl */ 826, /* pg_namespace */ 2615, "{defaclnamespace}", "{oid}", false, true},
+	{ /* pg_init_privs */ 3394, /* pg_class */ 1259, "{classoid}", "{oid}", false, false},
+	{ /* pg_seclabel */ 3596, /* pg_class */ 1259, "{classoid}", "{oid}", false, false},
+	{ /* pg_shseclabel */ 3592, /* pg_class */ 1259, "{classoid}", "{oid}", false, false},
+	{ /* pg_collation */ 3456, /* pg_namespace */ 2615, "{collnamespace}", "{oid}", false, false},
+	{ /* pg_collation */ 3456, /* pg_authid */ 1260, "{collowner}", "{oid}", false, false},
+	{ /* pg_partitioned_table */ 3350, /* pg_class */ 1259, "{partrelid}", "{oid}", false, false},
+	{ /* pg_partitioned_table */ 3350, /* pg_class */ 1259, "{partdefid}", "{oid}", false, true},
+	{ /* pg_partitioned_table */ 3350, /* pg_opclass */ 2616, "{partclass}", "{oid}", true, false},
+	{ /* pg_partitioned_table */ 3350, /* pg_collation */ 3456, "{partcollation}", "{oid}", true, true},
+	{ /* pg_partitioned_table */ 3350, /* pg_attribute */ 1249, "{partrelid, partattrs}", "{attrelid, attnum}", true, true},
+	{ /* pg_range */ 3541, /* pg_type */ 1247, "{rngtypid}", "{oid}", false, false},
+	{ /* pg_range */ 3541, /* pg_type */ 1247, "{rngsubtype}", "{oid}", false, false},
+	{ /* pg_range */ 3541, /* pg_type */ 1247, "{rngmultitypid}", "{oid}", false, false},
+	{ /* pg_range */ 3541, /* pg_collation */ 3456, "{rngcollation}", "{oid}", false, true},
+	{ /* pg_range */ 3541, /* pg_opclass */ 2616, "{rngsubopc}", "{oid}", false, false},
+	{ /* pg_range */ 3541, /* pg_proc */ 1255, "{rngcanonical}", "{oid}", false, true},
+	{ /* pg_range */ 3541, /* pg_proc */ 1255, "{rngsubdiff}", "{oid}", false, true},
+	{ /* pg_transform */ 3576, /* pg_type */ 1247, "{trftype}", "{oid}", false, false},
+	{ /* pg_transform */ 3576, /* pg_language */ 2612, "{trflang}", "{oid}", false, false},
+	{ /* pg_transform */ 3576, /* pg_proc */ 1255, "{trffromsql}", "{oid}", false, true},
+	{ /* pg_transform */ 3576, /* pg_proc */ 1255, "{trftosql}", "{oid}", false, true},
+	{ /* pg_sequence */ 2224, /* pg_class */ 1259, "{seqrelid}", "{oid}", false, false},
+	{ /* pg_sequence */ 2224, /* pg_type */ 1247, "{seqtypid}", "{oid}", false, false},
+	{ /* pg_publication */ 6104, /* pg_authid */ 1260, "{pubowner}", "{oid}", false, false},
+	{ /* pg_publication_namespace */ 6237, /* pg_publication */ 6104, "{pnpubid}", "{oid}", false, false},
+	{ /* pg_publication_namespace */ 6237, /* pg_namespace */ 2615, "{pnnspid}", "{oid}", false, false},
+	{ /* pg_publication_rel */ 6106, /* pg_publication */ 6104, "{prpubid}", "{oid}", false, false},
+	{ /* pg_publication_rel */ 6106, /* pg_class */ 1259, "{prrelid}", "{oid}", false, false},
+	{ /* pg_subscription */ 6100, /* pg_database */ 1262, "{subdbid}", "{oid}", false, false},
+	{ /* pg_subscription */ 6100, /* pg_authid */ 1260, "{subowner}", "{oid}", false, false},
+	{ /* pg_subscription_rel */ 6102, /* pg_subscription */ 6100, "{srsubid}", "{oid}", false, false},
+	{ /* pg_subscription_rel */ 6102, /* pg_class */ 1259, "{srrelid}", "{oid}", false, false},
+};
+
+#endif							/* SYSTEM_FK_INFO_H */
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index d937f49f19f..79b7a492b85 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -1046,11 +1046,15 @@ InitPlan(QueryDesc *queryDesc, int eflags)
  * Generally the parser and/or planner should have noticed any such mistake
  * already, but let's make sure.
  *
+ * For INSERT ON CONFLICT, the result relation is required to support the
+ * onConflictAction, regardless of whether a conflict actually occurs.
+ *
  * Note: when changing this function, you probably also need to look at
  * CheckValidRowMarkRel.
  */
 void
-CheckValidResultRel(ResultRelInfo *resultRelInfo, CmdType operation)
+CheckValidResultRelNew(ResultRelInfo *resultRelInfo, CmdType operation,
+					   OnConflictAction onConflictAction)
 {
 	Relation	resultRel = resultRelInfo->ri_RelationDesc;
 	TriggerDesc *trigDesc = resultRel->trigdesc;
@@ -1061,6 +1065,13 @@ CheckValidResultRel(ResultRelInfo *resultRelInfo, CmdType operation)
 		case RELKIND_RELATION:
 		case RELKIND_PARTITIONED_TABLE:
 			CheckCmdReplicaIdentity(resultRel, operation);
+
+			/*
+			 * For INSERT ON CONFLICT DO UPDATE, additionally verify whether
+			 * the UPDATE can be executed for the target relation.
+			 */
+			if (onConflictAction == ONCONFLICT_UPDATE)
+				CheckCmdReplicaIdentity(resultRel, CMD_UPDATE);
 			break;
 		case RELKIND_SEQUENCE:
 			ereport(ERROR,
@@ -1179,6 +1190,16 @@ CheckValidResultRel(ResultRelInfo *resultRelInfo, CmdType operation)
 	}
 }
 
+/*
+ * ABI-compatible wrapper to emulate old version of the above function.
+ * Do not call this version in new code.
+ */
+void
+CheckValidResultRel(ResultRelInfo *resultRelInfo, CmdType operation)
+{
+	return CheckValidResultRelNew(resultRelInfo, operation, ONCONFLICT_NONE);
+}
+
 /*
  * Check that a proposed rowmark target relation is a legal target
  *
diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c
index 84a07065ce3..1d70acd6a7c 100644
--- a/src/backend/executor/execPartition.c
+++ b/src/backend/executor/execPartition.c
@@ -377,11 +377,15 @@ ExecFindPartition(ModifyTableState *mtstate,
 									   &partoid, HASH_FIND, NULL);
 					if (elem)
 					{
+						ModifyTable *node = (ModifyTable *) mtstate->ps.plan;
+
 						found = true;
 						rri = elem->rri;
 
 						/* Verify this ResultRelInfo allows INSERTs */
-						CheckValidResultRel(rri, CMD_INSERT);
+						CheckValidResultRelNew(rri, CMD_INSERT, node
+											   ? node->onConflictAction
+											   : ONCONFLICT_NONE);
 
 						/* Set up the PartitionRoutingInfo for it */
 						ExecInitRoutingInfo(mtstate, estate, proute, dispatch,
@@ -590,7 +594,8 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate,
 	 * partition-key becomes a DELETE+INSERT operation, so this check is still
 	 * required when the operation is CMD_UPDATE.
 	 */
-	CheckValidResultRel(leaf_part_rri, CMD_INSERT);
+	CheckValidResultRelNew(leaf_part_rri, CMD_INSERT,
+						   node ? node->onConflictAction : ONCONFLICT_NONE);
 
 	/*
 	 * Open partition indices.  The user may have asked to check for conflicts
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index d25074181f9..fa8d3ccb813 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -2534,7 +2534,8 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
 		/*
 		 * Verify result relation is a valid target for the current operation
 		 */
-		CheckValidResultRel(resultRelInfo, operation);
+		CheckValidResultRelNew(resultRelInfo, operation,
+							   node->onConflictAction);
 
 		/*
 		 * If there are indices on the result relation, open them and save
diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h
index 292093eabfa..acd9671c066 100644
--- a/src/include/executor/executor.h
+++ b/src/include/executor/executor.h
@@ -188,6 +188,8 @@ extern void standard_ExecutorEnd(QueryDesc *queryDesc);
 extern void ExecutorRewind(QueryDesc *queryDesc);
 extern bool ExecCheckRTPerms(List *rangeTable, bool ereport_on_violation);
 extern bool ExecCheckRTEPerms(RangeTblEntry *rte);
+extern void CheckValidResultRelNew(ResultRelInfo *resultRelInfo, CmdType operation,
+								   OnConflictAction onConflictAction);
 extern void CheckValidResultRel(ResultRelInfo *resultRelInfo, CmdType operation);
 extern void InitResultRelInfo(ResultRelInfo *resultRelInfo,
 							  Relation resultRelationDesc,
diff --git a/src/test/regress/expected/publication.out b/src/test/regress/expected/publication.out
index 35595fb1427..e78d302d3bc 100644
--- a/src/test/regress/expected/publication.out
+++ b/src/test/regress/expected/publication.out
@@ -341,6 +341,29 @@ DROP PUBLICATION testpib_ins_trunct;
 DROP PUBLICATION testpub_fortbl;
 DROP SCHEMA pub_test CASCADE;
 NOTICE:  drop cascades to table pub_test.testpub_nopk
+-- Test that the INSERT ON CONFLICT command correctly checks REPLICA IDENTITY
+-- when the target table is published.
+CREATE TABLE testpub_insert_onconfl_no_ri (a int unique, b int);
+CREATE TABLE testpub_insert_onconfl_parted (a int unique, b int) PARTITION by RANGE (a);
+CREATE TABLE testpub_insert_onconfl_part_no_ri PARTITION OF testpub_insert_onconfl_parted FOR VALUES FROM (1) TO (10);
+SET client_min_messages = 'ERROR';
+CREATE PUBLICATION pub1 FOR ALL TABLES;
+RESET client_min_messages;
+-- fail - missing REPLICA IDENTITY
+INSERT INTO testpub_insert_onconfl_no_ri VALUES (1, 1) ON CONFLICT (a) DO UPDATE SET b = 2;
+ERROR:  cannot update table "testpub_insert_onconfl_no_ri" because it does not have a replica identity and publishes updates
+HINT:  To enable updating the table, set REPLICA IDENTITY using ALTER TABLE.
+-- ok - no updates
+INSERT INTO testpub_insert_onconfl_no_ri VALUES (1, 1) ON CONFLICT DO NOTHING;
+-- fail - missing REPLICA IDENTITY in partition testpub_insert_onconfl_no_ri
+INSERT INTO testpub_insert_onconfl_parted VALUES (1, 1) ON CONFLICT (a) DO UPDATE SET b = 2;
+ERROR:  cannot update table "testpub_insert_onconfl_part_no_ri" because it does not have a replica identity and publishes updates
+HINT:  To enable updating the table, set REPLICA IDENTITY using ALTER TABLE.
+-- ok - no updates
+INSERT INTO testpub_insert_onconfl_parted VALUES (1, 1) ON CONFLICT DO NOTHING;
+DROP PUBLICATION pub1;
+DROP TABLE testpub_insert_onconfl_no_ri;
+DROP TABLE testpub_insert_onconfl_parted;
 RESET SESSION AUTHORIZATION;
 DROP ROLE regress_publication_user, regress_publication_user2;
 DROP ROLE regress_publication_user_dummy;
diff --git a/src/test/regress/sql/publication.sql b/src/test/regress/sql/publication.sql
index 021d4e2cb24..dc09d1fdf6f 100644
--- a/src/test/regress/sql/publication.sql
+++ b/src/test/regress/sql/publication.sql
@@ -215,6 +215,32 @@ DROP PUBLICATION testpub_fortbl;
 
 DROP SCHEMA pub_test CASCADE;
 
+-- Test that the INSERT ON CONFLICT command correctly checks REPLICA IDENTITY
+-- when the target table is published.
+CREATE TABLE testpub_insert_onconfl_no_ri (a int unique, b int);
+CREATE TABLE testpub_insert_onconfl_parted (a int unique, b int) PARTITION by RANGE (a);
+CREATE TABLE testpub_insert_onconfl_part_no_ri PARTITION OF testpub_insert_onconfl_parted FOR VALUES FROM (1) TO (10);
+
+SET client_min_messages = 'ERROR';
+CREATE PUBLICATION pub1 FOR ALL TABLES;
+RESET client_min_messages;
+
+-- fail - missing REPLICA IDENTITY
+INSERT INTO testpub_insert_onconfl_no_ri VALUES (1, 1) ON CONFLICT (a) DO UPDATE SET b = 2;
+
+-- ok - no updates
+INSERT INTO testpub_insert_onconfl_no_ri VALUES (1, 1) ON CONFLICT DO NOTHING;
+
+-- fail - missing REPLICA IDENTITY in partition testpub_insert_onconfl_no_ri
+INSERT INTO testpub_insert_onconfl_parted VALUES (1, 1) ON CONFLICT (a) DO UPDATE SET b = 2;
+
+-- ok - no updates
+INSERT INTO testpub_insert_onconfl_parted VALUES (1, 1) ON CONFLICT DO NOTHING;
+
+DROP PUBLICATION pub1;
+DROP TABLE testpub_insert_onconfl_no_ri;
+DROP TABLE testpub_insert_onconfl_parted;
+
 RESET SESSION AUTHORIZATION;
 DROP ROLE regress_publication_user, regress_publication_user2;
 DROP ROLE regress_publication_user_dummy;
-- 
2.31.1

