public GroupByVisitor(Dictionary <string, Tuple <int, Type> > labels, VariableMap map, QueryExpressionInfo exprInfo) { this.holders = new List <ExpressionHolder>(); this.labels = labels; this.variableMap = map; this.exprInfo = exprInfo; }
/// <summary> /// Constructs Group by result processor. /// The suffix HS stands for Half Streamed solution, whereas the S stands for Full Streamed solution. /// The additional suffices B and L stand for the type of result storages. B is for buckets and L is for Lists. /// </summary> public static ResultProcessor Factory(QueryExpressionInfo expressionInfo, IGroupByExecutionHelper executionHelper, int columnCount, int[] usedVars, bool isStreamed) { if (executionHelper.IsSetSingleGroupGroupBy) { if (!isStreamed) { return(new SingleGroupGroupByHalfStreamed(expressionInfo, executionHelper, columnCount, usedVars)); } else { return(new SingleGroupGroupByStreamed(expressionInfo, executionHelper, columnCount, usedVars)); } } else { if (executionHelper.GrouperAlias == GrouperAlias.GlobalS) { return(new GlobalGroupByStreamed(expressionInfo, executionHelper, columnCount, usedVars)); } else if (executionHelper.GrouperAlias == GrouperAlias.TwoStepHSB) { return(new TwoStepHalfStreamedBucket(expressionInfo, executionHelper, columnCount, usedVars)); } else if (executionHelper.GrouperAlias == GrouperAlias.TwoStepHSL) { return(new TwoStepHalfStreamedListBucket(expressionInfo, executionHelper, columnCount, usedVars)); } else { throw new ArgumentException("Group by result processor, trying to create an unknown grouper."); } } }
public SelectVisitor(Dictionary <string, Tuple <int, Type> > labels, VariableMap map, QueryExpressionInfo exprInfo) { this.result = new List <ExpressionToStringWrapper>(); this.labels = labels; this.variableMap = map; this.exprInfo = exprInfo; }
public OrderByVisitor(Dictionary <string, Tuple <int, Type> > labels, VariableMap map, QueryExpressionInfo exprInfo) { this.result = new List <ExpressionComparer>(); this.labels = labels; this.variableMap = map; this.exprInfo = exprInfo; }
protected GroupByResultProcessor(QueryExpressionInfo expressionInfo, IGroupByExecutionHelper executionHelper, int columnCount, int[] usedVars) { this.aggregates = expressionInfo.Aggregates.ToArray(); this.hashes = expressionInfo.GroupByhashExprs.ToArray(); this.executionHelper = executionHelper; this.ColumnCount = columnCount; this.usedVars = usedVars; }
public SingleGroupGroupByStreamed(QueryExpressionInfo expressionInfo, IGroupByExecutionHelper executionHelper, int columnCount, int[] usedVars) : base(expressionInfo, executionHelper, columnCount, usedVars) { this.finalResults = AggregateBucketResult.CreateBucketResults(this.aggregates); Aggregate.ExtractNonAstAggsAndResults(this.aggregates, this.finalResults, out nonAsterixAggregates, out nonAsterixResults); if (this.finalResults.Length != this.nonAsterixResults.Length) { this.containsAst = true; } }
/// <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> /// Creates a group by object for a single group group by (not defined group by clause but only aggregations in select). /// Assumes that the executionHelper.IsSetSingleGroupGroupBy is set to true. /// </summary> /// <param name="executionHelper"> A group by execution helper. </param> /// <param name="exprInfo"> A query expression information. </param> public GroupByObject(IGroupByExecutionHelper executionHelper, QueryExpressionInfo exprInfo) { if (executionHelper == null || exprInfo == null) { throw new ArgumentNullException($"{this.GetType()}, passing null arguments to the constructor."); } this.aggregates = exprInfo.Aggregates; this.helper = executionHelper; }
public SingleGroupGroupByHalfStreamed(QueryExpressionInfo expressionInfo, IGroupByExecutionHelper helper, int columnCount, int[] usedVars) : base(expressionInfo, helper, columnCount, usedVars) { this.matcherNonAsterixResults = new AggregateBucketResult[this.executionHelper.ThreadCount][]; this.finalResults = AggregateBucketResult.CreateBucketResults(this.aggregates); Aggregate.ExtractNonAstAggsAndResults(this.aggregates, this.finalResults, out nonAsterixAggregates, out finalNonAsterixResults); if (this.finalResults.Length != this.finalNonAsterixResults.Length) { this.containsAst = true; } this.numberOfMatchedElements = new int[this.executionHelper.ThreadCount]; for (int i = 0; i < this.matcherNonAsterixResults.Length; i++) { this.matcherNonAsterixResults[i] = AggregateBucketResult.CreateBucketResults(this.nonAsterixAggregates); } }
/// <summary> /// Constructs Order by result processor. /// The suffix HS stands for Half Streamed solution, whereas the S stands for Full Streamed solution. /// </summary> public static ResultProcessor Factory(QueryExpressionInfo exprInfo, ExpressionComparer[] comparers, IOrderByExecutionHelper executionHelper, int columnCount, int[] usedVars) { if (executionHelper.SorterAlias == SorterAlias.AbtreeHS) { return(new ABTreeGenSorterHalfStreamed(comparers, executionHelper, columnCount, usedVars)); } else if (executionHelper.SorterAlias == SorterAlias.AbtreeAccumHS) { return(new ABTreeAccumSorterHalfStreamed(comparers, executionHelper, columnCount, usedVars)); } else if (executionHelper.SorterAlias == SorterAlias.AbtreeS) { var typeOfFirstKey = exprInfo.OrderByComparerExprs[0].GetExpressionType(); if (typeOfFirstKey == typeof(int)) { return(new ABTreeGenSorterStreamed <int>(comparers, executionHelper, columnCount, usedVars)); } else if (typeOfFirstKey == typeof(string)) { return(new ABTreeGenSorterStreamed <string>(comparers, executionHelper, columnCount, usedVars)); } else { throw new ArgumentException($"Order by result processor factory, trying to create an unknown type of the streamed sorted."); } } else if (executionHelper.SorterAlias == SorterAlias.AbtreeAccumS) { var typeOfFirstKey = exprInfo.OrderByComparerExprs[0].GetExpressionType(); if (typeOfFirstKey == typeof(int)) { return(new ABTreeAccumSorterStreamed <int>(comparers, executionHelper, columnCount, usedVars)); } else if (typeOfFirstKey == typeof(string)) { return(new ABTreeAccumSorterStreamed <string>(comparers, executionHelper, columnCount, usedVars)); } else { throw new ArgumentException($"Order by result processor factory, trying to create an unknown type of the streamed sorted."); } } else { throw new ArgumentException($"Order by result processor factory, trying to create an unknown sorter."); } }
public GlobalGroupByStreamed(QueryExpressionInfo expressionInfo, IGroupByExecutionHelper executionHelper, int columnCount, int[] usedVars) : base(expressionInfo, executionHelper, columnCount, usedVars) { this.matcherBucketFactories = new BucketsKeyValueFactory[this.executionHelper.ThreadCount]; for (int i = 0; i < this.executionHelper.ThreadCount; i++) { this.matcherBucketFactories[i] = new BucketsKeyValueFactory(this.aggregates, this.hashes); } var comparer = new RowEqualityComparerAggregateBucketResult(this.hashes.Length, this.hashes); if (this.executionHelper.InParallel) { this.parGroups = new ConcurrentDictionary <AggregateBucketResult[], AggregateBucketResult[]>(comparer); } else { this.stGroups = new Dictionary <AggregateBucketResult[], AggregateBucketResult[]>(comparer); } }
public TwoStepHalfStreamedBucket(QueryExpressionInfo expressionInfo, IGroupByExecutionHelper executionHelper, int columnCount, int[] usedVars) : base(expressionInfo, executionHelper, columnCount, usedVars) { this.groupJobs = new GroupJob[this.executionHelper.ThreadCount]; // Create an initial job, comparers and hashers this.CreateHashersAndComparers(out ExpressionComparer[] comparers, out ExpressionHasher[] hashers); var firstComp = RowEqualityComparerGroupKey.Factory(null, comparers, true); var firstHasher = new RowHasher(hashers); firstHasher.SetCache(firstComp.comparers); this.groupJobs[0] = new GroupJob(firstComp, firstHasher, new TableResults(this.ColumnCount, this.executionHelper.FixedArraySize, this.usedVars)); for (int i = 1; i < this.executionHelper.ThreadCount; i++) { CloneHasherAndComparer(firstComp, firstHasher, out RowEqualityComparerGroupKey newComp, out RowHasher newHasher); groupJobs[i] = new GroupJob(newComp, newHasher, new TableResults(this.ColumnCount, this.executionHelper.FixedArraySize, this.usedVars)); } this.globalGroups = new ConcurrentDictionary <GroupDictKeyFull, AggregateBucketResult[]>(RowEqualityComparerGroupDickKeyFull.Factory(comparers, false)); }
/// <summary> /// Creates Streamed Match object. /// </summary> /// <param name="graph"> Graph to conduct a query on. </param> /// <param name="variableMap"> Empty map of variables. </param> /// <param name="executionHelper"> Match execution helper. </param> /// <param name="matchNode"> Parse tree of match expression. </param> /// <param name="exprInfo"> A query expression information. </param> public MatchObjectStreamed(Graph graph, VariableMap variableMap, IMatchExecutionHelper executionHelper, MatchNode matchNode, QueryExpressionInfo exprInfo) { if (executionHelper == null || matchNode == null || variableMap == null || graph == null) { throw new ArgumentNullException($"{this.GetType()}, passing null arguments to the constructor."); } this.helper = executionHelper; MatchVisitor matchVisitor = new MatchVisitor(graph.nodeTables, graph.edgeTables); matchNode.Accept(matchVisitor); //Create real pattern and variableMap var result = matchVisitor.GetResult(); this.CheckParsedPatternCorrectness(result); // Create matcher and pattern based on the name of matcher and pattern // Change if necessary this.pattern = MatchFactory.CreatePattern(helper.ParallelPatternMatcherName, helper.PatternName, variableMap, result); this.matcher = (IPatternMatcherStreamed)MatchFactory.CreateMatcher(helper.ParallelPatternMatcherName, pattern, graph, executionHelper); }
/// <summary> /// Creates an order by object. /// </summary> /// <param name="graph"> A graph the query is computed on. </param> /// <param name="variableMap"> A map of query variables. </param> /// <param name="executionHelper"> An order by execution helper. </param> /// <param name="orderByNode"> A parse tree of order by expression. </param> /// <param name="exprInfo"> A query expression information. </param> public OrderByObject(Graph graph, VariableMap variableMap, IOrderByExecutionHelper executionHelper, OrderByNode orderByNode, QueryExpressionInfo exprInfo) { if (executionHelper == null || orderByNode == null || variableMap == null || graph == null || exprInfo == null) { throw new ArgumentNullException($"{this.GetType()}, passing null arguments to the constructor."); } this.helper = executionHelper; var orderByVisitor = new OrderByVisitor(graph.labels, variableMap, exprInfo); orderByVisitor.Visit(orderByNode); var comps = orderByVisitor.GetResult(); executionHelper.IsSetOrderBy = true; this.comparers = comps.ToArray(); }
/// <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()); }
public ExpressionVisitor(Dictionary <string, Tuple <int, Type> > labels, VariableMap map, QueryExpressionInfo exprInfo) { this.variableMap = map; this.labels = labels; this.exprInfo = exprInfo; }
/// <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}."); } }
public static ExpressionComparer[] ParseOrderBy(Graph graph, VariableMap variableMap, IOrderByExecutionHelper executionHelper, OrderByNode orderByNode, QueryExpressionInfo exprInfo, int columnCount) { if (executionHelper == null || orderByNode == null || variableMap == null || graph == null || exprInfo == null) { throw new ArgumentNullException($"Order by result processor, passing null arguments to the constructor."); } var orderByVisitor = new OrderByVisitor(graph.labels, variableMap, exprInfo); orderByVisitor.Visit(orderByNode); var comps = orderByVisitor.GetResult(); executionHelper.IsSetOrderBy = true; return(comps.ToArray()); }
/// <summary> /// Parses Group by parse tree, the information is stored in the expression info class. /// The reason this method is separated from constructor is because it cannot guess whether the /// clause is a normal group by or a single group group by, thus the group by must always be parsed /// as the first clause after the Match clause. /// </summary> public static void ParseGroupBy(Graph graph, VariableMap variableMap, IGroupByExecutionHelper executionHelper, GroupByNode groupByNode, QueryExpressionInfo exprInfo) { if (executionHelper == null || groupByNode == null || variableMap == null || graph == null || exprInfo == null) { throw new ArgumentNullException($"Group by results processor, passing null arguments to the constructor."); } var groupbyVisitor = new GroupByVisitor(graph.labels, variableMap, exprInfo); groupbyVisitor.Visit(groupByNode); executionHelper.IsSetGroupBy = true; }
/// <summary> /// Creates a Match object. /// </summary> /// <param name="graph"> A graph to conduct a query on. </param> /// <param name="variableMap"> An empty map of variables. </param> /// <param name="executionHelper"> A match execution helper. </param> /// <param name="matchNode"> A parse tree of match expression. </param> /// <param name="exprInfo"> A query expression information. </param> public MatchObject(Graph graph, VariableMap variableMap, IMatchExecutionHelper executionHelper, MatchNode matchNode, QueryExpressionInfo exprInfo) { if (executionHelper == null || matchNode == null || variableMap == null || graph == null) { throw new ArgumentNullException($"{this.GetType()}, passing null arguments to the constructor."); } this.helper = executionHelper; MatchVisitor matchVisitor = new MatchVisitor(graph.nodeTables, graph.edgeTables); matchNode.Accept(matchVisitor); // Create real pattern and variableMap. var result = matchVisitor.GetResult(); this.CheckParsedPatternCorrectness(result); // Create matcher and pattern based on the name of matcher and pattern. // Change if necessary . this.pattern = MatchFactory.CreatePattern(helper.ParallelPatternMatcherName, helper.PatternName, variableMap, result); // Now we have got enough information about results. // After creating pattern the variable map is filled and we know extend of the results. this.queryResults = new MatchFixedResults(this.helper.FixedArraySize, variableMap.GetCount(), executionHelper.ThreadCount); this.matcher = MatchFactory.CreateMatcher(helper.ParallelPatternMatcherName, pattern, graph, this.queryResults, executionHelper); }
/// <summary> /// Creates a group by object for multigroup group by (defined group by clause). /// </summary> /// <param name="graph"> A property graph. </param> /// <param name="variableMap"> A variable map. </param> /// <param name="executionHelper"> A group by execution helper. </param> /// <param name="groupByNode"> A parsed tree of group by expression. </param> /// <param name="exprInfo"> A query expression information. </param> public GroupByObject(Graph graph, VariableMap variableMap, IGroupByExecutionHelper executionHelper, GroupByNode groupByNode, QueryExpressionInfo exprInfo) { if (executionHelper == null || groupByNode == null || variableMap == null || graph == null || exprInfo == null) { throw new ArgumentNullException($"{this.GetType()}, passing null arguments to the constructor."); } this.helper = executionHelper; var groupbyVisitor = new GroupByVisitor(graph.labels, variableMap, exprInfo); groupbyVisitor.Visit(groupByNode); this.hashes = groupbyVisitor.GetResult().ToArray(); this.aggregates = exprInfo.Aggregates; this.helper.IsSetGroupBy = true; }
/// <summary> /// Creates a Select object. /// Parsing is done beforehand because first we need to parse match expression for variable definitions. /// </summary> /// <param name="graph"> A property graph. </param> /// <param name="map"> A variable map. </param> /// <param name="executionHelper"> A select execution helper. </param> /// <param name="selectNode"> A parsed tree of select expression. </param> /// <param name="exprInfo"> A query expression information. </param> public SelectObject(Graph graph, VariableMap map, ISelectExecutionHelper executionHelper, SelectNode selectNode, QueryExpressionInfo exprInfo) { if (executionHelper == null || selectNode == null || exprInfo == null) { throw new ArgumentNullException($"{this.GetType()}, passing null arguments to constructor. "); } this.helper = executionHelper; // Process the parse tree and creates a List of expression to be printed. SelectVisitor visitor = new SelectVisitor(graph.labels, map, exprInfo); selectNode.Accept(visitor); this.rowFormat = visitor.GetResult(); }