Skip to content

Commit

Permalink
Rename SQL parser components.
Browse files Browse the repository at this point in the history
  • Loading branch information
toverdijk authored and mp911de committed May 25, 2022
1 parent 43462fd commit c74bd6e
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 119 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import java.util.Set;
import java.util.TreeSet;

class TokenizedSql {
class ParsedSql {

private final String sql;

Expand All @@ -30,7 +30,7 @@ class TokenizedSql {

private final int parameterCount;

public TokenizedSql(String sql, List<TokenizedStatement> statements) {
public ParsedSql(String sql, List<TokenizedStatement> statements) {
this.sql = sql;
this.statements = statements;
this.statementCount = statements.size();
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/io/r2dbc/postgresql/PostgresqlBatch.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ final class PostgresqlBatch implements io.r2dbc.postgresql.api.PostgresqlBatch {
public PostgresqlBatch add(String sql) {
Assert.requireNonNull(sql, "sql must not be null");

if (!(PostgresqlSqlLexer.tokenize(sql).getParameterCount() == 0)) {
if (!(PostgresqlSqlParser.tokenize(sql).getParameterCount() == 0)) {
throw new IllegalArgumentException(String.format("Statement '%s' is not supported. This is often due to the presence of parameters.", sql));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
*
* @since 0.9
*/
class PostgresqlSqlLexer {
class PostgresqlSqlParser {

private static final char[] SPECIAL_AND_OPERATOR_CHARS = {
'+', '-', '*', '/', '<', '>', '=', '~', '!', '@', '#', '%', '^', '&', '|', '`', '?',
Expand All @@ -38,15 +38,15 @@ class PostgresqlSqlLexer {
Arrays.sort(SPECIAL_AND_OPERATOR_CHARS);
}

public static TokenizedSql tokenize(String sql) {
List<TokenizedSql.Token> tokens = new ArrayList<>();
List<TokenizedSql.TokenizedStatement> statements = new ArrayList<>();
public static ParsedSql tokenize(String sql) {
List<ParsedSql.Token> tokens = new ArrayList<>();
List<ParsedSql.TokenizedStatement> statements = new ArrayList<>();

int statementStartIndex = 0;
int i = 0;
while (i < sql.length()) {
char c = sql.charAt(i);
TokenizedSql.Token token = null;
ParsedSql.Token token = null;

if (isWhitespace(c)) {
i++;
Expand All @@ -73,25 +73,25 @@ public static TokenizedSql tokenize(String sql) {
token = getParameterOrDollarQuoteToken(sql, i);
break;
case ';':
token = new TokenizedSql.Token(TokenizedSql.TokenType.STATEMENT_END, ";");
token = new ParsedSql.Token(ParsedSql.TokenType.STATEMENT_END, ";");
break;
default:
break;
}
if (token == null) {
if (isSpecialOrOperatorChar(c)) {
token = new TokenizedSql.Token(TokenizedSql.TokenType.SPECIAL_OR_OPERATOR, Character.toString(c));//getSpecialOrOperatorToken(sql, i);
token = new ParsedSql.Token(ParsedSql.TokenType.SPECIAL_OR_OPERATOR, Character.toString(c));//getSpecialOrOperatorToken(sql, i);
} else {
token = getDefaultToken(sql, i);
}
}

i += token.getValue().length();

if (token.getType() == TokenizedSql.TokenType.STATEMENT_END) {
if (token.getType() == ParsedSql.TokenType.STATEMENT_END) {

tokens.add(token);
statements.add(new TokenizedSql.TokenizedStatement(sql.substring(statementStartIndex, i), tokens));
statements.add(new ParsedSql.TokenizedStatement(sql.substring(statementStartIndex, i), tokens));

tokens = new ArrayList<>();
statementStartIndex = i + 1;
Expand All @@ -101,27 +101,27 @@ public static TokenizedSql tokenize(String sql) {
}
// If tokens is not empty, implicit statement end
if (!tokens.isEmpty()) {
statements.add(new TokenizedSql.TokenizedStatement(sql.substring(statementStartIndex), tokens));
statements.add(new ParsedSql.TokenizedStatement(sql.substring(statementStartIndex), tokens));
}

return new TokenizedSql(sql, statements);
return new ParsedSql(sql, statements);
}

private static TokenizedSql.Token getDefaultToken(String sql, int beginIndex) {
private static ParsedSql.Token getDefaultToken(String sql, int beginIndex) {
for (int i = beginIndex + 1; i < sql.length(); i++) {
char c = sql.charAt(i);
if (Character.isWhitespace(c) || isSpecialOrOperatorChar(c)) {
return new TokenizedSql.Token(TokenizedSql.TokenType.DEFAULT, sql.substring(beginIndex, i));
return new ParsedSql.Token(ParsedSql.TokenType.DEFAULT, sql.substring(beginIndex, i));
}
}
return new TokenizedSql.Token(TokenizedSql.TokenType.DEFAULT, sql.substring(beginIndex));
return new ParsedSql.Token(ParsedSql.TokenType.DEFAULT, sql.substring(beginIndex));
}

private static boolean isSpecialOrOperatorChar(char c) {
return Arrays.binarySearch(SPECIAL_AND_OPERATOR_CHARS, c) >= 0;
}

private static TokenizedSql.Token getBlockCommentToken(String sql, int beginIndex) {
private static ParsedSql.Token getBlockCommentToken(String sql, int beginIndex) {
int depth = 1;
for (int i = beginIndex + 2; i < (sql.length() - 1); i++) {
char c1 = sql.charAt(i);
Expand All @@ -134,44 +134,44 @@ private static TokenizedSql.Token getBlockCommentToken(String sql, int beginInde
i++;
}
if (depth == 0) {
return new TokenizedSql.Token(TokenizedSql.TokenType.COMMENT, sql.substring(beginIndex, i + 1));
return new ParsedSql.Token(ParsedSql.TokenType.COMMENT, sql.substring(beginIndex, i + 1));
}
}
throw new IllegalArgumentException("Sql cannot be parsed: unclosed block comment (comment opened at index " + beginIndex + ") in statement: " + sql);
}

private static TokenizedSql.Token getCommentToLineEndToken(String sql, int beginIndex) {
private static ParsedSql.Token getCommentToLineEndToken(String sql, int beginIndex) {
int lineEnding = sql.indexOf('\n', beginIndex);
if (lineEnding == -1) {
return new TokenizedSql.Token(TokenizedSql.TokenType.COMMENT, sql.substring(beginIndex));
return new ParsedSql.Token(ParsedSql.TokenType.COMMENT, sql.substring(beginIndex));
} else {
return new TokenizedSql.Token(TokenizedSql.TokenType.COMMENT, sql.substring(beginIndex, lineEnding));
return new ParsedSql.Token(ParsedSql.TokenType.COMMENT, sql.substring(beginIndex, lineEnding));
}
}

private static TokenizedSql.Token getDollarQuoteToken(String sql, String tag, int beginIndex) {
private static ParsedSql.Token getDollarQuoteToken(String sql, String tag, int beginIndex) {
int nextQuote = sql.indexOf(tag, beginIndex + tag.length());
if (nextQuote == -1) {
throw new IllegalArgumentException("Sql cannot be parsed: unclosed quote (quote opened at index " + beginIndex + ") in statement: " + sql);
} else {
return new TokenizedSql.Token(TokenizedSql.TokenType.STRING_CONSTANT, sql.substring(beginIndex, nextQuote + tag.length()));
return new ParsedSql.Token(ParsedSql.TokenType.STRING_CONSTANT, sql.substring(beginIndex, nextQuote + tag.length()));
}
}

private static TokenizedSql.Token getParameterToken(String sql, int beginIndex) {
private static ParsedSql.Token getParameterToken(String sql, int beginIndex) {
for (int i = beginIndex + 1; i < sql.length(); i++) {
char c = sql.charAt(i);
if (isWhitespace(c) || isSpecialOrOperatorChar(c)) {
return new TokenizedSql.Token(TokenizedSql.TokenType.PARAMETER, sql.substring(beginIndex, i));
return new ParsedSql.Token(ParsedSql.TokenType.PARAMETER, sql.substring(beginIndex, i));
}
if (!isAsciiDigit(c)) {
throw new IllegalArgumentException("Sql cannot be parsed: illegal character in parameter or dollar-quote tag: " + c);
}
}
return new TokenizedSql.Token(TokenizedSql.TokenType.PARAMETER, sql.substring(beginIndex));
return new ParsedSql.Token(ParsedSql.TokenType.PARAMETER, sql.substring(beginIndex));
}

private static TokenizedSql.Token getParameterOrDollarQuoteToken(String sql, int beginIndex) {
private static ParsedSql.Token getParameterOrDollarQuoteToken(String sql, int beginIndex) {
char firstChar = sql.charAt(beginIndex + 1);
if (firstChar == '$') {
return getDollarQuoteToken(sql, "$$", beginIndex);
Expand All @@ -191,21 +191,21 @@ private static TokenizedSql.Token getParameterOrDollarQuoteToken(String sql, int
}
}

private static TokenizedSql.Token getStandardQuoteToken(String sql, int beginIndex) {
private static ParsedSql.Token getStandardQuoteToken(String sql, int beginIndex) {
int nextQuote = sql.indexOf('\'', beginIndex + 1);
if (nextQuote == -1) {
throw new IllegalArgumentException("Sql cannot be parsed: unclosed quote (quote opened at index " + beginIndex + ") in statement: " + sql);
} else {
return new TokenizedSql.Token(TokenizedSql.TokenType.STRING_CONSTANT, sql.substring(beginIndex, nextQuote + 1));
return new ParsedSql.Token(ParsedSql.TokenType.STRING_CONSTANT, sql.substring(beginIndex, nextQuote + 1));
}
}

private static TokenizedSql.Token getQuotedIdentifierToken(String sql, int beginIndex) {
private static ParsedSql.Token getQuotedIdentifierToken(String sql, int beginIndex) {
int nextQuote = sql.indexOf('\"', beginIndex + 1);
if (nextQuote == -1) {
throw new IllegalArgumentException("Sql cannot be parsed: unclosed quoted identifier (identifier opened at index " + beginIndex + ") in statement: " + sql);
} else {
return new TokenizedSql.Token(TokenizedSql.TokenType.QUOTED_IDENTIFIER, sql.substring(beginIndex, nextQuote + 1));
return new ParsedSql.Token(ParsedSql.TokenType.QUOTED_IDENTIFIER, sql.substring(beginIndex, nextQuote + 1));
}
}

Expand Down
28 changes: 14 additions & 14 deletions src/main/java/io/r2dbc/postgresql/PostgresqlStatement.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,19 +65,19 @@ final class PostgresqlStatement implements io.r2dbc.postgresql.api.PostgresqlSta

private final ConnectionContext connectionContext;

private final TokenizedSql tokenizedSql;
private final ParsedSql parsedSql;

private int fetchSize;

private String[] generatedColumns;

PostgresqlStatement(ConnectionResources resources, String sql) {
this.resources = Assert.requireNonNull(resources, "resources must not be null");
this.tokenizedSql = PostgresqlSqlLexer.tokenize(Assert.requireNonNull(sql, "sql must not be null"));
this.parsedSql = PostgresqlSqlParser.tokenize(Assert.requireNonNull(sql, "sql must not be null"));
this.connectionContext = resources.getClient().getContext();
this.bindings = new ArrayDeque<>(this.tokenizedSql.getParameterCount());
this.bindings = new ArrayDeque<>(this.parsedSql.getParameterCount());

if (this.tokenizedSql.getStatementCount() > 1 && this.tokenizedSql.getParameterCount() > 0) {
if (this.parsedSql.getStatementCount() > 1 && this.parsedSql.getParameterCount() > 0) {
throw new IllegalArgumentException(String.format("Statement '%s' cannot be created. This is often due to the presence of both multiple statements and parameters at the same time.", sql));
}

Expand All @@ -90,7 +90,7 @@ public PostgresqlStatement add() {
if (binding != null) {
binding.validate();
}
this.bindings.add(new Binding(this.tokenizedSql.getParameterCount()));
this.bindings.add(new Binding(this.parsedSql.getParameterCount()));
return this;
}

Expand All @@ -117,8 +117,8 @@ public PostgresqlStatement bindNull(String identifier, Class<?> type) {
public PostgresqlStatement bindNull(int index, Class<?> type) {
Assert.requireNonNull(type, "type must not be null");

if (index >= this.tokenizedSql.getParameterCount()) {
throw new UnsupportedOperationException(String.format("Cannot bind parameter %d, statement has %d parameters", index, this.tokenizedSql.getParameterCount()));
if (index >= this.parsedSql.getParameterCount()) {
throw new UnsupportedOperationException(String.format("Cannot bind parameter %d, statement has %d parameters", index, this.parsedSql.getParameterCount()));
}

BindingLogger.logBindNull(this.connectionContext, index, type);
Expand All @@ -130,7 +130,7 @@ public PostgresqlStatement bindNull(int index, Class<?> type) {
private Binding getCurrentOrFirstBinding() {
Binding binding = this.bindings.peekLast();
if (binding == null) {
Binding newBinding = new Binding(this.tokenizedSql.getParameterCount());
Binding newBinding = new Binding(this.parsedSql.getParameterCount());
this.bindings.add(newBinding);
return newBinding;
} else {
Expand All @@ -141,20 +141,20 @@ private Binding getCurrentOrFirstBinding() {
@Override
public Flux<io.r2dbc.postgresql.api.PostgresqlResult> execute() {
if (this.generatedColumns == null) {
return execute(this.tokenizedSql.getSql());
return execute(this.parsedSql.getSql());
}
return execute(GeneratedValuesUtils.augment(this.tokenizedSql.getSql(), this.generatedColumns));
return execute(GeneratedValuesUtils.augment(this.parsedSql.getSql(), this.generatedColumns));
}

@Override
public PostgresqlStatement returnGeneratedValues(String... columns) {
Assert.requireNonNull(columns, "columns must not be null");

if (this.tokenizedSql.hasDefaultTokenValue("RETURNING")) {
if (this.parsedSql.hasDefaultTokenValue("RETURNING")) {
throw new IllegalStateException("Statement already includes RETURNING clause");
}

if (!this.tokenizedSql.hasDefaultTokenValue("DELETE", "INSERT", "UPDATE")) {
if (!this.parsedSql.hasDefaultTokenValue("DELETE", "INSERT", "UPDATE")) {
throw new IllegalStateException("Statement is not a DELETE, INSERT, or UPDATE command");
}

Expand All @@ -174,7 +174,7 @@ public String toString() {
return "PostgresqlStatement{" +
"bindings=" + this.bindings +
", context=" + this.resources +
", sql='" + this.tokenizedSql.getSql() + '\'' +
", sql='" + this.parsedSql.getSql() + '\'' +
", generatedColumns=" + Arrays.toString(this.generatedColumns) +
'}';
}
Expand All @@ -199,7 +199,7 @@ private int getIdentifierIndex(String identifier) {
private Flux<io.r2dbc.postgresql.api.PostgresqlResult> execute(String sql) {
ExceptionFactory factory = ExceptionFactory.withSql(sql);

if (this.tokenizedSql.getParameterCount() != 0) {
if (this.parsedSql.getParameterCount() != 0) {
// Extended query protocol
if (this.bindings.size() == 0) {
throw new IllegalStateException("No parameters have been bound");
Expand Down
Loading

0 comments on commit c74bd6e

Please sign in to comment.