@@ -278,11 +278,14 @@ MemoizeHash_equal(struct memoize_hash *tb, const MemoizeKey *key1,
278278}
279279
280280/*
281- * Initialize the hash table to empty.
281+ * Initialize the hash table to empty. The MemoizeState's hashtable field
282+ * must point to NULL.
282283 */
283284static void
284285build_hash_table (MemoizeState * mstate ,uint32 size )
285286{
287+ Assert (mstate -> hashtable == NULL );
288+
286289/* Make a guess at a good size when we're not given a valid size. */
287290if (size == 0 )
288291size = 1024 ;
@@ -400,8 +403,10 @@ remove_cache_entry(MemoizeState *mstate, MemoizeEntry *entry)
400403static void
401404cache_purge_all (MemoizeState * mstate )
402405{
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 ;
405410
406411/*
407412 * Likely the most efficient way to remove all items is to just reset the
@@ -410,8 +415,8 @@ cache_purge_all(MemoizeState *mstate)
410415 */
411416MemoryContextReset (mstate -> tableContext );
412417
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 ;
415420
416421/* reset the LRU list */
417422dlist_init (& mstate -> lru_list );
@@ -707,6 +712,10 @@ ExecMemoize(PlanState *pstate)
707712
708713Assert (node -> entry == NULL );
709714
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+
710719/*
711720 * We're only ever in this state for the first call of the
712721 * 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)
10511060/* Zero the statistics counters */
10521061memset (& mstate -> stats ,0 ,sizeof (MemoizeInstrumentation ));
10531062
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 ;
10561068
10571069return mstate ;
10581070}
@@ -1062,6 +1074,7 @@ ExecEndMemoize(MemoizeState *node)
10621074{
10631075#ifdef USE_ASSERT_CHECKING
10641076/* Validate the memory accounting code is correct in assert builds. */
1077+ if (node -> hashtable != NULL )
10651078{
10661079int count ;
10671080uint64 mem = 0 ;