aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/executor/nodeMemoize.c38
-rw-r--r--src/backend/nodes/bitmapset.c2
-rw-r--r--src/backend/nodes/copyfuncs.c1
-rw-r--r--src/backend/nodes/outfuncs.c1
-rw-r--r--src/backend/nodes/readfuncs.c1
-rw-r--r--src/backend/optimizer/plan/createplan.c10
-rw-r--r--src/backend/optimizer/util/clauses.c31
7 files changed, 81 insertions, 3 deletions
diff --git a/src/backend/executor/nodeMemoize.c b/src/backend/executor/nodeMemoize.c
index cff7ee50469..fde8ebd5068 100644
--- a/src/backend/executor/nodeMemoize.c
+++ b/src/backend/executor/nodeMemoize.c
@@ -368,6 +368,37 @@ remove_cache_entry(MemoizeState *mstate, MemoizeEntry *entry)
}
/*
+ * cache_purge_all
+ * Remove all items from the cache
+ */
+static void
+cache_purge_all(MemoizeState *mstate)
+{
+ uint64 evictions = mstate->hashtable->members;
+ PlanState *pstate = (PlanState *) mstate;
+
+ /*
+ * Likely the most efficient way to remove all items is to just reset the
+ * memory context for the cache and then rebuild a fresh hash table. This
+ * saves having to remove each item one by one and pfree each cached tuple
+ */
+ MemoryContextReset(mstate->tableContext);
+
+ /* Make the hash table the same size as the original size */
+ build_hash_table(mstate, ((Memoize *) pstate->plan)->est_entries);
+
+ /* reset the LRU list */
+ dlist_init(&mstate->lru_list);
+ mstate->last_tuple = NULL;
+ mstate->entry = NULL;
+
+ mstate->mem_used = 0;
+
+ /* XXX should we add something new to track these purges? */
+ mstate->stats.cache_evictions += evictions; /* Update Stats */
+}
+
+/*
* cache_reduce_memory
* Evict older and less recently used items from the cache in order to
* reduce the memory consumption back to something below the
@@ -979,6 +1010,7 @@ ExecInitMemoize(Memoize *node, EState *estate, int eflags)
* getting the first tuple. This allows us to mark it as so.
*/
mstate->singlerow = node->singlerow;
+ mstate->keyparamids = node->keyparamids;
/*
* Record if the cache keys should be compared bit by bit, or logically
@@ -1082,6 +1114,12 @@ ExecReScanMemoize(MemoizeState *node)
if (outerPlan->chgParam == NULL)
ExecReScan(outerPlan);
+ /*
+ * Purge the entire cache if a parameter changed that is not part of the
+ * cache key.
+ */
+ if (bms_nonempty_difference(outerPlan->chgParam, node->keyparamids))
+ cache_purge_all(node);
}
/*
diff --git a/src/backend/nodes/bitmapset.c b/src/backend/nodes/bitmapset.c
index 649478b0d4d..bff70cfb1ab 100644
--- a/src/backend/nodes/bitmapset.c
+++ b/src/backend/nodes/bitmapset.c
@@ -540,6 +540,8 @@ bms_overlap_list(const Bitmapset *a, const List *b)
/*
* bms_nonempty_difference - do sets have a nonempty difference?
+ *
+ * i.e., are any members set in 'a' that are not also set in 'b'.
*/
bool
bms_nonempty_difference(const Bitmapset *a, const Bitmapset *b)
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 595efe196dd..5769536c6a0 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -972,6 +972,7 @@ _copyMemoize(const Memoize *from)
COPY_SCALAR_FIELD(singlerow);
COPY_SCALAR_FIELD(binary_mode);
COPY_SCALAR_FIELD(est_entries);
+ COPY_BITMAPSET_FIELD(keyparamids);
return newnode;
}
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index c8863288fc8..da212d9ddff 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -861,6 +861,7 @@ _outMemoize(StringInfo str, const Memoize *node)
WRITE_BOOL_FIELD(singlerow);
WRITE_BOOL_FIELD(binary_mode);
WRITE_UINT_FIELD(est_entries);
+ WRITE_BITMAPSET_FIELD(keyparamids);
}
static void
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index 3bcac709d3b..4c537c30e0b 100644
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -2231,6 +2231,7 @@ _readMemoize(void)
READ_BOOL_FIELD(singlerow);
READ_BOOL_FIELD(binary_mode);
READ_UINT_FIELD(est_entries);
+ READ_BITMAPSET_FIELD(keyparamids);
READ_DONE();
}
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index cc8d44bdc09..5658f24323f 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -280,7 +280,7 @@ static Material *make_material(Plan *lefttree);
static Memoize *make_memoize(Plan *lefttree, Oid *hashoperators,
Oid *collations, List *param_exprs,
bool singlerow, bool binary_mode,
- uint32 est_entries);
+ uint32 est_entries, Bitmapset *keyparamids);
static WindowAgg *make_windowagg(List *tlist, Index winref,
int partNumCols, AttrNumber *partColIdx, Oid *partOperators, Oid *partCollations,
int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
@@ -1586,6 +1586,7 @@ static Memoize *
create_memoize_plan(PlannerInfo *root, MemoizePath *best_path, int flags)
{
Memoize *plan;
+ Bitmapset *keyparamids;
Plan *subplan;
Oid *operators;
Oid *collations;
@@ -1617,9 +1618,11 @@ create_memoize_plan(PlannerInfo *root, MemoizePath *best_path, int flags)
i++;
}
+ keyparamids = pull_paramids((Expr *) param_exprs);
+
plan = make_memoize(subplan, operators, collations, param_exprs,
best_path->singlerow, best_path->binary_mode,
- best_path->est_entries);
+ best_path->est_entries, keyparamids);
copy_generic_path_info(&plan->plan, (Path *) best_path);
@@ -6419,7 +6422,7 @@ materialize_finished_plan(Plan *subplan)
static Memoize *
make_memoize(Plan *lefttree, Oid *hashoperators, Oid *collations,
List *param_exprs, bool singlerow, bool binary_mode,
- uint32 est_entries)
+ uint32 est_entries, Bitmapset *keyparamids)
{
Memoize *node = makeNode(Memoize);
Plan *plan = &node->plan;
@@ -6436,6 +6439,7 @@ make_memoize(Plan *lefttree, Oid *hashoperators, Oid *collations,
node->singlerow = singlerow;
node->binary_mode = binary_mode;
node->est_entries = est_entries;
+ node->keyparamids = keyparamids;
return node;
}
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index 4d0e093b314..9d7aa8b10ff 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -152,6 +152,7 @@ static Query *substitute_actual_srf_parameters(Query *expr,
int nargs, List *args);
static Node *substitute_actual_srf_parameters_mutator(Node *node,
substitute_actual_srf_parameters_context *context);
+static bool pull_paramids_walker(Node *node, Bitmapset **context);
/*****************************************************************************
@@ -5167,3 +5168,33 @@ substitute_actual_srf_parameters_mutator(Node *node,
substitute_actual_srf_parameters_mutator,
(void *) context);
}
+
+/*
+ * pull_paramids
+ * Returns a Bitmapset containing the paramids of all Params in 'expr'.
+ */
+Bitmapset *
+pull_paramids(Expr *expr)
+{
+ Bitmapset *result = NULL;
+
+ (void) pull_paramids_walker((Node *) expr, &result);
+
+ return result;
+}
+
+static bool
+pull_paramids_walker(Node *node, Bitmapset **context)
+{
+ if (node == NULL)
+ return false;
+ if (IsA(node, Param))
+ {
+ Param *param = (Param *)node;
+
+ *context = bms_add_member(*context, param->paramid);
+ return false;
+ }
+ return expression_tree_walker(node, pull_paramids_walker,
+ (void *) context);
+}