Skip to content

Commit 4b0b5cb

Browse files
committed
implemented optimize for, fixes #348
1 parent cb0e0b7 commit 4b0b5cb

File tree

5 files changed

+96
-8
lines changed

5 files changed

+96
-8
lines changed
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* #%L
3+
* JSQLParser library
4+
* %%
5+
* Copyright (C) 2004 - 2019 JSQLParser
6+
* %%
7+
* This program is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU Lesser General Public License as
9+
* published by the Free Software Foundation, either version 2.1 of the
10+
* License, or (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Lesser Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Lesser Public
18+
* License along with this program. If not, see
19+
* <http://www.gnu.org/licenses/lgpl-2.1.html>.
20+
* #L%
21+
*/
22+
package net.sf.jsqlparser.statement.select;
23+
24+
/**
25+
* A optimize for clause.
26+
*/
27+
public class OptimizeFor {
28+
29+
private long rowCount;
30+
31+
public OptimizeFor(long rowCount) {
32+
this.rowCount = rowCount;
33+
}
34+
35+
public long getRowCount() {
36+
return rowCount;
37+
}
38+
39+
public void setRowCount(long l) {
40+
rowCount = l;
41+
}
42+
43+
@Override
44+
public String toString() {
45+
return " OPTIMIZE FOR " + rowCount + " ROWS";
46+
}
47+
}

src/main/java/net/sf/jsqlparser/statement/select/PlainSelect.java

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,15 @@
2121
*/
2222
package net.sf.jsqlparser.statement.select;
2323

24-
import net.sf.jsqlparser.expression.Expression;
25-
import net.sf.jsqlparser.expression.OracleHierarchicalExpression;
26-
import net.sf.jsqlparser.expression.OracleHint;
27-
import net.sf.jsqlparser.schema.Table;
28-
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
29-
3024
import java.util.ArrayList;
3125
import java.util.Collections;
3226
import java.util.Iterator;
3327
import java.util.List;
28+
import net.sf.jsqlparser.expression.Expression;
29+
import net.sf.jsqlparser.expression.OracleHierarchicalExpression;
30+
import net.sf.jsqlparser.expression.OracleHint;
31+
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
32+
import net.sf.jsqlparser.schema.Table;
3433

3534
/**
3635
* The core of a "SELECT" statement (no UNION, no ORDER BY)
@@ -49,6 +48,7 @@ public class PlainSelect extends ASTNodeAccessImpl implements SelectBody {
4948
private Limit limit;
5049
private Offset offset;
5150
private Fetch fetch;
51+
private OptimizeFor optimizeFor;
5252
private Skip skip;
5353
private First first;
5454
private Top top;
@@ -169,6 +169,14 @@ public void setFetch(Fetch fetch) {
169169
this.fetch = fetch;
170170
}
171171

172+
public OptimizeFor getOptimizeFor() {
173+
return optimizeFor;
174+
}
175+
176+
public void setOptimizeFor(OptimizeFor optimizeFor) {
177+
this.optimizeFor = optimizeFor;
178+
}
179+
172180
public Top getTop() {
173181
return top;
174182
}
@@ -377,6 +385,9 @@ public String toString() {
377385
sql.append(wait);
378386
}
379387
}
388+
if (optimizeFor != null) {
389+
sql.append(optimizeFor);
390+
}
380391
} else {
381392
//without from
382393
if (where != null) {

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
*/
2222
package net.sf.jsqlparser.util.deparser;
2323

24-
import java.util.*;
2524
import net.sf.jsqlparser.expression.*;
2625
import net.sf.jsqlparser.schema.*;
2726
import net.sf.jsqlparser.statement.select.*;
@@ -188,6 +187,9 @@ public void visit(PlainSelect plainSelect) {
188187
buffer.append(plainSelect.getWait());
189188
}
190189
}
190+
if (plainSelect.getOptimizeFor() != null) {
191+
deparseOptimizeFor(plainSelect.getOptimizeFor());
192+
}
191193
if (plainSelect.isUseBrackets()) {
192194
buffer.append(")");
193195
}
@@ -479,4 +481,10 @@ public void visit(ParenthesisFromItem parenthesis) {
479481
public void visit(ValuesStatement values) {
480482
new ValuesStatementDeParser(expressionVisitor, buffer).deParse(values);
481483
}
484+
485+
private void deparseOptimizeFor(OptimizeFor optimizeFor) {
486+
buffer.append(" OPTIMIZE FOR ");
487+
buffer.append(optimizeFor.getRowCount());
488+
buffer.append(" ROWS");
489+
}
482490
}

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

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */
249249
| <K_ORDER:"ORDER">
250250
| <K_OUTER:"OUTER">
251251
| <K_OVER:"OVER">
252+
| <K_OPTIMIZE: "OPTIMIZE" >
252253
| <K_PARTITION:"PARTITION">
253254
| <K_PERCENT:"PERCENT">
254255
| <K_PIVOT:"PIVOT">
@@ -1097,7 +1098,7 @@ String RelObjectNameExt():
10971098
String result=null;
10981099
}
10991100
{
1100-
( result=RelObjectName() | tk=<K_LEFT> | tk=<K_RIGHT> | tk=<K_SET> | tk=<K_DOUBLE> | tk=<K_IF>)
1101+
( result=RelObjectName() | tk=<K_LEFT> | tk=<K_RIGHT> | tk=<K_SET> | tk=<K_DOUBLE> | tk=<K_IF> | <K_OPTIMIZE>)
11011102
{
11021103
if (tk!=null) result=tk.image;
11031104
return result;
@@ -1181,6 +1182,7 @@ PlainSelect PlainSelect() #PlainSelect:
11811182
Limit limit = null;
11821183
Offset offset = null;
11831184
Fetch fetch = null;
1185+
OptimizeFor optimize = null;
11841186
Top top = null;
11851187
Skip skip = null;
11861188
First first = null;
@@ -1189,6 +1191,7 @@ PlainSelect PlainSelect() #PlainSelect:
11891191
Table updateTable = null;
11901192
Wait wait = null;
11911193
boolean mySqlSqlCalcFoundRows = false;
1194+
Token token;
11921195
}
11931196
{
11941197
<K_SELECT>
@@ -1243,6 +1246,8 @@ PlainSelect PlainSelect() #PlainSelect:
12431246
[ <K_OF> updateTable = Table() { plainSelect.setForUpdateTable(updateTable); } ]
12441247
[ LOOKAHEAD(<K_WAIT>) wait = Wait() { plainSelect.setWait(wait); } ] ]
12451248

1249+
[LOOKAHEAD(<K_OPTIMIZE>) optimize = OptimizeFor() { plainSelect.setOptimizeFor(optimize); } ]
1250+
12461251
{
12471252
plainSelect.setSelectItems(selectItems);
12481253
plainSelect.setFromItem(fromItem);
@@ -1995,6 +2000,18 @@ Fetch Fetch():
19952000
}
19962001
}
19972002

