Skip to content

Commit c783240

Browse files
arh-euSzabó Miklós
and
Szabó Miklós
authored
Add support for boolean 'XOR' operator (JSQLParser#1193)
* Add support for boolean 'XOR' operator * XorExpression added to the ReflectionModelTest * XorExpression case added to the SelectTest * XorExpression cases added for Validation * Additional tests added for code coverage. * Code style fixed. * Separate test case for XOR added. * Imports explicitly added to avoid namespace pollution. * Additional tests cases for precedence and associativity. Co-authored-by: Szabó Miklós <[email protected]>
1 parent 1feea01 commit c783240

File tree

13 files changed

+260
-15
lines changed

13 files changed

+260
-15
lines changed

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

+3
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import net.sf.jsqlparser.expression.operators.arithmetic.*;
1313
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
1414
import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
15+
import net.sf.jsqlparser.expression.operators.conditional.XorExpression;
1516
import net.sf.jsqlparser.expression.operators.relational.*;
1617
import net.sf.jsqlparser.schema.Column;
1718
import net.sf.jsqlparser.statement.select.SubSelect;
@@ -62,6 +63,8 @@ public interface ExpressionVisitor {
6263

6364
void visit(OrExpression orExpression);
6465

66+
void visit(XorExpression orExpression);
67+
6568
void visit(Between between);
6669

6770
void visit(EqualsTo equalsTo);

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

+6
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import net.sf.jsqlparser.expression.operators.arithmetic.*;
1313
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
1414
import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
15+
import net.sf.jsqlparser.expression.operators.conditional.XorExpression;
1516
import net.sf.jsqlparser.expression.operators.relational.*;
1617
import net.sf.jsqlparser.schema.Column;
1718
import net.sf.jsqlparser.statement.select.AllColumns;
@@ -147,6 +148,11 @@ public void visit(OrExpression expr) {
147148
visitBinaryExpression(expr);
148149
}
149150

151+
@Override
152+
public void visit(XorExpression expr) {
153+
visitBinaryExpression(expr);
154+
}
155+
150156
@Override
151157
public void visit(Between expr) {
152158
expr.getLeftExpression().accept(this);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*-
2+
* #%L
3+
* JSQLParser library
4+
* %%
5+
* Copyright (C) 2004 - 2021 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.conditional;
11+
12+
import net.sf.jsqlparser.expression.BinaryExpression;
13+
import net.sf.jsqlparser.expression.Expression;
14+
import net.sf.jsqlparser.expression.ExpressionVisitor;
15+
16+
public class XorExpression extends BinaryExpression {
17+
18+
public XorExpression() {
19+
// nothing
20+
}
21+
22+
public XorExpression(Expression leftExpression, Expression rightExpression) {
23+
setLeftExpression(leftExpression);
24+
setRightExpression(rightExpression);
25+
}
26+
27+
@Override
28+
public XorExpression withLeftExpression(Expression expression) {
29+
return (XorExpression) super.withLeftExpression(expression);
30+
}
31+
32+
@Override
33+
public XorExpression withRightExpression(Expression expression) {
34+
return (XorExpression) super.withRightExpression(expression);
35+
}
36+
37+
@Override
38+
public void accept(ExpressionVisitor expressionVisitor) {
39+
expressionVisitor.visit(this);
40+
}
41+
42+
@Override
43+
public String getStringExpression() {
44+
return "XOR";
45+
}
46+
47+
}

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

+6
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
import net.sf.jsqlparser.expression.operators.arithmetic.*;
5959
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
6060
import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
61+
import net.sf.jsqlparser.expression.operators.conditional.XorExpression;
6162
import net.sf.jsqlparser.expression.operators.relational.*;
6263
import net.sf.jsqlparser.schema.Column;
6364
import net.sf.jsqlparser.schema.Table;
@@ -349,6 +350,11 @@ public void visit(OrExpression orExpression) {
349350
visitBinaryExpression(orExpression);
350351
}
351352

353+
@Override
354+
public void visit(XorExpression xorExpression) {
355+
visitBinaryExpression(xorExpression);
356+
}
357+
352358
@Override
353359
public void visit(Parenthesis parenthesis) {
354360
parenthesis.getExpression().accept(this);

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

+6
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
import net.sf.jsqlparser.expression.operators.arithmetic.Subtraction;
7373
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
7474
import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
75+
import net.sf.jsqlparser.expression.operators.conditional.XorExpression;
7576
import net.sf.jsqlparser.expression.operators.relational.Between;
7677
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
7778
import net.sf.jsqlparser.expression.operators.relational.ExistsExpression;
@@ -398,6 +399,11 @@ public void visit(NullValue nullValue) {
398399
public void visit(OrExpression orExpression) {
399400
visitBinaryExpression(orExpression, " OR ");
400401

402+
}
403+
@Override
404+
public void visit(XorExpression xorExpression) {
405+
visitBinaryExpression(xorExpression, " XOR ");
406+
401407
}
402408

403409
@Override

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

+7
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
import net.sf.jsqlparser.expression.operators.arithmetic.Subtraction;
7070
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
7171
import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
72+
import net.sf.jsqlparser.expression.operators.conditional.XorExpression;
7273
import net.sf.jsqlparser.expression.operators.relational.Between;
7374
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
7475
import net.sf.jsqlparser.expression.operators.relational.ExistsExpression;
@@ -275,6 +276,12 @@ public void visit(OrExpression orExpression) {
275276

276277
}
277278

279+
@Override
280+
public void visit(XorExpression xorExpression) {
281+
visitBinaryExpression(xorExpression, " XOR ");
282+
283+
}
284+
278285
@Override
279286
public void visit(Parenthesis parenthesis) {
280287
parenthesis.getExpression().accept(this);

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

+24-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* #%L
33
* JSQLParser library
44
* %%
5-
* Copyright (C) 2004 - 2019 JSQLParser
5+
* Copyright (C) 2004 - 2021 JSQLParser
66
* %%
77
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
88
* #L%
@@ -361,6 +361,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */
361361
| <K_WITHIN:"WITHIN">
362362
| <K_WITHOUT:"WITHOUT">
363363
| <K_XML:"XML">
364+
| <K_XOR:"XOR">
364365
| <K_XMLSERIALIZE:"XMLSERIALIZE">
365366
| <K_XMLAGG:"XMLAGG">
366367
| <K_XMLTEXT:"XMLTEXT">
@@ -2621,11 +2622,30 @@ Expression Expression() #Expression :
26212622
Expression retval = null;
26222623
}
26232624
{
2624-
retval=OrExpression()
2625+
retval=XorExpression()
26252626

26262627
{ return retval; }
26272628
}
26282629

2630+
Expression XorExpression():
2631+
{
2632+
Expression left, right, result;
2633+
}
2634+
{
2635+
left=OrExpression() { result = left; }
2636+
(
2637+
<K_XOR>
2638+
right=OrExpression()
2639+
{
2640+
result = new XorExpression(left, right);
2641+
left = result;
2642+
}
2643+
)*
2644+
{
2645+
return result;
2646+
}
2647+
}
2648+
26292649
Expression OrExpression():
26302650
{
26312651
Expression left, right, result;
@@ -2658,7 +2678,7 @@ Expression AndExpression() :
26582678
left=Condition()
26592679
|
26602680
[ <K_NOT> { not=true; } | "!" { not=true; exclamationMarkNot=true; } ]
2661-
"(" left=OrExpression() ")" {left = new Parenthesis(left); if (not) { left = new NotExpression(left, exclamationMarkNot); not = false; } }
2681+
"(" left=XorExpression() ")" {left = new Parenthesis(left); if (not) { left = new NotExpression(left, exclamationMarkNot); not = false; } }
26622682
)
26632683
{ result = left; }
26642684

@@ -2670,7 +2690,7 @@ Expression AndExpression() :
26702690
right=Condition()
26712691
|
26722692
[ <K_NOT> { not=true; } | "!" { not=true; exclamationMarkNot=true; } ]
2673-
"(" right=OrExpression() ")" {right = new Parenthesis(right); if (not) { right = new NotExpression(right, exclamationMarkNot); not = false; } }
2693+
"(" right=XorExpression() ")" {right = new Parenthesis(right); if (not) { right = new NotExpression(right, exclamationMarkNot); not = false; } }
26742694
)
26752695
{
26762696
result = new AndExpression(left, right);

src/test/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapterTest.java

+26-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
import java.util.ArrayList;
1313
import java.util.List;
14+
15+
import net.sf.jsqlparser.expression.operators.conditional.XorExpression;
1416
import org.junit.After;
1517
import org.junit.AfterClass;
1618
import org.junit.Before;
@@ -31,7 +33,6 @@
3133
import net.sf.jsqlparser.statement.select.SelectVisitorAdapter;
3234

3335
/**
34-
*
3536
* @author tw
3637
*/
3738
public class ExpressionVisitorAdapterTest {
@@ -100,6 +101,30 @@ public void visit(InExpression expr) {
100101
assertTrue(exprList.get(2) instanceof ItemsList);
101102
}
102103

104+
@Test
105+
public void testXorExpression() throws JSQLParserException {
106+
final List<Expression> exprList = new ArrayList<>();
107+
Select select = (Select) CCJSqlParserUtil.
108+
parse("SELECT * FROM table WHERE foo XOR bar");
109+
PlainSelect plainSelect = (PlainSelect) select.getSelectBody();
110+
Expression where = plainSelect.getWhere();
111+
where.accept(new ExpressionVisitorAdapter() {
112+
113+
@Override
114+
public void visit(XorExpression expr) {
115+
super.visit(expr);
116+
exprList.add(expr.getLeftExpression());
117+
exprList.add(expr.getRightExpression());
118+
}
119+
});
120+
121+
assertEquals(2, exprList.size());
122+
assertTrue(exprList.get(0) instanceof Column);
123+
assertEquals("foo", ((Column) exprList.get(0)).getColumnName());
124+
assertTrue(exprList.get(1) instanceof Column);
125+
assertEquals("bar", ((Column) exprList.get(1)).getColumnName());
126+
}
127+
103128
@Test
104129
public void testOracleHintExpressions() throws JSQLParserException {
105130
testOracleHintExpression("select --+ MYHINT \n * from foo", "MYHINT", true);

0 commit comments

Comments
 (0)