Polishing for handling subtleties in the JDBC behavior: (elastic/x-pack-elasticsearch#2967)

1. decouple JdbcDriver from other classes to not trigger static
initialization (this happens through JDBC service discovery)
2. reduce visibility of JdbcDriver#close so only on jar unloading it
gets triggered
3. mark 3 methods introduced in Jdbc 4.1 as unsupported (their semantics
are somewhat weird)
4. Move versioning info in one class
5. Hook Version class in both JDBC entry points to perform cp sanity
checks
6. Remove JdbcDataSource#close (DebugLog are closed when the Driver gets
unloaded by the DriverManager) as there can be multiple instances of DS
but only one for Driver known by the DriverManager

Replace Strings with constants
Properly set TZ in security tests as well
JdbcDataSource is more defensive with its internal properties
JdbcConfiguration password parameter is aligned with JDBC DriverManager
Remove usage of JdbcConnection API
Removed JdbcConnection#setTimeZone - this encourages folks to use our
private API which would tie us down.
It is somewhat limiting for folks but it has less downsides overall and
does not trip debugging (which adds a proxy unaware of this method).
Update docs
Add JdbcDataSource into the Jdbc suite

Original commit: elastic/x-pack-elasticsearch@c713665d53
This commit is contained in:
Costin Leau 2017-11-15 00:29:41 +02:00 committed by GitHub
parent 1a434636fe
commit 94d0a2d1ee
22 changed files with 264 additions and 136 deletions

View File

@ -3,17 +3,34 @@
== SQL JDBC
Elasticsearch's SQL jdbc driver is a fully featured JDBC driver
for Elasticsearch. You can connect to it with:
for Elasticsearch. You can connect to it using the two APIs offered
by JDBC, namely `java.sql.Driver` and `DriverManager`:
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{jdbc-tests}/JdbcIntegrationTestCase.java[connect]
include-tagged::{jdbc-tests}/JdbcIntegrationTestCase.java[connect-dm]
--------------------------------------------------
<1> The server and port on which Elasticsearch is listening for
HTTP traffic. The port is usually 9200.
<2> Properties for connecting to Elasticsearch. An empty `Properties`
instance is fine for unsecured Elasticsearch.
or `javax.sql.DataSource` through
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{jdbc-tests}/JdbcIntegrationTestCase.java[connect-ds]
--------------------------------------------------
<1> The server and port on which Elasticsearch is listening for
HTTP traffic. The port is usually 9200.
<2> Properties for connecting to Elasticsearch. An empty `Properties`
instance is fine for unsecured Elasticsearch.
Which one to use? Typically client applications that provide most
configuration parameters in the URL rely on the `DriverManager`-style
while `DataSource` is preferred when being _passed_ around since it can be
configured in one place and the consumer only has to call `getConnection`
without having to worry about any other parameters.
To connect to a secured Elasticsearch server the `Properties`
should look like:

View File

@ -22,6 +22,8 @@ public class JdbcCsvSpecIT extends CsvSpecTestCase {
@Override
protected Properties connectionProperties() {
return JdbcSecurityIT.adminProperties();
Properties sp = super.connectionProperties();
sp.putAll(JdbcSecurityIT.adminProperties());
return sp;
}
}

View File

@ -27,7 +27,7 @@ public class JdbcSecurityIT extends SqlSecurityTestCase {
// tag::admin_properties
Properties properties = new Properties();
properties.put("user", "test_admin");
properties.put("pass", "x-pack-test-password");
properties.put("password", "x-pack-test-password");
// end::admin_properties
return properties;
}
@ -42,7 +42,7 @@ public class JdbcSecurityIT extends SqlSecurityTestCase {
}
Properties prop = new Properties();
prop.put("user", user);
prop.put("pass", "testpass");
prop.put("password", "testpass");
return prop;
}

View File

@ -18,6 +18,8 @@ public class JdbcShowTablesIT extends ShowTablesTestCase {
@Override
protected Properties connectionProperties() {
return JdbcSecurityIT.adminProperties();
Properties sp = super.connectionProperties();
sp.putAll(JdbcSecurityIT.adminProperties());
return sp;
}
}

View File

@ -22,6 +22,8 @@ public class JdbcSqlSpecIT extends SqlSpecTestCase {
@Override
protected Properties connectionProperties() {
return JdbcSecurityIT.adminProperties();
Properties sp = super.connectionProperties();
sp.putAll(JdbcSecurityIT.adminProperties());
return sp;
}
}

