[fix](headless)Fix a number of issues. (#2026)
Some checks are pending
supersonic CentOS CI / build (21) (push) Waiting to run
supersonic mac CI / build (21) (push) Waiting to run
supersonic ubuntu CI / build (21) (push) Waiting to run
supersonic windows CI / build (21) (push) Waiting to run

This commit is contained in:
Jun Zhang
2025-02-02 12:50:29 +08:00
committed by GitHub
parent de92b357df
commit d294fec2a0
19 changed files with 184 additions and 239 deletions

View File

@@ -1,6 +1,5 @@
package com.tencent.supersonic.common.jsqlparser;
import com.tencent.supersonic.common.util.ContextUtils;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.AnalyticExpression;
import net.sf.jsqlparser.expression.ExpressionVisitorAdapter;
@@ -14,6 +13,7 @@ import java.util.Map;
@Slf4j
public class FieldReplaceVisitor extends ExpressionVisitorAdapter {
private Map<String, String> fieldNameMap;
private ThreadLocal<Boolean> exactReplace = ThreadLocal.withInitial(() -> false);
@@ -24,8 +24,7 @@ public class FieldReplaceVisitor extends ExpressionVisitorAdapter {
@Override
public void visit(Column column) {
ReplaceService replaceService = ContextUtils.getBean(ReplaceService.class);
replaceService.replaceColumn(column, fieldNameMap, exactReplace.get());
SqlReplaceHelper.replaceColumn(column, fieldNameMap, exactReplace.get());
}
@Override

View File

@@ -1,21 +1,8 @@
package com.tencent.supersonic.common.jsqlparser;
import com.tencent.supersonic.common.util.ContextUtils;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.DoubleValue;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.ExpressionVisitorAdapter;
import net.sf.jsqlparser.expression.Function;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.operators.relational.ComparisonOperator;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.GreaterThan;
import net.sf.jsqlparser.expression.operators.relational.GreaterThanEquals;
import net.sf.jsqlparser.expression.operators.relational.InExpression;
import net.sf.jsqlparser.expression.operators.relational.MinorThan;
import net.sf.jsqlparser.expression.operators.relational.MinorThanEquals;
import net.sf.jsqlparser.expression.*;
import net.sf.jsqlparser.expression.operators.relational.*;
import net.sf.jsqlparser.schema.Column;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
@@ -28,13 +15,14 @@ import java.util.Objects;
@Slf4j
public class FieldValueReplaceVisitor extends ExpressionVisitorAdapter {
private boolean exactReplace;
private Map<String, Map<String, String>> filedNameToValueMap;
private final boolean exactReplace;
private final Map<String, Map<String, String>> filedNameToValueMap;
public FieldValueReplaceVisitor(boolean exactReplace,
Map<String, Map<String, String>> filedNameToValueMap) {
this.exactReplace = exactReplace;
this.filedNameToValueMap = filedNameToValueMap;
this.exactReplace = exactReplace;
}
@Override
@@ -137,9 +125,8 @@ public class FieldValueReplaceVisitor extends ExpressionVisitorAdapter {
private String getReplaceValue(Map<String, String> valueMap, String beforeValue) {
String afterValue = valueMap.get(String.valueOf(beforeValue));
if (StringUtils.isEmpty(afterValue) && !exactReplace) {
ReplaceService replaceService = ContextUtils.getBean(ReplaceService.class);
return replaceService.getReplaceValue(beforeValue, valueMap, false);
if (StringUtils.isEmpty(afterValue)) {
return SqlReplaceHelper.getReplaceValue(beforeValue, valueMap, exactReplace);
}
return afterValue;
}

View File

@@ -1,6 +1,5 @@
package com.tencent.supersonic.common.jsqlparser;
import com.tencent.supersonic.common.util.ContextUtils;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.Function;
@@ -15,8 +14,8 @@ import java.util.Map;
@Slf4j
public class GroupByReplaceVisitor implements GroupByVisitor {
private Map<String, String> fieldNameMap;
private boolean exactReplace;
private final boolean exactReplace;
private final Map<String, String> fieldNameMap;
public GroupByReplaceVisitor(Map<String, String> fieldNameMap, boolean exactReplace) {
this.fieldNameMap = fieldNameMap;
@@ -34,11 +33,10 @@ public class GroupByReplaceVisitor implements GroupByVisitor {
}
private void replaceExpression(Expression expression) {
ReplaceService replaceService = ContextUtils.getBean(ReplaceService.class);
if (expression instanceof Column) {
replaceService.replaceColumn((Column) expression, fieldNameMap, exactReplace);
SqlReplaceHelper.replaceColumn((Column) expression, fieldNameMap, exactReplace);
} else if (expression instanceof Function) {
replaceService.replaceFunction((Function) expression, fieldNameMap, exactReplace);
SqlReplaceHelper.replaceFunction((Function) expression, fieldNameMap, exactReplace);
}
}
}

View File

@@ -1,6 +1,5 @@
package com.tencent.supersonic.common.jsqlparser;
import com.tencent.supersonic.common.util.ContextUtils;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.Function;
import net.sf.jsqlparser.schema.Column;
@@ -10,8 +9,9 @@ import net.sf.jsqlparser.statement.select.OrderByVisitorAdapter;
import java.util.Map;
public class OrderByReplaceVisitor extends OrderByVisitorAdapter {
private Map<String, String> fieldNameMap;
private boolean exactReplace;
private final boolean exactReplace;
private final Map<String, String> fieldNameMap;
public OrderByReplaceVisitor(Map<String, String> fieldNameMap, boolean exactReplace) {
this.fieldNameMap = fieldNameMap;
@@ -21,12 +21,11 @@ public class OrderByReplaceVisitor extends OrderByVisitorAdapter {
@Override
public void visit(OrderByElement orderBy) {
Expression expression = orderBy.getExpression();
ReplaceService replaceService = ContextUtils.getBean(ReplaceService.class);
if (expression instanceof Column) {
replaceService.replaceColumn((Column) expression, fieldNameMap, exactReplace);
SqlReplaceHelper.replaceColumn((Column) expression, fieldNameMap, exactReplace);
}
if (expression instanceof Function) {
replaceService.replaceFunction((Function) expression, fieldNameMap, exactReplace);
SqlReplaceHelper.replaceFunction((Function) expression, fieldNameMap, exactReplace);
}
super.visit(orderBy);
}

View File

@@ -12,6 +12,7 @@ import java.util.Objects;
public class QueryExpressionReplaceVisitor extends ExpressionVisitorAdapter {
private Map<String, String> fieldExprMap;
private String lastColumnName;
public QueryExpressionReplaceVisitor(Map<String, String> fieldExprMap) {
this.fieldExprMap = fieldExprMap;
@@ -23,24 +24,26 @@ public class QueryExpressionReplaceVisitor extends ExpressionVisitorAdapter {
}
public void visit(SelectItem selectExpressionItem) {
Expression expression = selectExpressionItem.getExpression();
String toReplace = "";
String columnName = "";
if (expression instanceof Function) {
Function leftFunc = (Function) expression;
if (Objects.nonNull(leftFunc.getParameters())
&& leftFunc.getParameters().getExpressions().get(0) instanceof Column) {
Column column = (Column) leftFunc.getParameters().getExpressions().get(0);
columnName = column.getColumnName();
lastColumnName = column.getColumnName();
toReplace = getReplaceExpr(leftFunc, fieldExprMap);
}
}
if (expression instanceof Column) {
} else if (expression instanceof Column) {
Column column = (Column) expression;
columnName = column.getColumnName();
lastColumnName = column.getColumnName();
toReplace = getReplaceExpr((Column) expression, fieldExprMap);
} else if (expression instanceof BinaryExpression) {
BinaryExpression expr = (BinaryExpression) expression;
expr.setLeftExpression(replace(expr.getLeftExpression(), fieldExprMap));
expr.setRightExpression(replace(expr.getRightExpression(), fieldExprMap));
}
if (expression instanceof BinaryExpression) {
BinaryExpression binaryExpression = (BinaryExpression) expression;
visitBinaryExpression(binaryExpression);
@@ -51,7 +54,7 @@ public class QueryExpressionReplaceVisitor extends ExpressionVisitorAdapter {
if (Objects.nonNull(toReplaceExpr)) {
selectExpressionItem.setExpression(toReplaceExpr);
if (Objects.isNull(selectExpressionItem.getAlias())) {
selectExpressionItem.setAlias(new Alias(columnName, true));
selectExpressionItem.setAlias(new Alias(lastColumnName, true));
}
}
}
@@ -68,6 +71,18 @@ public class QueryExpressionReplaceVisitor extends ExpressionVisitorAdapter {
if (expression instanceof Column) {
toReplace = getReplaceExpr((Column) expression, fieldExprMap);
}
if (expression instanceof BinaryExpression) {
BinaryExpression binaryExpression = (BinaryExpression) expression;
binaryExpression
.setLeftExpression(replace(binaryExpression.getLeftExpression(), fieldExprMap));
binaryExpression.setRightExpression(
replace(binaryExpression.getRightExpression(), fieldExprMap));
}
if (expression instanceof Parenthesis) {
Parenthesis parenthesis = (Parenthesis) expression;
parenthesis.setExpression(replace(parenthesis.getExpression(), fieldExprMap));
}
if (!toReplace.isEmpty()) {
Expression replace = getExpression(toReplace);
if (Objects.nonNull(replace)) {

View File

@@ -1,74 +0,0 @@
package com.tencent.supersonic.common.jsqlparser;
import com.tencent.supersonic.common.util.EditDistanceUtils;
import com.tencent.supersonic.common.util.StringUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.Function;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.schema.Column;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.stream.Collectors;
@Slf4j
@Service
@Data
public class ReplaceService {
@Value("${s2.replace.threshold:0.4}")
private double replaceColumnThreshold;
public void replaceFunction(Function expression, Map<String, String> fieldNameMap,
boolean exactReplace) {
Function function = expression;
ExpressionList<?> expressions = function.getParameters();
for (Expression column : expressions) {
if (column instanceof Column) {
replaceColumn((Column) column, fieldNameMap, exactReplace);
}
}
}
public void replaceColumn(Column column, Map<String, String> fieldNameMap,
boolean exactReplace) {
String columnName = StringUtil.replaceBackticks(column.getColumnName());
String replaceColumn = getReplaceValue(columnName, fieldNameMap, exactReplace);
if (StringUtils.isNotBlank(replaceColumn)) {
column.setColumnName(replaceColumn);
}
}
public String getReplaceValue(String beforeValue, Map<String, String> valueMap,
boolean exactReplace) {
String replaceValue = valueMap.get(beforeValue);
if (StringUtils.isNotBlank(replaceValue)) {
return replaceValue;
}
if (exactReplace) {
return null;
}
Optional<Entry<String, String>> first = valueMap.entrySet().stream().sorted((k1, k2) -> {
String k1Value = k1.getKey();
String k2Value = k2.getKey();
Double k1Similarity = EditDistanceUtils.getSimilarity(beforeValue, k1Value);
Double k2Similarity = EditDistanceUtils.getSimilarity(beforeValue, k2Value);
return k2Similarity.compareTo(k1Similarity);
}).collect(Collectors.toList()).stream().findFirst();
if (first.isPresent()) {
replaceValue = first.get().getValue();
double similarity = EditDistanceUtils.getSimilarity(beforeValue, replaceValue);
if (similarity > replaceColumnThreshold) {
return replaceValue;
}
}
return beforeValue;
}
}

View File

@@ -1,6 +1,7 @@
package com.tencent.supersonic.common.jsqlparser;
import com.tencent.supersonic.common.pojo.enums.AggOperatorEnum;
import com.tencent.supersonic.common.util.EditDistanceUtils;
import com.tencent.supersonic.common.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException;
@@ -25,21 +26,18 @@ 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.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.*;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
/**
* Sql Parser replace Helper
*/
@Slf4j
public class SqlReplaceHelper {
private final static double replaceColumnThreshold = 0.4;
public static String replaceAggFields(String sql,
Map<String, Pair<String, String>> fieldNameToAggMap) {
Select selectStatement = SqlSelectHelper.getSelect(sql);
@@ -769,4 +767,54 @@ public class SqlReplaceHelper {
}
}
}
public static void replaceFunction(Function expression, Map<String, String> fieldNameMap,
boolean exactReplace) {
Function function = expression;
ExpressionList<?> expressions = function.getParameters();
for (Expression column : expressions) {
if (column instanceof Column) {
replaceColumn((Column) column, fieldNameMap, exactReplace);
}
}
}
public static void replaceColumn(Column column, Map<String, String> fieldNameMap,
boolean exactReplace) {
String columnName = StringUtil.replaceBackticks(column.getColumnName());
String replaceColumn = getReplaceValue(columnName, fieldNameMap, exactReplace);
if (StringUtils.isNotBlank(replaceColumn)) {
log.debug("Replaced column {} to {}", column.getColumnName(), replaceColumn);
column.setColumnName(replaceColumn);
}
}
public static String getReplaceValue(String beforeValue, Map<String, String> valueMap,
boolean exactReplace) {
String replaceValue = valueMap.get(beforeValue);
if (StringUtils.isNotBlank(replaceValue)) {
return replaceValue;
}
if (exactReplace) {
return null;
}
Optional<Map.Entry<String, String>> first =
valueMap.entrySet().stream().sorted((k1, k2) -> {
String k1Value = k1.getKey();
String k2Value = k2.getKey();
Double k1Similarity = EditDistanceUtils.getSimilarity(beforeValue, k1Value);
Double k2Similarity = EditDistanceUtils.getSimilarity(beforeValue, k2Value);
return k2Similarity.compareTo(k1Similarity);
}).collect(Collectors.toList()).stream().findFirst();
if (first.isPresent()) {
replaceValue = first.get().getValue();
double similarity = EditDistanceUtils.getSimilarity(beforeValue, replaceValue);
if (similarity > replaceColumnThreshold) {
return replaceValue;
}
}
return beforeValue;
}
}

View File

@@ -459,6 +459,9 @@ public class SqlSelectHelper {
.map(fieldExpression -> fieldExpression.getFieldName()).filter(Objects::nonNull)
.collect(Collectors.toSet());
result.addAll(collect);
Set<String> aliases = getAliasFields(plainSelect);
result.removeAll(aliases);
}
public static List<FieldExpression> getOrderByExpressions(String sql) {

View File

@@ -1,38 +1,16 @@
package com.tencent.supersonic.common.jsqlparser;
import com.tencent.supersonic.common.pojo.enums.AggOperatorEnum;
import com.tencent.supersonic.common.util.ContextUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.junit.Assert;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import static org.mockito.Mockito.mockStatic;
import java.util.*;
/**
* SqlParserReplaceHelperTest
*/
class SqlReplaceHelperTest {
private MockedStatic<ContextUtils> mockedContextUtils;
@BeforeEach
public void setUp() {
ReplaceService replaceService = new ReplaceService();
replaceService.setReplaceColumnThreshold(0.4);
// Mock the static method ContextUtils.getBean
mockedContextUtils = mockStatic(ContextUtils.class);
mockedContextUtils.when(() -> ContextUtils.getBean(ReplaceService.class))
.thenReturn(replaceService);
}
@Test
void testReplaceAggField() {
@@ -385,11 +363,4 @@ class SqlReplaceHelperTest {
return fieldToBizName;
}
@AfterEach
public void tearDown() {
// Close the mocked static context
if (mockedContextUtils != null) {
mockedContextUtils.close();
}
}
}