/// <summary>
 ///     Create a new VarInfo for a structured type Var
 /// </summary>
 /// <param name="v"> The structured type Var </param>
 /// <param name="newType"> "Mapped" type for v </param>
 /// <param name="newVars"> List of vars corresponding to v </param>
 /// <param name="newProperties"> Flattened Properties </param>
 /// <param name="newVarsIncludeNullSentinelVar"> Do the new vars include a var that represents a null sentinel either for this type or for any nested type </param>
 /// <returns> the VarInfo </returns>
 internal VarInfo CreateStructuredVarInfo(
     Var v, RowType newType, List<Var> newVars, List<EdmProperty> newProperties, bool newVarsIncludeNullSentinelVar)
 {
     VarInfo varInfo = new StructuredVarInfo(newType, newVars, newProperties, newVarsIncludeNullSentinelVar);
     m_map.Add(v, varInfo);
     return varInfo;
 }
        private readonly List<Var> m_newVars; // always a singleton list

        /// <summary>
        /// Initializes a new instance of <see cref="PrimitiveTypeVarInfo"/> class.
        /// </summary>
        /// <param name="newVar">
        /// New <see cref="Var"/> that replaces current <see cref="Var"/>.
        /// </param>
        internal PrimitiveTypeVarInfo(Var newVar)
        {
            Debug.Assert(newVar != null, "newVar != null");
            m_newVars = new List<Var>
                {
                    newVar
                };
        }
        private readonly List<Var> m_newVars; // always a singleton list

        /// <summary>
        ///     Initializes a new instance of <see cref="PrimitiveTypeVarInfo" /> class.
        /// </summary>
        /// <param name="newVar">
        ///     New <see cref="Var" /> that replaces current <see cref="Var" /> .
        /// </param>
        internal PrimitiveTypeVarInfo(Var newVar)
        {
            DebugCheck.NotNull(newVar);
            m_newVars = new List<Var>
                {
                    newVar
                };
        }
        protected Node AddSubqueryToParentRelOp(Var outputVar, Node subquery)
        {
            var ancestor = FindRelOpAncestor();
            PlanCompiler.Assert(ancestor != null, "no ancestors found?");
            AddSubqueryToRelOpNode(ancestor, subquery);

            subquery = m_command.CreateNode(m_command.CreateVarRefOp(outputVar));
            return subquery;
        }
 /// <summary>
 ///     Determines whether the given node is a VarRef over the given var
 /// </summary>
 /// <param name="node"> </param>
 /// <param name="var"> </param>
 /// <returns> </returns>
 internal static bool IsVarRefOverGivenVar(Node node, Var var)
 {
     if (node.Op.OpType
         != OpType.VarRef)
     {
         return false;
     }
     return ((VarRefOp)node.Op).Var == var;
 }
 internal CollectionInfo(
     Var collectionVar, ColumnMap columnMap, VarList flattenedElementVars, VarVec keys, List<SortKey> sortKeys,
     object discriminatorValue)
 {
     m_collectionVar = collectionVar;
     m_columnMap = columnMap;
     m_flattenedElementVars = flattenedElementVars;
     m_keys = keys;
     m_sortKeys = sortKeys;
     m_discriminatorValue = discriminatorValue;
 }
        internal VarInfo CreatePrimitiveTypeVarInfo(Var v, Var newVar)
        {
            DebugCheck.NotNull(v);
            DebugCheck.NotNull(newVar);

            PlanCompiler.Assert(TypeSemantics.IsScalarType(v.Type), "The current variable should be of primitive or enum type.");
            PlanCompiler.Assert(TypeSemantics.IsScalarType(newVar.Type), "The new variable should be of primitive or enum type.");

            VarInfo varInfo = new PrimitiveTypeVarInfo(newVar);
            m_map.Add(v, varInfo);
            return varInfo;
        }
        // <summary>
        // Add an entry that the given property of the given var is a computation represented
        // by the computationTemplate over the var represented by the given groupAggregateVarInfo
        // </summary>
        internal void Add(
            Var var, GroupAggregateVarInfo groupAggregateVarInfo, Node computationTemplate, bool isUnnested, EdmMember property)
        {
            if (property == null)
            {
                Add(var, groupAggregateVarInfo, computationTemplate, isUnnested);
                return;
            }
            if (_groupAggregateVarRelatedVarPropertyToInfo == null)
            {
                _groupAggregateVarRelatedVarPropertyToInfo = new Dictionary<Var, Dictionary<EdmMember, GroupAggregateVarRefInfo>>();
            }
            Dictionary<EdmMember, GroupAggregateVarRefInfo> varPropertyDictionary;
            if (!_groupAggregateVarRelatedVarPropertyToInfo.TryGetValue(var, out varPropertyDictionary))
            {
                varPropertyDictionary = new Dictionary<EdmMember, GroupAggregateVarRefInfo>();
                _groupAggregateVarRelatedVarPropertyToInfo.Add(var, varPropertyDictionary);
            }
            varPropertyDictionary.Add(property, new GroupAggregateVarRefInfo(groupAggregateVarInfo, computationTemplate, isUnnested));

            // Note: The following line is not necessary with the current usage pattern, this method is 
            // never called with a new groupAggregateVarInfo thus it is a no-op.
            _groupAggregateVarInfos.Add(groupAggregateVarInfo);
        }
        /// <summary>
        /// Builds up a join between the relationshipset and the entityset corresponding to its toEnd. In essence,
        /// we produce
        ///    SELECT r, e
        ///    FROM RS as r, OFTYPE(ES, T) as e
        ///    WHERE r.ToEnd = Ref(e)
        ///    
        /// "T" is the entity type of the toEnd of the relationship.  
        /// </summary>
        /// <param name="relSet">the relationshipset</param>
        /// <param name="end">the toEnd of the relationship</param>
        /// <param name="rsVar">the var representing the relationship instance ("r") in the output subquery</param>
        /// <param name="esVar">the var representing the entity instance ("e") in the output subquery</param>
        /// <returns>the join subquery described above</returns>
        private Node BuildJoinForNavProperty(
            RelationshipSet relSet, RelationshipEndMember end,
            out Var rsVar, out Var esVar)
        {
            var entitySet = FindTargetEntitySet(relSet, end);

            //
            // Build out the ScanTable ops for the relationshipset and the entityset. Add the 
            //
            var asTableNode = BuildOfTypeTable(relSet, null, out rsVar);
            var esTableNode = BuildOfTypeTable(entitySet, TypeHelpers.GetElementTypeUsage(end.TypeUsage), out esVar);

            // 
            // Build up a join between the entityset and the associationset; join on the to-end
            //
            var joinPredicate = m_command.BuildComparison(
                OpType.EQ,
                m_command.CreateNode(m_command.CreateGetEntityRefOp(end.TypeUsage), m_command.CreateNode(m_command.CreateVarRefOp(esVar))),
                m_command.CreateNode(m_command.CreatePropertyOp(end), m_command.CreateNode(m_command.CreateVarRefOp(rsVar)))
                );

            var joinNode = m_command.CreateNode(
                m_command.CreateInnerJoinOp(),
                asTableNode, esTableNode, joinPredicate);

            return joinNode;
        }
