/// <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;
        }
示例#2
0
 /// <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;
 }