Hi Hou-san, I tried to compare the logic of patch v3-0001 versus the original HEAD code.
IMO this patch logic is not exactly the same as before -- there are some subtle differences. I am not sure if these differences represent real problems or not. Below are all my review comments: ====== 1. /* Switch relation if publishing via root. */ if (relentry->publish_as_relid != RelationGetRelid(relation)) { Assert(relation->rd_rel->relispartition); ancestor = RelationIdGetRelation(relentry->publish_as_relid); targetrel = ancestor; } ~ The "switch relation if publishing via root" logic is now happening first, whereas the original code was doing this after the slot assignments. AFAIK it does not matter, it's just a small point of difference. ====== 2. /* Convert tuple if needed. */ if (relentry->attrmap) { ... } The "Convert tuple if needed." logic looks the same, but when it is executed is NOT the same. It could be a problem. Previously, the conversion would only happen within the "Switch relation if publishing via root." condition. But the patch no longer has that extra condition -- now I think it attempts conversion every time regardless of "publishing via root". I would expect the "publish via root" case to be less common, so even if the current code works, by omitting that check won't this patch have an unnecessary performance hit due to the extra conversions? ~~ 3. if (old_slot) old_slot = execute_attr_map_slot(relentry->attrmap,old_slot,MakeTupleTableSlot(tupdesc, &TTSOpsVirtual)); ~ The previous conversion code for UPDATE (shown above) was checking "if (old_slot)". Actually, I don't know why that check was even necessary before but it seems to have been accounting for a possibility that UPDATE might not have "oldtuple". But this combination (if indeed it was possible) is not handled anymore with the patch code because the old_slot is unconditionally assigned in the same block doing this conversion. Perhaps that original HEAD extra check was just overkill? TAP tests obviously still are passing with the patch, but anyway, this is yet another small point of difference for the refactored patch code. ====== 4. AFAIK, the "if (change->data.tp.newtuple)" can only be true for INSERT or UPDATE, so the code would be better to include a sanity Assert. SUGGESTION if (change->data.tp.newtuple) { Assert(action == REORDER_BUFFER_CHANGE_INSERT || action == REORDER_BUFFER_CHANGE_UPDATE); ... } ====== 5. AFAIK, the "if (change->data.tp.oldtuple)" can only be true for UPDATE or DELETE, so the code would be better to include a sanity Assert. SUGGESTION if (change->data.tp.oldtuple) { Assert(action == REORDER_BUFFER_CHANGE_UPDATE || action == REORDER_BUFFER_CHANGE_DELETE); ... } ====== 6. I suggest moving the "change->data.tp.oldtuple" check before the "change->data.tp.newtuple" check. I don't think it makes any difference, but it seems more natural IMO to have old before new. ------ Kind Regards, Peter Smith