SQL: Lock down JDBC driver (#35798)

Move classes under the same package to avoid internal classes being
 exposed to the outside. Remove public visibility outside 3 classes:
 EsDriver, EsDataSource and EsTypes.
The driver only has one package, namely org.elasticsearch.xpack.sql.jdbc
Use Es prefix for classes to ease name conflict and indicate their
 destination

Fix #35437
This commit is contained in:
Costin Leau 2018-11-28 12:48:26 +02:00 committed by GitHub
parent 2f547bac65
commit 95346926ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
51 changed files with 376 additions and 414 deletions

View File

@ -43,9 +43,9 @@ from `artifacts.elastic.co/maven` by adding it to the repositories list:
[float] [float]
=== Setup === Setup
The driver main class is `org.elasticsearch.xpack.sql.jdbc.jdbc.JdbcDriver`. The driver main class is `org.elasticsearch.xpack.sql.jdbc.EsDriver`.
Note the driver implements the JDBC 4.0 +Service Provider+ mechanism meaning it is registered automatically Note the driver implements the JDBC 4.0 +Service Provider+ mechanism meaning it is registered automatically
as long as its available in the classpath. as long as it is available in the classpath.
Once registered, the driver understands the following syntax as an URL: Once registered, the driver understands the following syntax as an URL:

View File

@ -3,7 +3,7 @@
* or more contributor license agreements. Licensed under the Elastic License; * or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
package org.elasticsearch.xpack.sql.jdbc.debug; package org.elasticsearch.xpack.sql.jdbc;
import java.sql.DatabaseMetaData; import java.sql.DatabaseMetaData;
import java.sql.Statement; import java.sql.Statement;

View File

@ -3,14 +3,12 @@
* or more contributor license agreements. Licensed under the Elastic License; * or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
package org.elasticsearch.xpack.sql.jdbc.net.client; package org.elasticsearch.xpack.sql.jdbc;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.List; import java.util.List;
import org.elasticsearch.xpack.sql.jdbc.net.protocol.JdbcColumnInfo; interface Cursor {
public interface Cursor {
List<JdbcColumnInfo> columns(); List<JdbcColumnInfo> columns();

View File

@ -3,7 +3,7 @@
* or more contributor license agreements. Licensed under the Elastic License; * or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
package org.elasticsearch.xpack.sql.jdbc.debug; package org.elasticsearch.xpack.sql.jdbc;
import java.sql.ResultSet; import java.sql.ResultSet;

View File

@ -3,11 +3,9 @@
* or more contributor license agreements. Licensed under the Elastic License; * or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
package org.elasticsearch.xpack.sql.jdbc.debug; package org.elasticsearch.xpack.sql.jdbc;
import org.elasticsearch.xpack.sql.client.SuppressForbidden; import org.elasticsearch.xpack.sql.client.SuppressForbidden;
import org.elasticsearch.xpack.sql.jdbc.JdbcException;
import org.elasticsearch.xpack.sql.jdbc.jdbc.JdbcConfiguration;
import java.io.OutputStreamWriter; import java.io.OutputStreamWriter;
import java.io.PrintStream; import java.io.PrintStream;
@ -46,7 +44,7 @@ import javax.sql.DataSource;
* For this reason the {@link System#out} and {@link System#err} are being referred in this class though are used only * For this reason the {@link System#out} and {@link System#err} are being referred in this class though are used only
* when needed. * when needed.
*/ */
public final class Debug { final class Debug {
// cache for streams created by ourselves // cache for streams created by ourselves
private static final Map<String, DebugLog> OUTPUT_CACHE = new HashMap<>(); private static final Map<String, DebugLog> OUTPUT_CACHE = new HashMap<>();
@ -70,7 +68,7 @@ public final class Debug {
* own configuration first; if that does not exist it will fallback to the managed approaches (assuming they * own configuration first; if that does not exist it will fallback to the managed approaches (assuming they
* are specified, otherwise logging is simply disabled). * are specified, otherwise logging is simply disabled).
*/ */
public static Connection proxy(JdbcConfiguration info, Connection connection, PrintWriter managedPrinter) { static Connection proxy(JdbcConfiguration info, Connection connection, PrintWriter managedPrinter) {
return createProxy(Connection.class, new ConnectionProxy(logger(info, managedPrinter), connection)); return createProxy(Connection.class, new ConnectionProxy(logger(info, managedPrinter), connection));
} }
@ -180,7 +178,7 @@ public final class Debug {
return log; return log;
} }
public static void release(JdbcConfiguration info) { static void release(JdbcConfiguration info) {
if (!info.debug()) { if (!info.debug()) {
return; return;
} }
@ -206,7 +204,7 @@ public final class Debug {
} }
} }
public static synchronized void close() { static synchronized void close() {
// clear the ref // clear the ref
OUTPUT_REFS.clear(); OUTPUT_REFS.clear();
@ -235,4 +233,4 @@ public final class Debug {
private static PrintStream stderr() { private static PrintStream stderr() {
return System.err; return System.err;
} }
} }

View File

@ -3,7 +3,7 @@
* or more contributor license agreements. Licensed under the Elastic License; * or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
package org.elasticsearch.xpack.sql.jdbc.debug; package org.elasticsearch.xpack.sql.jdbc;
import org.elasticsearch.xpack.sql.client.StringUtils; import org.elasticsearch.xpack.sql.client.StringUtils;

View File

@ -3,7 +3,7 @@
* or more contributor license agreements. Licensed under the Elastic License; * or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
package org.elasticsearch.xpack.sql.jdbc.debug; package org.elasticsearch.xpack.sql.jdbc;
/** /**
* Debug marker interface for compatible proxy. * Debug marker interface for compatible proxy.

View File

@ -3,9 +3,7 @@
* or more contributor license agreements. Licensed under the Elastic License; * or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
package org.elasticsearch.xpack.sql.jdbc.debug; package org.elasticsearch.xpack.sql.jdbc;
import org.elasticsearch.xpack.sql.jdbc.JdbcSQLException;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;

View File

@ -3,10 +3,9 @@
* or more contributor license agreements. Licensed under the Elastic License; * or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
package org.elasticsearch.xpack.sql.jdbc.net.client; package org.elasticsearch.xpack.sql.jdbc;
import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.collect.Tuple;
import org.elasticsearch.xpack.sql.jdbc.net.protocol.JdbcColumnInfo;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.List; import java.util.List;

View File

@ -3,12 +3,9 @@
* or more contributor license agreements. Licensed under the Elastic License; * or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
package org.elasticsearch.xpack.sql.jdbc.jdbcx; package org.elasticsearch.xpack.sql.jdbc;
import org.elasticsearch.xpack.sql.client.ConnectionConfiguration; import org.elasticsearch.xpack.sql.client.ConnectionConfiguration;
import org.elasticsearch.xpack.sql.jdbc.debug.Debug;
import org.elasticsearch.xpack.sql.jdbc.jdbc.JdbcConfiguration;
import org.elasticsearch.xpack.sql.jdbc.jdbc.JdbcConnection;
import org.elasticsearch.xpack.sql.client.Version; import org.elasticsearch.xpack.sql.client.Version;
import java.io.PrintWriter; import java.io.PrintWriter;
@ -21,10 +18,13 @@ import java.util.logging.Logger;
import javax.sql.DataSource; import javax.sql.DataSource;
/**
public class JdbcDataSource implements DataSource, Wrapper { * Factory for connections to Elasticsearch SQL.
*/
public class EsDataSource implements DataSource, Wrapper {
static { static {
// invoke Version to perform classpath/jar sanity checks
Version.CURRENT.toString(); Version.CURRENT.toString();
} }
@ -33,7 +33,7 @@ public class JdbcDataSource implements DataSource, Wrapper {
private int loginTimeout; private int loginTimeout;
private Properties props; private Properties props;
public JdbcDataSource() {} public EsDataSource() {}
@Override @Override
public PrintWriter getLogWriter() throws SQLException { public PrintWriter getLogWriter() throws SQLException {

View File

@ -3,14 +3,13 @@
* or more contributor license agreements. Licensed under the Elastic License; * or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
package org.elasticsearch.xpack.sql.jdbc.jdbc; package org.elasticsearch.xpack.sql.jdbc;
import org.elasticsearch.xpack.sql.client.Version; import org.elasticsearch.xpack.sql.client.Version;
import org.elasticsearch.xpack.sql.jdbc.JdbcSQLException;
import org.elasticsearch.xpack.sql.jdbc.debug.Debug;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.sql.Connection; import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager; import java.sql.DriverManager;
import java.sql.DriverPropertyInfo; import java.sql.DriverPropertyInfo;
import java.sql.SQLException; import java.sql.SQLException;
@ -18,9 +17,9 @@ import java.sql.SQLFeatureNotSupportedException;
import java.util.Properties; import java.util.Properties;
import java.util.logging.Logger; import java.util.logging.Logger;
public class JdbcDriver implements java.sql.Driver { public class EsDriver implements Driver {
private static final JdbcDriver INSTANCE = new JdbcDriver(); private static final EsDriver INSTANCE = new EsDriver();
static { static {
// invoke Version to perform classpath/jar sanity checks // invoke Version to perform classpath/jar sanity checks
@ -40,7 +39,7 @@ public class JdbcDriver implements java.sql.Driver {
} }
} }
public static JdbcDriver register() throws SQLException { public static EsDriver register() throws SQLException {
// no closing callback // no closing callback
DriverManager.registerDriver(INSTANCE, INSTANCE::close); DriverManager.registerDriver(INSTANCE, INSTANCE::close);
return INSTANCE; return INSTANCE;

View File

@ -4,13 +4,13 @@
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
package org.elasticsearch.xpack.sql.jdbc.type; package org.elasticsearch.xpack.sql.jdbc;
import java.sql.SQLType; import java.sql.SQLType;
import java.sql.Types; import java.sql.Types;
public enum DataType implements SQLType { public enum EsType implements SQLType {
NULL( Types.NULL), NULL( Types.NULL),
UNSUPPORTED( Types.OTHER), UNSUPPORTED( Types.OTHER),
@ -46,7 +46,7 @@ public enum DataType implements SQLType {
private final Integer type; private final Integer type;
DataType(int type) { EsType(int type) {
this.type = Integer.valueOf(type); this.type = Integer.valueOf(type);
} }

View File

@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
package org.elasticsearch.xpack.sql.jdbc.type; package org.elasticsearch.xpack.sql.jdbc;
import java.sql.JDBCType; import java.sql.JDBCType;
import java.sql.Types; import java.sql.Types;

View File

@ -3,17 +3,17 @@
* or more contributor license agreements. Licensed under the Elastic License; * or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
package org.elasticsearch.xpack.sql.jdbc.net.protocol; package org.elasticsearch.xpack.sql.jdbc;
/** /**
* General information about the server. * General information about the server.
*/ */
public class InfoResponse { class InfoResponse {
public final String cluster; final String cluster;
public final int majorVersion; final int majorVersion;
public final int minorVersion; final int minorVersion;
public InfoResponse(String clusterName, byte versionMajor, byte versionMinor) { InfoResponse(String clusterName, byte versionMajor, byte versionMinor) {
this.cluster = clusterName; this.cluster = clusterName;
this.majorVersion = versionMajor; this.majorVersion = versionMajor;
this.minorVersion = versionMinor; this.minorVersion = versionMinor;

View File

@ -3,22 +3,20 @@
* or more contributor license agreements. Licensed under the Elastic License; * or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
package org.elasticsearch.xpack.sql.jdbc.net.protocol; package org.elasticsearch.xpack.sql.jdbc;
import org.elasticsearch.xpack.sql.jdbc.type.DataType;
import java.util.Objects; import java.util.Objects;
public class JdbcColumnInfo { class JdbcColumnInfo {
public final String catalog; public final String catalog;
public final String schema; public final String schema;
public final String table; public final String table;
public final String label; public final String label;
public final String name; public final String name;
public final int displaySize; public final int displaySize;
public final DataType type; public final EsType type;
public JdbcColumnInfo(String name, DataType type, String table, String catalog, String schema, String label, int displaySize) { JdbcColumnInfo(String name, EsType type, String table, String catalog, String schema, String label, int displaySize) {
if (name == null) { if (name == null) {
throw new IllegalArgumentException("[name] must not be null"); throw new IllegalArgumentException("[name] must not be null");
} }
@ -46,7 +44,7 @@ public class JdbcColumnInfo {
this.displaySize = displaySize; this.displaySize = displaySize;
} }
public int displaySize() { int displaySize() {
// 0 - means unknown // 0 - means unknown
return displaySize; return displaySize;
} }

View File

@ -3,12 +3,11 @@
* or more contributor license agreements. Licensed under the Elastic License; * or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
package org.elasticsearch.xpack.sql.jdbc.jdbc; package org.elasticsearch.xpack.sql.jdbc;
import org.elasticsearch.xpack.sql.client.ConnectionConfiguration; import org.elasticsearch.xpack.sql.client.ConnectionConfiguration;
import org.elasticsearch.xpack.sql.client.StringUtils; import org.elasticsearch.xpack.sql.client.StringUtils;
import org.elasticsearch.xpack.sql.client.Version; import org.elasticsearch.xpack.sql.client.Version;
import org.elasticsearch.xpack.sql.jdbc.JdbcSQLException;
import java.net.URI; import java.net.URI;
import java.sql.DriverPropertyInfo; import java.sql.DriverPropertyInfo;
@ -35,7 +34,7 @@ import static org.elasticsearch.xpack.sql.client.UriUtils.removeQuery;
/ Additional properties can be specified either through the Properties object or in the URL. In case of duplicates, the URL wins. / Additional properties can be specified either through the Properties object or in the URL. In case of duplicates, the URL wins.
*/ */
//TODO: beef this up for Security/SSL //TODO: beef this up for Security/SSL
public class JdbcConfiguration extends ConnectionConfiguration { class JdbcConfiguration extends ConnectionConfiguration {
static final String URL_PREFIX = "jdbc:es://"; static final String URL_PREFIX = "jdbc:es://";
public static URI DEFAULT_URI = URI.create("http://localhost:9200/"); public static URI DEFAULT_URI = URI.create("http://localhost:9200/");

View File

@ -3,10 +3,7 @@
* or more contributor license agreements. Licensed under the Elastic License; * or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
package org.elasticsearch.xpack.sql.jdbc.jdbc; package org.elasticsearch.xpack.sql.jdbc;
import org.elasticsearch.xpack.sql.jdbc.debug.Debug;
import org.elasticsearch.xpack.sql.jdbc.net.client.JdbcHttpClient;
import java.sql.Array; import java.sql.Array;
import java.sql.Blob; import java.sql.Blob;
@ -33,7 +30,7 @@ import java.util.concurrent.TimeUnit;
/** /**
* Implementation of {@link Connection} for Elasticsearch. * Implementation of {@link Connection} for Elasticsearch.
*/ */
public class JdbcConnection implements Connection, JdbcWrapper { class JdbcConnection implements Connection, JdbcWrapper {
private final String url, userName; private final String url, userName;
final JdbcConfiguration cfg; final JdbcConfiguration cfg;
@ -47,7 +44,7 @@ public class JdbcConnection implements Connection, JdbcWrapper {
* The SQLException is the only type of Exception the JDBC API can throw (and that the user expects). * The SQLException is the only type of Exception the JDBC API can throw (and that the user expects).
* If we remove it, we need to make sure no other types of Exceptions (runtime or otherwise) are thrown * If we remove it, we need to make sure no other types of Exceptions (runtime or otherwise) are thrown
*/ */
public JdbcConnection(JdbcConfiguration connectionInfo) throws SQLException { JdbcConnection(JdbcConfiguration connectionInfo) throws SQLException {
cfg = connectionInfo; cfg = connectionInfo;
client = new JdbcHttpClient(connectionInfo); client = new JdbcHttpClient(connectionInfo);

View File

@ -3,14 +3,10 @@
* or more contributor license agreements. Licensed under the Elastic License; * or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
package org.elasticsearch.xpack.sql.jdbc.jdbc; package org.elasticsearch.xpack.sql.jdbc;
import org.elasticsearch.xpack.sql.client.ObjectUtils; import org.elasticsearch.xpack.sql.client.ObjectUtils;
import org.elasticsearch.xpack.sql.client.Version; import org.elasticsearch.xpack.sql.client.Version;
import org.elasticsearch.xpack.sql.jdbc.JdbcSQLException;
import org.elasticsearch.xpack.sql.jdbc.net.client.Cursor;
import org.elasticsearch.xpack.sql.jdbc.net.protocol.JdbcColumnInfo;
import org.elasticsearch.xpack.sql.jdbc.type.DataType;
import java.sql.Connection; import java.sql.Connection;
import java.sql.DatabaseMetaData; import java.sql.DatabaseMetaData;
@ -1125,11 +1121,11 @@ class JdbcDatabaseMetaData implements DatabaseMetaData, JdbcWrapper {
Object obj = cols[i]; Object obj = cols[i];
if (obj instanceof String) { if (obj instanceof String) {
String name = obj.toString(); String name = obj.toString();
DataType type = DataType.KEYWORD; EsType type = EsType.KEYWORD;
if (i + 1 < cols.length) { if (i + 1 < cols.length) {
Object next = cols[i + 1]; Object next = cols[i + 1];
// check if the next item it's a type // check if the next item it's a type
if (next instanceof DataType || next instanceof JDBCType) { if (next instanceof EsType || next instanceof JDBCType) {
try { try {
type = TypeUtils.of((JDBCType) next); type = TypeUtils.of((JDBCType) next);
i++; i++;

View File

@ -5,13 +5,13 @@
*/ */
package org.elasticsearch.xpack.sql.jdbc; package org.elasticsearch.xpack.sql.jdbc;
public class JdbcException extends RuntimeException { class JdbcException extends RuntimeException {
public JdbcException(String message) { JdbcException(String message) {
super(message); super(message);
} }
public JdbcException(Throwable cause, String message) { JdbcException(Throwable cause, String message) {
super(message, cause); super(message, cause);
} }
} }

View File

@ -3,16 +3,12 @@
* or more contributor license agreements. Licensed under the Elastic License; * or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
package org.elasticsearch.xpack.sql.jdbc.net.client; package org.elasticsearch.xpack.sql.jdbc;
import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.collect.Tuple;
import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.xpack.sql.client.HttpClient; import org.elasticsearch.xpack.sql.client.HttpClient;
import org.elasticsearch.xpack.sql.client.Version; import org.elasticsearch.xpack.sql.client.Version;
import org.elasticsearch.xpack.sql.jdbc.jdbc.JdbcConfiguration;
import org.elasticsearch.xpack.sql.jdbc.jdbc.TypeUtils;
import org.elasticsearch.xpack.sql.jdbc.net.protocol.InfoResponse;
import org.elasticsearch.xpack.sql.jdbc.net.protocol.JdbcColumnInfo;
import org.elasticsearch.xpack.sql.proto.ColumnInfo; import org.elasticsearch.xpack.sql.proto.ColumnInfo;
import org.elasticsearch.xpack.sql.proto.MainResponse; import org.elasticsearch.xpack.sql.proto.MainResponse;
import org.elasticsearch.xpack.sql.proto.Mode; import org.elasticsearch.xpack.sql.proto.Mode;
@ -32,7 +28,7 @@ import static org.elasticsearch.xpack.sql.client.StringUtils.EMPTY;
* JDBC specific HTTP client. * JDBC specific HTTP client.
* Since JDBC is not thread-safe, neither is this class. * Since JDBC is not thread-safe, neither is this class.
*/ */
public class JdbcHttpClient { class JdbcHttpClient {
private final HttpClient httpClient; private final HttpClient httpClient;
private final JdbcConfiguration conCfg; private final JdbcConfiguration conCfg;
private InfoResponse serverInfo; private InfoResponse serverInfo;
@ -41,16 +37,16 @@ public class JdbcHttpClient {
* The SQLException is the only type of Exception the JDBC API can throw (and that the user expects). * The SQLException is the only type of Exception the JDBC API can throw (and that the user expects).
* If we remove it, we need to make sure no other types of Exceptions (runtime or otherwise) are thrown * If we remove it, we need to make sure no other types of Exceptions (runtime or otherwise) are thrown
*/ */
public JdbcHttpClient(JdbcConfiguration conCfg) throws SQLException { JdbcHttpClient(JdbcConfiguration conCfg) throws SQLException {
httpClient = new HttpClient(conCfg); httpClient = new HttpClient(conCfg);
this.conCfg = conCfg; this.conCfg = conCfg;
} }
public boolean ping(long timeoutInMs) throws SQLException { boolean ping(long timeoutInMs) throws SQLException {
return httpClient.ping(timeoutInMs); return httpClient.ping(timeoutInMs);
} }
public Cursor query(String sql, List<SqlTypedParamValue> params, RequestMeta meta) throws SQLException { Cursor query(String sql, List<SqlTypedParamValue> params, RequestMeta meta) throws SQLException {
int fetch = meta.fetchSize() > 0 ? meta.fetchSize() : conCfg.pageSize(); int fetch = meta.fetchSize() > 0 ? meta.fetchSize() : conCfg.pageSize();
SqlQueryRequest sqlRequest = new SqlQueryRequest(sql, params, null, Protocol.TIME_ZONE, SqlQueryRequest sqlRequest = new SqlQueryRequest(sql, params, null, Protocol.TIME_ZONE,
fetch, fetch,
@ -64,18 +60,18 @@ public class JdbcHttpClient {
* Read the next page of results and returning * Read the next page of results and returning
* the scroll id to use to fetch the next page. * the scroll id to use to fetch the next page.
*/ */
public Tuple<String, List<List<Object>>> nextPage(String cursor, RequestMeta meta) throws SQLException { Tuple<String, List<List<Object>>> nextPage(String cursor, RequestMeta meta) throws SQLException {
SqlQueryRequest sqlRequest = new SqlQueryRequest(cursor, TimeValue.timeValueMillis(meta.timeoutInMs()), SqlQueryRequest sqlRequest = new SqlQueryRequest(cursor, TimeValue.timeValueMillis(meta.timeoutInMs()),
TimeValue.timeValueMillis(meta.queryTimeoutInMs()), new RequestInfo(Mode.JDBC)); TimeValue.timeValueMillis(meta.queryTimeoutInMs()), new RequestInfo(Mode.JDBC));
SqlQueryResponse response = httpClient.query(sqlRequest); SqlQueryResponse response = httpClient.query(sqlRequest);
return new Tuple<>(response.cursor(), response.rows()); return new Tuple<>(response.cursor(), response.rows());
} }
public boolean queryClose(String cursor) throws SQLException { boolean queryClose(String cursor) throws SQLException {
return httpClient.queryClose(cursor); return httpClient.queryClose(cursor);
} }
public InfoResponse serverInfo() throws SQLException { InfoResponse serverInfo() throws SQLException {
if (serverInfo == null) { if (serverInfo == null) {
serverInfo = fetchServerInfo(); serverInfo = fetchServerInfo();
} }

View File

@ -3,9 +3,9 @@
* or more contributor license agreements. Licensed under the Elastic License; * or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
package org.elasticsearch.xpack.sql.jdbc.jdbc; package org.elasticsearch.xpack.sql.jdbc;
import org.elasticsearch.xpack.sql.jdbc.jdbc.PreparedQuery.ParamInfo; import org.elasticsearch.xpack.sql.jdbc.PreparedQuery.ParamInfo;
import java.sql.ParameterMetaData; import java.sql.ParameterMetaData;
import java.sql.SQLException; import java.sql.SQLException;

View File

@ -3,9 +3,7 @@
* or more contributor license agreements. Licensed under the Elastic License; * or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
package org.elasticsearch.xpack.sql.jdbc.jdbc; package org.elasticsearch.xpack.sql.jdbc;
import org.elasticsearch.xpack.sql.jdbc.type.DataType;
import java.io.InputStream; import java.io.InputStream;
import java.io.Reader; import java.io.Reader;
@ -72,7 +70,7 @@ class JdbcPreparedStatement extends JdbcStatement implements PreparedStatement {
setParam(parameterIndex, value, TypeUtils.of(sqlType)); setParam(parameterIndex, value, TypeUtils.of(sqlType));
} }
private void setParam(int parameterIndex, Object value, DataType type) throws SQLException { private void setParam(int parameterIndex, Object value, EsType type) throws SQLException {
checkOpen(); checkOpen();
if (parameterIndex < 0 || parameterIndex > query.paramCount()) { if (parameterIndex < 0 || parameterIndex > query.paramCount()) {
@ -189,7 +187,7 @@ class JdbcPreparedStatement extends JdbcStatement implements PreparedStatement {
@Override @Override
public void setObject(int parameterIndex, Object x) throws SQLException { public void setObject(int parameterIndex, Object x) throws SQLException {
if (x == null) { if (x == null) {
setParam(parameterIndex, null, DataType.NULL); setParam(parameterIndex, null, EsType.NULL);
return; return;
} }
@ -343,7 +341,7 @@ class JdbcPreparedStatement extends JdbcStatement implements PreparedStatement {
setObject(parameterIndex, x, TypeUtils.of(targetSqlType), targetSqlType.getName()); setObject(parameterIndex, x, TypeUtils.of(targetSqlType), targetSqlType.getName());
} }
private void setObject(int parameterIndex, Object x, DataType dataType, String typeString) throws SQLException { private void setObject(int parameterIndex, Object x, EsType dataType, String typeString) throws SQLException {
checkOpen(); checkOpen();
// set the null value on the type and exit // set the null value on the type and exit
@ -354,11 +352,11 @@ class JdbcPreparedStatement extends JdbcStatement implements PreparedStatement {
checkKnownUnsupportedTypes(x); checkKnownUnsupportedTypes(x);
if (x instanceof byte[]) { if (x instanceof byte[]) {
if (dataType != DataType.BINARY) { if (dataType != EsType.BINARY) {
throw new SQLFeatureNotSupportedException( throw new SQLFeatureNotSupportedException(
"Conversion from type [byte[]] to [" + typeString + "] not supported"); "Conversion from type [byte[]] to [" + typeString + "] not supported");
} }
setParam(parameterIndex, x, DataType.BINARY); setParam(parameterIndex, x, EsType.BINARY);
return; return;
} }
@ -369,7 +367,7 @@ class JdbcPreparedStatement extends JdbcStatement implements PreparedStatement {
|| x instanceof Time || x instanceof Time
|| x instanceof java.util.Date) || x instanceof java.util.Date)
{ {
if (dataType == DataType.DATE) { if (dataType == EsType.DATE) {
// converting to {@code java.util.Date} because this is the type supported by {@code XContentBuilder} for serialization // converting to {@code java.util.Date} because this is the type supported by {@code XContentBuilder} for serialization
java.util.Date dateToSet; java.util.Date dateToSet;
if (x instanceof Timestamp) { if (x instanceof Timestamp) {

View File

@ -3,12 +3,7 @@
* or more contributor license agreements. Licensed under the Elastic License; * or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
package org.elasticsearch.xpack.sql.jdbc.jdbc; package org.elasticsearch.xpack.sql.jdbc;
import org.elasticsearch.xpack.sql.jdbc.net.client.Cursor;
import org.elasticsearch.xpack.sql.jdbc.net.protocol.JdbcColumnInfo;
import org.elasticsearch.xpack.sql.jdbc.net.protocol.Nullable;
import org.elasticsearch.xpack.sql.jdbc.type.DataType;
import java.io.InputStream; import java.io.InputStream;
import java.io.Reader; import java.io.Reader;
@ -245,12 +240,12 @@ class JdbcResultSet implements ResultSet, JdbcWrapper {
private Long dateTime(int columnIndex) throws SQLException { private Long dateTime(int columnIndex) throws SQLException {
Object val = column(columnIndex); Object val = column(columnIndex);
DataType type = cursor.columns().get(columnIndex - 1).type; EsType type = cursor.columns().get(columnIndex - 1).type;
try { try {
// TODO: the B6 appendix of the jdbc spec does mention CHAR, VARCHAR, LONGVARCHAR, DATE, TIMESTAMP as supported // TODO: the B6 appendix of the jdbc spec does mention CHAR, VARCHAR, LONGVARCHAR, DATE, TIMESTAMP as supported
// jdbc types that should be handled by getDate and getTime methods. From all of those we support VARCHAR and // jdbc types that should be handled by getDate and getTime methods. From all of those we support VARCHAR and
// TIMESTAMP. Should we consider the VARCHAR conversion as a later enhancement? // TIMESTAMP. Should we consider the VARCHAR conversion as a later enhancement?
if (DataType.DATE == type) { if (EsType.DATE == type) {
// the cursor can return an Integer if the date-since-epoch is small enough, XContentParser (Jackson) will // the cursor can return an Integer if the date-since-epoch is small enough, XContentParser (Jackson) will
// return the "smallest" data type for numbers when parsing // return the "smallest" data type for numbers when parsing
// TODO: this should probably be handled server side // TODO: this should probably be handled server side
@ -333,7 +328,7 @@ class JdbcResultSet implements ResultSet, JdbcWrapper {
return null; return null;
} }
DataType columnType = cursor.columns().get(columnIndex - 1).type; EsType columnType = cursor.columns().get(columnIndex - 1).type;
String typeString = type != null ? type.getSimpleName() : columnType.getName(); String typeString = type != null ? type.getSimpleName() : columnType.getName();
return TypeConverter.convert(val, columnType, type, typeString); return TypeConverter.convert(val, columnType, type, typeString);

View File

@ -3,9 +3,7 @@
* or more contributor license agreements. Licensed under the Elastic License; * or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
package org.elasticsearch.xpack.sql.jdbc.jdbc; package org.elasticsearch.xpack.sql.jdbc;
import org.elasticsearch.xpack.sql.jdbc.net.protocol.JdbcColumnInfo;
import java.sql.ResultSetMetaData; import java.sql.ResultSetMetaData;
import java.sql.SQLException; import java.sql.SQLException;

View File

@ -7,13 +7,13 @@ package org.elasticsearch.xpack.sql.jdbc;
import java.sql.SQLException; import java.sql.SQLException;
public class JdbcSQLException extends SQLException { class JdbcSQLException extends SQLException {
public JdbcSQLException(String message) { JdbcSQLException(String message) {
super(message); super(message);
} }
public JdbcSQLException(Throwable cause, String message) { JdbcSQLException(Throwable cause, String message) {
super(message, cause); super(message, cause);
} }
} }

View File

@ -3,10 +3,8 @@
* or more contributor license agreements. Licensed under the Elastic License; * or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
package org.elasticsearch.xpack.sql.jdbc.jdbc; package org.elasticsearch.xpack.sql.jdbc;
import org.elasticsearch.xpack.sql.jdbc.net.client.Cursor;
import org.elasticsearch.xpack.sql.jdbc.net.client.RequestMeta;
import org.elasticsearch.xpack.sql.proto.SqlTypedParamValue; import org.elasticsearch.xpack.sql.proto.SqlTypedParamValue;
import java.sql.Connection; import java.sql.Connection;

View File

@ -3,7 +3,7 @@
* or more contributor license agreements. Licensed under the Elastic License; * or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
package org.elasticsearch.xpack.sql.jdbc.jdbc; package org.elasticsearch.xpack.sql.jdbc;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Wrapper; import java.sql.Wrapper;

View File

@ -3,7 +3,7 @@
* or more contributor license agreements. Licensed under the Elastic License; * or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
package org.elasticsearch.xpack.sql.jdbc.net.protocol; package org.elasticsearch.xpack.sql.jdbc;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
@ -19,5 +19,5 @@ import java.lang.annotation.Target;
@Documented @Documented
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER, ElementType.FIELD, ElementType.METHOD}) @Target({ElementType.PARAMETER, ElementType.FIELD, ElementType.METHOD})
public @interface Nullable { @interface Nullable {
} }

View File

@ -3,7 +3,7 @@
* or more contributor license agreements. Licensed under the Elastic License; * or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
package org.elasticsearch.xpack.sql.jdbc.debug; package org.elasticsearch.xpack.sql.jdbc;
final class ParameterMetaDataProxy extends DebuggingInvoker { final class ParameterMetaDataProxy extends DebuggingInvoker {

View File

@ -3,10 +3,8 @@
* or more contributor license agreements. Licensed under the Elastic License; * or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
package org.elasticsearch.xpack.sql.jdbc.jdbc; package org.elasticsearch.xpack.sql.jdbc;
import org.elasticsearch.xpack.sql.jdbc.JdbcSQLException;
import org.elasticsearch.xpack.sql.jdbc.type.DataType;
import org.elasticsearch.xpack.sql.proto.SqlTypedParamValue; import org.elasticsearch.xpack.sql.proto.SqlTypedParamValue;
import java.sql.SQLException; import java.sql.SQLException;
@ -17,10 +15,10 @@ import java.util.stream.Collectors;
class PreparedQuery { class PreparedQuery {
static class ParamInfo { static class ParamInfo {
DataType type; EsType type;
Object value; Object value;
ParamInfo(Object value, DataType type) { ParamInfo(Object value, EsType type) {
this.value = value; this.value = value;
this.type = type; this.type = type;
} }
@ -42,7 +40,7 @@ class PreparedQuery {
return params[param - 1]; return params[param - 1];
} }
void setParam(int param, Object value, DataType type) throws JdbcSQLException { void setParam(int param, Object value, EsType type) throws JdbcSQLException {
if (param < 1 || param > params.length) { if (param < 1 || param > params.length) {
throw new JdbcSQLException("Invalid parameter index [" + param + "]"); throw new JdbcSQLException("Invalid parameter index [" + param + "]");
} }
@ -56,7 +54,7 @@ class PreparedQuery {
void clearParams() { void clearParams() {
for (int i = 0; i < params.length; i++) { for (int i = 0; i < params.length; i++) {
params[i] = new ParamInfo(null, DataType.KEYWORD); params[i] = new ParamInfo(null, EsType.KEYWORD);
} }
} }

View File

@ -3,44 +3,44 @@
* or more contributor license agreements. Licensed under the Elastic License; * or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
package org.elasticsearch.xpack.sql.jdbc.net.client; package org.elasticsearch.xpack.sql.jdbc;
public class RequestMeta { class RequestMeta {
private int fetchSize; private int fetchSize;
private long timeoutInMs; private long timeoutInMs;
private long queryTimeoutInMs; private long queryTimeoutInMs;
public RequestMeta(int fetchSize, long timeout, long queryTimeoutInMs) { RequestMeta(int fetchSize, long timeout, long queryTimeoutInMs) {
this.fetchSize = fetchSize; this.fetchSize = fetchSize;
this.timeoutInMs = timeout; this.timeoutInMs = timeout;
this.queryTimeoutInMs = queryTimeoutInMs; this.queryTimeoutInMs = queryTimeoutInMs;
} }
public RequestMeta queryTimeout(long timeout) { RequestMeta queryTimeout(long timeout) {
this.queryTimeoutInMs = timeout; this.queryTimeoutInMs = timeout;
return this; return this;
} }
public RequestMeta timeout(long timeout) { RequestMeta timeout(long timeout) {
this.timeoutInMs = timeout; this.timeoutInMs = timeout;
return this; return this;
} }
public RequestMeta fetchSize(int size) { RequestMeta fetchSize(int size) {
this.fetchSize = size; this.fetchSize = size;
return this; return this;
} }
public int fetchSize() { int fetchSize() {
return fetchSize; return fetchSize;
} }
public long timeoutInMs() { long timeoutInMs() {
return timeoutInMs; return timeoutInMs;
} }
public long queryTimeoutInMs() { long queryTimeoutInMs() {
return queryTimeoutInMs; return queryTimeoutInMs;
} }
} }

View File

@ -3,7 +3,7 @@
* or more contributor license agreements. Licensed under the Elastic License; * or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
package org.elasticsearch.xpack.sql.jdbc.debug; package org.elasticsearch.xpack.sql.jdbc;
final class ResultSetMetaDataProxy extends DebuggingInvoker { final class ResultSetMetaDataProxy extends DebuggingInvoker {

View File

@ -3,7 +3,7 @@
* or more contributor license agreements. Licensed under the Elastic License; * or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
package org.elasticsearch.xpack.sql.jdbc.debug; package org.elasticsearch.xpack.sql.jdbc;
import java.sql.ResultSetMetaData; import java.sql.ResultSetMetaData;
import java.sql.Statement; import java.sql.Statement;

View File

@ -3,7 +3,7 @@
* or more contributor license agreements. Licensed under the Elastic License; * or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
package org.elasticsearch.xpack.sql.jdbc.jdbc; package org.elasticsearch.xpack.sql.jdbc;
import java.sql.SQLException; import java.sql.SQLException;

View File

@ -3,7 +3,7 @@
* or more contributor license agreements. Licensed under the Elastic License; * or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
package org.elasticsearch.xpack.sql.jdbc.debug; package org.elasticsearch.xpack.sql.jdbc;
import java.sql.Connection; import java.sql.Connection;
import java.sql.ParameterMetaData; import java.sql.ParameterMetaData;

View File

@ -3,9 +3,7 @@
* or more contributor license agreements. Licensed under the Elastic License; * or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
package org.elasticsearch.xpack.sql.jdbc.jdbc; package org.elasticsearch.xpack.sql.jdbc;
import org.elasticsearch.xpack.sql.jdbc.type.DataType;
import java.sql.Date; import java.sql.Date;
import java.sql.SQLException; import java.sql.SQLException;
@ -115,7 +113,7 @@ final class TypeConverter {
* Converts object val from columnType to type * Converts object val from columnType to type
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
static <T> T convert(Object val, DataType columnType, Class<T> type, String typeString) throws SQLException { static <T> T convert(Object val, EsType columnType, Class<T> type, String typeString) throws SQLException {
if (type == null) { if (type == null) {
return (T) convert(val, columnType, typeString); return (T) convert(val, columnType, typeString);
} }
@ -123,7 +121,7 @@ final class TypeConverter {
// converting a Long to a Timestamp shouldn't be possible according to the spec, // converting a Long to a Timestamp shouldn't be possible according to the spec,
// it feels a little brittle to check this scenario here and I don't particularly like it // it feels a little brittle to check this scenario here and I don't particularly like it
// TODO: can we do any better or should we go over the spec and allow getLong(date) to be valid? // TODO: can we do any better or should we go over the spec and allow getLong(date) to be valid?
if (!(type == Long.class && columnType == DataType.DATE) && type.isInstance(val)) { if (!(type == Long.class && columnType == EsType.DATE) && type.isInstance(val)) {
try { try {
return type.cast(val); return type.cast(val);
} catch (ClassCastException cce) { } catch (ClassCastException cce) {
@ -192,7 +190,7 @@ final class TypeConverter {
/** /**
* Converts the object from JSON representation to the specified JDBCType * Converts the object from JSON representation to the specified JDBCType
*/ */
static Object convert(Object v, DataType columnType, String typeString) throws SQLException { static Object convert(Object v, EsType columnType, String typeString) throws SQLException {
switch (columnType) { switch (columnType) {
case NULL: case NULL:
return null; return null;
@ -273,18 +271,18 @@ final class TypeConverter {
return nativeValue == null ? null : String.valueOf(nativeValue); return nativeValue == null ? null : String.valueOf(nativeValue);
} }
private static <T> T failConversion(Object value, DataType columnType, String typeString, Class<T> target) throws SQLException { private static <T> T failConversion(Object value, EsType columnType, String typeString, Class<T> target) throws SQLException {
return failConversion(value, columnType, typeString, target, null); return failConversion(value, columnType, typeString, target, null);
} }
private static <T> T failConversion(Object value, DataType columnType, String typeString, Class<T> target, Exception e) private static <T> T failConversion(Object value, EsType columnType, String typeString, Class<T> target, Exception e)
throws SQLException { throws SQLException {
String message = format(Locale.ROOT, "Unable to convert value [%.128s] of type [%s] to [%s]", value, columnType, String message = format(Locale.ROOT, "Unable to convert value [%.128s] of type [%s] to [%s]", value, columnType,
typeString); typeString);
throw e != null ? new SQLException(message, e) : new SQLException(message); throw e != null ? new SQLException(message, e) : new SQLException(message);
} }
private static Boolean asBoolean(Object val, DataType columnType, String typeString) throws SQLException { private static Boolean asBoolean(Object val, EsType columnType, String typeString) throws SQLException {
switch (columnType) { switch (columnType) {
case BOOLEAN: case BOOLEAN:
case BYTE: case BYTE:
@ -304,7 +302,7 @@ final class TypeConverter {
} }
} }
private static Byte asByte(Object val, DataType columnType, String typeString) throws SQLException { private static Byte asByte(Object val, EsType columnType, String typeString) throws SQLException {
switch (columnType) { switch (columnType) {
case BOOLEAN: case BOOLEAN:
return Byte.valueOf(((Boolean) val).booleanValue() ? (byte) 1 : (byte) 0); return Byte.valueOf(((Boolean) val).booleanValue() ? (byte) 1 : (byte) 0);
@ -331,7 +329,7 @@ final class TypeConverter {
return failConversion(val, columnType, typeString, Byte.class); return failConversion(val, columnType, typeString, Byte.class);
} }
private static Short asShort(Object val, DataType columnType, String typeString) throws SQLException { private static Short asShort(Object val, EsType columnType, String typeString) throws SQLException {
switch (columnType) { switch (columnType) {
case BOOLEAN: case BOOLEAN:
return Short.valueOf(((Boolean) val).booleanValue() ? (short) 1 : (short) 0); return Short.valueOf(((Boolean) val).booleanValue() ? (short) 1 : (short) 0);
@ -357,7 +355,7 @@ final class TypeConverter {
return failConversion(val, columnType, typeString, Short.class); return failConversion(val, columnType, typeString, Short.class);
} }
private static Integer asInteger(Object val, DataType columnType, String typeString) throws SQLException { private static Integer asInteger(Object val, EsType columnType, String typeString) throws SQLException {
switch (columnType) { switch (columnType) {
case BOOLEAN: case BOOLEAN:
return Integer.valueOf(((Boolean) val).booleanValue() ? 1 : 0); return Integer.valueOf(((Boolean) val).booleanValue() ? 1 : 0);
@ -383,7 +381,7 @@ final class TypeConverter {
return failConversion(val, columnType, typeString, Integer.class); return failConversion(val, columnType, typeString, Integer.class);
} }
private static Long asLong(Object val, DataType columnType, String typeString) throws SQLException { private static Long asLong(Object val, EsType columnType, String typeString) throws SQLException {
switch (columnType) { switch (columnType) {
case BOOLEAN: case BOOLEAN:
return Long.valueOf(((Boolean) val).booleanValue() ? 1 : 0); return Long.valueOf(((Boolean) val).booleanValue() ? 1 : 0);
@ -415,7 +413,7 @@ final class TypeConverter {
return failConversion(val, columnType, typeString, Long.class); return failConversion(val, columnType, typeString, Long.class);
} }
private static Float asFloat(Object val, DataType columnType, String typeString) throws SQLException { private static Float asFloat(Object val, EsType columnType, String typeString) throws SQLException {
switch (columnType) { switch (columnType) {
case BOOLEAN: case BOOLEAN:
return Float.valueOf(((Boolean) val).booleanValue() ? 1 : 0); return Float.valueOf(((Boolean) val).booleanValue() ? 1 : 0);
@ -441,7 +439,7 @@ final class TypeConverter {
return failConversion(val, columnType, typeString, Float.class); return failConversion(val, columnType, typeString, Float.class);
} }
private static Double asDouble(Object val, DataType columnType, String typeString) throws SQLException { private static Double asDouble(Object val, EsType columnType, String typeString) throws SQLException {
switch (columnType) { switch (columnType) {
case BOOLEAN: case BOOLEAN:
return Double.valueOf(((Boolean) val).booleanValue() ? 1 : 0); return Double.valueOf(((Boolean) val).booleanValue() ? 1 : 0);
@ -467,48 +465,48 @@ final class TypeConverter {
return failConversion(val, columnType, typeString, Double.class); return failConversion(val, columnType, typeString, Double.class);
} }
private static Date asDate(Object val, DataType columnType, String typeString) throws SQLException { private static Date asDate(Object val, EsType columnType, String typeString) throws SQLException {
if (columnType == DataType.DATE) { if (columnType == EsType.DATE) {
return new Date(utcMillisRemoveTime(((Number) val).longValue())); return new Date(utcMillisRemoveTime(((Number) val).longValue()));
} }
return failConversion(val, columnType, typeString, Date.class); return failConversion(val, columnType, typeString, Date.class);
} }
private static Time asTime(Object val, DataType columnType, String typeString) throws SQLException { private static Time asTime(Object val, EsType columnType, String typeString) throws SQLException {
if (columnType == DataType.DATE) { if (columnType == EsType.DATE) {
return new Time(utcMillisRemoveDate(((Number) val).longValue())); return new Time(utcMillisRemoveDate(((Number) val).longValue()));
} }
return failConversion(val, columnType, typeString, Time.class); return failConversion(val, columnType, typeString, Time.class);
} }
private static Timestamp asTimestamp(Object val, DataType columnType, String typeString) throws SQLException { private static Timestamp asTimestamp(Object val, EsType columnType, String typeString) throws SQLException {
if (columnType == DataType.DATE) { if (columnType == EsType.DATE) {
return new Timestamp(((Number) val).longValue()); return new Timestamp(((Number) val).longValue());
} }
return failConversion(val, columnType, typeString, Timestamp.class); return failConversion(val, columnType, typeString, Timestamp.class);
} }
private static byte[] asByteArray(Object val, DataType columnType, String typeString) throws SQLException { private static byte[] asByteArray(Object val, EsType columnType, String typeString) throws SQLException {
throw new SQLFeatureNotSupportedException(); throw new SQLFeatureNotSupportedException();
} }
private static LocalDate asLocalDate(Object val, DataType columnType, String typeString) throws SQLException { private static LocalDate asLocalDate(Object val, EsType columnType, String typeString) throws SQLException {
throw new SQLFeatureNotSupportedException(); throw new SQLFeatureNotSupportedException();
} }
private static LocalTime asLocalTime(Object val, DataType columnType, String typeString) throws SQLException { private static LocalTime asLocalTime(Object val, EsType columnType, String typeString) throws SQLException {
throw new SQLFeatureNotSupportedException(); throw new SQLFeatureNotSupportedException();
} }
private static LocalDateTime asLocalDateTime(Object val, DataType columnType, String typeString) throws SQLException { private static LocalDateTime asLocalDateTime(Object val, EsType columnType, String typeString) throws SQLException {
throw new SQLFeatureNotSupportedException(); throw new SQLFeatureNotSupportedException();
} }
private static OffsetTime asOffsetTime(Object val, DataType columnType, String typeString) throws SQLException { private static OffsetTime asOffsetTime(Object val, EsType columnType, String typeString) throws SQLException {
throw new SQLFeatureNotSupportedException(); throw new SQLFeatureNotSupportedException();
} }
private static OffsetDateTime asOffsetDateTime(Object val, DataType columnType, String typeString) throws SQLException { private static OffsetDateTime asOffsetDateTime(Object val, EsType columnType, String typeString) throws SQLException {
throw new SQLFeatureNotSupportedException(); throw new SQLFeatureNotSupportedException();
} }

View File

@ -0,0 +1,175 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.xpack.sql.jdbc;
import java.sql.JDBCType;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.sql.SQLType;
import java.sql.Timestamp;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.Period;
import java.util.Calendar;
import java.util.Collections;
import java.util.EnumSet;
import java.util.GregorianCalendar;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import static java.util.Collections.unmodifiableMap;
final class TypeUtils {
private TypeUtils() {}
private static final Map<Class<?>, EsType> CLASS_TO_TYPE;
private static final Map<EsType, Class<?>> TYPE_TO_CLASS;
private static final Map<String, EsType> ENUM_NAME_TO_TYPE;
private static final Map<Integer, EsType> SQL_TO_TYPE;
private static final Set<EsType> SIGNED_TYPE = EnumSet.of(EsType.BYTE,
EsType.SHORT, EsType.INTEGER, EsType.LONG,
EsType.FLOAT, EsType.HALF_FLOAT, EsType.SCALED_FLOAT, EsType.DOUBLE, EsType.DATE);
static {
Map<Class<?>, EsType> aMap = new LinkedHashMap<>();
aMap.put(Boolean.class, EsType.BOOLEAN);
aMap.put(Byte.class, EsType.BYTE);
aMap.put(Short.class, EsType.SHORT);
aMap.put(Integer.class, EsType.INTEGER);
aMap.put(Long.class, EsType.LONG);
aMap.put(Float.class, EsType.FLOAT);
aMap.put(Double.class, EsType.DOUBLE);
aMap.put(String.class, EsType.KEYWORD);
aMap.put(byte[].class, EsType.BINARY);
aMap.put(String.class, EsType.KEYWORD);
aMap.put(Timestamp.class, EsType.DATE);
// apart from the mappings in {@code DataType} three more Java classes can be mapped to a {@code JDBCType.TIMESTAMP}
// according to B-4 table from the jdbc4.2 spec
aMap.put(Calendar.class, EsType.DATE);
aMap.put(GregorianCalendar.class, EsType.DATE);
aMap.put(java.util.Date.class, EsType.DATE);
aMap.put(java.sql.Date.class, EsType.DATE);
aMap.put(java.sql.Time.class, EsType.DATE);
aMap.put(LocalDateTime.class, EsType.DATE);
CLASS_TO_TYPE = Collections.unmodifiableMap(aMap);
Map<EsType, Class<?>> types = new LinkedHashMap<>();
types.put(EsType.BOOLEAN, Boolean.class);
types.put(EsType.BYTE, Byte.class);
types.put(EsType.SHORT, Short.class);
types.put(EsType.INTEGER, Integer.class);
types.put(EsType.LONG, Long.class);
types.put(EsType.DOUBLE, Double.class);
types.put(EsType.FLOAT, Float.class);
types.put(EsType.HALF_FLOAT, Double.class);
types.put(EsType.SCALED_FLOAT, Double.class);
types.put(EsType.KEYWORD, String.class);
types.put(EsType.TEXT, String.class);
types.put(EsType.BINARY, byte[].class);
types.put(EsType.DATE, Timestamp.class);
types.put(EsType.IP, String.class);
types.put(EsType.INTERVAL_YEAR, Period.class);
types.put(EsType.INTERVAL_MONTH, Period.class);
types.put(EsType.INTERVAL_YEAR_TO_MONTH, Period.class);
types.put(EsType.INTERVAL_DAY, Duration.class);
types.put(EsType.INTERVAL_HOUR, Duration.class);
types.put(EsType.INTERVAL_MINUTE, Duration.class);
types.put(EsType.INTERVAL_SECOND, Duration.class);
types.put(EsType.INTERVAL_DAY_TO_HOUR, Duration.class);
types.put(EsType.INTERVAL_DAY_TO_MINUTE, Duration.class);
types.put(EsType.INTERVAL_DAY_TO_SECOND, Duration.class);
types.put(EsType.INTERVAL_HOUR_TO_MINUTE, Duration.class);
types.put(EsType.INTERVAL_HOUR_TO_SECOND, Duration.class);
types.put(EsType.INTERVAL_MINUTE_TO_SECOND, Duration.class);
TYPE_TO_CLASS = unmodifiableMap(types);
Map<String, EsType> strings = new LinkedHashMap<>();
Map<Integer, EsType> numbers = new LinkedHashMap<>();
for (EsType dataType : EsType.values()) {
strings.put(dataType.getName().toLowerCase(Locale.ROOT), dataType);
numbers.putIfAbsent(dataType.getVendorTypeNumber(), dataType);
}
ENUM_NAME_TO_TYPE = unmodifiableMap(strings);
SQL_TO_TYPE = unmodifiableMap(numbers);
}
static boolean isSigned(EsType type) {
return SIGNED_TYPE.contains(type);
}
static Class<?> classOf(EsType type) {
return TYPE_TO_CLASS.get(type);
}
static SQLType asSqlType(int sqlType) throws SQLException {
for (JDBCType jdbcType : JDBCType.class.getEnumConstants()) {
if (sqlType == jdbcType.getVendorTypeNumber().intValue()) {
return jdbcType;
}
}
// fallback to DataType
return of(sqlType);
}
static EsType of(SQLType sqlType) throws SQLException {
if (sqlType instanceof EsType) {
return (EsType) sqlType;
}
EsType dataType = SQL_TO_TYPE.get(Integer.valueOf(sqlType.getVendorTypeNumber()));
if (dataType == null) {
throw new SQLFeatureNotSupportedException("Unsupported SQL type [" + sqlType + "]");
}
return dataType;
}
static EsType of(int sqlType) throws SQLException {
EsType dataType = SQL_TO_TYPE.get(Integer.valueOf(sqlType));
if (dataType == null) {
throw new SQLFeatureNotSupportedException("Unsupported SQL type [" + sqlType + "]");
}
return dataType;
}
static EsType of(String name) throws SQLException {
EsType dataType = ENUM_NAME_TO_TYPE.get(name);
if (dataType == null) {
throw new SQLFeatureNotSupportedException("Unsupported Data type [" + name + "]");
}
return dataType;
}
static boolean isString(EsType dataType) {
return dataType == EsType.KEYWORD || dataType == EsType.TEXT;
}
static EsType of(Class<? extends Object> clazz) throws SQLException {
EsType dataType = CLASS_TO_TYPE.get(clazz);
if (dataType == null) {
// fall-back to iteration for checking class hierarchies (in case of custom objects)
for (Entry<Class<?>, EsType> e : CLASS_TO_TYPE.entrySet()) {
if (e.getKey().isAssignableFrom(clazz)) {
return e.getValue();
}
}
throw new SQLFeatureNotSupportedException("Objects of type [" + clazz.getName() + "] are not supported");
}
return dataType;
}
}

View File

@ -1,177 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.xpack.sql.jdbc.jdbc;
import org.elasticsearch.xpack.sql.jdbc.type.DataType;
import java.sql.JDBCType;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.sql.SQLType;
import java.sql.Timestamp;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.Period;
import java.util.Calendar;
import java.util.Collections;
import java.util.EnumSet;
import java.util.GregorianCalendar;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import static java.util.Collections.unmodifiableMap;
public class TypeUtils {
private TypeUtils() {}
private static final Map<Class<?>, DataType> CLASS_TO_TYPE;
private static final Map<DataType, Class<?>> TYPE_TO_CLASS;
private static final Map<String, DataType> ENUM_NAME_TO_TYPE;
private static final Map<Integer, DataType> SQL_TO_TYPE;
private static final Set<DataType> SIGNED_TYPE = EnumSet.of(DataType.BYTE,
DataType.SHORT, DataType.INTEGER, DataType.LONG,
DataType.FLOAT, DataType.HALF_FLOAT, DataType.SCALED_FLOAT, DataType.DOUBLE, DataType.DATE);
static {
Map<Class<?>, DataType> aMap = new LinkedHashMap<>();
aMap.put(Boolean.class, DataType.BOOLEAN);
aMap.put(Byte.class, DataType.BYTE);
aMap.put(Short.class, DataType.SHORT);
aMap.put(Integer.class, DataType.INTEGER);
aMap.put(Long.class, DataType.LONG);
aMap.put(Float.class, DataType.FLOAT);
aMap.put(Double.class, DataType.DOUBLE);
aMap.put(String.class, DataType.KEYWORD);
aMap.put(byte[].class, DataType.BINARY);
aMap.put(String.class, DataType.KEYWORD);
aMap.put(Timestamp.class, DataType.DATE);
// apart from the mappings in {@code DataType} three more Java classes can be mapped to a {@code JDBCType.TIMESTAMP}
// according to B-4 table from the jdbc4.2 spec
aMap.put(Calendar.class, DataType.DATE);
aMap.put(GregorianCalendar.class, DataType.DATE);
aMap.put(java.util.Date.class, DataType.DATE);
aMap.put(java.sql.Date.class, DataType.DATE);
aMap.put(java.sql.Time.class, DataType.DATE);
aMap.put(LocalDateTime.class, DataType.DATE);
CLASS_TO_TYPE = Collections.unmodifiableMap(aMap);
Map<DataType, Class<?>> types = new LinkedHashMap<>();
types.put(DataType.BOOLEAN, Boolean.class);
types.put(DataType.BYTE, Byte.class);
types.put(DataType.SHORT, Short.class);
types.put(DataType.INTEGER, Integer.class);
types.put(DataType.LONG, Long.class);
types.put(DataType.DOUBLE, Double.class);
types.put(DataType.FLOAT, Float.class);
types.put(DataType.HALF_FLOAT, Double.class);
types.put(DataType.SCALED_FLOAT, Double.class);
types.put(DataType.KEYWORD, String.class);
types.put(DataType.TEXT, String.class);
types.put(DataType.BINARY, byte[].class);
types.put(DataType.DATE, Timestamp.class);
types.put(DataType.IP, String.class);
types.put(DataType.INTERVAL_YEAR, Period.class);
types.put(DataType.INTERVAL_MONTH, Period.class);
types.put(DataType.INTERVAL_YEAR_TO_MONTH, Period.class);
types.put(DataType.INTERVAL_DAY, Duration.class);
types.put(DataType.INTERVAL_HOUR, Duration.class);
types.put(DataType.INTERVAL_MINUTE, Duration.class);
types.put(DataType.INTERVAL_SECOND, Duration.class);
types.put(DataType.INTERVAL_DAY_TO_HOUR, Duration.class);
types.put(DataType.INTERVAL_DAY_TO_MINUTE, Duration.class);
types.put(DataType.INTERVAL_DAY_TO_SECOND, Duration.class);
types.put(DataType.INTERVAL_HOUR_TO_MINUTE, Duration.class);
types.put(DataType.INTERVAL_HOUR_TO_SECOND, Duration.class);
types.put(DataType.INTERVAL_MINUTE_TO_SECOND, Duration.class);
TYPE_TO_CLASS = unmodifiableMap(types);
Map<String, DataType> strings = new LinkedHashMap<>();
Map<Integer, DataType> numbers = new LinkedHashMap<>();
for (DataType dataType : DataType.values()) {
strings.put(dataType.getName().toLowerCase(Locale.ROOT), dataType);
numbers.putIfAbsent(dataType.getVendorTypeNumber(), dataType);
}
ENUM_NAME_TO_TYPE = unmodifiableMap(strings);
SQL_TO_TYPE = unmodifiableMap(numbers);
}
static boolean isSigned(DataType type) {
return SIGNED_TYPE.contains(type);
}
static Class<?> classOf(DataType type) {
return TYPE_TO_CLASS.get(type);
}
static SQLType asSqlType(int sqlType) throws SQLException {
for (JDBCType jdbcType : JDBCType.class.getEnumConstants()) {
if (sqlType == jdbcType.getVendorTypeNumber().intValue()) {
return jdbcType;
}
}
// fallback to DataType
return of(sqlType);
}
static DataType of(SQLType sqlType) throws SQLException {
if (sqlType instanceof DataType) {
return (DataType) sqlType;
}
DataType dataType = SQL_TO_TYPE.get(Integer.valueOf(sqlType.getVendorTypeNumber()));
if (dataType == null) {
throw new SQLFeatureNotSupportedException("Unsupported SQL type [" + sqlType + "]");
}
return dataType;
}
static DataType of(int sqlType) throws SQLException {
DataType dataType = SQL_TO_TYPE.get(Integer.valueOf(sqlType));
if (dataType == null) {
throw new SQLFeatureNotSupportedException("Unsupported SQL type [" + sqlType + "]");
}
return dataType;
}
public static DataType of(String name) throws SQLException {
DataType dataType = ENUM_NAME_TO_TYPE.get(name);
if (dataType == null) {
throw new SQLFeatureNotSupportedException("Unsupported Data type [" + name + "]");
}
return dataType;
}
static boolean isString(DataType dataType) {
return dataType == DataType.KEYWORD || dataType == DataType.TEXT;
}
static DataType of(Class<? extends Object> clazz) throws SQLException {
DataType dataType = CLASS_TO_TYPE.get(clazz);
if (dataType == null) {
// fall-back to iteration for checking class hierarchies (in case of custom objects)
for (Entry<Class<?>, DataType> e : CLASS_TO_TYPE.entrySet()) {
if (e.getKey().isAssignableFrom(clazz)) {
return e.getValue();
}
}
throw new SQLFeatureNotSupportedException("Objects of type [" + clazz.getName() + "] are not supported");
}
return dataType;
}
}

View File

@ -1 +1 @@
org.elasticsearch.xpack.sql.jdbc.jdbc.JdbcDriver org.elasticsearch.xpack.sql.jdbc.EsDriver

View File

@ -3,31 +3,32 @@
* or more contributor license agreements. Licensed under the Elastic License; * or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
package org.elasticsearch.xpack.sql.jdbc.net.protocol; package org.elasticsearch.xpack.sql.jdbc;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xpack.sql.jdbc.type.DataType; import org.elasticsearch.xpack.sql.jdbc.EsType;
import org.elasticsearch.xpack.sql.jdbc.JdbcColumnInfo;
import static org.elasticsearch.xpack.sql.client.StringUtils.EMPTY; import static org.elasticsearch.xpack.sql.client.StringUtils.EMPTY;
public class ColumnInfoTests extends ESTestCase { public class ColumnInfoTests extends ESTestCase {
static JdbcColumnInfo varcharInfo(String name) { static JdbcColumnInfo varcharInfo(String name) {
return new JdbcColumnInfo(name, DataType.KEYWORD, EMPTY, EMPTY, EMPTY, EMPTY, 0); return new JdbcColumnInfo(name, EsType.KEYWORD, EMPTY, EMPTY, EMPTY, EMPTY, 0);
} }
static JdbcColumnInfo intInfo(String name) { static JdbcColumnInfo intInfo(String name) {
return new JdbcColumnInfo(name, DataType.INTEGER, EMPTY, EMPTY, EMPTY, EMPTY, 11); return new JdbcColumnInfo(name, EsType.INTEGER, EMPTY, EMPTY, EMPTY, EMPTY, 11);
} }
static JdbcColumnInfo doubleInfo(String name) { static JdbcColumnInfo doubleInfo(String name) {
return new JdbcColumnInfo(name, DataType.DOUBLE, EMPTY, EMPTY, EMPTY, EMPTY, 25); return new JdbcColumnInfo(name, EsType.DOUBLE, EMPTY, EMPTY, EMPTY, EMPTY, 25);
} }
public void testToString() { public void testToString() {
assertEquals("test.doc.a<type=[KEYWORD] catalog=[as] schema=[ads] label=[lab]>", assertEquals("test.doc.a<type=[KEYWORD] catalog=[as] schema=[ads] label=[lab]>",
new JdbcColumnInfo("a", DataType.KEYWORD, "test.doc", "as", "ads", "lab", 0).toString()); new JdbcColumnInfo("a", EsType.KEYWORD, "test.doc", "as", "ads", "lab", 0).toString());
assertEquals("test.doc.a<type=[KEYWORD]>", assertEquals("test.doc.a<type=[KEYWORD]>",
new JdbcColumnInfo("a", DataType.KEYWORD, "test.doc", EMPTY, EMPTY, EMPTY, 0).toString()); new JdbcColumnInfo("a", EsType.KEYWORD, "test.doc", EMPTY, EMPTY, EMPTY, 0).toString());
assertEquals("string<type=[KEYWORD]>", varcharInfo("string").toString()); assertEquals("string<type=[KEYWORD]>", varcharInfo("string").toString());
assertEquals("int<type=[INTEGER]>", intInfo("int").toString()); assertEquals("int<type=[INTEGER]>", intInfo("int").toString());
assertEquals("d<type=[DOUBLE]>", doubleInfo("d").toString()); assertEquals("d<type=[DOUBLE]>", doubleInfo("d").toString());

View File

@ -7,7 +7,6 @@ package org.elasticsearch.xpack.sql.jdbc;
import org.elasticsearch.Version; import org.elasticsearch.Version;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xpack.sql.jdbc.jdbc.JdbcDriver;
import java.security.AccessController; import java.security.AccessController;
import java.security.PrivilegedExceptionAction; import java.security.PrivilegedExceptionAction;
@ -32,7 +31,7 @@ public class DriverManagerRegistrationTests extends ESTestCase {
}); });
} }
private static void driverManagerTemplate(Consumer<JdbcDriver> c) throws Exception { private static void driverManagerTemplate(Consumer<EsDriver> c) throws Exception {
String url = "jdbc:es:localhost:9200/"; String url = "jdbc:es:localhost:9200/";
Driver driver = null; Driver driver = null;
try { try {
@ -44,7 +43,7 @@ public class DriverManagerRegistrationTests extends ESTestCase {
boolean set = driver != null; boolean set = driver != null;
try { try {
JdbcDriver d = JdbcDriver.register(); EsDriver d = EsDriver.register();
if (driver != null) { if (driver != null) {
assertEquals(driver, d); assertEquals(driver, d);
} }
@ -53,7 +52,7 @@ public class DriverManagerRegistrationTests extends ESTestCase {
AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> { AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> {
// mimic DriverManager and unregister the driver // mimic DriverManager and unregister the driver
JdbcDriver.deregister(); EsDriver.deregister();
return null; return null;
}); });
@ -61,7 +60,7 @@ public class DriverManagerRegistrationTests extends ESTestCase {
assertEquals("No suitable driver", ex.getMessage()); assertEquals("No suitable driver", ex.getMessage());
} finally { } finally {
if (set) { if (set) {
JdbcDriver.register(); EsDriver.register();
} }
} }
} }

View File

@ -6,7 +6,6 @@
package org.elasticsearch.xpack.sql.jdbc; package org.elasticsearch.xpack.sql.jdbc;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xpack.sql.jdbc.jdbc.JdbcConfiguration;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Properties; import java.util.Properties;

View File

@ -4,9 +4,10 @@
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
package org.elasticsearch.xpack.sql.jdbc.jdbc; package org.elasticsearch.xpack.sql.jdbc;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xpack.sql.jdbc.JdbcDatabaseMetaData;
public class JdbcDatabaseMetaDataTests extends ESTestCase { public class JdbcDatabaseMetaDataTests extends ESTestCase {

View File

@ -3,10 +3,12 @@
* or more contributor license agreements. Licensed under the Elastic License; * or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
package org.elasticsearch.xpack.sql.jdbc.jdbc; package org.elasticsearch.xpack.sql.jdbc;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xpack.sql.jdbc.type.DataType; import org.elasticsearch.xpack.sql.jdbc.EsType;
import org.elasticsearch.xpack.sql.jdbc.JdbcConfiguration;
import org.elasticsearch.xpack.sql.jdbc.JdbcPreparedStatement;
import java.net.URL; import java.net.URL;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
@ -26,17 +28,17 @@ import java.util.Locale;
import java.util.Map; import java.util.Map;
import static java.lang.String.format; import static java.lang.String.format;
import static org.elasticsearch.xpack.sql.jdbc.type.DataType.BINARY; import static org.elasticsearch.xpack.sql.jdbc.EsType.BINARY;
import static org.elasticsearch.xpack.sql.jdbc.type.DataType.BOOLEAN; import static org.elasticsearch.xpack.sql.jdbc.EsType.BOOLEAN;
import static org.elasticsearch.xpack.sql.jdbc.type.DataType.BYTE; import static org.elasticsearch.xpack.sql.jdbc.EsType.BYTE;
import static org.elasticsearch.xpack.sql.jdbc.type.DataType.DATE; import static org.elasticsearch.xpack.sql.jdbc.EsType.DATE;
import static org.elasticsearch.xpack.sql.jdbc.type.DataType.DOUBLE; import static org.elasticsearch.xpack.sql.jdbc.EsType.DOUBLE;
import static org.elasticsearch.xpack.sql.jdbc.type.DataType.FLOAT; import static org.elasticsearch.xpack.sql.jdbc.EsType.FLOAT;
import static org.elasticsearch.xpack.sql.jdbc.type.DataType.HALF_FLOAT; import static org.elasticsearch.xpack.sql.jdbc.EsType.HALF_FLOAT;
import static org.elasticsearch.xpack.sql.jdbc.type.DataType.INTEGER; import static org.elasticsearch.xpack.sql.jdbc.EsType.INTEGER;
import static org.elasticsearch.xpack.sql.jdbc.type.DataType.KEYWORD; import static org.elasticsearch.xpack.sql.jdbc.EsType.KEYWORD;
import static org.elasticsearch.xpack.sql.jdbc.type.DataType.LONG; import static org.elasticsearch.xpack.sql.jdbc.EsType.LONG;
import static org.elasticsearch.xpack.sql.jdbc.type.DataType.SHORT; import static org.elasticsearch.xpack.sql.jdbc.EsType.SHORT;
public class JdbcPreparedStatementTests extends ESTestCase { public class JdbcPreparedStatementTests extends ESTestCase {
@ -560,10 +562,10 @@ public class JdbcPreparedStatementTests extends ESTestCase {
JdbcPreparedStatement jps = createJdbcPreparedStatement(); JdbcPreparedStatement jps = createJdbcPreparedStatement();
byte[] buffer = "foo".getBytes(StandardCharsets.UTF_8); byte[] buffer = "foo".getBytes(StandardCharsets.UTF_8);
SQLException sqle = expectThrows(SQLFeatureNotSupportedException.class, () -> jps.setObject(1, buffer, DataType.KEYWORD)); SQLException sqle = expectThrows(SQLFeatureNotSupportedException.class, () -> jps.setObject(1, buffer, EsType.KEYWORD));
assertEquals("Conversion from type [byte[]] to [KEYWORD] not supported", sqle.getMessage()); assertEquals("Conversion from type [byte[]] to [KEYWORD] not supported", sqle.getMessage());
sqle = expectThrows(SQLFeatureNotSupportedException.class, () -> jps.setObject(1, buffer, DataType.INTERVAL_DAY_TO_MINUTE)); sqle = expectThrows(SQLFeatureNotSupportedException.class, () -> jps.setObject(1, buffer, EsType.INTERVAL_DAY_TO_MINUTE));
assertEquals("Conversion from type [byte[]] to [INTERVAL_DAY_TO_MINUTE] not supported", sqle.getMessage()); assertEquals("Conversion from type [byte[]] to [INTERVAL_DAY_TO_MINUTE] not supported", sqle.getMessage());
} }
@ -571,7 +573,7 @@ public class JdbcPreparedStatementTests extends ESTestCase {
return new JdbcPreparedStatement(null, JdbcConfiguration.create("jdbc:es://l:1", null, 0), "?"); return new JdbcPreparedStatement(null, JdbcConfiguration.create("jdbc:es://l:1", null, 0), "?");
} }
private DataType jdbcType(JdbcPreparedStatement jps) throws SQLException { private EsType jdbcType(JdbcPreparedStatement jps) throws SQLException {
return jps.query.getParam(1).type; return jps.query.getParam(1).type;
} }

View File

@ -3,9 +3,10 @@
* or more contributor license agreements. Licensed under the Elastic License; * or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
package org.elasticsearch.xpack.sql.jdbc.jdbc; package org.elasticsearch.xpack.sql.jdbc;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xpack.sql.jdbc.SqlQueryParameterAnalyzer;
import java.sql.SQLException; import java.sql.SQLException;

View File

@ -3,14 +3,13 @@
* or more contributor license agreements. Licensed under the Elastic License; * or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
package org.elasticsearch.xpack.sql.jdbc.jdbc; package org.elasticsearch.xpack.sql.jdbc;
import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentHelper; import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.common.xcontent.json.JsonXContent; import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xpack.sql.jdbc.type.DataType;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.joda.time.ReadableDateTime; import org.joda.time.ReadableDateTime;
@ -23,16 +22,16 @@ public class TypeConverterTests extends ESTestCase {
public void testFloatAsNative() throws Exception { public void testFloatAsNative() throws Exception {
assertThat(convertAsNative(42.0f, DataType.FLOAT), instanceOf(Float.class)); assertThat(convertAsNative(42.0f, EsType.FLOAT), instanceOf(Float.class));
assertThat(convertAsNative(42.0, DataType.FLOAT), instanceOf(Float.class)); assertThat(convertAsNative(42.0, EsType.FLOAT), instanceOf(Float.class));
assertEquals(42.0f, (float) convertAsNative(42.0, DataType.FLOAT), 0.001f); assertEquals(42.0f, (float) convertAsNative(42.0, EsType.FLOAT), 0.001f);
assertEquals(Float.NaN, convertAsNative(Float.NaN, DataType.FLOAT)); assertEquals(Float.NaN, convertAsNative(Float.NaN, EsType.FLOAT));
assertEquals(Float.NEGATIVE_INFINITY, convertAsNative(Float.NEGATIVE_INFINITY, DataType.FLOAT)); assertEquals(Float.NEGATIVE_INFINITY, convertAsNative(Float.NEGATIVE_INFINITY, EsType.FLOAT));
assertEquals(Float.POSITIVE_INFINITY, convertAsNative(Float.POSITIVE_INFINITY, DataType.FLOAT)); assertEquals(Float.POSITIVE_INFINITY, convertAsNative(Float.POSITIVE_INFINITY, EsType.FLOAT));
} }
public void testDoubleAsNative() throws Exception { public void testDoubleAsNative() throws Exception {
DataType type = randomFrom(DataType.HALF_FLOAT, DataType.SCALED_FLOAT, DataType.DOUBLE); EsType type = randomFrom(EsType.HALF_FLOAT, EsType.SCALED_FLOAT, EsType.DOUBLE);
assertThat(convertAsNative(42.0, type), instanceOf(Double.class)); assertThat(convertAsNative(42.0, type), instanceOf(Double.class));
assertEquals(42.0f, (double) convertAsNative(42.0, type), 0.001f); assertEquals(42.0f, (double) convertAsNative(42.0, type), 0.001f);
assertEquals(Double.NaN, convertAsNative(Double.NaN, type)); assertEquals(Double.NaN, convertAsNative(Double.NaN, type));
@ -42,11 +41,11 @@ public class TypeConverterTests extends ESTestCase {
public void testTimestampAsNative() throws Exception { public void testTimestampAsNative() throws Exception {
DateTime now = DateTime.now(); DateTime now = DateTime.now();
assertThat(convertAsNative(now, DataType.DATE), instanceOf(Timestamp.class)); assertThat(convertAsNative(now, EsType.DATE), instanceOf(Timestamp.class));
assertEquals(now.getMillis(), ((Timestamp) convertAsNative(now, DataType.DATE)).getTime()); assertEquals(now.getMillis(), ((Timestamp) convertAsNative(now, EsType.DATE)).getTime());
} }
private Object convertAsNative(Object value, DataType type) throws Exception { private Object convertAsNative(Object value, EsType type) throws Exception {
// Simulate sending over XContent // Simulate sending over XContent
XContentBuilder builder = JsonXContent.contentBuilder(); XContentBuilder builder = JsonXContent.contentBuilder();
builder.startObject(); builder.startObject();
@ -61,5 +60,4 @@ public class TypeConverterTests extends ESTestCase {
Object copy = XContentHelper.convertToMap(BytesReference.bytes(builder), false, builder.contentType()).v2().get("value"); Object copy = XContentHelper.convertToMap(BytesReference.bytes(builder), false, builder.contentType()).v2().get("value");
return TypeConverter.convert(copy, type, type.toString()); return TypeConverter.convert(copy, type, type.toString());
} }
} }

View File

@ -8,7 +8,7 @@ package org.elasticsearch.xpack.sql.qa.jdbc;
import com.carrotsearch.hppc.IntObjectHashMap; import com.carrotsearch.hppc.IntObjectHashMap;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.elasticsearch.xpack.sql.jdbc.type.DataType; import org.elasticsearch.xpack.sql.jdbc.EsType;
import org.elasticsearch.xpack.sql.proto.StringUtils; import org.elasticsearch.xpack.sql.proto.StringUtils;
import org.relique.jdbc.csv.CsvResultSet; import org.relique.jdbc.csv.CsvResultSet;
@ -39,10 +39,10 @@ import static org.junit.Assert.fail;
*/ */
public class JdbcAssert { public class JdbcAssert {
private static final IntObjectHashMap<DataType> SQL_TO_TYPE = new IntObjectHashMap<>(); private static final IntObjectHashMap<EsType> SQL_TO_TYPE = new IntObjectHashMap<>();
static { static {
for (DataType type : DataType.values()) { for (EsType type : EsType.values()) {
SQL_TO_TYPE.putIfAbsent(type.getVendorTypeNumber().intValue(), type); SQL_TO_TYPE.putIfAbsent(type.getVendorTypeNumber().intValue(), type);
} }
} }

View File

@ -13,8 +13,7 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentHelper; import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.common.xcontent.json.JsonXContent; import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.test.rest.ESRestTestCase; import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.xpack.sql.jdbc.jdbc.JdbcConfiguration; import org.elasticsearch.xpack.sql.jdbc.EsDataSource;
import org.elasticsearch.xpack.sql.jdbc.jdbcx.JdbcDataSource;
import org.junit.After; import org.junit.After;
import java.io.IOException; import java.io.IOException;
@ -61,21 +60,21 @@ public abstract class JdbcIntegrationTestCase extends ESRestTestCase {
Connection connection = Connection connection =
DriverManager.getConnection(address, connectionProperties); DriverManager.getConnection(address, connectionProperties);
// end::connect-dm // end::connect-dm
assertNotNull("The timezone should be specified", connectionProperties.getProperty(JdbcConfiguration.TIME_ZONE)); assertNotNull("The timezone should be specified", connectionProperties.getProperty("timezone"));
return connection; return connection;
} }
protected Connection useDataSource() throws SQLException { protected Connection useDataSource() throws SQLException {
String elasticsearchAddress = getProtocol() + "://" + elasticsearchAddress(); String elasticsearchAddress = getProtocol() + "://" + elasticsearchAddress();
// tag::connect-ds // tag::connect-ds
JdbcDataSource dataSource = new JdbcDataSource(); EsDataSource dataSource = new EsDataSource();
String address = "jdbc:es://" + elasticsearchAddress; // <1> String address = "jdbc:es://" + elasticsearchAddress; // <1>
dataSource.setUrl(address); dataSource.setUrl(address);
Properties connectionProperties = connectionProperties(); // <2> Properties connectionProperties = connectionProperties(); // <2>
dataSource.setProperties(connectionProperties); dataSource.setProperties(connectionProperties);
Connection connection = dataSource.getConnection(); Connection connection = dataSource.getConnection();
// end::connect-ds // end::connect-ds
assertNotNull("The timezone should be specified", connectionProperties.getProperty(JdbcConfiguration.TIME_ZONE)); assertNotNull("The timezone should be specified", connectionProperties.getProperty("timezone"));
return connection; return connection;
} }
@ -107,7 +106,7 @@ public abstract class JdbcIntegrationTestCase extends ESRestTestCase {
*/ */
protected Properties connectionProperties() { protected Properties connectionProperties() {
Properties connectionProperties = new Properties(); Properties connectionProperties = new Properties();
connectionProperties.put(JdbcConfiguration.TIME_ZONE, randomKnownTimeZone()); connectionProperties.put("timezone", randomKnownTimeZone());
return connectionProperties; return connectionProperties;
} }

View File

@ -19,6 +19,8 @@ public abstract class JdbcTestUtils {
public static final String SQL_TRACE = "org.elasticsearch.xpack.sql:TRACE"; public static final String SQL_TRACE = "org.elasticsearch.xpack.sql:TRACE";
public static final String JDBC_TIMEZONE = "timezone";
public static void logResultSetMetadata(ResultSet rs, Logger logger) throws SQLException { public static void logResultSetMetadata(ResultSet rs, Logger logger) throws SQLException {
ResultSetMetaData metaData = rs.getMetaData(); ResultSetMetaData metaData = rs.getMetaData();
// header // header

View File

@ -13,9 +13,8 @@ import org.elasticsearch.common.Strings;
import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.collect.Tuple;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.json.JsonXContent; import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.xpack.sql.jdbc.jdbc.JdbcConfiguration; import org.elasticsearch.xpack.sql.jdbc.EsDataSource;
import org.elasticsearch.xpack.sql.jdbc.jdbcx.JdbcDataSource; import org.elasticsearch.xpack.sql.jdbc.EsType;
import org.elasticsearch.xpack.sql.jdbc.type.DataType;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -58,6 +57,7 @@ import static java.util.Calendar.MINUTE;
import static java.util.Calendar.MONTH; import static java.util.Calendar.MONTH;
import static java.util.Calendar.SECOND; import static java.util.Calendar.SECOND;
import static java.util.Calendar.YEAR; import static java.util.Calendar.YEAR;
import static org.elasticsearch.xpack.sql.qa.jdbc.JdbcTestUtils.JDBC_TIMEZONE;
public class ResultSetTestCase extends JdbcIntegrationTestCase { public class ResultSetTestCase extends JdbcIntegrationTestCase {
@ -69,14 +69,14 @@ public class ResultSetTestCase extends JdbcIntegrationTestCase {
+ "test_long, test_short, test_double, test_float, test_keyword, test_date FROM test"; + "test_long, test_short, test_double, test_float, test_keyword, test_date FROM test";
static final String SELECT_WILDCARD = "SELECT * FROM test"; static final String SELECT_WILDCARD = "SELECT * FROM test";
static { static {
dateTimeTestingFields.put(new Tuple<String, Object>("test_boolean", true), DataType.BOOLEAN); dateTimeTestingFields.put(new Tuple<String, Object>("test_boolean", true), EsType.BOOLEAN);
dateTimeTestingFields.put(new Tuple<String, Object>("test_byte", 1), DataType.BYTE); dateTimeTestingFields.put(new Tuple<String, Object>("test_byte", 1), EsType.BYTE);
dateTimeTestingFields.put(new Tuple<String, Object>("test_integer", 1), DataType.INTEGER); dateTimeTestingFields.put(new Tuple<String, Object>("test_integer", 1), EsType.INTEGER);
dateTimeTestingFields.put(new Tuple<String, Object>("test_long", 1L), DataType.LONG); dateTimeTestingFields.put(new Tuple<String, Object>("test_long", 1L), EsType.LONG);
dateTimeTestingFields.put(new Tuple<String, Object>("test_short", 1), DataType.SHORT); dateTimeTestingFields.put(new Tuple<String, Object>("test_short", 1), EsType.SHORT);
dateTimeTestingFields.put(new Tuple<String, Object>("test_double", 1d), DataType.DOUBLE); dateTimeTestingFields.put(new Tuple<String, Object>("test_double", 1d), EsType.DOUBLE);
dateTimeTestingFields.put(new Tuple<String, Object>("test_float", 1f), DataType.FLOAT); dateTimeTestingFields.put(new Tuple<String, Object>("test_float", 1f), EsType.FLOAT);
dateTimeTestingFields.put(new Tuple<String, Object>("test_keyword", "true"), DataType.KEYWORD); dateTimeTestingFields.put(new Tuple<String, Object>("test_keyword", "true"), EsType.KEYWORD);
} }
// Byte values testing // Byte values testing
@ -1525,24 +1525,24 @@ public class ResultSetTestCase extends JdbcIntegrationTestCase {
String elasticsearchAddress = getProtocol() + "://" + elasticsearchAddress(); String elasticsearchAddress = getProtocol() + "://" + elasticsearchAddress();
String address = "jdbc:es://" + elasticsearchAddress; String address = "jdbc:es://" + elasticsearchAddress;
Properties connectionProperties = connectionProperties(); Properties connectionProperties = connectionProperties();
connectionProperties.put(JdbcConfiguration.TIME_ZONE, timeZoneId); connectionProperties.put(JDBC_TIMEZONE, timeZoneId);
Connection connection = DriverManager.getConnection(address, connectionProperties); Connection connection = DriverManager.getConnection(address, connectionProperties);
assertNotNull("The timezone should be specified", connectionProperties.getProperty(JdbcConfiguration.TIME_ZONE)); assertNotNull("The timezone should be specified", connectionProperties.getProperty(JDBC_TIMEZONE));
return connection; return connection;
} }
private Connection useDataSource(String timeZoneId) throws SQLException { private Connection useDataSource(String timeZoneId) throws SQLException {
String elasticsearchAddress = getProtocol() + "://" + elasticsearchAddress(); String elasticsearchAddress = getProtocol() + "://" + elasticsearchAddress();
JdbcDataSource dataSource = new JdbcDataSource(); EsDataSource dataSource = new EsDataSource();
String address = "jdbc:es://" + elasticsearchAddress; String address = "jdbc:es://" + elasticsearchAddress;
dataSource.setUrl(address); dataSource.setUrl(address);
Properties connectionProperties = connectionProperties(); Properties connectionProperties = connectionProperties();
connectionProperties.put(JdbcConfiguration.TIME_ZONE, timeZoneId); connectionProperties.put(JDBC_TIMEZONE, timeZoneId);
dataSource.setProperties(connectionProperties); dataSource.setProperties(connectionProperties);
Connection connection = dataSource.getConnection(); Connection connection = dataSource.getConnection();
assertNotNull("The timezone should be specified", connectionProperties.getProperty(JdbcConfiguration.TIME_ZONE)); assertNotNull("The timezone should be specified", connectionProperties.getProperty(JDBC_TIMEZONE));
return connection; return connection;
} }
} }

View File

@ -11,7 +11,6 @@ import org.elasticsearch.client.ResponseException;
import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestClient;
import org.elasticsearch.common.Strings; import org.elasticsearch.common.Strings;
import org.elasticsearch.common.SuppressForbidden; import org.elasticsearch.common.SuppressForbidden;
import org.elasticsearch.xpack.sql.jdbc.jdbc.JdbcConfiguration;
import org.junit.AfterClass; import org.junit.AfterClass;
import org.junit.Before; import org.junit.Before;
@ -115,7 +114,7 @@ public abstract class SpecBaseIntegrationTestCase extends JdbcIntegrationTestCas
@Override @Override
protected Properties connectionProperties() { protected Properties connectionProperties() {
Properties connectionProperties = new Properties(); Properties connectionProperties = new Properties();
connectionProperties.setProperty(JdbcConfiguration.TIME_ZONE, "UTC"); connectionProperties.setProperty("timezone", "UTC");
return connectionProperties; return connectionProperties;
} }