/// <summary>
        /// The driver routine.
        /// </summary>
        /// <param name="planCompilerState">plan compiler state</param>
        /// <param name="typeInfo">type information about all types/sets referenced in the query</param>
        /// <param name="tvfResultKeys">inferred key columns of tvfs return types</param>
        internal static void Process(
            PlanCompiler planCompilerState,
            out StructuredTypeInfo typeInfo,
            out Dictionary<EdmFunction, EdmProperty[]> tvfResultKeys)
        {
            var preProcessor = new PreProcessor(planCompilerState);
            preProcessor.Process(out tvfResultKeys);

            StructuredTypeInfo.Process(
                planCompilerState.Command,
                preProcessor.m_referencedTypes,
                preProcessor.m_referencedEntitySets,
                preProcessor.m_freeFloatingEntityConstructorTypes,
                preProcessor.m_suppressDiscriminatorMaps ? null : preProcessor.m_discriminatorMaps,
                preProcessor.m_relPropertyHelper,
                preProcessor.m_typesNeedingNullSentinel,
                out typeInfo);
        }
 internal static void Validate(PlanCompiler compilerState, Node n)
 {
     var validator = new Validator(compilerState);
     validator.Validate(n);
 }
 private PreProcessor(PlanCompiler planCompilerState)
     : base(planCompilerState)
 {
     m_relPropertyHelper = new RelPropertyHelper(m_command.MetadataWorkspace, m_command.ReferencedRelProperties);
 }
Example #4
0
 internal static void Compile(
     cqt.DbCommandTree ctree, out List<ProviderCommandInfo> providerCommands, out ColumnMap resultColumnMap, out int columnCount,
     out Set<md.EntitySet> entitySets)
 {
     Assert(ctree != null, "Expected a valid, non-null Command Tree input");
     var pc = new PlanCompiler(ctree);
     pc.Compile(out providerCommands, out resultColumnMap, out columnCount, out entitySets);
 }
        // <summary>
        // Apply the rules that belong to the specified group to the given query tree.
        // </summary>
        internal static bool Process(PlanCompiler compilerState, TransformationRulesGroup rulesGroup)
        {
            ReadOnlyCollection<ReadOnlyCollection<Rule>> rulesTable = null;
            switch (rulesGroup)
            {
                case TransformationRulesGroup.All:
                    rulesTable = AllRulesTable;
                    break;
                case TransformationRulesGroup.PostJoinElimination:
                    rulesTable = PostJoinEliminationRulesTable;
                    break;
                case TransformationRulesGroup.Project:
                    rulesTable = ProjectRulesTable;
                    break;
                case TransformationRulesGroup.NullSemantics:
                    rulesTable = NullSemanticsRulesTable;
                    break;
            }

            // If any rule has been applied after which reapplying nullability rules may be useful,
            // reapply nullability rules.
            bool projectionPrunningRequired;
            if (Process(compilerState, rulesTable, out projectionPrunningRequired))
            {
                bool projectionPrunningRequired2;
                Process(compilerState, NullabilityRulesTable, out projectionPrunningRequired2);
                projectionPrunningRequired = projectionPrunningRequired || projectionPrunningRequired2;
            }
            return projectionPrunningRequired;
        }
        /// <summary>
        ///     Apply Aggregate Pushdown over the tree in the given plan complier state.
        /// </summary>
        internal static void Process(PlanCompiler planCompilerState)
        {
            var aggregatePushdown = new AggregatePushdown(planCompilerState.Command);

            aggregatePushdown.Process();
        }
Example #7
0
 /// <summary>
 /// This involves 
 ///   * Converting the ITree into a set of ProviderCommandInfo objects
 ///   * Creating a column map to enable result assembly
 /// Currently, we only produce a single ITree, and correspondingly, the 
 /// following steps are trivial
 /// </summary>
 /// <param name="compilerState">current compiler state</param>
 /// <param name="childCommands">CQTs for each store command</param>
 /// <param name="resultColumnMap">column map to help in result assembly</param>
 internal static void Process(
     PlanCompiler compilerState, out List<ProviderCommandInfo> childCommands, out ColumnMap resultColumnMap, out int columnCount)
 {
     var codeGen = new CodeGen(compilerState);
     codeGen.Process(out childCommands, out resultColumnMap, out columnCount);
 }
Example #8
0
 private NestPullup(PlanCompiler compilerState)
 {
     m_compilerState = compilerState;
     m_varRemapper = new VarRemapper(compilerState.Command);
 }
 internal NestedPropertyRef(PropertyRef innerProperty, PropertyRef outerProperty)
 {
     PlanCompiler.Assert(!(innerProperty is NestedPropertyRef), "innerProperty cannot be a NestedPropertyRef");
     m_inner = innerProperty;
     m_outer = outerProperty;
 }
