private static void CheckNullExpression(ExpressionHolder expressionHolder) { if (expressionHolder == null || expressionHolder.Expr == null) { throw new ArgumentNullException($"Query expression info, cannot store null expressions."); } }
public Count(ExpressionHolder expressionHolder) : base(expressionHolder) { if (expressionHolder == null) { this.IsAstCount = true; } }
/// <summary> /// Expects "Expression as label" /// Parses expression nodes and tries to get a label for the expression. /// At the end, it creates a expression holder. /// </summary> public void Visit(ExpressionNode node) { string label = null; ExpressionBase expr = null; // Parse expression. if (node.exp == null) { throw new ArgumentException($"{this.GetType()}, expected expression."); } else { var tmpVisitor = new ExpressionVisitor(this.labels, this.variableMap, this.exprInfo); node.exp.Accept(tmpVisitor); expr = tmpVisitor.GetResult(); } // Try get a label for entire expression. if (node.asLabel != null) { label = ((IdentifierNode)(node.asLabel)).value; } this.expressionHolder = this.exprInfo.Exprs[this.exprInfo.AddOrderByComp(new ExpressionHolder(expr, label))]; }
/// <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]); } }
public ExpressionToStringWrapper(ExpressionHolder expressionHolder) { if (expressionHolder == null) { throw new ArgumentNullException($"{this.GetType()}, trying to assign null to a constructor."); } this.expressionHolder = expressionHolder; }
protected ExpressionHasher(ExpressionHolder expressionHolder) { if (expressionHolder == null) { throw new ArgumentNullException($"{this.GetType()}, trying to assign null to a constructor."); } this.expressionHolder = expressionHolder; }
public Aggregate(ExpressionHolder expressionHolder) { this.expressionHolder = expressionHolder; // The provided expressions are not stored in the expression info manager since // it stores the aggregates directly. if (this.expressionHolder != null) { this.expressionHolder.SetExprPosition(-1); } }
/// <summary> /// Select * case. That means that there are as many expressions as variables in the query. /// For each variable, expression that consists only of reference id will be created. /// It returns from here because there is no other node to visit. /// </summary> public void Visit(VariableNode node) { if (node.name == null || ((IdentifierNode)node.name).value != "*") { throw new ArgumentException($"{this.GetType()}, expected asterix."); } foreach (var item in variableMap) { var tmpExprHolder = new ExpressionHolder(new VariableIDReference(new VariableReferenceNameHolder(item.Key), item.Value.Item1), null); tmpExprHolder = this.exprInfo.Exprs[exprInfo.AddExpression(tmpExprHolder)]; this.result.Add(ExpressionToStringWrapper.Factory(tmpExprHolder, tmpExprHolder.ExpressionType)); } }
public static BucketKeyFactory Factory(ExpressionHolder expressionHolder) { if (expressionHolder.ExpressionType == typeof(int)) { return(new BucketKeyFactory <int>(expressionHolder)); } else if (expressionHolder.ExpressionType == typeof(string)) { return(new BucketKeyFactory <string>(expressionHolder)); } else { throw new ArgumentException($"Bucket key factory, unknown type of bucket factory. Type = {expressionHolder.ExpressionType}."); } }
public ABTreeStreamedSorter(ExpressionComparer[] comparers, IOrderByExecutionHelper executionHelper, int columnCount, int[] usedVars, bool allowDup) : base(comparers, executionHelper, columnCount, usedVars) { this.firstKeyHasher = (TypeRangeHasher <T>)TypeRangeHasher.Factory(this.executionHelper.ThreadCount, typeof(T)); this.firstKeyExpressionHolder = this.comparers[0].GetExpressionHolder(); this.firstKeyExpression = (ExpressionReturnValue <T>) this.firstKeyExpressionHolder.Expr; this.rangeBuckets = new RangeBucket[this.firstKeyHasher.BucketCount]; this.firstKeyComparers = new ExpressionComparer <T> [this.rangeBuckets.Length]; for (int i = 0; i < this.rangeBuckets.Length; i++) { var results = new TableResults(this.ColumnCount, this.executionHelper.FixedArraySize, this.usedVars); var tmpRowComparer = RowComparer.Factory(this.comparers, true); this.firstKeyComparers[i] = (ExpressionComparer <T>)tmpRowComparer.comparers[0]; this.rangeBuckets[i] = CreateBucket(new IndexToRowProxyComparer(tmpRowComparer, results, allowDup), results); } }
/// <summary> /// Constructs an expression comparer. /// </summary> /// <param name="expressionHolder"> An expression to be evaluated during comparing. </param> /// <param name="ascending"> Whether to use asc or desc order. </param> /// <param name="cacheResults"> Whether to cache results of the computed expressions. </param> protected ExpressionComparer(ExpressionHolder expressionHolder, bool ascending, bool cacheResults) { if (expressionHolder == null) { throw new ArgumentException($"{this.GetType()}, trying to assign null to a constructor."); } this.expressionHolder = expressionHolder; this.isAscending = ascending; this.cacheResults = cacheResults; var tmp = new List <int>(); expressionHolder.CollectUsedVars(ref tmp); this.usedVars = tmp.ToArray(); }
/// <summary> /// Tried to insert an expression to the general expr. list. /// </summary> /// <param name="expressionHolder"> An expression to add to the general expr. list. </param> /// <returns> If the main expression list contains the expression, return its position. Otherwise add the expression and return its new position. </returns> private int InsertExpr(ExpressionHolder expressionHolder) { CheckNullExpression(expressionHolder); int position = -1; if ((position = this.Exprs.IndexOf(expressionHolder)) != -1) { return(position); } else { this.Exprs.Add(expressionHolder); expressionHolder.SetExprPosition(this.Exprs.Count - 1); return(this.Exprs.Count - 1); } }
/// <summary> /// Adds a hash expression for group by. /// Cannot contain aggregations. /// Each hash can be added only once. /// Note that this method is called only when the group by keys are created. /// Thus, hashes and expr have the same count. /// </summary> /// <param name="expressionHolder"> An expression to hash with. </param> /// <returns> Returns a position of the passed expression in the main expression list. </returns> public int AddGroupByHash(ExpressionHolder expressionHolder) { CheckNullExpression(expressionHolder); if (expressionHolder.ContainsAggregate()) { throw new ArgumentException($"{this.GetType()}, group by clause cannot contain aggregates."); } else if (this.GroupByhashExprs.Contains(expressionHolder)) { throw new ArgumentException($"{this.GetType()}, group by clause cannot contain the same key multiple times."); } else { var pos = InsertExpr(expressionHolder); this.GroupByhashExprs.Add(this.Exprs[pos]); return(pos); } }
/// <summary> /// Adds a expression for order by. /// Cannot contain multiple occurrences of the same expression. /// </summary> /// <param name="expressionHolder"> An expression to sort with. </param> /// <returns> Returns a position of the passed expression in the main expression list. </returns> public int AddOrderByComp(ExpressionHolder expressionHolder) { CheckNullExpression(expressionHolder); if (this.OrderByComparerExprs.Contains(expressionHolder)) { throw new ArgumentException($"{this.GetType()}, order by clause cannot contain the same comparer expression multiple times."); } else if (expressionHolder.ContainsAggregate()) { throw new ArgumentException($"{this.GetType()}, order by clause cannot contain aggregates."); } else { var pos = InsertExpr(expressionHolder); this.OrderByComparerExprs.Add(this.Exprs[pos]); return(pos); } }
/// <summary> /// Creates an aggregate that is bound with the array type results. /// </summary> /// <param name="funcName"> A name of the aggregate function. </param> /// <param name="compType"> A return type of the aggregate function. </param> /// <param name="holder"> An expression to compute values with for the aggregate.</param> public static Aggregate Factory(string funcName, Type compType, ExpressionHolder holder = null) { if (funcName == "count" && compType == typeof(int)) { return(new Count <int>(holder)); } else if (funcName == "count" && compType == typeof(string)) { return(new Count <string>(holder)); } else if (funcName == "max" && compType == typeof(int)) { return(new IntMax(holder)); } else if (funcName == "max" && compType == typeof(string)) { return(new StrMax(holder)); } else if (funcName == "min" && compType == typeof(int)) { return(new IntMin(holder)); } else if (funcName == "min" && compType == typeof(string)) { return(new StrMin(holder)); } else if (funcName == "avg" && compType == typeof(int)) { return(new IntAvg(holder)); } else if (funcName == "sum" && compType == typeof(int)) { return(new IntSum(holder)); } else { throw new ArgumentException($"Aggregate factory, trying to create a non existent array bound aggregate. {funcName}, {compType}"); } }
/// <summary> /// Checks whether an expression (no aggregation) is valid, in terms of grouping expressions. /// That is to say, if the group by is set, the clause provides expressions to group the results with. /// This function should check, whether the expressions in other clauses are the same as in the grouping exp. /// Because, only the same expressions can be referenced throughout the query + aggregates. /// /// If no group by is set and aggregation is referenced, then only aggregations can be referenced in the entire query -> single group group by. /// /// This function is very simplified becuase expressions contain only one block. /// Thus, it must be reimplemented in the future. /// So far called only from Select clause parser. /// </summary> /// <param name="expressionHolder"> An expression. </param> /// <returns> Returns a position of the passed expression in the main expression list. </returns> public int AddExpression(ExpressionHolder expressionHolder) { CheckNullExpression(expressionHolder); // Only expressions from group by clause and aggregates can be used. if (this.IsSetGroupBy) { // Aggregates in expressions can be referenced freely if (!expressionHolder.ContainsAggregate()) { // There can be referenced only expressions from group by. if (this.GroupByhashExprs.IndexOf(expressionHolder) == -1) { throw new ArgumentException($"{this.GetType()}, expression in the query can contain only references from group by clause."); } else { return(this.Exprs.IndexOf(expressionHolder)); } // The check is not done, because the aggregate reference is create at the same time as the corresponding aggregate. } else { return(InsertExpr(expressionHolder)); } } else { // No group by is set. if ((expressionHolder.ContainsAggregate() && ContainsSimpleExpr()) || (!expressionHolder.ContainsAggregate() && this.Aggregates.Count > 0)) { throw new ArgumentException($"{this.GetType()}, there was references an aggregate and a simple expression while group by is not set."); } else { return(InsertExpr(expressionHolder)); } } }
public IntAvg(ExpressionHolder expressionHolder) : base(expressionHolder) { }
public IntSum(ExpressionHolder expressionHolder) : base(expressionHolder) { }
public MinMaxBase(ExpressionHolder expressionHolder) : base(expressionHolder) { }