diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/optimizer/path/clausesel.c | 21 | ||||
-rw-r--r-- | src/backend/statistics/extended_stats.c | 25 | ||||
-rw-r--r-- | src/test/regress/expected/stats_ext.out | 4 |
3 files changed, 48 insertions, 2 deletions
diff --git a/src/backend/optimizer/path/clausesel.c b/src/backend/optimizer/path/clausesel.c index b88b29ec23a..a7e535c27f5 100644 --- a/src/backend/optimizer/path/clausesel.c +++ b/src/backend/optimizer/path/clausesel.c @@ -538,7 +538,28 @@ find_single_rel_for_clauses(PlannerInfo *root, List *clauses) * However, currently the extended-stats machinery won't do anything * with non-RestrictInfo clauses anyway, so there's no point in * spending extra cycles; just fail if that's what we have. + * + * An exception to that rule is if we have a bare BoolExpr AND clause. + * We treat this as a special case because the restrictinfo machinery + * doesn't build RestrictInfos on top of AND clauses. */ + if (is_andclause(rinfo)) + { + RelOptInfo *rel; + + rel = find_single_rel_for_clauses(root, + ((BoolExpr *) rinfo)->args); + + if (rel == NULL) + return NULL; + if (lastrelid == 0) + lastrelid = rel->relid; + else if (rel->relid != lastrelid) + return NULL; + + continue; + } + if (!IsA(rinfo, RestrictInfo)) return NULL; diff --git a/src/backend/statistics/extended_stats.c b/src/backend/statistics/extended_stats.c index 555bc325619..6d26de37f4d 100644 --- a/src/backend/statistics/extended_stats.c +++ b/src/backend/statistics/extended_stats.c @@ -1174,6 +1174,31 @@ statext_is_compatible_clause(PlannerInfo *root, Node *clause, Index relid, RestrictInfo *rinfo = (RestrictInfo *) clause; Oid userid; + /* + * Special-case handling for bare BoolExpr AND clauses, because the + * restrictinfo machinery doesn't build RestrictInfos on top of AND + * clauses. + */ + if (is_andclause(clause)) + { + BoolExpr *expr = (BoolExpr *) clause; + ListCell *lc; + + /* + * Check that each sub-clause is compatible. We expect these to be + * RestrictInfos. + */ + foreach(lc, expr->args) + { + if (!statext_is_compatible_clause(root, (Node *) lfirst(lc), + relid, attnums)) + return false; + } + + return true; + } + + /* Otherwise it must be a RestrictInfo. */ if (!IsA(rinfo, RestrictInfo)) return false; diff --git a/src/test/regress/expected/stats_ext.out b/src/test/regress/expected/stats_ext.out index 6e1c4f3edd1..7bfeaf85f0e 100644 --- a/src/test/regress/expected/stats_ext.out +++ b/src/test/regress/expected/stats_ext.out @@ -1594,13 +1594,13 @@ SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists_partial WHERE a = 0 SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists_partial WHERE (a = 0 AND b = 0 AND c = 0) OR (a = 1 AND b = 1 AND c = 1) OR (a = 2 AND b = 2 AND c = 2)'); estimated | actual -----------+-------- - 300 | 306 + 306 | 306 (1 row) SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists_partial WHERE (a = 0 AND b = 0) OR (a = 0 AND c = 0) OR (b = 0 AND c = 0)'); estimated | actual -----------+-------- - 306 | 102 + 108 | 102 (1 row) DROP TABLE mcv_lists_partial; |