Beispiel #1
0
        public override void Visit(DerefOp op, Node n)
        {
            VisitScalarOpDefault(op, n);
            Assert(TypeSemantics.IsEntityType(op.Type), "Expected an entity type. Found " + op.Type);
            Assert(TypeSemantics.IsReferenceType(n.Child0.Op.Type), "Expected a ref type. Found " + n.Child0.Op.Type);
            RefType r = n.Child0.Op.Type.EdmType as RefType;

            Assert(r.ElementType.EdmEquals(op.Type.EdmType), "Inconsistent types");
        }
        /// <summary>
        /// Produces a relop tree that "logically" produces the target of the derefop. In essence, this gets rewritten
        /// into 
        ///      SELECT VALUE e
        ///      FROM (SELECT VALUE e0 FROM OFTYPE(ES0, T) as e0
        ///            UNION ALL
        ///            SELECT VALUE e1 FROM OFTYPE(ES1, T) as e1
        ///            ...
        ///            SELECT VALUE eN from OFTYPE(ESN, T) as eN)) as e
        ///      WHERE REF(e) = myRef
        ///      
        /// "T" is the target type of the Deref, and myRef is the (single) argument to the DerefOp
        /// 
        /// ES0, ES1 etc. are all the EntitySets that could hold instances that are at least of type "T". We identify this list of sets 
        /// by looking at all entitycontainers referenced in the query, and looking at all entitysets in those
        /// containers that are of the right type
        /// An EntitySet ES (of entity type X) can hold instances of T, if one of the following is true
        ///   - T is a subtype of X 
        ///   - X is equal to T
        /// Our situation is a little trickier, since we also need to look for cases where X is a subtype of T. 
        /// </summary>
        /// <param name="derefOpNode">the derefOp subtree</param>
        /// <param name="derefOp">the derefOp</param>
        /// <param name="outputVar">output var produced</param>
        /// <returns>the subquery described above</returns>
        private Node RewriteDerefOp(Node derefOpNode, DerefOp derefOp, out Var outputVar)
        {
            var entityType = derefOp.Type;
            var targetEntitySets = GetEntitySets(entityType);
            if (targetEntitySets.Count == 0)
            {
                // We didn't find any entityset that could match this. Simply return a null-value
                outputVar = null;
                return m_command.CreateNode(m_command.CreateNullOp(entityType));
            }

            var scanTableNodes = new List<Node>();
            var scanTableVars = new List<Var>();
            foreach (var entitySet in targetEntitySets)
            {
                Var tableVar;
                var tableNode = BuildOfTypeTable(entitySet, entityType, out tableVar);

                scanTableNodes.Add(tableNode);
                scanTableVars.Add(tableVar);
            }
            Node unionAllNode;
            Var unionAllVar;
            m_command.BuildUnionAllLadder(scanTableNodes, scanTableVars, out unionAllNode, out unionAllVar);

            //
            // Finally build up the key comparison predicate
            //
            var entityRefNode = m_command.CreateNode(
                m_command.CreateGetEntityRefOp(derefOpNode.Child0.Op.Type),
                m_command.CreateNode(m_command.CreateVarRefOp(unionAllVar)));
            var keyComparisonPred = m_command.BuildComparison(OpType.EQ, derefOpNode.Child0, entityRefNode);
            var filterNode = m_command.CreateNode(
                m_command.CreateFilterOp(),
                unionAllNode,
                keyComparisonPred);

            outputVar = unionAllVar;
            return filterNode;
        }
        /// <summary>
        /// Rewrite a DerefOp subtree. We have two cases to consider here. 
        /// We call RewriteDerefOp to return a subtree (and an optional outputVar). 
        /// If the outputVar is null, then we simply return the subtree produced by those calls. 
        /// Otherwise, we add the subtree to the "parent" relop (to be outer-applied), and then use the outputVar
        /// in its place. 
        /// 
        /// As an example, 
        ///    select deref(e) from T
        /// gets rewritten into
        ///    select v from T OuterApply X
        /// where X is the subtree returned from the RewriteXXX calls, and "v" is the output var produced by X
        /// 
        /// </summary>
        /// <param name="op">the derefOp</param>
        /// <param name="n">the deref subtree</param>
        /// <returns>the rewritten tree</returns>
        public override Node Visit(DerefOp op, Node n)
        {
            Var outputVar;

            VisitScalarOpDefault(op, n);

            var ret = RewriteDerefOp(n, op, out outputVar);
            ret = VisitNode(ret);

            if (outputVar != null)
            {
                ret = AddSubqueryToParentRelOp(outputVar, ret);
            }

            return ret;
        }
 public override void Visit(DerefOp op, Node n)
 {
     VisitScalarOpDefault(op, n);
     Assert(TypeSemantics.IsEntityType(op.Type), "Expected an entity type. Found " + op.Type);
     Assert(TypeSemantics.IsReferenceType(n.Child0.Op.Type), "Expected a ref type. Found " + n.Child0.Op.Type);
     var r = n.Child0.Op.Type.EdmType as RefType;
     Assert(r.ElementType.EdmEquals(op.Type.EdmType), "Inconsistent types");
 }
Beispiel #5
0
 /// <summary>
 /// Copies a DerefOp
 /// </summary>
 /// <param name="op">the derefOp to copy</param>
 /// <param name="n">the subtree</param>
 /// <returns>a copy of the subtree</returns>
 public override Node Visit(DerefOp op, Node n)
 {
     return(CopyDefault(m_destCmd.CreateDerefOp(op.Type), n));
 }
 public virtual void Visit(DerefOp op, Node n)
 {
     VisitScalarOpDefault(op, n);
 }
Beispiel #7
0
 // <summary>
 // Copies a DerefOp
 // </summary>
 // <param name="op"> the derefOp to copy </param>
 // <param name="n"> the subtree </param>
 // <returns> a copy of the subtree </returns>
 public override Node Visit(DerefOp op, Node n)
 {
     return CopyDefault(m_destCmd.CreateDerefOp(op.Type), n);
 }