2003+
OptimizeFor OptimizeFor():
2004+
{
2005+
Token token;
2006+
LongValue value;
2007+
}
2008+
{
2009+
<K_OPTIMIZE> <K_FOR> token=<S_LONG> <K_ROWS> { value = new LongValue(token.image); }
2010+
{
2011+
return new OptimizeFor(value.getValue());
2012+
}
2013+
}
2014+
19982015
// according to http://technet.microsoft.com/en-us/library/ms189463.aspx
19992016
Top Top():
20002017
{

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3350,6 +3350,11 @@ public void testCaseThenCondition5() throws JSQLParserException {
33503350
assertSqlCanBeParsedAndDeparsed("SELECT * FROM col WHERE CASE WHEN a = 'c' THEN a IN (SELECT id FROM mytable) ELSE b IN (SELECT id FROM mytable) END");
33513351
}
33523352

3353+
@Test
3354+
public void testOptimizeForIssue348() throws JSQLParserException {
3355+
assertSqlCanBeParsedAndDeparsed("SELECT * FROM EMP ORDER BY SALARY DESC OPTIMIZE FOR 20 ROWS");
3356+
}
3357+
33533358
@Test
33543359
public void testRawStringExpressionIssue656() throws JSQLParserException {
33553360
for (String c : new String[]{"u", "e", "n", "r", "b", "rb"}) {

0 commit comments

Comments
 (0)