Hello, let me make some comments. At Tue, 30 Jan 2018 09:57:44 +0900, Amit Langote <langote_amit...@lab.ntt.co.jp> wrote in <4a7dda08-b883-6e5e-b0bf-f5ce95584...@lab.ntt.co.jp> > Hi Jesper. > > On 2018/01/29 22:13, Jesper Pedersen wrote: > > Hi Amit, > > > > On 01/26/2018 04:17 AM, Amit Langote wrote: > >> I made a few of those myself in the updated patches. > >> > >> Thanks a lot again for your work on this. > >> > > > > This needs a rebase. > > AFAICS, v22 cleanly applies to HEAD (c12693d8f3 [1]), compiles, and make > check passes.
Yes, it cleanly applies to HEAD and seems working. 0001 seems fine. I have some random comments on 0002. -extract_partition_key_clauses implicitly assumes that the commutator of inequality operator is the same to the original operator. (commutation for such operators is an identity function.) I believe it is always true for a sane operator definition, but perhaps wouldn't it be better using commutator instead of opclause->opno as the source of negator if any? (Attached diff 1) -get_partitions_from_or_clause_args abandons arg_partset with all bit set when partition constraint doesn't refute whole the partition. Finally get_partitions_from_clauses does the same thing but it's waste of cycles and looks weird. It seems to have intended to return immediately there. > /* Couldn't eliminate any of the partitions. */ > partdesc = RelationGetPartitionDesc(context->relation); > - arg_partset = bms_add_range(NULL, 0, partdesc->nparts - 1); > + return bms_add_range(NULL, 0, partdesc->nparts - 1); > } > > subcontext.rt_index = context->rt_index; > subcontext.relation = context->relation; > subcontext.clauseinfo = &partclauseinfo; !> arg_partset = get_partitions_from_clauses(&subcontext); -get_partitions_from_or_clause_args converts IN (null) into nulltest and the nulltest doesn't exclude a child that the partition key column can be null. drop table if exists p; create table p (a int, b int) partition by list (a); create table c1 partition of p for values in (1, 5, 7); create table c2 partition of p for values in (4, 6, null); insert into p values (1, 0), (null, 0); explain select tableoid::regclass, * from p where a in (1, null); > QUERY PLAN > ----------------------------------------------------------------- > Result (cost=0.00..76.72 rows=22 width=12) > -> Append (cost=0.00..76.50 rows=22 width=12) > -> Seq Scan on c1 (cost=0.00..38.25 rows=11 width=12) > Filter: (a = ANY ('{1,NULL}'::integer[])) > -> Seq Scan on c2 (cost=0.00..38.25 rows=11 width=12) > Filter: (a = ANY ('{1,NULL}'::integer[])) Although the clause "a in (null)" doesn't match the (null, 0) row so it donesn't harm finally, I don't think this is a right behavior. null in an SAOP rightop should be just ignored on partition pruning. Or is there any purpose of this behavior? - In extract_bounding_datums, clauseinfo is set twice to the same value. regards, -- Kyotaro Horiguchi NTT Open Source Software Center
diff --git a/src/backend/catalog/partition.c b/src/backend/catalog/partition.c index ab17524..a2488ab 100644 --- a/src/backend/catalog/partition.c +++ b/src/backend/catalog/partition.c @@ -2111,7 +2111,6 @@ extract_partition_key_clauses(PartitionKey partkey, List *clauses, PartClause *pc; Oid partopfamily = partkey->partopfamily[i]; Oid partcoll = partkey->partcollation[i]; - Oid commutator = InvalidOid; AttrNumber partattno = partkey->partattrs[i]; Expr *partexpr = NULL; @@ -2144,6 +2143,7 @@ extract_partition_key_clauses(PartitionKey partkey, List *clauses, if (IsA(clause, OpExpr)) { OpExpr *opclause = (OpExpr *) clause; + Oid comparator = opclause->opno; Expr *leftop, *rightop, *valueexpr; @@ -2161,13 +2161,14 @@ extract_partition_key_clauses(PartitionKey partkey, List *clauses, valueexpr = rightop; else if (EXPR_MATCHES_PARTKEY(rightop, partattno, partexpr)) { - valueexpr = leftop; - - commutator = get_commutator(opclause->opno); + Oid commutator = get_commutator(opclause->opno); /* nothing we can do unless we can swap the operands */ if (!OidIsValid(commutator)) continue; + + valueexpr = leftop; + comparator = commutator; } else /* Clause does not match this partition key. */ @@ -2212,7 +2213,7 @@ extract_partition_key_clauses(PartitionKey partkey, List *clauses, * equality operator *and* this is a list partitioned * table, we can use it prune partitions. */ - negator = get_negator(opclause->opno); + negator = get_negator(comparator); if (OidIsValid(negator) && op_in_opfamily(negator, partopfamily)) { @@ -2236,7 +2237,7 @@ extract_partition_key_clauses(PartitionKey partkey, List *clauses, } pc = (PartClause *) palloc0(sizeof(PartClause)); - pc->opno = OidIsValid(commutator) ? commutator : opclause->opno; + pc->opno = comparator; pc->inputcollid = opclause->inputcollid; pc->value = valueexpr;