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"); }
/// <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); }
// <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); }