/// <summary> /// Factory method. /// </summary> /// <param name="type"> A type of the clause to build. </param> /// <param name="graph"> A graph to conduct computation on. </param> /// <param name="helper"> A helper that contains information about execution. </param> /// <param name="map"> A map of variables. </param> /// <param name="parseTree"> A parsed tree to create the clause from. </param> /// <param name="exprInfo"> A query expression information. </param> public static QueryObject Factory(Type type, Graph graph, QueryExecutionHelper helper, VariableMap map, Node parseTree, QueryExpressionInfo exprInfo) { if (type == typeof(SelectObject)) { return(new SelectObject(graph, map, helper, (SelectNode)parseTree, exprInfo)); } else if (type == typeof(MatchObject)) { return(new MatchObject(graph, map, helper, (MatchNode)parseTree, exprInfo)); } else if (type == typeof(MatchObjectStreamed)) { return(new MatchObjectStreamed(graph, map, helper, (MatchNode)parseTree, exprInfo)); } else if (type == typeof(OrderByObject)) { return(new OrderByObject(graph, map, helper, (OrderByNode)parseTree, exprInfo)); } else if (type == typeof(GroupByObject) && graph == null && map == null && parseTree == null) { return(new GroupByObject(helper, exprInfo)); } else if (type == typeof(GroupByObject)) { return(new GroupByObject(graph, map, helper, (GroupByNode)parseTree, exprInfo)); } else { throw new ArgumentException($"Query object factory, cannot create type {type}."); } }
/// <summary> /// Builds a streamed version of a query from an input. /// Cannot contain order by and group by simultaneously. /// Called by static create method. /// </summary> /// <param name="tokens"> An input query.</param> /// <param name="graph"> A graph to compute the query on.</param> /// <param name="threadCount"> Maximum number of threads available to use.</param> /// <param name="printer"> A printer to use. </param> /// <param name="formater"> A formater to use by printer. </param> /// <param name="verticesPerThread"> A number of vertices distributed to threads during parallel computation of the query.</param> /// <param name="fileName"> A file to store results into if set, otherwise null. </param> /// <param name="isStreamed"> A flag to distinguish a normal construtor from streamed constructor.</param> /// <param name="allowPrint"> Whether to allow printing. Mainly for benchmarking purposes.</param> /// <param name="fixedArraySize"> The size of the arrays used for storing results of the matcher.</param> /// <param name="grouperAlias"> A grouper to use when specifying group by.</param> /// <param name="sorterAlias"> A sorter to use when specifying order by.</param> private Query(List <Token> tokens, Graph graph, bool allowPrint, int threadCount, PrinterType printer, FormaterType formater, int verticesPerThread, string fileName, GrouperAlias grouperAlias, SorterAlias sorterAlias, int fixedArraySize, bool isStreamed) { this.graph = graph; this.variableMap = new VariableMap(); this.qEhelper = new QueryExecutionHelper(threadCount, printer, formater, verticesPerThread, fixedArraySize, fileName, "DFSParallelStreamed", "DFSSingleThreadStreamed", "SIMPLE", grouperAlias, sorterAlias); // Parse input query. var parsedClauses = Parser.Parse(tokens); if (parsedClauses.ContainsKey(Parser.Clause.OrderBy) && parsedClauses.ContainsKey(Parser.Clause.GroupBy)) { throw new ArgumentException($"{this.GetType()}, the streamed version of the query cannot contain group by and order by at the same time."); } // MATCH is always leaf. MatchObjectStreamed match = (MatchObjectStreamed)QueryObject.Factory (typeof(MatchObjectStreamed), graph, qEhelper, variableMap, parsedClauses[Parser.Clause.Match], null); // GROUP BY and obtain the aggregates and hashes -> the all necessary info is in the expressionInfo class. if (parsedClauses.ContainsKey(Parser.Clause.GroupBy)) { this.exprInfo = new QueryExpressionInfo(true); GroupByResultProcessor.ParseGroupBy(graph, variableMap, qEhelper, (GroupByNode)parsedClauses[Parser.Clause.GroupBy], exprInfo); } else { this.exprInfo = new QueryExpressionInfo(false); } // SELECT is the last one to process the resuls. this.query = QueryObject.Factory (typeof(SelectObject), graph, qEhelper, variableMap, parsedClauses[Parser.Clause.Select], exprInfo); ((SelectObject)this.query).allowPrint = allowPrint; SetSingleGroupFlags(); // ORDER BY if (parsedClauses.ContainsKey(Parser.Clause.OrderBy)) { var comps = OrderByResultProcessor.ParseOrderBy(graph, variableMap, qEhelper, (OrderByNode)parsedClauses[Parser.Clause.OrderBy], exprInfo, variableMap.GetCount()); var orderByProc = OrderByResultProcessor.Factory(this.exprInfo, comps, qEhelper, variableMap.GetCount(), this.exprInfo.CollectUsedVariables()); match.PassResultProcessor(orderByProc); } else { // Check if the query is aggregation and not a simple query. if ((this.exprInfo.Aggregates.Count == 0 && this.qEhelper.IsSetSingleGroupGroupBy) || (!this.qEhelper.IsSetSingleGroupGroupBy && !parsedClauses.ContainsKey(Parser.Clause.GroupBy))) { throw new ArgumentException($"{this.GetType()}, no grouping or sorting was specified. The Streamed version allows to compute only aggregations. If you want to use only patter matching, please change to mode Normal."); } var groupByProc = GroupByResultProcessor.Factory(exprInfo, qEhelper, variableMap.GetCount(), this.exprInfo.CollectUsedVariables(), isStreamed); match.PassResultProcessor(groupByProc); } query.AddToEnd(match); }
/// <summary> /// Builds a query from an input. /// Cannot contain order by and group by simultaneously. /// Called by static Create method. /// </summary> /// <param name="tokens"> An input query. </param> /// <param name="graph"> A graph to compute the query on. </param> /// <param name="threadCount"> Maximum number of threads available to use. </param> /// <param name="printer"> A printer to use. </param> /// <param name="formater"> A formater to use by printer. </param> /// <param name="verticesPerThread"> A number of vertices distributed to threads during parallel computation of the query.</param> /// <param name="fileName"> A file to store results into if set, otherwise null. </param> /// <param name="allowPrint"> Whether to allow printing. Mainly for benchmarking purposes.</param> /// <param name="fixedArraySize"> The size of the arrays used for storing results of the matcher.</param> /// <param name="grouperAlias"> A grouper to use when specifying group by.</param> /// <param name="sorterAlias"> A sorter to use when specifying order by.</param> private Query(List <Token> tokens, Graph graph, bool allowPrint, int threadCount, PrinterType printer, FormaterType formater, int verticesPerThread, string fileName, GrouperAlias grouperAlias, SorterAlias sorterAlias, int fixedArraySize) { this.graph = graph; this.variableMap = new VariableMap(); this.qEhelper = new QueryExecutionHelper(threadCount, printer, formater, verticesPerThread, fixedArraySize, fileName, "DFSParallel", "DFSSingleThread", "SIMPLE", grouperAlias, sorterAlias); // Parse input query. var parsedClauses = Parser.Parse(tokens); // Create execution chain. if (parsedClauses.ContainsKey(Parser.Clause.GroupBy) && parsedClauses.ContainsKey(Parser.Clause.OrderBy)) { throw new ArgumentException($"{this.GetType()}, the query cannot contain both order by and group by"); } QueryObject groupBy = null; QueryObject orderBy = null; // MATCH is always leaf. QueryObject match = QueryObject.Factory (typeof(MatchObject), graph, qEhelper, variableMap, parsedClauses[Parser.Clause.Match], null); // Second must be group by because it defines what can be in other clauses. // GROUP BY if (parsedClauses.ContainsKey(Parser.Clause.GroupBy)) { this.exprInfo = new QueryExpressionInfo(true); groupBy = QueryObject.Factory(typeof(GroupByObject), graph, qEhelper, variableMap, parsedClauses[Parser.Clause.GroupBy], exprInfo); } else { this.exprInfo = new QueryExpressionInfo(false); } // SELECT is the last one to process the resuls. this.query = QueryObject.Factory (typeof(SelectObject), graph, qEhelper, variableMap, parsedClauses[Parser.Clause.Select], exprInfo); ((SelectObject)this.query).allowPrint = allowPrint; // Check if the results are in a single group. this.SetSingleGroupFlags(); // ORDER BY if (parsedClauses.ContainsKey(Parser.Clause.OrderBy)) { orderBy = QueryObject.Factory(typeof(OrderByObject), graph, qEhelper, variableMap, parsedClauses[Parser.Clause.OrderBy], exprInfo); query.AddToEnd(orderBy); } // If the single group by is set, add GroupBy object to the execution chain. if (this.qEhelper.IsSetSingleGroupGroupBy && !this.qEhelper.IsSetGroupBy) { groupBy = QueryObject.Factory(typeof(GroupByObject), null, qEhelper, null, null, exprInfo); } if (groupBy != null) { query.AddToEnd(groupBy); } query.AddToEnd(match); query.PassStoringVariables(this.exprInfo.CollectUsedVariables()); }