Skip to content

feat: Salesforce SOQL INCLUDES and EXCLUDES operators #1985

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,10 @@ JSQLParser-4.9 is the last JDK8 compatible version and any future development wi

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

| RDBMS | Statements |
|-----------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------|
| 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 ...` |

| RDBMS | Statements |
|-----------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------|
| 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 ...` |
| Salesforce SOQL | `INCLUDES`, `EXCLUDES` |

**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)).

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,15 @@
import net.sf.jsqlparser.expression.operators.relational.Contains;
import net.sf.jsqlparser.expression.operators.relational.DoubleAnd;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.expression.operators.relational.ExcludesExpression;
import net.sf.jsqlparser.expression.operators.relational.ExistsExpression;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.FullTextSearch;
import net.sf.jsqlparser.expression.operators.relational.GeometryDistance;
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.IncludesExpression;
import net.sf.jsqlparser.expression.operators.relational.IsBooleanExpression;
import net.sf.jsqlparser.expression.operators.relational.IsDistinctExpression;
import net.sf.jsqlparser.expression.operators.relational.IsNullExpression;
Expand Down Expand Up @@ -116,6 +118,10 @@ public interface ExpressionVisitor {

void visit(InExpression inExpression);

void visit(IncludesExpression includesExpression);

void visit(ExcludesExpression excludesExpression);

void visit(FullTextSearch fullTextSearch);

void visit(IsNullExpression isNullExpression);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,18 @@ public void visit(InExpression expr) {
expr.getRightExpression().accept(this);
}

@Override
public void visit(IncludesExpression expr) {
expr.getLeftExpression().accept(this);
expr.getRightExpression().accept(this);
}

@Override
public void visit(ExcludesExpression expr) {
expr.getLeftExpression().accept(this);
expr.getRightExpression().accept(this);
}

@Override
public void visit(IsNullExpression expr) {
expr.getLeftExpression().accept(this);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*-
* #%L
* JSQLParser library
* %%
* Copyright (C) 2004 - 2019 JSQLParser
* %%
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
* #L%
*/
package net.sf.jsqlparser.expression.operators.relational;

import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.ExpressionVisitor;
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;

public class ExcludesExpression extends ASTNodeAccessImpl implements Expression {

private Expression leftExpression;
private Expression rightExpression;

public ExcludesExpression() {}

public ExcludesExpression(Expression leftExpression, Expression rightExpression) {
this.leftExpression = leftExpression;
this.rightExpression = rightExpression;
}

public Expression getLeftExpression() {
return leftExpression;
}

public ExcludesExpression withLeftExpression(Expression expression) {
this.setLeftExpression(expression);
return this;
}

public final void setLeftExpression(Expression expression) {
leftExpression = expression;
}

public Expression getRightExpression() {
return rightExpression;
}

public void setRightExpression(Expression rightExpression) {
this.rightExpression = rightExpression;
}

@Override
public void accept(ExpressionVisitor expressionVisitor) {
expressionVisitor.visit(this);
}

@Override
public String toString() {
StringBuilder statementBuilder = new StringBuilder();
statementBuilder.append(leftExpression);

statementBuilder.append(" ");
statementBuilder.append("EXCLUDES ");

statementBuilder.append(rightExpression);
return statementBuilder.toString();
}

public ExcludesExpression withRightExpression(Expression rightExpression) {
this.setRightExpression(rightExpression);
return this;
}

public <E extends Expression> E getLeftExpression(Class<E> type) {
return type.cast(getLeftExpression());
}

public <E extends Expression> E getRightExpression(Class<E> type) {
return type.cast(getRightExpression());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*-
* #%L
* JSQLParser library
* %%
* Copyright (C) 2004 - 2019 JSQLParser
* %%
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
* #L%
*/
package net.sf.jsqlparser.expression.operators.relational;

import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.ExpressionVisitor;
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;

public class IncludesExpression extends ASTNodeAccessImpl
implements Expression {

private Expression leftExpression;
private Expression rightExpression;

public IncludesExpression() {}

public IncludesExpression(Expression leftExpression, Expression rightExpression) {
this.leftExpression = leftExpression;
this.rightExpression = rightExpression;
}

public Expression getLeftExpression() {
return leftExpression;
}

public IncludesExpression withLeftExpression(Expression expression) {
this.setLeftExpression(expression);
return this;
}

public final void setLeftExpression(Expression expression) {
leftExpression = expression;
}

public Expression getRightExpression() {
return rightExpression;
}

public void setRightExpression(Expression rightExpression) {
this.rightExpression = rightExpression;
}

@Override
public void accept(ExpressionVisitor expressionVisitor) {
expressionVisitor.visit(this);
}

@Override
public String toString() {
StringBuilder statementBuilder = new StringBuilder();
statementBuilder.append(leftExpression);

statementBuilder.append(" ");
statementBuilder.append("INCLUDES ");

statementBuilder.append(rightExpression);
return statementBuilder.toString();
}

public IncludesExpression withRightExpression(Expression rightExpression) {
this.setRightExpression(rightExpression);
return this;
}

public <E extends Expression> E getLeftExpression(Class<E> type) {
return type.cast(getLeftExpression());
}

public <E extends Expression> E getRightExpression(Class<E> type) {
return type.cast(getRightExpression());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ public class ParserKeywordsUtils {
{"DOUBLE", RESTRICTED_ALIAS},
{"ELSE", RESTRICTED_JSQLPARSER},
{"EXCEPT", RESTRICTED_SQL2016},
{"EXCLUDES", RESTRICTED_JSQLPARSER},
{"EXISTS", RESTRICTED_SQL2016},
{"FETCH", RESTRICTED_SQL2016},
{"FINAL", RESTRICTED_JSQLPARSER},
Expand All @@ -82,6 +83,7 @@ public class ParserKeywordsUtils {
{"IGNORE", RESTRICTED_ALIAS},
{"ILIKE", RESTRICTED_SQL2016},
{"IN", RESTRICTED_SQL2016},
{"INCLUDES", RESTRICTED_JSQLPARSER},
{"INNER", RESTRICTED_SQL2016},
{"INTERSECT", RESTRICTED_SQL2016},
{"INTERVAL", RESTRICTED_SQL2016},
Expand Down
14 changes: 14 additions & 0 deletions src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,15 @@
import net.sf.jsqlparser.expression.operators.relational.Contains;
import net.sf.jsqlparser.expression.operators.relational.DoubleAnd;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.expression.operators.relational.ExcludesExpression;
import net.sf.jsqlparser.expression.operators.relational.ExistsExpression;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.FullTextSearch;
import net.sf.jsqlparser.expression.operators.relational.GeometryDistance;
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.IncludesExpression;
import net.sf.jsqlparser.expression.operators.relational.IsBooleanExpression;
import net.sf.jsqlparser.expression.operators.relational.IsDistinctExpression;
import net.sf.jsqlparser.expression.operators.relational.IsNullExpression;
Expand Down Expand Up @@ -418,6 +420,18 @@ public void visit(InExpression inExpression) {
inExpression.getRightExpression().accept(this);
}

@Override
public void visit(IncludesExpression includesExpression) {
includesExpression.getLeftExpression().accept(this);
includesExpression.getRightExpression().accept(this);
}

@Override
public void visit(ExcludesExpression excludesExpression) {
excludesExpression.getLeftExpression().accept(this);
excludesExpression.getRightExpression().accept(this);
}

@Override
public void visit(FullTextSearch fullTextSearch) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,15 @@
import net.sf.jsqlparser.expression.operators.relational.Contains;
import net.sf.jsqlparser.expression.operators.relational.DoubleAnd;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.expression.operators.relational.ExcludesExpression;
import net.sf.jsqlparser.expression.operators.relational.ExistsExpression;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.FullTextSearch;
import net.sf.jsqlparser.expression.operators.relational.GeometryDistance;
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.IncludesExpression;
import net.sf.jsqlparser.expression.operators.relational.IsBooleanExpression;
import net.sf.jsqlparser.expression.operators.relational.IsDistinctExpression;
import net.sf.jsqlparser.expression.operators.relational.IsNullExpression;
Expand Down Expand Up @@ -266,6 +268,20 @@ public void visit(InExpression inExpression) {
inExpression.getRightExpression().accept(this);
}

@Override
public void visit(IncludesExpression includesExpression) {
includesExpression.getLeftExpression().accept(this);
buffer.append(" INCLUDES ");
includesExpression.getRightExpression().accept(this);
}

@Override
public void visit(ExcludesExpression excludesExpression) {
excludesExpression.getLeftExpression().accept(this);
buffer.append(" EXCLUDES ");
excludesExpression.getRightExpression().accept(this);
}

@Override
public void visit(FullTextSearch fullTextSearch) {
// Build a list of matched columns
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,13 +84,15 @@
import net.sf.jsqlparser.expression.operators.relational.Contains;
import net.sf.jsqlparser.expression.operators.relational.DoubleAnd;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.expression.operators.relational.ExcludesExpression;
import net.sf.jsqlparser.expression.operators.relational.ExistsExpression;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.FullTextSearch;
import net.sf.jsqlparser.expression.operators.relational.GeometryDistance;
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.IncludesExpression;
import net.sf.jsqlparser.expression.operators.relational.IsBooleanExpression;
import net.sf.jsqlparser.expression.operators.relational.IsDistinctExpression;
import net.sf.jsqlparser.expression.operators.relational.IsNullExpression;
Expand Down Expand Up @@ -225,6 +227,18 @@ public void visit(InExpression inExpression) {
validateOptionalExpression(inExpression.getRightExpression(), this);
}

@Override
public void visit(IncludesExpression includesExpression) {
validateOptionalExpression(includesExpression.getLeftExpression(), this);
validateOptionalExpression(includesExpression.getRightExpression(), this);
}

@Override
public void visit(ExcludesExpression excludesExpression) {
validateOptionalExpression(excludesExpression.getLeftExpression(), this);
validateOptionalExpression(excludesExpression.getRightExpression(), this);
}

@Override
public void visit(FullTextSearch fullTextSearch) {
validateOptionalExpressions(fullTextSearch.getMatchColumns());
Expand Down
Loading