#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"
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);
{
Node *basenode;
Relids varnos;
+ Relids basevarnos;
RelOptInfo *onerel;
/* Make sure we don't return dangling pointers in vardata */
* 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 */
}
{
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)
{
}
}
- bms_free(varnos);
+ bms_free(basevarnos);
vardata->var = node;
vardata->atttype = exprType(node);
ListCell *slist;
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
}
}
}
+
+ bms_free(varnos);
}
/*
-> Materialize
-> Seq Scan on int4_tbl t2
Filter: (f1 > 1)
- -> Seq Scan on int4_tbl t3
+ -> Materialize
+ -> Seq Scan on int4_tbl t3
-> Materialize
-> Seq Scan on int4_tbl t4
-(13 rows)
+(14 rows)
explain (costs off)
select * from int4_tbl t1
RESET enable_seqscan;
RESET enable_indexscan;
+-- Test that we do not account for nullingrels when looking up statistics
+CREATE TABLE group_tbl (a INT, b INT);
+INSERT INTO group_tbl SELECT 1, 1;
+CREATE STATISTICS group_tbl_stat (ndistinct) ON a, b FROM group_tbl;
+ANALYZE group_tbl;
+EXPLAIN (COSTS OFF)
+SELECT 1 FROM group_tbl t1
+ LEFT JOIN (SELECT a c1, COALESCE(a) c2 FROM group_tbl t2) s ON TRUE
+GROUP BY s.c1, s.c2;
+ QUERY PLAN
+--------------------------------------------
+ Group
+ Group Key: t2.a, (COALESCE(t2.a))
+ -> Sort
+ Sort Key: t2.a, (COALESCE(t2.a))
+ -> Nested Loop Left Join
+ -> Seq Scan on group_tbl t1
+ -> Seq Scan on group_tbl t2
+(7 rows)
+
+DROP TABLE group_tbl;
RESET enable_seqscan;
RESET enable_indexscan;
+
+-- Test that we do not account for nullingrels when looking up statistics
+CREATE TABLE group_tbl (a INT, b INT);
+INSERT INTO group_tbl SELECT 1, 1;
+CREATE STATISTICS group_tbl_stat (ndistinct) ON a, b FROM group_tbl;
+ANALYZE group_tbl;
+
+EXPLAIN (COSTS OFF)
+SELECT 1 FROM group_tbl t1
+ LEFT JOIN (SELECT a c1, COALESCE(a) c2 FROM group_tbl t2) s ON TRUE
+GROUP BY s.c1, s.c2;
+
+DROP TABLE group_tbl;