Hi Ashutosh:

All your suggestions are followed except the UNION ALL one. I replied the
reason
below.  For the suggestions about partitioned table,  looks lot of cases to
handle, so
I summarize/enrich your idea in README and email thread,  we can continue
to talk about that.



>> +
>> +    foreach(lc,  unionrel->reltarget->exprs)
>> +    {
>> +        exprs = lappend(exprs, lfirst(lc));
>> +        colnos = lappend_int(colnos, i);
>> +        i++;
>> +    }
>>
>> This should be only possible when it's not UNION ALL. We should add some
>> assert
>> or protection for that.
>>
>
> OK, actually I called this function in generate_union_paths. which handle
> UNION case only.  I will add the Assert anyway.
>
>

Finally I found I have to add one more parameter to
populate_unionrel_uniquekeys, and
the only usage of that parameter is used to Assert, so I didn't do that at
last.


>
>> +
>> +    /* Fast path */
>> +    if (innerrel->uniquekeys == NIL || outerrel->uniquekeys == NIL)
>> +        return;
>> +
>> +    outer_is_onerow = relation_is_onerow(outerrel);
>> +    inner_is_onerow = relation_is_onerow(innerrel);
>> +
>> +    outerrel_ukey_ctx = initililze_uniquecontext_for_joinrel(joinrel,
>> outerrel);
>> +    innerrel_ukey_ctx = initililze_uniquecontext_for_joinrel(joinrel,
>> innerrel);
>> +
>> +    clause_list = gather_mergeable_joinclauses(joinrel, outerrel,
>> innerrel,
>> +                                               restrictlist, jointype);
>>
>> Something similar happens in select_mergejoin_clauses().
>
>
> I didn't realized this before.  I will refactor this code accordingly if
> necessary
> after reading that.
>
>

 I reused select_mergejoin_clauses and removed the duplicated code in
uniquekeys.c
in v8.

At least from the
>> first reading of this patch, I get an impression that all these functions
>> which
>> are going through clause lists and index lists should be merged into other
>> functions which go through these lists hunting for some information
>> useful to
>> the optimizer.
>>
> +
>> +
>> +    if (innerrel_keeps_unique(root, outerrel, innerrel, clause_list,
>> false))
>> +    {
>> +        foreach(lc, innerrel_ukey_ctx)
>> +        {
>> +            UniqueKeyContext ctx = (UniqueKeyContext)lfirst(lc);
>> +            if (!list_is_subset(ctx->uniquekey->exprs,
>> joinrel->reltarget->exprs))
>> +            {
>> +                /* The UniqueKey on baserel is not useful on the joinrel
>> */
>>
>> A joining relation need not be a base rel always, it could be a join rel
>> as
>> well.
>>
>
> good catch.
>

Fixed.


>
>
>>
>> +                ctx->useful = false;
>> +                continue;
>> +            }
>> +            if ((jointype == JOIN_LEFT || jointype == JOIN_FULL) &&
>> !ctx->uniquekey->multi_nullvals)
>> +            {
>> +                /* Change the multi_nullvals to true at this case */
>>
>> Need a comment explaining this. Generally, I feel, this and other
>> functions in
>> this file need good comments explaining the logic esp. "why" instead of
>> "what".
>
>
> Exactly.
>

Done in v8.


>> Will continue reviewing your new set of patches as time permits.
>>
>
> Thank you!  Actually there is no big difference between v6 and v7
> regarding the
>  UniqueKey part except 2 bug fix.  However v7 has some more documents,
> comments improvement and code refactor/split, which may be helpful
> for review. You may try v7 next time if v8 has not come yet:)
>
>
v8 has come :)

Best Regards
Andy Fan

Reply via email to