All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.elasticsearch.xpack.sql.jdbc.SqlQueryParameterAnalyzer Maven / Gradle / Ivy

/*
 * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
 * or more contributor license agreements. Licensed under the Elastic License
 * 2.0; you may not use this file except in compliance with the Elastic License
 * 2.0.
 */
package org.elasticsearch.xpack.sql.jdbc;

import java.sql.SQLException;

/**
 * Simplistic parser that can find parameters and escape sequences in a query and counts the number of parameters
 * 

* It is used by JDBC client to approximate the number of parameters that JDBC client should accept. The parser is simplistic * in a sense that it can accept ? in the places where it's not allowed by the server (for example as a index name), but that's * a reasonable compromise to avoid sending the prepared statement server to the server for extra validation. */ final class SqlQueryParameterAnalyzer { private SqlQueryParameterAnalyzer() { } /** * Returns number of parameters in the specified SQL query */ public static int parametersCount(String sql) throws SQLException { int l = sql.length(); int params = 0; for (int i = 0; i < l; i++) { char c = sql.charAt(i); switch (c) { case '{': i = skipJdbcEscape(i, sql); break; case '\'': i = skipString(i, sql, c); break; case '"': i = skipString(i, sql, c); break; case '?': params++; break; case '-': if (i + 1 < l && sql.charAt(i + 1) == '-') { i = skipLineComment(i, sql); } break; case '/': if (i + 1 < l && sql.charAt(i + 1) == '*') { i = skipMultiLineComment(i, sql); } break; } } return params; } /** * Skips jdbc escape sequence starting at the current position i, returns the length of the sequence */ private static int skipJdbcEscape(int i, String sql) throws SQLException { // TODO: JDBC escape syntax // https://db.apache.org/derby/docs/10.5/ref/rrefjdbc1020262.html throw new SQLException("Jdbc escape sequences are not supported yet"); } /** * Skips a line comment starting at the current position i, returns the length of the comment */ private static int skipLineComment(int i, String sql) { for (; i < sql.length(); i++) { char c = sql.charAt(i); if (c == '\n' || c == '\r') { return i; } } return i; } /** * Skips a multi-line comment starting at the current position i, returns the length of the comment */ private static int skipMultiLineComment(int i, String sql) throws SQLException { int block = 0; for (; i < sql.length() - 1; i++) { char c = sql.charAt(i); if (c == '/' && sql.charAt(i + 1) == '*') { i++; block++; } else if (c == '*' && sql.charAt(i + 1) == '/') { i++; block--; } if (block == 0) { return i; } } throw new SQLException("Cannot parse given sql; unclosed /* comment"); } /** * Skips a string starting at the current position i, returns the length of the string */ private static int skipString(int i, String sql, char q) throws SQLException { for (i = i + 1; i < sql.length(); i++) { char c = sql.charAt(i); if (c == q) { // double quotes mean escaping if (i + 1 < sql.length() && sql.charAt(i + 1) == q) { i++; } else { return i; } } } throw new SQLException("Cannot parse given sql; unclosed string"); } }





© 2015 - 2026 Weber Informatics LLC | Privacy Policy