Skip to content

Commit 2cae62d

Browse files
Savepoint rollback (#1236)
* Implement SAVEPOINT and ROLLBACK statements, fixes issue #1235 * Activate a test which is supported now.
1 parent 750f3d1 commit 2cae62d

File tree

11 files changed

+300
-25
lines changed

11 files changed

+300
-25
lines changed
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/*-
2+
* #%L
3+
* JSQLParser library
4+
* %%
5+
* Copyright (C) 2004 - 2021 JSQLParser
6+
* %%
7+
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
8+
* #L%
9+
*/
10+
/*
11+
* Copyright (C) 2021 JSQLParser.
12+
*
13+
* This library is free software; you can redistribute it and/or modify it under the terms of the
14+
* GNU Lesser General Public License as published by the Free Software Foundation; either version
15+
* 2.1 of the License, or (at your option) any later version.
16+
*
17+
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
18+
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19+
* Lesser General Public License for more details.
20+
*
21+
* You should have received a copy of the GNU Lesser General Public License along with this library;
22+
* if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23+
* 02110-1301 USA
24+
*/
25+
26+
package net.sf.jsqlparser.statement;
27+
28+
/**
29+
*
30+
* @author are
31+
*/
32+
public class RollbackStatement implements Statement {
33+
private boolean usingWorkKeyword=false;
34+
private boolean usingSavepointKeyword=false;
35+
private String savepointName=null;
36+
private String forceDistributedTransactionIdentifier=null;
37+
38+
public boolean isUsingWorkKeyword() {
39+
return usingWorkKeyword;
40+
}
41+
42+
public RollbackStatement withUsingWorkKeyword(boolean usingWorkKeyword) {
43+
this.usingWorkKeyword = usingWorkKeyword;
44+
return this;
45+
}
46+
47+
public void setUsingWorkKeyword(boolean usingWorkKeyword) {
48+
this.usingWorkKeyword = usingWorkKeyword;
49+
}
50+
51+
public boolean isUsingSavepointKeyword() {
52+
return usingSavepointKeyword;
53+
}
54+
55+
public RollbackStatement withUsingSavepointKeyword(boolean usingSavepointKeyword) {
56+
this.usingSavepointKeyword = usingSavepointKeyword;
57+
return this;
58+
}
59+
60+
public void setUsingSavepointKeyword(boolean usingSavepointKeyword) {
61+
this.usingSavepointKeyword = usingSavepointKeyword;
62+
}
63+
64+
public String getSavepointName() {
65+
return savepointName;
66+
}
67+
68+
public RollbackStatement withSavepointName(String savepointName) {
69+
this.savepointName = savepointName;
70+
return this;
71+
}
72+
73+
public void setSavepointName(String savepointName) {
74+
this.savepointName = savepointName;
75+
}
76+
77+
public String getForceDistributedTransactionIdentifier() {
78+
return forceDistributedTransactionIdentifier;
79+
}
80+
81+
public RollbackStatement withForceDistributedTransactionIdentifier(String forceDistributedTransactionIdentifier) {
82+
this.forceDistributedTransactionIdentifier = forceDistributedTransactionIdentifier;
83+
return this;
84+
}
85+
86+
public void setForceDistributedTransactionIdentifier(String forceDistributedTransactionIdentifier) {
87+
this.forceDistributedTransactionIdentifier = forceDistributedTransactionIdentifier;
88+
}
89+
90+
@Override
91+
public String toString() {
92+
return "ROLLBACK "
93+
+ ( usingWorkKeyword
94+
? "WORK "
95+
: "" )
96+
+ (savepointName!=null && savepointName.trim().length()!=0
97+
? "TO " + (usingSavepointKeyword
98+
? "SAVEPOINT "
99+
: "") + savepointName
100+
: forceDistributedTransactionIdentifier!=null && forceDistributedTransactionIdentifier.trim().length()!=0
101+
? "FORCE " + forceDistributedTransactionIdentifier
102+
: ""
103+
104+
);
105+
}
106+
107+
@Override
108+
public void accept(StatementVisitor statementVisitor) {
109+
statementVisitor.visit(this);
110+
}
111+
112+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*-
2+
* #%L
3+
* JSQLParser library
4+
* %%
5+
* Copyright (C) 2004 - 2021 JSQLParser
6+
* %%
7+
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
8+
* #L%
9+
*/
10+
/*
11+
* Copyright (C) 2021 JSQLParser.
12+
*
13+
* This library is free software; you can redistribute it and/or modify it under the terms of the
14+
* GNU Lesser General Public License as published by the Free Software Foundation; either version
15+
* 2.1 of the License, or (at your option) any later version.
16+
*
17+
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
18+
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19+
* Lesser General Public License for more details.
20+
*
21+
* You should have received a copy of the GNU Lesser General Public License along with this library;
22+
* if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23+
* 02110-1301 USA
24+
*/
25+
26+
package net.sf.jsqlparser.statement;
27+
28+
import java.util.Objects;
29+
30+
/**
31+
*
32+
* @author are
33+
*/
34+
public class SavepointStatement implements Statement {
35+
private String savepointName;
36+
37+
public String getSavepointName() {
38+
return savepointName;
39+
}
40+
41+
public void setSavepointName(String savepointName) {
42+
this.savepointName = Objects.requireNonNull(savepointName, "The Savepoint Name must not be NULL.");
43+
}
44+
45+
public SavepointStatement(String savepointName) {
46+
this.savepointName = Objects.requireNonNull(savepointName, "The Savepoint Name must not be NULL.");
47+
}
48+
49+
@Override
50+
public String toString() {
51+
return "SAVEPOINT " + savepointName;
52+
}
53+
54+
@Override
55+
public void accept(StatementVisitor statementVisitor) {
56+
statementVisitor.visit(this);
57+
}
58+
}

src/main/java/net/sf/jsqlparser/statement/StatementVisitor.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@
3535
import net.sf.jsqlparser.statement.values.ValuesStatement;
3636

3737
public interface StatementVisitor {
38+
39+
void visit(SavepointStatement savepointStatement);
40+
41+
void visit(RollbackStatement rollbackStatement);
3842

3943
void visit(Comment comment);
4044

src/main/java/net/sf/jsqlparser/statement/StatementVisitorAdapter.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,8 +197,17 @@ public void visit(CreateFunctionalStatement createFunctionalStatement) {
197197
public void visit(CreateSynonym createSynonym) {
198198
}
199199

200+
@Override
201+
public void visit(SavepointStatement savepointStatement) {
202+
//@todo: do something usefull here
203+
}
204+
205+
@Override
206+
public void visit(RollbackStatement rollbackStatement) {
207+
//@todo: do something usefull here
208+
}
200209
@Override
201210
public void visit(AlterSession alterSession) {
202-
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
211+
//@todo: do something usefull here
203212
}
204213
}

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -994,7 +994,17 @@ public void visit(TimezoneExpression aThis) {
994994
aThis.getLeftExpression().accept(this);
995995
}
996996

997+
@Override
998+
public void visit(SavepointStatement savepointStatement) {
999+
}
1000+
1001+
@Override
1002+
public void visit(RollbackStatement rollbackStatement) {
1003+
1004+
}
1005+
9971006
@Override
9981007
public void visit(AlterSession alterSession) {
1008+
9991009
}
10001010
}

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
import net.sf.jsqlparser.statement.DeclareStatement;
1919
import net.sf.jsqlparser.statement.DescribeStatement;
2020
import net.sf.jsqlparser.statement.ExplainStatement;
21+
import net.sf.jsqlparser.statement.RollbackStatement;
22+
import net.sf.jsqlparser.statement.SavepointStatement;
2123
import net.sf.jsqlparser.statement.ResetStatement;
2224
import net.sf.jsqlparser.statement.SetStatement;
2325
import net.sf.jsqlparser.statement.ShowColumnsStatement;
@@ -216,6 +218,16 @@ public void visit(Merge merge) {
216218
buffer.append(merge.toString());
217219
}
218220

221+
@Override
222+
public void visit(SavepointStatement savepointStatement) {
223+
buffer.append(savepointStatement.toString());
224+
}
225+
226+
@Override
227+
public void visit(RollbackStatement rollbackStatement) {
228+
buffer.append(rollbackStatement.toString());
229+
}
230+
219231
@Override
220232
public void visit(Commit commit) {
221233
buffer.append(commit.toString());

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

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
import net.sf.jsqlparser.statement.DeclareStatement;
1717
import net.sf.jsqlparser.statement.DescribeStatement;
1818
import net.sf.jsqlparser.statement.ExplainStatement;
19+
import net.sf.jsqlparser.statement.RollbackStatement;
20+
import net.sf.jsqlparser.statement.SavepointStatement;
1921
import net.sf.jsqlparser.statement.ResetStatement;
2022
import net.sf.jsqlparser.statement.SetStatement;
2123
import net.sf.jsqlparser.statement.ShowColumnsStatement;
@@ -262,8 +264,17 @@ public void visit(CreateSynonym createSynonym) {
262264
}
263265

264266
@Override
267+
public void visit(SavepointStatement savepointStatement) {
268+
//@todo: write something usefull here
269+
}
270+
271+
@Override
272+
public void visit(RollbackStatement rollbackStatement) {
273+
//@todo: write something usefull here
274+
}
275+
265276
public void visit(AlterSession alterSession) {
266-
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
277+
//@todo: write something usefull here
267278
}
268279

269280
}

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

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */
323323
| <K_ROLLBACK:"ROLLBACK">
324324
| <K_ROW: "ROW">
325325
| <K_ROWS: "ROWS">
326+
| <K_SAVEPOINT: "SAVEPOINT">
326327
| <K_SCHEMA: "SCHEMA">
327328
| <K_SELECT: ("SELECT" | "SEL")>
328329
| <K_SEMI : "SEMI">
@@ -381,6 +382,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */
381382
| <K_WITH:"WITH">
382383
| <K_WITHIN:"WITHIN">
383384
| <K_WITHOUT:"WITHOUT">
385+
| <K_WORK:"WORK">
384386
| <K_XML:"XML">
385387
| <K_XOR:"XOR">
386388
| <K_XMLSERIALIZE:"XMLSERIALIZE">
@@ -551,6 +553,10 @@ Statement SingleStatement() :
551553
|
552554
stm = Use()
553555
|
556+
stm = SavepointStatement()
557+
|
558+
stm = RollbackStatement()
559+
|
554560
stm = Commit()
555561
|
556562
stm = Comment()
@@ -5238,6 +5244,42 @@ Wait Wait():
52385244
}
52395245
}
52405246

