mirror of
				https://github.com/postgres/postgres.git
				synced 2025-10-29 22:49:41 +03:00 
			
		
		
		
	Fix replica identity check for MERGE.
When executing a MERGE, check that the target relation supports all actions mentioned in the MERGE command. Specifically, check that it has a REPLICA IDENTITY if it publishes updates or deletes and the MERGE command contains update or delete actions. Failing to do this can silently break replication. Author: Zhijie Hou <houzj.fnst@fujitsu.com> Reviewed-by: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com> Reviewed-by: Dean Rasheed <dean.a.rasheed@gmail.com> Tested-by: Chao Li <li.evan.chao@gmail.com> Discussion: https://postgr.es/m/OS3PR01MB57180C87E43A679A730482DF94B62@OS3PR01MB5718.jpnprd01.prod.outlook.com Backpatch-through: 15
This commit is contained in:
		| @@ -1013,12 +1013,16 @@ InitPlan(QueryDesc *queryDesc, int eflags) | ||||
|  * For INSERT ON CONFLICT, the result relation is required to support the | ||||
|  * onConflictAction, regardless of whether a conflict actually occurs. | ||||
|  * | ||||
|  * For MERGE, mergeActions is the list of actions that may be performed.  The | ||||
|  * result relation is required to support every action, regardless of whether | ||||
|  * or not they are all executed. | ||||
|  * | ||||
|  * Note: when changing this function, you probably also need to look at | ||||
|  * CheckValidRowMarkRel. | ||||
|  */ | ||||
| void | ||||
| CheckValidResultRelNew(ResultRelInfo *resultRelInfo, CmdType operation, | ||||
| 					   OnConflictAction onConflictAction) | ||||
| 					   OnConflictAction onConflictAction, List *mergeActions) | ||||
| { | ||||
| 	Relation	resultRel = resultRelInfo->ri_RelationDesc; | ||||
| 	TriggerDesc *trigDesc = resultRel->trigdesc; | ||||
| @@ -1032,7 +1036,24 @@ CheckValidResultRelNew(ResultRelInfo *resultRelInfo, CmdType operation, | ||||
| 	{ | ||||
| 		case RELKIND_RELATION: | ||||
| 		case RELKIND_PARTITIONED_TABLE: | ||||
| 			CheckCmdReplicaIdentity(resultRel, operation); | ||||
|  | ||||
| 			/* | ||||
| 			 * For MERGE, check that the target relation supports each action. | ||||
| 			 * For other operations, just check the operation itself. | ||||
| 			 */ | ||||
| 			if (operation == CMD_MERGE) | ||||
| 			{ | ||||
| 				ListCell   *lc; | ||||
|  | ||||
| 				foreach(lc, mergeActions) | ||||
| 				{ | ||||
| 					MergeAction *action = (MergeAction *) lfirst(lc); | ||||
|  | ||||
| 					CheckCmdReplicaIdentity(resultRel, action->commandType); | ||||
| 				} | ||||
| 			} | ||||
| 			else | ||||
| 				CheckCmdReplicaIdentity(resultRel, operation); | ||||
|  | ||||
| 			/* | ||||
| 			 * For INSERT ON CONFLICT DO UPDATE, additionally check that the | ||||
| @@ -1165,7 +1186,7 @@ CheckValidResultRelNew(ResultRelInfo *resultRelInfo, CmdType operation, | ||||
| void | ||||
| CheckValidResultRel(ResultRelInfo *resultRelInfo, CmdType operation) | ||||
| { | ||||
| 	return CheckValidResultRelNew(resultRelInfo, operation, ONCONFLICT_NONE); | ||||
| 	return CheckValidResultRelNew(resultRelInfo, operation, ONCONFLICT_NONE, NIL); | ||||
| } | ||||
|  | ||||
| /* | ||||
|   | ||||
		Reference in New Issue
	
	Block a user