@@ -278,11 +278,14 @@ MemoizeHash_equal(struct memoize_hash *tb, const MemoizeKey *key1,
278
278
}
279
279
280
280
/*
281
- * Initialize the hash table to empty.
281
+ * Initialize the hash table to empty. The MemoizeState's hashtable field
282
+ * must point to NULL.
282
283
*/
283
284
static void
284
285
build_hash_table (MemoizeState * mstate ,uint32 size )
285
286
{
287
+ Assert (mstate -> hashtable == NULL );
288
+
286
289
/* Make a guess at a good size when we're not given a valid size. */
287
290
if (size == 0 )
288
291
size = 1024 ;
@@ -400,8 +403,10 @@ remove_cache_entry(MemoizeState *mstate, MemoizeEntry *entry)
400
403
static void
401
404
cache_purge_all (MemoizeState * mstate )
402
405
{
403
- uint64 evictions = mstate -> hashtable -> members ;
404
- PlanState * pstate = (PlanState * )mstate ;
406
+ uint64 evictions = 0 ;
407
+
408
+ if (mstate -> hashtable != NULL )
409
+ evictions = mstate -> hashtable -> members ;
405
410
406
411
/*
407
412
* Likely the most efficient way to remove all items is to just reset the
@@ -410,8 +415,8 @@ cache_purge_all(MemoizeState *mstate)
410
415
*/
411
416
MemoryContextReset (mstate -> tableContext );
412
417
413
- /*Make the hash table thesame size as theoriginal size */
414
- build_hash_table ( mstate , (( Memoize * ) pstate -> plan ) -> est_entries ) ;
418
+ /*NULLify so we recreate thetable on thenext call */
419
+ mstate -> hashtable = NULL ;
415
420
416
421
/* reset the LRU list */
417
422
dlist_init (& mstate -> lru_list );
@@ -707,6 +712,10 @@ ExecMemoize(PlanState *pstate)
707
712
708
713
Assert (node -> entry == NULL );
709
714
715
+ /* first call? we'll need a hash table. */
716
+ if (unlikely (node -> hashtable == NULL ))
717
+ build_hash_table (node , ((Memoize * )pstate -> plan )-> est_entries );
718
+
710
719
/*
711
720
* We're only ever in this state for the first call of the
712
721
* scan. Here we have a look to see if we've already seen the
@@ -1051,8 +1060,11 @@ ExecInitMemoize(Memoize *node, EState *estate, int eflags)
1051
1060
/* Zero the statistics counters */
1052
1061
memset (& mstate -> stats ,0 ,sizeof (MemoizeInstrumentation ));
1053
1062
1054
- /* Allocate and set up the actual cache */
1055
- build_hash_table (mstate ,node -> est_entries );
1063
+ /*
1064
+ * Because it may require a large allocation, we delay building of the
1065
+ * hash table until executor run.
1066
+ */
1067
+ mstate -> hashtable = NULL ;
1056
1068
1057
1069
return mstate ;
1058
1070
}
@@ -1062,6 +1074,7 @@ ExecEndMemoize(MemoizeState *node)
1062
1074
{
1063
1075
#ifdef USE_ASSERT_CHECKING
1064
1076
/* Validate the memory accounting code is correct in assert builds. */
1077
+ if (node -> hashtable != NULL )
1065
1078
{
1066
1079
int count ;
1067
1080
uint64 mem = 0 ;