Skip to content

Commit

Permalink
#1610 Support for SKIP LOCKED tokens on SELECT statements (#1649)
Browse files Browse the repository at this point in the history
Co-authored-by: Lucas Dillmann <lucas.dillmann@totvs.com.br>
  • Loading branch information
lucasdillmann and Lucas Dillmann authored Oct 25, 2022
1 parent 15ff843 commit e6d50f7
Show file tree
Hide file tree
Showing 11 changed files with 73 additions and 5 deletions.
4 changes: 4 additions & 0 deletions src/main/java/net/sf/jsqlparser/parser/feature/Feature.java
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,10 @@ public enum Feature {
* "FOR UPDATE NOWAIT"
*/
selectForUpdateNoWait,
/**
* "FOR UPDATE SKIP LOCKED"
*/
selectForUpdateSkipLocked,


/**
Expand Down
16 changes: 16 additions & 0 deletions src/main/java/net/sf/jsqlparser/statement/select/PlainSelect.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public class PlainSelect extends ASTNodeAccessImpl implements SelectBody {
private boolean oracleSiblings = false;
private boolean forUpdate = false;
private Table forUpdateTable = null;
private boolean skipLocked;
private boolean useBrackets = false;
private Wait wait;
private boolean mySqlSqlCalcFoundRows = false;
Expand Down Expand Up @@ -349,6 +350,14 @@ public void setWindowDefinitions(List<WindowDefinition> windowDefinitions) {
this.windowDefinitions = windowDefinitions;
}

public boolean isSkipLocked() {
return skipLocked;
}

public void setSkipLocked(boolean skipLocked) {
this.skipLocked = skipLocked;
}

@Override
@SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.ExcessiveMethodLength", "PMD.NPathComplexity"})
public String toString() {
Expand Down Expand Up @@ -464,6 +473,8 @@ public String toString() {

if (isNoWait()) {
sql.append(" NOWAIT");
} else if (isSkipLocked()) {
sql.append(" SKIP LOCKED");
}
}
if (optimizeFor != null) {
Expand Down Expand Up @@ -720,6 +731,11 @@ public PlainSelect withNoWait(boolean noWait) {
return this;
}

public PlainSelect withSkipLocked(boolean skipLocked) {
this.setSkipLocked(skipLocked);
return this;
}

public PlainSelect withHaving(Expression having) {
this.setHaving(having);
return this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,8 @@ public void visit(PlainSelect plainSelect) {
}
if (plainSelect.isNoWait()) {
buffer.append(" NOWAIT");
} else if (plainSelect.isSkipLocked()) {
buffer.append(" SKIP LOCKED");
}
}
if (plainSelect.getOptimizeFor() != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ public enum MariaDbVersion implements Version {
Feature.selectHaving,
Feature.limit, Feature.limitOffset, Feature.offset, Feature.offsetParam,
Feature.orderBy,
Feature.selectForUpdate, Feature.selectForUpdateWait, Feature.selectForUpdateNoWait,
Feature.selectForUpdate,
Feature.selectForUpdateWait,
Feature.selectForUpdateNoWait,
Feature.selectForUpdateSkipLocked,

// https://mariadb.com/kb/en/join-syntax/
Feature.join, Feature.joinSimple, Feature.joinRight, Feature.joinNatural, Feature.joinLeft,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ public enum MySqlVersion implements Version {
Feature.select,
Feature.selectGroupBy, Feature.selectHaving,
Feature.limit, Feature.limitOffset, Feature.offset, Feature.offsetParam, Feature.orderBy,
Feature.selectForUpdate, Feature.selectForUpdateOfTable, Feature.selectForUpdateNoWait,
Feature.selectForUpdate,
Feature.selectForUpdateOfTable,
Feature.selectForUpdateNoWait,
Feature.selectForUpdateSkipLocked,
Feature.distinct,

Feature.setOperation,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,9 @@ public enum OracleVersion implements Version {
// https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/SELECT.html
// see "for_update_clause"
Feature.selectForUpdate,
Feature.selectForUpdateWait, Feature.selectForUpdateNoWait,
Feature.selectForUpdateWait,
Feature.selectForUpdateNoWait,
Feature.selectForUpdateSkipLocked,

// https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/INSERT.html
Feature.insert,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ public enum PostgresqlVersion implements Version {
Feature.selectForUpdate,
Feature.selectForUpdateOfTable,
Feature.selectForUpdateNoWait,
Feature.selectForUpdateSkipLocked,

// https://www.postgresql.org/docs/current/queries-union.html
Feature.setOperation,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ public void visit(PlainSelect plainSelect) {
validateOptionalFeature(c, plainSelect.getForUpdateTable(), Feature.selectForUpdateOfTable);
validateOptionalFeature(c, plainSelect.getWait(), Feature.selectForUpdateWait);
validateFeature(c, plainSelect.isNoWait(), Feature.selectForUpdateNoWait);
validateFeature(c, plainSelect.isSkipLocked(), Feature.selectForUpdateSkipLocked);
}

validateOptionalFeature(c, plainSelect.getForXmlPath(), Feature.selectForXmlPath);
Expand Down
4 changes: 3 additions & 1 deletion src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */
| <K_LIKE:"LIKE">
| <K_LIMIT:"LIMIT">
| <K_LOCAL:"LOCAL">
| <K_LOCKED:"LOCKED">
| <K_LINK:"LINK">
| <K_LOG:"LOG">
| <K_LOW_PRIORITY : "LOW_PRIORITY">
Expand Down Expand Up @@ -2076,7 +2077,8 @@ PlainSelect PlainSelect() #PlainSelect:
[LOOKAHEAD(2) <K_FOR> <K_UPDATE> { plainSelect.setForUpdate(true); }
[ <K_OF> updateTable = Table() { plainSelect.setForUpdateTable(updateTable); } ]
[ LOOKAHEAD(<K_WAIT>) wait = Wait() { plainSelect.setWait(wait); } ]
[ <K_NOWAIT> { plainSelect.setNoWait(true); } ] ]
[ <K_NOWAIT> { plainSelect.setNoWait(true); }
| <K_SKIP> <K_LOCKED> { plainSelect.setSkipLocked(true); } ] ]

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

