diff options
author | David Rowley | 2024-03-04 01:40:03 +0000 |
---|---|---|
committer | David Rowley | 2024-03-04 01:40:22 +0000 |
commit | 07c36c1333e00df5a4baf6b04ba2f3f300f57d69 (patch) | |
tree | 4fb527508736e7e5e96ddaa6404ba15cc6f05605 /src/backend | |
parent | eca2c1ea85eb22716f93339f4e7cec3145c25723 (diff) |
Support partition pruning on boolcol IS [NOT] UNKNOWN
While working on 4c2369ac5, I noticed we went out of our way not to
support clauses on boolean partitioned tables in the form of "IS
UNKNOWN" and "IS NOT UNKNOWN". It's almost as much code to disallow
this as it is to allow it, so let's allow it.
Discussion: https://postgr.es/m/CAApHDvobKtcN6+xOuOfcutfp6T7jP=JPA9y3=MAEqnuKdDsQrw@mail.gmail.com
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/partitioning/partprune.c | 71 |
1 files changed, 40 insertions, 31 deletions
diff --git a/src/backend/partitioning/partprune.c b/src/backend/partitioning/partprune.c index a19f596d4de..0b6c627b503 100644 --- a/src/backend/partitioning/partprune.c +++ b/src/backend/partitioning/partprune.c @@ -200,7 +200,7 @@ static PartClauseMatchStatus match_boolean_partition_clause(Oid partopfamily, Expr *clause, Expr *partkey, Expr **outconst, - bool *noteq); + bool *notclause); static void partkey_datum_from_expr(PartitionPruneContext *context, Expr *expr, int stateidx, Datum *value, bool *isnull); @@ -1798,13 +1798,14 @@ match_clause_to_partition_key(GeneratePruningStepsContext *context, Oid partopfamily = part_scheme->partopfamily[partkeyidx], partcoll = part_scheme->partcollation[partkeyidx]; Expr *expr; - bool noteq; + bool notclause; /* * Recognize specially shaped clauses that match a Boolean partition key. */ boolmatchstatus = match_boolean_partition_clause(partopfamily, clause, - partkey, &expr, ¬eq); + partkey, &expr, + ¬clause); if (boolmatchstatus == PARTCLAUSE_MATCH_CLAUSE) { @@ -1818,7 +1819,7 @@ match_clause_to_partition_key(GeneratePruningStepsContext *context, * punt it off to gen_partprune_steps_internal() to generate pruning * steps. */ - if (noteq) + if (notclause) { List *new_clauses; List *or_clause; @@ -1836,9 +1837,8 @@ match_clause_to_partition_key(GeneratePruningStepsContext *context, else { /* - * We only expect match_boolean_partition_clause to match for - * IS_NOT_TRUE and IS_NOT_FALSE. IS_NOT_UNKNOWN is not - * supported. + * We only expect match_boolean_partition_clause to return + * PARTCLAUSE_MATCH_CLAUSE for IS_NOT_TRUE and IS_NOT_FALSE. */ Assert(false); } @@ -1876,6 +1876,15 @@ match_clause_to_partition_key(GeneratePruningStepsContext *context, return PARTCLAUSE_MATCH_CLAUSE; } + else if (boolmatchstatus == PARTCLAUSE_MATCH_NULLNESS) + { + /* + * Handle IS UNKNOWN and IS NOT UNKNOWN. These just logically + * translate to IS NULL and IS NOT NULL. + */ + *clause_is_not_null = notclause; + return PARTCLAUSE_MATCH_NULLNESS; + } else if (IsA(clause, OpExpr) && list_length(((OpExpr *) clause)->args) == 2) { @@ -3652,22 +3661,23 @@ perform_pruning_combine_step(PartitionPruneContext *context, * match_boolean_partition_clause * * If we're able to match the clause to the partition key as specially-shaped - * boolean clause, set *outconst to a Const containing a true or false value, - * set *noteq according to if the clause was in the "not" form, i.e. "is not - * true" or "is not false", and return PARTCLAUSE_MATCH_CLAUSE. Returns - * PARTCLAUSE_UNSUPPORTED if the clause is not a boolean clause or if the - * boolean clause is unsuitable for partition pruning. Returns - * PARTCLAUSE_NOMATCH if it's a bool quals but just does not match this - * partition key. *outconst is set to NULL in the latter two cases. + * boolean clause, set *outconst to a Const containing a true, false or NULL + * value, set *notclause according to if the clause was in the "not" form, + * i.e. "IS NOT TRUE", "IS NOT FALSE" or "IS NOT UNKNOWN" and return + * PARTCLAUSE_MATCH_CLAUSE for "IS [NOT] (TRUE|FALSE)" clauses and + * PARTCLAUSE_MATCH_NULLNESS for "IS [NOT] UNKNOWN" clauses. Otherwise, + * return PARTCLAUSE_UNSUPPORTED if the clause cannot be used for partition + * pruning, and PARTCLAUSE_NOMATCH for supported clauses that do not match this + * 'partkey'. */ static PartClauseMatchStatus match_boolean_partition_clause(Oid partopfamily, Expr *clause, Expr *partkey, - Expr **outconst, bool *noteq) + Expr **outconst, bool *notclause) { Expr *leftop; *outconst = NULL; - *noteq = false; + *notclause = false; /* * Partitioning currently can only use built-in AMs, so checking for @@ -3680,11 +3690,6 @@ match_boolean_partition_clause(Oid partopfamily, Expr *clause, Expr *partkey, { BooleanTest *btest = (BooleanTest *) clause; - /* Only IS [NOT] TRUE/FALSE are any good to us */ - if (btest->booltesttype == IS_UNKNOWN || - btest->booltesttype == IS_NOT_UNKNOWN) - return PARTCLAUSE_UNSUPPORTED; - leftop = btest->arg; if (IsA(leftop, RelabelType)) leftop = ((RelabelType *) leftop)->arg; @@ -3694,23 +3699,28 @@ match_boolean_partition_clause(Oid partopfamily, Expr *clause, Expr *partkey, switch (btest->booltesttype) { case IS_NOT_TRUE: - *noteq = true; + *notclause = true; /* fall through */ case IS_TRUE: *outconst = (Expr *) makeBoolConst(true, false); - break; + return PARTCLAUSE_MATCH_CLAUSE; case IS_NOT_FALSE: - *noteq = true; + *notclause = true; /* fall through */ case IS_FALSE: *outconst = (Expr *) makeBoolConst(false, false); - break; + return PARTCLAUSE_MATCH_CLAUSE; + case IS_NOT_UNKNOWN: + *notclause = true; + /* fall through */ + case IS_UNKNOWN: + return PARTCLAUSE_MATCH_NULLNESS; default: return PARTCLAUSE_UNSUPPORTED; } } - if (*outconst) - return PARTCLAUSE_MATCH_CLAUSE; + /* does not match partition key */ + return PARTCLAUSE_NOMATCH; } else { @@ -3726,12 +3736,11 @@ match_boolean_partition_clause(Oid partopfamily, Expr *clause, Expr *partkey, *outconst = (Expr *) makeBoolConst(!is_not_clause, false); else if (equal(negate_clause((Node *) leftop), partkey)) *outconst = (Expr *) makeBoolConst(is_not_clause, false); + else + return PARTCLAUSE_NOMATCH; - if (*outconst) - return PARTCLAUSE_MATCH_CLAUSE; + return PARTCLAUSE_MATCH_CLAUSE; } - - return PARTCLAUSE_NOMATCH; } /* |