Skip to content

Commit e6d50f7

Browse files
lucasdillmannLucas Dillmann
andauthored
#1610 Support for SKIP LOCKED tokens on SELECT statements (#1649)
Co-authored-by: Lucas Dillmann <[email protected]>
1 parent 15ff843 commit e6d50f7

File tree

11 files changed

+73
-5
lines changed

11 files changed

+73
-5
lines changed

src/main/java/net/sf/jsqlparser/parser/feature/Feature.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,10 @@ public enum Feature {
261261
* "FOR UPDATE NOWAIT"
262262
*/
263263
selectForUpdateNoWait,
264+
/**
265+
* "FOR UPDATE SKIP LOCKED"
266+
*/
267+
selectForUpdateSkipLocked,
264268

265269

266270
/**

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ public class PlainSelect extends ASTNodeAccessImpl implements SelectBody {
4848
private boolean oracleSiblings = false;
4949
private boolean forUpdate = false;
5050
private Table forUpdateTable = null;
51+
private boolean skipLocked;
5152
private boolean useBrackets = false;
5253
private Wait wait;
5354
private boolean mySqlSqlCalcFoundRows = false;
@@ -349,6 +350,14 @@ public void setWindowDefinitions(List<WindowDefinition> windowDefinitions) {
349350
this.windowDefinitions = windowDefinitions;
350351
}
351352

353+
public boolean isSkipLocked() {
354+
return skipLocked;
355+
}
356+
357+
public void setSkipLocked(boolean skipLocked) {
358+
this.skipLocked = skipLocked;
359+
}
360+
352361
@Override
353362
@SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.ExcessiveMethodLength", "PMD.NPathComplexity"})
354363
public String toString() {
@@ -464,6 +473,8 @@ public String toString() {
464473

465474
if (isNoWait()) {
466475
sql.append(" NOWAIT");
476+
} else if (isSkipLocked()) {
477+
sql.append(" SKIP LOCKED");
467478
}
468479
}
469480
if (optimizeFor != null) {
@@ -720,6 +731,11 @@ public PlainSelect withNoWait(boolean noWait) {
720731
return this;
721732
}
722733

734+
public PlainSelect withSkipLocked(boolean skipLocked) {
735+
this.setSkipLocked(skipLocked);
736+
return this;
737+
}
738+
723739
public PlainSelect withHaving(Expression having) {
724740
this.setHaving(having);
725741
return this;

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,8 @@ public void visit(PlainSelect plainSelect) {
217217
}
218218
if (plainSelect.isNoWait()) {
219219
buffer.append(" NOWAIT");
220+
} else if (plainSelect.isSkipLocked()) {
221+
buffer.append(" SKIP LOCKED");
220222
}
221223
}
222224
if (plainSelect.getOptimizeFor() != null) {

src/main/java/net/sf/jsqlparser/util/validation/feature/MariaDbVersion.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,10 @@ public enum MariaDbVersion implements Version {
3535
Feature.selectHaving,
3636
Feature.limit, Feature.limitOffset, Feature.offset, Feature.offsetParam,
3737
Feature.orderBy,
38-
Feature.selectForUpdate, Feature.selectForUpdateWait, Feature.selectForUpdateNoWait,
38+
Feature.selectForUpdate,
39+
Feature.selectForUpdateWait,
40+
Feature.selectForUpdateNoWait,
41+
Feature.selectForUpdateSkipLocked,
3942

4043
// https://mariadb.com/kb/en/join-syntax/
4144
Feature.join, Feature.joinSimple, Feature.joinRight, Feature.joinNatural, Feature.joinLeft,

src/main/java/net/sf/jsqlparser/util/validation/feature/MySqlVersion.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,10 @@ public enum MySqlVersion implements Version {
3333
Feature.select,
3434
Feature.selectGroupBy, Feature.selectHaving,
3535
Feature.limit, Feature.limitOffset, Feature.offset, Feature.offsetParam, Feature.orderBy,
36-
Feature.selectForUpdate, Feature.selectForUpdateOfTable, Feature.selectForUpdateNoWait,
36+
Feature.selectForUpdate,
37+
Feature.selectForUpdateOfTable,
38+
Feature.selectForUpdateNoWait,
39+
Feature.selectForUpdateSkipLocked,
3740
Feature.distinct,
3841

3942
Feature.setOperation,

src/main/java/net/sf/jsqlparser/util/validation/feature/OracleVersion.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,9 @@ public enum OracleVersion implements Version {
8383
// https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/SELECT.html
8484
// see "for_update_clause"
8585
Feature.selectForUpdate,
86-
Feature.selectForUpdateWait, Feature.selectForUpdateNoWait,
86+
Feature.selectForUpdateWait,
87+
Feature.selectForUpdateNoWait,
88+
Feature.selectForUpdateSkipLocked,
8789

8890
// https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/INSERT.html
8991
Feature.insert,

src/main/java/net/sf/jsqlparser/util/validation/feature/PostgresqlVersion.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ public enum PostgresqlVersion implements Version {
7676
Feature.selectForUpdate,
7777
Feature.selectForUpdateOfTable,
7878
Feature.selectForUpdateNoWait,
79+
Feature.selectForUpdateSkipLocked,
7980

8081
// https://www.postgresql.org/docs/current/queries-union.html
8182
Feature.setOperation,

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ public void visit(PlainSelect plainSelect) {
8686
validateOptionalFeature(c, plainSelect.getForUpdateTable(), Feature.selectForUpdateOfTable);
8787
validateOptionalFeature(c, plainSelect.getWait(), Feature.selectForUpdateWait);
8888
validateFeature(c, plainSelect.isNoWait(), Feature.selectForUpdateNoWait);
89+
validateFeature(c, plainSelect.isSkipLocked(), Feature.selectForUpdateSkipLocked);
8990
}
9091

9192
validateOptionalFeature(c, plainSelect.getForXmlPath(), Feature.selectForXmlPath);

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */
274274
| <K_LIKE:"LIKE">
275275
| <K_LIMIT:"LIMIT">
276276
| <K_LOCAL:"LOCAL">
277+
| <K_LOCKED:"LOCKED">
277278
| <K_LINK:"LINK">
278279
| <K_LOG:"LOG">
279280
| <K_LOW_PRIORITY : "LOW_PRIORITY">
@@ -2076,7 +2077,8 @@ PlainSelect PlainSelect() #PlainSelect:
20762077
[LOOKAHEAD(2) <K_FOR> <K_UPDATE> { plainSelect.setForUpdate(true); }
20772078
[ <K_OF> updateTable = Table() { plainSelect.setForUpdateTable(updateTable); } ]
20782079
[ LOOKAHEAD(<K_WAIT>) wait = Wait() { plainSelect.setWait(wait); } ]
2079-
[ <K_NOWAIT> { plainSelect.setNoWait(true); } ] ]
2080+
[ <K_NOWAIT> { plainSelect.setNoWait(true); }
2081+
| <K_SKIP> <K_LOCKED> { plainSelect.setSkipLocked(true); } ] ]
20802082

