Skip to content

Commit f3f0e05

Browse files
feat: Salesforce SOQL INCLUDES and EXCLUDES operators (#1985)
* feat: Salesforce SOQL `INCLUDES` and `EXCLUDES` operators * style: Add missing whitespaces --------- Co-authored-by: Luca Rota <lrota@eutelsat.com>
1 parent 0d813f0 commit f3f0e05

File tree

13 files changed

+324
-4
lines changed

13 files changed

+324
-4
lines changed

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,10 @@ JSQLParser-4.9 is the last JDK8 compatible version and any future development wi
5252

5353
**JSqlParser** aims to support the SQL standard as well as all major RDBMS. Any missing syntax or features can be added on demand.
5454

55-
| RDBMS | Statements |
56-
|-----------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------|
57-
| Oracle<br>MS SQL Server and Sybase<br>Postgres<br>MySQL and MariaDB<br>DB2<br>H2 and HSQLDB and Derby<br>SQLite | `SELECT`<br>`INSERT`, `UPDATE`, `UPSERT`, `MERGE`<br>`DELETE`, `TRUNCATE TABLE`<br>`CREATE ...`, `ALTER ....`, `DROP ...`<br>`WITH ...` |
58-
55+
| RDBMS | Statements |
56+
|-----------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------|
57+
| Oracle<br>MS SQL Server and Sybase<br>Postgres<br>MySQL and MariaDB<br>DB2<br>H2 and HSQLDB and Derby<br>SQLite | `SELECT`<br>`INSERT`, `UPDATE`, `UPSERT`, `MERGE`<br>`DELETE`, `TRUNCATE TABLE`<br>`CREATE ...`, `ALTER ....`, `DROP ...`<br>`WITH ...` |
58+
| Salesforce SOQL | `INCLUDES`, `EXCLUDES` |
5959

6060
**JSqlParser** can also be used to create SQL Statements from Java Code with a fluent API (see [Samples](https://jsqlparser.github.io/JSqlParser/usage.html#build-a-sql-statements)).
6161

src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,15 @@
2929
import net.sf.jsqlparser.expression.operators.relational.Contains;
3030
import net.sf.jsqlparser.expression.operators.relational.DoubleAnd;
3131
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
32+
import net.sf.jsqlparser.expression.operators.relational.ExcludesExpression;
3233
import net.sf.jsqlparser.expression.operators.relational.ExistsExpression;
3334
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
3435
import net.sf.jsqlparser.expression.operators.relational.FullTextSearch;
3536
import net.sf.jsqlparser.expression.operators.relational.GeometryDistance;
3637
import net.sf.jsqlparser.expression.operators.relational.GreaterThan;
3738
import net.sf.jsqlparser.expression.operators.relational.GreaterThanEquals;
3839
import net.sf.jsqlparser.expression.operators.relational.InExpression;
40+
import net.sf.jsqlparser.expression.operators.relational.IncludesExpression;
3941
import net.sf.jsqlparser.expression.operators.relational.IsBooleanExpression;
4042
import net.sf.jsqlparser.expression.operators.relational.IsDistinctExpression;
4143
import net.sf.jsqlparser.expression.operators.relational.IsNullExpression;
@@ -116,6 +118,10 @@ public interface ExpressionVisitor {
116118

117119
void visit(InExpression inExpression);
118120

121+
void visit(IncludesExpression includesExpression);
122+
123+
void visit(ExcludesExpression excludesExpression);
124+
119125
void visit(FullTextSearch fullTextSearch);
120126

121127
void visit(IsNullExpression isNullExpression);

src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,18 @@ public void visit(InExpression expr) {
224224
expr.getRightExpression().accept(this);
225225
}
226226

227+
@Override
228+
public void visit(IncludesExpression expr) {
229+
expr.getLeftExpression().accept(this);
230+
expr.getRightExpression().accept(this);
231+
}
232+
233+
@Override
234+
public void visit(ExcludesExpression expr) {
235+
expr.getLeftExpression().accept(this);
236+
expr.getRightExpression().accept(this);
237+
}
238+
227239
@Override
228240
public void visit(IsNullExpression expr) {
229241
expr.getLeftExpression().accept(this);
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*-
2+
* #%L
3+
* JSQLParser library
4+
* %%
5+
* Copyright (C) 2004 - 2019 JSQLParser
6+
* %%
7+
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
8+
* #L%
9+
*/
10+
package net.sf.jsqlparser.expression.operators.relational;
11+
12+
import net.sf.jsqlparser.expression.Expression;
13+
import net.sf.jsqlparser.expression.ExpressionVisitor;
14+
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
15+
16+
public class ExcludesExpression extends ASTNodeAccessImpl implements Expression {
17+
18+
private Expression leftExpression;
19+
private Expression rightExpression;
20+
21+
public ExcludesExpression() {}
22+
23+
public ExcludesExpression(Expression leftExpression, Expression rightExpression) {
24+
this.leftExpression = leftExpression;
25+
this.rightExpression = rightExpression;
26+
}
27+
28+
public Expression getLeftExpression() {
29+
return leftExpression;
30+
}
31+
32+
public ExcludesExpression withLeftExpression(Expression expression) {
33+
this.setLeftExpression(expression);
34+
return this;
35+
}
36+
37+
public final void setLeftExpression(Expression expression) {
38+
leftExpression = expression;
39+
}
40+
41+
public Expression getRightExpression() {
42+
return rightExpression;
43+
}
44+
45+
public void setRightExpression(Expression rightExpression) {
46+
this.rightExpression = rightExpression;
47+
}
48+
49+
@Override
50+
public void accept(ExpressionVisitor expressionVisitor) {
51+
expressionVisitor.visit(this);
52+
}
53+
54+
@Override
55+
public String toString() {
56+
StringBuilder statementBuilder = new StringBuilder();
57+
statementBuilder.append(leftExpression);
58+
59+
statementBuilder.append(" ");
60+
statementBuilder.append("EXCLUDES ");
61+
62+
statementBuilder.append(rightExpression);
63+
return statementBuilder.toString();
64+
}
65+
66+
public ExcludesExpression withRightExpression(Expression rightExpression) {
67+
this.setRightExpression(rightExpression);
68+
return this;
69+
}
70+
71+
public <E extends Expression> E getLeftExpression(Class<E> type) {
72+
return type.cast(getLeftExpression());
73+
}
74+
75+
public <E extends Expression> E getRightExpression(Class<E> type) {
76+
return type.cast(getRightExpression());
77+
}
78+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*-
2+
* #%L
3+
* JSQLParser library
4+
* %%
5+
* Copyright (C) 2004 - 2019 JSQLParser
6+
* %%
7+
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
8+
* #L%
9+
*/
10+
package net.sf.jsqlparser.expression.operators.relational;
11+
12+
import net.sf.jsqlparser.expression.Expression;
13+
import net.sf.jsqlparser.expression.ExpressionVisitor;
14+
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
15+
16+
public class IncludesExpression extends ASTNodeAccessImpl
17+
implements Expression {
18+
19+
private Expression leftExpression;
20+
private Expression rightExpression;
21+
22+
public IncludesExpression() {}
23+
24+
public IncludesExpression(Expression leftExpression, Expression rightExpression) {
25+
this.leftExpression = leftExpression;
26+
this.rightExpression = rightExpression;
27+
}
28+
29+
public Expression getLeftExpression() {
30+
return leftExpression;
31+
}
32+
33+
public IncludesExpression withLeftExpression(Expression expression) {
34+
this.setLeftExpression(expression);
35+
return this;
36+
}
37+
38+
public final void setLeftExpression(Expression expression) {
39+
leftExpression = expression;
40+
}
41+
42+
public Expression getRightExpression() {
43+
return rightExpression;
44+
}
45+
46+
public void setRightExpression(Expression rightExpression) {
47+
this.rightExpression = rightExpression;
48+
}
49+
50+
@Override
51+
public void accept(ExpressionVisitor expressionVisitor) {
52+
expressionVisitor.visit(this);
53+
}
54+
55+
@Override
56+
public String toString() {
57+
StringBuilder statementBuilder = new StringBuilder();
58+
statementBuilder.append(leftExpression);
59+
60+
statementBuilder.append(" ");
61+
statementBuilder.append("INCLUDES ");
62+
63+
statementBuilder.append(rightExpression);
64+
return statementBuilder.toString();
65+
}
66+
67+
public IncludesExpression withRightExpression(Expression rightExpression) {
68+
this.setRightExpression(rightExpression);
69+
return this;
70+
}
71+
72+
public <E extends Expression> E getLeftExpression(Class<E> type) {
73+
return type.cast(getLeftExpression());
74+
}
75+
76+
public <E extends Expression> E getRightExpression(Class<E> type) {
77+
return type.cast(getRightExpression());
78+
}
79+
}

src/main/java/net/sf/jsqlparser/parser/ParserKeywordsUtils.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ public class ParserKeywordsUtils {
6464
{"DOUBLE", RESTRICTED_ALIAS},
6565
{"ELSE", RESTRICTED_JSQLPARSER},
6666
{"EXCEPT", RESTRICTED_SQL2016},
67+
{"EXCLUDES", RESTRICTED_JSQLPARSER},
6768
{"EXISTS", RESTRICTED_SQL2016},
6869
{"FETCH", RESTRICTED_SQL2016},
6970
{"FINAL", RESTRICTED_JSQLPARSER},
@@ -82,6 +83,7 @@ public class ParserKeywordsUtils {
8283
{"IGNORE", RESTRICTED_ALIAS},
8384
{"ILIKE", RESTRICTED_SQL2016},
8485
{"IN", RESTRICTED_SQL2016},
86+
{"INCLUDES", RESTRICTED_JSQLPARSER},
8587
{"INNER", RESTRICTED_SQL2016},
8688
{"INTERSECT", RESTRICTED_SQL2016},
8789
{"INTERVAL", RESTRICTED_SQL2016},

src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,13 +89,15 @@
8989
import net.sf.jsqlparser.expression.operators.relational.Contains;
9090
import net.sf.jsqlparser.expression.operators.relational.DoubleAnd;
9191
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
92+
import net.sf.jsqlparser.expression.operators.relational.ExcludesExpression;
9293
import net.sf.jsqlparser.expression.operators.relational.ExistsExpression;
9394
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
9495
import net.sf.jsqlparser.expression.operators.relational.FullTextSearch;
9596
import net.sf.jsqlparser.expression.operators.relational.GeometryDistance;
9697
import net.sf.jsqlparser.expression.operators.relational.GreaterThan;
9798
import net.sf.jsqlparser.expression.operators.relational.GreaterThanEquals;
9899
import net.sf.jsqlparser.expression.operators.relational.InExpression;
100+
import net.sf.jsqlparser.expression.operators.relational.IncludesExpression;
99101
import net.sf.jsqlparser.expression.operators.relational.IsBooleanExpression;
100102
import net.sf.jsqlparser.expression.operators.relational.IsDistinctExpression;
101103
import net.sf.jsqlparser.expression.operators.relational.IsNullExpression;
@@ -419,6 +421,18 @@ public void visit(InExpression inExpression) {
419421
inExpression.getRightExpression().accept(this);
420422
}
421423

424+
@Override
425+
public void visit(IncludesExpression includesExpression) {
426+
includesExpression.getLeftExpression().accept(this);
427+
includesExpression.getRightExpression().accept(this);
428+
}
429+
430+
@Override
431+
public void visit(ExcludesExpression excludesExpression) {
432+
excludesExpression.getLeftExpression().accept(this);
433+
excludesExpression.getRightExpression().accept(this);
434+
}
435+
422436
@Override
423437
public void visit(FullTextSearch fullTextSearch) {
424438

src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,15 @@
8484
import net.sf.jsqlparser.expression.operators.relational.Contains;
8585
import net.sf.jsqlparser.expression.operators.relational.DoubleAnd;
8686
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
87+
import net.sf.jsqlparser.expression.operators.relational.ExcludesExpression;
8788
import net.sf.jsqlparser.expression.operators.relational.ExistsExpression;
8889
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
8990
import net.sf.jsqlparser.expression.operators.relational.FullTextSearch;
9091
import net.sf.jsqlparser.expression.operators.relational.GeometryDistance;
9192
import net.sf.jsqlparser.expression.operators.relational.GreaterThan;
9293
import net.sf.jsqlparser.expression.operators.relational.GreaterThanEquals;
9394
import net.sf.jsqlparser.expression.operators.relational.InExpression;
95+
import net.sf.jsqlparser.expression.operators.relational.IncludesExpression;
9496
import net.sf.jsqlparser.expression.operators.relational.IsBooleanExpression;
9597
import net.sf.jsqlparser.expression.operators.relational.IsDistinctExpression;
9698
import net.sf.jsqlparser.expression.operators.relational.IsNullExpression;
@@ -267,6 +269,20 @@ public void visit(InExpression inExpression) {
267269
inExpression.getRightExpression().accept(this);
268270
}
269271

272+
@Override
273+
public void visit(IncludesExpression includesExpression) {
274+
includesExpression.getLeftExpression().accept(this);
275+
buffer.append(" INCLUDES ");
276+
includesExpression.getRightExpression().accept(this);
277+
}
278+
279+
@Override
280+
public void visit(ExcludesExpression excludesExpression) {
281+
excludesExpression.getLeftExpression().accept(this);
282+
buffer.append(" EXCLUDES ");
283+
excludesExpression.getRightExpression().accept(this);
284+
}
285+
270286
@Override
271287
public void visit(FullTextSearch fullTextSearch) {
272288
// Build a list of matched columns

src/main/java/net/sf/jsqlparser/util/validation/validator/ExpressionValidator.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,13 +85,15 @@
8585
import net.sf.jsqlparser.expression.operators.relational.Contains;
8686
import net.sf.jsqlparser.expression.operators.relational.DoubleAnd;
8787
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
88+
import net.sf.jsqlparser.expression.operators.relational.ExcludesExpression;
8889
import net.sf.jsqlparser.expression.operators.relational.ExistsExpression;
8990
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
9091
import net.sf.jsqlparser.expression.operators.relational.FullTextSearch;
9192
import net.sf.jsqlparser.expression.operators.relational.GeometryDistance;
9293
import net.sf.jsqlparser.expression.operators.relational.GreaterThan;
9394
import net.sf.jsqlparser.expression.operators.relational.GreaterThanEquals;
9495
import net.sf.jsqlparser.expression.operators.relational.InExpression;
96+
import net.sf.jsqlparser.expression.operators.relational.IncludesExpression;
9597
import net.sf.jsqlparser.expression.operators.relational.IsBooleanExpression;
9698
import net.sf.jsqlparser.expression.operators.relational.IsDistinctExpression;
9799
import net.sf.jsqlparser.expression.operators.relational.IsNullExpression;
@@ -226,6 +228,18 @@ public void visit(InExpression inExpression) {
226228
validateOptionalExpression(inExpression.getRightExpression(), this);
227229
}
228230

231+
@Override
232+
public void visit(IncludesExpression includesExpression) {
233+
validateOptionalExpression(includesExpression.getLeftExpression(), this);
234+
validateOptionalExpression(includesExpression.getRightExpression(), this);
235+
}
236+
237+
@Override
238+
public void visit(ExcludesExpression excludesExpression) {
239+
validateOptionalExpression(excludesExpression.getLeftExpression(), this);
240+
validateOptionalExpression(excludesExpression.getRightExpression(), this);
241+
}
242+
229243
@Override
230244
public void visit(FullTextSearch fullTextSearch) {
231245
validateOptionalExpressions(fullTextSearch.getMatchColumns());

0 commit comments

Comments
 (0)