Skip to content

Commit 6e7a78d

Browse files
1 parent 09a70a4 commit 6e7a78d

9 files changed

Lines changed: 142 additions & 10 deletions

File tree

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import net.sf.jsqlparser.expression.operators.relational.JsonOperator;
4040
import net.sf.jsqlparser.expression.operators.relational.LikeExpression;
4141
import net.sf.jsqlparser.expression.operators.relational.Matches;
42+
import net.sf.jsqlparser.expression.operators.relational.MemberOfExpression;
4243
import net.sf.jsqlparser.expression.operators.relational.MinorThan;
4344
import net.sf.jsqlparser.expression.operators.relational.MinorThanEquals;
4445
import net.sf.jsqlparser.expression.operators.relational.NotEqualsTo;
@@ -135,6 +136,8 @@ public interface ExpressionVisitor {
135136

136137
void visit(ExistsExpression existsExpression);
137138

139+
void visit(MemberOfExpression memberOfExpression);
140+
138141
void visit(AnyComparisonExpression anyComparisonExpression);
139142

140143
void visit(Concat concat);

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import net.sf.jsqlparser.expression.operators.relational.JsonOperator;
4040
import net.sf.jsqlparser.expression.operators.relational.LikeExpression;
4141
import net.sf.jsqlparser.expression.operators.relational.Matches;
42+
import net.sf.jsqlparser.expression.operators.relational.MemberOfExpression;
4243
import net.sf.jsqlparser.expression.operators.relational.MinorThan;
4344
import net.sf.jsqlparser.expression.operators.relational.MinorThanEquals;
4445
import net.sf.jsqlparser.expression.operators.relational.NotEqualsTo;
@@ -299,6 +300,11 @@ public void visit(ExistsExpression expr) {
299300
expr.getRightExpression().accept(this);
300301
}
301302

303+
@Override
304+
public void visit(MemberOfExpression memberOfExpression) {
305+
memberOfExpression.getRightExpression().accept(this);
306+
}
307+
302308
@Override
303309
public void visit(AnyComparisonExpression expr) {
304310

src/main/java/net/sf/jsqlparser/expression/operators/relational/ExistsExpression.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515

1616
public class ExistsExpression extends ASTNodeAccessImpl implements Expression {
1717

18-
private Expression rightExpression;
19-
private boolean not = false;
18+
protected Expression rightExpression;
19+
protected boolean not = false;
2020

2121
public Expression getRightExpression() {
2222
return rightExpression;
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package net.sf.jsqlparser.expression.operators.relational;
2+
3+
import net.sf.jsqlparser.expression.Expression;
4+
import net.sf.jsqlparser.expression.ExpressionVisitor;
5+
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
6+
7+
public class MemberOfExpression extends ASTNodeAccessImpl implements Expression {
8+
9+
Expression leftExpression;
10+
Expression rightExpression;
11+
boolean isNot;
12+
13+
public MemberOfExpression(Expression leftExpression, Expression rightExpression) {
14+
this.leftExpression = leftExpression;
15+
this.rightExpression = rightExpression;
16+
}
17+
18+
public Expression getLeftExpression() {
19+
return leftExpression;
20+
}
21+
22+
public MemberOfExpression setLeftExpression(Expression leftExpression) {
23+
this.leftExpression = leftExpression;
24+
return this;
25+
}
26+
27+
public Expression getRightExpression() {
28+
return rightExpression;
29+
}
30+
31+
public MemberOfExpression setRightExpression(Expression rightExpression) {
32+
this.rightExpression = rightExpression;
33+
return this;
34+
}
35+
36+
public boolean isNot() {
37+
return isNot;
38+
}
39+
40+
public MemberOfExpression setNot(boolean not) {
41+
isNot = not;
42+
return this;
43+
}
44+
45+
@Override
46+
public String toString() {
47+
return leftExpression + " MEMBER OF " + rightExpression;
48+
}
49+
50+
@Override
51+
public void accept(ExpressionVisitor expressionVisitor) {
52+
expressionVisitor.visit(this);
53+
}
54+
}

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@
9191
import net.sf.jsqlparser.expression.operators.relational.JsonOperator;
9292
import net.sf.jsqlparser.expression.operators.relational.LikeExpression;
9393
import net.sf.jsqlparser.expression.operators.relational.Matches;
94+
import net.sf.jsqlparser.expression.operators.relational.MemberOfExpression;
9495
import net.sf.jsqlparser.expression.operators.relational.MinorThan;
9596
import net.sf.jsqlparser.expression.operators.relational.MinorThanEquals;
9697
import net.sf.jsqlparser.expression.operators.relational.NotEqualsTo;
@@ -410,6 +411,12 @@ public void visit(ExistsExpression existsExpression) {
410411
existsExpression.getRightExpression().accept(this);
411412
}
412413

414+
@Override
415+
public void visit(MemberOfExpression memberOfExpression) {
416+
memberOfExpression.getLeftExpression().accept(this);
417+
memberOfExpression.getRightExpression().accept(this);
418+
}
419+
413420
@Override
414421
public void visit(LongValue longValue) {
415422

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292
import net.sf.jsqlparser.expression.operators.relational.JsonOperator;
9393
import net.sf.jsqlparser.expression.operators.relational.LikeExpression;
9494
import net.sf.jsqlparser.expression.operators.relational.Matches;
95+
import net.sf.jsqlparser.expression.operators.relational.MemberOfExpression;
9596
import net.sf.jsqlparser.expression.operators.relational.MinorThan;
9697
import net.sf.jsqlparser.expression.operators.relational.MinorThanEquals;
9798
import net.sf.jsqlparser.expression.operators.relational.NotEqualsTo;
@@ -346,6 +347,17 @@ public void visit(ExistsExpression existsExpression) {
346347
existsExpression.getRightExpression().accept(this);
347348
}
348349

350+
@Override
351+
public void visit(MemberOfExpression memberOfExpression) {
352+
memberOfExpression.getLeftExpression().accept(this);
353+
if (memberOfExpression.isNot()) {
354+
buffer.append(" NOT MEMBER OF ");
355+
} else {
356+
buffer.append(" MEMBER OF ");
357+
}
358+
memberOfExpression.getRightExpression().accept(this);
359+
}
360+
349361
@Override
350362
public void visit(LongValue longValue) {
351363
buffer.append(longValue.getStringValue());

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@
9393
import net.sf.jsqlparser.expression.operators.relational.JsonOperator;
9494
import net.sf.jsqlparser.expression.operators.relational.LikeExpression;
9595
import net.sf.jsqlparser.expression.operators.relational.Matches;
96+
import net.sf.jsqlparser.expression.operators.relational.MemberOfExpression;
9697
import net.sf.jsqlparser.expression.operators.relational.MinorThan;
9798
import net.sf.jsqlparser.expression.operators.relational.MinorThanEquals;
9899
import net.sf.jsqlparser.expression.operators.relational.NotEqualsTo;
@@ -255,6 +256,12 @@ public void visit(ExistsExpression existsExpression) {
255256
existsExpression.getRightExpression().accept(this);
256257
}
257258

259+
@Override
260+
public void visit(MemberOfExpression memberOfExpression) {
261+
memberOfExpression.getLeftExpression().accept(this);
262+
memberOfExpression.getRightExpression().accept(this);
263+
}
264+
258265
@Override
259266
public void visit(LongValue longValue) {
260267
// nothing to validate

src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */
289289
| <K_MATCHED: "MATCHED">
290290
| <K_MATERIALIZED:"MATERIALIZED">
291291
| <K_MAXVALUE: "MAXVALUE">
292+
| <K_MEMBER: "MEMBER">
292293
| <K_MERGE: "MERGE">
293294
| <K_MINUS:"MINUS">
294295
| <K_MINVALUE:"MINVALUE">
@@ -1711,7 +1712,7 @@ String RelObjectNameWithoutValue() :
17111712
{ Token tk = null; }
17121713
{
17131714
( tk=<S_IDENTIFIER> | tk=<S_QUOTED_IDENTIFIER> | tk=<K_DATE_LITERAL> | tk=<K_DATETIMELITERAL> | tk=<K_STRING_FUNCTION_NAME> | tk=<K_ISOLATION> | tk=<K_TIME_KEY_EXPR>
1714-
| tk="ACTION" | tk="ACTIVE" | tk="ADD" | tk="ADVANCE" | tk="ADVISE" | tk="AGAINST" | tk="ALGORITHM" | tk="ALTER" | tk="ANALYZE" | tk="APPLY" | tk="ARCHIVE" | tk="ARRAY" | tk="ASC" | tk="AT" | tk="AUTHORIZATION" | tk="AUTO" | tk="BEGIN" | tk="BINARY" | tk="BIT" | tk="BUFFERS" | tk="BY" | tk="BYTE" | tk="BYTES" | tk="CACHE" | tk="CALL" | tk="CASCADE" | tk="CASE" | tk="CAST" | tk="CHANGE" | tk="CHANGES" | tk="CHAR" | tk="CHARACTER" | tk="CHECKPOINT" | tk="CLOSE" | tk="COLLATE" | tk="COLUMN" | tk="COLUMNS" | tk="COMMENT" | tk="COMMIT" | tk="CONFLICT" | tk="CONVERT" | tk="COSTS" | tk="CS" | tk="CYCLE" | tk="DATABASE" | tk="DDL" | tk="DECLARE" | tk="DEFAULT" | tk="DEFERRABLE" | tk="DELAYED" | tk="DELETE" | tk="DESC" | tk="DESCRIBE" | tk="DISABLE" | tk="DISCONNECT" | tk="DIV" | tk="DML" | tk="DO" | tk="DROP" | tk="DUMP" | tk="DUPLICATE" | tk="EMIT" | tk="ENABLE" | tk="END" | tk="ESCAPE" | tk="EXCLUDE" | tk="EXEC" | tk="EXECUTE" | tk="EXPLAIN" | tk="EXTENDED" | tk="EXTRACT" | tk="FALSE" | tk="FILTER" | tk="FIRST" | tk="FLUSH" | tk="FN" | tk="FOLLOWING" | tk="FORMAT" | tk="FULLTEXT" | tk="FUNCTION" | tk="GLOBAL" | tk="GRANT" | tk="GUARD" | tk="HISTORY" | tk="HOPPING" | tk="INCLUDE" | tk="INCREMENT" | tk="INDEX" | tk="INSERT" | tk="INTERLEAVE" | tk="ISNULL" | tk="JSON" | tk="KEEP" | tk="KEY" | tk="KEYS" | tk="LAST" | tk="LEADING" | tk="LINK" | tk="LOCAL" | tk="LOCKED" | tk="LOG" | tk="MATCH" | tk="MATCHED" | tk="MATERIALIZED" | tk="MAXVALUE" | tk="MERGE" | tk="MINVALUE" | tk="MODIFY" | tk="MOVEMENT" | tk="NEXT" | tk="NO" | tk="NOCACHE" | tk="NOKEEP" | tk="NOLOCK" | tk="NOMAXVALUE" | tk="NOMINVALUE" | tk="NOORDER" | tk="NOTHING" | tk="NOVALIDATE" | tk="NOWAIT" | tk="NULLS" | tk="OF" | tk="OFF" | tk="OPEN" | tk="OVER" | tk="OVERLAPS" | tk="PARALLEL" | tk="PARENT" | tk="PARTITION" | tk="PATH" | tk="PERCENT" | tk="PLACING" | tk="PRECEDING" | tk="PRECISION" | tk="PRIMARY" | tk="PRIOR" | tk="PURGE" | tk="QUERY" | tk="QUICK" | tk="QUIESCE" | tk="RANGE" | tk="READ" | tk="RECYCLEBIN" | tk="REFERENCES" | tk="REFRESH" | tk="REGISTER" | tk="RENAME" | tk="REPLACE" | tk="RESET" | tk="RESTART" | tk="RESTRICT" | tk="RESTRICTED" | tk="RESUMABLE" | tk="RESUME" | tk="RLIKE" | tk="ROLLBACK" | tk="ROW" | tk="ROWS" | tk="RR" | tk="RS" | tk="SAVEPOINT" | tk="SCHEMA" | tk="SEPARATOR" | tk="SEQUENCE" | tk="SESSION" | tk="SETS" | tk="SHOW" | tk="SHUTDOWN" | tk="SIBLINGS" | tk="SIGNED" | tk="SIMILAR" | tk="SIZE" | tk="SKIP" | tk="STORED" | tk="STRING" | tk="SUSPEND" | tk="SWITCH" | tk="SYNONYM" | tk="SYSTEM" | tk="TABLE" | tk="TABLESPACE" | tk="TEMP" | tk="TEMPORARY" | tk="THEN" | tk="TIMEOUT" | tk="TIMESTAMPTZ" | tk="TO" | tk="TRUE" | tk="TRUNCATE" | tk="TUMBLING" | tk="TYPE" | tk="UNLOGGED" | tk="UNQIESCE" | tk="UNSIGNED" | tk="UPDATE" | tk="UPSERT" | tk="UR" | tk="USER" | tk="VALIDATE" | tk="VERBOSE" | tk="VIEW" | tk="WAIT" | tk="WITHIN" | tk="WITHOUT" | tk="WORK" | tk="XML" | tk="XMLAGG" | tk="XMLTEXT" | tk="YAML" | tk="YES" | tk="ZONE" )
1715+
| tk="ACTION" | tk="ACTIVE" | tk="ADD" | tk="ADVANCE" | tk="ADVISE" | tk="AGAINST" | tk="ALGORITHM" | tk="ALTER" | tk="ANALYZE" | tk="APPLY" | tk="ARCHIVE" | tk="ARRAY" | tk="ASC" | tk="AT" | tk="AUTHORIZATION" | tk="AUTO" | tk="BEGIN" | tk="BINARY" | tk="BIT" | tk="BUFFERS" | tk="BY" | tk="BYTE" | tk="BYTES" | tk="CACHE" | tk="CALL" | tk="CASCADE" | tk="CASE" | tk="CAST" | tk="CHANGE" | tk="CHANGES" | tk="CHAR" | tk="CHARACTER" | tk="CHECKPOINT" | tk="CLOSE" | tk="COLLATE" | tk="COLUMN" | tk="COLUMNS" | tk="COMMENT" | tk="COMMIT" | tk="CONFLICT" | tk="CONVERT" | tk="COSTS" | tk="CS" | tk="CYCLE" | tk="DATABASE" | tk="DDL" | tk="DECLARE" | tk="DEFAULT" | tk="DEFERRABLE" | tk="DELAYED" | tk="DELETE" | tk="DESC" | tk="DESCRIBE" | tk="DISABLE" | tk="DISCONNECT" | tk="DIV" | tk="DML" | tk="DO" | tk="DROP" | tk="DUMP" | tk="DUPLICATE" | tk="EMIT" | tk="ENABLE" | tk="END" | tk="ESCAPE" | tk="EXCLUDE" | tk="EXEC" | tk="EXECUTE" | tk="EXPLAIN" | tk="EXTENDED" | tk="EXTRACT" | tk="FALSE" | tk="FILTER" | tk="FIRST" | tk="FLUSH" | tk="FN" | tk="FOLLOWING" | tk="FORMAT" | tk="FULLTEXT" | tk="FUNCTION" | tk="GLOBAL" | tk="GRANT" | tk="GUARD" | tk="HISTORY" | tk="HOPPING" | tk="INCLUDE" | tk="INCREMENT" | tk="INDEX" | tk="INSERT" | tk="INTERLEAVE" | tk="ISNULL" | tk="JSON" | tk="KEEP" | tk="KEY" | tk="KEYS" | tk="LAST" | tk="LEADING" | tk="LINK" | tk="LOCAL" | tk="LOCKED" | tk="LOG" | tk="MATCH" | tk="MATCHED" | tk="MATERIALIZED" | tk="MAXVALUE" | tk="MEMBER" | tk="MERGE" | tk="MINVALUE" | tk="MODIFY" | tk="MOVEMENT" | tk="NEXT" | tk="NO" | tk="NOCACHE" | tk="NOKEEP" | tk="NOLOCK" | tk="NOMAXVALUE" | tk="NOMINVALUE" | tk="NOORDER" | tk="NOTHING" | tk="NOVALIDATE" | tk="NOWAIT" | tk="NULLS" | tk="OF" | tk="OFF" | tk="OPEN" | tk="OVER" | tk="OVERLAPS" | tk="PARALLEL" | tk="PARENT" | tk="PARTITION" | tk="PATH" | tk="PERCENT" | tk="PLACING" | tk="PRECEDING" | tk="PRECISION" | tk="PRIMARY" | tk="PRIOR" | tk="PURGE" | tk="QUERY" | tk="QUICK" | tk="QUIESCE" | tk="RANGE" | tk="READ" | tk="RECYCLEBIN" | tk="REFERENCES" | tk="REFRESH" | tk="REGISTER" | tk="RENAME" | tk="REPLACE" | tk="RESET" | tk="RESTART" | tk="RESTRICT" | tk="RESTRICTED" | tk="RESUMABLE" | tk="RESUME" | tk="RLIKE" | tk="ROLLBACK" | tk="ROW" | tk="ROWS" | tk="RR" | tk="RS" | tk="SAVEPOINT" | tk="SCHEMA" | tk="SEPARATOR" | tk="SEQUENCE" | tk="SESSION" | tk="SETS" | tk="SHOW" | tk="SHUTDOWN" | tk="SIBLINGS" | tk="SIGNED" | tk="SIMILAR" | tk="SIZE" | tk="SKIP" | tk="STORED" | tk="STRING" | tk="SUSPEND" | tk="SWITCH" | tk="SYNONYM" | tk="SYSTEM" | tk="TABLE" | tk="TABLESPACE" | tk="TEMP" | tk="TEMPORARY" | tk="THEN" | tk="TIMEOUT" | tk="TIMESTAMPTZ" | tk="TO" | tk="TRUE" | tk="TRUNCATE" | tk="TUMBLING" | tk="TYPE" | tk="UNLOGGED" | tk="UNQIESCE" | tk="UNSIGNED" | tk="UPDATE" | tk="UPSERT" | tk="UR" | tk="USER" | tk="VALIDATE" | tk="VERBOSE" | tk="VIEW" | tk="WAIT" | tk="WITHIN" | tk="WITHOUT" | tk="WORK" | tk="XML" | tk="XMLAGG" | tk="XMLTEXT" | tk="YAML" | tk="YES" | tk="ZONE" )
17151716
{ return tk.image; }
17161717
}
17171718

@@ -3209,13 +3210,25 @@ Expression SQLCondition():
32093210
| LOOKAHEAD(InExpression()) result=InExpression()
32103211
| LOOKAHEAD(OverlapsCondition()) result=OverlapsCondition()
32113212
| left = SimpleExpression() { result = left; }
3212-
[ LOOKAHEAD(2) ((LOOKAHEAD(2) result=Between(left)
3213-
| LOOKAHEAD(IsNullExpression()) result=IsNullExpression(left)
3214-
| LOOKAHEAD(IsBooleanExpression()) result=IsBooleanExpression(left)
3215-
| LOOKAHEAD(2) result=LikeExpression(left)
3216-
| LOOKAHEAD(IsDistinctExpression()) result=IsDistinctExpression(left)
3217-
| result=SimilarToExpression(left)
3218-
)) ]
3213+
[
3214+
LOOKAHEAD(2) (
3215+
(
3216+
LOOKAHEAD(2) result=Between(left)
3217+
|
3218+
result = MemberOfExpression(left)
3219+
|
3220+
LOOKAHEAD(IsNullExpression()) result=IsNullExpression(left)
3221+
|
3222+
LOOKAHEAD(IsBooleanExpression()) result=IsBooleanExpression(left)
3223+
|
3224+
LOOKAHEAD(2) result=LikeExpression(left)
3225+
|
3226+
LOOKAHEAD(IsDistinctExpression()) result=IsDistinctExpression(left)
3227+
|
3228+
result=SimilarToExpression(left)
3229+
)
3230+
)
3231+
]
32193232
)
32203233
{ return result; }
32213234
}
@@ -3366,6 +3379,18 @@ Expression ExistsExpression():
33663379
}
33673380
}
33683381

3382+
Expression MemberOfExpression(Expression leftExpression):
3383+
{
3384+
MemberOfExpression result;
3385+
Expression rightExpression = null;
3386+
}
3387+
{
3388+
<K_MEMBER> <K_OF> rightExpression=Expression()
3389+
{
3390+
return new MemberOfExpression(leftExpression, rightExpression );
3391+
}
3392+
}
3393+
33693394
ExpressionList ExpressionList() #ExpressionList:
33703395
{
33713396
ExpressionList expressionList;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package net.sf.jsqlparser.expression.operators.relational;
2+
3+
import net.sf.jsqlparser.JSQLParserException;
4+
import net.sf.jsqlparser.test.TestUtils;
5+
import org.junit.jupiter.api.Test;
6+
7+
import static org.junit.jupiter.api.Assertions.*;
8+
9+
class MemberOfExpressionTest {
10+
@Test
11+
void testMemberOf() throws JSQLParserException {
12+
String sqlStr = "SELECT 17 MEMBER OF ( cxr_post_id->'$.value' ) ";
13+
TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true);
14+
15+
sqlStr = "SELECT 17 MEMBER OF ( '[23, \"abc\", 17, \"ab\", 10]' ) ";
16+
TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true);
17+
}
18+
}

0 commit comments

Comments
 (0)