@@ -41,6 +41,8 @@ PGDLLEXPORT Datum versioning(PG_FUNCTION_ARGS);
41
41
PGDLLEXPORT Datum versioning2 (PG_FUNCTION_ARGS );
42
42
PGDLLEXPORT Datum set_system_time (PG_FUNCTION_ARGS );
43
43
44
+ static Datum versioning_common (bool has_oid , PG_FUNCTION_ARGS );
45
+
44
46
PG_FUNCTION_INFO_V1 (versioning );
45
47
PG_FUNCTION_INFO_V1 (versioning2 );
46
48
PG_FUNCTION_INFO_V1 (set_system_time );
@@ -53,6 +55,7 @@ typedef struct VersioningHashEntry
53
55
{
54
56
Oid relid ; /* hash key (must be first) */
55
57
Oid history_relid ; /* OID of the history relation */
58
+ char history_relname [NAMEDATALEN ];
56
59
TupleDesc tupdesc ; /* tuple descriptor of the versioned relation */
57
60
TupleDesc history_tupdesc ; /* tuple descriptor of the history relation */
58
61
@@ -185,8 +188,8 @@ static VersioningHashEntry *lookup_versioning_hash_entry(Oid relid,
185
188
* FOR EACH ROW EXECUTE PROCEDURE
186
189
* versioning(<system_period_column_name>, <history_relation>, <adjust>).
187
190
*/
188
- Datum
189
- versioning ( PG_FUNCTION_ARGS )
191
+ static Datum
192
+ versioning_common ( bool has_oid , PG_FUNCTION_ARGS )
190
193
{
191
194
TriggerData * trigdata ;
192
195
Trigger * trigger ;
@@ -273,9 +276,14 @@ versioning(PG_FUNCTION_ARGS)
273
276
return versioning_insert (trigdata , typcache , period_attnum );
274
277
else
275
278
{
276
- RangeVar * relrv = makeRangeVarFromNameList (stringToQualifiedNameList (args [1 ]));
277
- Oid history_relation_oid = RangeVarGetRelid (relrv , AccessShareLock , false);;
278
-
279
+ Oid history_relation_oid ;
280
+ if (has_oid )
281
+ history_relation_oid = strtoul (args [1 ], NULL , 10 );
282
+ else
283
+ {
284
+ RangeVar * relrv = makeRangeVarFromNameList (stringToQualifiedNameList (args [1 ]));
285
+ history_relation_oid = RangeVarGetRelid (relrv , AccessShareLock , false);;
286
+ }
279
287
if (TRIGGER_FIRED_BY_UPDATE (trigdata -> tg_event ))
280
288
return versioning_update (trigdata , typcache ,
281
289
period_attnum , period_attname ,
@@ -289,104 +297,15 @@ versioning(PG_FUNCTION_ARGS)
289
297
}
290
298
291
299
Datum
292
- versioning2 (PG_FUNCTION_ARGS )
300
+ versioning (PG_FUNCTION_ARGS )
293
301
{
294
- TriggerData * trigdata ;
295
- Trigger * trigger ;
296
- char * * args ;
297
- Relation relation ;
298
- TupleDesc tupdesc ;
299
- char * period_attname ;
300
- int period_attnum ;
301
- Form_pg_attribute period_attr ;
302
- TypeCacheEntry * typcache ;
303
-
304
- trigdata = (TriggerData * )fcinfo -> context ;
305
-
306
- /* Check that the trigger function was called in expected context. */
307
- if (!CALLED_AS_TRIGGER (fcinfo ))
308
- ereport (ERROR ,
309
- (errcode (ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED ),
310
- errmsg ("function \"versioning2\" was not called by trigger manager" )));
311
-
312
- /* Check proper event. */
313
- if (!TRIGGER_FIRED_BEFORE (trigdata -> tg_event ) ||
314
- !TRIGGER_FIRED_FOR_ROW (trigdata -> tg_event ))
315
- ereport (ERROR ,
316
- (errcode (ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED ),
317
- errmsg ("function \"versioning2\" must be fired BEFORE ROW" )));
318
-
319
- if (!TRIGGER_FIRED_BY_INSERT (trigdata -> tg_event ) &&
320
- !TRIGGER_FIRED_BY_UPDATE (trigdata -> tg_event ) &&
321
- !TRIGGER_FIRED_BY_DELETE (trigdata -> tg_event ))
322
- ereport (ERROR ,
323
- (errcode (ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED ),
324
- errmsg ("function \"versioning2\" must be fired for INSERT or UPDATE or DELETE" )));
325
-
326
- trigger = trigdata -> tg_trigger ;
327
-
328
- /* Check number of arguments. */
329
- if (trigger -> tgnargs != 3 )
330
- ereport (ERROR ,
331
- (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
332
- errmsg ("wrong number of parameters for function \"versioning2\"" ),
333
- errdetail ("expected 3 parameters but got %d" ,
334
- trigger -> tgnargs )));
335
-
336
- args = trigger -> tgargs ;
337
-
338
- relation = trigdata -> tg_relation ;
339
-
340
- tupdesc = RelationGetDescr (relation );
341
-
342
- period_attname = args [0 ];
343
-
344
- /* Check that system period attribute exists in the versioned relation. */
345
- period_attnum = SPI_fnumber (tupdesc , period_attname );
346
-
347
- if (period_attnum == SPI_ERROR_NOATTRIBUTE )
348
- ereport (ERROR ,
349
- (errcode (ERRCODE_UNDEFINED_COLUMN ),
350
- errmsg ("column \"%s\" of relation \"%s\" does not exist" ,
351
- period_attname ,
352
- RelationGetRelationName (relation ))));
353
-
354
- period_attr = tupdesc -> attrs [period_attnum - 1 ];
355
-
356
- /* Check that system period attribute is not dropped. */
357
- if (period_attr -> attisdropped )
358
- ereport (ERROR ,
359
- (errcode (ERRCODE_UNDEFINED_COLUMN ),
360
- errmsg ("column \"%s\" of relation \"%s\" does not exist" ,
361
- period_attname ,
362
- RelationGetRelationName (relation ))));
363
-
364
- /* Check that system period attribute is not an array. */
365
- if (period_attr -> attndims != 0 )
366
- ereport (ERROR ,
367
- (errcode (ERRCODE_DATATYPE_MISMATCH ),
368
- errmsg ("system period column \"%s\" of relation \"%s\" is not a range but an array" ,
369
- period_attname ,
370
- RelationGetRelationName (relation ))));
371
-
372
- /* Locate the typcache entry for the type of system period attribute. */
373
- typcache = get_period_typcache (fcinfo , period_attr , relation );
302
+ return versioning_common (false, fcinfo );
303
+ }
374
304
375
- if (TRIGGER_FIRED_BY_INSERT (trigdata -> tg_event ))
376
- return versioning_insert (trigdata , typcache , period_attnum );
377
- else
378
- {
379
- Oid oid = strtoul (args [1 ], NULL , 10 );
380
- if (TRIGGER_FIRED_BY_UPDATE (trigdata -> tg_event ))
381
- return versioning_update (trigdata , typcache ,
382
- period_attnum , period_attname ,
383
- oid , args [2 ]);
384
- else
385
- /* otherwise this is ON DELETE trigger */
386
- return versioning_delete (trigdata , typcache ,
387
- period_attnum , period_attname ,
388
- oid , args [2 ]);
389
- }
305
+ Datum
306
+ versioning2 (PG_FUNCTION_ARGS )
307
+ {
308
+ return versioning_common (true, fcinfo );
390
309
}
391
310
392
311
/*
@@ -677,6 +596,7 @@ fill_versioning_hash_entry(VersioningHashEntry *hash_entry,
677
596
oldcontext = MemoryContextSwitchTo (TopMemoryContext );
678
597
679
598
hash_entry -> history_relid = RelationGetRelid (history_relation );
599
+ memcpy (hash_entry -> history_relname , NameStr (history_relation -> rd_rel -> relname ), NAMEDATALEN );
680
600
hash_entry -> tupdesc = CreateTupleDescCopyConstr (tupdesc );
681
601
hash_entry -> history_tupdesc = CreateTupleDescCopyConstr (history_tupdesc );
682
602
@@ -743,11 +663,14 @@ insert_history_row(HeapTuple tuple,
743
663
* Then check that the structure of the versioned table and the history
744
664
* table is intact by comparing the cached TupleDesc with the current
745
665
* one.
666
+ *
667
+ * Also check whether history table name has changed.
746
668
*/
747
669
if (hash_entry -> natts == -1 ||
748
670
RelationGetRelid (history_relation ) != hash_entry -> history_relid ||
749
671
!equalTupleDescs (tupdesc , hash_entry -> tupdesc ) ||
750
- !equalTupleDescs (history_tupdesc , hash_entry -> history_tupdesc ))
672
+ !equalTupleDescs (history_tupdesc , hash_entry -> history_tupdesc ) ||
673
+ 0 != strncmp (NameStr (history_relation -> rd_rel -> relname ), hash_entry -> history_relname , NAMEDATALEN ))
751
674
{
752
675
/* Mark the entry invalid. */
753
676
hash_entry -> natts = -1 ;
0 commit comments