mirror of
				https://github.com/postgres/postgres.git
				synced 2025-10-28 11:55:03 +03:00 
			
		
		
		
	Generated columns
This is an SQL-standard feature that allows creating columns that are computed from expressions rather than assigned, similar to a view or materialized view but on a column basis. This implements one kind of generated column: stored (computed on write). Another kind, virtual (computed on read), is planned for the future, and some room is left for it. Reviewed-by: Michael Paquier <michael@paquier.xyz> Reviewed-by: Pavel Stehule <pavel.stehule@gmail.com> Discussion: https://www.postgresql.org/message-id/flat/b151f851-4019-bdb1-699e-ebab07d2f40a@2ndquadrant.com
This commit is contained in:
		| @@ -75,8 +75,9 @@ static int	MyTriggerDepth = 0; | ||||
|  * they use, so we let them be duplicated.  Be sure to update all if one needs | ||||
|  * to be changed, however. | ||||
|  */ | ||||
| #define GetUpdatedColumns(relinfo, estate) \ | ||||
| 	(exec_rt_fetch((relinfo)->ri_RangeTableIndex, estate)->updatedCols) | ||||
| #define GetAllUpdatedColumns(relinfo, estate) \ | ||||
| 	(bms_union(exec_rt_fetch((relinfo)->ri_RangeTableIndex, estate)->updatedCols, \ | ||||
| 			   exec_rt_fetch((relinfo)->ri_RangeTableIndex, estate)->extraUpdatedCols)) | ||||
|  | ||||
| /* Local function prototypes */ | ||||
| static void ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid); | ||||
| @@ -640,6 +641,24 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString, | ||||
| 								(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), | ||||
| 								 errmsg("BEFORE trigger's WHEN condition cannot reference NEW system columns"), | ||||
| 								 parser_errposition(pstate, var->location))); | ||||
| 					if (TRIGGER_FOR_BEFORE(tgtype) && | ||||
| 						var->varattno == 0 && | ||||
| 						RelationGetDescr(rel)->constr && | ||||
| 						RelationGetDescr(rel)->constr->has_generated_stored) | ||||
| 						ereport(ERROR, | ||||
| 								(errcode(ERRCODE_INVALID_OBJECT_DEFINITION), | ||||
| 								 errmsg("BEFORE trigger's WHEN condition cannot reference NEW generated columns"), | ||||
| 								 errdetail("A whole-row reference is used and the table contains generated columns."), | ||||
| 								 parser_errposition(pstate, var->location))); | ||||
| 					if (TRIGGER_FOR_BEFORE(tgtype) && | ||||
| 						var->varattno > 0 && | ||||
| 						TupleDescAttr(RelationGetDescr(rel), var->varattno - 1)->attgenerated) | ||||
| 						ereport(ERROR, | ||||
| 								(errcode(ERRCODE_INVALID_OBJECT_DEFINITION), | ||||
| 								 errmsg("BEFORE trigger's WHEN condition cannot reference NEW generated columns"), | ||||
| 								 errdetail("Column \"%s\" is a generated column.", | ||||
| 										   NameStr(TupleDescAttr(RelationGetDescr(rel), var->varattno - 1)->attname)), | ||||
| 								 parser_errposition(pstate, var->location))); | ||||
| 					break; | ||||
| 				default: | ||||
| 					/* can't happen without add_missing_from, so just elog */ | ||||
| @@ -2931,7 +2950,7 @@ ExecBSUpdateTriggers(EState *estate, ResultRelInfo *relinfo) | ||||
| 								   CMD_UPDATE)) | ||||
| 		return; | ||||
|  | ||||
| 	updatedCols = GetUpdatedColumns(relinfo, estate); | ||||
| 	updatedCols = GetAllUpdatedColumns(relinfo, estate); | ||||
|  | ||||
| 	LocTriggerData.type = T_TriggerData; | ||||
| 	LocTriggerData.tg_event = TRIGGER_EVENT_UPDATE | | ||||
| @@ -2980,7 +2999,7 @@ ExecASUpdateTriggers(EState *estate, ResultRelInfo *relinfo, | ||||
| 	if (trigdesc && trigdesc->trig_update_after_statement) | ||||
| 		AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_UPDATE, | ||||
| 							  false, NULL, NULL, NIL, | ||||
| 							  GetUpdatedColumns(relinfo, estate), | ||||
| 							  GetAllUpdatedColumns(relinfo, estate), | ||||
| 							  transition_capture); | ||||
| } | ||||
|  | ||||
| @@ -3049,7 +3068,7 @@ ExecBRUpdateTriggers(EState *estate, EPQState *epqstate, | ||||
| 	LocTriggerData.tg_relation = relinfo->ri_RelationDesc; | ||||
| 	LocTriggerData.tg_oldtable = NULL; | ||||
| 	LocTriggerData.tg_newtable = NULL; | ||||
| 	updatedCols = GetUpdatedColumns(relinfo, estate); | ||||
| 	updatedCols = GetAllUpdatedColumns(relinfo, estate); | ||||
| 	for (i = 0; i < trigdesc->numtriggers; i++) | ||||
| 	{ | ||||
| 		Trigger    *trigger = &trigdesc->triggers[i]; | ||||
| @@ -3140,7 +3159,7 @@ ExecARUpdateTriggers(EState *estate, ResultRelInfo *relinfo, | ||||
|  | ||||
| 		AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_UPDATE, | ||||
| 							  true, oldslot, newslot, recheckIndexes, | ||||
| 							  GetUpdatedColumns(relinfo, estate), | ||||
| 							  GetAllUpdatedColumns(relinfo, estate), | ||||
| 							  transition_capture); | ||||
| 	} | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user