Exemple #10
0
 /// <summary>
 ///     Simple constructor
 /// </summary>
 /// <param name="type"> datatype of this Var </param>
 /// <param name="name"> the name of the column </param>
 /// <param name="v"> the var producing the value for this column </param>
 internal VarRefColumnMap(TypeUsage type, string name, Var v)
     : base(type, name)
 {
     m_var = v;
 }
        /// <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;
        }
Exemple #12
0
        // <summary>
        // Convert a SingleStreamNestOp into a massive UnionAllOp
        // </summary>
        private Node BuildUnionAllSubqueryForNestOp(
            NestBaseOp nestOp, Node nestNode, VarList drivingNodeVars, VarList discriminatorVarList, out Var discriminatorVar,
            out List<Dictionary<Var, Var>> varMapList)
        {
            var drivingNode = nestNode.Child0;

            // For each of the NESTED collections...
            Node unionAllNode = null;
            VarList unionAllOutputs = null;
            for (var i = 1; i < nestNode.Children.Count; i++)
            {
                // Ensure we only use the driving collection tree once, so other
                // transformations do not unintentionally change more than one path.
                // To prevent nodes in the tree from being used in multiple paths,
                // we copy the driving input on successive nodes.
                VarList newDrivingNodeVars;
                Node newDrivingNode;
                VarList newFlattenedElementVars;
                Op op;

                if (i > 1)
                {
                    newDrivingNode = OpCopier.Copy(Command, drivingNode, drivingNodeVars, out newDrivingNodeVars);
                    // 
                    // Bug 450245: If we copied the driver node, then references to driver node vars
                    // from the collection subquery must be patched up
                    //
                    var varRemapper = new VarRemapper(Command);
                    for (var j = 0; j < drivingNodeVars.Count; j++)
                    {
                        varRemapper.AddMapping(drivingNodeVars[j], newDrivingNodeVars[j]);
                    }
                    // Remap all references in the current subquery
                    varRemapper.RemapSubtree(nestNode.Children[i]);

                    // Bug 479183: Remap the flattened element vars
                    newFlattenedElementVars = varRemapper.RemapVarList(nestOp.CollectionInfo[i - 1].FlattenedElementVars);

                    // Create a cross apply for all but the first collection
                    op = Command.CreateCrossApplyOp();
                }
                else
                {
                    newDrivingNode = drivingNode;
                    newDrivingNodeVars = drivingNodeVars;
                    newFlattenedElementVars = nestOp.CollectionInfo[i - 1].FlattenedElementVars;

                    // Create an outer apply for the first collection, 
                    // that way we ensure at least one row for each row in the driver node.
                    op = Command.CreateOuterApplyOp();
                }

                // Create an outer apply with the driver node and the nested collection.
                var applyNode = Command.CreateNode(op, newDrivingNode, nestNode.Children[i]);

                // Now create a ProjectOp that augments the output from the OuterApplyOp
                // with nulls for each column from other collections

                // Build the VarDefList (the list of vars) for the Project, starting
                // with the collection discriminator var
                var varDefListChildren = new List<Node>();
                var projectOutputs = Command.CreateVarList();

                // Add the collection discriminator var to the output.
                projectOutputs.Add(discriminatorVarList[i]);

                // Add all columns from the driving node
                projectOutputs.AddRange(newDrivingNodeVars);

                // Add all the vars from all the nested collections;
                for (var j = 1; j < nestNode.Children.Count; j++)
                {
                    var otherCollectionInfo = nestOp.CollectionInfo[j - 1];
                    // For the current nested collection, we just pick the var that's
                    // coming from there and don't need have a new var defined, but for
                    // the rest we construct null values.
                    if (i == j)
                    {
                        projectOutputs.AddRange(newFlattenedElementVars);
                    }
                    else
                    {
                        foreach (var v in otherCollectionInfo.FlattenedElementVars)
                        {
                            var nullOp = Command.CreateNullOp(v.Type);
                            var nullOpNode = Command.CreateNode(nullOp);
                            Var nullOpVar;
                            var nullOpVarDefNode = Command.CreateVarDefNode(nullOpNode, out nullOpVar);
                            varDefListChildren.Add(nullOpVarDefNode);
                            projectOutputs.Add(nullOpVar);
                        }
                    }
                }

                var varDefListNode = Command.CreateNode(Command.CreateVarDefListOp(), varDefListChildren);

                // Now, build up the projectOp
                var projectOutputsVarSet = Command.CreateVarVec(projectOutputs);
                var projectOp = Command.CreateProjectOp(projectOutputsVarSet);
                var projectNode = Command.CreateNode(projectOp, applyNode, varDefListNode);

                // finally, build the union all
                if (unionAllNode == null)
                {
                    unionAllNode = projectNode;
                    unionAllOutputs = projectOutputs;
                }
                else
                {
                    var unionAllMap = new VarMap();
                    var projectMap = new VarMap();
                    for (var idx = 0; idx < unionAllOutputs.Count; idx++)
                    {
                        Var outputVar = Command.CreateSetOpVar(unionAllOutputs[idx].Type);
                        unionAllMap.Add(outputVar, unionAllOutputs[idx]);
                        projectMap.Add(outputVar, projectOutputs[idx]);
                    }
                    var unionAllOp = Command.CreateUnionAllOp(unionAllMap, projectMap);
                    unionAllNode = Command.CreateNode(unionAllOp, unionAllNode, projectNode);

                    // Get the output vars from the union-op. This must be in the same order
                    // as the original list of Vars
                    unionAllOutputs = GetUnionOutputs(unionAllOp, unionAllOutputs);
                }
            }

            // We're done building the node, but now we have to build a mapping from
            // the before-Vars to the after-Vars
            varMapList = new List<Dictionary<Var, Var>>();
            IEnumerator<Var> outputVarsEnumerator = unionAllOutputs.GetEnumerator();
            if (!outputVarsEnumerator.MoveNext())
            {
                throw EntityUtil.InternalError(EntityUtil.InternalErrorCode.ColumnCountMismatch, 4, null);
                // more columns from children than are on the unionAll?
            }
            // The discriminator var is always first
            discriminatorVar = outputVarsEnumerator.Current;

            // Build a map for each input
            for (var i = 0; i < nestNode.Children.Count; i++)
            {
                var varMap = new Dictionary<Var, Var>();
                var varList = (i == 0) ? drivingNodeVars : nestOp.CollectionInfo[i - 1].FlattenedElementVars;
                foreach (var v in varList)
                {
                    if (!outputVarsEnumerator.MoveNext())
                    {
                        throw EntityUtil.InternalError(EntityUtil.InternalErrorCode.ColumnCountMismatch, 5, null);
                        // more columns from children than are on the unionAll?
                    }
                    varMap[v] = outputVarsEnumerator.Current;
                }
                varMapList.Add(varMap);
            }
            if (outputVarsEnumerator.MoveNext())
            {
                throw EntityUtil.InternalError(EntityUtil.InternalErrorCode.ColumnCountMismatch, 6, null);
                // at this point, we better be done with both lists...
            }

            return unionAllNode;
        }
