public void Add(OperatorBindingContext context) { if (!_resolutions.ContainsKey(context)) { _resolutions.Add(context, context); } }
public OperatorBindingContext this[OperatorBindingContext context] { get { OperatorBindingContext localContext = null; _resolutions.TryGetValue(context, out localContext); return(localContext); } }
/* * Resolution Algorithm -> * if the signature is in this list * return the operator signature * else * for each signature in this list * if the given signature is the signature * return the Resolve on the signature * return null */ public void Resolve(Plan plan, OperatorBindingContext context) { OperatorSignature resultSignature = null; if (_signatures.TryGetValue(context.CallSignature, out resultSignature)) { if (!context.Matches.Contains(resultSignature)) { context.Matches.Add(new OperatorMatch(resultSignature, true)); } } else { foreach (KeyValuePair <Signature, OperatorSignature> entry in _signatures) { var signature = entry.Value; if (context.CallSignature.Is(signature.Signature)) { int matchCount = context.Matches.Count; signature.Signatures.Resolve(plan, context); if (context.Matches.IsExact) { break; } else if (matchCount == context.Matches.Count) { if (!context.Matches.Contains(signature)) { OperatorMatch match = new OperatorMatch(signature, false); for (int index = 0; index < signature.Signature.Count; index++) { match.CanConvert[index] = true; } context.Matches.Add(match); } } } else { if (context.CallSignature.Count == signature.Signature.Count) { if (!context.Matches.Contains(signature)) { OperatorMatch match = new OperatorMatch(signature); bool addMatch = true; match.IsMatch = true; for (int elementIndex = 0; elementIndex < context.CallSignature.Count; elementIndex++) { match.CanConvert[elementIndex] = context.CallSignature[elementIndex].DataType.Is(signature.Signature[elementIndex].DataType); if (!match.CanConvert[elementIndex] && (context.CallSignature[elementIndex].Modifier != Modifier.Var) && (signature.Signature[elementIndex].Modifier != Modifier.Var)) { match.ConversionContexts[elementIndex] = Compiler.FindConversionPath(plan, context.CallSignature[elementIndex].DataType, signature.Signature[elementIndex].DataType); match.CanConvert[elementIndex] = match.ConversionContexts[elementIndex].CanConvert; // As soon as the match being constructed is more narrowing or longer than the best match found so far, it can be safely discarded as a candidate. if ((match.NarrowingScore < context.Matches.BestNarrowingScore) || ((match.NarrowingScore == context.Matches.BestNarrowingScore) && (match.PathLength > context.Matches.ShortestPathLength))) { addMatch = false; break; } } if (!match.CanConvert[elementIndex]) { match.IsMatch = false; } } if (addMatch) { context.Matches.Add(match); } } } } } } }
// AggregateNode // Nodes[0] = Project over {by Columns} // Nodes[0] = ASourceNode // Nodes[1..AggregateExpression.Count] = PlanNode - class determined by lookup from the server catalog // Nodes[0] = Project over {aggregate columns for this expression} // Nodes[0] = Restrict // Nodes[0] = ASourceNode // Nodes[1] = Condition over the first key in the project of the aggregate source (AggregateNode.Nodes[0]); public override void DetermineDataType(Plan plan) { DetermineModifiers(plan); _dataType = new Schema.TableType(); _tableVar = new Schema.ResultTableVar(this); _tableVar.Owner = plan.User; _tableVar.InheritMetaData(SourceTableVar.MetaData); _sourceNode = SourceNode; // TODO: Aggregation source is required to be deterministic because it is long handed, we should do something that allows non-deterministic sources for aggregation if (!_sourceNode.IsRepeatable) { throw new CompilerException(CompilerException.Codes.InvalidAggregationSource, plan.CurrentStatement()); } if (_columns.Count > 0) { ProjectNode projectNode = (ProjectNode)Compiler.EmitProjectNode(plan, SourceNode, _columns, true); Nodes[0] = projectNode; } else { Schema.TableType tableType = new Schema.TableType(); TableSelectorNode node = new TableSelectorNode(tableType); node.TableVar.Keys.Add(new Schema.Key()); node.Nodes.Add(new RowSelectorNode(new Schema.RowType())); node.DetermineCharacteristics(plan); Nodes[0] = node; } CopyTableVarColumns(SourceTableVar.Columns); CopyKeys(SourceTableVar.Keys); CopyOrders(SourceTableVar.Orders); if (SourceNode.Order != null) { Order = CopyOrder(SourceNode.Order); } #if UseReferenceDerivation #if UseElaborable if (plan.CursorContext.CursorCapabilities.HasFlag(CursorCapability.Elaborable)) #endif CopyReferences(plan, SourceTableVar); #endif _aggregateColumnOffset = TableVar.Columns.Count; Schema.Key compareKey = Compiler.FindClusteringKey(plan, TableVar); // Add the computed columns plan.EnterRowContext(); try { plan.Symbols.Push(new Symbol(String.Empty, DataType.CreateRowType(Keywords.Source))); try { Schema.RowType rowType = new Schema.RowType(compareKey.Columns); Schema.RowType sourceRowType = new Schema.RowType(compareKey.Columns, Keywords.Source); Schema.TableVarColumn newColumn; foreach (AggregateColumnExpression expression in _computeColumns) { PlanNode sourceNode = null; string[] columnNames = new string[expression.Columns.Count]; for (int index = 0; index < expression.Columns.Count; index++) { columnNames[index] = expression.Columns[index].ColumnName; } if (expression.Distinct) { sourceNode = Compiler.EmitProjectNode(plan, _sourceNode, columnNames, true); } else { sourceNode = _sourceNode; } for (int index = 0; index < columnNames.Length; index++) { if (((TableNode)sourceNode).TableVar.Columns.IndexOf(columnNames[index]) < 0) { throw new Schema.SchemaException(Schema.SchemaException.Codes.ObjectNotFound, columnNames[index]); } } OperatorBindingContext context = new OperatorBindingContext(expression, expression.AggregateOperator, plan.NameResolutionPath, Compiler.AggregateSignatureFromArguments(sourceNode, columnNames, true), false); PlanNode aggregateNode = Compiler.EmitAggregateCallNode(plan, context, sourceNode, columnNames, expression.HasByClause ? expression.OrderColumns : null); Compiler.CheckOperatorResolution(plan, context); sourceNode = aggregateNode.Nodes[0]; // Make sure to preserve any conversion and casting done by the operator resolution int stackDisplacement = ((AggregateCallNode)aggregateNode).Operator.Initialization.StackDisplacement + 1; // add 1 to account for the result variable stackDisplacement += columnNames.Length; for (int index = 0; index < stackDisplacement; index++) { plan.Symbols.Push(new Symbol(String.Empty, plan.DataTypes.SystemScalar)); } try { // Walk sourceNode (assuming an n-length list of unary table operators) until _sourceNode is found // Insert a restriction between it and a recompile of _sourceNode (to account for possible context changes) if (sourceNode == _sourceNode) { sourceNode = Compiler.EmitRestrictNode(plan, Compiler.CompileExpression(plan, (Expression)_sourceNode.EmitStatement(EmitMode.ForCopy)), Compiler.BuildRowEqualExpression(plan, sourceRowType.Columns, rowType.Columns)); } else { PlanNode currentNode = sourceNode; while (currentNode != null) { if (currentNode.NodeCount >= 1) { if (currentNode.Nodes[0] == _sourceNode) { currentNode.Nodes[0] = Compiler.EmitRestrictNode(plan, Compiler.CompileExpression(plan, (Expression)_sourceNode.EmitStatement(EmitMode.ForCopy)), Compiler.BuildRowEqualExpression(plan, sourceRowType.Columns, rowType.Columns)); break; } currentNode = currentNode.Nodes[0]; } else { Error.Fail("Internal Error: Original source node not found in aggregate invocation argument."); } } } if (expression.HasByClause) { sourceNode = Compiler.EmitOrderNode(plan, (TableNode)sourceNode, Compiler.CompileOrderColumnDefinitions(plan, ((TableNode)sourceNode).TableVar, expression.OrderColumns, null, false), false); } aggregateNode.Nodes[0] = sourceNode; } finally { for (int index = 0; index < stackDisplacement; index++) { plan.Symbols.Pop(); } } newColumn = new Schema.TableVarColumn ( new Schema.Column ( expression.ColumnAlias, aggregateNode.DataType ), expression.MetaData, Schema.TableVarColumnType.Virtual ); DataType.Columns.Add(newColumn.Column); TableVar.Columns.Add(newColumn); newColumn.IsNilable = aggregateNode.IsNilable; Nodes.Add(aggregateNode); } DetermineRemotable(plan); } finally { plan.Symbols.Pop(); } } finally { plan.ExitRowContext(); } }
public void ResolveCall(Plan plan, OperatorBindingContext context) { lock (this) { bool didResolve = false; IntegerList indexes = InternalIndexesOf(context.OperatorName); OperatorBindingContext localContext = new OperatorBindingContext(context.Statement, context.OperatorName, context.ResolutionPath, context.CallSignature, context.IsExact); for (int index = 0; index < indexes.Count; index++) { localContext.OperatorNameContext.Names.Add(this[indexes[index]].Name); this[indexes[index]].ResolveSignature(plan, localContext); } foreach (Schema.LoadedLibraries level in plan.NameResolutionPath) { OperatorBindingContext levelContext = new OperatorBindingContext(context.Statement, context.OperatorName, context.ResolutionPath, context.CallSignature, context.IsExact); foreach (OperatorMatch match in localContext.Matches) { // If the operator resolution is in any library at this level, add it to a binding context for this level if ((match.Signature.Operator.Library == null) || level.ContainsName(match.Signature.Operator.Library.Name)) { if (!levelContext.OperatorNameContext.Names.Contains(match.Signature.Operator.OperatorName)) { levelContext.OperatorNameContext.Names.Add(match.Signature.Operator.OperatorName); } if (!levelContext.Matches.Contains(match)) { levelContext.Matches.Add(match); } } } if (levelContext.Matches.IsExact) { levelContext.Operator = levelContext.Matches.Match.Signature.Operator; levelContext.OperatorNameContext.Object = this[IndexOfName(levelContext.Operator.OperatorName)]; levelContext.OperatorNameContext.Names.Add(levelContext.OperatorNameContext.Object.Name); context.SetBindingDataFromContext(levelContext); return; } else { // If there is no match, or a partial match, collect the signatures and map names resolved at this level foreach (string name in levelContext.OperatorNameContext.Names) { if (!context.OperatorNameContext.Names.Contains(name)) { context.OperatorNameContext.Names.Add(name); } } foreach (OperatorMatch match in levelContext.Matches) { if (!context.Matches.Contains(match)) { context.Matches.Add(match); didResolve = true; } } } } // If a partial match is found within the name resolution path, use it if (!context.IsExact && context.Matches.IsPartial) { didResolve = true; } else { // The name resolution path has been searched and no match was found, so attempt to resolve based on all signatures if (localContext.Matches.IsExact) { localContext.Operator = localContext.Matches.Match.Signature.Operator; localContext.OperatorNameContext.Object = this[IndexOfName(localContext.Operator.OperatorName)]; localContext.OperatorNameContext.Names.Add(localContext.OperatorNameContext.Object.Name); context.SetBindingDataFromContext(localContext); return; } else { // If there is no match, or a partial match, collect the signatures and map names resolved at all levels foreach (string name in localContext.OperatorNameContext.Names) { if (!context.OperatorNameContext.Names.Contains(name)) { context.OperatorNameContext.Names.Add(name); } } foreach (OperatorMatch match in localContext.Matches) { if (!context.Matches.Contains(match)) { context.Matches.Add(match); didResolve = true; } } } } // Ensure that if any resolutions were performed in this catalog, the binding data is set in the context if (didResolve) { if (context.Matches.IsExact || (!context.IsExact && context.Matches.IsPartial)) { if ((context.Operator == null) || (context.Operator != context.Matches.Match.Signature.Operator)) { context.Operator = context.Matches.Match.Signature.Operator; context.OperatorNameContext.Object = this[context.Operator.OperatorName]; } } else { context.Operator = null; } } } }
public void ResolveSignature(Plan plan, OperatorBindingContext context) { _signatures.Resolve(plan, context); }