예제 #1
0
        /// <summary>
        /// Visits an aggregation node.
        /// Creates a new aggregation function based on the provided name.
        /// And initilises parsing of the aggregation argument.
        /// </summary>
        public void Visit(AggregateFuncNode node)
        {
            Aggregate aggregate = null;
            Type      aggType   = null;

            if (node.next == null)
            {
                throw new ArgumentException($"{this.GetType()}, exprected aggregation arguments.");
            }
            else
            {
                // count(*)
                if (node.next.GetType() == typeof(IdentifierNode))
                {
                    if (node.funcName.ToLower() == "count" && ((IdentifierNode)node.next).value == "*")
                    {
                        aggregate = Aggregate.Factory("count", typeof(int), null);
                        aggType   = typeof(int);
                    }
                    else
                    {
                        throw new ArgumentException($"{this.GetType()}, expected count(*).");
                    }
                }
                else
                {
                    // Every other aggregation.
                    // The only possibility is that the next node is VariableNode.
                    // So the argument will be created in this.Expr, from this expr the holder must be created.
                    // After the holder is created the aggregation is created with the expression.
                    // After this process, the expression that will be returned is created -> aggregation reference.
                    node.next.Accept(this);
                    var tmpHolder = new ExpressionHolder(this.expr);
                    aggregate = Aggregate.Factory(node.funcName.ToLower(), tmpHolder.ExpressionType, tmpHolder);
                    aggType   = tmpHolder.ExpressionType;
                }
            }

            // Rewrite the expression used for aggregation argument to aggregation reference.
            int aggPos = this.exprInfo.AddAggregate(aggregate);

            if (node.funcName.ToLower() == "avg")
            {
                this.expr = AggregateReferenceFactory.Create(typeof(double), aggPos, this.exprInfo.GroupByhashExprs.Count, this.exprInfo.Aggregates[aggPos]);
            }
            else if (node.funcName.ToLower() == "count")
            {
                this.expr = AggregateReferenceFactory.Create(typeof(int), aggPos, this.exprInfo.GroupByhashExprs.Count, this.exprInfo.Aggregates[aggPos]);
            }
            else if (node.funcName.ToLower() == "sum")
            {
                this.expr = AggregateReferenceFactory.Create(typeof(long), aggPos, this.exprInfo.GroupByhashExprs.Count, this.exprInfo.Aggregates[aggPos]);
            }
            else
            {
                this.expr = AggregateReferenceFactory.Create(aggType, aggPos, this.exprInfo.GroupByhashExprs.Count, this.exprInfo.Aggregates[aggPos]);
            }
        }
예제 #2
0
        /// <summary>
        /// AggregateFunc -> IDENTIFIER \( VarReference \)
        /// </summary>
        /// <param name="tokens"> Tokens to parse. </param>
        /// <param name="position"> A position of a token. </param>
        /// <returns> A non empty aggregate node. </returns>
        static private Node ParseAggregateFunc(ref int position, List <Token> tokens)
        {
            // FuncName (
            if (!((CheckToken(position, Token.TokenType.Identifier, tokens)) &&
                  (CheckToken(position + 1, Token.TokenType.LeftParen, tokens))))
            {
                return(null);
            }
            else
            {
                AggregateFuncNode aggregate = new AggregateFuncNode();
                // Save the name of the function.
                aggregate.funcName = tokens[position].strValue;
                // It must inc by 2 because it was +1 moves it to left parent and another +1 moves it to next token.
                position += 2;

                if (CheckToken(position, Token.TokenType.Asterix, tokens))
                {
                    if (aggregate.funcName.ToLower() != "count")
                    {
                        ThrowError("Expression parser", "Cannot call other aggregate functions with * except count.", position, tokens);
                    }
                    else
                    {
                        aggregate.next = new IdentifierNode("*");
                        position++;
                    }
                }
                else
                {
                    aggregate.next = ParseVarReference(ref position, tokens);
                }

                // )
                if (!CheckToken(position, Token.TokenType.RightParen, tokens))
                {
                    ThrowError("Expression parser", "Expected ) .", position, tokens);
                }
                else
                {
                    position++;
                }
                return(aggregate);
            }
        }
예제 #3
0
 public void Visit(AggregateFuncNode node)
 {
     throw new NotImplementedException();
 }