Exemple #13
0
        // <summary>
        // Input =>  Filter(input, Ref(var) is not null)
        // </summary>
        private Node CapWithIsNotNullFilter(Node input, Var var)
        {
            var varRefNode = Command.CreateNode(Command.CreateVarRefOp(var));
            var predicateNode = Command.CreateNode(
                Command.CreateConditionalOp(OpType.Not),
                Command.CreateNode(
                    Command.CreateConditionalOp(OpType.IsNull),
                    varRefNode));

            var filterNode = Command.CreateNode(Command.CreateFilterOp(), input, predicateNode);
            return filterNode;
        }
Exemple #14
0
        // <summary>
        // Convert a CollectOp subtree (when used as the defining expression for a
        // VarDefOp) into a reasonable input to a NestOp.
        // </summary>
        // <remarks>
        // There are a couple of cases that we handle here:
        // (a) PhysicalProject(X) ==> X
        // (b) PhysicalProject(Sort(X)) ==> Sort(X)
        // </remarks>
        // <param name="physicalProjectNode"> the child of the CollectOp </param>
        // <param name="collectionVar"> the collectionVar being defined </param>
        // <param name="collectionInfoList"> where to append the new collectionInfo </param>
        // <param name="collectionNodes"> where to append the collectionNode </param>
        // <param name="externalReferences"> a bit vector of external references of the physicalProject </param>
        // <param name="collectionReferences"> a bit vector of collection vars </param>
        private void ConvertToNestOpInput(
            Node physicalProjectNode, Var collectionVar, List<CollectionInfo> collectionInfoList, List<Node> collectionNodes,
            VarVec externalReferences, VarVec collectionReferences)
        {
            // Keep track of any external references the physicalProjectOp has
            externalReferences.Or(Command.GetNodeInfo(physicalProjectNode).ExternalReferences);

            // Case: (a) PhysicalProject(X) ==> X
            var nestOpInput = physicalProjectNode.Child0;

            // Now build the collectionInfo for this input, including the flattened
            // list of vars, which is essentially the outputs from the physicalProject
            // with the sortKey vars that aren't already in the outputs we already 
            // have.
            var physicalProjectOp = (PhysicalProjectOp)physicalProjectNode.Op;
            var flattenedElementVarList = Command.CreateVarList(physicalProjectOp.Outputs);
            var flattenedElementVarVec = Command.CreateVarVec(flattenedElementVarList); // Use a VarVec to make the lookups faster
            List<SortKey> sortKeys = null;

            if (OpType.Sort
                == nestOpInput.Op.OpType)
            {
                // Case: (b) PhysicalProject(Sort(X)) ==> Sort(X)
                var sortOp = (SortOp)nestOpInput.Op;
                sortKeys = OpCopier.Copy(Command, sortOp.Keys);

                foreach (var sk in sortKeys)
                {
                    if (!flattenedElementVarVec.IsSet(sk.Var))
                    {
                        flattenedElementVarList.Add(sk.Var);
                        flattenedElementVarVec.Set(sk.Var);
                    }
                }
            }
            else
            {
                sortKeys = new List<SortKey>();
            }

            // Get the keys for the collection
            var keyVars = Command.GetExtendedNodeInfo(nestOpInput).Keys.KeyVars;

            //Check whether all key are projected
            var keyVarsClone = keyVars.Clone();
            keyVarsClone.Minus(flattenedElementVarVec);

            var keys = (keyVarsClone.IsEmpty) ? keyVars.Clone() : Command.CreateVarVec();

            // Create the collectionInfo
            var collectionInfo = Command.CreateCollectionInfo(
                collectionVar, physicalProjectOp.ColumnMap.Element, flattenedElementVarList, keys, sortKeys, null /*discriminatorValue*/);

            // Now update the collections we're tracking.
            collectionInfoList.Add(collectionInfo);
            collectionNodes.Add(nestOpInput);
            collectionReferences.Set(collectionVar);
        }
