@@ -130,7 +130,8 @@ static dlist_head *changesStack = NULL;
130
130
static MemoryContext changesStackContext = NULL ;
131
131
132
132
/*
133
- * List to store all the running hash_seq_search scan for hash table.
133
+ * List to store all the running hash_seq_search, variable and package scan for
134
+ * hash table.
134
135
*
135
136
* NOTE: In function variable_select we use hash_seq_search to find next tuple.
136
137
* So, in case user do not get all the data from set at once (use cursors or
@@ -143,10 +144,116 @@ static MemoryContext changesStackContext = NULL;
143
144
* TopTransactionContext is handy here, becouse it wount be reset by the time
144
145
* pgvTransCallback is called.
145
146
*/
146
- static List * variables_stats = NIL ;
147
+ static List * variables_stats = NIL ;
147
148
static List * packages_stats = NIL ;
148
149
149
- static void freeStatsLists (bool deep );
150
+ typedef struct tagHtabToStat {
151
+ HTAB * hash ;
152
+ HASH_SEQ_STATUS * status ;
153
+ Variable * variable ;
154
+ Package * package ;
155
+ } HtabToStat ;
156
+
157
+ /*
158
+ * A bunch of comp functions for HtabToStat members here.
159
+ */
160
+ static bool
161
+ HtabToStat_status_eq (HtabToStat * entry , void * value )
162
+ {
163
+ return entry -> status == (HASH_SEQ_STATUS * ) value ;
164
+ }
165
+
166
+ static bool
167
+ HtabToStat_variable_eq (HtabToStat * entry , void * value )
168
+ {
169
+ return entry -> variable == (Variable * ) value ;
170
+ }
171
+
172
+ static bool
173
+ HtabToStat_package_eq (HtabToStat * entry , void * value )
174
+ {
175
+ return entry -> package == (Package * ) value ;
176
+ }
177
+
178
+ static bool
179
+ HtabToStat_eq_all (HtabToStat * entry , void * value )
180
+ {
181
+ return true;
182
+ }
183
+
184
+ /*
185
+ * Generic remove_if algorithm for HtabToStat.
186
+ *
187
+ * + eq if function pointer used to compare list entry to the value.
188
+ * + if match_first is true return on first match.
189
+ */
190
+ static void
191
+ HtabToStat_remove_if (List * * l , void * value ,
192
+ bool (* eq )(HtabToStat * , void * ),
193
+ bool match_first )
194
+ {
195
+ ListCell * cell , * next , * prev = NULL ;
196
+ HtabToStat * entry = NULL ;
197
+
198
+ for (cell = list_head (* l ); cell ; cell = next )
199
+ {
200
+ entry = (HtabToStat * ) lfirst (cell );
201
+ next = lnext (cell );
202
+
203
+ if (eq (entry , value ))
204
+ {
205
+ * l = list_delete_cell (* l , cell , prev );
206
+ pfree (entry -> status );
207
+ pfree (entry );
208
+
209
+ if (match_first )
210
+ return ;
211
+ }
212
+ else
213
+ {
214
+ prev = cell ;
215
+ }
216
+ }
217
+ }
218
+
219
+ /*
220
+ * Remove first entry for status.
221
+ */
222
+ static void
223
+ remove_variables_status (List * * l , HASH_SEQ_STATUS * status )
224
+ {
225
+ HtabToStat_remove_if (l , status , HtabToStat_status_eq , true);
226
+ }
227
+
228
+ /*
229
+ * Remove first entry for variable.
230
+ */
231
+ static void
232
+ remove_variables_variable (List * * l , Variable * variable )
233
+ {
234
+ HtabToStat_remove_if (l , variable , HtabToStat_variable_eq , true);
235
+ }
236
+
237
+ /*
238
+ * Remove all the entrys for package.
239
+ */
240
+ static void
241
+ remove_variables_package (List * * l , Package * package )
242
+ {
243
+ HtabToStat_remove_if (l , package , HtabToStat_package_eq , false);
244
+ }
245
+
246
+ /*
247
+ * Remove all.
248
+ */
249
+ static void
250
+ remove_variables_all (List * * l )
251
+ {
252
+ HtabToStat_remove_if (l , NULL , HtabToStat_eq_all , false);
253
+ * l = NIL ;
254
+ }
255
+
256
+ static void freeStatsLists (void );
150
257
/* Returns a lists of packages and variables changed at current subxact level */
151
258
#define get_actual_changes_list () \
152
259
( \
@@ -632,6 +739,7 @@ variable_select(PG_FUNCTION_ARGS)
632
739
{
633
740
MemoryContext oldcontext ;
634
741
RecordVar * record ;
742
+ HtabToStat * htab_to_stat ;
635
743
636
744
record = & (GetActualValue (variable ).record );
637
745
funcctx = SRF_FIRSTCALL_INIT ();
@@ -644,7 +752,12 @@ variable_select(PG_FUNCTION_ARGS)
644
752
hash_seq_init (rstat , record -> rhash );
645
753
funcctx -> user_fctx = rstat ;
646
754
647
- variables_stats = lcons ((void * )rstat , variables_stats );
755
+ htab_to_stat = palloc0 (sizeof (HtabToStat ));
756
+ htab_to_stat -> hash = record -> rhash ;
757
+ htab_to_stat -> status = rstat ;
758
+ htab_to_stat -> variable = variable ;
759
+ htab_to_stat -> package = package ;
760
+ variables_stats = lcons ((void * )htab_to_stat , variables_stats );
648
761
649
762
MemoryContextSwitchTo (oldcontext );
650
763
PG_FREE_IF_COPY (package_name , 0 );
@@ -665,8 +778,7 @@ variable_select(PG_FUNCTION_ARGS)
665
778
}
666
779
else
667
780
{
668
- variables_stats = list_delete (variables_stats , rstat );
669
- pfree (rstat );
781
+ remove_variables_status (& variables_stats , rstat );
670
782
SRF_RETURN_DONE (funcctx );
671
783
}
672
784
}
@@ -968,6 +1080,8 @@ remove_package(PG_FUNCTION_ARGS)
968
1080
969
1081
resetVariablesCache ();
970
1082
1083
+ remove_variables_package (& variables_stats , package );
1084
+
971
1085
PG_FREE_IF_COPY (package_name , 0 );
972
1086
PG_RETURN_VOID ();
973
1087
}
@@ -1063,6 +1177,7 @@ remove_packages(PG_FUNCTION_ARGS)
1063
1177
}
1064
1178
1065
1179
resetVariablesCache ();
1180
+ remove_variables_all (& variables_stats );
1066
1181
1067
1182
PG_RETURN_VOID ();
1068
1183
}
@@ -1317,7 +1432,7 @@ get_packages_stats(PG_FUNCTION_ARGS)
1317
1432
else
1318
1433
{
1319
1434
packages_stats = list_delete (packages_stats , rstat );
1320
- pfree (rstat );
1435
+ // pfree(rstat);
1321
1436
SRF_RETURN_DONE (funcctx );
1322
1437
}
1323
1438
}
@@ -1777,6 +1892,7 @@ removeObject(TransObject *object, TransObjectType type)
1777
1892
1778
1893
/* Remove object from hash table */
1779
1894
hash_search (hash , object -> name , HASH_REMOVE , & found );
1895
+ remove_variables_variable (& variables_stats , (Variable * ) object );
1780
1896
1781
1897
/* Remove package if it became empty */
1782
1898
if (type == TRANS_VARIABLE && isPackageEmpty (package ))
@@ -2227,7 +2343,7 @@ pgvTransCallback(XactEvent event, void *arg)
2227
2343
}
2228
2344
2229
2345
if (event == XACT_EVENT_PRE_COMMIT || event == XACT_EVENT_ABORT )
2230
- freeStatsLists (true );
2346
+ freeStatsLists ();
2231
2347
}
2232
2348
2233
2349
/*
@@ -2241,25 +2357,23 @@ variable_ExecutorEnd(QueryDesc *queryDesc)
2241
2357
else
2242
2358
standard_ExecutorEnd (queryDesc );
2243
2359
2244
- freeStatsLists (false );
2360
+ freeStatsLists ();
2245
2361
}
2246
2362
2247
2363
/*
2248
2364
* Free hash_seq_search scans
2249
2365
*/
2250
- void
2251
- freeStatsLists (bool deep )
2366
+ static void
2367
+ freeStatsLists (void )
2252
2368
{
2253
2369
ListCell * cell ;
2254
2370
HASH_SEQ_STATUS * status ;
2371
+ HtabToStat * htab_to_stat ;
2255
2372
2256
2373
foreach (cell , variables_stats )
2257
2374
{
2258
- status = (HASH_SEQ_STATUS * ) lfirst (cell );
2259
- hash_seq_term (status );
2260
-
2261
- if (deep )
2262
- pfree (status );
2375
+ htab_to_stat = (HtabToStat * ) lfirst (cell );
2376
+ hash_seq_term (htab_to_stat -> status );
2263
2377
}
2264
2378
2265
2379
variables_stats = NIL ;
@@ -2268,8 +2382,6 @@ freeStatsLists(bool deep)
2268
2382
{
2269
2383
status = (HASH_SEQ_STATUS * ) lfirst (cell );
2270
2384
hash_seq_term (status );
2271
-
2272
- pfree (status );
2273
2385
}
2274
2386
2275
2387
packages_stats = NIL ;
0 commit comments