View File

@ -72,8 +72,10 @@ public class EmbeddedJdbcServer extends ExternalResource {
server = null;
}
public Connection connection() throws SQLException {
public Connection connection(Properties props) throws SQLException {
assertNotNull("ES JDBC Server is null - make sure ES is properly run as a @ClassRule", server);
return DriverManager.getConnection(jdbcUrl, properties);
Properties p = new Properties(properties);
p.putAll(props);
return DriverManager.getConnection(jdbcUrl, p);
}
}

View File

@ -10,7 +10,7 @@ import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.collect.Tuple;
import org.elasticsearch.common.io.Streams;
import org.elasticsearch.xpack.sql.jdbc.jdbc.JdbcConnection;
import org.elasticsearch.xpack.sql.jdbc.jdbc.JdbcConfiguration;
import org.elasticsearch.xpack.sql.util.CollectionUtils;
import org.relique.io.TableReader;
import org.relique.jdbc.csv.CsvConnection;
@ -28,7 +28,6 @@ import java.sql.Statement;
import java.util.List;
import java.util.Locale;
import java.util.Properties;
import java.util.TimeZone;
import static org.hamcrest.Matchers.arrayWithSize;
@ -83,9 +82,6 @@ public abstract class CsvSpecTestCase extends SpecBaseIntegrationTestCase {
try (Connection csv = new CsvConnection(tableReader, csvProperties, "") {};
Connection es = esJdbc()) {
// make sure ES uses UTC (otherwise JDBC driver picks up the JVM timezone per spec/convention)
((JdbcConnection) es).setTimeZone(TimeZone.getTimeZone("UTC"));
// pass the testName as table for debugging purposes (in case the underlying reader is missing)
ResultSet expected = csv.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY)
.executeQuery("SELECT * FROM " + csvTableName);
@ -96,6 +92,14 @@ public abstract class CsvSpecTestCase extends SpecBaseIntegrationTestCase {
}
}
// make sure ES uses UTC (otherwise JDBC driver picks up the JVM timezone per spec/convention)
@Override
protected Properties connectionProperties() {
Properties connectionProperties = new Properties();
connectionProperties.setProperty(JdbcConfiguration.TIME_ZONE, "UTC");
return connectionProperties;
}
private Tuple<String,String> extractColumnTypes(String expectedResults) throws IOException {
try (StringReader reader = new StringReader(expectedResults)){
try (BufferedReader bufferedReader = new BufferedReader(reader)){

View File

@ -17,6 +17,7 @@ import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.xpack.qa.sql.embed.EmbeddedJdbcServer;
import org.elasticsearch.xpack.sql.jdbc.jdbc.JdbcConfiguration;
import org.elasticsearch.xpack.sql.jdbc.jdbcx.JdbcDataSource;
import org.joda.time.DateTimeZone;
import org.junit.ClassRule;
@ -64,13 +65,28 @@ public abstract class JdbcIntegrationTestCase extends ESRestTestCase {
public Connection esJdbc() throws SQLException {
if (EMBED_SQL) {
return EMBEDDED_SERVER.connection();
return EMBEDDED_SERVER.connection(connectionProperties());
}
// tag::connect
return randomBoolean() ? useDriverManager() : useDataSource();
}
protected Connection useDriverManager() throws SQLException {
// tag::connect-dm
String address = "jdbc:es://" + elasticsearchAddress(); // <1>
Properties connectionProperties = connectionProperties(); // <2>
return DriverManager.getConnection(address, connectionProperties);
// end::connect
// end::connect-dm
}
protected Connection useDataSource() throws SQLException {
// tag::connect-ds
JdbcDataSource dataSource = new JdbcDataSource();
String address = "jdbc:es://" + elasticsearchAddress(); // <1>
dataSource.setUrl(address);
Properties connectionProperties = connectionProperties(); // <2>
dataSource.setProperties(connectionProperties);
return dataSource.getConnection();
// end::connect-ds
}
public static void index(String index, CheckedConsumer<XContentBuilder, IOException> body) throws IOException {
@ -110,5 +126,4 @@ public abstract class JdbcIntegrationTestCase extends ESRestTestCase {
Collections.sort(ids);
return randomFrom(ids);
}
}

View File

@ -7,14 +7,14 @@ package org.elasticsearch.xpack.qa.sql.jdbc;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.xpack.sql.jdbc.jdbc.JdbcConnection;
import org.elasticsearch.xpack.sql.jdbc.jdbc.JdbcConfiguration;
import org.elasticsearch.xpack.sql.util.CollectionUtils;
import org.junit.ClassRule;
import java.sql.Connection;
import java.sql.ResultSet;
import java.util.List;
import java.util.TimeZone;
import java.util.Properties;
/**
* Tests comparing sql queries executed against our jdbc client
@ -68,9 +68,6 @@ public abstract class SqlSpecTestCase extends SpecBaseIntegrationTestCase {
try (Connection h2 = H2.get();
Connection es = esJdbc()) {
// TODO: use UTC for now until deciding on a strategy for handling date extraction
((JdbcConnection) es).setTimeZone(TimeZone.getTimeZone("UTC"));
ResultSet expected, elasticResults;
expected = executeJdbcQuery(h2, query);
elasticResults = executeJdbcQuery(es, query);
@ -78,4 +75,12 @@ public abstract class SqlSpecTestCase extends SpecBaseIntegrationTestCase {
assertResults(expected, elasticResults);
}
}
// TODO: use UTC for now until deciding on a strategy for handling date extraction
@Override
protected Properties connectionProperties() {
Properties connectionProperties = new Properties();
connectionProperties.setProperty(JdbcConfiguration.TIME_ZONE, "UTC");
return connectionProperties;
}
}

View File

@ -5,11 +5,11 @@
*/
package org.elasticsearch.xpack.sql.cli;
import org.elasticsearch.xpack.sql.cli.net.protocol.QueryResponse;
import org.elasticsearch.xpack.sql.cli.net.protocol.Proto.ResponseType;
import org.elasticsearch.xpack.sql.cli.net.protocol.QueryResponse;
import org.elasticsearch.xpack.sql.client.shared.IOUtils;
import org.elasticsearch.xpack.sql.client.shared.SuppressForbidden;
import org.elasticsearch.xpack.sql.client.shared.StringUtils;
import org.elasticsearch.xpack.sql.client.shared.SuppressForbidden;
import org.elasticsearch.xpack.sql.protocol.shared.AbstractQueryInitRequest;
import org.elasticsearch.xpack.sql.protocol.shared.Response;
import org.jline.reader.EndOfFileException;
@ -87,8 +87,8 @@ public class Cli {
password = new BufferedReader(term.reader()).readLine();
term.echo(true);
}
properties.setProperty("user", user);
properties.setProperty("pass", password);
properties.setProperty(CliConfiguration.AUTH_USER, user);
properties.setProperty(CliConfiguration.AUTH_PASS, password);
}
boolean debug = StringUtils.parseBoolean(System.getProperty("cli.debug", "false"));

View File

@ -8,6 +8,7 @@ package org.elasticsearch.xpack.sql.jdbc.jdbc;
import org.elasticsearch.xpack.sql.client.shared.ConnectionConfiguration;
import org.elasticsearch.xpack.sql.client.shared.StringUtils;
import org.elasticsearch.xpack.sql.jdbc.JdbcSQLException;
import org.elasticsearch.xpack.sql.jdbc.util.Version;
import java.net.MalformedURLException;
import java.net.URL;
@ -53,6 +54,14 @@ public class JdbcConfiguration extends ConnectionConfiguration {
// options that don't change at runtime
private static final Set<String> OPTION_NAMES = new LinkedHashSet<>(Arrays.asList(TIME_ZONE, DEBUG, DEBUG_OUTPUT));
static {
// trigger version initialization
// typically this should have already happened but in case the
// JdbcDriver/JdbcDataSource are not used and the impl. classes used directly
// this covers that case
Version.version();
}
// immutable properties
private final HostAndPort hostAndPort;
private final String originalUrl;

View File

@ -27,7 +27,6 @@ import java.sql.Statement;
import java.sql.Struct;
import java.util.Map;
import java.util.Properties;
import java.util.TimeZone;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
@ -384,26 +383,17 @@ public class JdbcConnection implements Connection, JdbcWrapper {
@Override
public void abort(Executor executor) throws SQLException {
if (executor == null) {
throw new SQLException("Null executor");
}
close();
throw new SQLFeatureNotSupportedException();
}
@Override
public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {
if (executor == null) {
throw new SQLException("Null executor");
}
if (milliseconds < 0) {
throw new SQLException("Negative milliseconds");
}
client.setNetworkTimeout(milliseconds);
throw new SQLFeatureNotSupportedException();
}
@Override
public int getNetworkTimeout() throws SQLException {
return (int) client.getNetworkTimeout();
throw new SQLFeatureNotSupportedException();
}
private void checkResultSet(int resultSetType, int resultSetConcurrency) throws SQLException {
@ -440,8 +430,4 @@ public class JdbcConnection implements Connection, JdbcWrapper {
int esInfoMinorVersion() throws SQLException {
return client.serverInfo().minorVersion;
}
public void setTimeZone(TimeZone tz) {
cfg.timeZone(tz);
}
}

View File

@ -1082,12 +1082,12 @@ class JdbcDatabaseMetaData implements DatabaseMetaData, JdbcWrapper {
@Override
public int getJDBCMajorVersion() throws SQLException {
return JdbcDriver.jdbcMajorVersion();
return Version.jdbcMajorVersion();
}
@Override
public int getJDBCMinorVersion() throws SQLException {
return JdbcDriver.jdbcMinorVersion();
return Version.jdbcMinorVersion();
}
@Override

View File

@ -9,7 +9,6 @@ import org.elasticsearch.xpack.sql.jdbc.JdbcSQLException;
import org.elasticsearch.xpack.sql.jdbc.debug.Debug;
import org.elasticsearch.xpack.sql.jdbc.util.Version;
import java.io.Closeable;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
@ -20,24 +19,30 @@ import java.util.Properties;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
public class JdbcDriver implements java.sql.Driver, Closeable {
public class JdbcDriver implements java.sql.Driver {
private static final JdbcDriver INSTANCE = new JdbcDriver();
static {
// invoke Version to perform classpath/jar sanity checks
Version.version();
try {
register();
} catch (SQLException ex) {
// the SQLException is bogus as there's no source for it
// but we handle it just in case
PrintWriter writer = DriverManager.getLogWriter();
if (writer != null) {
ex.printStackTrace(writer);
writer.flush();
}
throw new ExceptionInInitializerError(ex);
}
}
public static JdbcDriver register() throws SQLException {
// no closing callback
DriverManager.registerDriver(INSTANCE, INSTANCE::close);
return INSTANCE;
}
@ -51,19 +56,12 @@ public class JdbcDriver implements java.sql.Driver, Closeable {
PrintWriter writer = DriverManager.getLogWriter();
if (writer != null) {
ex.printStackTrace(writer);
writer.flush();
}
throw ex;
}
}
public static int jdbcMajorVersion() {
return 4;
}
public static int jdbcMinorVersion() {
return 2;
}
//
// Jdbc 4.0
//
@ -126,9 +124,12 @@ public class JdbcDriver implements java.sql.Driver, Closeable {
throw new SQLFeatureNotSupportedException();
}
@Override
public void close() {
// TODO: clean-up resources
/**
* Cleanup method invoked by the DriverManager when unregistering the driver.
* Since this happens typically when the JDBC driver gets unloaded (from the classloader)
* cleaning all debug information is a good safety check.
*/
private void close() {
Debug.close();
}
}

View File

@ -9,8 +9,8 @@ import org.elasticsearch.xpack.sql.client.shared.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.jdbc.util.Version;
import java.io.Closeable;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
@ -22,7 +22,11 @@ import java.util.logging.Logger;
import javax.sql.DataSource;
public class JdbcDataSource implements DataSource, Wrapper, Closeable {
public class JdbcDataSource implements DataSource, Wrapper {
static {
Version.version();
}
private String url;
private PrintWriter writer;
@ -68,26 +72,26 @@ public class JdbcDataSource implements DataSource, Wrapper, Closeable {
}
public Properties getProperties() {
return props;
Properties copy = new Properties();
if (props != null) {
copy.putAll(props);
}
return copy;
}
public void setProperties(Properties props) {
this.props = props;
}
private Properties createConfig() {
Properties p = props != null ? new Properties(props) : new Properties();
return p;
this.props = new Properties();
this.props.putAll(props);
}
@Override
public Connection getConnection() throws SQLException {
return doGetConnection(props);
return doGetConnection(getProperties());
}
@Override
public Connection getConnection(String username, String password) throws SQLException {
Properties p = createConfig();
Properties p = getProperties();
p.setProperty(ConnectionConfiguration.AUTH_USER, username);
p.setProperty(ConnectionConfiguration.AUTH_PASS, password);
return doGetConnection(p);
@ -100,7 +104,7 @@ public class JdbcDataSource implements DataSource, Wrapper, Closeable {
}
JdbcConnection con = new JdbcConnection(cfg);
// enable logging if needed
return Debug.proxy(cfg, con, writer);
return cfg.debug() ? Debug.proxy(cfg, con, writer) : con;
}
@Override
@ -116,9 +120,4 @@ public class JdbcDataSource implements DataSource, Wrapper, Closeable {
}
throw new SQLException();
}
@Override
public void close() {
Debug.close();
}
}

View File

@ -21,8 +21,17 @@ public abstract class Version {
private static final String VER;
private static final String SHORT_HASH;
private static final int VER_MAJ, VER_MIN;
private static final int VER_MAJ, VER_MIN, VER_REV;
static int[] from(String ver) {
String[] parts = ver.split("[.-]");
if (parts.length == 3 || parts.length == 4) {
return new int[] { Integer.parseInt(parts[0]), Integer.parseInt(parts[1]), Integer.parseInt(parts[2]) };
}
else {
throw new Error("Detected Elasticsearch SQL JDBC driver but found invalid version " + ver);
}
}
static {
// check classpath
@ -32,8 +41,7 @@ public abstract class Version {
try {
res = Version.class.getClassLoader().getResources(target);
} catch (IOException ex) {
// LogFactory.getLog(Version.class)
// .warn("Cannot detect Elasticsearch JDBC driver jar; it typically indicates a deployment issue...");
throw new Error("Cannot detect Elasticsearch SQL JDBC driver jar; it typically indicates a deployment issue...");
}
if (res != null) {
@ -47,7 +55,7 @@ public abstract class Version {
int foundJars = 0;
if (normalized.size() > 1) {
StringBuilder sb = new StringBuilder(
"Multiple Elasticsearch JDBC driver versions detected in the classpath; please use only one\n");
"Multiple Elasticsearch SQL JDBC driver versions detected in the classpath; please use only one\n");
for (String s : normalized) {
if (s.contains("jar:")) {
foundJars++;
@ -56,32 +64,37 @@ public abstract class Version {
}
}
if (foundJars > 1) {
// LogFactory.getLog(Version.class).fatal(sb);
throw new Error(sb.toString());
}
}
}
// This is similar to how Elasticsearch's Build class digs up its build information.
// Since version info is not critical, the parsing is lenient
URL url = Version.class.getProtectionDomain().getCodeSource().getLocation();
String urlStr = url.toString();
int maj = 0, min = 0, rev = 0;
String ver = "Unknown";
String hash = ver;
if (urlStr.startsWith("file:/") && (urlStr.endsWith(".jar") || urlStr.endsWith("-SNAPSHOT.jar"))) {
try (JarInputStream jar = new JarInputStream(url.openStream())) {
Manifest manifest = jar.getManifest();
VER = manifest.getMainAttributes().getValue("X-Compile-Elasticsearch-Version");
int sep = VER.indexOf('.');
VER_MAJ = Integer.parseInt(VER.substring(0, sep - 1));
VER_MIN = Integer.parseInt(VER.substring(sep, VER.indexOf(sep, '.') - 1));
SHORT_HASH = manifest.getMainAttributes().getValue("Change");
} catch (IOException e) {
throw new RuntimeException("error finding version of driver", e);
hash = manifest.getMainAttributes().getValue("Change");
int[] vers = from(manifest.getMainAttributes().getValue("X-Compile-Elasticsearch-Version"));
maj = vers[0];
min = vers[1];
rev = vers[2];
} catch (Exception ex) {
throw new Error("Detected Elasticsearch SQL JDBC driver but cannot retrieve its version", ex);
}
} else {
VER_MAJ = 0;
VER_MIN = 0;
VER = "Unknown";
SHORT_HASH = "Unknown";
}
VER_MAJ = maj;
VER_MIN = min;
VER_REV = rev;
VER = ver;
SHORT_HASH = hash;
}
public static int versionMajor() {
@ -92,15 +105,27 @@ public abstract class Version {
return VER_MIN;
}
public static int versionRevision() {
return VER_REV;
}
public static String version() {
return "v" + versionNumber() + " [" + versionHashShort() + "]";
return "v" + versionNumber() + " [" + versionHash() + "]";
}
public static String versionNumber() {
return VER;
}
public static String versionHashShort() {
public static String versionHash() {
return SHORT_HASH;
}
public static int jdbcMajorVersion() {
return 4;
}
public static int jdbcMinorVersion() {
return 2;
}
}

View File

@ -1,18 +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;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xpack.sql.jdbc.util.BytesArray;
public class BytesArrayTests extends ESTestCase {
public void testToString() {
assertEquals("01020af6", new BytesArray(new byte[] {1, 2, 10, -10}).toString());
assertEquals("", new BytesArray(new byte[] {}).toString());
}
}

View File

@ -0,0 +1,49 @@
/*
* 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 org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xpack.sql.jdbc.jdbc.JdbcDriver;
import java.security.AccessController;
import java.security.PrivilegedExceptionAction;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DriverManagerRegistrationTests extends ESTestCase {
public void testRegistration() throws Exception {
String url = "jdbc:es:localhost:9200/";
Driver driver = null;
try {
// can happen (if the driver jar was not loaded)
driver = DriverManager.getDriver(url);
} catch (SQLException ex) {
assertEquals("No suitable driver", ex.getMessage());
}
boolean set = driver != null;
try {
Driver d = JdbcDriver.register();
if (driver != null) {
assertEquals(driver, d);
}
AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> {
// mimic DriverManager and unregister the driver
JdbcDriver.deregister();
return null;
});
SQLException ex = expectThrows(SQLException.class, () -> DriverManager.getDriver(url));
assertEquals("No suitable driver", ex.getMessage());
} finally {
if (set) {
JdbcDriver.register();
}
}
}
}

View File

@ -1,19 +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;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xpack.sql.jdbc.util.Version;
public class VersionTests extends ESTestCase {
public void testVersionIsUnknownWithoutAJar() {
// We aren't running in a jar so we have a bunch of "Unknown"
assertEquals("Unknown", Version.versionNumber());
assertEquals("Unknown", Version.versionHashShort());
assertEquals(0, Version.versionMajor());
assertEquals(0, Version.versionMinor());
}
}

View File

@ -0,0 +1,44 @@
/*
* 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.util;
import org.elasticsearch.test.ESTestCase;
public class VersionTests extends ESTestCase {
public void testVersionIsUnknownWithoutAJar() {
// We aren't running in a jar so we have a bunch of "Unknown"
assertEquals("Unknown", Version.versionNumber());
assertEquals("Unknown", Version.versionHash());
assertEquals(0, Version.versionMajor());
assertEquals(0, Version.versionMinor());
}
public void test70Version() {
int[] ver = Version.from("7.0.0-alpha");
assertEquals(7, ver[0]);
assertEquals(0, ver[1]);
assertEquals(0, ver[2]);
}
public void test712Version() {
int[] ver = Version.from("7.1.2");
assertEquals(7, ver[0]);
assertEquals(1, ver[1]);
assertEquals(2, ver[2]);
}
public void testCurrent() {
int[] ver = Version.from(org.elasticsearch.Version.CURRENT.toString());
assertEquals(org.elasticsearch.Version.CURRENT.major, ver[0]);
assertEquals(org.elasticsearch.Version.CURRENT.minor, ver[1]);
assertEquals(org.elasticsearch.Version.CURRENT.revision, ver[2]);
}
public void testInvalidVersion() {
Error err = expectThrows(Error.class, () -> Version.from("7.1"));
assertEquals("Detected Elasticsearch SQL JDBC driver but found invalid version 7.1", err.getMessage());
}
}

View File

@ -0,0 +1,4 @@
grant {
// Required for testing the Driver registration
permission java.sql.SQLPermission "deregisterDriver";
};

View File

@ -5,8 +5,6 @@
*/
package org.elasticsearch.xpack.sql.client.shared;
import org.elasticsearch.xpack.sql.client.shared.StringUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@ -72,7 +70,8 @@ public class ConnectionConfiguration {
// Auth
public static final String AUTH_USER = "user";
public static final String AUTH_PASS = "pass";
// NB: this is password instead of pass since that's what JDBC DriverManager/tools use
public static final String AUTH_PASS = "password";
protected static final Set<String> OPTION_NAMES = new LinkedHashSet<>(
Arrays.asList(CONNECT_TIMEOUT, NETWORK_TIMEOUT, QUERY_TIMEOUT, PAGE_TIMEOUT, PAGE_SIZE, AUTH_USER, AUTH_PASS));