예제 #1
0
        private ExpressionNode ParseNumberLiteral()
        {
            string text = _token.Text;

            bool hasHexModifier         = text.EndsWith("h", StringComparison.OrdinalIgnoreCase);
            bool hasExponentialModifier = text.IndexOfAny(new char[] { '.', 'E', 'e' }) != -1;

            if (hasExponentialModifier && !hasHexModifier)
            {
                return(LiteralExpression.FromDouble(ParseReal()));
            }

            long integer = ParseInteger();

            // If the integer can be represented as Int32 we return
            // an Int32 literal. Otherwise we return an Int64.

            try
            {
                checked
                {
                    return(LiteralExpression.FromInt32((int)integer));
                }
            }
            catch (OverflowException)
            {
                return(LiteralExpression.FromInt64(integer));
            }
        }
예제 #2
0
        private static AlgebraNode AlgebrizeRecursiveCte(CommonTableBinding commonTableBinding)
        {
            // It is a recursive query.
            //
            // Create row buffer entry that is used to guard the recursion and the primary table spool
            // that spools the results needed by nested recursion calls.

            ExpressionBuilder            expressionBuilder = new ExpressionBuilder();
            StackedTableSpoolAlgebraNode primaryTableSpool = new StackedTableSpoolAlgebraNode();

            RowBufferEntry anchorRecursionLevel;

            RowBufferEntry[] anchorOutput;
            AlgebraNode      anchorNode;

            #region Anchor member
            {
                // Emit anchor member.

                AlgebraNode algebrizedAnchor = Convert(commonTableBinding.AnchorMember);

                // Emit compute scalar that initializes the recursion level to 0.

                anchorRecursionLevel = new RowBufferEntry(typeof(int));
                ComputedValueDefinition computedValueDefinition1 = new ComputedValueDefinition();
                computedValueDefinition1.Target     = anchorRecursionLevel;
                computedValueDefinition1.Expression = LiteralExpression.FromInt32(0);

                ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode();
                computeScalarAlgebraNode.Input         = algebrizedAnchor;
                computeScalarAlgebraNode.DefinedValues = new ComputedValueDefinition[] { computedValueDefinition1 };

                anchorOutput = algebrizedAnchor.OutputList;
                anchorNode   = computeScalarAlgebraNode;
            }
            #endregion

            RowBufferEntry   incrementedRecursionLevel;
            RowBufferEntry[] tableSpoolOutput;
            AlgebraNode      tableSpoolNode;

            #region Table spool
            {
                // Emit table spool reference.

                RowBufferEntry recursionLevelRefEntry = new RowBufferEntry(typeof(int));
                tableSpoolOutput = new RowBufferEntry[anchorOutput.Length];
                for (int i = 0; i < tableSpoolOutput.Length; i++)
                {
                    tableSpoolOutput[i] = new RowBufferEntry(anchorOutput[i].DataType);
                }

                StackedTableSpoolRefAlgebraNode tableSpoolReference = new StackedTableSpoolRefAlgebraNode();
                tableSpoolReference.PrimarySpool  = primaryTableSpool;
                tableSpoolReference.DefinedValues = ArrayHelpers.JoinArrays(new RowBufferEntry[] { recursionLevelRefEntry }, tableSpoolOutput);

                // Emit compute scalar that increases the recursion level by one and renames
                // columns from the spool to the CTE column buffer entries.

                expressionBuilder.Push(new RowBufferEntryExpression(recursionLevelRefEntry));
                expressionBuilder.Push(LiteralExpression.FromInt32(1));
                expressionBuilder.PushBinary(BinaryOperator.Add);

                incrementedRecursionLevel = new RowBufferEntry(typeof(int));
                ComputedValueDefinition incremenedRecLevelValueDefinition = new ComputedValueDefinition();
                incremenedRecLevelValueDefinition.Target     = incrementedRecursionLevel;
                incremenedRecLevelValueDefinition.Expression = expressionBuilder.Pop();

                CteColumnMappingFinder cteColumnMappingFinder = new CteColumnMappingFinder(commonTableBinding, tableSpoolOutput);
                foreach (QueryNode recursiveMember in commonTableBinding.RecursiveMembers)
                {
                    cteColumnMappingFinder.Visit(recursiveMember);
                }

                CteColumnMapping[] cteColumnMappings = cteColumnMappingFinder.GetMappings();

                List <ComputedValueDefinition> definedValues = new List <ComputedValueDefinition>();
                definedValues.Add(incremenedRecLevelValueDefinition);
                foreach (CteColumnMapping cteColumnMapping in cteColumnMappings)
                {
                    ComputedValueDefinition definedValue = new ComputedValueDefinition();
                    definedValue.Target     = cteColumnMapping.VirtualBufferEntry;
                    definedValue.Expression = new RowBufferEntryExpression(cteColumnMapping.SpoolBufferEntry);
                    definedValues.Add(definedValue);
                }

                ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode();
                computeScalarAlgebraNode.Input         = tableSpoolReference;
                computeScalarAlgebraNode.DefinedValues = definedValues.ToArray();

                tableSpoolNode = computeScalarAlgebraNode;
            }
            #endregion

            RowBufferEntry[] recursiveOutput;
            AlgebraNode      recursiveNode;

            #region Recursive member(s)
            {
                // Emit all recursive parts. The join conditions to the recursive part are replaced by simple filters
                // in the nested Convert() call.

                ConcatAlgebraNode concatAlgebraNode = new ConcatAlgebraNode();
                concatAlgebraNode.Inputs = new AlgebraNode[commonTableBinding.RecursiveMembers.Length];
                for (int i = 0; i < commonTableBinding.RecursiveMembers.Length; i++)
                {
                    concatAlgebraNode.Inputs[i] = Convert(commonTableBinding, commonTableBinding.RecursiveMembers[i]);
                }

                concatAlgebraNode.DefinedValues = new UnitedValueDefinition[anchorOutput.Length];
                for (int i = 0; i < anchorOutput.Length; i++)
                {
                    List <RowBufferEntry> dependencies = new List <RowBufferEntry>();
                    foreach (ResultAlgebraNode algebrizedRecursivePart in concatAlgebraNode.Inputs)
                    {
                        dependencies.Add(algebrizedRecursivePart.OutputList[i]);
                    }

                    concatAlgebraNode.DefinedValues[i]                  = new UnitedValueDefinition();
                    concatAlgebraNode.DefinedValues[i].Target           = new RowBufferEntry(anchorOutput[i].DataType);
                    concatAlgebraNode.DefinedValues[i].DependendEntries = dependencies.ToArray();
                }

                // Calculate the recursive output.

                recursiveOutput = new RowBufferEntry[concatAlgebraNode.DefinedValues.Length];
                for (int i = 0; i < concatAlgebraNode.DefinedValues.Length; i++)
                {
                    recursiveOutput[i] = concatAlgebraNode.DefinedValues[i].Target;
                }

                // Emit cross join

                JoinAlgebraNode crossJoinNode = new JoinAlgebraNode();
                crossJoinNode.Left  = tableSpoolNode;
                crossJoinNode.Right = concatAlgebraNode;

                // Emit assert that ensures that the recursion level is <= 100.

                expressionBuilder.Push(new RowBufferEntryExpression(incrementedRecursionLevel));
                expressionBuilder.Push(LiteralExpression.FromInt32(100));
                expressionBuilder.PushBinary(BinaryOperator.Greater);

                CaseExpression caseExpression = new CaseExpression();
                caseExpression.WhenExpressions    = new ExpressionNode[1];
                caseExpression.WhenExpressions[0] = expressionBuilder.Pop();
                caseExpression.ThenExpressions    = new ExpressionNode[1];
                caseExpression.ThenExpressions[0] = LiteralExpression.FromInt32(0);

                AssertAlgebraNode assertAlgebraNode = new AssertAlgebraNode();
                assertAlgebraNode.Input         = crossJoinNode;
                assertAlgebraNode.AssertionType = AssertionType.BelowRecursionLimit;
                assertAlgebraNode.Predicate     = caseExpression;

                recursiveNode = assertAlgebraNode;
            }
            #endregion

            RowBufferEntry[] algebrizedOutput;
            AlgebraNode      algebrizedCte;

            #region Combination
            {
                // Create concat node to combine anchor and recursive part.

                ConcatAlgebraNode concatAlgebraNode = new ConcatAlgebraNode();
                concatAlgebraNode.Inputs    = new AlgebraNode[2];
                concatAlgebraNode.Inputs[0] = anchorNode;
                concatAlgebraNode.Inputs[1] = recursiveNode;

                concatAlgebraNode.DefinedValues                     = new UnitedValueDefinition[anchorOutput.Length + 1];
                concatAlgebraNode.DefinedValues[0]                  = new UnitedValueDefinition();
                concatAlgebraNode.DefinedValues[0].Target           = new RowBufferEntry(anchorRecursionLevel.DataType);
                concatAlgebraNode.DefinedValues[0].DependendEntries = new RowBufferEntry[] { anchorRecursionLevel, incrementedRecursionLevel };

                for (int i = 0; i < anchorOutput.Length; i++)
                {
                    concatAlgebraNode.DefinedValues[i + 1]                  = new UnitedValueDefinition();
                    concatAlgebraNode.DefinedValues[i + 1].Target           = new RowBufferEntry(anchorOutput[i].DataType);
                    concatAlgebraNode.DefinedValues[i + 1].DependendEntries = new RowBufferEntry[] { anchorOutput[i], recursiveOutput[i] };
                }

                algebrizedOutput = new RowBufferEntry[concatAlgebraNode.DefinedValues.Length];
                for (int i = 0; i < concatAlgebraNode.DefinedValues.Length; i++)
                {
                    algebrizedOutput[i] = concatAlgebraNode.DefinedValues[i].Target;
                }

                // Assign the combination as the input to the primray spool

                primaryTableSpool.Input = concatAlgebraNode;

                // The primary spool represents the result of the "inlined" CTE.

                algebrizedCte = primaryTableSpool;
            }
            #endregion

            algebrizedCte.OutputList = algebrizedOutput;
            return(algebrizedCte);
        }