Example #10
0
        private void CreateFlattenedRecordType(RootTypeInfo type)
        {
            //
            // If this type corresponds to an entity type, and that entity type
            // has no subtypes, and that that entity type has no complex properties
            // then simply use the name from that property
            //
            bool usePropertyNamesFromUnderlyingType;

            if (md.TypeSemantics.IsEntityType(type.Type)
                &&
                type.ImmediateSubTypes.Count == 0)
            {
                usePropertyNamesFromUnderlyingType = true;
            }
            else
            {
                usePropertyNamesFromUnderlyingType = false;
            }

            // Build the record type
            var fieldList   = new List <KeyValuePair <string, md.TypeUsage> >();
            var fieldNames  = new HashSet <string>();
            var nextFieldId = 0;

            foreach (var p in type.PropertyRefList)
            {
                string fieldName = null;
                if (usePropertyNamesFromUnderlyingType)
                {
                    var simpleP = p as SimplePropertyRef;
                    if (simpleP != null)
                    {
                        fieldName = simpleP.Property.Name;
                    }
                }

                if (fieldName == null)
                {
                    fieldName = "F" + nextFieldId.ToString(CultureInfo.InvariantCulture);
                    nextFieldId++;
                }

                // Deal with collisions
                while (fieldNames.Contains(fieldName))
                {
                    fieldName = "F" + nextFieldId.ToString(CultureInfo.InvariantCulture);
                    nextFieldId++;
                }

                var propertyType = GetPropertyType(type, p);
                fieldList.Add(new KeyValuePair <string, md.TypeUsage>(fieldName, propertyType));
                fieldNames.Add(fieldName);
            }

            type.FlattenedType = TypeHelpers.CreateRowType(fieldList);

            // Now build up the property map
            var origProps = type.PropertyRefList.GetEnumerator();

            foreach (var p in type.FlattenedType.Properties)
            {
                if (!origProps.MoveNext())
                {
                    PlanCompiler.Assert(false, "property refs count and flattened type member count mismatch?");
                }
                type.AddPropertyMapping(origProps.Current, p);
            }
        }
Example #11
0
        private TypeInfo CreateTypeInfoForStructuredType(md.TypeUsage type, ExplicitDiscriminatorMap discriminatorMap)
        {
            TypeInfo typeInfo;

            PlanCompiler.Assert(TypeUtils.IsStructuredType(type), "expected structured type. Found " + type);

            // Return existing entry, if one is available
            typeInfo = GetTypeInfo(type);
            if (typeInfo != null)
            {
                return(typeInfo);
            }

            // Ensure that my supertype has been added to the map.
            TypeInfo superTypeInfo = null;

            md.RefType refType;
            if (type.EdmType.BaseType != null)
            {
                superTypeInfo = CreateTypeInfoForStructuredType(md.TypeUsage.Create(type.EdmType.BaseType), discriminatorMap);
            }
            //
            // Handle Ref types also in a similar fashion
            //
            else if (TypeHelpers.TryGetEdmType(type, out refType))
            {
                var entityType = refType.ElementType as md.EntityType;
                if (entityType != null &&
                    entityType.BaseType != null)
                {
                    var baseRefType = TypeHelpers.CreateReferenceTypeUsage(entityType.BaseType as md.EntityType);
                    superTypeInfo = CreateTypeInfoForStructuredType(baseRefType, discriminatorMap);
                }
            }

            //
            // Add the types of my properties to the TypeInfo map
            //
            foreach (md.EdmMember m in TypeHelpers.GetDeclaredStructuralMembers(type))
            {
                CreateTypeInfoForType(m.TypeUsage);
            }

            //
            // Get the types of the rel properties also
            //
            {
                md.EntityTypeBase entityType;
                if (TypeHelpers.TryGetEdmType(type, out entityType))
                {
                    foreach (var p in m_relPropertyHelper.GetDeclaredOnlyRelProperties(entityType))
                    {
                        CreateTypeInfoForType(p.ToEnd.TypeUsage);
                    }
                }
            }

            // Now add myself to the map
            typeInfo = TypeInfo.Create(type, superTypeInfo, discriminatorMap);
            m_typeInfoMap.Add(type, typeInfo);

            return(typeInfo);
        }
        private static bool ProcessOuterApplyOverProject(RuleProcessingContext context, Node applyNode, out Node newNode)
        {
            newNode = applyNode;
            var projectNode    = applyNode.Child1;
            var varDefListNode = projectNode.Child1;

            var trc           = (TransformationRulesContext)context;
            var inputNodeInfo = context.Command.GetExtendedNodeInfo(projectNode.Child0);
            var sentinelVar   = inputNodeInfo.NonNullableDefinitions.First;

            //
            // special case handling first - we'll end up in an infinite loop otherwise.
            // If the ProjectOp is the dummy ProjectOp that we would be building (ie)
            // it defines only 1 var - and the defining expression is simply a constant
            //
            if (sentinelVar == null
                &&
                varDefListNode.Children.Count == 1
                &&
                (varDefListNode.Child0.Child0.Op.OpType == OpType.InternalConstant ||
                 varDefListNode.Child0.Child0.Op.OpType == OpType.NullSentinel))
            {
                return(false);
            }

            var  command          = context.Command;
            Node dummyProjectNode = null;
            InternalConstantOp nullSentinelDefinitionOp = null;

            // get node information for the project's child
            var projectInputNodeInfo = command.GetExtendedNodeInfo(projectNode.Child0);

            //
            // Build up a dummy project node.
            // Walk through each local definition of the current project Node, and convert
            // all expressions into case expressions whose value depends on the var
            // produced by the dummy project node
            //

            // Dev10 #480443: If any of the definitions changes we need to recompute the node info.
            var anyVarDefChagned = false;

            foreach (var varDefNode in varDefListNode.Children)
            {
                PlanCompiler.Assert(varDefNode.Op.OpType == OpType.VarDef, "Expected VarDefOp. Found " + varDefNode.Op.OpType + " instead");
                var varRefOp = varDefNode.Child0.Op as VarRefOp;
                if (varRefOp == null ||
                    !projectInputNodeInfo.Definitions.IsSet(varRefOp.Var))
                {
                    // do we need to build a dummy project node
                    if (sentinelVar == null)
                    {
                        nullSentinelDefinitionOp = command.CreateInternalConstantOp(command.IntegerType, 1);
                        var dummyConstantExpr          = command.CreateNode(nullSentinelDefinitionOp);
                        var dummyProjectVarDefListNode = command.CreateVarDefListNode(dummyConstantExpr, out sentinelVar);
                        var dummyProjectOp             = command.CreateProjectOp(sentinelVar);
                        dummyProjectOp.Outputs.Or(projectInputNodeInfo.Definitions);
                        dummyProjectNode = command.CreateNode(dummyProjectOp, projectNode.Child0, dummyProjectVarDefListNode);
                    }

                    Node currentDefinition;

                    // If the null sentinel was just created, and the local definition of the current project Node
                    // is an internal constant equivalent to the null sentinel, it can be rewritten as a reference
                    // to the null sentinel.
                    if (nullSentinelDefinitionOp != null &&
                        (nullSentinelDefinitionOp.IsEquivalent(varDefNode.Child0.Op) ||
                         //The null sentinel has the same value of 1, thus it is safe.
                         varDefNode.Child0.Op.OpType == OpType.NullSentinel))
                    {
                        currentDefinition = command.CreateNode(command.CreateVarRefOp(sentinelVar));
                    }
                    else
                    {
                        currentDefinition = trc.BuildNullIfExpression(sentinelVar, varDefNode.Child0);
                    }
                    varDefNode.Child0 = currentDefinition;
                    command.RecomputeNodeInfo(varDefNode);
                    anyVarDefChagned = true;
                }
            }

            // Recompute node info if needed
            if (anyVarDefChagned)
            {
                command.RecomputeNodeInfo(varDefListNode);
            }

            //
            // If we've created a dummy project node, make that the new child of the applyOp
            //
            applyNode.Child1 = dummyProjectNode != null ? dummyProjectNode : projectNode.Child0;
            command.RecomputeNodeInfo(applyNode);

            //
            // Pull up the project node above the apply node now. Also, make sure that every Var of
            // the applyNode's definitions actually shows up in the new Project
            //
            projectNode.Child0 = applyNode;
            var applyLeftChildNodeInfo = command.GetExtendedNodeInfo(applyNode.Child0);
            var projectOp = (ProjectOp)projectNode.Op;

            projectOp.Outputs.Or(applyLeftChildNodeInfo.Definitions);

            newNode = projectNode;
            return(true);
        }