20812083
[LOOKAHEAD(<K_OPTIMIZE>) optimize = OptimizeFor() { plainSelect.setOptimizeFor(optimize); } ]
20822084

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

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5265,4 +5265,37 @@ public void testOracleDBLink() throws JSQLParserException {
52655265
assertEquals("tablename", table.getName());
52665266
assertEquals("dblink", table.getDBLinkName());
52675267
}
5268+
5269+
@Test
5270+
public void testSelectStatementWithForUpdateAndSkipLockedTokens() throws JSQLParserException {
5271+
String sql = "SELECT * FROM test FOR UPDATE SKIP LOCKED";
5272+
assertSqlCanBeParsedAndDeparsed(sql);
5273+
5274+
Select select = (Select) CCJSqlParserUtil.parse(sql);
5275+
PlainSelect plainSelect = (PlainSelect) select.getSelectBody();
5276+
assertTrue(plainSelect.isForUpdate());
5277+
assertTrue(plainSelect.isSkipLocked());
5278+
}
5279+
5280+
@Test
5281+
public void testSelectStatementWithForUpdateButWithoutSkipLockedTokens() throws JSQLParserException {
5282+
String sql = "SELECT * FROM test FOR UPDATE";
5283+
assertSqlCanBeParsedAndDeparsed(sql);
5284+
5285+
Select select = (Select) CCJSqlParserUtil.parse(sql);
5286+
PlainSelect plainSelect = (PlainSelect) select.getSelectBody();
5287+
assertTrue(plainSelect.isForUpdate());
5288+
assertFalse(plainSelect.isSkipLocked());
5289+
}
5290+
5291+
@Test
5292+
public void testSelectStatementWithoutForUpdateAndSkipLockedTokens() throws JSQLParserException {
5293+
String sql = "SELECT * FROM test";
5294+
assertSqlCanBeParsedAndDeparsed(sql);
5295+
5296+
Select select = (Select) CCJSqlParserUtil.parse(sql);
5297+
PlainSelect plainSelect = (PlainSelect) select.getSelectBody();
5298+
assertFalse(plainSelect.isForUpdate());
5299+
assertFalse(plainSelect.isSkipLocked());
5300+
}
52685301
}

0 commit comments

Comments
 (0)