private bool PropagateColumnUpdates(TableUpdate update, int columnRowIndex, IReactiveTable table, Dictionary <int, HashSet <int> > columnRowsToJoinRows, JoinSide side) { HashSet <int> joinRows; IReactiveColumn updateColumn; if (table.GetColumnByName(update.Column.ColumnId, out updateColumn) && columnRowsToJoinRows.TryGetValue(columnRowIndex, out joinRows)) { foreach (var joinRow in joinRows) { var row = _rows[joinRow]; if (row.HasValue && row.Value.RowId.HasValue && !IsRowUnlinked(row.Value, side)) { var colUpdate = new TableUpdate(TableUpdateAction.Update, joinRow, update.Column); if (_updateObservers != null) { _updateObservers.OnNext(colUpdate); } return(true); } } } return(false); }
private static bool IsLastRowForColumnRowIndex(IEnumerable <Join <TKey> .Row> colRowMappings, JoinSide joinSide, int rowIndex, JoinType joinType) { if (rowIndex < 0) { return(true); } // When it's an inner join we never keep the last row // if (joinType == JoinType.Inner) return false; if (joinSide == JoinSide.Left) { // Don't keep the last row when if it's a sided outer join and we're on the other side if (joinType == JoinType.RightOuter) { return(false); } return(colRowMappings.Count(m => m.LeftRowId == rowIndex) <= 1); } // Don't keep the last row when if it's a sided outer join and we're on the other side if (joinType == JoinType.LeftOuter) { return(false); } return(colRowMappings.Count(m => m.RightRowId == rowIndex) <= 1); }
/// <summary> /// Keep the key dictionaries up to date when the key columns are updated. /// </summary> /// <param name="update"></param> private void OnNext(TableUpdate update, JoinSide side) { // Filter out add/deletes if (update.Action == TableUpdateAction.Delete) { return; } // If we have an add and which is a replay of the underlying tables then we need to // simulate column updates for all columns if (update.Action == TableUpdateAction.Add) { if (!_replaying) { return; } var columns = GetTableColumns(side); foreach (var column in columns) { update = new TableUpdate(TableUpdateAction.Update, update.RowIndex, column); ProcessColumnUpdate(update, column); } } else { // Key update ProcessColumnUpdate(update, update.Column); } }
private void AddNewRowMapping(int columnRowIndex, JoinSide side, ColumnRowMapping keyRowsMapping, List <RowToUpdate> updateRows, TKey key, Dictionary <int, HashSet <int> > otherColumnRowsToJoinRows, Dictionary <int, HashSet <int> > columnRowsToJoinRows) { // For each distinct row on the other side we need to create a new row and link ourselves var otherRows = GetDistinctOtherRows(keyRowsMapping, side); var otherRowIds = otherRows.ToArray(); foreach (var otherRowId in otherRowIds) { int?joinedRowId = GetNewRowId(); var joinRow = CreateNewLinkedJoinRow(columnRowIndex, joinedRowId.Value, key, otherRowId, side); keyRowsMapping.ColRowMappings.Add(joinRow); AddNewRow(joinRow, updateRows, joinedRowId.Value); // Update the reverse lookup columnRowsToJoinRows.GetOrAddNew(columnRowIndex).Add(joinedRowId.Value); otherColumnRowsToJoinRows.GetOrAddNew(otherRowId.Value).Add(joinedRowId.Value); } // If there are no matching entries on the other side we still need to add a row and mapping if (otherRowIds.Length == 0) { UpdateNewKeyInExistingMapping(columnRowIndex, side, key, updateRows, columnRowsToJoinRows, keyRowsMapping); } }
private static bool IsRowUnlinked(Row row, JoinSide side) { if (side == JoinSide.Left) { return(!row.LeftRowId.HasValue); } return(!row.RightRowId.HasValue); }
private static Func <Row, bool> FindKeyByRow(int columnRowIndex, JoinSide side) { if (side == JoinSide.Left) { return(r => r.LeftRowId == columnRowIndex); } return(r => r.RightRowId == columnRowIndex); }
private static void LinkRow(ref Row unlinked, int columnRowIndex, JoinSide side) { if (side == JoinSide.Left) { unlinked.LeftRowId = columnRowIndex; } else { unlinked.RightRowId = columnRowIndex; } }
public JoinRowDeleteHandler(List <Join <TKey> .Row?> rows, Dictionary <TKey, Join <TKey> .ColumnRowMapping> rowsByKey, Dictionary <int, HashSet <int> > columnRowsToJoinRows, Dictionary <int, HashSet <int> > otherColumnRowsToJoinRows, JoinSide joinSide, JoinType joinType, FieldRowManager rowManager) { _rows = rows; _rowsByKey = rowsByKey; _columnRowsToJoinRows = columnRowsToJoinRows; _otherColumnRowsToJoinRows = otherColumnRowsToJoinRows; _joinSide = joinSide; _joinType = joinType; _rowManager = rowManager; }
private void SendColumnUpdates(JoinSide side, int rowIndex) { var table = GetTableForSide(side); foreach (var tableColumn in table.Columns) { var columnUpdate = new TableUpdate(TableUpdateAction.Update, rowIndex, tableColumn); if (_updateObservers != null) { _updateObservers.OnNext(columnUpdate); } } }
private ColumnRowMapping UpdateNewKey(int columnRowIndex, JoinSide side, TKey key, List <RowToUpdate> updateRows, Dictionary <int, HashSet <int> > columnRowsToJoinRows) { // First time this key has been used so create a new (unlinked on the other side) var keyRowsMapping = new ColumnRowMapping { ColRowMappings = new List <Row>() }; UpdateNewKeyInExistingMapping(columnRowIndex, side, key, updateRows, columnRowsToJoinRows, keyRowsMapping); return(keyRowsMapping); }
private bool ShouldAddUnlinkedRow(JoinSide side) { if (_joinType == JoinType.Inner) { return(false); } if (_joinType == JoinType.LeftOuter) { return(side == JoinSide.Left); } if (_joinType == JoinType.RightOuter) { return(side == JoinSide.Right); } return(true); }
private void UpdateNewKeyInExistingMapping(int columnRowIndex, JoinSide side, TKey key, List <RowToUpdate> updateRows, Dictionary <int, HashSet <int> > columnRowsToJoinRows, ColumnRowMapping keyRowsMapping) { var shouldAddUnlinkedRow = ShouldAddUnlinkedRow(side); var joinedRowId = shouldAddUnlinkedRow ? GetNewRowId() : (int?)null; var joinRow = CreateNewJoinRow(columnRowIndex, key, joinedRowId, side); keyRowsMapping.ColRowMappings.Add(joinRow); if (shouldAddUnlinkedRow) { AddNewRow(joinRow, updateRows, joinedRowId.Value); // Update the reverse lookup columnRowsToJoinRows.GetOrAddNew(columnRowIndex).Add(joinedRowId.Value); } }
private void LinkNewItemToUnlinkedRows(int columnRowIndex, JoinSide side, ColumnRowMapping keyRowsMapping, List <RowToUpdate> updateRows, Dictionary <int, HashSet <int> > otherColumnRowsToJoinRows, Dictionary <int, HashSet <int> > columnRowsToJoinRows, int i) { int?joinedRowId; // Link the row to the joined row. var rowToLink = keyRowsMapping.ColRowMappings[i]; LinkRow(ref rowToLink, columnRowIndex, side); // We need to create the new row here (when we link) if (!rowToLink.RowId.HasValue) { joinedRowId = GetNewRowId(); rowToLink.RowId = joinedRowId; // Can't forget to update the existing row object with the new id AddNewRow(rowToLink, updateRows, joinedRowId.Value); // Need to update the reverse mapping for the other side too as it wasn't done before var otherRowId = side == JoinSide.Left ? rowToLink.RightRowId : rowToLink.LeftRowId; otherColumnRowsToJoinRows.GetOrAddNew(otherRowId.Value).Add(joinedRowId.Value); } else { updateRows.Add(new RowToUpdate { RowIndex = rowToLink.RowId.Value, Type = RowToUpdate.RowUpdateType.Link }); joinedRowId = rowToLink.RowId; } keyRowsMapping.ColRowMappings[i] = rowToLink; _rows[joinedRowId.Value] = rowToLink; // Update the reverse lookup columnRowsToJoinRows.GetOrAddNew(columnRowIndex).Add(joinedRowId.Value); }
private static void RemoveReverseMapping(Join <TKey> .Row mapping, JoinSide joinSide, Dictionary <int, HashSet <int> > columnRowsToJoinRows) { if (joinSide == JoinSide.Left) { var leftRowsToJoinRow = columnRowsToJoinRows[mapping.LeftRowId.Value]; if (mapping.RowId.HasValue) { leftRowsToJoinRow.Remove(mapping.RowId.Value); } else { leftRowsToJoinRow.Clear(); } if (leftRowsToJoinRow.Count == 0) { columnRowsToJoinRows.Remove(mapping.LeftRowId.Value); } } else { var rightRowsToJoinRow = columnRowsToJoinRows[mapping.RightRowId.Value]; if (mapping.RowId.HasValue) { rightRowsToJoinRow.Remove(mapping.RowId.Value); } else { rightRowsToJoinRow.Clear(); } if (rightRowsToJoinRow.Count == 0) { columnRowsToJoinRows.Remove(mapping.RightRowId.Value); } } }
private List <RowToUpdate> OnColumnUpdate(int columnRowIndex, JoinSide side) { var updateRows = new List <RowToUpdate>(); var table = side == JoinSide.Left ? _leftTable : _rightTable; var column = side == JoinSide.Left ? _leftColumn : _rightColumn; var key = table.GetValue <TKey>(column.ColumnId, columnRowIndex); ColumnRowMapping keyRowsMapping; // Has the key been used before? var otherColumnRowsToJoinRows = side == JoinSide.Left ? _rightColumnRowsToJoinRows : _leftColumnRowsToJoinRows; var columnRowsToJoinRows = side == JoinSide.Left ? _leftColumnRowsToJoinRows : _rightColumnRowsToJoinRows; if (_rowsByKey.TryGetValue(key, out keyRowsMapping)) { HashSet <int> existingRowIndeces; // Existing row if (columnRowsToJoinRows.TryGetValue(columnRowIndex, out existingRowIndeces)) { UpdateExistingRow(columnRowIndex, side, keyRowsMapping, existingRowIndeces, key, columnRowsToJoinRows); } // New row else { UpdateNewRow(columnRowIndex, side, keyRowsMapping, updateRows, key, otherColumnRowsToJoinRows, columnRowsToJoinRows); } } // New key else { keyRowsMapping = UpdateNewKey(columnRowIndex, side, key, updateRows, columnRowsToJoinRows); } _rowsByKey[key] = keyRowsMapping; return(updateRows); }
private void UpdateNewRow(int columnRowIndex, JoinSide side, ColumnRowMapping keyRowsMapping, List <RowToUpdate> updateRows, TKey key, Dictionary <int, HashSet <int> > otherColumnRowsToJoinRows, Dictionary <int, HashSet <int> > columnRowsToJoinRows) { // Other side rows exist with no mapping - try to join to an unlinked one var unlinkedIndex = keyRowsMapping.ColRowMappings.FindIndex(IsRowUnlinked(side)); if (unlinkedIndex >= 0) { for (var i = unlinkedIndex; i < keyRowsMapping.ColRowMappings.Count; i++) { LinkNewItemToUnlinkedRows(columnRowIndex, side, keyRowsMapping, updateRows, otherColumnRowsToJoinRows, columnRowsToJoinRows, i); } } // No unlinked - add new mappings and rows for each row on the other side else { AddNewRowMapping(columnRowIndex, side, keyRowsMapping, updateRows, key, otherColumnRowsToJoinRows, columnRowsToJoinRows); } }
private void UpdateExistingRow(int columnRowIndex, JoinSide side, ColumnRowMapping keyRowsMapping, HashSet <int> existingRowIndeces, TKey key, Dictionary <int, HashSet <int> > columnRowsToJoinRows) { // Same key as before if (keyRowsMapping.ColRowMappings.Any(FindKeyByRow(columnRowIndex, side))) { // Do nothing } // Key has changed else { foreach (var rowId in existingRowIndeces) { var oldKey = _rows[rowId].Value.Key; // TODO: Need to possibly alter other keyRowMappings - not possible with current method signature. keyRowsMapping = MoveKeyEntry(_rows, rowId, oldKey, key, columnRowsToJoinRows, keyRowsMapping, _rowsByKey); } } }
private static bool IsRow(Join <TKey> .Row row, JoinSide joinSide, int rowIndex) { return(joinSide == JoinSide.Left ? row.LeftRowId == rowIndex : row.RightRowId == rowIndex); }
private static Predicate <Row> IsRowUnlinked(JoinSide side) { return(r => IsRowUnlinked(r, side)); }
private static bool IsRowForOtherSide(Join <TKey> .Row row, JoinSide joinSide, int rowIndex) { return(joinSide == JoinSide.Left ? row.LeftRowId == rowIndex && row.RightRowId == null : row.RightRowId == rowIndex && row.LeftRowId == null); }
private static Row CreateNewLinkedJoinRow(int columnRowIndex, int joinedRowId, TKey key, int?otherRowId, JoinSide side) { if (side == JoinSide.Left) { return(new Row { RowId = joinedRowId, Key = key, LeftRowId = columnRowIndex, RightRowId = otherRowId }); } return(new Row { RowId = joinedRowId, Key = key, RightRowId = columnRowIndex, LeftRowId = otherRowId }); }
private static IEnumerable <int?> GetDistinctOtherRows(ColumnRowMapping keyRowsMapping, JoinSide side) { if (side == JoinSide.Left) { return(keyRowsMapping.ColRowMappings.Where(r => r.RightRowId.HasValue).Select(r => r.RightRowId).Distinct()); } return(keyRowsMapping.ColRowMappings.Where(r => r.LeftRowId.HasValue).Select(r => r.LeftRowId).Distinct()); }
private static Row CreateNewJoinRow(int columnRowIndex, TKey key, int?joinedRowId, JoinSide side) { if (side == JoinSide.Left) { return(new Row { Key = key, LeftRowId = columnRowIndex, RowId = joinedRowId }); } return(new Row { Key = key, RightRowId = columnRowIndex, RowId = joinedRowId }); }
public Page this[JoinSide side] { get => side == JoinSide.A ? Page : AdditionalInformationPage;
private static bool Equals(TEntity item, TJoinEntity e, JoinSide target) => Equals(e[target], item);
public JoinCollectionFacade(TEntity ownerEntity, ICollection <TJoinEntity> collection, JoinSide navigationTarget) { this.ownerEntity = ownerEntity; this.collection = collection; this.navigationTarget = navigationTarget; }
public static JoinSide GetOtherSide(this JoinSide joinSide) { return(joinSide == JoinSide.Left ? JoinSide.Right : JoinSide.Left); }
private IEnumerable <IReactiveColumn> GetTableColumns(JoinSide side) { var table = GetTableForSide(side); return(table.Columns); }
private void UpdateRowObserversAdd(IEnumerable <RowToUpdate> updatedRows, IReactiveColumn column, JoinSide side) { foreach (var updatedRow in updatedRows) { // Update that the new row exists if (updatedRow.Type == RowToUpdate.RowUpdateType.Add) { var rowUpdate = new TableUpdate(TableUpdateAction.Add, updatedRow.RowIndex); if (_updateObservers != null) { _updateObservers.OnNext(rowUpdate); } // Update all columns for newly added row on the sides that are present. var row = _rows[updatedRow.RowIndex]; if (row.HasValue && row.Value.LeftRowId.HasValue) { SendColumnUpdates(JoinSide.Left, updatedRow.RowIndex); } if (row.HasValue && row.Value.RightRowId.HasValue) { SendColumnUpdates(JoinSide.Right, updatedRow.RowIndex); } } else { // Update all rows on the side that has been added and also on the other side if also joined SendColumnUpdates(side, updatedRow.RowIndex); } } }
private IReactiveTable GetTableForSide(JoinSide side) { return(side == JoinSide.Left ? _leftTable : _rightTable); }