aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/adt')
-rw-r--r--src/backend/utils/adt/selfuncs.c29
1 files changed, 26 insertions, 3 deletions
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index d4c6f6ed5a4..93e4a8906c5 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -121,6 +121,7 @@
#include "parser/parse_clause.h"
#include "parser/parse_relation.h"
#include "parser/parsetree.h"
+#include "rewrite/rewriteManip.h"
#include "statistics/statistics.h"
#include "storage/bufmgr.h"
#include "utils/acl.h"
@@ -3306,6 +3307,15 @@ add_unique_group_var(PlannerInfo *root, List *varinfos,
ndistinct = get_variable_numdistinct(vardata, &isdefault);
+ /*
+ * The nullingrels bits within the var could cause the same var to be
+ * counted multiple times if it's marked with different nullingrels. They
+ * could also prevent us from matching the var to the expressions in
+ * extended statistics (see estimate_multivariate_ndistinct). So strip
+ * them out first.
+ */
+ var = remove_nulling_relids(var, root->outer_join_rels, NULL);
+
foreach(lc, varinfos)
{
varinfo = (GroupVarInfo *) lfirst(lc);
@@ -5025,6 +5035,7 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid,
{
Node *basenode;
Relids varnos;
+ Relids basevarnos;
RelOptInfo *onerel;
/* Make sure we don't return dangling pointers in vardata */
@@ -5066,10 +5077,11 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid,
* relation are considered "real" vars.
*/
varnos = pull_varnos(root, basenode);
+ basevarnos = bms_difference(varnos, root->outer_join_rels);
onerel = NULL;
- if (bms_is_empty(varnos))
+ if (bms_is_empty(basevarnos))
{
/* No Vars at all ... must be pseudo-constant clause */
}
@@ -5077,7 +5089,8 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid,
{
int relid;
- if (bms_get_singleton_member(varnos, &relid))
+ /* Check if the expression is in vars of a single base relation */
+ if (bms_get_singleton_member(basevarnos, &relid))
{
if (varRelid == 0 || varRelid == relid)
{
@@ -5107,7 +5120,7 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid,
}
}
- bms_free(varnos);
+ bms_free(basevarnos);
vardata->var = node;
vardata->atttype = exprType(node);
@@ -5133,6 +5146,14 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid,
Oid userid;
/*
+ * The nullingrels bits within the expression could prevent us from
+ * matching it to expressional index columns or to the expressions in
+ * extended statistics. So strip them out first.
+ */
+ if (bms_overlap(varnos, root->outer_join_rels))
+ node = remove_nulling_relids(node, root->outer_join_rels, NULL);
+
+ /*
* Determine the user ID to use for privilege checks: either
* onerel->userid if it's set (e.g., in case we're accessing the table
* via a view), or the current user otherwise.
@@ -5402,6 +5423,8 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid,
}
}
}
+
+ bms_free(varnos);
}
/*