Skip to content

Commit c430207

Browse files
author
石源
committed
fix #884 delete sql support CONFLICTS hint
1 parent e5a362e commit c430207

10 files changed

+152
-14
lines changed

pom.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<modelVersion>4.0.0</modelVersion>
44
<groupId>org.nlpcn</groupId>
55
<artifactId>elasticsearch-sql</artifactId>
6-
<version>6.6.0.0</version>
6+
<version>6.6.0.1</version>
77
<packaging>jar</packaging>
88
<description>Query elasticsearch using SQL</description>
99
<name>elasticsearch-sql</name>

src/main/java/org/nlpcn/es4sql/domain/Query.java

+8-1
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,19 @@
33
import java.util.ArrayList;
44
import java.util.List;
55

6+
import org.nlpcn.es4sql.domain.hints.Hint;
7+
68
/**
79
* Represents abstract query. every query
810
* has indexes, types, and where clause.
911
*/
1012
public abstract class Query {
1113

1214
private Where where = null;
13-
private List<From> from = new ArrayList<>();
15+
private final List<From> from = new ArrayList<>();
1416
private int offset;
1517
private int rowCount = -1;
18+
private final List<Hint> hints = new ArrayList<>();
1619

1720
public Where getWhere() {
1821
return this.where;
@@ -42,6 +45,10 @@ public void setRowCount(int rowCount) {
4245
this.rowCount = rowCount;
4346
}
4447

48+
public List<Hint> getHints() {
49+
return hints;
50+
}
51+
4552
/**
4653
* Get the indexes the query refer to.
4754
* @return list of strings, the indexes names

src/main/java/org/nlpcn/es4sql/domain/Select.java

-7
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package org.nlpcn.es4sql.domain;
22

33
import org.elasticsearch.search.sort.ScriptSortBuilder;
4-
import org.nlpcn.es4sql.domain.hints.Hint;
54
import org.nlpcn.es4sql.parse.SubQueryExpression;
65

76
import java.util.ArrayList;
@@ -19,7 +18,6 @@ public class Select extends Query {
1918

2019
// Using this functions, will cause query to execute as aggregation.
2120
private final List<String> aggsFunctions = Arrays.asList("SUM", "MAX", "MIN", "AVG", "TOPHITS", "COUNT", "STATS","EXTENDED_STATS","PERCENTILES","SCRIPTED_METRIC");
22-
private List<Hint> hints = new ArrayList<>();
2321
private List<Field> fields = new ArrayList<>();
2422
private List<List<Field>> groupBys = new ArrayList<>();
2523
private List<Order> orderBys = new ArrayList<>();
@@ -83,11 +81,6 @@ public void addField(Field field) {
8381
fields.add(field);
8482
}
8583

86-
public List<Hint> getHints() {
87-
return hints;
88-
}
89-
90-
9184
public void fillSubQueries() {
9285
subQueries = new ArrayList<>();
9386
Where where = this.getWhere();

src/main/java/org/nlpcn/es4sql/domain/hints/HintFactory.java

+4
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,10 @@ public static Hint getHintFromString(String hintAsString) throws SqlParseExcepti
155155
String[] statsGroups = getParamsFromHint(hintAsString, "! STATS");
156156
return new Hint(HintType.STATS, statsGroups);
157157
}
158+
if (hintAsString.startsWith("! CONFLICTS")) {
159+
String conflictsParam = getParamFromHint(hintAsString, "! CONFLICTS");
160+
return new Hint(HintType.CONFLICTS, new String[] { conflictsParam });
161+
}
158162

159163
return null;
160164
}

src/main/java/org/nlpcn/es4sql/domain/hints/HintType.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,6 @@ public enum HintType
1919
MINUS_USE_TERMS_OPTIMIZATION,
2020
COLLAPSE,
2121
POST_FILTER,
22-
STATS
22+
STATS,
23+
CONFLICTS
2324
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package org.nlpcn.es4sql.parse;
2+
3+
import com.alibaba.druid.sql.ast.SQLCommentHint;
4+
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDeleteStatement;
5+
6+
import java.util.ArrayList;
7+
import java.util.List;
8+
9+
public class ElasticSqlDeleteStatement extends MySqlDeleteStatement {
10+
11+
private List<SQLCommentHint> hints;
12+
13+
public List<SQLCommentHint> getHints() {
14+
if (hints == null) {
15+
hints = new ArrayList<SQLCommentHint>(2);
16+
}
17+
18+
return hints;
19+
}
20+
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package org.nlpcn.es4sql.parse;
2+
3+
import com.alibaba.druid.sql.ast.SQLExpr;
4+
import com.alibaba.druid.sql.ast.SQLOrderBy;
5+
import com.alibaba.druid.sql.ast.statement.SQLTableSource;
6+
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDeleteStatement;
7+
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;
8+
import com.alibaba.druid.sql.parser.Lexer;
9+
import com.alibaba.druid.sql.parser.ParserException;
10+
import com.alibaba.druid.sql.parser.Token;
11+
12+
public class ElasticSqlStatementParser extends MySqlStatementParser {
13+
14+
private static final String LOW_PRIORITY = "LOW_PRIORITY";
15+
private static final String QUICK = "QUICK";
16+
private static final String IGNORE = "IGNORE";
17+
private static final String USING = "USING";
18+
19+
public ElasticSqlStatementParser(String sql) {
20+
super(sql);
21+
}
22+
23+
public ElasticSqlStatementParser(Lexer lexer) {
24+
super(lexer);
25+
}
26+
27+
@Override
28+
public MySqlDeleteStatement parseDeleteStatement() {
29+
ElasticSqlDeleteStatement deleteStatement = new ElasticSqlDeleteStatement();
30+
31+
if (lexer.token() == Token.DELETE) {
32+
lexer.nextToken();
33+
34+
if (lexer.token() == Token.COMMENT) {
35+
lexer.nextToken();
36+
}
37+
38+
getExprParser().parseHints(deleteStatement.getHints());
39+
40+
if (identifierEquals(LOW_PRIORITY)) {
41+
deleteStatement.setLowPriority(true);
42+
lexer.nextToken();
43+
}
44+
45+
if (identifierEquals(QUICK)) {
46+
deleteStatement.setQuick(true);
47+
lexer.nextToken();
48+
}
49+
50+
if (identifierEquals(IGNORE)) {
51+
deleteStatement.setIgnore(true);
52+
lexer.nextToken();
53+
}
54+
55+
if (lexer.token() == Token.IDENTIFIER) {
56+
deleteStatement.setTableSource(createSQLSelectParser().parseTableSource());
57+
58+
if (lexer.token() == Token.FROM) {
59+
lexer.nextToken();
60+
SQLTableSource tableSource = createSQLSelectParser().parseTableSource();
61+
deleteStatement.setFrom(tableSource);
62+
}
63+
} else if (lexer.token() == Token.FROM) {
64+
lexer.nextToken();
65+
deleteStatement.setTableSource(createSQLSelectParser().parseTableSource());
66+
} else {
67+
throw new ParserException("syntax error");
68+
}
69+
70+
if (identifierEquals(USING)) {
71+
lexer.nextToken();
72+
73+
SQLTableSource tableSource = createSQLSelectParser().parseTableSource();
74+
deleteStatement.setUsing(tableSource);
75+
}
76+
}
77+
78+
if (lexer.token() == (Token.WHERE)) {
79+
lexer.nextToken();
80+
SQLExpr where = this.exprParser.expr();
81+
deleteStatement.setWhere(where);
82+
}
83+
84+
if (lexer.token() == (Token.ORDER)) {
85+
SQLOrderBy orderBy = exprParser.parseOrderBy();
86+
deleteStatement.setOrderBy(orderBy);
87+
}
88+
89+
deleteStatement.setLimit(parseLimit());
90+
91+
return deleteStatement;
92+
}
93+
}

src/main/java/org/nlpcn/es4sql/parse/SqlParser.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import com.alibaba.druid.sql.ast.statement.*;
77
import com.alibaba.druid.sql.ast.*;
88
import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlSelectGroupByExpr;
9-
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDeleteStatement;
109
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock;
1110

1211

@@ -94,7 +93,9 @@ public Delete parseDelete(SQLDeleteStatement deleteStatement) throws SqlParseExc
9493

9594
delete.setWhere(whereParser.findWhere());
9695

97-
findLimit(((MySqlDeleteStatement) deleteStatement).getLimit(), delete);
96+
delete.getHints().addAll(parseHints(((ElasticSqlDeleteStatement) deleteStatement).getHints()));
97+
98+
findLimit(((ElasticSqlDeleteStatement) deleteStatement).getLimit(), delete);
9899

99100
return delete;
100101
}

src/main/java/org/nlpcn/es4sql/query/DeleteQueryAction.java

+18
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
import org.elasticsearch.index.reindex.DeleteByQueryRequestBuilder;
1111
import org.nlpcn.es4sql.domain.Delete;
1212
import org.nlpcn.es4sql.domain.Where;
13+
import org.nlpcn.es4sql.domain.hints.Hint;
14+
import org.nlpcn.es4sql.domain.hints.HintType;
1315
import org.nlpcn.es4sql.exception.SqlParseException;
1416

1517
import org.nlpcn.es4sql.query.maker.QueryMaker;
@@ -36,6 +38,9 @@ public SqlElasticDeleteByQueryRequestBuilder explain() throws SqlParseException
3638
request.size(delete.getRowCount());
3739
}
3840

41+
// set conflicts param
42+
updateRequestWithConflicts();
43+
3944
SqlElasticDeleteByQueryRequestBuilder deleteByQueryRequestBuilder = new SqlElasticDeleteByQueryRequestBuilder(request);
4045
return deleteByQueryRequestBuilder;
4146
}
@@ -75,4 +80,17 @@ private void setWhere(Where where) throws SqlParseException {
7580
}
7681
}
7782

83+
private void updateRequestWithConflicts() {
84+
for (Hint hint : delete.getHints()) {
85+
if (hint.getType() == HintType.CONFLICTS && hint.getParams() != null && 0 < hint.getParams().length) {
86+
String conflicts = hint.getParams()[0].toString();
87+
switch (conflicts) {
88+
case "proceed": request.abortOnVersionConflict(false); return;
89+
case "abort": request.abortOnVersionConflict(true); return;
90+
default: throw new IllegalArgumentException("conflicts may only be \"proceed\" or \"abort\" but was [" + conflicts + "]");
91+
}
92+
}
93+
}
94+
}
95+
7896
}

src/main/java/org/nlpcn/es4sql/query/ESActionFactory.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource;
88
import com.alibaba.druid.sql.ast.statement.SQLUnionQuery;
99
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock;
10-
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;
1110
import com.alibaba.druid.sql.parser.*;
1211
import org.elasticsearch.client.Client;
1312
import org.elasticsearch.plugin.nlpcn.ElasticResultHandler;
@@ -20,6 +19,7 @@
2019
import org.nlpcn.es4sql.exception.SqlParseException;
2120
import org.nlpcn.es4sql.parse.ElasticLexer;
2221
import org.nlpcn.es4sql.parse.ElasticSqlExprParser;
22+
import org.nlpcn.es4sql.parse.ElasticSqlStatementParser;
2323
import org.nlpcn.es4sql.parse.SqlParser;
2424
import org.nlpcn.es4sql.parse.SubQueryExpression;
2525
import org.nlpcn.es4sql.query.join.ESJoinQueryActionFactory;
@@ -123,7 +123,7 @@ private static QueryAction handleSelect(Client client, Select select) {
123123
private static SQLStatementParser createSqlStatementParser(String sql) {
124124
ElasticLexer lexer = new ElasticLexer(sql);
125125
lexer.nextToken();
126-
return new MySqlStatementParser(lexer);
126+
return new ElasticSqlStatementParser(lexer);
127127
}
128128

129129
private static boolean isJoin(SQLQueryExpr sqlExpr,String sql) {

0 commit comments

Comments
 (0)