(improvement)(chat) rewrite datediff logic and perfect sql style (#461)

This commit is contained in:
mainmain
2023-12-04 10:41:41 +08:00
committed by GitHub
parent c220ca69c2
commit 2bc29d64a4
8 changed files with 154 additions and 106 deletions

View File

@@ -2,6 +2,12 @@ package com.tencent.supersonic.common.util.jsqlparser;
import lombok.extern.slf4j.Slf4j;
import java.util.AbstractMap;
import java.util.Map;
import java.util.stream.Stream;
import static java.util.stream.Collectors.toMap;
@Slf4j
public class JsqlConstants {
@@ -9,14 +15,31 @@ public class JsqlConstants {
public static final double HALF_YEAR = 0.5d;
public static final int SIX_MONTH = 6;
public static final String EQUAL = "=";
public static final String MINOR_THAN = "<";
public static final String MINOR_THAN_EQUALS = "<=";
public static final String GREATER_THAN = ">";
public static final String GREATER_THAN_EQUALS = ">=";
public static final String MINOR_THAN_CONSTANT = " 1 < 2 ";
public static final String MINOR_THAN_EQUALS_CONSTANT = " 1 <= 1 ";
public static final String GREATER_THAN_CONSTANT = " 2 > 1 ";
public static final String GREATER_THAN_EQUALS_CONSTANT = " 1 >= 1 ";
public static final String EQUAL_CONSTANT = " 1 = 1 ";
public static final String IN_CONSTANT = " 1 in (1) ";
public static final String LIKE_CONSTANT = "1 like 1";
public static final String IN = "IN";
public static final Map<String, String> rightMap = Stream.of(
new AbstractMap.SimpleEntry<>("<=", "<="),
new AbstractMap.SimpleEntry<>("<", "<"),
new AbstractMap.SimpleEntry<>(">=", "<="),
new AbstractMap.SimpleEntry<>(">", "<"),
new AbstractMap.SimpleEntry<>("=", "<="))
.collect(toMap(AbstractMap.SimpleEntry::getKey, AbstractMap.SimpleEntry::getValue));
public static final Map<String, String> leftMap = Stream.of(
new AbstractMap.SimpleEntry<>("<=", ">="),
new AbstractMap.SimpleEntry<>("<", ">"),
new AbstractMap.SimpleEntry<>(">=", "<="),
new AbstractMap.SimpleEntry<>(">", "<"),
new AbstractMap.SimpleEntry<>("=", ">="))
.collect(toMap(AbstractMap.SimpleEntry::getKey, AbstractMap.SimpleEntry::getValue));
}

View File

@@ -0,0 +1,6 @@
package com.tencent.supersonic.common.util.jsqlparser;
public enum SqlEditEnum {
NUMBER_FILTER,
DATEDIFF
}

View File

@@ -342,8 +342,7 @@ public class SqlParserAddHelper {
}
}
}
sql = SqlParserRemoveHelper.removeNumberCondition(selectStatement.toString());
return sql;
return SqlParserRemoveHelper.removeNumberFilter(selectStatement.toString());
}
public static String addHaving(String sql, List<Expression> expressionList) {

View File

@@ -10,6 +10,7 @@ import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
import net.sf.jsqlparser.expression.operators.relational.ComparisonOperator;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.expression.operators.relational.NotEqualsTo;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.GreaterThan;
import net.sf.jsqlparser.expression.operators.relational.GreaterThanEquals;
@@ -17,7 +18,6 @@ import net.sf.jsqlparser.expression.operators.relational.InExpression;
import net.sf.jsqlparser.expression.operators.relational.LikeExpression;
import net.sf.jsqlparser.expression.operators.relational.MinorThan;
import net.sf.jsqlparser.expression.operators.relational.MinorThanEquals;
import net.sf.jsqlparser.expression.operators.relational.NotEqualsTo;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.statement.select.GroupByElement;
@@ -30,8 +30,8 @@ import net.sf.jsqlparser.statement.select.SelectVisitorAdapter;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.Objects;
/**
* Sql Parser remove Helper
@@ -73,8 +73,7 @@ public class SqlParserRemoveHelper {
removeWhereCondition(plainSelect.getWhere(), removeFieldNames);
}
});
sql = removeNumberCondition(selectStatement.toString());
return sql;
return removeNumberFilter(selectStatement.toString());
}
private static void removeWhereCondition(Expression whereExpression, Set<String> removeFieldNames) {
@@ -84,7 +83,7 @@ public class SqlParserRemoveHelper {
removeWhereExpression(whereExpression, removeFieldNames);
}
public static String removeNumberCondition(String sql) {
public static String removeNumberFilter(String sql) {
Select selectStatement = SqlParserSelectHelper.getSelect(sql);
if (selectStatement == null) {
return sql;
@@ -96,10 +95,12 @@ public class SqlParserRemoveHelper {
}
Expression where = ((PlainSelect) selectBody).getWhere();
Expression having = ((PlainSelect) selectBody).getHaving();
where = filteredWhereExpression(where);
having = filteredWhereExpression(having);
((PlainSelect) selectBody).setWhere(where);
((PlainSelect) selectBody).setHaving(having);
try {
((PlainSelect) selectBody).setWhere(filteredExpression(where, SqlEditEnum.NUMBER_FILTER));
((PlainSelect) selectBody).setHaving(filteredExpression(having, SqlEditEnum.NUMBER_FILTER));
} catch (Exception e) {
log.info("replaceFunction has an exception:{}", e.toString());
}
return selectStatement.toString();
}
@@ -203,8 +204,7 @@ public class SqlParserRemoveHelper {
removeWhereCondition(plainSelect.getHaving(), removeFieldNames);
}
});
sql = removeNumberCondition(selectStatement.toString());
return sql;
return removeNumberFilter(selectStatement.toString());
}
public static String removeWhere(String sql, List<String> fields) {
@@ -252,12 +252,12 @@ public class SqlParserRemoveHelper {
return selectStatement.toString();
}
private static Expression filteredWhereExpression(Expression where) {
public static Expression filteredExpression(Expression where, SqlEditEnum sqlEditEnum) throws Exception {
if (Objects.isNull(where)) {
return null;
}
if (where instanceof Parenthesis) {
Expression expression = filteredWhereExpression(((Parenthesis) where).getExpression());
Expression expression = filteredExpression(((Parenthesis) where).getExpression(), sqlEditEnum);
if (expression != null) {
try {
Expression parseExpression = CCJSqlParserUtil.parseExpression("(" + expression + ")");
@@ -270,19 +270,20 @@ public class SqlParserRemoveHelper {
}
} else if (where instanceof AndExpression) {
AndExpression andExpression = (AndExpression) where;
return filteredNumberExpression(andExpression);
return filteredLogicExpression(andExpression, sqlEditEnum);
} else if (where instanceof OrExpression) {
OrExpression orExpression = (OrExpression) where;
return filteredNumberExpression(orExpression);
return filteredLogicExpression(orExpression, sqlEditEnum);
} else {
return replaceComparisonOperatorFunction(where);
return dealComparisonOperatorFilter(where, sqlEditEnum);
}
return where;
}
private static <T extends BinaryExpression> Expression filteredNumberExpression(T binaryExpression) {
Expression leftExpression = filteredWhereExpression(binaryExpression.getLeftExpression());
Expression rightExpression = filteredWhereExpression(binaryExpression.getRightExpression());
private static <T extends BinaryExpression> Expression filteredLogicExpression(
T binaryExpression, SqlEditEnum sqlEditEnum) throws Exception {
Expression leftExpression = filteredExpression(binaryExpression.getLeftExpression(), sqlEditEnum);
Expression rightExpression = filteredExpression(binaryExpression.getRightExpression(), sqlEditEnum);
if (leftExpression != null && rightExpression != null) {
binaryExpression.setLeftExpression(leftExpression);
binaryExpression.setRightExpression(rightExpression);
@@ -296,40 +297,43 @@ public class SqlParserRemoveHelper {
}
}
private static Expression replaceComparisonOperatorFunction(Expression expression) {
private static Expression dealComparisonOperatorFilter(Expression expression, SqlEditEnum sqlEditEnum) {
if (Objects.isNull(expression)) {
return null;
}
if (expression instanceof GreaterThanEquals) {
return removeSingleFilter((GreaterThanEquals) expression);
} else if (expression instanceof GreaterThan) {
return removeSingleFilter((GreaterThan) expression);
} else if (expression instanceof MinorThan) {
return removeSingleFilter((MinorThan) expression);
} else if (expression instanceof MinorThanEquals) {
return removeSingleFilter((MinorThanEquals) expression);
} else if (expression instanceof EqualsTo) {
return removeSingleFilter((EqualsTo) expression);
} else if (expression instanceof NotEqualsTo) {
return removeSingleFilter((NotEqualsTo) expression);
if (expression instanceof GreaterThanEquals || expression instanceof GreaterThan
|| expression instanceof MinorThan || expression instanceof MinorThanEquals
|| expression instanceof EqualsTo || expression instanceof NotEqualsTo) {
return removeSingleFilter((ComparisonOperator) expression, sqlEditEnum);
} else if (expression instanceof InExpression) {
InExpression inExpression = (InExpression) expression;
Expression leftExpression = inExpression.getLeftExpression();
return distinguishNumberCondition(leftExpression, expression);
return recursionBase(leftExpression, expression, sqlEditEnum);
} else if (expression instanceof LikeExpression) {
LikeExpression likeExpression = (LikeExpression) expression;
Expression leftExpression = likeExpression.getLeftExpression();
return distinguishNumberCondition(leftExpression, expression);
return recursionBase(leftExpression, expression, sqlEditEnum);
}
return expression;
}
private static <T extends ComparisonOperator> Expression removeSingleFilter(T comparisonExpression) {
private static Expression removeSingleFilter(
ComparisonOperator comparisonExpression, SqlEditEnum sqlEditEnum) {
Expression leftExpression = comparisonExpression.getLeftExpression();
return distinguishNumberCondition(leftExpression, comparisonExpression);
return recursionBase(leftExpression, comparisonExpression, sqlEditEnum);
}
public static Expression distinguishNumberCondition(Expression leftExpression, Expression expression) {
private static Expression recursionBase(Expression leftExpression, Expression expression, SqlEditEnum sqlEditEnum) {
if (sqlEditEnum.equals(SqlEditEnum.NUMBER_FILTER)) {
return distinguishNumberFilter(leftExpression, expression);
}
if (sqlEditEnum.equals(SqlEditEnum.DATEDIFF)) {
return SqlParserReplaceHelper.distinguishDateDiffFilter(leftExpression, expression);
}
return expression;
}
private static Expression distinguishNumberFilter(Expression leftExpression, Expression expression) {
if (leftExpression instanceof LongValue) {
return null;
} else {

View File

@@ -6,7 +6,9 @@ import java.util.Objects;
import java.util.Set;
import java.util.ArrayList;
import com.tencent.supersonic.common.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.Alias;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.Function;
@@ -19,6 +21,7 @@ import net.sf.jsqlparser.expression.operators.relational.GreaterThanEquals;
import net.sf.jsqlparser.expression.operators.relational.MinorThan;
import net.sf.jsqlparser.expression.operators.relational.MinorThanEquals;
import net.sf.jsqlparser.expression.operators.relational.NotEqualsTo;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.statement.select.GroupByElement;
import net.sf.jsqlparser.statement.select.Join;
@@ -267,29 +270,17 @@ public class SqlParserReplaceHelper {
if (!(selectBody instanceof PlainSelect)) {
return sql;
}
List<PlainSelect> plainSelectList = new ArrayList<>();
plainSelectList.add((PlainSelect) selectBody);
List<PlainSelect> plainSelects = SqlParserSelectHelper.getPlainSelects(plainSelectList);
for (PlainSelect plainSelect : plainSelects) {
replaceFunction(plainSelect);
Expression where = ((PlainSelect) selectBody).getWhere();
try {
Expression expression = SqlParserRemoveHelper.filteredExpression(where, SqlEditEnum.DATEDIFF);
((PlainSelect) selectBody).setWhere(expression);
} catch (Exception e) {
log.info("replaceFunction has an exception:{}", e.toString());
}
return selectStatement.toString();
}
private static void replaceFunction(PlainSelect selectBody) {
PlainSelect plainSelect = selectBody;
//1. replace where dataDiff function
Expression where = plainSelect.getWhere();
FunctionReplaceVisitor visitor = new FunctionReplaceVisitor();
if (Objects.nonNull(where)) {
where.accept(visitor);
}
//2. add Waiting Expression
List<Expression> waitingForAdds = visitor.getWaitingForAdds();
addWaitingExpression(plainSelect, where, waitingForAdds);
}
private static void replaceHavingFunction(Map<String, String> functionMap, Expression having) {
if (Objects.nonNull(having)) {
if (having instanceof AndExpression) {
@@ -351,21 +342,6 @@ public class SqlParserReplaceHelper {
}
}
private static void addWaitingExpression(PlainSelect plainSelect, Expression where,
List<Expression> waitingForAdds) {
if (CollectionUtils.isEmpty(waitingForAdds)) {
return;
}
for (Expression expression : waitingForAdds) {
if (where == null) {
plainSelect.setWhere(expression);
} else {
where = new AndExpression(where, expression);
}
}
plainSelect.setWhere(where);
}
public static String replaceTable(String sql, String tableName) {
if (StringUtils.isEmpty(tableName)) {
return sql;
@@ -448,5 +424,46 @@ public class SqlParserReplaceHelper {
}
return selectStatement.toString();
}
public static Expression distinguishDateDiffFilter(Expression leftExpression, Expression expression) {
if (leftExpression instanceof Function) {
Function function = (Function) leftExpression;
if (function.getName().equals(JsqlConstants.DATE_FUNCTION)) {
ComparisonOperator comparisonOperator = (ComparisonOperator) expression;
List<Expression> leftExpressions = function.getParameters().getExpressions();
Column field = (Column) function.getParameters().getExpressions().get(1);
String columnName = field.getColumnName();
try {
String startDateValue = DateFunctionHelper.getStartDateStr(comparisonOperator, leftExpressions);
String endDateValue = DateFunctionHelper.getEndDateValue(leftExpressions);
String dateOperator = comparisonOperator.getStringExpression();
String endDateOperator = JsqlConstants.rightMap.get(dateOperator);
String startDateOperator = JsqlConstants.leftMap.get(dateOperator);
String endDateCondExpr = columnName + endDateOperator + StringUtil.getCommaWrap(endDateValue);
ComparisonOperator rightExpression = (ComparisonOperator)
CCJSqlParserUtil.parseCondExpression(endDateCondExpr);
String startDateCondExpr = columnName + StringUtil.getSpaceWrap(startDateOperator)
+ StringUtil.getCommaWrap(startDateValue);
ComparisonOperator newLeftExpression = (ComparisonOperator)
CCJSqlParserUtil.parseCondExpression(startDateCondExpr);
AndExpression andExpression = new AndExpression(newLeftExpression, rightExpression);
if (JsqlConstants.GREATER_THAN.equals(dateOperator)
|| JsqlConstants.GREATER_THAN_EQUALS.equals(dateOperator)) {
return newLeftExpression;
} else {
return CCJSqlParserUtil.parseCondExpression("(" + andExpression.toString() + ")");
}
} catch (JSQLParserException e) {
log.error("JSQLParserException", e);
}
}
return expression;
} else {
return expression;
}
}
}