Skip to content

Commit 5bdd4bf

Browse files
authored
fix(parser): parse Oracle outer join operator (+) on BETWEEN operands (#672) (#2564)
Signed-off-by: 付典 <fudianchn@gmail.com>
1 parent d45f796 commit 5bdd4bf

2 files changed

Lines changed: 93 additions & 0 deletions

File tree

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8202,6 +8202,15 @@ Expression Between(Expression leftExpression) :
82028202
LOOKAHEAD({ isComparisonOperatorAhead() })
82038203
betweenExpressionStart = RegularConditionRHS(betweenExpressionStart, EqualsTo.NO_ORACLE_JOIN)
82048204
]
8205+
[
8206+
LOOKAHEAD("(" "+" ")")
8207+
"(" "+" ")"
8208+
{
8209+
if (betweenExpressionStart instanceof Column) {
8210+
((Column) betweenExpressionStart).setOldOracleJoinSyntax(EqualsTo.ORACLE_JOIN_RIGHT);
8211+
}
8212+
}
8213+
]
82058214
)
82068215

82078216
<K_AND>
@@ -8213,6 +8222,15 @@ Expression Between(Expression leftExpression) :
82138222
LOOKAHEAD({ isComparisonOperatorAhead() })
82148223
betweenExpressionEnd = RegularConditionRHS(betweenExpressionEnd, EqualsTo.NO_ORACLE_JOIN)
82158224
]
8225+
[
8226+
LOOKAHEAD("(" "+" ")")
8227+
"(" "+" ")"
8228+
{
8229+
if (betweenExpressionEnd instanceof Column) {
8230+
((Column) betweenExpressionEnd).setOldOracleJoinSyntax(EqualsTo.ORACLE_JOIN_RIGHT);
8231+
}
8232+
}
8233+
]
82168234
)
82178235

82188236
{

src/test/java/net/sf/jsqlparser/expression/operators/relational/BetweenTest.java

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
package net.sf.jsqlparser.expression.operators.relational;
1111

1212
import net.sf.jsqlparser.JSQLParserException;
13+
import net.sf.jsqlparser.schema.Column;
1314
import net.sf.jsqlparser.statement.select.PlainSelect;
1415
import net.sf.jsqlparser.test.TestUtils;
1516
import org.junit.jupiter.api.Assertions;
@@ -50,4 +51,78 @@ void testBetweenASymmetricIssue2250() throws JSQLParserException {
5051
Assertions.assertFalse(between.isUsingSymmetric());
5152
Assertions.assertTrue(between.isUsingAsymmetric());
5253
}
54+
55+
@Test
56+
void testBetweenWithOldOracleJoinSyntaxOnBothOperandsIssue672() throws JSQLParserException {
57+
String sqlStr =
58+
"SELECT * FROM table1 t1, table2 t2 WHERE t1.col1 BETWEEN t2.col2(+) AND t2.col3(+)";
59+
PlainSelect select = (PlainSelect) TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true);
60+
Between between = (Between) select.getWhere();
61+
62+
assertEquals(EqualsTo.ORACLE_JOIN_RIGHT,
63+
((Column) between.getBetweenExpressionStart()).getOldOracleJoinSyntax());
64+
assertEquals(EqualsTo.ORACLE_JOIN_RIGHT,
65+
((Column) between.getBetweenExpressionEnd()).getOldOracleJoinSyntax());
66+
}
67+
68+
@Test
69+
void testBetweenWithOldOracleJoinSyntaxOnStartOperandIssue672() throws JSQLParserException {
70+
TestUtils.assertSqlCanBeParsedAndDeparsed(
71+
"SELECT * FROM table1 t1, table2 t2 WHERE t1.col1 BETWEEN t2.col2(+) AND 5", true);
72+
}
73+
74+
@Test
75+
void testBetweenWithOldOracleJoinSyntaxOnEndOperandIssue672() throws JSQLParserException {
76+
TestUtils.assertSqlCanBeParsedAndDeparsed(
77+
"SELECT * FROM table1 t1, table2 t2 WHERE t1.col1 BETWEEN 1 AND t2.col3(+)", true);
78+
}
79+
80+
@Test
81+
void testNotBetweenWithOldOracleJoinSyntaxIssue672() throws JSQLParserException {
82+
String sqlStr =
83+
"SELECT * FROM table1 t1, table2 t2 WHERE t1.col1 NOT BETWEEN t2.col2(+) AND t2.col3(+)";
84+
PlainSelect select = (PlainSelect) TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true);
85+
Between between = (Between) select.getWhere();
86+
87+
assertTrue(between.isNot());
88+
assertEquals(EqualsTo.ORACLE_JOIN_RIGHT,
89+
((Column) between.getBetweenExpressionStart()).getOldOracleJoinSyntax());
90+
assertEquals(EqualsTo.ORACLE_JOIN_RIGHT,
91+
((Column) between.getBetweenExpressionEnd()).getOldOracleJoinSyntax());
92+
}
93+
94+
@Test
95+
void testBetweenSymmetricWithOldOracleJoinSyntaxIssue672() throws JSQLParserException {
96+
TestUtils.assertSqlCanBeParsedAndDeparsed(
97+
"SELECT * FROM t1, t2 WHERE t1.c BETWEEN SYMMETRIC t2.c(+) AND t2.d(+)", true);
98+
}
99+
100+
@Test
101+
void testBetweenWithOldOracleJoinSyntaxInJoinOnClauseIssue672() throws JSQLParserException {
102+
TestUtils.assertSqlCanBeParsedAndDeparsed(
103+
"SELECT * FROM t1 JOIN t2 ON t1.c BETWEEN t2.c(+) AND t2.d(+)", true);
104+
}
105+
106+
@Test
107+
void testBetweenWithOldOracleJoinSyntaxOnLeftOperand() throws JSQLParserException {
108+
TestUtils.assertSqlCanBeParsedAndDeparsed(
109+
"SELECT * FROM table1 t1, table2 t2 WHERE t2.col2(+) BETWEEN t1.col1 AND t1.col3",
110+
true);
111+
}
112+
113+
@Test
114+
void testBetweenWithOldOracleJoinSyntaxBeforeComparisonSuffixOnOperand()
115+
throws JSQLParserException {
116+
// (+) directly followed by a comparison operator keeps the pre-existing
117+
// RegularConditionRHS path, where the marker sits on the comparison itself
118+
String sqlStr =
119+
"SELECT * FROM t1, t2 WHERE t1.c BETWEEN t2.c(+) = 5 AND 1";
120+
PlainSelect select = (PlainSelect) TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true);
121+
Between between = (Between) select.getWhere();
122+
EqualsTo comparison = (EqualsTo) between.getBetweenExpressionStart();
123+
124+
assertEquals(EqualsTo.ORACLE_JOIN_RIGHT, comparison.getOldOracleJoinSyntax());
125+
assertEquals(EqualsTo.NO_ORACLE_JOIN,
126+
((Column) comparison.getLeftExpression()).getOldOracleJoinSyntax());
127+
}
53128
}

0 commit comments

Comments
 (0)