Example #1
0
            /// <summary>
            /// Constructs a join propagator.
            /// </summary>
            /// <param name="left">Result of propagating changes in the left input to the join</param>
            /// <param name="right">Result of propagating changes in the right input to the join</param>
            /// <param name="node">Join operator in update mapping view over which to propagate changes</param>
            /// <param name="parent">Handler of propagation for the entire update mapping view</param>
            internal JoinPropagator(ChangeNode left, ChangeNode right, DbJoinExpression node, Propagator parent)
            {
                EntityUtil.CheckArgumentNull(left, "left");
                EntityUtil.CheckArgumentNull(right, "right");
                EntityUtil.CheckArgumentNull(node, "node");
                EntityUtil.CheckArgumentNull(parent, "parent");

                m_left           = left;
                m_right          = right;
                m_joinExpression = node;
                m_parent         = parent;

                Debug.Assert(DbExpressionKind.LeftOuterJoin == node.ExpressionKind || DbExpressionKind.InnerJoin == node.ExpressionKind, "(Update/JoinPropagagtor/JoinEvaluator) " +
                             "caller must ensure only left outer and inner joins are requested");
                // Retrieve propagation rules for the join type of the expression.
                if (DbExpressionKind.InnerJoin == m_joinExpression.ExpressionKind)
                {
                    m_insertRules = s_innerJoinInsertRules;
                    m_deleteRules = s_innerJoinDeleteRules;
                }
                else
                {
                    m_insertRules = s_leftOuterJoinInsertRules;
                    m_deleteRules = s_leftOuterJoinDeleteRules;
                }

                // Figure out key selectors involved in the equi-join (if it isn't an equi-join, we don't support it)
                JoinConditionVisitor.GetKeySelectors(node.JoinCondition, out m_leftKeySelectors, out m_rightKeySelectors);

                // Find the key selector expressions in the left and right placeholders
                m_leftPlaceholderKey  = ExtractKey(m_left.Placeholder, m_leftKeySelectors, m_parent);
                m_rightPlaceholderKey = ExtractKey(m_right.Placeholder, m_rightKeySelectors, m_parent);
            }
Example #2
0
            /// <summary>
            /// Performs join propagation.
            /// </summary>
            /// <returns>Changes propagated to the current join node in the update mapping view.</returns>
            internal ChangeNode Propagate()
            {
                // Construct an empty change node for the result
                ChangeNode result = Propagator.BuildChangeNode(m_joinExpression);

                // Gather all keys involved in the join
                JoinDictionary leftDeletes  = ProcessKeys(m_left.Deleted, m_leftKeySelectors);
                JoinDictionary leftInserts  = ProcessKeys(m_left.Inserted, m_leftKeySelectors);
                JoinDictionary rightDeletes = ProcessKeys(m_right.Deleted, m_rightKeySelectors);
                JoinDictionary rightInserts = ProcessKeys(m_right.Inserted, m_rightKeySelectors);
                var            allKeys      = leftDeletes.Keys
                                              .Concat(leftInserts.Keys)
                                              .Concat(rightDeletes.Keys)
                                              .Concat(rightInserts.Keys)
                                              .Distinct(m_parent.UpdateTranslator.KeyComparer);

                // Perform propagation one key at a time
                foreach (CompositeKey key in allKeys)
                {
                    Propagate(key, result, leftDeletes, leftInserts, rightDeletes, rightInserts);
                }

                // Construct a new placeholder (see ChangeNode.Placeholder) for the join result node.
                result.Placeholder = CreateResultTuple(Tuple.Create((CompositeKey)null, m_left.Placeholder), Tuple.Create((CompositeKey)null, m_right.Placeholder), result);

                return(result);
            }
            /// <summary>
            /// Constructs an evaluator for evaluating expressions for the given row.
            /// </summary>
            /// <param name="row">Row to match</param>
            /// <param name="parent">Propagator context</param>
            private Evaluator(PropagatorResult row, Propagator parent)
            {
                EntityUtil.CheckArgumentNull(row, "row");
                EntityUtil.CheckArgumentNull(parent, "parent");

                m_row    = row;
                m_parent = parent;
            }