Expand Down
33 changes: 33 additions & 0 deletions src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -5265,4 +5265,37 @@ public void testOracleDBLink() throws JSQLParserException {
assertEquals("tablename", table.getName());
assertEquals("dblink", table.getDBLinkName());
}

@Test
public void testSelectStatementWithForUpdateAndSkipLockedTokens() throws JSQLParserException {
String sql = "SELECT * FROM test FOR UPDATE SKIP LOCKED";
assertSqlCanBeParsedAndDeparsed(sql);

Select select = (Select) CCJSqlParserUtil.parse(sql);
PlainSelect plainSelect = (PlainSelect) select.getSelectBody();
assertTrue(plainSelect.isForUpdate());
assertTrue(plainSelect.isSkipLocked());
}

@Test
public void testSelectStatementWithForUpdateButWithoutSkipLockedTokens() throws JSQLParserException {
String sql = "SELECT * FROM test FOR UPDATE";
assertSqlCanBeParsedAndDeparsed(sql);

Select select = (Select) CCJSqlParserUtil.parse(sql);
PlainSelect plainSelect = (PlainSelect) select.getSelectBody();
assertTrue(plainSelect.isForUpdate());
assertFalse(plainSelect.isSkipLocked());
}

@Test
public void testSelectStatementWithoutForUpdateAndSkipLockedTokens() throws JSQLParserException {
String sql = "SELECT * FROM test";
assertSqlCanBeParsedAndDeparsed(sql);

Select select = (Select) CCJSqlParserUtil.parse(sql);
PlainSelect plainSelect = (PlainSelect) select.getSelectBody();
assertFalse(plainSelect.isForUpdate());
assertFalse(plainSelect.isSkipLocked());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ select employee_id from (select employee_id+1 as employee_id from employees)
for update of employee_id skip locked


--@FAILURE: Encountered unexpected token: "skip" "SKIP" recorded first on Aug 3, 2021, 7:20:08 AM
--@FAILURE: Encountered unexpected token: "skip" "SKIP" recorded first on Aug 3, 2021, 7:20:08 AM
--@SUCCESSFULLY_PARSED_AND_DEPARSED first on Oct 19, 2022, 6:34:12 PM

0 comments on commit e6d50f7

Please sign in to comment.