跟我一起读postgresql源码(十三)——Executor(查询执行模块之——Join节点(上)) (3)

跟我一起读postgresql源码(十三)——Executor(查询执行模块之——Join节点(上))

5)判断两个current是否相同,发现Currem(outer)=2等于current(inner)=2,则进行连接,同样标记inner的当前位置,并将inner的cuirent向后移动,如下图所示。其中的current(inner) = 2仍满足连接条件,因此连接完成后inner的current继续向后移动。

跟我一起读postgresql源码(十三)——Executor(查询执行模块之——Join节点(上))

6)如下图所示,current(outer)=2 小于current(inner)=5,则将 outer的current指针向后移动。

跟我一起读postgresql源码(十三)——Executor(查询执行模块之——Join节点(上))

7)此时判断current(outer)和mark(inner)相等,则将inner的current指向mark的位置,重新获取inner的元组进行匹配,如下图所示。

跟我一起读postgresql源码(十三)——Executor(查询执行模块之——Join节点(上))

8)不断重复这样的匹配模式,直到inner或outer中的一方被扫描完毕,则表示连接完成。

MergeJoin节点的定义如下:

typedef struct MergeJoin { Join join; List *mergeclauses; /* mergeclauses as expression trees */ /* these are arrays, but have the same length as the mergeclauses list: */ Oid *mergeFamilies; /* per-clause OIDs of btree opfamilies */ Oid *mergeCollations; /* per-clause OIDs of collations */ int *mergeStrategies; /* per-clause ordering (ASC or DESC) */ bool *mergeNullsFirst; /* per-clause nulls ordering */ } MergeJoin;

该节点在join的基础上扩展定义了几个mergexxx字段。其中mergeclauses存储用于计算左右子节点元组是否匹配的表达式链表,mergeFamilies、mergeCollations、mergeStrategies、mergeNullsFirst均与表达式链表对应,表明其中每一个操作符的操作符类、执行的策略(ASC或DEC)以及空值排序策略。

在初始化过程中,会使用Mergejoin构造MergeJoinState结构:

typedef struct MergeJoinState { JoinState js; /* its first field is NodeTag */ int mj_NumClauses; MergeJoinClause mj_Clauses; /* array of length mj_NumClauses */ int mj_JoinState; bool mj_ExtraMarks; bool mj_ConstFalseJoin; bool mj_FillOuter; bool mj_FillInner; bool mj_MatchedOuter; bool mj_MatchedInner; TupleTableSlot *mj_OuterTupleSlot; TupleTableSlot *mj_InnerTupleSlot; TupleTableSlot *mj_MarkedTupleSlot; TupleTableSlot *mj_NullOuterTupleSlot; TupleTableSlot *mj_NullInnerTupleSlot; ExprContext *mj_OuterEContext; ExprContext *mj_InnerEContext; } MergeJoinState;

通过对于连接类型的判断来设置如下几个变量的值:

1)mj_FillOuter:为true表示不能忽略没有匹配项的左子节点元组,需要与空元组进行连接,在 LEFT JOIN、ANTI JOIN 和 FULL JOIN时为true。

2)mj_FillInner:为true表示不能忽略没有匹配项的右子节点元组,需要与空元组进行连接,在 RIGHT JOIN、FULL JOIN 时为 true。

3)mj_InnerTupleSlot:为右子节点元组生成的空元组,在mj_FillOuter为真时构造。

4)mj_OuterTupleSlot:为左子节点元组生成的空元组,在mj_FillInner为真时构造。

除此之外,需要将标记当前左(右)子节点元组是否找到能够连接的元组的变量mj_MatchedOuter(mj_MatchedInner)设置为 false,将存储左(右)子节点元组的字段mj_NullOuterTupleSlot(mj_InnerTupleSlot)设置为 NULL,并为mj_MarkedTupleSlot分配存储空间。

还剩一个hashjoin,我看了半天看不太懂,下篇再说吧~

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpxxdf.html