Example #13
0
        public override void Visit(UnionAllOp op, Node n)
        {
#if DEBUG
            var input = Dump.ToXml(n);
#endif
            //DEBUG

            // Ensure we have keys pulled up on each branch of the union all.
            VisitChildren(n);

            // Create the setOp var we'll use to output the branch discriminator value; if
            // any of the branches are already surfacing a branchDiscriminator var to the
            // output of this operation then we won't need to use this but we construct it
            // early to simplify logic.
            Var outputBranchDiscriminatorVar = m_command.CreateSetOpVar(m_command.IntegerType);

            // Now ensure that we're outputting the key vars from this op as well.
            var allKeyVarsMissingFromOutput = Command.CreateVarList();
            var keyVarsMissingFromOutput    = new VarVec[n.Children.Count];

            for (var i = 0; i < n.Children.Count; i++)
            {
                var branchNode     = n.Children[i];
                var branchNodeInfo = m_command.GetExtendedNodeInfo(branchNode);

                // Identify keys that aren't in the output list of this operation. We
                // determine these by remapping the keys that are found through the node's
                // VarMap, which gives us the keys in the same "varspace" as the outputs
                // of the UnionAll, then we subtract out the outputs of this UnionAll op,
                // leaving things that are not in the output vars.  Of course, if they're
                // not in the output vars, then we didn't really remap.
                var existingKeyVars = branchNodeInfo.Keys.KeyVars.Remap(op.VarMap[i]);

                keyVarsMissingFromOutput[i] = m_command.CreateVarVec(existingKeyVars);
                keyVarsMissingFromOutput[i].Minus(op.Outputs);

                // Special Case: if the branch is a UnionAll, it will already have it's
                // branch discriminator var added in the keys; we don't want to add that
                // a second time...
                if (OpType.UnionAll
                    == branchNode.Op.OpType)
                {
                    var branchUnionAllOp = (UnionAllOp)branchNode.Op;

                    keyVarsMissingFromOutput[i].Clear(branchUnionAllOp.BranchDiscriminator);
                }

                allKeyVarsMissingFromOutput.AddRange(keyVarsMissingFromOutput[i]);
            }

            // Construct the setOp vars we're going to map to output.
            var allKeyVarsToAddToOutput = Command.CreateVarList();

            foreach (var v in allKeyVarsMissingFromOutput)
            {
                Var newKeyVar = m_command.CreateSetOpVar(v.Type);
                allKeyVarsToAddToOutput.Add(newKeyVar);
            }

            // Now that we've identified all the keys we need to add, ensure that each branch
            // has both the branch discrimination var and the all the keys in them, even when
            // the keys are just going to null (which we construct, as needed)
            for (var i = 0; i < n.Children.Count; i++)
            {
                var branchNode     = n.Children[i];
                var branchNodeInfo = m_command.GetExtendedNodeInfo(branchNode);

                var branchOutputVars = m_command.CreateVarVec();
                var varDefNodes      = new List <Node>();

                // If the branch is a UnionAllOp that has a branch discriminator var then we can
                // use it, otherwise we'll construct a new integer constant with the next value
                // of the branch discriminator value from the command object.
                Var branchDiscriminatorVar;

                if (OpType.UnionAll == branchNode.Op.OpType &&
                    null != ((UnionAllOp)branchNode.Op).BranchDiscriminator)
                {
                    branchDiscriminatorVar = ((UnionAllOp)branchNode.Op).BranchDiscriminator;

                    // If the branch has a discriminator var, but we haven't added it to the
                    // varmap yet, then we do so now.
                    if (!op.VarMap[i].ContainsValue(branchDiscriminatorVar))
                    {
                        op.VarMap[i].Add(outputBranchDiscriminatorVar, branchDiscriminatorVar);
                        // We don't need to add this to the branch outputs, because it's already there,
                        // otherwise we wouln't have gotten here, yes?
                    }
                    else
                    {
                        // In this case, we're already outputting the branch discriminator var -- we'll
                        // just use it for both sides.  We should never have a case where only one of the
                        // two branches are outputting the branch discriminator var, because it can only
                        // be constructed in this method, and we wouldn't need it for any other purpose.
                        PlanCompiler.Assert(0 == i, "right branch has a discriminator var that the left branch doesn't have?");
                        var reverseVarMap = op.VarMap[i].GetReverseMap();
                        outputBranchDiscriminatorVar = reverseVarMap[branchDiscriminatorVar];
                    }
                }
                else
                {
                    // Not a unionAll -- we have to add a BranchDiscriminator var.
                    varDefNodes.Add(
                        m_command.CreateVarDefNode(
                            m_command.CreateNode(
                                m_command.CreateConstantOp(m_command.IntegerType, m_command.NextBranchDiscriminatorValue)),
                            out branchDiscriminatorVar));

                    branchOutputVars.Set(branchDiscriminatorVar);
                    op.VarMap[i].Add(outputBranchDiscriminatorVar, branchDiscriminatorVar);
                }

                // Append all the missing keys to the branch outputs.  If the missing key
                // is not from this branch then create a null.
                for (var j = 0; j < allKeyVarsMissingFromOutput.Count; j++)
                {
                    var keyVar = allKeyVarsMissingFromOutput[j];

                    if (!keyVarsMissingFromOutput[i].IsSet(keyVar))
                    {
                        varDefNodes.Add(
                            m_command.CreateVarDefNode(
                                m_command.CreateNode(
                                    m_command.CreateNullOp(keyVar.Type)), out keyVar));

                        branchOutputVars.Set(keyVar);
                    }

                    // In all cases, we're adding a key to the output so we need to update the
                    // varmap.
                    op.VarMap[i].Add(allKeyVarsToAddToOutput[j], keyVar);
                }

                // If we got this far and didn't add anything to the branch, then we're done.
                // Otherwise we'll have to construct the new projectOp around the input branch
                // to add the stuff we've added.
                if (branchOutputVars.IsEmpty)
                {
                    // Actually, we're not quite done -- we need to update the key vars for the
                    // branch to include the branch discriminator var we
                    branchNodeInfo.Keys.KeyVars.Set(branchDiscriminatorVar);
                }
                else
                {
                    PlanCompiler.Assert(varDefNodes.Count != 0, "no new nodes?");

                    // Start by ensuring all the existing outputs from the branch are in the list.
                    foreach (var v in op.VarMap[i].Values)
                    {
                        branchOutputVars.Set(v);
                    }

                    // Now construct a project op to project out everything we've added, and
                    // replace the branchNode with it in the flattened ladder.
                    n.Children[i] = m_command.CreateNode(
                        m_command.CreateProjectOp(branchOutputVars),
                        branchNode,
                        m_command.CreateNode(m_command.CreateVarDefListOp(), varDefNodes));

                    // Finally, ensure that we update the Key info for the projectOp to include
                    // the original branch's keys, along with the branch discriminator var.
                    m_command.RecomputeNodeInfo(n.Children[i]);
                    var projectNodeInfo = m_command.GetExtendedNodeInfo(n.Children[i]);
                    projectNodeInfo.Keys.KeyVars.InitFrom(branchNodeInfo.Keys.KeyVars);
                    projectNodeInfo.Keys.KeyVars.Set(branchDiscriminatorVar);
                }
            }

            // All done with the branches, now it's time to update the UnionAll op to indicate
            // that we've got a branch discriminator var.
            n.Op = m_command.CreateUnionAllOp(op.VarMap[0], op.VarMap[1], outputBranchDiscriminatorVar);

            // Finally, the thing we've all been waiting for -- computing the keys.  We cheat here and let
            // nodeInfo do it so we don't have to duplicate the logic...
            m_command.RecomputeNodeInfo(n);

#if DEBUG
            input = input.Trim();
            var output = Dump.ToXml(n);
#endif
            //DEBUG
        }
