in src/main/java/com/google/cloud/spanner/pgadapter/statements/SimpleParser.java [243:291]
static Statement replaceForUpdate(
Statement statement, String lowerCaseSql, boolean replaceWithHint) {
// If there is no 'for' clause, then we know that we don't have to analyze any further.
if (!lowerCaseSql.contains("for")) {
return statement;
}
SimpleParser parser = new SimpleParser(statement.getSql());
parser.parseExpressionUntilKeyword(ImmutableList.of("for"), true, false, false);
if (parser.pos >= parser.getSql().length()) {
return statement;
}
int startPos = parser.pos;
if (parser.eatKeyword("for") && parser.eatKeyword("update")) {
if (!replaceWithHint) {
startPos = parser.pos;
}
int endPos = parser.pos;
// Skip 'of table1[, table2[, ...]] clauses
if (parser.eatKeyword("of")) {
List<TableOrIndexName> tables = parser.readTableList();
if (tables.isEmpty()) {
return statement;
}
endPos = parser.pos;
} else if (!replaceWithHint) {
// Stop here if the statement does not contain an 'of table' clause.
return statement;
}
// 'nowait' and 'skip locked' clauses are not supported.
if (parser.eatKeyword("nowait") || parser.eatKeyword("skip")) {
return statement;
}
if (parser.hasMoreTokens()) {
return statement;
}
// This is a simple 'for update' clause. Replace it with a 'LOCK_SCANNED_RANGES=exclusive'
// hint and/or remove the 'of table' clause.
if (replaceWithHint) {
return Statement.of(
"/*@ LOCK_SCANNED_RANGES=exclusive */"
+ statement.getSql().substring(0, startPos)
+ statement.getSql().substring(endPos));
} else {
return Statement.of(
statement.getSql().substring(0, startPos) + statement.getSql().substring(endPos));
}
}
return statement;
}