예제 #3
0
        private static ResultAlgebraNode CreateAssertedSubquery(ResultAlgebraNode inputNode)
        {
            if (AstUtil.WillProduceAtMostOneRow(inputNode))
            {
                return(inputNode);
            }

            RowBufferEntry inputEntry = inputNode.OutputList[0];

            AggregatedValueDefinition countDefinedValue = new AggregatedValueDefinition();

            countDefinedValue.Aggregate  = new CountAggregateBinding("COUNT");
            countDefinedValue.Aggregator = countDefinedValue.Aggregate.CreateAggregator(typeof(int));
            countDefinedValue.Argument   = LiteralExpression.FromInt32(0);

            RowBufferEntry countDefinedValueEntry = new RowBufferEntry(countDefinedValue.Aggregator.ReturnType);

            countDefinedValue.Target = countDefinedValueEntry;

            RowBufferEntryExpression anyAggregateArgument = new RowBufferEntryExpression();

            anyAggregateArgument.RowBufferEntry = inputEntry;

            AggregatedValueDefinition anyDefinedValue = new AggregatedValueDefinition();

            anyDefinedValue.Aggregate  = new FirstAggregateBinding("ANY");
            anyDefinedValue.Aggregator = anyDefinedValue.Aggregate.CreateAggregator(inputEntry.DataType);
            anyDefinedValue.Argument   = anyAggregateArgument;

            RowBufferEntry anyDefinedValueEntry = new RowBufferEntry(inputEntry.DataType);

            anyDefinedValue.Target = anyDefinedValueEntry;

            AggregateAlgebraNode aggregateAlgebraNode = new AggregateAlgebraNode();

            aggregateAlgebraNode.Input         = inputNode.Input;
            aggregateAlgebraNode.DefinedValues = new AggregatedValueDefinition[] { countDefinedValue, anyDefinedValue };

            // CASE WHEN SubqueryCount > 1 THEN 0 ELSE NULL END

            ExpressionBuilder expressionBuilder = new ExpressionBuilder();

            expressionBuilder.Push(new RowBufferEntryExpression(countDefinedValueEntry));
            expressionBuilder.Push(LiteralExpression.FromInt32(1));
            expressionBuilder.PushBinary(BinaryOperator.Greater);
            ExpressionNode whenExpression = expressionBuilder.Pop();
            ExpressionNode thenExpression = LiteralExpression.FromInt32(0);

            CaseExpression caseExpression = new CaseExpression();

            caseExpression.WhenExpressions = new ExpressionNode[] { whenExpression };
            caseExpression.ThenExpressions = new ExpressionNode[] { thenExpression };

            expressionBuilder.Push(caseExpression);
            ExpressionNode predicate = expressionBuilder.Pop();

            AssertAlgebraNode assertAlgebraNode = new AssertAlgebraNode();

            assertAlgebraNode.Input         = aggregateAlgebraNode;
            assertAlgebraNode.Predicate     = predicate;
            assertAlgebraNode.AssertionType = AssertionType.MaxOneRow;

            ResultAlgebraNode resultAlgebraNode = new ResultAlgebraNode();

            resultAlgebraNode.Input       = assertAlgebraNode;
            resultAlgebraNode.OutputList  = new RowBufferEntry[] { anyDefinedValueEntry };
            resultAlgebraNode.ColumnNames = inputNode.ColumnNames;

            return(resultAlgebraNode);
        }