Example #14
0
        private static bool ProcessJoinOverProject(RuleProcessingContext context, Node joinNode, out Node newNode)
        {
            newNode = joinNode;

            var trc     = (TransformationRulesContext)context;
            var command = trc.Command;

            var joinConditionNode = joinNode.HasChild2 ? joinNode.Child2 : null;
            var varRefMap         = new Dictionary <Var, int>();

            if (joinConditionNode != null &&
                !trc.IsScalarOpTree(joinConditionNode, varRefMap))
            {
                return(false);
            }

            Node newJoinNode;
            Node newProjectNode;

            // Now locate the ProjectOps
            var newVarSet   = command.CreateVarVec();
            var varDefNodes = new List <Node>();

            //
            // Try and handle "project" on both sides only if we're not dealing with
            // an LOJ.
            //
            if ((joinNode.Op.OpType != OpType.LeftOuterJoin)
                &&
                (joinNode.Child0.Op.OpType == OpType.Project)
                &&
                (joinNode.Child1.Op.OpType == OpType.Project))
            {
                var projectOp1 = (ProjectOp)joinNode.Child0.Op;
                var projectOp2 = (ProjectOp)joinNode.Child1.Op;

                var varMap1 = trc.GetVarMap(joinNode.Child0.Child1, varRefMap);
                var varMap2 = trc.GetVarMap(joinNode.Child1.Child1, varRefMap);
                if (varMap1 == null ||
                    varMap2 == null)
                {
                    return(false);
                }

                if (joinConditionNode != null)
                {
                    joinConditionNode = trc.ReMap(joinConditionNode, varMap1);
                    joinConditionNode = trc.ReMap(joinConditionNode, varMap2);
                    newJoinNode       = context.Command.CreateNode(joinNode.Op, joinNode.Child0.Child0, joinNode.Child1.Child0, joinConditionNode);
                }
                else
                {
                    newJoinNode = context.Command.CreateNode(joinNode.Op, joinNode.Child0.Child0, joinNode.Child1.Child0);
                }

                newVarSet.InitFrom(projectOp1.Outputs);
                foreach (var v in projectOp2.Outputs)
                {
                    newVarSet.Set(v);
                }
                var newProjectOp = command.CreateProjectOp(newVarSet);
                varDefNodes.AddRange(joinNode.Child0.Child1.Children);
                varDefNodes.AddRange(joinNode.Child1.Child1.Children);
                var varDefListNode = command.CreateNode(
                    command.CreateVarDefListOp(),
                    varDefNodes);
                newProjectNode = command.CreateNode(
                    newProjectOp,
                    newJoinNode, varDefListNode);
                newNode = newProjectNode;
                return(true);
            }

            var projectNodeIdx = -1;
            var otherNodeIdx   = -1;

            if (joinNode.Child0.Op.OpType
                == OpType.Project)
            {
                projectNodeIdx = 0;
                otherNodeIdx   = 1;
            }
            else
            {
                PlanCompiler.Assert(joinNode.Op.OpType != OpType.LeftOuterJoin, "unexpected non-LeftOuterJoin");
                projectNodeIdx = 1;
                otherNodeIdx   = 0;
            }
            var projectNode = joinNode.Children[projectNodeIdx];

            var projectOp = projectNode.Op as ProjectOp;
            var varMap    = trc.GetVarMap(projectNode.Child1, varRefMap);

            if (varMap == null)
            {
                return(false);
            }
            var otherChildInfo = command.GetExtendedNodeInfo(joinNode.Children[otherNodeIdx]);
            var vec            = command.CreateVarVec(projectOp.Outputs);

            vec.Or(otherChildInfo.Definitions);
            projectOp.Outputs.InitFrom(vec);
            if (joinConditionNode != null)
            {
                joinConditionNode = trc.ReMap(joinConditionNode, varMap);
                joinNode.Child2   = joinConditionNode;
            }
            joinNode.Children[projectNodeIdx] = projectNode.Child0; // bypass the projectOp
            context.Command.RecomputeNodeInfo(joinNode);

            newNode = context.Command.CreateNode(projectOp, joinNode, projectNode.Child1);
            return(true);
        }
        private void TryProcessCandidate(
            KeyValuePair <Node, Node> candidate,
            GroupAggregateVarInfo groupAggregateVarInfo)
        {
            IList <Node> functionAncestors;
            IList <Node> groupByAncestors;
            var          definingGroupNode = groupAggregateVarInfo.DefiningGroupNode;

            FindPathsToLeastCommonAncestor(candidate.Key, definingGroupNode, out functionAncestors, out groupByAncestors);

            //Check whether all ancestors of the GroupByInto node are of type that we support propagating through
            if (!AreAllNodesSupportedForPropagation(groupByAncestors))
            {
                return;
            }

            //Add the function to the group by node
            var definingGroupOp = (GroupByIntoOp)definingGroupNode.Op;

            PlanCompiler.Assert(definingGroupOp.Inputs.Count == 1, "There should be one input var to GroupByInto at this stage");
            var inputVar   = definingGroupOp.Inputs.First;
            var functionOp = (FunctionOp)candidate.Key.Op;

            //
            // Remap the template from referencing the groupAggregate var to reference the input to
            // the group by into
            //
            var argumentNode = OpCopier.Copy(m_command, candidate.Value);
            var dictionary   = new Dictionary <Var, Var>(1);

            dictionary.Add(groupAggregateVarInfo.GroupAggregateVar, inputVar);
            var remapper = new VarRemapper(m_command, dictionary);

            remapper.RemapSubtree(argumentNode);

            var newFunctionDefiningNode = m_command.CreateNode(
                m_command.CreateAggregateOp(functionOp.Function, false),
                argumentNode);

            Var newFunctionVar;
            var varDefNode = m_command.CreateVarDefNode(newFunctionDefiningNode, out newFunctionVar);

            // Add the new aggregate to the list of aggregates
            definingGroupNode.Child2.Children.Add(varDefNode);
            var groupByOp = (GroupByIntoOp)definingGroupNode.Op;

            groupByOp.Outputs.Set(newFunctionVar);

            //Propagate the new var throught the ancestors of the GroupByInto
            for (var i = 0; i < groupByAncestors.Count; i++)
            {
                var groupByAncestor = groupByAncestors[i];
                if (groupByAncestor.Op.OpType
                    == OpType.Project)
                {
                    var ancestorProjectOp = (ProjectOp)groupByAncestor.Op;
                    ancestorProjectOp.Outputs.Set(newFunctionVar);
                }
            }

            //Update the functionNode
            candidate.Key.Op = m_command.CreateVarRefOp(newFunctionVar);
            candidate.Key.Children.Clear();
        }