Exemple #15
0
 // <summary>
 // 'Extend' a given input node to also project out an internal integer constant with the given value
 // </summary>
 private Node AugmentNodeWithInternalIntegerConstant(Node input, int value, out Var internalConstantVar)
 {
     return AugmentNodeWithConstant(
         input, () => Command.CreateInternalConstantOp(Command.IntegerType, value), out internalConstantVar);
 }
 /// <summary>
 ///     Given a list of vars try to get one that is of type Int32
 /// </summary>
 /// <param name="varList"> </param>
 /// <param name="int32Var"> </param>
 /// <returns> </returns>
 internal static bool TryGetInt32Var(IEnumerable<Var> varList, out Var int32Var)
 {
     foreach (var v in varList)
     {
         // Any Int32 var regardless of the fasets will do
         PrimitiveTypeKind typeKind;
         if (TypeHelpers.TryGetPrimitiveTypeKind(v.Type, out typeKind)
             && typeKind == PrimitiveTypeKind.Int32)
         {
             int32Var = v;
             return true;
         }
     }
     int32Var = null;
     return false;
 }
 /// <summary>
 ///     Is the given var guaranteed to be non-nullable with regards to the node
 ///     that is currently being processed.
 ///     True, if it is listed as such on any on the node infos on any of the
 ///     current relop ancestors.
 /// </summary>
 /// <param name="var"> </param>
 /// <returns> </returns>
 internal bool IsNonNullable(Var var)
 {
     foreach (var relOpAncestor in m_relOpAncestors)
     {
         // Rules applied to the children of the relOpAncestor may have caused it change. 
         // Thus, if the node is used, it has to have its node info recomputed
         Command.RecomputeNodeInfo(relOpAncestor);
         var nodeInfo = Command.GetExtendedNodeInfo(relOpAncestor);
         if (nodeInfo.NonNullableVisibleDefinitions.IsSet(var))
         {
             return true;
         }
         else if (nodeInfo.LocalDefinitions.IsSet(var))
         {
             //The var is defined on this ancestor but is not non-nullable,
             // therefore there is no need to further check other ancestors
             return false;
         }
     }
     return false;
 }
        private Node RewriteFromOneNavigationProperty(
            RelProperty relProperty, List<RelationshipSet> relationshipSets, Node sourceRefNode, out Var outputVar)
        {
            PlanCompiler.Assert(relationshipSets.Count > 0, "expected at least one relationship set here");
            PlanCompiler.Assert(
                relProperty.FromEnd.RelationshipMultiplicity != RelationshipMultiplicity.Many,
                "Expected source end multiplicity to be one. Found 'Many' instead " + relProperty);

            var entityType = TypeHelpers.GetElementTypeUsage(relProperty.ToEnd.TypeUsage);
            var scanTableNodes = new List<Node>(relationshipSets.Count);
            var scanTableVars = new List<Var>(relationshipSets.Count);
            foreach (var r in relationshipSets)
            {
                var entitySet = FindTargetEntitySet(r, relProperty.ToEnd);
                Var tableVar;
                var tableNode = BuildOfTypeTable(entitySet, entityType, out tableVar);

                scanTableNodes.Add(tableNode);
                scanTableVars.Add(tableVar);
            }

            // 
            // Build the union-all node
            //
            Node unionAllNode;

            m_command.BuildUnionAllLadder(scanTableNodes, scanTableVars, out unionAllNode, out outputVar);

            //
            // Now build up the appropriate filter. Select out the relproperty from the other end
            //
            var inverseRelProperty = new RelProperty(relProperty.Relationship, relProperty.ToEnd, relProperty.FromEnd);
            PlanCompiler.Assert(
                m_command.IsRelPropertyReferenced(inverseRelProperty),
                "Unreferenced rel property? " + inverseRelProperty);
            var inverseRelPropertyNode = m_command.CreateNode(
                m_command.CreateRelPropertyOp(inverseRelProperty),
                m_command.CreateNode(m_command.CreateVarRefOp(outputVar)));
            var predicateNode = m_command.BuildComparison(
                OpType.EQ,
                sourceRefNode, inverseRelPropertyNode);
            var ret = m_command.CreateNode(m_command.CreateFilterOp(), unionAllNode, predicateNode);

            return ret;
        }