5247+
SavepointStatement SavepointStatement():
5248+
{
5249+
SavepointStatement savepointStatement;
5250+
}
5251+
{
5252+
<K_SAVEPOINT> token=<S_IDENTIFIER> { savepointStatement = new SavepointStatement(token.image); }
5253+
{
5254+
return savepointStatement;
5255+
}
5256+
}
5257+
5258+
RollbackStatement RollbackStatement():
5259+
{
5260+
RollbackStatement rollbackStatement;
5261+
boolean usingWorkKeyword=false;
5262+
boolean usingSavepointKeyword=false;
5263+
String savepointName=null;
5264+
String forceDistributedTransactionIdentifier=null;
5265+
}
5266+
{
5267+
<K_ROLLBACK> { rollbackStatement = new RollbackStatement(); }
5268+
[ <K_WORK> { rollbackStatement.setUsingWorkKeyword(true); } ]
5269+
[ (
5270+
<K_TO> [ <K_SAVEPOINT> { rollbackStatement.setUsingSavepointKeyword(true); }]
5271+
token=<S_IDENTIFIER> { rollbackStatement.setSavepointName(token.image); }
5272+
)
5273+
|
5274+
(
5275+
<K_FORCE> token=<S_CHAR_LITERAL> { rollbackStatement.setForceDistributedTransactionIdentifier(token.image); }
5276+
) ]
5277+
5278+
{
5279+
return rollbackStatement;
5280+
}
5281+
}
5282+
52415283
Commit Commit():
52425284
{
52435285
Commit commit=new Commit();
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*-
2+
* #%L
3+
* JSQLParser library
4+
* %%
5+
* Copyright (C) 2004 - 2019 JSQLParser
6+
* %%
7+
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
8+
* #L%
9+
*/
10+
package net.sf.jsqlparser.statement;
11+
12+
import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed;
13+
14+
import org.junit.Test;
15+
16+
public class SavepointRollbackCommitTest {
17+
@Test
18+
public void testSavepoint() throws Exception {
19+
assertSqlCanBeParsedAndDeparsed("SAVEPOINT banda_sal", true);
20+
}
21+
22+
@Test
23+
public void testRollback() throws Exception {
24+
assertSqlCanBeParsedAndDeparsed("ROLLBACK", true);
25+
assertSqlCanBeParsedAndDeparsed("ROLLBACK WORK", true);
26+
assertSqlCanBeParsedAndDeparsed("ROLLBACK TO banda_sal", true);
27+
assertSqlCanBeParsedAndDeparsed("ROLLBACK TO SAVEPOINT banda_sal", true);
28+
assertSqlCanBeParsedAndDeparsed("ROLLBACK WORK TO banda_sal", true);
29+
assertSqlCanBeParsedAndDeparsed("ROLLBACK WORK TO SAVEPOINT banda_sal", true);
30+
assertSqlCanBeParsedAndDeparsed("ROLLBACK FORCE '25.32.87'", true);
31+
assertSqlCanBeParsedAndDeparsed("ROLLBACK WORK FORCE '25.32.87'", true);
32+
}
33+
34+
35+
@Test
36+
public void testCommit() throws Exception {
37+
assertSqlCanBeParsedAndDeparsed("COMMIT");
38+
}
39+
}

src/test/java/net/sf/jsqlparser/statement/insert/InsertTest.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -334,9 +334,8 @@ public void testInsertKeyWordIntervalIssue682() throws JSQLParserException {
334334
}
335335

336336
@Test
337-
@Ignore
338337
public void testWithAtFront() throws JSQLParserException {
339-
assertSqlCanBeParsedAndDeparsed("WITH foo AS ( SELECT attr FROM bar ) INSERT INTO lalelu (attr) SELECT attr FROM foo");
338+
assertSqlCanBeParsedAndDeparsed("WITH foo AS ( SELECT attr FROM bar ) INSERT INTO lalelu (attr) SELECT attr FROM foo", true);
340339
}
341340

342341
@Test

0 commit comments

Comments
 (0)