Example #16
0
 private Validator(PlanCompiler compilerState)
     : base(compilerState.Command)
 {
     m_compilerState = compilerState;
 }
        private const string PrefixMatchCharacter = "%"; // This is ANSI-SQL defined, but it should probably be configurable.

        #endregion

        #region constructors

        private NominalTypeEliminator(
            PlanCompiler compilerState,
            StructuredTypeInfo typeInfo,
            Dictionary<Var, PropertyRefList> varPropertyMap,
            Dictionary<Node, PropertyRefList> nodePropertyMap,
            Dictionary<md.EdmFunction, md.EdmProperty[]> tvfResultKeys)
        {
            m_compilerState = compilerState;
            m_typeInfo = typeInfo;
            m_varPropertyMap = varPropertyMap;
            m_nodePropertyMap = nodePropertyMap;
            m_varInfoMap = new VarInfoMap();
            m_tvfResultKeys = tvfResultKeys;
            m_typeToNewTypeMap = new Dictionary<md.TypeUsage, md.TypeUsage>(TypeUsageEqualityComparer.Instance);
        }
        private Node VisitCollect(Node n)
        {
            //Make sure the only children are projects over unnest
            var currentNode         = n.Child0;
            var constantDefinitions = new Dictionary <Var, Node>();

            while (currentNode.Child0.Op.OpType
                   == OpType.Project)
            {
                currentNode = currentNode.Child0;
                //Visit the VarDefListOp child
                if (VisitDefault(currentNode.Child1) == null)
                {
                    return(null);
                }
                foreach (var definitionNode in currentNode.Child1.Children)
                {
                    if (IsConstant(definitionNode.Child0))
                    {
                        constantDefinitions.Add(((VarDefOp)definitionNode.Op).Var, definitionNode.Child0);
                    }
                }
            }

            if (currentNode.Child0.Op.OpType
                != OpType.Unnest)
            {
                return(null);
            }

            // Handle the unnest
            var unnestOp = (UnnestOp)currentNode.Child0.Op;
            GroupAggregateVarRefInfo groupAggregateVarRefInfo;

            if (_groupAggregateVarInfoManager.TryGetReferencedGroupAggregateVarInfo(unnestOp.Var, out groupAggregateVarRefInfo))
            {
                if (_targetGroupAggregateVarInfo == null)
                {
                    _targetGroupAggregateVarInfo = groupAggregateVarRefInfo.GroupAggregateVarInfo;
                }
                else if (_targetGroupAggregateVarInfo != groupAggregateVarRefInfo.GroupAggregateVarInfo)
                {
                    return(null);
                }
                if (!_isUnnested)
                {
                    return(null);
                }
            }
            else
            {
                return(null);
            }

            var physicalProjectOp = (PhysicalProjectOp)n.Child0.Op;

            PlanCompiler.Assert(physicalProjectOp.Outputs.Count == 1, "Physical project should only have one output at this stage");
            var outputVar = physicalProjectOp.Outputs[0];

            var computationTemplate = TranslateOverGroupAggregateVar(outputVar, null);

            if (computationTemplate != null)
            {
                _isUnnested = true;
                return(computationTemplate);
            }

            Node constantDefinitionNode;

            if (constantDefinitions.TryGetValue(outputVar, out constantDefinitionNode))
            {
                _isUnnested = true;
                return(constantDefinitionNode);
            }
            return(null);
        }
