/// <summary> /// Executes this operation /// </summary> /// <param name="rows">Rows in pipeline. These are only used if a left part of the join was not specified.</param> /// <returns></returns> public override IEnumerable <Row> Execute(IEnumerable <Row> rows) { Initialize(); Guard.Against(left == null, "Left branch of a join cannot be null"); Guard.Against(right == null, "Right branch of a join cannot be null"); var leftRows = new EventRaisingEnumerator(left, left.Execute(leftRegistered ? null : rows)).GetEnumerator(); leftRows.MoveNext(); var leftRow = (Row)leftRows.Current; var rightRows = new EventRaisingEnumerator(right, right.Execute(null)).GetEnumerator(); rightRows.MoveNext(); var rightRow = (Row)rightRows.Current; while (leftRow != null && rightRow != null) { var match = MatchJoinCondition(leftRow, rightRow); Row mergedRow = null; if (match == 0) { mergedRow = MergeRows(leftRow, rightRow); leftRow = leftRows.MoveNext() ? (Row)leftRows.Current : null; rightRow = rightRows.MoveNext() ? (Row)rightRows.Current : null; } else if (match < 0) { if ((JoinType & JoinType.Left) != 0) { mergedRow = MergeRows(leftRow, new Row()); } else { LeftOrphanRow(leftRow); } leftRow = leftRows.MoveNext() ? (Row)leftRows.Current : null; } else if (match > 0) { if ((JoinType & JoinType.Right) != 0) { mergedRow = MergeRows(new Row(), rightRow); } else { RightOrphanRow(rightRow); } rightRow = rightRows.MoveNext() ? (Row)rightRows.Current : null; } if (mergedRow != null) { yield return(mergedRow); } } if (leftRow == null && rightRow != null && (JoinType & JoinType.Right) != 0) { yield return(MergeRows(new Row(), rightRow)); } }
/// <summary> /// Executes this operation /// </summary> /// <param name="rows">Rows in pipeline. These are only used if a left part of the join was not specified.</param> /// <returns></returns> public override IEnumerable <Row> Execute(IEnumerable <Row> rows) { Initialize(); Guard.Against(left == null, "Left branch of a join cannot be null"); Guard.Against(right == null, "Right branch of a join cannot be null"); var matchedRightRows = new Dictionary <Row, object>(); var rightEnumerable = new CachingEnumerable <Row>( new EventRaisingEnumerator(right, right.Execute(null)) ); var execute = left.Execute(leftRegistered ? null : rows); foreach (Row leftRow in new EventRaisingEnumerator(left, execute)) { var leftNeedOuterJoin = true; currentLeftRow = leftRow; foreach (Row rightRow in rightEnumerable) { currentRightRow = rightRow; if (MatchJoinCondition(leftRow, rightRow)) { leftNeedOuterJoin = false; matchedRightRows[rightRow] = null; yield return(MergeRows(leftRow, rightRow)); } } if (leftNeedOuterJoin) { var emptyRow = new Row(); emptyRow[IsEmptyRowMarker] = IsEmptyRowMarker; currentRightRow = emptyRow; if (MatchJoinCondition(leftRow, emptyRow)) { yield return(MergeRows(leftRow, emptyRow)); } else { LeftOrphanRow(leftRow); } } } foreach (Row rightRow in rightEnumerable) { if (matchedRightRows.ContainsKey(rightRow)) { continue; } currentRightRow = rightRow; var emptyRow = new Row(); emptyRow[IsEmptyRowMarker] = IsEmptyRowMarker; currentLeftRow = emptyRow; if (MatchJoinCondition(emptyRow, rightRow)) { yield return(MergeRows(emptyRow, rightRow)); } else { RightOrphanRow(rightRow); } } }