@@ -57,6 +57,7 @@ static Variable *createVariableInternal(Package *package,
57
57
text * name , Oid typid ,
58
58
bool is_transactional );
59
59
static void removePackageInternal (Package * package );
60
+ static void resetVariablesCache (bool with_package );
60
61
61
62
/* Functions to work with transactional objects */
62
63
static void createSavepoint (TransObject * object , TransObjectType type );
@@ -99,6 +100,8 @@ static MemoryContext ModuleContext = NULL;
99
100
static Package * LastPackage = NULL ;
100
101
/* Recent variable */
101
102
static Variable * LastVariable = NULL ;
103
+ /* Recent row type id */
104
+ static Oid LastTypeId = InvalidOid ;
102
105
103
106
104
107
/* This stack contains lists of changed variables and packages per each subxact level */
@@ -291,7 +294,7 @@ variable_insert(PG_FUNCTION_ARGS)
291
294
292
295
Oid tupType ;
293
296
int32 tupTypmod ;
294
- TupleDesc tupdesc ;
297
+ TupleDesc tupdesc = NULL ;
295
298
RecordVar * record ;
296
299
297
300
/* Checks */
@@ -360,23 +363,34 @@ variable_insert(PG_FUNCTION_ARGS)
360
363
/* Insert a record */
361
364
tupType = HeapTupleHeaderGetTypeId (rec );
362
365
tupTypmod = HeapTupleHeaderGetTypMod (rec );
363
- tupdesc = lookup_rowtype_tupdesc (tupType , tupTypmod );
364
366
365
367
record = & (GetActualValue (variable ).record );
366
368
if (!record -> tupdesc )
367
369
{
368
370
/*
369
371
* This is the first record for the var_name. Initialize record.
370
372
*/
373
+ tupdesc = lookup_rowtype_tupdesc (tupType , tupTypmod );
371
374
init_record (record , tupdesc , variable );
372
375
}
373
- else
376
+ else if (LastTypeId == RECORDOID || !OidIsValid (LastTypeId ) ||
377
+ LastTypeId != tupType )
378
+ {
379
+ /*
380
+ * We need to check attributes of the new row if this is a transient
381
+ * record type or if last record has different id.
382
+ */
383
+ tupdesc = lookup_rowtype_tupdesc (tupType , tupTypmod );
374
384
check_attributes (variable , tupdesc );
385
+ }
386
+
387
+ LastTypeId = tupType ;
375
388
376
389
insert_record (variable , rec );
377
390
378
391
/* Release resources */
379
- ReleaseTupleDesc (tupdesc );
392
+ if (tupdesc )
393
+ ReleaseTupleDesc (tupdesc );
380
394
381
395
PG_FREE_IF_COPY (package_name , 0 );
382
396
PG_FREE_IF_COPY (var_name , 1 );
@@ -396,7 +410,6 @@ variable_update(PG_FUNCTION_ARGS)
396
410
bool res ;
397
411
Oid tupType ;
398
412
int32 tupTypmod ;
399
- TupleDesc tupdesc ;
400
413
401
414
/* Checks */
402
415
CHECK_ARGS_FOR_NULL ();
@@ -447,14 +460,22 @@ variable_update(PG_FUNCTION_ARGS)
447
460
/* Update a record */
448
461
tupType = HeapTupleHeaderGetTypeId (rec );
449
462
tupTypmod = HeapTupleHeaderGetTypMod (rec );
450
- tupdesc = lookup_rowtype_tupdesc (tupType , tupTypmod );
451
463
452
- check_attributes (variable , tupdesc );
464
+ if (LastTypeId == RECORDOID || !OidIsValid (LastTypeId ) ||
465
+ LastTypeId != tupType )
466
+ {
467
+ TupleDesc tupdesc = NULL ;
468
+
469
+ tupdesc = lookup_rowtype_tupdesc (tupType , tupTypmod );
470
+ check_attributes (variable , tupdesc );
471
+ ReleaseTupleDesc (tupdesc );
472
+ }
473
+
474
+ LastTypeId = tupType ;
475
+
453
476
res = update_record (variable , rec );
454
477
455
478
/* Release resources */
456
- ReleaseTupleDesc (tupdesc );
457
-
458
479
PG_FREE_IF_COPY (package_name , 0 );
459
480
PG_FREE_IF_COPY (var_name , 1 );
460
481
@@ -867,8 +888,7 @@ remove_variable(PG_FUNCTION_ARGS)
867
888
GetActualState (variable )-> is_valid = false;
868
889
}
869
890
870
- /* Remove variable from cache */
871
- LastVariable = NULL ;
891
+ resetVariablesCache (false);
872
892
873
893
PG_FREE_IF_COPY (package_name , 0 );
874
894
PG_FREE_IF_COPY (var_name , 1 );
@@ -904,9 +924,7 @@ remove_package(PG_FUNCTION_ARGS)
904
924
errmsg ("unrecognized package \"%s\"" , key )));
905
925
}
906
926
907
- /* Remove package and variable from cache */
908
- LastPackage = NULL ;
909
- LastVariable = NULL ;
927
+ resetVariablesCache (true);
910
928
911
929
PG_FREE_IF_COPY (package_name , 0 );
912
930
PG_RETURN_VOID ();
@@ -934,6 +952,20 @@ removePackageInternal(Package *package)
934
952
GetActualState (package )-> is_valid = false;
935
953
}
936
954
955
+ /*
956
+ * Reset cache variables to their default values. It is necessary to do in case
957
+ * of some changes: removing, rollbacking, etc.
958
+ */
959
+ static void
960
+ resetVariablesCache (bool with_package )
961
+ {
962
+ /* Remove package and variable from cache */
963
+ if (with_package )
964
+ LastPackage = NULL ;
965
+ LastVariable = NULL ;
966
+ LastTypeId = InvalidOid ;
967
+ }
968
+
937
969
/*
938
970
* Remove all packages and variables.
939
971
* Memory context will be released after committing.
@@ -955,9 +987,7 @@ remove_packages(PG_FUNCTION_ARGS)
955
987
removePackageInternal (package );
956
988
}
957
989
958
- /* Remove package and variable from cache */
959
- LastPackage = NULL ;
960
- LastVariable = NULL ;
990
+ resetVariablesCache (true);
961
991
962
992
PG_RETURN_VOID ();
963
993
}
@@ -1632,8 +1662,7 @@ removeObject(TransObject *object, TransObjectType type)
1632
1662
/* Remove object from hash table */
1633
1663
hash_search (hash , object -> name , HASH_REMOVE , & found );
1634
1664
1635
- LastPackage = NULL ;
1636
- LastVariable = NULL ;
1665
+ resetVariablesCache (true);
1637
1666
}
1638
1667
1639
1668
/*
@@ -2004,8 +2033,7 @@ processChanges(Action action)
2004
2033
MemoryContextDelete (ModuleContext );
2005
2034
packagesHash = NULL ;
2006
2035
ModuleContext = NULL ;
2007
- LastPackage = NULL ;
2008
- LastVariable = NULL ;
2036
+ resetVariablesCache (true);
2009
2037
changesStack = NULL ;
2010
2038
changesStackContext = NULL ;
2011
2039
}
0 commit comments