Example #19
0
 private JoinElimination(PlanCompiler compilerState)
 {
     m_compilerState = compilerState;
     m_varRemapper = new VarRemapper(m_compilerState.Command);
     m_varRefManager = new VarRefManager(m_compilerState.Command);
 }
        private static bool ProcessSimplifyCase_EliminateWhenClauses(
            RuleProcessingContext context, CaseOp caseOp, Node caseOpNode, out Node newNode)
        {
            List <Node> newNodeArgs = null;

            newNode = caseOpNode;

            for (var i = 0; i < caseOpNode.Children.Count;)
            {
                // Special handling for the else clause
                if (i == caseOpNode.Children.Count - 1)
                {
                    // If the else clause is a SoftCast then we do not attempt to simplify
                    // the case operation, since this may change the result type.
                    // This really belongs in more general SoftCastOp logic in the CTreeGenerator
                    // that converts SoftCasts that could affect the result type of the query into
                    // a real cast or a trivial case statement, to preserve the result type.
                    // This is tracked by SQL PT Work Item #300003327.
                    if (OpType.SoftCast
                        == caseOpNode.Children[i].Op.OpType)
                    {
                        return(false);
                    }

                    if (newNodeArgs != null)
                    {
                        newNodeArgs.Add(caseOpNode.Children[i]);
                    }
                    break;
                }

                // If the current then clause is a SoftCast then we do not attempt to simplify
                // the case operation, since this may change the result type.
                // Again, this really belongs in the CTreeGenerator as per SQL PT Work Item #300003327.
                if (OpType.SoftCast
                    == caseOpNode.Children[i + 1].Op.OpType)
                {
                    return(false);
                }

                // Check to see if the when clause is a ConstantPredicate
                if (caseOpNode.Children[i].Op.OpType
                    != OpType.ConstantPredicate)
                {
                    if (newNodeArgs != null)
                    {
                        newNodeArgs.Add(caseOpNode.Children[i]);
                        newNodeArgs.Add(caseOpNode.Children[i + 1]);
                    }
                    i += 2;
                    continue;
                }

                // Found a when-clause which is a constant predicate
                var constPred = (ConstantPredicateOp)caseOpNode.Children[i].Op;
                // Create the newArgs list, if we haven't done so already
                if (newNodeArgs == null)
                {
                    newNodeArgs = new List <Node>();
                    for (var j = 0; j < i; j++)
                    {
                        newNodeArgs.Add(caseOpNode.Children[j]);
                    }
                }

                // If the when-clause is the "true" predicate, then we simply ignore all
                // the succeeding arguments. We make the "then" clause of this when-clause
                // as the "else-clause" of the resulting caseOp
                if (constPred.IsTrue)
                {
                    newNodeArgs.Add(caseOpNode.Children[i + 1]);
                    break;
                }
                else
                {
                    // Otherwise, we simply skip the when-then pair
                    PlanCompiler.Assert(constPred.IsFalse, "constant predicate must be either true or false");
                    i += 2;
                    continue;
                }
            }

            // Did we see any changes? Simply return
            if (newNodeArgs == null)
            {
                return(false);
            }

            // Otherwise, we did do some processing
            PlanCompiler.Assert(newNodeArgs.Count > 0, "new args list must not be empty");
            // Is there only one expression in the args list - simply return that expression
            if (newNodeArgs.Count == 1)
            {
                newNode = newNodeArgs[0];
            }
            else
            {
                newNode = context.Command.CreateNode(caseOp, newNodeArgs);
            }

            return(true);
        }
