/// <summary> /// Executes this operation /// </summary> /// <param name="rows">The pre-sorted rows.</param> /// <returns></returns> public override IEnumerable <Row> Execute(IEnumerable <Row> rows) { ObjectArrayKeys previousKey = null; var aggregate = new Row(); var groupBy = GetColumnsToGroupBy(); foreach (var row in rows) { var key = row.CreateKey(groupBy); if (previousKey != null && !previousKey.Equals(key)) { FinishAggregation(aggregate); yield return(aggregate); aggregate = new Row(); } Accumulate(row, aggregate); previousKey = key; } FinishAggregation(aggregate); yield return(aggregate); }
/// <summary> /// Executes this operation /// </summary> /// <param name="rows">The pre-sorted rows.</param> /// <param name="cancellationToken">A CancellationToken to stop execution</param> /// <returns></returns> public override IAsyncEnumerable <Row> Execute(IAsyncEnumerable <Row> rows, CancellationToken cancellationToken = default) { return(new AsyncEnumerable <Row>(async yield => { ObjectArrayKeys previousKey = null; var aggregate = new Row(); var groupBy = GetColumnsToGroupBy(); await rows.ForEachAsync(async row => { var key = row.CreateKey(groupBy); if (previousKey != null && !previousKey.Equals(key)) { FinishAggregation(aggregate); await yield.ReturnAsync(aggregate); aggregate = new Row(); } Accumulate(row, aggregate); previousKey = key; }, cancellationToken); FinishAggregation(aggregate); await yield.ReturnAsync(aggregate); })); }
/// <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> /// <param name="cancellationToken">A CancellationToken to stop execution</param> /// <returns></returns> public override IAsyncEnumerable <Row> Execute(IAsyncEnumerable <Row> rows, CancellationToken cancellationToken = default) { return(new AsyncEnumerable <Row>(async yield => { PrepareForJoin(); SetupJoinConditions(); Guard.Against(leftColumns == null, "You must setup the left columns"); Guard.Against(rightColumns == null, "You must setup the right columns"); IAsyncEnumerable <Row> rightEnumerable = await GetRightEnumerable(cancellationToken); IAsyncEnumerable <Row> execute = left.Execute(leftRegistered ? null : rows, cancellationToken); await new EventRaisingEnumerator(left, execute) .ForEachAsync(async leftRow => { ObjectArrayKeys key = leftRow.CreateKey(leftColumns); List <Row> rightRows; if (this.rightRowsByJoinKey.TryGetValue(key, out rightRows)) { foreach (Row rightRow in rightRows) { rightRowsWereMatched[rightRow] = null; await yield.ReturnAsync(MergeRows(leftRow, rightRow)); } } else if ((jointype & JoinType.Left) != 0) { Row emptyRow = new Row(); await yield.ReturnAsync(MergeRows(leftRow, emptyRow)); } else { LeftOrphanRow(leftRow); } }, cancellationToken); await rightEnumerable.ForEachAsync(async rightRow => { if (rightRowsWereMatched.ContainsKey(rightRow)) { return; } Row emptyRow = new Row(); if ((jointype & JoinType.Right) != 0) { await yield.ReturnAsync(MergeRows(emptyRow, rightRow)); } else { RightOrphanRow(rightRow); } }, cancellationToken); })); }
/// <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) { PrepareForJoin(); SetupJoinConditions(); Guard.Against(leftColumns == null, "You must setup the left columns"); Guard.Against(rightColumns == null, "You must setup the right columns"); IEnumerable <Row> rightEnumerable = GetRightEnumerable(); IEnumerable <Row> execute = left.Execute(leftRegistered ? null : rows); foreach (Row leftRow in new EventRaisingEnumerator(left, execute)) { ObjectArrayKeys key = leftRow.CreateKey(leftColumns); List <Row> rightRows; if (this.rightRowsByJoinKey.TryGetValue(key, out rightRows)) { foreach (Row rightRow in rightRows) { rightRowsWereMatched[rightRow] = null; yield return(MergeRows(leftRow, rightRow)); } } else if ((jointype & JoinType.Left) != 0) { Row emptyRow = new Row(); yield return(MergeRows(leftRow, emptyRow)); } else { LeftOrphanRow(leftRow); } } foreach (Row rightRow in rightEnumerable) { if (rightRowsWereMatched.ContainsKey(rightRow)) { continue; } Row emptyRow = new Row(); if ((jointype & JoinType.Right) != 0) { yield return(MergeRows(emptyRow, rightRow)); } else { RightOrphanRow(rightRow); } } }
/// <summary> /// Executes this operation /// </summary> /// <param name="ignored">Ignored rows</param> /// <returns></returns> public override IEnumerable <FdoRow> Execute(IEnumerable <FdoRow> ignored) { PrepareForJoin(); IEnumerable <FdoRow> rightEnumerable = GetRightEnumerable(); IEnumerable <FdoRow> execute = left.Execute(null); foreach (FdoRow leftRow in new EventRaisingEnumerator(left, execute)) { ObjectArrayKeys key = leftRow.CreateKey(leftColumns); List <FdoRow> rightRows; if (this.rightRowsByJoinKey.TryGetValue(key, out rightRows)) { foreach (FdoRow rightRow in rightRows) { rightRowsWereMatched[rightRow] = null; yield return(MergeRows(leftRow, rightRow)); } } else if ((jointype & JoinType.Left) != 0) { FdoRow emptyRow = new FdoRow(); yield return(MergeRows(leftRow, emptyRow)); } else { LeftOrphanRow(leftRow); } } foreach (FdoRow rightRow in rightEnumerable) { if (rightRowsWereMatched.ContainsKey(rightRow)) { continue; } FdoRow emptyRow = new FdoRow(); if ((jointype & JoinType.Right) != 0) { yield return(MergeRows(emptyRow, rightRow)); } else { RightOrphanRow(rightRow); } } }
private IEnumerable <FdoRow> GetRightEnumerable() { IEnumerable <FdoRow> rightEnumerable = new CachingEnumerable <FdoRow>( new EventRaisingEnumerator(right, right.Execute(null)) ); foreach (FdoRow row in rightEnumerable) { ObjectArrayKeys key = row.CreateKey(rightColumns); List <FdoRow> rowsForKey; if (this.rightRowsByJoinKey.TryGetValue(key, out rowsForKey) == false) { this.rightRowsByJoinKey[key] = rowsForKey = new List <FdoRow>(); } rowsForKey.Add(row); } return(rightEnumerable); }
private async Task <IAsyncEnumerable <Row> > GetRightEnumerable(CancellationToken cancellationToken = default) { IAsyncEnumerable <Row> rightEnumerable = new CachingEnumerable <Row>(new EventRaisingEnumerator(right, right.Execute(null, cancellationToken)), cancellationToken); await rightEnumerable.ForEachAsync(row => { ObjectArrayKeys key = row.CreateKey(rightColumns); List <Row> rowsForKey; if (this.rightRowsByJoinKey.TryGetValue(key, out rowsForKey) == false) { this.rightRowsByJoinKey[key] = rowsForKey = new List <Row>(); } rowsForKey.Add(row); }, cancellationToken); return(rightEnumerable); }
/// <summary> /// Determines whether the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>. /// </summary> /// <param name="obj">The <see cref="T:System.Object"/> to compare with the current <see cref="T:System.Object"/>.</param> /// <returns> /// true if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>; otherwise, false. /// </returns> /// <exception cref="T:System.NullReferenceException">The <paramref name="obj"/> parameter is null.</exception> public override bool Equals(object obj) { if (this == obj) { return(true); } ObjectArrayKeys other = obj as ObjectArrayKeys; if (other == null || other.columnValues.Length != this.columnValues.Length) { return(false); } for (int i = 0; i < columnValues.Length; i++) { if (Equals(this.columnValues[i], other.columnValues[i]) == false) { return(false); } } return(true); }
/// <summary> /// Executes this operation /// </summary> /// <param name="rows">The rows.</param> /// <returns></returns> public override IEnumerable <Row> Execute(IEnumerable <Row> rows) { IDictionary <ObjectArrayKeys, Row> aggregations = new Dictionary <ObjectArrayKeys, Row>(); string[] groupBy = GetColumnsToGroupBy(); foreach (Row row in rows) { ObjectArrayKeys key = row.CreateKey(groupBy); Row aggregate; if (aggregations.TryGetValue(key, out aggregate) == false) { aggregations[key] = aggregate = new Row(); } Accumulate(row, aggregate); } foreach (Row row in aggregations.Values) { FinishAggregation(row); yield return(row); } }
/// <summary> /// Executes this operation /// </summary> /// <param name="rows">The rows.</param> /// <param name="cancellationToken">A CancellationToken to stop execution</param> /// <returns></returns> public override IAsyncEnumerable <Row> Execute(IAsyncEnumerable <Row> rows, CancellationToken cancellationToken = default) { return(new AsyncEnumerable <Row>(async yield => { IDictionary <ObjectArrayKeys, Row> aggregations = new Dictionary <ObjectArrayKeys, Row>(); string[] groupBy = GetColumnsToGroupBy(); await rows.ForEachAsync(row => { ObjectArrayKeys key = row.CreateKey(groupBy); Row aggregate; if (aggregations.TryGetValue(key, out aggregate) == false) { aggregations[key] = aggregate = new Row(); } Accumulate(row, aggregate); return Task.CompletedTask; }, cancellationToken); foreach (Row row in aggregations.Values) { FinishAggregation(row); await yield.ReturnAsync(row); } })); }