Beispiel #1
0
 public void Add(OperatorBindingContext context)
 {
     if (!_resolutions.ContainsKey(context))
     {
         _resolutions.Add(context, context);
     }
 }
Beispiel #2
0
 public OperatorBindingContext this[OperatorBindingContext context]
 {
     get
     {
         OperatorBindingContext localContext = null;
         _resolutions.TryGetValue(context, out localContext);
         return(localContext);
     }
 }
Beispiel #3
0
        /*
         *      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);
                                }
                            }
                        }
                    }
                }
            }
        }
Beispiel #4
0
        // 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();
            }
        }
Beispiel #5
0
        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;
                    }
                }
            }
        }
Beispiel #6
0
 public void ResolveSignature(Plan plan, OperatorBindingContext context)
 {
     _signatures.Resolve(plan, context);
 }