Beispiel #1
0
        public override Statement EmitStatement(EmitMode mode)
        {
            AggregateExpression expression = new AggregateExpression();

            expression.Expression = (Expression)_sourceNode.EmitStatement(mode);
            expression.ByColumns.AddRange(_columns);
            expression.ComputeColumns.AddRange(_computeColumns);
            expression.Modifiers = Modifiers;
            return(expression);
        }
Beispiel #2
0
        public override Statement EmitStatement(EmitMode mode)
        {
            ExplodeExpression expression = new ExplodeExpression();

            expression.Expression = (Expression)Nodes[0].EmitStatement(mode);
            PlanNode  rootNode  = Nodes[1];
            OrderNode orderNode = rootNode as OrderNode;

            if (orderNode != null)
            {
                expression.HasOrderByClause = true;
                for (int index = 0; index < orderNode.RequestedOrder.Columns.Count; index++)
                {
                    expression.OrderColumns.Add(orderNode.RequestedOrder.Columns[index].EmitStatement(mode));
                }
                rootNode = rootNode.Nodes[0];
            }

            expression.RootExpression = ((RestrictExpression)rootNode.EmitStatement(mode)).Condition;

            PlanNode byNode = Nodes[2];

            if (byNode is OrderNode)
            {
                byNode = byNode.Nodes[0];
            }

            expression.ByExpression = ((RestrictExpression)byNode.EmitStatement(mode)).Condition;

            if (_levelColumnIndex >= 0)
            {
                Schema.TableVarColumn levelColumn = TableVar.Columns[_levelColumnIndex];
                expression.LevelColumn = new IncludeColumnExpression(levelColumn.Name, levelColumn.MetaData == null ? null : levelColumn.MetaData.Copy());
            }

            if (_sequenceColumnIndex >= 0)
            {
                Schema.TableVarColumn sequenceColumn = TableVar.Columns[_sequenceColumnIndex];
                expression.SequenceColumn = new IncludeColumnExpression(sequenceColumn.Name, sequenceColumn.MetaData == null ? null : sequenceColumn.MetaData.Copy());
            }
            expression.Modifiers = Modifiers;
            return(expression);
        }
Beispiel #3
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();
            }
        }