diff --git a/pmd-rules.xml b/pmd-rules.xml
index 08a020da1..28f4a94d5 100644
--- a/pmd-rules.xml
+++ b/pmd-rules.xml
@@ -54,8 +54,17 @@ under the License.
-
-
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/java/net/sf/jsqlparser/expression/CaseExpression.java b/src/main/java/net/sf/jsqlparser/expression/CaseExpression.java
index 9544615bd..371c40bf0 100644
--- a/src/main/java/net/sf/jsqlparser/expression/CaseExpression.java
+++ b/src/main/java/net/sf/jsqlparser/expression/CaseExpression.java
@@ -43,6 +43,7 @@
*/
public class CaseExpression extends ASTNodeAccessImpl implements Expression {
+ private boolean usingBrackets = false;
private Expression switchExpression;
private List whenClauses;
private Expression elseExpression;
@@ -90,9 +91,9 @@ public void setWhenClauses(List whenClauses) {
@Override
public String toString() {
- return "CASE " + ((switchExpression != null) ? switchExpression + " " : "")
+ return (usingBrackets ? "(" : "") + "CASE " + ((switchExpression != null) ? switchExpression + " " : "")
+ PlainSelect.getStringList(whenClauses, false, false) + " "
- + ((elseExpression != null) ? "ELSE " + elseExpression + " " : "") + "END";
+ + ((elseExpression != null) ? "ELSE " + elseExpression + " " : "") + "END" + (usingBrackets ? ")" : "");
}
public CaseExpression withSwitchExpression(Expression switchExpression) {
@@ -129,4 +130,26 @@ public E getSwitchExpression(Class type) {
public E getElseExpression(Class type) {
return type.cast(getElseExpression());
}
+
+ /**
+ * @return the usingBrackets
+ */
+ public boolean isUsingBrackets() {
+ return usingBrackets;
+ }
+
+ /**
+ * @param usingBrackets the usingBrackets to set
+ */
+ public void setUsingBrackets(boolean usingBrackets) {
+ this.usingBrackets = usingBrackets;
+ }
+
+ /**
+ * @param usingBrackets the usingBrackets to set
+ */
+ public CaseExpression withUsingBrackets(boolean usingBrackets) {
+ this.usingBrackets=usingBrackets;
+ return this;
+ }
}
diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java
index fc4ea0d36..db810b29e 100644
--- a/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java
+++ b/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java
@@ -604,7 +604,7 @@ public void visit(TimeValue timeValue) {
@Override
public void visit(CaseExpression caseExpression) {
- buffer.append("CASE ");
+ buffer.append(caseExpression.isUsingBrackets() ? "(" : "").append("CASE ");
Expression switchExp = caseExpression.getSwitchExpression();
if (switchExp != null) {
switchExp.accept(this);
@@ -622,7 +622,7 @@ public void visit(CaseExpression caseExpression) {
buffer.append(" ");
}
- buffer.append("END");
+ buffer.append("END").append(caseExpression.isUsingBrackets() ? ")" : "");
}
@Override
diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt
index ab31845fc..95b5ad739 100644
--- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt
+++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt
@@ -67,6 +67,8 @@ import java.util.*;
* The parser generated by JavaCC
*/
public class CCJSqlParser extends AbstractJSqlParser {
+ public int bracketsCounter = 0;
+ public int caseCounter = 0;
public CCJSqlParser withConfiguration(FeatureConfiguration configuration) {
token_source.configuration = configuration;
@@ -3697,11 +3699,14 @@ Expression CaseWhenExpression() #CaseWhenExpression:
Expression elseExp = null;
}
{
-
+ { caseCounter++; }
[ switchExp=Condition() ]
( clause=WhenThenSearchCondition() { whenClauses.add(clause); } )+
- [ elseExp=Condition()]
-
+ [ (LOOKAHEAD( ["("] CaseWhenExpression() [")"] ) ["("] elseExp=CaseWhenExpression() [")" { ((CaseExpression) elseExp).setUsingBrackets(true); } ]
+ | elseExp=Condition()
+ )
+ ]
+ { caseCounter--; }
{
caseExp.setSwitchExpression(switchExp);
caseExp.setWhenClauses(whenClauses);
@@ -3717,8 +3722,10 @@ WhenClause WhenThenSearchCondition():
Expression thenExp = null;
}
{
- (LOOKAHEAD(Expression()) whenExp=Expression() | whenExp=SimpleExpression())
- thenExp=Expression()
+ whenExp=Expression()
+ (LOOKAHEAD( ["("] CaseWhenExpression() [")"] ) ["("] thenExp=CaseWhenExpression() [")" { ((CaseExpression) thenExp).setUsingBrackets(true); }]
+ | thenExp=Expression()
+ )
{
whenThen.setWhenExpression(whenExp);
whenThen.setThenExpression(thenExp);
diff --git a/src/test/java/net/sf/jsqlparser/statement/select/NestedBracketsPerformanceTest.java b/src/test/java/net/sf/jsqlparser/statement/select/NestedBracketsPerformanceTest.java
index 396197777..d7fd43c67 100644
--- a/src/test/java/net/sf/jsqlparser/statement/select/NestedBracketsPerformanceTest.java
+++ b/src/test/java/net/sf/jsqlparser/statement/select/NestedBracketsPerformanceTest.java
@@ -38,7 +38,73 @@ public void testIssue235() throws JSQLParserException {
assertSqlCanBeParsedAndDeparsed("SELECT CASE WHEN ( CASE WHEN ( CASE WHEN ( CASE WHEN ( 1 ) THEN 0 END ) THEN 0 END ) THEN 0 END ) THEN 0 END FROM a", true);
}
- @Test(timeout = 100000)
+ @Test
+ public void testNestedCaseWhenWithoutBracketsIssue1162() throws JSQLParserException {
+ assertSqlCanBeParsedAndDeparsed("CREATE VIEW VIEW_NAME1 AS\n" +
+ "SELECT CASE\n" +
+ "WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
+ "ELSE CASE\n" +
+ "WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
+ "ELSE CASE\n" +
+ "WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
+ "ELSE CASE\n" +
+ "WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
+ "ELSE CASE\n" +
+ "WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
+ "ELSE CASE\n" +
+ "WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
+ "ELSE CASE\n" +
+ "WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
+ "ELSE CASE\n" +
+ "WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
+ "ELSE CASE\n" +
+ "WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
+ "ELSE CASE\n" +
+ "WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
+ "ELSE CASE\n" +
+ "WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
+ "ELSE CASE\n" +
+ "WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
+ "ELSE CASE\n" +
+ "WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
+ "ELSE CASE WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT' ELSE '0' END END END END END END END END END END END END END END COLUMNALIAS\n" +
+ "FROM TABLE1", true);
+ }
+
+ @Test
+ public void testNestedCaseWhenWithBracketsIssue1162() throws JSQLParserException {
+ assertSqlCanBeParsedAndDeparsed("CREATE VIEW VIEW_NAME1 AS\n" +
+ "SELECT CASE\n" +
+ "WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
+ "ELSE (CASE\n" +
+ "WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
+ "ELSE (CASE\n" +
+ "WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
+ "ELSE (CASE\n" +
+ "WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
+ "ELSE (CASE\n" +
+ "WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
+ "ELSE (CASE\n" +
+ "WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
+ "ELSE (CASE\n" +
+ "WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
+ "ELSE (CASE\n" +
+ "WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
+ "ELSE (CASE\n" +
+ "WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
+ "ELSE (CASE\n" +
+ "WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
+ "ELSE (CASE\n" +
+ "WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
+ "ELSE (CASE\n" +
+ "WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
+ "ELSE (CASE\n" +
+ "WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
+ "ELSE (CASE WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT' ELSE '0' END) END) END) END) END) END) END) END) END) END) END) END) END) END COLUMNALIAS\n" +
+ "FROM TABLE1", true);
+ }
+
+ @Test(timeout = 200000)
@Ignore
public void testIssue496() throws JSQLParserException {
assertSqlCanBeParsedAndDeparsed("select isNull(charLen(TEST_ID,0)+ isNull(charLen(TEST_DVC,0)+ isNull(charLen(TEST_NO,0)+ isNull(charLen(ATEST_ID,0)+ isNull(charLen(TESTNO,0)+ isNull(charLen(TEST_CTNT,0)+ isNull(charLen(TEST_MESG_CTNT,0)+ isNull(charLen(TEST_DTM,0)+ isNull(charLen(TEST_DTT,0)+ isNull(charLen(TEST_ADTT,0)+ isNull(charLen(TEST_TCD,0)+ isNull(charLen(TEST_PD,0)+ isNull(charLen(TEST_VAL,0)+ isNull(charLen(TEST_YN,0)+ isNull(charLen(TEST_DTACM,0)+ isNull(charLen(TEST_MST,0) from test_info_m");
diff --git a/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java b/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java
index 105182e9a..daaa77562 100644
--- a/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java
+++ b/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java
@@ -1358,7 +1358,12 @@ public void testCase() throws JSQLParserException {
+ // "WHEN (SELECT c FROM tab2 WHERE d = 2) = 3 THEN 'AAA' " +
"END) FROM tab1";
assertSqlCanBeParsedAndDeparsed(statement);
+ }
+ @Test
+ public void testNestedCaseCondition() throws JSQLParserException {
+ assertSqlCanBeParsedAndDeparsed("SELECT CASE WHEN CASE WHEN 1 THEN 10 ELSE 20 END > 15 THEN 'BBB' END FROM tab1");
+ assertSqlCanBeParsedAndDeparsed("SELECT (CASE WHEN (CASE a WHEN 1 THEN 10 ELSE 20 END) > 15 THEN 'BBB' END) FROM tab1");
}
@Test