Example #21
0
 private Normalizer(PlanCompiler planCompilerState)
     : base(planCompilerState)
 {
 }
Example #22
0
        private readonly VarVec m_referencedVars; // the list of referenced vars in the query

        #endregion

        #region constructor

        // <summary>
        // Trivial private constructor
        // </summary>
        // <param name="compilerState"> current compiler state </param>
        private ProjectionPruner(PlanCompiler compilerState)
        {
            m_compilerState  = compilerState;
            m_referencedVars = compilerState.Command.CreateVarVec();
        }
 protected SubqueryTrackingVisitor(PlanCompiler planCompilerState)
 {
     m_compilerState = planCompilerState;
 }
Example #24
0
 // <summary>
 // Runs through the root node of the tree, and eliminates all
 // unreferenced expressions
 // </summary>
 // <param name="compilerState"> current compiler state </param>
 internal static void Process(PlanCompiler compilerState)
 {
     compilerState.Command.Root = Process(compilerState, compilerState.Command.Root);
 }
 // <summary>
 // Apply the rules that belong to the specified rules table to the given query tree.
 // </summary>
 // <param name="projectionPruningRequired"> is projection pruning required after the rule application </param>
 // <returns> Whether any rule has been applied after which reapplying nullability rules may be useful </returns>
 private static bool Process(
     PlanCompiler compilerState, ReadOnlyCollection<ReadOnlyCollection<Rule>> rulesTable, out bool projectionPruningRequired)
 {
     var ruleProcessor = new RuleProcessor();
     var context = new TransformationRulesContext(compilerState);
     compilerState.Command.Root = ruleProcessor.ApplyRulesToSubtree(context, rulesTable, compilerState.Command.Root);
     projectionPruningRequired = context.ProjectionPrunningRequired;
     return context.ReapplyNullabilityRules;
 }
Example #26
0
        // <summary>
        // Runs through the given subtree, and eliminates all
        // unreferenced expressions
        // </summary>
        // <param name="compilerState"> current compiler state </param>
        // <param name="node"> The node to be processed </param>
        // <returns> The processed, i.e. transformed node </returns>
        internal static Node Process(PlanCompiler compilerState, Node node)
        {
            var pruner = new ProjectionPruner(compilerState);

            return(pruner.Process(node));
        }
 // <summary>
 // Apply Aggregate Pushdown over the tree in the given plan complier state.
 // </summary>
 internal static void Process(PlanCompiler planCompilerState)
 {
     var aggregatePushdown = new AggregatePushdown(planCompilerState.Command);
     aggregatePushdown.Process();
 }
Example #28
0
 internal Predicate(Command command, Node andTree)
     : this(command)
 {
     PlanCompiler.Assert(andTree != null, "null node passed to Predicate() constructor");
     InitFromAndTree(andTree);
 }
Example #29
0
 private Normalizer(PlanCompiler planCompilerState)
     : base(planCompilerState)
 {
 }
Example #30
0
        // <summary>
        // The driver routine.
        // </summary>
        // <param name="planCompilerState"> plan compiler state </param>
        internal static void Process(PlanCompiler planCompilerState)
        {
            var normalizer = new Normalizer(planCompilerState);

            normalizer.Process();
        }
Example #31
0
 internal static void Validate(PlanCompiler compilerState)
 {
     Validate(compilerState, compilerState.Command.Root);
 }
Example #32
0
 private CodeGen(PlanCompiler compilerState)
 {
     m_compilerState = compilerState;
 }
 internal TransformationRulesContext(PlanCompiler compilerState)
     : base(compilerState.Command)
 {
     m_compilerState = compilerState;
     m_remapper = new VarRemapper(compilerState.Command);
     m_suppressions = new Dictionary<Node, Node>();
     m_remappedVars = compilerState.Command.CreateVarVec();
 }
