/// <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); }
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(); }
/// <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); }
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; }
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); } }
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); }
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 }
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(); }
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); }
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); }
private Normalizer(PlanCompiler planCompilerState) : base(planCompilerState) { }
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; }
// <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; }
// <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(); }
internal Predicate(Command command, Node andTree) : this(command) { PlanCompiler.Assert(andTree != null, "null node passed to Predicate() constructor"); InitFromAndTree(andTree); }
private Normalizer(PlanCompiler planCompilerState) : base(planCompilerState) { }
// <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(); }
internal static void Validate(PlanCompiler compilerState) { Validate(compilerState, compilerState.Command.Root); }
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(); }
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 }
internal static void Validate(PlanCompiler compilerState, Node n) { var validator = new Validator(compilerState); validator.Validate(n); }
internal static void Process(PlanCompiler compilerState) { var np = new NestPullup(compilerState); np.Process(); }
internal static void Validate(PlanCompiler compilerState) { Validate(compilerState, compilerState.Command.Root); }
internal static bool Process(PlanCompiler compilerState) { var je = new JoinElimination(compilerState); je.Process(); return je.m_treeModified; }
private Validator(PlanCompiler compilerState) : base(compilerState.Command) { m_compilerState = compilerState; }
private CodeGen(PlanCompiler compilerState) { m_compilerState = compilerState; }
public override void Visit(ScanTableOp op, Node n) { PlanCompiler.Assert(!n.HasChild0, "scanTableOp with an input?"); }
/// <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); }