Example #4
0
        /// <summary>
        /// Propagate changes from C-Space (contained in <paramref name="parent" /> to the S-Space.
        /// </summary>
        /// <remarks>
        /// See Walker class for an explanation of this coding pattern.
        /// </remarks>
        /// <param name="parent">Grouper supporting retrieval of changes for C-Space
        /// extents referenced in the update mapping view.</param>
        /// <param name="table">Table for which updates are being produced.</param>
        /// <param name="umView">Update mapping view to propagate.</param>
        /// <returns>Changes in S-Space.</returns>
        static internal ChangeNode Propagate(UpdateTranslator parent, EntitySet table, DbQueryCommandTree umView)
        {
            // Construct a new instance of a propagator, which implements a visitor interface
            // for expression nodes (nodes in the update mapping view) and returns changes nodes
            // (seeded by C-Space extent changes returned by the grouper).
            DbExpressionVisitor <ChangeNode> propagator = new Propagator(parent, table);

            // Walk the update mapping view using the visitor pattern implemented in this class.
            // The update mapping view describes the S-Space table we're targeting, so the result
            // returned for the root of view corresponds to changes propagated to the S-Space.
            return(umView.Query.Accept(propagator));
        }
Example #5
0
 // extracts key values from row expression
 private static CompositeKey ExtractKey(PropagatorResult change, ReadOnlyCollection <DbExpression> keySelectors, Propagator parent)
 {
     Debug.Assert(null != change && null != keySelectors && null != parent);
     PropagatorResult[] keyValues = new PropagatorResult[keySelectors.Count];
     for (int i = 0; i < keySelectors.Count; i++)
     {
         PropagatorResult constant = Evaluator.Evaluate(keySelectors[i], change, parent);
         keyValues[i] = constant;
     }
     return(new CompositeKey(keyValues));
 }
 /// <summary>
 /// Utility method filtering out a set of rows given a predicate.
 /// </summary>
 /// <param name="predicate">Match criteria.</param>
 /// <param name="rows">Input rows.</param>
 /// <param name="parent">Propagator context</param>
 /// <returns>Input rows matching criteria.</returns>
 internal static IEnumerable <PropagatorResult> Filter(DbExpression predicate, IEnumerable <PropagatorResult> rows, Propagator parent)
 {
     foreach (PropagatorResult row in rows)
     {
         if (EvaluatePredicate(predicate, row, parent))
         {
             yield return(row);
         }
     }
 }
            /// <summary>
            /// Evaluates scalar node.
            /// </summary>
            /// <param name="node">Sub-query returning a scalar value.</param>
            /// <param name="row">Row to evaluate.</param>
            /// <param name="parent">Propagator context.</param>
            /// <returns>Scalar result.</returns>
            static internal PropagatorResult Evaluate(DbExpression node, PropagatorResult row, Propagator parent)
            {
                DbExpressionVisitor <PropagatorResult> evaluator = new Evaluator(row, parent);

                return(node.Accept(evaluator));
            }
            /// <summary>
            /// Utility method determining whether a row matches a predicate.
            /// </summary>
            /// <remarks>
            /// See Walker class for an explanation of this coding pattern.
            /// </remarks>
            /// <param name="predicate">Match criteria.</param>
            /// <param name="row">Input row.</param>
            /// <param name="parent">Propagator context</param>
            /// <returns><c>true</c> if the row matches the criteria; <c>false</c> otherwise</returns>
            internal static bool EvaluatePredicate(DbExpression predicate, PropagatorResult row, Propagator parent)
            {
                Evaluator        evaluator        = new Evaluator(row, parent);
                PropagatorResult expressionResult = predicate.Accept(evaluator);

                bool?result = ConvertResultToBool(expressionResult);

                // unknown --> false at base of predicate
                return(result ?? false);
            }