diff --git a/hsweb-commons/hsweb-commons-crud/pom.xml b/hsweb-commons/hsweb-commons-crud/pom.xml
index 8b53d6d44..3e3892d55 100644
--- a/hsweb-commons/hsweb-commons-crud/pom.xml
+++ b/hsweb-commons/hsweb-commons-crud/pom.xml
@@ -12,6 +12,57 @@
hsweb-commons-crud
${project.artifactId}
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+
+
+ net/sf/jsqlparser/**
+ org/hswebframework/web/crud/shaded/jsqlparser/**
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 3.5.1
+
+
+ package
+
+ shade
+
+
+
+
+ com.github.jsqlparser:jsqlparser
+
+
+
+
+ net.sf.jsqlparser
+ org.hswebframework.web.crud.shaded.jsqlparser
+
+
+
+
+ *:*
+
+ META-INF/*.SF
+ META-INF/*.DSA
+ META-INF/*.RSA
+
+
+
+
+
+
+
+
+
+
@@ -148,7 +199,7 @@
com.github.jsqlparser
jsqlparser
- 4.6
+ 5.3
@@ -166,4 +217,4 @@
-
\ No newline at end of file
+
diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/query/QueryAnalyzerImpl.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/query/QueryAnalyzerImpl.java
index fb5e13d48..5dc4cc5c7 100644
--- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/query/QueryAnalyzerImpl.java
+++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/query/QueryAnalyzerImpl.java
@@ -3,12 +3,11 @@
import lombok.Getter;
import lombok.SneakyThrows;
import net.sf.jsqlparser.expression.*;
-import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table;
+import net.sf.jsqlparser.statement.piped.FromQuery;
import net.sf.jsqlparser.statement.select.*;
-import net.sf.jsqlparser.statement.values.ValuesStatement;
import org.apache.commons.collections4.CollectionUtils;
import org.hswebframework.ezorm.core.meta.FeatureSupportedMetadata;
import org.hswebframework.ezorm.core.param.Sort;
@@ -24,29 +23,51 @@
import java.util.*;
-import static net.sf.jsqlparser.statement.select.PlainSelect.getFormatedList;
+import static net.sf.jsqlparser.statement.select.Select.getFormattedList;
import static org.hswebframework.ezorm.rdb.operator.builder.fragments.TermFragmentBuilder.createFeatureId;
-class QueryAnalyzerImpl implements FromItemVisitor, SelectItemVisitor, SelectVisitor, QueryAnalyzer {
+class QueryAnalyzerImpl implements FromItemVisitor, SelectItemVisitor, SelectVisitor, QueryAnalyzer {
+
+ private static final String UNSUPPORTED_DISTANCE_OPERATOR = "<=>";
+
+ private static final List PARSER_OPERATOR_PLACEHOLDERS = Arrays.asList("!~*", "~*", "@@", "@>", "<@", "&&", "~");
private final DatabaseOperator database;
private String sql;
- private final SelectBody parsed;
+ private final net.sf.jsqlparser.statement.select.Select parsed;
+
+ private String parserOperatorPlaceholder;
private QueryAnalyzer.Select select;
private final Map joins = new LinkedHashMap<>();
- private final List withItems = new ArrayList<>();
+ private final List> withItems = new ArrayList<>();
private QueryRefactor injector;
private volatile Map columnMappings;
private final Map virtualTable = new HashMap<>();
+ private static T acceptFromItem(FromItem fromItem, FromItemVisitor visitor) {
+ return fromItem.accept(visitor, null);
+ }
+
+ private static T acceptSelect(net.sf.jsqlparser.statement.select.Select select, SelectVisitor visitor) {
+ return select.accept(visitor, null);
+ }
+
+ private static T acceptWithItem(WithItem> withItem, SelectVisitor visitor) {
+ return withItem.accept(visitor, null);
+ }
+
+ private static T acceptSelectItem(SelectItem> selectItem, SelectItemVisitor visitor) {
+ return selectItem.accept(visitor, null);
+ }
+
@Override
public String originalSql() {
return sql;
@@ -88,6 +109,11 @@ public List joins() {
this.sql = sql;
}
+ private QueryAnalyzerImpl(DatabaseOperator database, ParsedSelect parsed) {
+ this(database, parsed.select);
+ this.parserOperatorPlaceholder = parsed.operatorPlaceholder;
+ }
+
public boolean columnIsExpression(String name, int index) {
@@ -178,48 +204,69 @@ private Column getColumnOrSelectColumn(String name) {
}
@SneakyThrows
- private static net.sf.jsqlparser.statement.select.Select parse(String sql) {
- return ((net.sf.jsqlparser.statement.select.Select) CCJSqlParserUtil.parse(sql));
+ private static ParsedSelect parse(String sql) {
+ String operatorPlaceholder = null;
+ String sqlToParse = sql;
+ if (sql.contains(UNSUPPORTED_DISTANCE_OPERATOR)) {
+ operatorPlaceholder = PARSER_OPERATOR_PLACEHOLDERS
+ .stream()
+ .filter(candidate -> !sql.contains(candidate))
+ .findFirst()
+ .orElseThrow(() -> new IllegalArgumentException("Unable to parse sql with operator " + UNSUPPORTED_DISTANCE_OPERATOR));
+ sqlToParse = sql.replace(UNSUPPORTED_DISTANCE_OPERATOR, operatorPlaceholder);
+ }
+ return new ParsedSelect(
+ ((net.sf.jsqlparser.statement.select.Select) CCJSqlParserUtil.parse(sqlToParse)),
+ operatorPlaceholder
+ );
}
- QueryAnalyzerImpl(DatabaseOperator database, SelectBody selectBody, QueryAnalyzerImpl parent) {
- this.database = database;
- this.virtualTable.putAll(parent.virtualTable);
- if (null != selectBody) {
- this.parsed = selectBody;
- selectBody.accept(this);
- } else {
- this.parsed = null;
+ private static net.sf.jsqlparser.statement.select.Select unwrapParenthesedSelect(net.sf.jsqlparser.statement.select.Select select) {
+ while (select instanceof ParenthesedSelect parenthesedSelect) {
+ select = parenthesedSelect.getSelect();
}
+ return select;
+ }
+
+ private String restoreParserPlaceholders(Object sql) {
+ return sql == null ? null : restoreParserPlaceholders(sql.toString());
}
- QueryAnalyzerImpl(DatabaseOperator database, SubSelect select, QueryAnalyzerImpl parent) {
- this.parsed = select.getSelectBody();
+ private String restoreParserPlaceholders(String sql) {
+ if (parserOperatorPlaceholder == null || sql == null) {
+ return sql;
+ }
+ return sql.replace(parserOperatorPlaceholder, UNSUPPORTED_DISTANCE_OPERATOR);
+ }
+
+ QueryAnalyzerImpl(DatabaseOperator database, net.sf.jsqlparser.statement.select.Select selectBody, QueryAnalyzerImpl parent) {
this.database = database;
this.virtualTable.putAll(parent.virtualTable);
- //with ...
- if (CollectionUtils.isNotEmpty(select.getWithItemsList())) {
- for (WithItem withItem : select.getWithItemsList()) {
- withItem.accept(this);
+ if (null != selectBody) {
+ this.parsed = selectBody;
+ if (CollectionUtils.isNotEmpty(selectBody.getWithItemsList())) {
+ for (WithItem> withItem : selectBody.getWithItemsList()) {
+ acceptWithItem(withItem, this);
+ }
}
- }
- if (this.parsed != null) {
- this.parsed.accept(this);
+ acceptSelect(selectBody, this);
+ } else {
+ this.parsed = null;
}
}
QueryAnalyzerImpl(DatabaseOperator database, net.sf.jsqlparser.statement.select.Select select) {
- this.parsed = select.getSelectBody();
+ this.parsed = select;
this.database = database;
//with ...
if (CollectionUtils.isNotEmpty(select.getWithItemsList())) {
- for (WithItem withItem : select.getWithItemsList()) {
- withItem.accept(this);
+ for (WithItem> withItem : select.getWithItemsList()) {
+ acceptWithItem(withItem, this);
}
}
if (this.parsed != null) {
- this.parsed.accept(this);
+ acceptSelect(this.parsed, this);
}
}
@@ -239,7 +286,7 @@ private String parsePlainName(String name) {
}
@Override
- public void visit(net.sf.jsqlparser.schema.Table tableName) {
+ public Void visit(net.sf.jsqlparser.schema.Table tableName, S context) {
String schema = parsePlainName(tableName.getSchemaName());
String name = parsePlainName(tableName.getName());
@@ -273,17 +320,28 @@ public void visit(net.sf.jsqlparser.schema.Table tableName) {
);
select = new QueryAnalyzer.Select(new ArrayList<>(), table);
-
+ return null;
}
// select * from ( select a,b,c from table ) t
@Override
- public void visit(SubSelect subSelect) {
- visit(subSelect, subSelect.getAlias() == null ? null : subSelect.getAlias().getName());
+ public Void visit(ParenthesedSelect select, S context) {
+ visit(select, select.getAlias() == null ? null : select.getAlias().getName());
+ return null;
+ }
+
+ @Override
+ public void visit(ParenthesedSelect select) {
+ visit(select, (Object) null);
}
- public void visit(SubSelect subSelect, String alias) {
- SelectBody body = subSelect.getSelectBody();
+ private void visit(ParenthesedSelect subSelect, String alias) {
+ net.sf.jsqlparser.statement.select.Select body = subSelect.getSelect();
+ if (body instanceof Values values) {
+ visitValues(values, subSelect.getAlias() == null ? values.getAlias() : subSelect.getAlias());
+ return;
+ }
+
QueryAnalyzerImpl sub = new QueryAnalyzerImpl(database, body, this);
Map columnMap = new LinkedHashMap<>();
for (Column column : sub.select.getColumnList()) {
@@ -327,36 +385,28 @@ public void visit(SubSelect subSelect, String alias) {
}
@Override
- public void visit(SubJoin subjoin) {
- for (net.sf.jsqlparser.statement.select.Join join : subjoin.getJoinList()) {
- join.getRightItem().accept(this);
- }
+ public Void visit(LateralSubSelect lateralSubSelect, S context) {
+ this.visit((ParenthesedSelect) lateralSubSelect,
+ lateralSubSelect.getAlias() == null ? null : lateralSubSelect.getAlias().getName());
+ return null;
}
@Override
public void visit(LateralSubSelect lateralSubSelect) {
- this.visit(lateralSubSelect.getSubSelect(),
- lateralSubSelect.getAlias() == null ? null : lateralSubSelect.getAlias().getName());
+ visit(lateralSubSelect, (Object) null);
}
- @Override
- public void visit(ValuesList valuesList) {
- if (valuesList.getAlias() == null) {
- throw new IllegalArgumentException("valuesList[" + valuesList + "] must have alias");
+ private void visitValues(Values values, Alias alias) {
+ if (alias == null) {
+ throw new IllegalArgumentException("values[" + values + "] must have alias");
}
- String name = parsePlainName(valuesList.getAlias().getName());
+ String name = parsePlainName(alias.getName());
FakeTable view = new FakeTable();
view.setSchema(database.getMetadata().getCurrentSchema());
- if (valuesList.getColumnNames() != null) {
- //获取会自动创建列
- for (String columnName : valuesList.getColumnNames()) {
- RDBColumnMetadata ignore = view.getColumn(parsePlainName(columnName)).orElse(null);
- }
- }
- if (valuesList.getAlias().getAliasColumns() != null) {
- for (Alias.AliasColumn alias : valuesList.getAlias().getAliasColumns()) {
- RDBColumnMetadata ignore = view.getColumn(parsePlainName(alias.name)).orElse(null);
+ if (alias.getAliasColumns() != null) {
+ for (Alias.AliasColumn aliasColumn : alias.getAliasColumns()) {
+ RDBColumnMetadata ignore = view.getColumn(parsePlainName(aliasColumn.name)).orElse(null);
}
}
@@ -371,7 +421,7 @@ public void visit(ValuesList valuesList) {
}
@Override
- public void visit(TableFunction tableFunction) {
+ public Void visit(TableFunction tableFunction, S context) {
if (tableFunction.getAlias() == null) {
throw new IllegalArgumentException("table function[" + tableFunction + "] must have alias");
}
@@ -386,19 +436,42 @@ public void visit(TableFunction tableFunction) {
Table table = new Table(name, view);
select = new QueryAnalyzer.Select(new ArrayList<>(), table);
-
+ return null;
}
@Override
- public void visit(ParenthesisFromItem aThis) {
- aThis.getFromItem().accept(this);
+ public Void visit(ParenthesedFromItem aThis, S context) {
+ if (aThis.getFromItem() instanceof Values values) {
+ visitValues(values, aThis.getAlias());
+ } else {
+ acceptFromItem(aThis.getFromItem(), this);
+ }
+ if (CollectionUtils.isNotEmpty(aThis.getJoins())) {
+ for (net.sf.jsqlparser.statement.select.Join join : aThis.getJoins()) {
+ FromItem fromItem = join.getRightItem();
+ QueryAnalyzerImpl joinAn = new QueryAnalyzerImpl(database, (net.sf.jsqlparser.statement.select.Select) null, this);
+ acceptFromItem(fromItem, joinAn);
+
+ Join.Type type;
+ if (join.isLeft()) {
+ type = Join.Type.left;
+ } else if (join.isRight()) {
+ type = Join.Type.right;
+ } else if (join.isInner()) {
+ type = Join.Type.inner;
+ } else {
+ type = null;
+ }
+ joins.put(joinAn.select.table.alias, new Join(joinAn.select.table.alias, type, joinAn.select.table));
+ }
+ }
String alias = parsePlainName(aThis.getAlias() == null ? null : aThis.getAlias().getName());
if (alias != null) {
this.select = select.newSelectAlias(alias);
}
+ return null;
}
- @Override
public void visit(AllColumns allColumns) {
putSelectColumns(select.table, select.columnList);
@@ -435,7 +508,6 @@ private void putSelectColumns(QueryAnalyzer.Table table, List expr;
- public ExpressionColumn(String alias, String owner, RDBColumnMetadata metadata, SelectItem expr) {
+ public ExpressionColumn(String alias, String owner, RDBColumnMetadata metadata, SelectItem> expr) {
super(alias, alias, owner, metadata);
this.expr = expr;
}
@@ -501,8 +573,17 @@ private void refactorAlias(Alias alias) {
}
@Override
- public void visit(SelectExpressionItem selectExpressionItem) {
+ public Void visit(SelectItem extends Expression> selectExpressionItem, S context) {
Expression expr = selectExpressionItem.getExpression();
+ if (expr instanceof AllColumns allColumns) {
+ visit(allColumns);
+ return null;
+ }
+ if (expr instanceof AllTableColumns allTableColumns) {
+ visit(allTableColumns);
+ return null;
+ }
+
Alias alias = selectExpressionItem.getAlias();
if (!(expr instanceof net.sf.jsqlparser.schema.Column column)) {
@@ -510,7 +591,7 @@ public void visit(SelectExpressionItem selectExpressionItem) {
refactorAlias(alias);
select.columnList.add(new ExpressionColumn(aliasName, null, null, selectExpressionItem));
- return;
+ return null;
}
String columnName = parsePlainName(column.getColumnName());
@@ -530,7 +611,7 @@ public void visit(SelectExpressionItem selectExpressionItem) {
if (null != c) {
if (c.metadata == null) {
select.columnList.add(new QueryAnalyzer.Column(c.getName(), aliasName, table.alias, null));
- return;
+ return null;
}
metadata = c.metadata;
}
@@ -542,19 +623,18 @@ public void visit(SelectExpressionItem selectExpressionItem) {
}
select.columnList.add(new QueryAnalyzer.Column(metadata.getRealName(), aliasName, table.alias, metadata));
-
-
+ return null;
}
@Override
- public void visit(PlainSelect select) {
+ public Void visit(PlainSelect select, S context) {
FromItem from = select.getFromItem();
if (from == null) {
throw new IllegalArgumentException("select can not be without 'from'");
}
- from.accept(this);
+ acceptFromItem(from, this);
List joinList = select.getJoins();
@@ -562,8 +642,8 @@ public void visit(PlainSelect select) {
if (joinList != null) {
for (net.sf.jsqlparser.statement.select.Join join : joinList) {
FromItem fromItem = join.getRightItem();
- QueryAnalyzerImpl joinAn = new QueryAnalyzerImpl(database, (SelectBody) null, this);
- fromItem.accept(joinAn);
+ QueryAnalyzerImpl joinAn = new QueryAnalyzerImpl(database, (net.sf.jsqlparser.statement.select.Select) null, this);
+ acceptFromItem(fromItem, joinAn);
Join.Type type;
if (join.isLeft()) {
@@ -579,34 +659,44 @@ public void visit(PlainSelect select) {
}
}
- for (SelectItem selectItem : select.getSelectItems()) {
- selectItem.accept(this);
+ for (SelectItem> selectItem : select.getSelectItems()) {
+ acceptSelectItem(selectItem, this);
}
+ return null;
}
@Override
- public void visit(SetOperationList setOpList) {
+ public void visit(PlainSelect select) {
+ visit(select, (Object) null);
+ }
+
+ @Override
+ public Void visit(SetOperationList setOpList, S context) {
//union
- for (SelectBody body : setOpList.getSelects()) {
- body.accept(this);
+ for (net.sf.jsqlparser.statement.select.Select body : setOpList.getSelects()) {
+ acceptSelect(body, this);
// break;
}
+ return null;
+ }
-
+ @Override
+ public void visit(SetOperationList setOpList) {
+ visit(setOpList, (Object) null);
}
@Override
- public void visit(WithItem withItem) {
+ public Void visit(WithItem> withItem, S context) {
withItems.add(withItem);
- String name = withItem.getName();
+ String name = withItem.getAlias().getName();
RDBViewMetadata view = new RDBViewMetadata();
view.setName(name);
view.setSchema(database.getMetadata().getCurrentSchema());
virtualTable.put(name, view);
- if (withItem.getSubSelect() != null) {
- QueryAnalyzerImpl analyzer = new QueryAnalyzerImpl(database, withItem.getSubSelect(), this);
+ if (withItem.getSelect() != null) {
+ QueryAnalyzerImpl analyzer = new QueryAnalyzerImpl(database, unwrapParenthesedSelect(withItem.getSelect()), this);
for (Column column : analyzer.select.getColumnList()) {
RDBColumnMetadata metadata;
if (column.getMetadata() == null) {
@@ -619,18 +709,39 @@ public void visit(WithItem withItem) {
view.addColumn(metadata);
}
}
+ return null;
+ }
+
+ @Override
+ public Void visit(Values values, S context) {
+ visitValues(values, values.getAlias());
+ return null;
+ }
+
+ @Override
+ public void visit(Values values) {
+ visit(values, (Object) null);
+ }
+
+ @Override
+ public Void visit(TableStatement tableStatement, S context) {
+ return null;
}
@Override
- public void visit(ValuesStatement aThis) {
+ public void visit(TableStatement tableStatement) {
+ }
+ @Override
+ public Void visit(FromQuery fromQuery, S context) {
+ throw new UnsupportedOperationException("Pipe query syntax is not supported");
}
private void initInjector() {
SimpleQueryRefactor injector = new SimpleQueryRefactor();
- parsed.accept(injector);
- for (WithItem withItem : withItems) {
- withItem.accept(injector);
+ acceptSelect(parsed, injector);
+ for (WithItem> withItem : withItems) {
+ acceptWithItem(withItem, injector);
}
this.injector = injector;
}
@@ -708,7 +819,7 @@ public SqlFragments createTermFragments(QueryAnalyzerImpl impl, Term term) {
static QueryAnalyzerTermsFragmentBuilder TERMS_BUILDER = new QueryAnalyzerTermsFragmentBuilder();
- class SimpleQueryRefactor implements QueryRefactor, SelectVisitor {
+ class SimpleQueryRefactor implements QueryRefactor, SelectVisitor {
private String prefix = "";
private String from;
@@ -748,7 +859,7 @@ private void initColumns(StringBuilder columns) {
columns.append(",");
}
if (column instanceof ExpressionColumn) {
- columns.append(((ExpressionColumn) column).expr);
+ columns.append(restoreParserPlaceholders(((ExpressionColumn) column).expr));
fastCount = false;
continue;
}
@@ -762,7 +873,7 @@ private void initColumns(StringBuilder columns) {
}
@Override
- public void visit(PlainSelect plainSelect) {
+ public Void visit(PlainSelect plainSelect, S context) {
StringBuilder from = new StringBuilder();
StringBuilder columns = new StringBuilder();
@@ -779,8 +890,8 @@ public void visit(PlainSelect plainSelect) {
if (plainSelect.getSelectItems() != null) {
PrepareStatementVisitor visitor = new PrepareStatementVisitor();
- for (SelectItem selectItem : plainSelect.getSelectItems()) {
- selectItem.accept(visitor);
+ for (SelectItem> selectItem : plainSelect.getSelectItems()) {
+ acceptSelectItem(selectItem, visitor);
}
prefixParameters += visitor.parameterSize;
}
@@ -788,9 +899,9 @@ public void visit(PlainSelect plainSelect) {
if (plainSelect.getFromItem() != null) {
from.append("FROM ");
- from.append(plainSelect.getFromItem());
+ from.append(restoreParserPlaceholders(plainSelect.getFromItem()));
PrepareStatementVisitor visitor = new PrepareStatementVisitor();
- plainSelect.getFromItem().accept(visitor);
+ acceptFromItem(plainSelect.getFromItem(), visitor);
prefixParameters += visitor.parameterSize;
}
@@ -798,12 +909,12 @@ public void visit(PlainSelect plainSelect) {
PrepareStatementVisitor visitor = new PrepareStatementVisitor();
for (net.sf.jsqlparser.statement.select.Join join : plainSelect.getJoins()) {
if (join.isSimple()) {
- from.append(", ").append(join);
+ from.append(", ").append(restoreParserPlaceholders(join));
} else {
- from.append(" ").append(join);
+ from.append(" ").append(restoreParserPlaceholders(join));
}
if (null != join.getRightItem()) {
- join.getRightItem().accept(visitor);
+ acceptFromItem(join.getRightItem(), visitor);
}
if (null != join.getOnExpressions()) {
for (Expression onExpression : join.getOnExpressions()) {
@@ -818,7 +929,7 @@ public void visit(PlainSelect plainSelect) {
PrepareStatementVisitor visitor = new PrepareStatementVisitor();
plainSelect.getWhere().accept(visitor);
prefixParameters += visitor.parameterSize;
- where = plainSelect.getWhere().toString();
+ where = restoreParserPlaceholders(plainSelect.getWhere());
}
if (plainSelect.getOrderByElements() != null) {
@@ -827,12 +938,12 @@ public void visit(PlainSelect plainSelect) {
orderByElement.getExpression().accept(visitor);
}
suffixParameters = visitor.parameterSize;
- orderBy = getFormatedList(plainSelect.getOrderByElements(), "");
+ orderBy = restoreParserPlaceholders(getFormattedList(plainSelect.getOrderByElements(), ""));
}
if (plainSelect.getGroupBy() != null) {
fastCount = false;
- suffix.append(' ').append(plainSelect.getGroupBy());
+ suffix.append(' ').append(restoreParserPlaceholders(plainSelect.getGroupBy()));
PrepareStatementVisitor visitor = new PrepareStatementVisitor();
plainSelect.getGroupBy().getGroupByExpressionList().accept(visitor);
@@ -844,48 +955,73 @@ public void visit(PlainSelect plainSelect) {
PrepareStatementVisitor visitor = new PrepareStatementVisitor();
plainSelect.getHaving().accept(visitor);
suffixParameters = visitor.parameterSize;
- suffix.append(" HAVING ").append(plainSelect.getHaving());
+ suffix.append(" HAVING ").append(restoreParserPlaceholders(plainSelect.getHaving()));
}
this.columns = columns.toString();
this.from = from.toString();
this.suffix = suffix.toString();
-
+ return null;
}
@Override
- public void visit(SetOperationList setOpList) {
+ public Void visit(SetOperationList setOpList, S context) {
StringBuilder from = new StringBuilder();
StringBuilder columns = new StringBuilder();
initColumns(columns);
from.append("FROM (");
- from.append(setOpList);
+ from.append(restoreParserPlaceholders(setOpList));
from.append(") ");
from.append(select.table.alias);
this.from = from.toString();
this.columns = columns.toString();
this.suffix = "";
+ return null;
+ }
+ @Override
+ public Void visit(ParenthesedSelect select, S context) {
+ if (select.getSelect() != null) {
+ acceptSelect(select.getSelect(), this);
+ }
+ return null;
}
@Override
- public void visit(WithItem withItem) {
+ public Void visit(WithItem> withItem, S context) {
if (!StringUtils.hasText(prefix)) {
prefix += "WITH ";
}
- prefix += withItem;
+ prefix += restoreParserPlaceholders(withItem);
PrepareStatementVisitor visitor = new PrepareStatementVisitor();
- withItem.accept(visitor);
+ acceptWithItem(withItem, visitor);
prefixParameters += visitor.parameterSize;
+ return null;
}
@Override
- public void visit(ValuesStatement aThis) {
+ public Void visit(Values values, S context) {
PrepareStatementVisitor visitor = new PrepareStatementVisitor();
- aThis.accept(visitor);
+ values.getExpressions().accept(visitor);
+ return null;
+ }
+
+ @Override
+ public Void visit(LateralSubSelect lateralSubSelect, S context) {
+ return visit((ParenthesedSelect) lateralSubSelect, context);
+ }
+
+ @Override
+ public Void visit(TableStatement tableStatement, S context) {
+ return null;
+ }
+
+ @Override
+ public Void visit(FromQuery fromQuery, S context) {
+ throw new UnsupportedOperationException("Pipe query syntax is not supported");
}
public Object[] getPrefixParameters(Object... args) {
@@ -1074,7 +1210,7 @@ private void appendWhere(AppendableSqlFragments sql, QueryParamEntity param) {
@Getter
- static class PrepareStatementVisitor extends ExpressionVisitorAdapter implements FromItemVisitor, SelectVisitor {
+ static class PrepareStatementVisitor extends ExpressionVisitorAdapter implements FromItemVisitor, SelectVisitor {
private int parameterSize;
public PrepareStatementVisitor() {
@@ -1082,73 +1218,80 @@ public PrepareStatementVisitor() {
}
@Override
- public void visit(JdbcParameter parameter) {
+ public Void visit(JdbcParameter parameter, S context) {
parameterSize++;
- super.visit(parameter);
+ return super.visit(parameter, context);
}
@Override
- public void visit(net.sf.jsqlparser.schema.Table tableName) {
-
+ public Void visit(net.sf.jsqlparser.schema.Table tableName, S context) {
+ return null;
}
@Override
- public void visit(SubJoin subjoin) {
- if (subjoin.getLeft() != null) {
- subjoin.getLeft().accept(this);
+ public Void visit(ParenthesedFromItem fromItem, S context) {
+ if (fromItem.getFromItem() != null) {
+ acceptFromItem(fromItem.getFromItem(), this);
}
- if (CollectionUtils.isNotEmpty(subjoin.getJoinList())) {
- for (net.sf.jsqlparser.statement.select.Join join : subjoin.getJoinList()) {
+ if (CollectionUtils.isNotEmpty(fromItem.getJoins())) {
+ for (net.sf.jsqlparser.statement.select.Join join : fromItem.getJoins()) {
if (join.getRightItem() != null) {
- join.getRightItem().accept(this);
+ acceptFromItem(join.getRightItem(), this);
}
if (join.getOnExpressions() != null) {
join.getOnExpressions().forEach(expr -> expr.accept(this));
}
}
}
+ return null;
}
@Override
- public void visit(LateralSubSelect lateralSubSelect) {
- if (lateralSubSelect.getSubSelect() != null) {
- lateralSubSelect.getSubSelect().accept((ExpressionVisitor) this);
+ public Void visit(LateralSubSelect lateralSubSelect, S context) {
+ if (lateralSubSelect.getSelect() != null) {
+ acceptSelect(lateralSubSelect.getSelect(), this);
}
+ return null;
}
@Override
- public void visit(ValuesList valuesList) {
- if (valuesList.getMultiExpressionList() != null) {
- for (ExpressionList expressionList : valuesList.getMultiExpressionList().getExpressionLists()) {
- expressionList.getExpressions().forEach(expr -> expr.accept(this));
- }
+ public void visit(LateralSubSelect lateralSubSelect) {
+ visit(lateralSubSelect, (Object) null);
+ }
+
+ @Override
+ public Void visit(Values values, S context) {
+ if (values.getExpressions() != null) {
+ values.getExpressions().accept(this);
}
+ return null;
}
@Override
- public void visit(TableFunction tableFunction) {
- tableFunction.getFunction().accept(this);
+ public void visit(Values values) {
+ visit(values, (Object) null);
}
@Override
- public void visit(ParenthesisFromItem aThis) {
- aThis.getFromItem().accept(this);
+ public Void visit(TableFunction tableFunction, S context) {
+ tableFunction.getFunction().accept(this);
+ return null;
}
@Override
- public void visit(PlainSelect plainSelect) {
- plainSelect.getFromItem().accept(this);
+ public Void visit(PlainSelect plainSelect, S context) {
+ acceptFromItem(plainSelect.getFromItem(), this);
if (plainSelect.getJoins() != null) {
for (net.sf.jsqlparser.statement.select.Join join : plainSelect.getJoins()) {
- join.getRightItem().accept(this);
+ acceptFromItem(join.getRightItem(), this);
if (join.getOnExpressions() != null) {
join.getOnExpressions().forEach(expr -> expr.accept(this));
}
}
}
if (plainSelect.getSelectItems() != null) {
- for (SelectItem selectItem : plainSelect.getSelectItems()) {
- selectItem.accept(this);
+ for (SelectItem> selectItem : plainSelect.getSelectItems()) {
+ acceptSelectItem(selectItem, this);
}
}
if (plainSelect.getWhere() != null) {
@@ -1159,7 +1302,7 @@ public void visit(PlainSelect plainSelect) {
}
if (plainSelect.getDistinct() != null && plainSelect.getDistinct().getOnSelectItems() != null) {
- plainSelect.getDistinct().getOnSelectItems().forEach(expr -> expr.accept(this));
+ plainSelect.getDistinct().getOnSelectItems().forEach(item -> item.getExpression().accept(this));
}
if (plainSelect.getOrderByElements() != null) {
@@ -1169,17 +1312,23 @@ public void visit(PlainSelect plainSelect) {
}
if (plainSelect.getGroupBy() != null) {
- for (Expression expression : plainSelect.getGroupBy().getGroupByExpressionList().getExpressions()) {
- expression.accept(this);
+ for (Object expression : plainSelect.getGroupBy().getGroupByExpressionList()) {
+ ((Expression) expression).accept(this);
}
}
+ return null;
}
@Override
- public void visit(SetOperationList setOpList) {
+ public void visit(PlainSelect plainSelect) {
+ visit(plainSelect, (Object) null);
+ }
+
+ @Override
+ public Void visit(SetOperationList setOpList, S context) {
if (CollectionUtils.isNotEmpty(setOpList.getSelects())) {
- for (SelectBody select : setOpList.getSelects()) {
- select.accept(this);
+ for (net.sf.jsqlparser.statement.select.Select select : setOpList.getSelects()) {
+ acceptSelect(select, this);
}
}
if (setOpList.getOffset() != null) {
@@ -1193,25 +1342,73 @@ public void visit(SetOperationList setOpList) {
setOpList.getLimit().getOffset().accept(this);
}
}
+ return null;
+ }
+
+ @Override
+ public void visit(SetOperationList setOpList) {
+ visit(setOpList, (Object) null);
}
@Override
- public void visit(WithItem withItem) {
+ public Void visit(WithItem> withItem, S context) {
if (CollectionUtils.isNotEmpty(withItem.getWithItemList())) {
- for (SelectItem selectItem : withItem.getWithItemList()) {
- selectItem.accept(this);
+ for (SelectItem> selectItem : withItem.getWithItemList()) {
+ acceptSelectItem(selectItem, this);
}
}
- if (withItem.getSubSelect() != null) {
- withItem.getSubSelect().accept((ExpressionVisitor) this);
+ if (withItem.getSelect() != null) {
+ acceptSelect(withItem.getSelect(), this);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visit(ParenthesedSelect select, S context) {
+ if (select.getSelect() != null) {
+ acceptSelect(select.getSelect(), this);
+ }
+ return null;
+ }
+
+ @Override
+ public void visit(ParenthesedSelect select) {
+ visit(select, (Object) null);
+ }
+
+ @Override
+ public Void visit(TableStatement tableStatement, S context) {
+ return null;
+ }
+
+ @Override
+ public void visit(TableStatement tableStatement) {
+ }
+
+ @Override
+ public Void visit(FromQuery fromQuery, S context) {
+ if (fromQuery.getFromItem() != null) {
+ acceptFromItem(fromQuery.getFromItem(), this);
+ }
+ if (CollectionUtils.isNotEmpty(fromQuery.getJoins())) {
+ for (net.sf.jsqlparser.statement.select.Join join : fromQuery.getJoins()) {
+ if (join.getRightItem() != null) {
+ acceptFromItem(join.getRightItem(), this);
+ }
+ if (join.getOnExpressions() != null) {
+ join.getOnExpressions().forEach(expr -> expr.accept(this));
+ }
+ }
}
+ return null;
}
@Override
- public void visit(ValuesStatement aThis) {
- if (aThis.getExpressions() != null) {
- aThis.getExpressions().accept(this);
+ public Void visit(SelectItem extends Expression> selectItem, S context) {
+ if (selectItem.getExpression() != null) {
+ selectItem.getExpression().accept(this);
}
+ return null;
}
}
@@ -1230,6 +1427,16 @@ public Optional getColumn(String name) {
}
}
+ private static class ParsedSelect {
+ final net.sf.jsqlparser.statement.select.Select select;
+ final String operatorPlaceholder;
+
+ private ParsedSelect(net.sf.jsqlparser.statement.select.Select select, String operatorPlaceholder) {
+ this.select = select;
+ this.operatorPlaceholder = operatorPlaceholder;
+ }
+ }
+
private interface QueryRefactor {
SqlRequest refactor(QueryParamEntity param, Object... args);
diff --git a/hsweb-commons/hsweb-commons-crud/src/test/java/org/hswebframework/web/crud/query/DefaultQueryHelperTest.java b/hsweb-commons/hsweb-commons-crud/src/test/java/org/hswebframework/web/crud/query/DefaultQueryHelperTest.java
index c5d7844ee..dab376a3d 100644
--- a/hsweb-commons/hsweb-commons-crud/src/test/java/org/hswebframework/web/crud/query/DefaultQueryHelperTest.java
+++ b/hsweb-commons/hsweb-commons-crud/src/test/java/org/hswebframework/web/crud/query/DefaultQueryHelperTest.java
@@ -337,9 +337,9 @@ public void test() {
DefaultQueryHelper helper = new DefaultQueryHelper(database);
helper.select(TestInfo.class)
- // .all(EventTestEntity.class, TestInfo::setEventList)
+ // .all(EventTestEntity.class, TestInfo::setEventList)
.all("e2", TestInfo::setEvent)
- .as("e2.name",TestInfo::setE2Name)
+ .as("e2.name", TestInfo::setE2Name)
.all(TestEntity.class)
.from(TestEntity.class)
// .leftJoin(EventTestEntity.class,
@@ -353,8 +353,8 @@ public void test() {
.alias("e2")
.is(EventTestEntity::getId, TestEntity::getId)
.nest()
- .is(EventTestEntity::getId,TestEntity::getId)
- .is(EventTestEntity::getAge,10)
+ .is(EventTestEntity::getId, TestEntity::getId)
+ .is(EventTestEntity::getAge, 10)
.end()
)
.where(dsl -> dsl.is(EventTestEntity::getName, "Ename")
diff --git a/hsweb-commons/hsweb-commons-crud/src/test/java/org/hswebframework/web/crud/query/QueryAnalyzerImplTest.java b/hsweb-commons/hsweb-commons-crud/src/test/java/org/hswebframework/web/crud/query/QueryAnalyzerImplTest.java
index 0beab09f8..1d813a153 100644
--- a/hsweb-commons/hsweb-commons-crud/src/test/java/org/hswebframework/web/crud/query/QueryAnalyzerImplTest.java
+++ b/hsweb-commons/hsweb-commons-crud/src/test/java/org/hswebframework/web/crud/query/QueryAnalyzerImplTest.java
@@ -6,11 +6,13 @@
import org.hswebframework.web.api.crud.entity.QueryParamEntity;
import org.hswebframework.web.crud.TestApplication;
import org.junit.Assert;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import reactor.core.publisher.Flux;
import reactor.test.StepVerifier;
import static org.junit.jupiter.api.Assertions.*;
@@ -21,6 +23,18 @@ public class QueryAnalyzerImplTest {
@Autowired
private DatabaseOperator database;
+ @Before
+ public void before() {
+ Flux.concat(
+ database.sql().reactive().update("delete from test_tree_sort"),
+ database.sql().reactive().update("delete from s_test_event"),
+ database.sql().reactive().update("delete from s_test")
+ )
+ .then()
+ .as(StepVerifier::create)
+ .verifyComplete();
+ }
+
/**
* 执行SQL并验证是否有错误
*/
@@ -1093,4 +1107,4 @@ public void testAggregateFunctions() {
// 验证SQL可以执行
executeAndVerify(request);
}
-}
\ No newline at end of file
+}