Exemple #19
0
 internal VarRefColumnMap(Var v)
     : this(v.Type, null, v)
 {
 }
 internal UnionAllOp(VarVec outputs, VarMap left, VarMap right, Var branchDiscriminator)
     : base(OpType.UnionAll, outputs, left, right)
 {
     m_branchDiscriminator = branchDiscriminator;
 }
        private readonly List<Var> m_newVars; // always a singleton list

        /// <summary>
        ///     Create a CollectionVarInfo
        /// </summary>
        internal CollectionVarInfo(Var newVar)
        {
            m_newVars = new List<Var>();
            m_newVars.Add(newVar);
        }
 // <summary>
 // Gets the groupAggregateVarRefInfo representing the definition of the given var over
 // a group aggregate var if any.
 // </summary>
 internal bool TryGetReferencedGroupAggregateVarInfo(Var var, out GroupAggregateVarRefInfo groupAggregateVarRefInfo)
 {
     return _groupAggregateVarRelatedVarToInfo.TryGetValue(var, out groupAggregateVarRefInfo);
 }
        /// <summary>
        ///     Builds a NULLIF expression (ie) a Case expression that looks like
        ///     CASE WHEN v is null THEN null ELSE expr END
        ///     where v is the conditionVar parameter, and expr is the value of the expression
        ///     when v is non-null
        /// </summary>
        /// <param name="conditionVar"> null discriminator var </param>
        /// <param name="expr"> expression </param>
        /// <returns> </returns>
        internal Node BuildNullIfExpression(Var conditionVar, Node expr)
        {
            var varRefOp = Command.CreateVarRefOp(conditionVar);
            var varRefNode = Command.CreateNode(varRefOp);
            var whenNode = Command.CreateNode(Command.CreateConditionalOp(OpType.IsNull), varRefNode);
            var elseNode = expr;
            var thenNode = Command.CreateNode(Command.CreateNullOp(elseNode.Op.Type));
            var caseNode = Command.CreateNode(Command.CreateCaseOp(elseNode.Op.Type), whenNode, thenNode, elseNode);

            return caseNode;
        }
        // <summary>
        // Gets the groupAggregateVarRefInfo representing the definition of the given property of the given
        // var over a group aggregate var if any.
        // </summary>
        internal bool TryGetReferencedGroupAggregateVarInfo(
            Var var, EdmMember property, out GroupAggregateVarRefInfo groupAggregateVarRefInfo)
        {
            if (property == null)
            {
                return TryGetReferencedGroupAggregateVarInfo(var, out groupAggregateVarRefInfo);
            }

            Dictionary<EdmMember, GroupAggregateVarRefInfo> varPropertyDictionary;
            if (_groupAggregateVarRelatedVarPropertyToInfo == null
                || !_groupAggregateVarRelatedVarPropertyToInfo.TryGetValue(var, out varPropertyDictionary))
            {
                groupAggregateVarRefInfo = null;
                return false;
            }
            return varPropertyDictionary.TryGetValue(property, out groupAggregateVarRefInfo);
        }
 /// <summary>
 ///     Adds a mapping from oldVar to newVar
 /// </summary>
 /// <param name="oldVar"> </param>
 /// <param name="newVar"> </param>
 internal void AddVarMapping(Var oldVar, Var newVar)
 {
     m_remapper.AddMapping(oldVar, newVar);
     m_remappedVars.Set(oldVar);
 }
 /// <summary>
 ///     Get the list of desired properties for a Var
 /// </summary>
 /// <param name="v"> the var </param>
 /// <returns> List of desired properties </returns>
 private PropertyRefList GetPropertyRefList(Var v)
 {
     PropertyRefList propRefs;
     if (!m_varPropertyRefMap.TryGetValue(v, out propRefs))
     {
         propRefs = new PropertyRefList();
         m_varPropertyRefMap[v] = propRefs;
     }
     return propRefs;
 }
