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:
parent
2f547bac65
commit
95346926ef
|
@ -43,9 +43,9 @@ from `artifacts.elastic.co/maven` by adding it to the repositories list:
|
|||
[float]
|
||||
=== 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
|
||||
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:
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* 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.debug;
|
||||
package org.elasticsearch.xpack.sql.jdbc;
|
||||
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.Statement;
|
|
@ -3,14 +3,12 @@
|
|||
* 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.net.client;
|
||||
package org.elasticsearch.xpack.sql.jdbc;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
import org.elasticsearch.xpack.sql.jdbc.net.protocol.JdbcColumnInfo;
|
||||
|
||||
public interface Cursor {
|
||||
interface Cursor {
|
||||
|
||||
List<JdbcColumnInfo> columns();
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
* 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.debug;
|
||||
package org.elasticsearch.xpack.sql.jdbc;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
|
|
@ -3,11 +3,9 @@
|
|||
* 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.debug;
|
||||
package org.elasticsearch.xpack.sql.jdbc;
|
||||
|
||||
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.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
|
||||
* when needed.
|
||||
*/
|
||||
public final class Debug {
|
||||
final class Debug {
|
||||
|
||||
// cache for streams created by ourselves
|
||||
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
|
||||
* 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));
|
||||
}
|
||||
|
||||
|
@ -180,7 +178,7 @@ public final class Debug {
|
|||
return log;
|
||||
}
|
||||
|
||||
public static void release(JdbcConfiguration info) {
|
||||
static void release(JdbcConfiguration info) {
|
||||
if (!info.debug()) {
|
||||
return;
|
||||
}
|
||||
|
@ -206,7 +204,7 @@ public final class Debug {
|
|||
}
|
||||
}
|
||||
|
||||
public static synchronized void close() {
|
||||
static synchronized void close() {
|
||||
// clear the ref
|
||||
OUTPUT_REFS.clear();
|
||||
|
||||
|
@ -235,4 +233,4 @@ public final class Debug {
|
|||
private static PrintStream stderr() {
|
||||
return System.err;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
* 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.debug;
|
||||
package org.elasticsearch.xpack.sql.jdbc;
|
||||
|
||||
import org.elasticsearch.xpack.sql.client.StringUtils;
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
* 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.debug;
|
||||
package org.elasticsearch.xpack.sql.jdbc;
|
||||
|
||||
/**
|
||||
* Debug marker interface for compatible proxy.
|
|
@ -3,9 +3,7 @@
|
|||
* 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.debug;
|
||||
|
||||
import org.elasticsearch.xpack.sql.jdbc.JdbcSQLException;
|
||||
package org.elasticsearch.xpack.sql.jdbc;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.InvocationTargetException;
|
|
@ -3,10 +3,9 @@
|
|||
* 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.net.client;
|
||||
package org.elasticsearch.xpack.sql.jdbc;
|
||||
|
||||
import org.elasticsearch.common.collect.Tuple;
|
||||
import org.elasticsearch.xpack.sql.jdbc.net.protocol.JdbcColumnInfo;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
|
@ -3,12 +3,9 @@
|
|||
* 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.jdbcx;
|
||||
package org.elasticsearch.xpack.sql.jdbc;
|
||||
|
||||
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 java.io.PrintWriter;
|
||||
|
@ -21,10 +18,13 @@ import java.util.logging.Logger;
|
|||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
|
||||
public class JdbcDataSource implements DataSource, Wrapper {
|
||||
/**
|
||||
* Factory for connections to Elasticsearch SQL.
|
||||
*/
|
||||
public class EsDataSource implements DataSource, Wrapper {
|
||||
|
||||
static {
|
||||
// invoke Version to perform classpath/jar sanity checks
|
||||
Version.CURRENT.toString();
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@ public class JdbcDataSource implements DataSource, Wrapper {
|
|||
private int loginTimeout;
|
||||
private Properties props;
|
||||
|
||||
public JdbcDataSource() {}
|
||||
public EsDataSource() {}
|
||||
|
||||
@Override
|
||||
public PrintWriter getLogWriter() throws SQLException {
|
|
@ -3,14 +3,13 @@
|
|||
* 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;
|
||||
package org.elasticsearch.xpack.sql.jdbc;
|
||||
|
||||
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.sql.Connection;
|
||||
import java.sql.Driver;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.DriverPropertyInfo;
|
||||
import java.sql.SQLException;
|
||||
|
@ -18,9 +17,9 @@ import java.sql.SQLFeatureNotSupportedException;
|
|||
import java.util.Properties;
|
||||
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 {
|
||||
// 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
|
||||
DriverManager.registerDriver(INSTANCE, INSTANCE::close);
|
||||
return INSTANCE;
|
|
@ -4,13 +4,13 @@
|
|||
* 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.Types;
|
||||
|
||||
public enum DataType implements SQLType {
|
||||
public enum EsType implements SQLType {
|
||||
|
||||
NULL( Types.NULL),
|
||||
UNSUPPORTED( Types.OTHER),
|
||||
|
@ -46,7 +46,7 @@ public enum DataType implements SQLType {
|
|||
|
||||
private final Integer type;
|
||||
|
||||
DataType(int type) {
|
||||
EsType(int type) {
|
||||
this.type = Integer.valueOf(type);
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
* 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.Types;
|
|
@ -3,17 +3,17 @@
|
|||
* 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.net.protocol;
|
||||
package org.elasticsearch.xpack.sql.jdbc;
|
||||
|
||||
/**
|
||||
* General information about the server.
|
||||
*/
|
||||
public class InfoResponse {
|
||||
public final String cluster;
|
||||
public final int majorVersion;
|
||||
public final int minorVersion;
|
||||
class InfoResponse {
|
||||
final String cluster;
|
||||
final int majorVersion;
|
||||
final int minorVersion;
|
||||
|
||||
public InfoResponse(String clusterName, byte versionMajor, byte versionMinor) {
|
||||
InfoResponse(String clusterName, byte versionMajor, byte versionMinor) {
|
||||
this.cluster = clusterName;
|
||||
this.majorVersion = versionMajor;
|
||||
this.minorVersion = versionMinor;
|
|
@ -3,22 +3,20 @@
|
|||
* 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.net.protocol;
|
||||
|
||||
import org.elasticsearch.xpack.sql.jdbc.type.DataType;
|
||||
package org.elasticsearch.xpack.sql.jdbc;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class JdbcColumnInfo {
|
||||
class JdbcColumnInfo {
|
||||
public final String catalog;
|
||||
public final String schema;
|
||||
public final String table;
|
||||
public final String label;
|
||||
public final String name;
|
||||
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) {
|
||||
throw new IllegalArgumentException("[name] must not be null");
|
||||
}
|
||||
|
@ -46,7 +44,7 @@ public class JdbcColumnInfo {
|
|||
this.displaySize = displaySize;
|
||||
}
|
||||
|
||||
public int displaySize() {
|
||||
int displaySize() {
|
||||
// 0 - means unknown
|
||||
return displaySize;
|
||||
}
|
|
@ -3,12 +3,11 @@
|
|||
* 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;
|
||||
package org.elasticsearch.xpack.sql.jdbc;
|
||||
|
||||
import org.elasticsearch.xpack.sql.client.ConnectionConfiguration;
|
||||
import org.elasticsearch.xpack.sql.client.StringUtils;
|
||||
import org.elasticsearch.xpack.sql.client.Version;
|
||||
import org.elasticsearch.xpack.sql.jdbc.JdbcSQLException;
|
||||
|
||||
import java.net.URI;
|
||||
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.
|
||||
*/
|
||||
//TODO: beef this up for Security/SSL
|
||||
public class JdbcConfiguration extends ConnectionConfiguration {
|
||||
class JdbcConfiguration extends ConnectionConfiguration {
|
||||
static final String URL_PREFIX = "jdbc:es://";
|
||||
public static URI DEFAULT_URI = URI.create("http://localhost:9200/");
|
||||
|
|
@ -3,10 +3,7 @@
|
|||
* 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.debug.Debug;
|
||||
import org.elasticsearch.xpack.sql.jdbc.net.client.JdbcHttpClient;
|
||||
package org.elasticsearch.xpack.sql.jdbc;
|
||||
|
||||
import java.sql.Array;
|
||||
import java.sql.Blob;
|
||||
|
@ -33,7 +30,7 @@ import java.util.concurrent.TimeUnit;
|
|||
/**
|
||||
* Implementation of {@link Connection} for Elasticsearch.
|
||||
*/
|
||||
public class JdbcConnection implements Connection, JdbcWrapper {
|
||||
class JdbcConnection implements Connection, JdbcWrapper {
|
||||
|
||||
private final String url, userName;
|
||||
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).
|
||||
* 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;
|
||||
client = new JdbcHttpClient(connectionInfo);
|
||||
|
|
@ -3,14 +3,10 @@
|
|||
* 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;
|
||||
package org.elasticsearch.xpack.sql.jdbc;
|
||||
|
||||
import org.elasticsearch.xpack.sql.client.ObjectUtils;
|
||||
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.DatabaseMetaData;
|
||||
|
@ -1125,11 +1121,11 @@ class JdbcDatabaseMetaData implements DatabaseMetaData, JdbcWrapper {
|
|||
Object obj = cols[i];
|
||||
if (obj instanceof String) {
|
||||
String name = obj.toString();
|
||||
DataType type = DataType.KEYWORD;
|
||||
EsType type = EsType.KEYWORD;
|
||||
if (i + 1 < cols.length) {
|
||||
Object next = cols[i + 1];
|
||||
// check if the next item it's a type
|
||||
if (next instanceof DataType || next instanceof JDBCType) {
|
||||
if (next instanceof EsType || next instanceof JDBCType) {
|
||||
try {
|
||||
type = TypeUtils.of((JDBCType) next);
|
||||
i++;
|
|
@ -5,13 +5,13 @@
|
|||
*/
|
||||
package org.elasticsearch.xpack.sql.jdbc;
|
||||
|
||||
public class JdbcException extends RuntimeException {
|
||||
class JdbcException extends RuntimeException {
|
||||
|
||||
public JdbcException(String message) {
|
||||
JdbcException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public JdbcException(Throwable cause, String message) {
|
||||
JdbcException(Throwable cause, String message) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,16 +3,12 @@
|
|||
* 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.net.client;
|
||||
package org.elasticsearch.xpack.sql.jdbc;
|
||||
|
||||
import org.elasticsearch.common.collect.Tuple;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.xpack.sql.client.HttpClient;
|
||||
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.MainResponse;
|
||||
import org.elasticsearch.xpack.sql.proto.Mode;
|
||||
|
@ -32,7 +28,7 @@ import static org.elasticsearch.xpack.sql.client.StringUtils.EMPTY;
|
|||
* JDBC specific HTTP client.
|
||||
* Since JDBC is not thread-safe, neither is this class.
|
||||
*/
|
||||
public class JdbcHttpClient {
|
||||
class JdbcHttpClient {
|
||||
private final HttpClient httpClient;
|
||||
private final JdbcConfiguration conCfg;
|
||||
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).
|
||||
* 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);
|
||||
this.conCfg = conCfg;
|
||||
}
|
||||
|
||||
public boolean ping(long timeoutInMs) throws SQLException {
|
||||
boolean ping(long timeoutInMs) throws SQLException {
|
||||
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();
|
||||
SqlQueryRequest sqlRequest = new SqlQueryRequest(sql, params, null, Protocol.TIME_ZONE,
|
||||
fetch,
|
||||
|
@ -64,18 +60,18 @@ public class JdbcHttpClient {
|
|||
* Read the next page of results and returning
|
||||
* 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()),
|
||||
TimeValue.timeValueMillis(meta.queryTimeoutInMs()), new RequestInfo(Mode.JDBC));
|
||||
SqlQueryResponse response = httpClient.query(sqlRequest);
|
||||
return new Tuple<>(response.cursor(), response.rows());
|
||||
}
|
||||
|
||||
public boolean queryClose(String cursor) throws SQLException {
|
||||
boolean queryClose(String cursor) throws SQLException {
|
||||
return httpClient.queryClose(cursor);
|
||||
}
|
||||
|
||||
public InfoResponse serverInfo() throws SQLException {
|
||||
InfoResponse serverInfo() throws SQLException {
|
||||
if (serverInfo == null) {
|
||||
serverInfo = fetchServerInfo();
|
||||
}
|
|
@ -3,9 +3,9 @@
|
|||
* 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;
|
||||
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.SQLException;
|
|
@ -3,9 +3,7 @@
|
|||
* 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;
|
||||
package org.elasticsearch.xpack.sql.jdbc;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
|
@ -72,7 +70,7 @@ class JdbcPreparedStatement extends JdbcStatement implements PreparedStatement {
|
|||
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();
|
||||
|
||||
if (parameterIndex < 0 || parameterIndex > query.paramCount()) {
|
||||
|
@ -189,7 +187,7 @@ class JdbcPreparedStatement extends JdbcStatement implements PreparedStatement {
|
|||
@Override
|
||||
public void setObject(int parameterIndex, Object x) throws SQLException {
|
||||
if (x == null) {
|
||||
setParam(parameterIndex, null, DataType.NULL);
|
||||
setParam(parameterIndex, null, EsType.NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -343,7 +341,7 @@ class JdbcPreparedStatement extends JdbcStatement implements PreparedStatement {
|
|||
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();
|
||||
|
||||
// set the null value on the type and exit
|
||||
|
@ -354,11 +352,11 @@ class JdbcPreparedStatement extends JdbcStatement implements PreparedStatement {
|
|||
|
||||
checkKnownUnsupportedTypes(x);
|
||||
if (x instanceof byte[]) {
|
||||
if (dataType != DataType.BINARY) {
|
||||
if (dataType != EsType.BINARY) {
|
||||
throw new SQLFeatureNotSupportedException(
|
||||
"Conversion from type [byte[]] to [" + typeString + "] not supported");
|
||||
}
|
||||
setParam(parameterIndex, x, DataType.BINARY);
|
||||
setParam(parameterIndex, x, EsType.BINARY);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -369,7 +367,7 @@ class JdbcPreparedStatement extends JdbcStatement implements PreparedStatement {
|
|||
|| x instanceof Time
|
||||
|| 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
|
||||
java.util.Date dateToSet;
|
||||
if (x instanceof Timestamp) {
|
|
@ -3,12 +3,7 @@
|
|||
* 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.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;
|
||||
package org.elasticsearch.xpack.sql.jdbc;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
|
@ -245,12 +240,12 @@ class JdbcResultSet implements ResultSet, JdbcWrapper {
|
|||
|
||||
private Long dateTime(int columnIndex) throws SQLException {
|
||||
Object val = column(columnIndex);
|
||||
DataType type = cursor.columns().get(columnIndex - 1).type;
|
||||
EsType type = cursor.columns().get(columnIndex - 1).type;
|
||||
try {
|
||||
// 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
|
||||
// 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
|
||||
// return the "smallest" data type for numbers when parsing
|
||||
// TODO: this should probably be handled server side
|
||||
|
@ -333,7 +328,7 @@ class JdbcResultSet implements ResultSet, JdbcWrapper {
|
|||
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();
|
||||
|
||||
return TypeConverter.convert(val, columnType, type, typeString);
|
|
@ -3,9 +3,7 @@
|
|||
* 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.net.protocol.JdbcColumnInfo;
|
||||
package org.elasticsearch.xpack.sql.jdbc;
|
||||
|
||||
import java.sql.ResultSetMetaData;
|
||||
import java.sql.SQLException;
|
|
@ -7,13 +7,13 @@ package org.elasticsearch.xpack.sql.jdbc;
|
|||
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class JdbcSQLException extends SQLException {
|
||||
class JdbcSQLException extends SQLException {
|
||||
|
||||
public JdbcSQLException(String message) {
|
||||
JdbcSQLException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public JdbcSQLException(Throwable cause, String message) {
|
||||
JdbcSQLException(Throwable cause, String message) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,10 +3,8 @@
|
|||
* 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;
|
||||
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 java.sql.Connection;
|
|
@ -3,7 +3,7 @@
|
|||
* 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;
|
||||
package org.elasticsearch.xpack.sql.jdbc;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Wrapper;
|
|
@ -3,7 +3,7 @@
|
|||
* 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.net.protocol;
|
||||
package org.elasticsearch.xpack.sql.jdbc;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
|
@ -19,5 +19,5 @@ import java.lang.annotation.Target;
|
|||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.PARAMETER, ElementType.FIELD, ElementType.METHOD})
|
||||
public @interface Nullable {
|
||||
@interface Nullable {
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
* 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.debug;
|
||||
package org.elasticsearch.xpack.sql.jdbc;
|
||||
|
||||
final class ParameterMetaDataProxy extends DebuggingInvoker {
|
||||
|
|
@ -3,10 +3,8 @@
|
|||
* 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;
|
||||
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 java.sql.SQLException;
|
||||
|
@ -17,10 +15,10 @@ import java.util.stream.Collectors;
|
|||
class PreparedQuery {
|
||||
|
||||
static class ParamInfo {
|
||||
DataType type;
|
||||
EsType type;
|
||||
Object value;
|
||||
|
||||
ParamInfo(Object value, DataType type) {
|
||||
ParamInfo(Object value, EsType type) {
|
||||
this.value = value;
|
||||
this.type = type;
|
||||
}
|
||||
|
@ -42,7 +40,7 @@ class PreparedQuery {
|
|||
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) {
|
||||
throw new JdbcSQLException("Invalid parameter index [" + param + "]");
|
||||
}
|
||||
|
@ -56,7 +54,7 @@ class PreparedQuery {
|
|||
|
||||
void clearParams() {
|
||||
for (int i = 0; i < params.length; i++) {
|
||||
params[i] = new ParamInfo(null, DataType.KEYWORD);
|
||||
params[i] = new ParamInfo(null, EsType.KEYWORD);
|
||||
}
|
||||
}
|
||||
|
|
@ -3,44 +3,44 @@
|
|||
* 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.net.client;
|
||||
package org.elasticsearch.xpack.sql.jdbc;
|
||||
|
||||
public class RequestMeta {
|
||||
class RequestMeta {
|
||||
|
||||
private int fetchSize;
|
||||
private long timeoutInMs;
|
||||
private long queryTimeoutInMs;
|
||||
|
||||
public RequestMeta(int fetchSize, long timeout, long queryTimeoutInMs) {
|
||||
RequestMeta(int fetchSize, long timeout, long queryTimeoutInMs) {
|
||||
this.fetchSize = fetchSize;
|
||||
this.timeoutInMs = timeout;
|
||||
this.queryTimeoutInMs = queryTimeoutInMs;
|
||||
}
|
||||
|
||||
public RequestMeta queryTimeout(long timeout) {
|
||||
RequestMeta queryTimeout(long timeout) {
|
||||
this.queryTimeoutInMs = timeout;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RequestMeta timeout(long timeout) {
|
||||
RequestMeta timeout(long timeout) {
|
||||
this.timeoutInMs = timeout;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RequestMeta fetchSize(int size) {
|
||||
RequestMeta fetchSize(int size) {
|
||||
this.fetchSize = size;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int fetchSize() {
|
||||
int fetchSize() {
|
||||
return fetchSize;
|
||||
}
|
||||
|
||||
public long timeoutInMs() {
|
||||
long timeoutInMs() {
|
||||
return timeoutInMs;
|
||||
}
|
||||
|
||||
public long queryTimeoutInMs() {
|
||||
long queryTimeoutInMs() {
|
||||
return queryTimeoutInMs;
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
* 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.debug;
|
||||
package org.elasticsearch.xpack.sql.jdbc;
|
||||
|
||||
final class ResultSetMetaDataProxy extends DebuggingInvoker {
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
* 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.debug;
|
||||
package org.elasticsearch.xpack.sql.jdbc;
|
||||
|
||||
import java.sql.ResultSetMetaData;
|
||||
import java.sql.Statement;
|
|
@ -3,7 +3,7 @@
|
|||
* 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;
|
||||
package org.elasticsearch.xpack.sql.jdbc;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
* 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.debug;
|
||||
package org.elasticsearch.xpack.sql.jdbc;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.ParameterMetaData;
|
|
@ -3,9 +3,7 @@
|
|||
* 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;
|
||||
package org.elasticsearch.xpack.sql.jdbc;
|
||||
|
||||
import java.sql.Date;
|
||||
import java.sql.SQLException;
|
||||
|
@ -115,7 +113,7 @@ final class TypeConverter {
|
|||
* Converts object val from columnType to type
|
||||
*/
|
||||
@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) {
|
||||
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,
|
||||
// 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?
|
||||
if (!(type == Long.class && columnType == DataType.DATE) && type.isInstance(val)) {
|
||||
if (!(type == Long.class && columnType == EsType.DATE) && type.isInstance(val)) {
|
||||
try {
|
||||
return type.cast(val);
|
||||
} catch (ClassCastException cce) {
|
||||
|
@ -192,7 +190,7 @@ final class TypeConverter {
|
|||
/**
|
||||
* 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) {
|
||||
case NULL:
|
||||
return null;
|
||||
|
@ -273,18 +271,18 @@ final class TypeConverter {
|
|||
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);
|
||||
}
|
||||
|
||||
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 {
|
||||
String message = format(Locale.ROOT, "Unable to convert value [%.128s] of type [%s] to [%s]", value, columnType,
|
||||
typeString);
|
||||
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) {
|
||||
case BOOLEAN:
|
||||
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) {
|
||||
case BOOLEAN:
|
||||
return Byte.valueOf(((Boolean) val).booleanValue() ? (byte) 1 : (byte) 0);
|
||||
|
@ -331,7 +329,7 @@ final class TypeConverter {
|
|||
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) {
|
||||
case BOOLEAN:
|
||||
return Short.valueOf(((Boolean) val).booleanValue() ? (short) 1 : (short) 0);
|
||||
|
@ -357,7 +355,7 @@ final class TypeConverter {
|
|||
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) {
|
||||
case BOOLEAN:
|
||||
return Integer.valueOf(((Boolean) val).booleanValue() ? 1 : 0);
|
||||
|
@ -383,7 +381,7 @@ final class TypeConverter {
|
|||
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) {
|
||||
case BOOLEAN:
|
||||
return Long.valueOf(((Boolean) val).booleanValue() ? 1 : 0);
|
||||
|
@ -415,7 +413,7 @@ final class TypeConverter {
|
|||
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) {
|
||||
case BOOLEAN:
|
||||
return Float.valueOf(((Boolean) val).booleanValue() ? 1 : 0);
|
||||
|
@ -441,7 +439,7 @@ final class TypeConverter {
|
|||
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) {
|
||||
case BOOLEAN:
|
||||
return Double.valueOf(((Boolean) val).booleanValue() ? 1 : 0);
|
||||
|
@ -467,48 +465,48 @@ final class TypeConverter {
|
|||
return failConversion(val, columnType, typeString, Double.class);
|
||||
}
|
||||
|
||||
private static Date asDate(Object val, DataType columnType, String typeString) throws SQLException {
|
||||
if (columnType == DataType.DATE) {
|
||||
private static Date asDate(Object val, EsType columnType, String typeString) throws SQLException {
|
||||
if (columnType == EsType.DATE) {
|
||||
return new Date(utcMillisRemoveTime(((Number) val).longValue()));
|
||||
}
|
||||
return failConversion(val, columnType, typeString, Date.class);
|
||||
}
|
||||
|
||||
private static Time asTime(Object val, DataType columnType, String typeString) throws SQLException {
|
||||
if (columnType == DataType.DATE) {
|
||||
private static Time asTime(Object val, EsType columnType, String typeString) throws SQLException {
|
||||
if (columnType == EsType.DATE) {
|
||||
return new Time(utcMillisRemoveDate(((Number) val).longValue()));
|
||||
}
|
||||
return failConversion(val, columnType, typeString, Time.class);
|
||||
}
|
||||
|
||||
private static Timestamp asTimestamp(Object val, DataType columnType, String typeString) throws SQLException {
|
||||
if (columnType == DataType.DATE) {
|
||||
private static Timestamp asTimestamp(Object val, EsType columnType, String typeString) throws SQLException {
|
||||
if (columnType == EsType.DATE) {
|
||||
return new Timestamp(((Number) val).longValue());
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -1 +1 @@
|
|||
org.elasticsearch.xpack.sql.jdbc.jdbc.JdbcDriver
|
||||
org.elasticsearch.xpack.sql.jdbc.EsDriver
|
|
@ -3,31 +3,32 @@
|
|||
* 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.net.protocol;
|
||||
package org.elasticsearch.xpack.sql.jdbc;
|
||||
|
||||
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;
|
||||
|
||||
public class ColumnInfoTests extends ESTestCase {
|
||||
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) {
|
||||
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) {
|
||||
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() {
|
||||
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]>",
|
||||
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("int<type=[INTEGER]>", intInfo("int").toString());
|
||||
assertEquals("d<type=[DOUBLE]>", doubleInfo("d").toString());
|
|
@ -7,7 +7,6 @@ package org.elasticsearch.xpack.sql.jdbc;
|
|||
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.xpack.sql.jdbc.jdbc.JdbcDriver;
|
||||
|
||||
import java.security.AccessController;
|
||||
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/";
|
||||
Driver driver = null;
|
||||
try {
|
||||
|
@ -44,7 +43,7 @@ public class DriverManagerRegistrationTests extends ESTestCase {
|
|||
boolean set = driver != null;
|
||||
|
||||
try {
|
||||
JdbcDriver d = JdbcDriver.register();
|
||||
EsDriver d = EsDriver.register();
|
||||
if (driver != null) {
|
||||
assertEquals(driver, d);
|
||||
}
|
||||
|
@ -53,7 +52,7 @@ public class DriverManagerRegistrationTests extends ESTestCase {
|
|||
|
||||
AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> {
|
||||
// mimic DriverManager and unregister the driver
|
||||
JdbcDriver.deregister();
|
||||
EsDriver.deregister();
|
||||
return null;
|
||||
});
|
||||
|
||||
|
@ -61,7 +60,7 @@ public class DriverManagerRegistrationTests extends ESTestCase {
|
|||
assertEquals("No suitable driver", ex.getMessage());
|
||||
} finally {
|
||||
if (set) {
|
||||
JdbcDriver.register();
|
||||
EsDriver.register();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
package org.elasticsearch.xpack.sql.jdbc;
|
||||
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.xpack.sql.jdbc.jdbc.JdbcConfiguration;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.Properties;
|
||||
|
|
|
@ -4,9 +4,10 @@
|
|||
* 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.xpack.sql.jdbc.JdbcDatabaseMetaData;
|
||||
|
||||
public class JdbcDatabaseMetaDataTests extends ESTestCase {
|
||||
|
|
@ -3,10 +3,12 @@
|
|||
* 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;
|
||||
package org.elasticsearch.xpack.sql.jdbc;
|
||||
|
||||
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.nio.charset.StandardCharsets;
|
||||
|
@ -26,17 +28,17 @@ import java.util.Locale;
|
|||
import java.util.Map;
|
||||
|
||||
import static java.lang.String.format;
|
||||
import static org.elasticsearch.xpack.sql.jdbc.type.DataType.BINARY;
|
||||
import static org.elasticsearch.xpack.sql.jdbc.type.DataType.BOOLEAN;
|
||||
import static org.elasticsearch.xpack.sql.jdbc.type.DataType.BYTE;
|
||||
import static org.elasticsearch.xpack.sql.jdbc.type.DataType.DATE;
|
||||
import static org.elasticsearch.xpack.sql.jdbc.type.DataType.DOUBLE;
|
||||
import static org.elasticsearch.xpack.sql.jdbc.type.DataType.FLOAT;
|
||||
import static org.elasticsearch.xpack.sql.jdbc.type.DataType.HALF_FLOAT;
|
||||
import static org.elasticsearch.xpack.sql.jdbc.type.DataType.INTEGER;
|
||||
import static org.elasticsearch.xpack.sql.jdbc.type.DataType.KEYWORD;
|
||||
import static org.elasticsearch.xpack.sql.jdbc.type.DataType.LONG;
|
||||
import static org.elasticsearch.xpack.sql.jdbc.type.DataType.SHORT;
|
||||
import static org.elasticsearch.xpack.sql.jdbc.EsType.BINARY;
|
||||
import static org.elasticsearch.xpack.sql.jdbc.EsType.BOOLEAN;
|
||||
import static org.elasticsearch.xpack.sql.jdbc.EsType.BYTE;
|
||||
import static org.elasticsearch.xpack.sql.jdbc.EsType.DATE;
|
||||
import static org.elasticsearch.xpack.sql.jdbc.EsType.DOUBLE;
|
||||
import static org.elasticsearch.xpack.sql.jdbc.EsType.FLOAT;
|
||||
import static org.elasticsearch.xpack.sql.jdbc.EsType.HALF_FLOAT;
|
||||
import static org.elasticsearch.xpack.sql.jdbc.EsType.INTEGER;
|
||||
import static org.elasticsearch.xpack.sql.jdbc.EsType.KEYWORD;
|
||||
import static org.elasticsearch.xpack.sql.jdbc.EsType.LONG;
|
||||
import static org.elasticsearch.xpack.sql.jdbc.EsType.SHORT;
|
||||
|
||||
public class JdbcPreparedStatementTests extends ESTestCase {
|
||||
|
||||
|
@ -560,10 +562,10 @@ public class JdbcPreparedStatementTests extends ESTestCase {
|
|||
JdbcPreparedStatement jps = createJdbcPreparedStatement();
|
||||
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());
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
|
@ -571,7 +573,7 @@ public class JdbcPreparedStatementTests extends ESTestCase {
|
|||
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;
|
||||
}
|
||||
|
|
@ -3,9 +3,10 @@
|
|||
* 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;
|
||||
package org.elasticsearch.xpack.sql.jdbc;
|
||||
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.xpack.sql.jdbc.SqlQueryParameterAnalyzer;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
|
@ -3,14 +3,13 @@
|
|||
* 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;
|
||||
package org.elasticsearch.xpack.sql.jdbc;
|
||||
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentHelper;
|
||||
import org.elasticsearch.common.xcontent.json.JsonXContent;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.xpack.sql.jdbc.type.DataType;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.ReadableDateTime;
|
||||
|
||||
|
@ -23,16 +22,16 @@ public class TypeConverterTests extends ESTestCase {
|
|||
|
||||
|
||||
public void testFloatAsNative() throws Exception {
|
||||
assertThat(convertAsNative(42.0f, DataType.FLOAT), instanceOf(Float.class));
|
||||
assertThat(convertAsNative(42.0, DataType.FLOAT), instanceOf(Float.class));
|
||||
assertEquals(42.0f, (float) convertAsNative(42.0, DataType.FLOAT), 0.001f);
|
||||
assertEquals(Float.NaN, convertAsNative(Float.NaN, DataType.FLOAT));
|
||||
assertEquals(Float.NEGATIVE_INFINITY, convertAsNative(Float.NEGATIVE_INFINITY, DataType.FLOAT));
|
||||
assertEquals(Float.POSITIVE_INFINITY, convertAsNative(Float.POSITIVE_INFINITY, DataType.FLOAT));
|
||||
assertThat(convertAsNative(42.0f, EsType.FLOAT), instanceOf(Float.class));
|
||||
assertThat(convertAsNative(42.0, EsType.FLOAT), instanceOf(Float.class));
|
||||
assertEquals(42.0f, (float) convertAsNative(42.0, EsType.FLOAT), 0.001f);
|
||||
assertEquals(Float.NaN, convertAsNative(Float.NaN, EsType.FLOAT));
|
||||
assertEquals(Float.NEGATIVE_INFINITY, convertAsNative(Float.NEGATIVE_INFINITY, EsType.FLOAT));
|
||||
assertEquals(Float.POSITIVE_INFINITY, convertAsNative(Float.POSITIVE_INFINITY, EsType.FLOAT));
|
||||
}
|
||||
|
||||
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));
|
||||
assertEquals(42.0f, (double) convertAsNative(42.0, type), 0.001f);
|
||||
assertEquals(Double.NaN, convertAsNative(Double.NaN, type));
|
||||
|
@ -42,11 +41,11 @@ public class TypeConverterTests extends ESTestCase {
|
|||
|
||||
public void testTimestampAsNative() throws Exception {
|
||||
DateTime now = DateTime.now();
|
||||
assertThat(convertAsNative(now, DataType.DATE), instanceOf(Timestamp.class));
|
||||
assertEquals(now.getMillis(), ((Timestamp) convertAsNative(now, DataType.DATE)).getTime());
|
||||
assertThat(convertAsNative(now, EsType.DATE), instanceOf(Timestamp.class));
|
||||
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
|
||||
XContentBuilder builder = JsonXContent.contentBuilder();
|
||||
builder.startObject();
|
||||
|
@ -61,5 +60,4 @@ public class TypeConverterTests extends ESTestCase {
|
|||
Object copy = XContentHelper.convertToMap(BytesReference.bytes(builder), false, builder.contentType()).v2().get("value");
|
||||
return TypeConverter.convert(copy, type, type.toString());
|
||||
}
|
||||
|
||||
}
|
|
@ -8,7 +8,7 @@ package org.elasticsearch.xpack.sql.qa.jdbc;
|
|||
import com.carrotsearch.hppc.IntObjectHashMap;
|
||||
|
||||
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.relique.jdbc.csv.CsvResultSet;
|
||||
|
||||
|
@ -39,10 +39,10 @@ import static org.junit.Assert.fail;
|
|||
*/
|
||||
public class JdbcAssert {
|
||||
|
||||
private static final IntObjectHashMap<DataType> SQL_TO_TYPE = new IntObjectHashMap<>();
|
||||
private static final IntObjectHashMap<EsType> SQL_TO_TYPE = new IntObjectHashMap<>();
|
||||
|
||||
static {
|
||||
for (DataType type : DataType.values()) {
|
||||
for (EsType type : EsType.values()) {
|
||||
SQL_TO_TYPE.putIfAbsent(type.getVendorTypeNumber().intValue(), type);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,8 +13,7 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
|
|||
import org.elasticsearch.common.xcontent.XContentHelper;
|
||||
import org.elasticsearch.common.xcontent.json.JsonXContent;
|
||||
import org.elasticsearch.test.rest.ESRestTestCase;
|
||||
import org.elasticsearch.xpack.sql.jdbc.jdbc.JdbcConfiguration;
|
||||
import org.elasticsearch.xpack.sql.jdbc.jdbcx.JdbcDataSource;
|
||||
import org.elasticsearch.xpack.sql.jdbc.EsDataSource;
|
||||
import org.junit.After;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -61,21 +60,21 @@ public abstract class JdbcIntegrationTestCase extends ESRestTestCase {
|
|||
Connection connection =
|
||||
DriverManager.getConnection(address, connectionProperties);
|
||||
// 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;
|
||||
}
|
||||
|
||||
protected Connection useDataSource() throws SQLException {
|
||||
String elasticsearchAddress = getProtocol() + "://" + elasticsearchAddress();
|
||||
// tag::connect-ds
|
||||
JdbcDataSource dataSource = new JdbcDataSource();
|
||||
EsDataSource dataSource = new EsDataSource();
|
||||
String address = "jdbc:es://" + elasticsearchAddress; // <1>
|
||||
dataSource.setUrl(address);
|
||||
Properties connectionProperties = connectionProperties(); // <2>
|
||||
dataSource.setProperties(connectionProperties);
|
||||
Connection connection = dataSource.getConnection();
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
@ -107,7 +106,7 @@ public abstract class JdbcIntegrationTestCase extends ESRestTestCase {
|
|||
*/
|
||||
protected Properties connectionProperties() {
|
||||
Properties connectionProperties = new Properties();
|
||||
connectionProperties.put(JdbcConfiguration.TIME_ZONE, randomKnownTimeZone());
|
||||
connectionProperties.put("timezone", randomKnownTimeZone());
|
||||
return connectionProperties;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@ public abstract class JdbcTestUtils {
|
|||
|
||||
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 {
|
||||
ResultSetMetaData metaData = rs.getMetaData();
|
||||
// header
|
||||
|
|
|
@ -13,9 +13,8 @@ import org.elasticsearch.common.Strings;
|
|||
import org.elasticsearch.common.collect.Tuple;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.json.JsonXContent;
|
||||
import org.elasticsearch.xpack.sql.jdbc.jdbc.JdbcConfiguration;
|
||||
import org.elasticsearch.xpack.sql.jdbc.jdbcx.JdbcDataSource;
|
||||
import org.elasticsearch.xpack.sql.jdbc.type.DataType;
|
||||
import org.elasticsearch.xpack.sql.jdbc.EsDataSource;
|
||||
import org.elasticsearch.xpack.sql.jdbc.EsType;
|
||||
|
||||
import java.io.IOException;
|
||||
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.SECOND;
|
||||
import static java.util.Calendar.YEAR;
|
||||
import static org.elasticsearch.xpack.sql.qa.jdbc.JdbcTestUtils.JDBC_TIMEZONE;
|
||||
|
||||
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";
|
||||
static final String SELECT_WILDCARD = "SELECT * FROM test";
|
||||
static {
|
||||
dateTimeTestingFields.put(new Tuple<String, Object>("test_boolean", true), DataType.BOOLEAN);
|
||||
dateTimeTestingFields.put(new Tuple<String, Object>("test_byte", 1), DataType.BYTE);
|
||||
dateTimeTestingFields.put(new Tuple<String, Object>("test_integer", 1), DataType.INTEGER);
|
||||
dateTimeTestingFields.put(new Tuple<String, Object>("test_long", 1L), DataType.LONG);
|
||||
dateTimeTestingFields.put(new Tuple<String, Object>("test_short", 1), DataType.SHORT);
|
||||
dateTimeTestingFields.put(new Tuple<String, Object>("test_double", 1d), DataType.DOUBLE);
|
||||
dateTimeTestingFields.put(new Tuple<String, Object>("test_float", 1f), DataType.FLOAT);
|
||||
dateTimeTestingFields.put(new Tuple<String, Object>("test_keyword", "true"), DataType.KEYWORD);
|
||||
dateTimeTestingFields.put(new Tuple<String, Object>("test_boolean", true), EsType.BOOLEAN);
|
||||
dateTimeTestingFields.put(new Tuple<String, Object>("test_byte", 1), EsType.BYTE);
|
||||
dateTimeTestingFields.put(new Tuple<String, Object>("test_integer", 1), EsType.INTEGER);
|
||||
dateTimeTestingFields.put(new Tuple<String, Object>("test_long", 1L), EsType.LONG);
|
||||
dateTimeTestingFields.put(new Tuple<String, Object>("test_short", 1), EsType.SHORT);
|
||||
dateTimeTestingFields.put(new Tuple<String, Object>("test_double", 1d), EsType.DOUBLE);
|
||||
dateTimeTestingFields.put(new Tuple<String, Object>("test_float", 1f), EsType.FLOAT);
|
||||
dateTimeTestingFields.put(new Tuple<String, Object>("test_keyword", "true"), EsType.KEYWORD);
|
||||
}
|
||||
|
||||
// Byte values testing
|
||||
|
@ -1525,24 +1525,24 @@ public class ResultSetTestCase extends JdbcIntegrationTestCase {
|
|||
String elasticsearchAddress = getProtocol() + "://" + elasticsearchAddress();
|
||||
String address = "jdbc:es://" + elasticsearchAddress;
|
||||
Properties connectionProperties = connectionProperties();
|
||||
connectionProperties.put(JdbcConfiguration.TIME_ZONE, timeZoneId);
|
||||
connectionProperties.put(JDBC_TIMEZONE, timeZoneId);
|
||||
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;
|
||||
}
|
||||
|
||||
private Connection useDataSource(String timeZoneId) throws SQLException {
|
||||
String elasticsearchAddress = getProtocol() + "://" + elasticsearchAddress();
|
||||
JdbcDataSource dataSource = new JdbcDataSource();
|
||||
EsDataSource dataSource = new EsDataSource();
|
||||
String address = "jdbc:es://" + elasticsearchAddress;
|
||||
dataSource.setUrl(address);
|
||||
Properties connectionProperties = connectionProperties();
|
||||
connectionProperties.put(JdbcConfiguration.TIME_ZONE, timeZoneId);
|
||||
connectionProperties.put(JDBC_TIMEZONE, timeZoneId);
|
||||
dataSource.setProperties(connectionProperties);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,7 +11,6 @@ import org.elasticsearch.client.ResponseException;
|
|||
import org.elasticsearch.client.RestClient;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.SuppressForbidden;
|
||||
import org.elasticsearch.xpack.sql.jdbc.jdbc.JdbcConfiguration;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
|
||||
|
@ -115,7 +114,7 @@ public abstract class SpecBaseIntegrationTestCase extends JdbcIntegrationTestCas
|
|||
@Override
|
||||
protected Properties connectionProperties() {
|
||||
Properties connectionProperties = new Properties();
|
||||
connectionProperties.setProperty(JdbcConfiguration.TIME_ZONE, "UTC");
|
||||
connectionProperties.setProperty("timezone", "UTC");
|
||||
return connectionProperties;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue