// 集約関数の場合、Trueを返す internal bool IsAggregative() { if (this.Node == null || this.Node.IsTableWildcard) { return(false); } var exprValue = ((ResultExpr)this.Node).Value; var visitor = new FindAggregateExprVisitor(); exprValue.Accept(visitor); return(visitor.ContainsAggregativeExpr); }
private void ReplaceColumnNameInOrderBy(IQuery query) { // queryのSELECT句情報を取得する var mainQueryResults = this.GetResults((IQueryClause)query); foreach (var candidateReplaceColumn in _candidateReplaceColumns) { Column replaceColumn = null; string newAliasName = null; bool aliasNameIsFound = false; foreach (var mainQueryResult in mainQueryResults) { var aliasName = mainQueryResult.Item2; // ORDER BY句でAS別名を参照するColumnはTableAliasNameを指定できない if (string.IsNullOrEmpty(candidateReplaceColumn.Item2.TableAliasName) && aliasName == candidateReplaceColumn.Item2.Name) { // AS別名で参照しているOrderBy句は、そのまま置き換えない replaceColumn = null; aliasNameIsFound = true; break; } else if (mainQueryResult.Item1 != null) { var resultColumn = mainQueryResult.Item1; if (this.IsEqual(resultColumn, candidateReplaceColumn.Item2)) { // Column名で参照しているOrderBy句は、 // AS別名で参照するように置き換える replaceColumn = candidateReplaceColumn.Item2; newAliasName = aliasName; } } } // foreach // ORDER BY句のColumnオブジェクトをAS別名に変換する if (replaceColumn != null) { replaceColumn.ServerName = null; replaceColumn.DataBaseName = null; replaceColumn.SchemaName = null; replaceColumn.TableAliasName = null; replaceColumn.Name = newAliasName; } else if (!aliasNameIsFound) { // CompoundQueryの場合SELECT句に無い列はORDER BY句で参照できないので、 // SELECT句に補完しない var queryClause = (IQueryClause)query; while (queryClause.Type == QueryType.Bracketed) { queryClause = ((BracketedQueryClause)queryClause).Operand; } if (queryClause.Type == QueryType.Compound) { // this.RemoveOrderingTerm(query.OrderBy, candidateReplaceColumn.Item1); continue; } var singleQueryClause = (SingleQueryClause)queryClause; // DISTINCTの指定がある場合、SELECT句に補完しない if (singleQueryClause.Quantifier == QuantifierType.Distinct) { this.RemoveOrderingTerm(query.OrderBy, candidateReplaceColumn.Item1); continue; } if (singleQueryClause.HasGroupBy) { // DISTINCTの指定が無く、GROUP BY句にORDER BY句で指定するColumnがある場合 // そのColumnを参照するSELECT句を補完する var foundInGroupBy = false; foreach (var g in singleQueryClause.GroupBy) { if (g.GetType() == typeof(Column)) { if (this.IsEqual((Column)g, candidateReplaceColumn.Item2)) { this.AppendResult(query, (Column)candidateReplaceColumn.Item2.Clone()); foundInGroupBy = true; break; } } } // foreach // GROUP BY句にORDER BY句で指定するColumnがない場合、そのOrderingTerm句を削除する if (!foundInGroupBy) { this.RemoveOrderingTerm(query.OrderBy, candidateReplaceColumn.Item1); } } else { // GROUP BY句がなく集約関数のみの場合、SELECT句に補完しない var aggregateFinder = new FindAggregateExprVisitor(); singleQueryClause.Results.Accept(aggregateFinder); if (aggregateFinder.ContainsAggregativeExpr) { this.RemoveOrderingTerm(query.OrderBy, candidateReplaceColumn.Item1); continue; } // SELECT句にORDER BY句が指定するAS別名またはColumnが無いが、 // 抽出元にある場合は、その抽出元を参照するSELECT句を補完する foreach (var resultInfo in _stack.Peek()) { if (resultInfo.IsDirectSource(candidateReplaceColumn.Item2, _ignoreCase)) { this.AppendResult(query, (Column)candidateReplaceColumn.Item2.Clone()); break; } } // foreach } } // if } // foreach }
public sealed override void VisitAfter(SingleQueryClause query) { // ReadロックはReadするテーブル行をロックするのが目的なので、その行を抽出するための条件 // (EXISTS, IN, ..)で用いられるサブクエリ内のテーブル行はロックしない if (this.IsNotInMainResultsSource()) { return; } // // このQueryの列情報(ResultInfoList)を作成する // // 作成するこのQueryの列情報 var resultInfoList = new ResultInfoList(); // SELECT句サブクエリ var subQueries = new Stack <ResultInfoList>(); // FROM句の抽出元テーブル列 ResultInfoList sources; while (true) { ResultInfoList subQuery = _stack.Pop(); if (subQuery.IsSubQueryInResults) { subQueries.Push(subQuery); } else if (this.CurrentSubQueryIs(SubQueryType.Exists)) { // Existsサブクエリの場合はSELECT句情報を作成しない return; } else if (this.CurrentSubQueryIs(SubQueryType.OrderBy)) { // OrderByサブクエリの場合はSELECT句情報を作成しない return; } else { sources = subQuery; break; } } if (query.HasWildcard) { foreach (var source in sources) { resultInfoList.Add(new ResultInfo("", source.ColumnAliasName, null, source)); } _stack.Push(resultInfoList); return; } foreach (var resultColumn in query.Results) { if (resultColumn.IsTableWildcard) { var tableWildcard = (TableWildcard)resultColumn; foreach (var source in sources) { if (source.TableAliasName == tableWildcard.TableAliasName) { resultInfoList.Add(new ResultInfo("", source.ColumnAliasName, tableWildcard, source)); } } } else { var resultExpr = (ResultExpr)resultColumn; if (resultExpr.Value.GetType() == typeof(Column)) { // sourcesから参照元のResultInfoを見つける var column = (Column)resultExpr.Value; var columnAliasName = string.IsNullOrEmpty(resultExpr.AliasName) ? column.Name : resultExpr.AliasName; var foundInSources = false; foreach (var source in sources) { if (source.IsDirectSource(column, _ignoreCase)) { resultInfoList.Add(new ResultInfo("", columnAliasName, resultExpr, source)); foundInSources = true; break; } } // 参照元のResultInfoが見つからない場合(抽出元テーブルの列名が不明な場合等) // UNIONでResultInfoをマージするためSELECT句には必ずResultInfoを用意する if (!foundInSources) { resultInfoList.Add(new ResultInfo("", columnAliasName, resultExpr)); } } else if (resultExpr.Value.GetType() == typeof(SubQueryExp)) { var subQueryExp = (SubQueryExp)resultExpr.Value; var subQueryResultInfo = subQueries.Pop(); if (subQueryResultInfo.Count == 0) { resultInfoList.Add(new ResultInfo("", resultExpr.AliasName, resultExpr, null)); } else { resultInfoList.Add(new ResultInfo("", resultExpr.AliasName, resultExpr, subQueryResultInfo[0])); } } else { // UNIONでResultInfoをマージするためSELECT句には必ずResultInfoを用意する resultInfoList.Add(new ResultInfo("", resultExpr.AliasName, resultColumn)); } } // if } // for if (query.HasGroupBy) { // GROUP BY句がある場合は、そのGROUPBY句で指定されていないSELECT句は // 一致条件の被演算子に指定されてもテーブル列への一致条件とは見做さない for (var i = resultInfoList.Count - 1; i >= 0; --i) { if (!this.FindInGroupByItems(query.GroupBy, resultInfoList[i], i)) { resultInfoList[i] = new ResultInfo("" , resultInfoList[i].ColumnAliasName , resultInfoList[i].Node); } } } else { var aggregateFinder = new FindAggregateExprVisitor(); query.Results.Accept(aggregateFinder); if (aggregateFinder.ContainsAggregativeExpr) { // GROUP BY句がなく集約関数がある場合は、全てのSELECT句は // 一致条件の被演算子に指定されてもテーブル列への一致条件とは見做さない for (var i = resultInfoList.Count - 1; i >= 0; --i) { resultInfoList[i] = new ResultInfo("" , resultInfoList[i].ColumnAliasName , resultInfoList[i].Node); } } } // if _stack.Push(resultInfoList); }