Exemple #27
0
 // <summary>
 // Follow the VarRef chain to the defining var
 // </summary>
 private Var ResolveVarReference(Var refVar)
 {
     var x = refVar;
     while (m_varRefMap.TryGetValue(x, out x))
     {
         refVar = x;
     }
     return refVar;
 }
 /// <summary>
 ///     Add a new set of properties to a Var
 /// </summary>
 /// <param name="v"> the var </param>
 /// <param name="propertyRefs"> desired properties </param>
 private void AddPropertyRefs(Var v, PropertyRefList propertyRefs)
 {
     var currentRefs = GetPropertyRefList(v);
     currentRefs.Append(propertyRefs);
 }
Exemple #29
0
        // <summary>
        // Add a constant to a node. Specifically:
        // N ==> Project(N,{definitions-from-N, constant})
        // </summary>
        // <param name="input"> the input node to augment </param>
        // <param name="createOp"> The fucntion to create the constant op </param>
        // <param name="constantVar"> the computed Var for the internal constant </param>
        // <returns> the augmented node </returns>
        private Node AugmentNodeWithConstant(Node input, Func<ConstantBaseOp> createOp, out Var constantVar)
        {
            // Construct the op for the constant value and 
            // a VarDef node that that defines it.
            var constantOp = createOp();
            var constantNode = Command.CreateNode(constantOp);
            var varDefListNode = Command.CreateVarDefListNode(constantNode, out constantVar);

            // Now identify the list of definitions from the input, and project out
            // every one of them and include the constantVar
            var inputNodeInfo = Command.GetExtendedNodeInfo(input);
            var projectOutputs = Command.CreateVarVec(inputNodeInfo.Definitions);
            projectOutputs.Set(constantVar);

            var projectOp = Command.CreateProjectOp(projectOutputs);
            var projectNode = Command.CreateNode(projectOp, input, varDefListNode);

            return projectNode;
        }
        private Node RewriteNavigateOp(Node navigateOpNode, NavigateOp navigateOp, out Var outputVar)
        {
            outputVar = null;

            //
            // Currently, navigation of composition relationships is not supported.
            //
            if (!Helper.IsAssociationType(navigateOp.Relationship))
            {
                throw new NotSupportedException(Strings.Cqt_RelNav_NoCompositions);
            }

            //
            // If the input to the navigateOp is a GetEntityRefOp, and the navigation
            // is to the 1-end of the relationship, convert this into a RelPropertyOp instead - operating on the
            // input child to the GetEntityRefOp
            //
            if (navigateOpNode.Child0.Op.OpType == OpType.GetEntityRef
                &&
                (navigateOp.ToEnd.RelationshipMultiplicity == RelationshipMultiplicity.ZeroOrOne ||
                 navigateOp.ToEnd.RelationshipMultiplicity == RelationshipMultiplicity.One))
            {
                PlanCompiler.Assert(
                    m_command.IsRelPropertyReferenced(navigateOp.RelProperty),
                    "Unreferenced rel property? " + navigateOp.RelProperty);
                Op relPropertyOp = m_command.CreateRelPropertyOp(navigateOp.RelProperty);
                var relPropertyNode = m_command.CreateNode(
                    relPropertyOp,
                    navigateOpNode.Child0.Child0);
                return relPropertyNode;
            }

            var relationshipSets = GetRelationshipSets(navigateOp.Relationship);

            //
            // Special case: when no relationshipsets can be found. Return NULL or an empty multiset,
            //   depending on the multiplicity of the toEnd
            //
            if (relationshipSets.Count == 0)
            {
                // 
                // If we're navigating to the 1-end of the relationship, then simply return a null constant
                //
                if (navigateOp.ToEnd.RelationshipMultiplicity
                    != RelationshipMultiplicity.Many)
                {
                    return m_command.CreateNode(m_command.CreateNullOp(navigateOp.Type));
                }
                else // return an empty set
                {
                    return m_command.CreateNode(m_command.CreateNewMultisetOp(navigateOp.Type));
                }
            }

            //
            // Build up a UNION-ALL ladder over all the relationshipsets
            // 
            var scanTableNodes = new List<Node>();
            var scanTableVars = new List<Var>();
            foreach (var relSet in relationshipSets)
            {
                var tableMD = Command.CreateTableDefinition(relSet);
                var tableOp = m_command.CreateScanTableOp(tableMD);
                var branchNode = m_command.CreateNode(tableOp);
                var branchVar = tableOp.Table.Columns[0];
                scanTableVars.Add(branchVar);
                scanTableNodes.Add(branchNode);
            }

            Node unionAllNode = null;
            Var unionAllVar;
            m_command.BuildUnionAllLadder(scanTableNodes, scanTableVars, out unionAllNode, out unionAllVar);

            //
            // Now build up the predicate
            //
            var targetEnd = m_command.CreateNode(
                m_command.CreatePropertyOp(navigateOp.ToEnd),
                m_command.CreateNode(m_command.CreateVarRefOp(unionAllVar)));
            var sourceEnd = m_command.CreateNode(
                m_command.CreatePropertyOp(navigateOp.FromEnd),
                m_command.CreateNode(m_command.CreateVarRefOp(unionAllVar)));
            var predicateNode = m_command.BuildComparison(OpType.EQ, navigateOpNode.Child0, sourceEnd);
            var filterNode = m_command.CreateNode(
                m_command.CreateFilterOp(),
                unionAllNode, predicateNode);
            Var projectVar;
            var projectNode = m_command.BuildProject(filterNode, targetEnd, out projectVar);

            //
            // Finally, some magic about single-valued vs collection-valued ends
            //
            Node ret;
            if (navigateOp.ToEnd.RelationshipMultiplicity
                == RelationshipMultiplicity.Many)
            {
                ret = m_command.BuildCollect(projectNode, projectVar);
            }
            else
            {
                ret = projectNode;
                outputVar = projectVar;
            }

            return ret;
        }
