Skip to content

Commit 426102e

Browse files
Fix Nested CASE WHEN performance, fixes issue #1162 (#1208)
* Fix Nested CASE WHEN performance, fixes issue #1162 * Apease Codazy * Apease Codazy
1 parent 86b613c commit 426102e

File tree

6 files changed

+122
-12
lines changed

6 files changed

+122
-12
lines changed

pmd-rules.xml

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,17 @@ under the License.
5454
<rule ref="category/java/codestyle.xml/UselessParentheses" />
5555
<rule ref="category/java/codestyle.xml/UselessQualifiedThis" />
5656

57-
<!-- for Codazy -->
58-
<rule ref="category/java/codestyle.xml/MethodNamingConventions" />
57+
<!-- for Codazy -->
58+
<rule ref="category/java/codestyle.xml/MethodNamingConventions">
59+
<properties>
60+
<property name="methodPattern" value="[a-z][a-zA-Z0-9]*" />
61+
<property name="staticPattern" value="[a-z][a-zA-Z0-9]*" />
62+
<property name="nativePattern" value="[a-z][a-zA-Z0-9]*" />
63+
<property name="junit3TestPattern" value="test[A-Z0-9][a-zA-Z0-9]*" />
64+
<property name="junit4TestPattern" value="[a-z][a-zA-Z0-9]*" />
65+
<property name="junit5TestPattern" value="[a-z][a-zA-Z0-9]*" />
66+
</properties>
67+
</rule>
5968
<rule ref="category/java/codestyle.xml/ClassNamingConventions" />
6069

