/// <summary> /// Helps flatten out a computedVar expression /// </summary> /// <param name="v">The Var</param> /// <param name="node">Subtree rooted at the VarDefOp expression</param> /// <param name="newNodes">list of new nodes produced</param> /// <param name="newType"></param> /// <returns>VarInfo for this var</returns> private void FlattenComputedVar(ComputedVar v, Node node, out List<Node> newNodes, out md.TypeUsage newType) { newNodes = new List<Node>(); Node definingExprNode = node.Child0; // defining expression for the VarDefOp newType = null; if (TypeUtils.IsCollectionType(v.Type)) { PlanCompiler.Assert(definingExprNode.Op.OpType != OpType.Function, "Flattening of TVF output is not allowed."); newType = GetNewType(v.Type); Var newVar; Node newVarDefNode = m_command.CreateVarDefNode(definingExprNode, out newVar); newNodes.Add(newVarDefNode); m_varInfoMap.CreateCollectionVarInfo(v, newVar); return; } // Get the "new" type for the Var TypeInfo typeInfo = m_typeInfo.GetTypeInfo(v.Type); // Get a list of properties that we think are necessary PropertyRefList desiredProperties = m_varPropertyMap[v]; List<Var> newVars = new List<Var>(); List<md.EdmProperty> newProps = new List<md.EdmProperty>(); newNodes = new List<Node>(); var hasNullSentinelVar = false; foreach (PropertyRef p in typeInfo.PropertyRefList) { // do I care for this property? if (!desiredProperties.Contains(p)) { continue; } md.EdmProperty newProperty = typeInfo.GetNewProperty(p); // // #479467 - Make sure that we build Vars for all properties - if // we are asked to produce all properties. This is extremely important // for the top-level Vars // Node propAccessor = null; if (desiredProperties.AllProperties) { propAccessor = BuildAccessorWithNulls(definingExprNode, newProperty); } else { propAccessor = BuildAccessor(definingExprNode, newProperty); if (propAccessor == null) { continue; } } // Add the new property newProps.Add(newProperty); // Create a new VarDefOp. Var newVar; Node newVarDefNode = m_command.CreateVarDefNode(propAccessor, out newVar); newNodes.Add(newVarDefNode); newVars.Add(newVar); // Check if it is a null sentinel var if (!hasNullSentinelVar && IsNullSentinelPropertyRef(p)) { hasNullSentinelVar = true; } } m_varInfoMap.CreateStructuredVarInfo(v, typeInfo.FlattenedType, newVars, newProps, hasNullSentinelVar); return; }
/// <summary> /// Creates a computed var (ie) a variable that is computed by an expression /// </summary> /// <param name="type">The type of the result produced by the expression that defines the variable</param> /// <returns>A new ComputedVar instance with the specified result type</returns> internal ComputedVar CreateComputedVar(TypeUsage type) { ComputedVar v = new ComputedVar(NewVarId(), type); m_vars.Add(v); return v; }