Skip to content

Commit 283b28a

Browse files
committed
Merge remote-tracking branch 'refs/remotes/JSQLParser/master' into fix-alter-drop
2 parents b6f71e6 + e570a91 commit 283b28a

File tree

13 files changed

+280
-0
lines changed

13 files changed

+280
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ Also I would like to know about needed examples or documentation stuff.
3838

3939
## Extensions in the latest SNAPSHOT version 0.9.5
4040

41+
* first Oracle hint support for **select** statements
4142
* first **alter table foreign key** support
4243
* first **merge** support
4344
* first version of escaped single quotes support

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,4 +162,7 @@ public interface ExpressionVisitor {
162162
void visit(MySQLGroupConcat groupConcat);
163163

164164
void visit(RowConstructor rowConstructor);
165+
166+
void visit(OracleHint hint);
167+
165168
}

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,4 +452,10 @@ public void visit(RowConstructor rowConstructor) {
452452
public void visit(HexValue hexValue) {
453453

454454
}
455+
456+
@Override
457+
public void visit(OracleHint hint) {
458+
459+
}
460+
455461
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/*
2+
* #%L
3+
* JSQLParser library
4+
* %%
5+
* Copyright (C) 2004 - 2013 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.expression;
23+
24+
import java.util.regex.Matcher;
25+
import java.util.regex.Pattern;
26+
27+
/**
28+
* Oracle Hint Expression
29+
* @author valdo
30+
*/
31+
public class OracleHint implements Expression {
32+
33+
private static final Pattern SINGLE_LINE = Pattern.compile("--\\+ *([^ ].*[^ ])");
34+
private static final Pattern MULTI_LINE = Pattern.compile("\\/\\*\\+ *([^ ].*[^ ]) *\\*+\\/", Pattern.MULTILINE | Pattern.DOTALL);
35+
36+
public static boolean isHintMatch(String comment) {
37+
return SINGLE_LINE.matcher(comment).find() ||
38+
MULTI_LINE.matcher(comment).find();
39+
}
40+
41+
private String value;
42+
private boolean singleLine = false;
43+
44+
public final void setComment(String comment) {
45+
Matcher m;
46+
{
47+
m = SINGLE_LINE.matcher(comment);
48+
if (m.find()) {
49+
this.value = m.group(1);
50+
this.singleLine = true;
51+
return;
52+
}
53+
}
54+
{
55+
m = MULTI_LINE.matcher(comment);
56+
if (m.find()) {
57+
this.value = m.group(1);
58+
this.singleLine = false;
59+
}
60+
}
61+
}
62+
63+
public String getValue() {
64+
return value;
65+
}
66+
67+
public void setValue(String value) {
68+
this.value = value;
69+
}
70+
71+
public boolean isSingleLine() {
72+
return singleLine;
73+
}
74+
75+
public void setSingleLine(boolean singleLine) {
76+
this.singleLine = singleLine;
77+
}
78+
79+
@Override
80+
public void accept(ExpressionVisitor visitor) {
81+
visitor.visit(this);
82+
}
83+
84+
@Override
85+
public String toString() {
86+
if (singleLine) {
87+
return "--+ " + value + "\n";
88+
} else {
89+
return "/*+ " + value + " */";
90+
}
91+
}
92+
93+
}

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import java.util.Iterator;
3030
import java.util.List;
3131
import net.sf.jsqlparser.expression.OracleHierarchicalExpression;
32+
import net.sf.jsqlparser.expression.OracleHint;
3233

3334
/**
3435
* The core of a "SELECT" statement (no UNION, no ORDER BY)
@@ -51,6 +52,7 @@ public class PlainSelect implements SelectBody {
5152
private First first;
5253
private Top top;
5354
private OracleHierarchicalExpression oracleHierarchical = null;
55+
private OracleHint oracleHint = null;
5456
private boolean oracleSiblings = false;
5557
private boolean forUpdate = false;
5658
private Table forUpdateTable = null;
@@ -257,6 +259,14 @@ public void setForUpdateTable(Table forUpdateTable) {
257259
this.forUpdateTable = forUpdateTable;
258260
}
259261

262+
public OracleHint getOracleHint() {
263+
return oracleHint;
264+
}
265+
266+
public void setOracleHint(OracleHint oracleHint) {
267+
this.oracleHint = oracleHint;
268+
}
269+
260270
@Override
261271
public String toString() {
262272
StringBuilder sql = new StringBuilder();
@@ -265,6 +275,10 @@ public String toString() {
265275
}
266276
sql.append("SELECT ");
267277

278+
if (oracleHint != null) {
279+
sql.append(oracleHint).append(" ");
280+
}
281+
268282
if (skip != null) {
269283
sql.append(skip).append(" ");
270284
}

src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -633,4 +633,9 @@ public void visit(HexValue hexValue) {
633633
public void visit(Merge merge) {
634634
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
635635
}
636+
637+
@Override
638+
public void visit(OracleHint hint) {
639+
}
640+
636641
}

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,4 +569,10 @@ public void visit(RowConstructor rowConstructor) {
569569
}
570570
buffer.append(")");
571571
}
572+
573+
@Override
574+
public void visit(OracleHint hint) {
575+
buffer.append(hint.toString());
576+
}
577+
572578
}

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@ public void visit(PlainSelect plainSelect) {
5757
}
5858
buffer.append("SELECT ");
5959

60+
OracleHint hint = plainSelect.getOracleHint();
61+
if (hint != null) {
62+
buffer.append(hint).append(" ");
63+
}
64+
6065
Skip skip = plainSelect.getSkip();
6166
if (skip != null) {
6267
buffer.append(skip).append(" ");

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -722,6 +722,8 @@ PlainSelect PlainSelect():
722722
{
723723
<K_SELECT>
724724

725+
{ plainSelect.setOracleHint(getOracleHint()); }
726+
725727
[skip = Skip() { plainSelect.setSkip(skip); } ]
726728

727729
[LOOKAHEAD(2) first = First() { plainSelect.setFirst(first); } ]
@@ -1397,6 +1399,23 @@ Skip Skip():
13971399
}
13981400
}
13991401

1402+
JAVACODE
1403+
OracleHint getOracleHint() {
1404+
OracleHint hint = null;
1405+
Token tok = getToken(1);
1406+
// Retrieve first comment (if any) prior next token
1407+
if (tok.specialToken != null) {
1408+
tok = tok.specialToken;
1409+
while (tok.specialToken != null) tok = tok.specialToken;
1410+
// Check if it matches Hint pattern?
1411+
if (OracleHint.isHintMatch(tok.image)) {
1412+
hint = new OracleHint();
1413+
hint.setComment(tok.image);
1414+
}
1415+
}
1416+
return hint;
1417+
}
1418+
14001419
First First():
14011420
{
14021421
First first = new First();

src/test/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapterTest.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,11 @@
2828
import net.sf.jsqlparser.statement.select.Select;
2929
import org.junit.After;
3030
import org.junit.AfterClass;
31+
import static org.junit.Assert.assertNotNull;
3132
import static org.junit.Assert.assertNull;
3233
import static org.junit.Assert.assertTrue;
34+
import static org.junit.Assert.assertFalse;
35+
import static org.junit.Assert.assertEquals;
3336
import org.junit.Before;
3437
import org.junit.BeforeClass;
3538
import org.junit.Test;
@@ -102,4 +105,30 @@ public void visit(InExpression expr) {
102105
assertTrue(exprList.get(1) instanceof ItemsList);
103106
assertTrue(exprList.get(2) instanceof ItemsList);
104107
}
108+
109+
@Test
110+
public void testOracleHintExpressions() throws JSQLParserException {
111+
testOracleHintExpression("select --+ MYHINT \n * from foo", "MYHINT", true);
112+
testOracleHintExpression("select /*+ MYHINT */ * from foo", "MYHINT", false);
113+
}
114+
115+
public static void testOracleHintExpression(String sql, String hint, boolean singleLine) throws JSQLParserException {
116+
Select select = (Select) CCJSqlParserUtil.parse(sql);
117+
PlainSelect plainSelect = (PlainSelect) select.getSelectBody();
118+
final OracleHint[] holder = new OracleHint[1];
119+
assertNotNull(plainSelect.getOracleHint());
120+
plainSelect.getOracleHint().accept(new ExpressionVisitorAdapter() {
121+
122+
@Override
123+
public void visit(OracleHint hint) {
124+
super.visit(hint);
125+
holder[0] = hint;
126+
}
127+
});
128+
129+
assertNotNull(holder[0]);
130+
assertEquals(singleLine, holder[0].isSingleLine());
131+
assertEquals(hint, holder[0].getValue());
132+
}
133+
105134
}

0 commit comments

Comments
 (0)