6170
<rule ref="category/java/design.xml/CollapsibleIfStatements" />

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

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
*/
4444
public class CaseExpression extends ASTNodeAccessImpl implements Expression {
4545

46+
private boolean usingBrackets = false;
4647
private Expression switchExpression;
4748
private List<WhenClause> whenClauses;
4849
private Expression elseExpression;
@@ -90,9 +91,9 @@ public void setWhenClauses(List<WhenClause> whenClauses) {
9091

9192
@Override
9293
public String toString() {
93-
return "CASE " + ((switchExpression != null) ? switchExpression + " " : "")
94+
return (usingBrackets ? "(" : "") + "CASE " + ((switchExpression != null) ? switchExpression + " " : "")
9495
+ PlainSelect.getStringList(whenClauses, false, false) + " "
95-
+ ((elseExpression != null) ? "ELSE " + elseExpression + " " : "") + "END";
96+
+ ((elseExpression != null) ? "ELSE " + elseExpression + " " : "") + "END" + (usingBrackets ? ")" : "");
9697
}
9798

9899
public CaseExpression withSwitchExpression(Expression switchExpression) {
@@ -129,4 +130,26 @@ public <E extends Expression> E getSwitchExpression(Class<E> type) {
129130
public <E extends Expression> E getElseExpression(Class<E> type) {
130131
return type.cast(getElseExpression());
131132
}
133+
134+
/**
135+
* @return the usingBrackets
136+
*/
137+
public boolean isUsingBrackets() {
138+
return usingBrackets;
139+
}
140+
141+
/**
142+
* @param usingBrackets the usingBrackets to set
143+
*/
144+
public void setUsingBrackets(boolean usingBrackets) {
145+
this.usingBrackets = usingBrackets;
146+
}
147+
148+
/**
149+
* @param usingBrackets the usingBrackets to set
150+
*/
151+
public CaseExpression withUsingBrackets(boolean usingBrackets) {
152+
this.usingBrackets=usingBrackets;
153+
return this;
154+
}
132155
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -604,7 +604,7 @@ public void visit(TimeValue timeValue) {
604604

605605
@Override
606606
public void visit(CaseExpression caseExpression) {
607-
buffer.append("CASE ");
607+
buffer.append(caseExpression.isUsingBrackets() ? "(" : "").append("CASE ");
608608
Expression switchExp = caseExpression.getSwitchExpression();
609609
if (switchExp != null) {
610610
switchExp.accept(this);
@@ -622,7 +622,7 @@ public void visit(CaseExpression caseExpression) {
622622
buffer.append(" ");
623623
}
624624

625-
buffer.append("END");
625+
buffer.append("END").append(caseExpression.isUsingBrackets() ? ")" : "");
626626
}
627627

628628
@Override

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

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ import java.util.*;
6767
* The parser generated by JavaCC
6868
*/
6969
public class CCJSqlParser extends AbstractJSqlParser<CCJSqlParser> {
70+
public int bracketsCounter = 0;
71+
public int caseCounter = 0;
7072

7173
public CCJSqlParser withConfiguration(FeatureConfiguration configuration) {
7274
token_source.configuration = configuration;
@@ -3697,11 +3699,14 @@ Expression CaseWhenExpression() #CaseWhenExpression:
36973699
Expression elseExp = null;
36983700
}
36993701
{
3700-
<K_CASE>
3702+
<K_CASE> { caseCounter++; }
37013703
[ switchExp=Condition() ]
37023704
( clause=WhenThenSearchCondition() { whenClauses.add(clause); } )+
3703-
[<K_ELSE> elseExp=Condition()]
3704-
<K_END>
3705+
[<K_ELSE> (LOOKAHEAD( ["("] CaseWhenExpression() [")"] ) ["("] elseExp=CaseWhenExpression() [")" { ((CaseExpression) elseExp).setUsingBrackets(true); } ]
3706+
| elseExp=Condition()
3707+
)
3708+
]
3709+
<K_END> { caseCounter--; }
37053710
{
37063711
caseExp.setSwitchExpression(switchExp);
37073712
caseExp.setWhenClauses(whenClauses);
@@ -3717,8 +3722,10 @@ WhenClause WhenThenSearchCondition():
37173722
Expression thenExp = null;
37183723
}
37193724
{
3720-
<K_WHEN> (LOOKAHEAD(Expression()) whenExp=Expression() | whenExp=SimpleExpression())
3721-
<K_THEN> thenExp=Expression()
3725+
<K_WHEN> whenExp=Expression()
3726+
<K_THEN> (LOOKAHEAD( ["("] CaseWhenExpression() [")"] ) ["("] thenExp=CaseWhenExpression() [")" { ((CaseExpression) thenExp).setUsingBrackets(true); }]
3727+
| thenExp=Expression()
3728+
)
37223729
{
37233730
whenThen.setWhenExpression(whenExp);
37243731
whenThen.setThenExpression(thenExp);

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

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,73 @@ public void testIssue235() throws JSQLParserException {
3838
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);
3939
}
4040

41-
@Test(timeout = 100000)
41+
@Test
42+
public void testNestedCaseWhenWithoutBracketsIssue1162() throws JSQLParserException {
43+
assertSqlCanBeParsedAndDeparsed("CREATE VIEW VIEW_NAME1 AS\n" +
44+
"SELECT CASE\n" +
45+
"WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
46+
"ELSE CASE\n" +
47+
"WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
48+
"ELSE CASE\n" +
49+
"WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
50+
"ELSE CASE\n" +
51+
"WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
52+
"ELSE CASE\n" +
53+
"WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
54+
"ELSE CASE\n" +
55+
"WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
56+
"ELSE CASE\n" +
57+
"WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
58+
"ELSE CASE\n" +
59+
"WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
60+
"ELSE CASE\n" +
61+
"WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
62+
"ELSE CASE\n" +
63+
"WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
64+
"ELSE CASE\n" +
65+
"WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
66+
"ELSE CASE\n" +
67+
"WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
68+
"ELSE CASE\n" +
69+
"WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
70+
"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" +
71+
"FROM TABLE1", true);
72+
}
73+
74+
@Test
75+
public void testNestedCaseWhenWithBracketsIssue1162() throws JSQLParserException {
76+
assertSqlCanBeParsedAndDeparsed("CREATE VIEW VIEW_NAME1 AS\n" +
77+
"SELECT CASE\n" +
78+
"WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
79+
"ELSE (CASE\n" +
80+
"WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
81+
"ELSE (CASE\n" +
82+
"WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
83+
"ELSE (CASE\n" +
84+
"WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
85+
"ELSE (CASE\n" +
86+
"WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
87+
"ELSE (CASE\n" +
88+
"WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
89+
"ELSE (CASE\n" +
90+
"WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
91+
"ELSE (CASE\n" +
92+
"WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
93+
"ELSE (CASE\n" +
94+
"WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
95+
"ELSE (CASE\n" +
96+
"WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
97+
"ELSE (CASE\n" +
98+
"WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
99+
"ELSE (CASE\n" +
100+
"WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
101+
"ELSE (CASE\n" +
102+
"WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" +
103+
"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" +
104+
"FROM TABLE1", true);
105+
}
106+
107+
@Test(timeout = 200000)
42108
@Ignore
43109
public void testIssue496() throws JSQLParserException {
44110
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");

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1358,7 +1358,12 @@ public void testCase() throws JSQLParserException {
13581358
+ // "WHEN (SELECT c FROM tab2 WHERE d = 2) = 3 THEN 'AAA' " +
13591359
"END) FROM tab1";
13601360
assertSqlCanBeParsedAndDeparsed(statement);
1361+
}
13611362

1363+
@Test
1364+
public void testNestedCaseCondition() throws JSQLParserException {
1365+
assertSqlCanBeParsedAndDeparsed("SELECT CASE WHEN CASE WHEN 1 THEN 10 ELSE 20 END > 15 THEN 'BBB' END FROM tab1");
1366+
assertSqlCanBeParsedAndDeparsed("SELECT (CASE WHEN (CASE a WHEN 1 THEN 10 ELSE 20 END) > 15 THEN 'BBB' END) FROM tab1");
13621367
}
13631368

13641369
@Test

0 commit comments

Comments
 (0)