Skip to content

Commit 834afe1

Browse files
authored
Fix oracle outer join case with nvl/coalesce (#2386)
1 parent 865a3bf commit 834afe1

File tree

5 files changed

+40
-0
lines changed

5 files changed

+40
-0
lines changed

src/main/java/net/sf/jsqlparser/schema/Column.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import net.sf.jsqlparser.expression.ArrayConstructor;
1717
import net.sf.jsqlparser.expression.Expression;
1818
import net.sf.jsqlparser.expression.ExpressionVisitor;
19+
import net.sf.jsqlparser.expression.operators.relational.SupportsOldOracleJoinSyntax;
1920
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
2021

2122
/**
@@ -28,6 +29,7 @@ public class Column extends ASTNodeAccessImpl implements Expression, MultiPartNa
2829
private String commentText;
2930
private ArrayConstructor arrayConstructor;
3031
private String tableDelimiter = ".";
32+
private int oldOracleJoinSyntax = SupportsOldOracleJoinSyntax.NO_ORACLE_JOIN;
3133

3234
// holds the physical table when resolved against an actual schema information
3335
private Table resolvedTable = null;
@@ -192,6 +194,14 @@ public void setTableDelimiter(String tableDelimiter) {
192194
this.tableDelimiter = tableDelimiter;
193195
}
194196

197+
public int getOldOracleJoinSyntax() {
198+
return oldOracleJoinSyntax;
199+
}
200+
201+
public void setOldOracleJoinSyntax(int oldOracleJoinSyntax) {
202+
this.oldOracleJoinSyntax = oldOracleJoinSyntax;
203+
}
204+
195205
@Override
196206
public String getFullyQualifiedName() {
197207
return getFullyQualifiedName(false);
@@ -245,6 +255,7 @@ public <T, S> T accept(ExpressionVisitor<T> expressionVisitor, S context) {
245255
@Override
246256
public String toString() {
247257
return getFullyQualifiedName(true)
258+
+ (oldOracleJoinSyntax != SupportsOldOracleJoinSyntax.NO_ORACLE_JOIN ? "(+)" : "")
248259
+ (commentText != null ? " /* " + commentText + "*/ " : "");
249260
}
250261

@@ -268,6 +279,11 @@ public Column withTableDelimiter(String delimiter) {
268279
return this;
269280
}
270281

282+
public Column withOldOracleJoinSyntax(int oldOracleJoinSyntax) {
283+
this.setOldOracleJoinSyntax(oldOracleJoinSyntax);
284+
return this;
285+
}
286+
271287
public String getCommentText() {
272288
return commentText;
273289
}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -832,6 +832,9 @@ public <S> StringBuilder visit(Column tableColumn, S context) {
832832
}
833833

834834
builder.append(tableColumn.getColumnName());
835+
if (tableColumn.getOldOracleJoinSyntax() != SupportsOldOracleJoinSyntax.NO_ORACLE_JOIN) {
836+
builder.append("(+)");
837+
}
835838

836839
if (tableColumn.getArrayConstructor() != null) {
837840
tableColumn.getArrayConstructor().accept(this, context);

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,10 @@ public <S> Void visit(ParenthesedSelect selectBody, S context) {
527527

528528
@Override
529529
public <S> Void visit(Column tableColumn, S context) {
530+
if (tableColumn
531+
.getOldOracleJoinSyntax() != SupportsOldOracleJoinSyntax.NO_ORACLE_JOIN) {
532+
validateFeature(Feature.oracleOldJoinSyntax);
533+
}
530534
validateName(NamedObject.column, tableColumn.getFullyQualifiedName());
531535
return null;
532536
}

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6639,6 +6639,10 @@ Expression PrimaryExpression() #PrimaryExpression:
66396639
| LOOKAHEAD(2, {!interrupted}) <K_ALL> { retval = new AllValue(); }
66406640

66416641
| LOOKAHEAD(2, {!interrupted}) retval=Column()
6642+
[
6643+
LOOKAHEAD( "(" "+" ")" ("," | ")") )
6644+
"(" "+" ")" { ((Column) retval).setOldOracleJoinSyntax(EqualsTo.ORACLE_JOIN_RIGHT); }
6645+
]
66426646

66436647
| LOOKAHEAD(2, {!interrupted}) (token=<K_TRUE> | token=<K_FALSE>) { retval = new BooleanValue(token.image); }
66446648

src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2379,6 +2379,19 @@ public void testOracleJoinIssue318() throws JSQLParserException {
23792379
"SELECT * FROM TBL_A, TBL_B, TBL_C WHERE TBL_A.ID(+) = TBL_B.ID AND TBL_C.ROOM(+) = TBL_B.ROOM");
23802380
}
23812381

2382+
@Test
2383+
public void testOracleJoinWithinNvlArgument() throws JSQLParserException {
2384+
assertSqlCanBeParsedAndDeparsed(
2385+
"SELECT * FROM dual d, dual d2 WHERE d.dummy = nvl(d2.dummy (+), 'y')", true);
2386+
}
2387+
2388+
@Test
2389+
public void testOracleJoinWithinCoalesceArgument() throws JSQLParserException {
2390+
assertSqlCanBeParsedAndDeparsed(
2391+
"SELECT * FROM dual d, dual d2 WHERE d.dummy = coalesce(d2.dummy (+), 'y')",
2392+
true);
2393+
}
2394+
23822395
@Test
23832396
public void testProblemSqlIntersect() throws Exception {
23842397
String stmt = "(SELECT * FROM a) INTERSECT (SELECT * FROM b)";

0 commit comments

Comments
 (0)