Beispiel #1
0
        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);
        }
Beispiel #3
0
        /// <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);
            }
        }
Beispiel #4
0
        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);
            }
        }
Beispiel #5
0
        private static bool IsRowUnlinked(Row row, JoinSide side)
        {
            if (side == JoinSide.Left)
            {
                return(!row.LeftRowId.HasValue);
            }

            return(!row.RightRowId.HasValue);
        }
Beispiel #6
0
        private static Func <Row, bool> FindKeyByRow(int columnRowIndex, JoinSide side)
        {
            if (side == JoinSide.Left)
            {
                return(r => r.LeftRowId == columnRowIndex);
            }

            return(r => r.RightRowId == columnRowIndex);
        }
Beispiel #7
0
 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;
 }
Beispiel #9
0
        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);
                }
            }
        }
Beispiel #10
0
        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);
        }
Beispiel #11
0
 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);
 }
Beispiel #12
0
        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);
            }
        }
Beispiel #13
0
        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);
                }
            }
        }
Beispiel #15
0
        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);
        }
Beispiel #16
0
        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);
            }
        }
Beispiel #17
0
 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);
 }
Beispiel #19
0
 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);
 }
Beispiel #21
0
        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
            });
        }
Beispiel #22
0
        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());
        }
Beispiel #23
0
 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
     });
 }
Beispiel #24
0
 public Page this[JoinSide side]
 {
     get => side == JoinSide.A ? Page : AdditionalInformationPage;
Beispiel #25
0
 private static bool Equals(TEntity item, TJoinEntity e, JoinSide target) => Equals(e[target], item);
Beispiel #26
0
 public JoinCollectionFacade(TEntity ownerEntity, ICollection <TJoinEntity> collection, JoinSide navigationTarget)
 {
     this.ownerEntity      = ownerEntity;
     this.collection       = collection;
     this.navigationTarget = navigationTarget;
 }
Beispiel #27
0
 public static JoinSide GetOtherSide(this JoinSide joinSide)
 {
     return(joinSide == JoinSide.Left ? JoinSide.Right : JoinSide.Left);
 }
Beispiel #28
0
        private IEnumerable <IReactiveColumn> GetTableColumns(JoinSide side)
        {
            var table = GetTableForSide(side);

            return(table.Columns);
        }
Beispiel #29
0
        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);
                }
            }
        }
Beispiel #30
0
 private IReactiveTable GetTableForSide(JoinSide side)
 {
     return(side == JoinSide.Left ? _leftTable : _rightTable);
 }