Exemple #31
0
        // <summary>
        // Applies a IsNotNull(sentinelVar) filter to the given node.
        // The filter is pushed below all MultiStremNest-s, because this part of the tree has
        // already been visited and it is expected that the MultiStreamNests have bubbled up
        // above the filters.
        // </summary>
        private Node ApplyIsNotNullFilter(Node node, Var sentinelVar)
        {
            var newFilterChild = node;
            Node newFilterParent = null;
            while (newFilterChild.Op.OpType
                   == OpType.MultiStreamNest)
            {
                newFilterParent = newFilterChild;
                newFilterChild = newFilterChild.Child0;
            }

            var newFilterNode = CapWithIsNotNullFilter(newFilterChild, sentinelVar);
            Node result;

            if (newFilterParent != null)
            {
                newFilterParent.Child0 = newFilterNode;
                result = node;
            }
            else
            {
                result = newFilterNode;
            }
            return result;
        }
        /// <summary>
        /// Build up a node tree that represents the set of instances from the given table that are at least
        /// of the specified type ("ofType"). If "ofType" is NULL, then all rows are returned
        /// 
        /// Return the outputVar from the nodetree
        /// </summary>
        /// <param name="entitySet">the entityset or relationshipset to scan over</param>
        /// <param name="ofType">the element types we're interested in</param>
        /// <param name="resultVar">the output var produced by this node tree</param>
        /// <returns>the node tree</returns>
        private Node BuildOfTypeTable(EntitySetBase entitySet, TypeUsage ofType, out Var resultVar)
        {
            var tableMetadata = Command.CreateTableDefinition(entitySet);
            var tableOp = m_command.CreateScanTableOp(tableMetadata);
            var tableNode = m_command.CreateNode(tableOp);
            var tableVar = tableOp.Table.Columns[0];

            Node resultNode;
            // 
            // Build a logical "oftype" expression - simply a filter predicate
            //
            if ((ofType != null)
                && !entitySet.ElementType.EdmEquals(ofType.EdmType))
            {
                m_command.BuildOfTypeTree(tableNode, tableVar, ofType, true, out resultNode, out resultVar);
            }
            else
            {
                resultNode = tableNode;
                resultVar = tableVar;
            }

            return resultNode;
        }
 // <summary>
 // Get the Var corresponding to a specific property
 // </summary>
 // <param name="p"> the requested property </param>
 // <param name="v"> the corresponding Var </param>
 // <returns> true, if the Var was found </returns>
 internal bool TryGetVar(EdmProperty p, out Var v)
 {
     if (m_propertyToVarMap == null)
     {
         InitPropertyToVarMap();
     }
     return m_propertyToVarMap.TryGetValue(p, out v);
 }
Exemple #34
0
 internal UnnestOp(Var v, Table t)
     : this()
 {
     m_var   = v;
     m_table = t;
 }