mirror of
https://github.com/tencentmusic/supersonic.git
synced 2025-12-11 12:07:42 +00:00
(improvement)(headless) adapter for derived metrics (#646)
This commit is contained in:
@@ -10,6 +10,7 @@ public enum AggOperatorEnum {
|
||||
|
||||
SUM("SUM"),
|
||||
|
||||
COUNT("COUNT"),
|
||||
COUNT_DISTINCT("COUNT_DISTINCT"),
|
||||
DISTINCT("DISTINCT"),
|
||||
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
package com.tencent.supersonic.common.util.jsqlparser;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import net.sf.jsqlparser.expression.BinaryExpression;
|
||||
import net.sf.jsqlparser.expression.Expression;
|
||||
import net.sf.jsqlparser.expression.ExpressionVisitorAdapter;
|
||||
import net.sf.jsqlparser.expression.Function;
|
||||
import net.sf.jsqlparser.schema.Column;
|
||||
|
||||
public class ExpressionReplaceVisitor extends ExpressionVisitorAdapter {
|
||||
|
||||
private Map<String, String> fieldExprMap;
|
||||
|
||||
|
||||
public ExpressionReplaceVisitor(Map<String, String> fieldExprMap) {
|
||||
this.fieldExprMap = fieldExprMap;
|
||||
}
|
||||
|
||||
protected void visitBinaryExpression(BinaryExpression expr) {
|
||||
Expression left = expr.getLeftExpression();
|
||||
Expression right = expr.getRightExpression();
|
||||
Boolean leftVisited = false;
|
||||
Boolean rightVisited = false;
|
||||
if (left instanceof Function) {
|
||||
Function leftFunc = (Function) left;
|
||||
if (visitFunction(leftFunc)) {
|
||||
leftVisited = true;
|
||||
}
|
||||
}
|
||||
if (right instanceof Function) {
|
||||
Function function = (Function) right;
|
||||
if (visitFunction(function)) {
|
||||
rightVisited = true;
|
||||
}
|
||||
}
|
||||
if (left instanceof Column) {
|
||||
Expression expression = QueryExpressionReplaceVisitor.getExpression(
|
||||
QueryExpressionReplaceVisitor.getReplaceExpr((Column) left, fieldExprMap));
|
||||
if (Objects.nonNull(expression)) {
|
||||
expr.setLeftExpression(expression);
|
||||
leftVisited = true;
|
||||
}
|
||||
}
|
||||
if (right instanceof Column) {
|
||||
Expression expression = QueryExpressionReplaceVisitor.getExpression(
|
||||
QueryExpressionReplaceVisitor.getReplaceExpr((Column) right, fieldExprMap));
|
||||
if (Objects.nonNull(expression)) {
|
||||
expr.setRightExpression(expression);
|
||||
rightVisited = true;
|
||||
}
|
||||
}
|
||||
if (!leftVisited) {
|
||||
expr.getLeftExpression().accept(this);
|
||||
}
|
||||
if (!rightVisited) {
|
||||
expr.getRightExpression().accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean visitFunction(Function function) {
|
||||
if (function.getParameters().getExpressions().get(0) instanceof Column) {
|
||||
Expression expression = QueryExpressionReplaceVisitor.getExpression(
|
||||
QueryExpressionReplaceVisitor.getReplaceExpr(function, fieldExprMap));
|
||||
if (Objects.nonNull(expression)) {
|
||||
List<Expression> expressions = new ArrayList<>();
|
||||
expressions.add(expression);
|
||||
for (int i = 1; i < function.getParameters().getExpressions().size(); i++) {
|
||||
expressions.add(function.getParameters().getExpressions().get(i));
|
||||
}
|
||||
function.getParameters().setExpressions(expressions);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package com.tencent.supersonic.common.util.jsqlparser;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import net.sf.jsqlparser.expression.BinaryExpression;
|
||||
import net.sf.jsqlparser.expression.Expression;
|
||||
import net.sf.jsqlparser.expression.ExpressionVisitorAdapter;
|
||||
import net.sf.jsqlparser.expression.Function;
|
||||
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
|
||||
import net.sf.jsqlparser.schema.Column;
|
||||
import net.sf.jsqlparser.statement.select.SelectExpressionItem;
|
||||
|
||||
public class QueryExpressionReplaceVisitor extends ExpressionVisitorAdapter {
|
||||
|
||||
private Map<String, String> fieldExprMap;
|
||||
|
||||
public QueryExpressionReplaceVisitor(Map<String, String> fieldExprMap) {
|
||||
this.fieldExprMap = fieldExprMap;
|
||||
}
|
||||
|
||||
protected void visitBinaryExpression(BinaryExpression expr) {
|
||||
Expression left = expr.getLeftExpression();
|
||||
String toReplace = "";
|
||||
if (left instanceof Function) {
|
||||
Function leftFunc = (Function) left;
|
||||
if (leftFunc.getParameters().getExpressions().get(0) instanceof Column) {
|
||||
toReplace = getReplaceExpr(leftFunc, fieldExprMap);
|
||||
}
|
||||
}
|
||||
if (left instanceof Column) {
|
||||
toReplace = getReplaceExpr((Column) left, fieldExprMap);
|
||||
}
|
||||
if (!toReplace.isEmpty()) {
|
||||
Expression expression = getExpression(toReplace);
|
||||
if (Objects.nonNull(expression)) {
|
||||
expr.setLeftExpression(expression);
|
||||
return;
|
||||
}
|
||||
}
|
||||
expr.getLeftExpression().accept(this);
|
||||
expr.getRightExpression().accept(this);
|
||||
|
||||
}
|
||||
|
||||
public void visit(SelectExpressionItem selectExpressionItem) {
|
||||
|
||||
Expression expression = selectExpressionItem.getExpression();
|
||||
String toReplace = "";
|
||||
if (expression instanceof Function) {
|
||||
Function leftFunc = (Function) expression;
|
||||
if (leftFunc.getParameters().getExpressions().get(0) instanceof Column) {
|
||||
toReplace = getReplaceExpr(leftFunc, fieldExprMap);
|
||||
}
|
||||
|
||||
}
|
||||
if (expression instanceof Column) {
|
||||
toReplace = getReplaceExpr((Column) expression, fieldExprMap);
|
||||
}
|
||||
if (!toReplace.isEmpty()) {
|
||||
Expression toReplaceExpr = getExpression(toReplace);
|
||||
if (Objects.nonNull(toReplaceExpr)) {
|
||||
selectExpressionItem.setExpression(toReplaceExpr);
|
||||
}
|
||||
}
|
||||
//selectExpressionItem.getExpression().accept(this);
|
||||
}
|
||||
|
||||
public static Expression replace(Expression expression, Map<String, String> fieldExprMap) {
|
||||
String toReplace = "";
|
||||
if (expression instanceof Function) {
|
||||
toReplace = getReplaceExpr((Function) expression, fieldExprMap);
|
||||
}
|
||||
if (expression instanceof Column) {
|
||||
toReplace = getReplaceExpr((Column) expression, fieldExprMap);
|
||||
}
|
||||
if (!toReplace.isEmpty()) {
|
||||
Expression replace = getExpression(toReplace);
|
||||
if (Objects.nonNull(replace)) {
|
||||
return replace;
|
||||
}
|
||||
}
|
||||
return expression;
|
||||
}
|
||||
|
||||
public static Expression getExpression(String expr) {
|
||||
if (expr.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
Expression expression = CCJSqlParserUtil.parseExpression(expr);
|
||||
return expression;
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getReplaceExpr(Column column, Map<String, String> fieldExprMap) {
|
||||
return fieldExprMap.containsKey(column.getColumnName()) ? fieldExprMap.get(column.getColumnName()) : "";
|
||||
}
|
||||
|
||||
public static String getReplaceExpr(Function function, Map<String, String> fieldExprMap) {
|
||||
Column column = (Column) function.getParameters().getExpressions().get(0);
|
||||
return getReplaceExpr(column, fieldExprMap);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,6 +2,11 @@ package com.tencent.supersonic.common.util.jsqlparser;
|
||||
|
||||
import com.tencent.supersonic.common.pojo.enums.AggOperatorEnum;
|
||||
import com.tencent.supersonic.common.util.StringUtil;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.sf.jsqlparser.JSQLParserException;
|
||||
import net.sf.jsqlparser.expression.Alias;
|
||||
@@ -32,11 +37,6 @@ import net.sf.jsqlparser.statement.select.SubSelect;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Sql Parser replace Helper
|
||||
@@ -120,7 +120,7 @@ public class SqlParserReplaceHelper {
|
||||
}
|
||||
|
||||
public static String replaceValue(String sql, Map<String, Map<String, String>> filedNameToValueMap,
|
||||
boolean exactReplace) {
|
||||
boolean exactReplace) {
|
||||
Select selectStatement = SqlParserSelectHelper.getSelect(sql);
|
||||
SelectBody selectBody = selectStatement.getSelectBody();
|
||||
if (!(selectBody instanceof PlainSelect)) {
|
||||
@@ -196,7 +196,7 @@ public class SqlParserReplaceHelper {
|
||||
}
|
||||
|
||||
private static void replaceFieldsInPlainOneSelect(Map<String, String> fieldNameMap, boolean exactReplace,
|
||||
PlainSelect plainSelect) {
|
||||
PlainSelect plainSelect) {
|
||||
//1. replace where fields
|
||||
Expression where = plainSelect.getWhere();
|
||||
FieldReplaceVisitor visitor = new FieldReplaceVisitor(fieldNameMap, exactReplace);
|
||||
@@ -351,7 +351,7 @@ public class SqlParserReplaceHelper {
|
||||
}
|
||||
|
||||
private static void replaceOrderByFunction(Map<String, String> functionMap,
|
||||
List<OrderByElement> orderByElementList) {
|
||||
List<OrderByElement> orderByElementList) {
|
||||
if (Objects.isNull(orderByElementList)) {
|
||||
return;
|
||||
}
|
||||
@@ -499,5 +499,66 @@ public class SqlParserReplaceHelper {
|
||||
return expression;
|
||||
}
|
||||
}
|
||||
|
||||
public static String replaceExpression(String expr, Map<String, String> replace) {
|
||||
Expression expression = QueryExpressionReplaceVisitor.getExpression(expr);
|
||||
if (Objects.nonNull(expression)) {
|
||||
if (expression instanceof Column && replace.containsKey(expr)) {
|
||||
return replace.get(expr);
|
||||
}
|
||||
ExpressionReplaceVisitor expressionReplaceVisitor = new ExpressionReplaceVisitor(replace);
|
||||
expression.accept(expressionReplaceVisitor);
|
||||
return expression.toString();
|
||||
}
|
||||
return expr;
|
||||
}
|
||||
|
||||
public static String replaceSqlByExpression(String sql, Map<String, String> replace) {
|
||||
Select selectStatement = SqlParserSelectHelper.getSelect(sql);
|
||||
SelectBody selectBody = selectStatement.getSelectBody();
|
||||
List<PlainSelect> plainSelectList = new ArrayList<>();
|
||||
if (selectBody instanceof PlainSelect) {
|
||||
plainSelectList.add((PlainSelect) selectBody);
|
||||
} else if (selectBody instanceof SetOperationList) {
|
||||
SetOperationList setOperationList = (SetOperationList) selectBody;
|
||||
if (!CollectionUtils.isEmpty(setOperationList.getSelects())) {
|
||||
setOperationList.getSelects().forEach(subSelectBody -> {
|
||||
PlainSelect subPlainSelect = (PlainSelect) subSelectBody;
|
||||
plainSelectList.add(subPlainSelect);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
return sql;
|
||||
}
|
||||
List<PlainSelect> plainSelects = SqlParserSelectHelper.getPlainSelects(plainSelectList);
|
||||
for (PlainSelect plainSelect : plainSelects) {
|
||||
replacePlainSelectByExpr(plainSelect, replace);
|
||||
}
|
||||
return selectStatement.toString();
|
||||
}
|
||||
|
||||
private static void replacePlainSelectByExpr(PlainSelect plainSelect, Map<String, String> replace) {
|
||||
QueryExpressionReplaceVisitor expressionReplaceVisitor = new QueryExpressionReplaceVisitor(replace);
|
||||
for (SelectItem selectItem : plainSelect.getSelectItems()) {
|
||||
selectItem.accept(expressionReplaceVisitor);
|
||||
}
|
||||
Expression having = plainSelect.getHaving();
|
||||
if (Objects.nonNull(having)) {
|
||||
having.accept(expressionReplaceVisitor);
|
||||
}
|
||||
|
||||
Expression where = plainSelect.getWhere();
|
||||
if (Objects.nonNull(where)) {
|
||||
where.accept(expressionReplaceVisitor);
|
||||
}
|
||||
|
||||
List<OrderByElement> orderByElements = plainSelect.getOrderByElements();
|
||||
if (!CollectionUtils.isEmpty(orderByElements)) {
|
||||
for (OrderByElement orderByElement : orderByElements) {
|
||||
orderByElement.setExpression(
|
||||
QueryExpressionReplaceVisitor.replace(orderByElement.getExpression(), replace));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,9 +6,9 @@ import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.sf.jsqlparser.JSQLParserException;
|
||||
import net.sf.jsqlparser.expression.BinaryExpression;
|
||||
import net.sf.jsqlparser.expression.Expression;
|
||||
import net.sf.jsqlparser.expression.ExpressionVisitorAdapter;
|
||||
import net.sf.jsqlparser.expression.Function;
|
||||
@@ -32,8 +32,8 @@ import net.sf.jsqlparser.statement.select.SelectBody;
|
||||
import net.sf.jsqlparser.statement.select.SelectExpressionItem;
|
||||
import net.sf.jsqlparser.statement.select.SelectItem;
|
||||
import net.sf.jsqlparser.statement.select.SelectVisitorAdapter;
|
||||
import net.sf.jsqlparser.statement.select.SubSelect;
|
||||
import net.sf.jsqlparser.statement.select.SetOperationList;
|
||||
import net.sf.jsqlparser.statement.select.SubSelect;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
@@ -480,5 +480,31 @@ public class SqlParserSelectHelper {
|
||||
}
|
||||
return selectStatement.toString();
|
||||
}
|
||||
|
||||
public static Set<String> getColumnFromExpr(String expr) {
|
||||
Expression expression = QueryExpressionReplaceVisitor.getExpression(expr);
|
||||
Set<String> columns = new HashSet<>();
|
||||
if (Objects.nonNull(expression)) {
|
||||
getColumnFromExpr(expression, columns);
|
||||
}
|
||||
return columns;
|
||||
}
|
||||
|
||||
public static void getColumnFromExpr(Expression expression, Set<String> columns) {
|
||||
if (expression instanceof Column) {
|
||||
columns.add(((Column) expression).getColumnName());
|
||||
}
|
||||
if (expression instanceof Function) {
|
||||
List<Expression> expressionList = ((Function) expression).getParameters().getExpressions();
|
||||
for (Expression expr : expressionList) {
|
||||
getColumnFromExpr(expr, columns);
|
||||
}
|
||||
}
|
||||
if (expression instanceof BinaryExpression) {
|
||||
BinaryExpression expr = (BinaryExpression) expression;
|
||||
getColumnFromExpr(expr.getLeftExpression(), columns);
|
||||
getColumnFromExpr(expr.getRightExpression(), columns);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user