[Enhancement](grouping) Add a switch for users to force using alias name in group by and having clause (#15748)

This commit is contained in:
xy720
2023-01-31 23:46:31 +08:00
committed by GitHub
parent c63a960df6
commit cd457312e4
6 changed files with 98 additions and 18 deletions

View File

@ -1135,23 +1135,32 @@ public class SelectStmt extends QueryStmt {
* select id, floor(v1) v, sum(v2) vsum from table group by id,v having(v>1 AND vsum>1);
*/
if (groupByClause != null) {
ExprSubstitutionMap excludeAliasSMap = aliasSMap.clone();
List<Expr> havingSlots = Lists.newArrayList();
havingClause.collect(SlotRef.class, havingSlots);
for (Expr expr : havingSlots) {
if (excludeAliasSMap.get(expr) == null) {
continue;
}
try {
// try to use column name firstly
expr.clone().analyze(analyzer);
// analyze success means column name exist, do not use alias name
excludeAliasSMap.removeByLhsExpr(expr);
} catch (AnalysisException ex) {
// according to case3, column name do not exist, keep alias name inside alias map
}
boolean aliasFirst = false;
if (analyzer.getContext() != null) {
aliasFirst = analyzer.getContext().getSessionVariable().isGroupByAndHavingUseAliasFirst();
}
if (!aliasFirst) {
ExprSubstitutionMap excludeAliasSMap = aliasSMap.clone();
List<Expr> havingSlots = Lists.newArrayList();
havingClause.collect(SlotRef.class, havingSlots);
for (Expr expr : havingSlots) {
if (excludeAliasSMap.get(expr) == null) {
continue;
}
try {
// try to use column name firstly
expr.clone().analyze(analyzer);
// analyze success means column name exist, do not use alias name
excludeAliasSMap.removeByLhsExpr(expr);
} catch (AnalysisException ex) {
// according to case3, column name do not exist, keep alias name inside alias map
}
}
havingClauseAfterAnaylzed = havingClause.substitute(excludeAliasSMap, analyzer, false);
} else {
// If user set force using alias, then having clauses prefer using alias rather than column name
havingClauseAfterAnaylzed = havingClause.substitute(aliasSMap, analyzer, false);
}
havingClauseAfterAnaylzed = havingClause.substitute(excludeAliasSMap, analyzer, false);
} else {
// according to mysql
// if there is no group by clause, the having clause should use alias
@ -1268,7 +1277,11 @@ public class SelectStmt extends QueryStmt {
groupingInfo.buildRepeat(groupingExprs, groupByClause.getGroupingSetList());
}
substituteOrdinalsAliases(groupingExprs, "GROUP BY", analyzer, false);
boolean aliasFirst = false;
if (analyzer.getContext() != null) {
aliasFirst = analyzer.getContext().getSessionVariable().isGroupByAndHavingUseAliasFirst();
}
substituteOrdinalsAliases(groupingExprs, "GROUP BY", analyzer, aliasFirst);
if (!groupByClause.isGroupByExtension() && !groupingExprs.isEmpty()) {
ArrayList<Expr> tempExprs = new ArrayList<>(groupingExprs);
@ -2241,7 +2254,11 @@ public class SelectStmt extends QueryStmt {
}
// substitute group by
if (groupByClause != null) {
substituteOrdinalsAliases(groupByClause.getGroupingExprs(), "GROUP BY", analyzer, false);
boolean aliasFirst = false;
if (analyzer.getContext() != null) {
aliasFirst = analyzer.getContext().getSessionVariable().isGroupByAndHavingUseAliasFirst();
}
substituteOrdinalsAliases(groupByClause.getGroupingExprs(), "GROUP BY", analyzer, aliasFirst);
}
// substitute having
if (havingClause != null) {

View File

@ -260,6 +260,8 @@ public class SessionVariable implements Serializable, Writable {
public static final String ENABLE_TWO_PHASE_READ_OPT = "enable_two_phase_read_opt";
public static final String TWO_PHASE_READ_OPT_LIMIT_THRESHOLD = "two_phase_read_opt_limit_threshold";
public static final String GROUP_BY_AND_HAVING_USE_ALIAS_FIRST = "group_by_and_having_use_alias_first";
// session origin value
public Map<Field, String> sessionOriginValue = new HashMap<Field, String>();
// check stmt is or not [select /*+ SET_VAR(...)*/ ...]
@ -679,6 +681,11 @@ public class SessionVariable implements Serializable, Writable {
@VariableMgr.VarAttr(name = TWO_PHASE_READ_OPT_LIMIT_THRESHOLD)
public long twoPhaseReadLimitThreshold = 512;
// Default value is false, which means the group by and having clause
// should first use column name not alias. According to mysql.
@VariableMgr.VarAttr(name = GROUP_BY_AND_HAVING_USE_ALIAS_FIRST)
public boolean groupByAndHavingUseAliasFirst = false;
// If this fe is in fuzzy mode, then will use initFuzzyModeVariables to generate some variables,
// not the default value set in the code.
public void initFuzzyModeVariables() {
@ -1238,6 +1245,10 @@ public class SessionVariable implements Serializable, Writable {
return extractWideRangeExpr;
}
public boolean isGroupByAndHavingUseAliasFirst() {
return groupByAndHavingUseAliasFirst;
}
public int getCpuResourceLimit() {
return cpuResourceLimit;
}