public void Visit(CteInnerExpressionNode node) { var set = Nodes.Pop(); var collector = new SelectFieldsCollectVisitor(); var traverser = new CloneTraverseVisitor(collector); set.Accept(traverser); var table = new VariableTable(collector.CollectedFieldNames); _currentScope.Parent.ScopeSymbolTable.AddSymbol(node.Name, new TableSymbol(node.Name, new TransitionSchema(node.Name, table), table, false)); Nodes.Push(new CteInnerExpressionNode(set, node.Name)); }
public void Visit(QueryNode node) { var orderBy = node.OrderBy != null?Nodes.Pop() as OrderByNode : null; var groupBy = node.GroupBy != null?Nodes.Pop() as GroupByNode : null; var skip = node.Skip != null?Nodes.Pop() as SkipNode : null; var take = node.Take != null?Nodes.Pop() as TakeNode : null; var select = Nodes.Pop() as SelectNode; var where = node.Where != null?Nodes.Pop() as WhereNode : null; var from = Nodes.Pop() as ExpressionFromNode; var scoreSelect = select; var scoreWhere = where; QueryNode query; var splittedNodes = new List <Node>(); var source = from.Alias.ToRowsSource().WithRowsUsage(); QueryNode lastJoinQuery = null; _scope[MetaAttributes.MethodName] = $"ComputeTable_{from.Alias}"; IReadOnlyList <AccessMethodNode> usedRefreshMethods = null; if (_scope.ScopeSymbolTable.SymbolIsOfType <RefreshMethodsSymbol>(from.Alias.ToRefreshMethodsSymbolName())) { usedRefreshMethods = _scope.ScopeSymbolTable .GetSymbol <RefreshMethodsSymbol>(from.Alias.ToRefreshMethodsSymbolName()).RefreshMethods; } if (from.Expression is JoinsNode) { var current = _joinedTables[0]; var left = _scope.ScopeSymbolTable.GetSymbol <TableSymbol>(current.Source.Alias); var right = _scope.ScopeSymbolTable.GetSymbol <TableSymbol>(current.With.Alias); var scopeCreateTable = _scope.AddScope("Table"); var scopeJoinedQuery = _scope.AddScope("Query"); var bothForCreateTable = CreateAndConcatFields(left, current.Source.Alias, right, current.With.Alias, (name, alias) => NamingHelper.ToColumnName(alias, name)); var bothForSelect = CreateAndConcatFields(left, current.Source.Alias, right, current.With.Alias, (name, alias) => name); scopeJoinedQuery.ScopeSymbolTable.AddSymbol(current.Source.Alias, left); scopeJoinedQuery.ScopeSymbolTable.AddSymbol(current.With.Alias, right); var targetTableName = $"{current.Source.Alias}{current.With.Alias}"; scopeJoinedQuery.ScopeSymbolTable.AddSymbol(targetTableName, _scope.ScopeSymbolTable.GetSymbol(targetTableName)); scopeJoinedQuery[MetaAttributes.SelectIntoVariableName] = targetTableName.ToTransitionTable(); scopeCreateTable[MetaAttributes.CreateTableVariableName] = targetTableName.ToTransitionTable(); var joinedQuery = new InternalQueryNode( new SelectNode(bothForSelect), new ExpressionFromNode(new JoinSourcesTableFromNode(current.Source, current.With, current.Expression)), null, null, null, null, null, new RefreshNode(new AccessMethodNode[0])); var targetTable = new CreateTableNode(targetTableName, new string[0], bothForCreateTable, false); splittedNodes.Add(targetTable); splittedNodes.Add(joinedQuery); lastJoinQuery = joinedQuery; source = targetTableName.ToTransitionTable().ToTransformedRowsSource(); var usedTables = new Dictionary <string, string> { { current.Source.Alias, targetTableName }, { current.With.Alias, targetTableName } }; for (var i = 1; i < _joinedTables.Count; i++) { current = _joinedTables[i]; left = _scope.ScopeSymbolTable.GetSymbol <TableSymbol>(current.Source.Alias); right = _scope.ScopeSymbolTable.GetSymbol <TableSymbol>(current.With.Alias); targetTableName = $"{current.Source.Alias}{current.With.Alias}"; scopeCreateTable = _scope.AddScope("Table"); scopeJoinedQuery = _scope.AddScope("Query"); bothForCreateTable = CreateAndConcatFields(left, current.Source.Alias, right, current.With.Alias, (name, alias) => NamingHelper.ToColumnName(alias, name)); bothForSelect = CreateAndConcatFields( left, current.Source.Alias, right, current.With.Alias, (name, alias) => NamingHelper.ToColumnName(alias, name), (name, alias) => name, (name, alias) => NamingHelper.ToColumnName(alias, name), (name, alias) => name); scopeJoinedQuery.ScopeSymbolTable.AddSymbol(current.Source.Alias, left); scopeJoinedQuery.ScopeSymbolTable.AddSymbol(current.With.Alias, right); scopeJoinedQuery.ScopeSymbolTable.AddSymbol(targetTableName, _scope.ScopeSymbolTable.GetSymbol(targetTableName)); scopeJoinedQuery[MetaAttributes.SelectIntoVariableName] = targetTableName.ToTransitionTable(); scopeCreateTable[MetaAttributes.CreateTableVariableName] = targetTableName.ToTransitionTable(); var expressionUpdater = new RewriteWhereConditionWithUpdatedColumnAccess(usedTables); var traverser = new CloneTraverseVisitor(expressionUpdater); new WhereNode(current.Expression).Accept(traverser); foreach (var key in usedTables.Keys.ToArray()) { usedTables[key] = targetTableName; } usedTables[current.Source.Alias] = targetTableName; usedTables.Add(current.With.Alias, targetTableName); joinedQuery = new InternalQueryNode( new SelectNode(bothForSelect), new ExpressionFromNode(new JoinInMemoryWithSourceTableFromNode(current.Source.Alias, current.With, expressionUpdater.Where.Expression)), null, null, null, null, null, new RefreshNode(new AccessMethodNode[0])); targetTable = new CreateTableNode(targetTableName, new string[0], bothForCreateTable, false); splittedNodes.Add(targetTable); splittedNodes.Add(joinedQuery); lastJoinQuery = joinedQuery; source = targetTableName.ToTransitionTable().ToTransformedRowsSource(); } var rewriter = new RewritePartsToUseJoinTransitionTable(); var partsTraverser = new CloneTraverseVisitor(rewriter); select.Accept(partsTraverser); where?.Accept(partsTraverser); scoreSelect = rewriter.ChangedSelect; scoreWhere = rewriter.ChangedWhere; } if (groupBy != null) { var nestedFrom = splittedNodes.Count > 0 ? new ExpressionFromNode(new InMemoryGroupedFromNode(lastJoinQuery.From.Alias)) : from; var splitted = SplitBetweenAggreateAndNonAggreagate(select.Fields, groupBy.Fields, true); var refreshMethods = CreateRefreshMethods(usedRefreshMethods); var aggSelect = new SelectNode(ConcatAggregateFieldsWithGroupByFields(splitted[0], groupBy.Fields) .Reverse().ToArray()); var outSelect = new SelectNode(splitted[1]); var scopeCreateTranformingTable = _scope.AddScope("Table"); var scopeTransformedQuery = _scope.AddScope("Query"); var scopeCreateResultTable = _scope.AddScope("Table"); var scopeResultQuery = _scope.AddScope("Query"); scopeCreateTranformingTable[MetaAttributes.CreateTableVariableName] = nestedFrom.Alias.ToGroupingTable(); scopeCreateResultTable[MetaAttributes.CreateTableVariableName] = nestedFrom.Alias.ToScoreTable(); var destination = nestedFrom.Alias.ToGroupingTable().ToTransformedRowsSource(); scopeTransformedQuery[MetaAttributes.SelectIntoVariableName] = destination; scopeTransformedQuery[MetaAttributes.SourceName] = splittedNodes.Count > 0 ? nestedFrom.Alias.ToTransitionTable().ToTransformedRowsSource() : nestedFrom.Alias.ToRowsSource().WithRowsUsage(); scopeTransformedQuery.ScopeSymbolTable.AddSymbol(nestedFrom.Alias, _scope.ScopeSymbolTable.GetSymbol(nestedFrom.Alias)); if (splittedNodes.Count > 0) { var selectRewriter = new RewritePartsToUseJoinTransitionTable(nestedFrom.Alias); var selectTraverser = new CloneTraverseVisitor(selectRewriter); groupBy.Accept(selectTraverser); groupBy = selectRewriter.ChangedGroupBy; scopeTransformedQuery.ScopeSymbolTable.AddSymbol("groupFields", new FieldsNamesSymbol(groupBy.Fields.Select(f => f.FieldName).ToArray())); var newRefreshMethods = new List <AccessMethodNode>(); foreach (var method in refreshMethods.Nodes) { var newNodes = new List <Node>(); foreach (var arg in method.Arguments.Args) { arg.Accept(selectTraverser); newNodes.Add(selectRewriter.RewrittenNode); } var newArgs = new ArgsListNode(newNodes.ToArray()); newRefreshMethods.Add(new AccessMethodNode(method.FToken, newArgs, method.ExtraAggregateArguments, method.Method)); } refreshMethods = new RefreshNode(newRefreshMethods.ToArray()); } else { scopeTransformedQuery.ScopeSymbolTable.AddSymbol("groupFields", new FieldsNamesSymbol(groupBy.Fields.Select(f => f.Expression.ToString()).ToArray())); } var transformingQuery = new InternalQueryNode(aggSelect, nestedFrom, where, groupBy, null, null, null, refreshMethods); var returnScore = nestedFrom.Alias.ToScoreTable(); scopeResultQuery[MetaAttributes.SelectIntoVariableName] = returnScore; scopeResultQuery[MetaAttributes.SourceName] = destination; query = new DetailedQueryNode( outSelect, new ExpressionFromNode( new InMemoryGroupedFromNode(returnScore)), null, null, null, skip, take, returnScore); splittedNodes.Add(new CreateTableNode(destination, new string[0], transformingQuery.Select.Fields, true)); splittedNodes.Add(transformingQuery); splittedNodes.Add(new CreateTableNode(query.From.Alias, new string[0], query.Select.Fields, false)); splittedNodes.Add(query); Nodes.Push( new MultiStatementNode( splittedNodes.ToArray(), null)); } else { var splitted = SplitBetweenAggreateAndNonAggreagate(select.Fields, new FieldNode[0], true); if (IsQueryWithMixedAggregateAndNonAggregateMethods(splitted)) { query = new InternalQueryNode(select, from, where, null, null, skip, take, CreateRefreshMethods(usedRefreshMethods)); } else { var scopeCreateResultTable = _scope.AddScope("Table"); var scopeResultQuery = _scope.AddScope("Query"); scopeCreateResultTable[MetaAttributes.CreateTableVariableName] = from.Alias.ToScoreTable(); scopeResultQuery[MetaAttributes.SelectIntoVariableName] = from.Alias.ToScoreTable(); scopeResultQuery[MetaAttributes.SourceName] = source; var newFrom = lastJoinQuery != null ? new ExpressionFromNode(new InMemoryGroupedFromNode(lastJoinQuery.From.Alias)) : from; splittedNodes.Add(new CreateTableNode(scopeResultQuery[MetaAttributes.SelectIntoVariableName], new string[0], select.Fields, false)); splittedNodes.Add(new DetailedQueryNode(scoreSelect, newFrom, scoreWhere, null, null, skip, take, scopeResultQuery[MetaAttributes.SelectIntoVariableName])); Nodes.Push( new MultiStatementNode( splittedNodes.ToArray(), null)); } } _joinedTables.Clear(); }