On Fri, Apr 6, 2018 at 11:54 PM, Alvaro Herrera <alvhe...@alvh.no-ip.org> wrote: > Alvaro Herrera wrote: > >> Yeah. Looking at this function, I noticed it tests for BooleanTest, and >> falls back to checking "not_clause" and a few equals. Does it make >> sense if the clause is a SAOP? I added this assert: >> Assert(IsA(clause, BooleanTest) || >> IsA(clause, BoolExpr) || >> IsA(clause, RelabelType)); >> >> and it failed: >> #3 0x0000556cf04505db in match_boolean_partition_clause (partopfamily=424, >> clause=0x556cf1041670, partkey=0x556cf1042218, rightop=0x7ffe520ec068) >> at /pgsql/source/master/src/backend/optimizer/util/partprune.c:2159 >> 2159 Assert(IsA(clause, BooleanTest) || >> (gdb) print *clause >> $1 = {type = T_ScalarArrayOpExpr} >> >> I'm not sure whether or not this function can trust that what's incoming >> must absolutely be only those node types. > > So this is what I need for current regression tests not to crash > anymore: > > Assert(IsA(clause, BooleanTest) || > IsA(clause, BoolExpr) || > IsA(clause, RelabelType) || > IsA(clause, ScalarArrayOpExpr) || > IsA(clause, OpExpr) || > IsA(clause, Var)); > > I'm not confident in my ability to write code to handle all possible > cases right now (obviously there must be more cases that are not covered > by current regression tests), so I'll leave it without the assert since > it handles a couple of the useful cases, but I suspect it could stand > some more improvement. > > I guess the question is, how interesting is boolean partitioning? I bet > it has its uses.
match_boolean_partition_clauses() exists to capture some cases where an OpExpr (any expression that returns a Boolean for that matter) itself is the partition key: create table boolpart (a int) partition by list ((a = 1)); create table boolpart_t partition of boolpart for values in ('true'); create table boolpart_f partition of boolpart for values in ('false'); explain select * from boolpart where a = 1; QUERY PLAN ------------------------------------------------------------------ Append (cost=0.00..41.88 rows=13 width=4) -> Seq Scan on boolpart_t (cost=0.00..41.88 rows=13 width=4) Filter: (a = 1) (3 rows) explain select * from boolpart where a = 2; QUERY PLAN ------------------------------------------------------------------ Append (cost=0.00..41.88 rows=13 width=4) -> Seq Scan on boolpart_f (cost=0.00..41.88 rows=13 width=4) Filter: (a = 2) (3 rows) So, it's not that we're only in position to accept certain node types in match_boolean_partition_clauses(). Before it existed, the pruning didn't work because it wasn't matched to the partition key in the special way that match_boolean_partition_clauses() does and end up in the block in match_clause_to_partition_key() where the OpExpr's are analyzed for normal (non-Boolean) situations, where we extract either the leftop or rightop and try to match it with the partition key. It might as well be: create table boolpart (a int) partition by list ((a in (1, 2))); Requiring us to be position to match an ScalarArrayOpExpr with the partition key. This resembles match_boolean_index_clause(), by the way. Thanks, Amit