Example #34
0
        private EntityColumnMap CreateEntityColumnMap(
            TypeInfo typeInfo, string name, EntityColumnMap superTypeColumnMap,
            Dictionary <object, TypedColumnMap> discriminatorMap, List <TypedColumnMap> allMaps, bool handleRelProperties)
        {
            EntityColumnMap columnMap             = null;
            var             propertyColumnMapList = new List <ColumnMap>();

            // Copy over information from my supertype if it already exists
            if (superTypeColumnMap != null)
            {
                // get supertype properties
                foreach (var c in superTypeColumnMap.Properties)
                {
                    propertyColumnMapList.Add(c);
                }
                // Now add on all of my "specific" properties
                foreach (md.EdmMember property in TypeHelpers.GetDeclaredStructuralMembers(typeInfo.Type))
                {
                    var propertyColumnMap = CreateColumnMap(md.Helper.GetModelTypeUsage(property), property.Name);
                    propertyColumnMapList.Add(propertyColumnMap);
                }
                // create the entity column map w/ information from my supertype
                columnMap = new EntityColumnMap(typeInfo.Type, name, propertyColumnMapList.ToArray(), superTypeColumnMap.EntityIdentity);
            }
            else
            {
                SimpleColumnMap entitySetIdColumnMap = null;
                if (typeInfo.HasEntitySetIdProperty)
                {
                    entitySetIdColumnMap = CreateEntitySetIdColumnMap(typeInfo.EntitySetIdProperty);
                }

                // build up a list of key columns
                var keyColumnMapList = new List <SimpleColumnMap>();
                // Create a dictionary to look up the key properties
                var keyPropertyMap = new Dictionary <md.EdmProperty, ColumnMap>();

                foreach (md.EdmMember property in TypeHelpers.GetDeclaredStructuralMembers(typeInfo.Type))
                {
                    var propertyColumnMap = CreateColumnMap(md.Helper.GetModelTypeUsage(property), property.Name);
                    propertyColumnMapList.Add(propertyColumnMap);
                    // add property to keymap, if this property is part of the key
                    if (md.TypeSemantics.IsPartOfKey(property))
                    {
                        var edmProperty = property as md.EdmProperty;
                        PlanCompiler.Assert(edmProperty != null, "EntityType key member is not property?");
                        keyPropertyMap[edmProperty] = propertyColumnMap;
                    }
                }

                // Build up the key list if required
                foreach (var keyProperty in TypeHelpers.GetEdmType <md.EntityType>(typeInfo.Type).KeyMembers)
                {
                    var edmKeyProperty = keyProperty as md.EdmProperty;
                    PlanCompiler.Assert(edmKeyProperty != null, "EntityType key member is not property?");
                    var keyColumnMap = keyPropertyMap[edmKeyProperty] as SimpleColumnMap;
                    PlanCompiler.Assert(keyColumnMap != null, "keyColumnMap is null");
                    keyColumnMapList.Add(keyColumnMap);
                }

                //
                // Create the entity identity.
                //
                var identity = CreateEntityIdentity((md.EntityType)typeInfo.Type.EdmType, entitySetIdColumnMap, keyColumnMapList.ToArray());

                // finally create the entity column map
                columnMap = new EntityColumnMap(typeInfo.Type, name, propertyColumnMapList.ToArray(), identity);
            }

            // if a dictionary is supplied, add myself to the dictionary (abstract types need not be added)
            if (discriminatorMap != null)
            {
                // where DiscriminatedNewInstanceOp is used, there will not be an explicit type id for an abstract type
                // or types that do not appear in the QueryView
                // (the mapping will not include such information)
                if (null != typeInfo.TypeId)
                {
                    discriminatorMap[typeInfo.TypeId] = columnMap;
                }
            }
            if (allMaps != null)
            {
                allMaps.Add(columnMap);
            }
            // Finally walk through my subtypes
            foreach (var subTypeInfo in typeInfo.ImmediateSubTypes)
            {
                CreateEntityColumnMap(subTypeInfo, name, columnMap, discriminatorMap, allMaps, false);
            }

            //
            // Build up the list of rel property column maps
            //
            if (handleRelProperties)
            {
                BuildRelPropertyColumnMaps(typeInfo, true);
            }
            return(columnMap);
        }
        /// <summary>
        ///     Eliminates all structural types from the query
        /// </summary>
        /// <param name="compilerState"> current compiler state </param>
        /// <param name="structuredTypeInfo"> </param>
        /// <param name="tvfResultKeys"> inferred s-space keys for TVFs that are mapped to entities </param>
        internal static void Process(
            PlanCompiler compilerState,
            StructuredTypeInfo structuredTypeInfo,
            Dictionary<md.EdmFunction, md.EdmProperty[]> tvfResultKeys)
        {
#if DEBUG
    //string phase0 = Dump.ToXml(compilerState.Command);
            Validator.Validate(compilerState);
#endif

            // Phase 1: Top-down property pushdown
            Dictionary<Var, PropertyRefList> varPropertyMap;
            Dictionary<Node, PropertyRefList> nodePropertyMap;
            PropertyPushdownHelper.Process(compilerState.Command, out varPropertyMap, out nodePropertyMap);

#if DEBUG
    //string phase1 = Dump.ToXml(compilerState.Command);
            Validator.Validate(compilerState);
#endif

            // Phase 2: actually eliminate nominal types
            var nte = new NominalTypeEliminator(
                compilerState, structuredTypeInfo, varPropertyMap, nodePropertyMap, tvfResultKeys);
            nte.Process();

#if DEBUG
    //string phase2 = Dump.ToXml(compilerState.Command);
            Validator.Validate(compilerState);
#endif

#if DEBUG
    //To avoid garbage collection
    //int size = phase0.Length;
    //size = phase1.Length;
    //size = phase2.Length;
#endif
        }
Example #36
0
        internal static void Validate(PlanCompiler compilerState, Node n)
        {
            var validator = new Validator(compilerState);

            validator.Validate(n);
        }
Example #37
0
 internal static void Process(PlanCompiler compilerState)
 {
     var np = new NestPullup(compilerState);
     np.Process();
 }
Example #38
0
 internal static void Validate(PlanCompiler compilerState)
 {
     Validate(compilerState, compilerState.Command.Root);
 }
Example #39
0
 internal static bool Process(PlanCompiler compilerState)
 {
     var je = new JoinElimination(compilerState);
     je.Process();
     return je.m_treeModified;
 }
Example #40
0
 private Validator(PlanCompiler compilerState)
     : base(compilerState.Command)
 {
     m_compilerState = compilerState;
 }
Example #41
0
 private CodeGen(PlanCompiler compilerState)
 {
     m_compilerState = compilerState;
 }
Example #42
0
 public override void Visit(ScanTableOp op, Node n)
 {
     PlanCompiler.Assert(!n.HasChild0, "scanTableOp with an input?");
 }
Example #43
0
 /// <summary>
 ///     The driver routine.
 /// </summary>
 /// <param name="planCompilerState"> plan compiler state </param>
 internal static void Process(PlanCompiler planCompilerState)
 {
     var normalizer = new Normalizer(planCompilerState);
     normalizer.Process();
 }
 private JoinElimination(PlanCompiler compilerState)
 {
     m_compilerState = compilerState;
     m_varRemapper   = new VarRemapper(m_compilerState.Command);
     m_varRefManager = new VarRefManager(m_compilerState.Command);
 }