[Enhancement](grouping) Add a switch for users to force using alias name in group by and having clause (#15748)
This commit is contained in:
@ -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) {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user