Fix SQL's DatabaseMetaData (elastic/x-pack-elasticsearch#2214)
It was failing because it was missing config needed to properly handle time zones. Original commit: elastic/x-pack-elasticsearch@1166ea7475
This commit is contained in:
parent
e5973ec356
commit
85937c6e78
|
@ -33,6 +33,8 @@ import org.elasticsearch.xpack.sql.net.client.util.StringUtils;
|
|||
|
||||
public class JdbcConnection implements Connection, JdbcWrapper {
|
||||
|
||||
private final String url, userName;
|
||||
final JdbcConfiguration cfg;
|
||||
final JdbcHttpClient client;
|
||||
|
||||
private boolean closed = false;
|
||||
|
@ -40,12 +42,8 @@ public class JdbcConnection implements Connection, JdbcWrapper {
|
|||
private String schema;
|
||||
private Properties clientInfo = new Properties();
|
||||
|
||||
private final JdbcConfiguration info;
|
||||
private final String url, userName;
|
||||
|
||||
|
||||
public JdbcConnection(JdbcConfiguration connectionInfo) {
|
||||
info = connectionInfo;
|
||||
cfg = connectionInfo;
|
||||
client = new JdbcHttpClient(connectionInfo);
|
||||
|
||||
url = connectionInfo.asUrl().toExternalForm();
|
||||
|
@ -61,13 +59,13 @@ public class JdbcConnection implements Connection, JdbcWrapper {
|
|||
@Override
|
||||
public Statement createStatement() throws SQLException {
|
||||
checkOpen();
|
||||
return new JdbcStatement(this, info);
|
||||
return new JdbcStatement(this, cfg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreparedStatement prepareStatement(String sql) throws SQLException {
|
||||
checkOpen();
|
||||
return new JdbcPreparedStatement(this, info, sql);
|
||||
return new JdbcPreparedStatement(this, cfg, sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -117,7 +115,7 @@ public class JdbcConnection implements Connection, JdbcWrapper {
|
|||
public void close() throws SQLException {
|
||||
if (!isClosed()) {
|
||||
closed = true;
|
||||
Debug.release(info);
|
||||
Debug.release(cfg);
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -636,7 +636,8 @@ class JdbcDatabaseMetaData implements DatabaseMetaData, JdbcWrapper {
|
|||
// https://www.postgresql.org/docs/9.0/static/infoschema-routines.html
|
||||
@Override
|
||||
public ResultSet getProcedures(String catalog, String schemaPattern, String procedureNamePattern) throws SQLException {
|
||||
return emptySet("ROUTINES",
|
||||
return emptySet(con.cfg,
|
||||
"ROUTINES",
|
||||
"PROCEDURE_CAT",
|
||||
"PROCEDURE_SCHEM",
|
||||
"PROCEDURE_NAME",
|
||||
|
@ -650,7 +651,8 @@ class JdbcDatabaseMetaData implements DatabaseMetaData, JdbcWrapper {
|
|||
|
||||
@Override
|
||||
public ResultSet getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern, String columnNamePattern) throws SQLException {
|
||||
return emptySet("PARAMETERS",
|
||||
return emptySet(con.cfg,
|
||||
"PARAMETERS",
|
||||
"PROCEDURE_CAT",
|
||||
"PROCEDURE_SCHEM",
|
||||
"PROCEDURE_NAME",
|
||||
|
@ -703,7 +705,7 @@ class JdbcDatabaseMetaData implements DatabaseMetaData, JdbcWrapper {
|
|||
|
||||
// schema and catalogs are not being used, if these are specified return an empty result set
|
||||
if (!isDefaultCatalog(catalog) || !isDefaultSchema(schemaPattern)) {
|
||||
return emptySet(info);
|
||||
return emptySet(con.cfg, info);
|
||||
}
|
||||
|
||||
String cat = defaultCatalog();
|
||||
|
@ -724,7 +726,7 @@ class JdbcDatabaseMetaData implements DatabaseMetaData, JdbcWrapper {
|
|||
row[8] = null;
|
||||
row[9] = null;
|
||||
}
|
||||
return memorySet(info, data);
|
||||
return memorySet(con.cfg, info, data);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -747,7 +749,7 @@ class JdbcDatabaseMetaData implements DatabaseMetaData, JdbcWrapper {
|
|||
@Override
|
||||
public ResultSet getSchemas() throws SQLException {
|
||||
Object[][] data = { { EMPTY, defaultCatalog() } };
|
||||
return memorySet(columnInfo("SCHEMATA",
|
||||
return memorySet(con.cfg, columnInfo("SCHEMATA",
|
||||
"TABLE_SCHEM",
|
||||
"TABLE_CATALOG"), data);
|
||||
}
|
||||
|
@ -758,23 +760,23 @@ class JdbcDatabaseMetaData implements DatabaseMetaData, JdbcWrapper {
|
|||
"TABLE_SCHEM",
|
||||
"TABLE_CATALOG");
|
||||
if (!isDefaultCatalog(catalog) || !isDefaultSchema(schemaPattern)) {
|
||||
return emptySet(info);
|
||||
return emptySet(con.cfg, info);
|
||||
}
|
||||
Object[][] data = { { EMPTY, defaultCatalog() } };
|
||||
return memorySet(info, data);
|
||||
return memorySet(con.cfg, info, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultSet getCatalogs() throws SQLException {
|
||||
Object[][] data = { { defaultCatalog() } };
|
||||
return memorySet(columnInfo("CATALOGS",
|
||||
return memorySet(con.cfg, columnInfo("CATALOGS",
|
||||
"TABLE_CAT"), data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultSet getTableTypes() throws SQLException {
|
||||
Object[][] data = { { "TABLE" } };
|
||||
return memorySet(columnInfo("TABLE_TYPES",
|
||||
return memorySet(con.cfg, columnInfo("TABLE_TYPES",
|
||||
"TABLE_TYPE"), data);
|
||||
}
|
||||
|
||||
|
@ -809,7 +811,7 @@ class JdbcDatabaseMetaData implements DatabaseMetaData, JdbcWrapper {
|
|||
|
||||
// schema and catalogs are not being used, if these are specified return an empty result set
|
||||
if (!isDefaultCatalog(catalog) || !isDefaultSchema(schemaPattern)) {
|
||||
return emptySet(info);
|
||||
return emptySet(con.cfg, info);
|
||||
}
|
||||
|
||||
String cat = defaultCatalog();
|
||||
|
@ -845,7 +847,7 @@ class JdbcDatabaseMetaData implements DatabaseMetaData, JdbcWrapper {
|
|||
row[22] = EMPTY;
|
||||
row[23] = EMPTY;
|
||||
}
|
||||
return memorySet(info, data);
|
||||
return memorySet(con.cfg, info, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -890,7 +892,8 @@ class JdbcDatabaseMetaData implements DatabaseMetaData, JdbcWrapper {
|
|||
|
||||
@Override
|
||||
public ResultSet getTypeInfo() throws SQLException {
|
||||
return emptySet("TYPE_INFO",
|
||||
return emptySet(con.cfg,
|
||||
"TYPE_INFO",
|
||||
"TYPE_NAME",
|
||||
"DATA_TYPE", int.class,
|
||||
"PRECISION", int.class,
|
||||
|
@ -979,7 +982,8 @@ class JdbcDatabaseMetaData implements DatabaseMetaData, JdbcWrapper {
|
|||
|
||||
@Override
|
||||
public ResultSet getUDTs(String catalog, String schemaPattern, String typeNamePattern, int[] types) throws SQLException {
|
||||
return emptySet("USER_DEFINED_TYPES",
|
||||
return emptySet(con.cfg,
|
||||
"USER_DEFINED_TYPES",
|
||||
"TYPE_CAT",
|
||||
"TYPE_SCHEM",
|
||||
"TYPE_NAME",
|
||||
|
@ -1016,7 +1020,8 @@ class JdbcDatabaseMetaData implements DatabaseMetaData, JdbcWrapper {
|
|||
|
||||
@Override
|
||||
public ResultSet getSuperTypes(String catalog, String schemaPattern, String typeNamePattern) throws SQLException {
|
||||
return emptySet("SUPER_TYPES",
|
||||
return emptySet(con.cfg,
|
||||
"SUPER_TYPES",
|
||||
"TYPE_CAT",
|
||||
"TYPE_SCHEM",
|
||||
"TYPE_NAME",
|
||||
|
@ -1028,7 +1033,7 @@ class JdbcDatabaseMetaData implements DatabaseMetaData, JdbcWrapper {
|
|||
|
||||
@Override
|
||||
public ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern) throws SQLException {
|
||||
return emptySet("SUPER_TABLES",
|
||||
return emptySet(con.cfg, "SUPER_TABLES",
|
||||
"TABLE_CAT",
|
||||
"TABLE_SCHEM",
|
||||
"TABLE_NAME",
|
||||
|
@ -1037,7 +1042,8 @@ class JdbcDatabaseMetaData implements DatabaseMetaData, JdbcWrapper {
|
|||
|
||||
@Override
|
||||
public ResultSet getAttributes(String catalog, String schemaPattern, String typeNamePattern, String attributeNamePattern) throws SQLException {
|
||||
return emptySet("ATTRIBUTES",
|
||||
return emptySet(con.cfg,
|
||||
"ATTRIBUTES",
|
||||
"TYPE_CAT",
|
||||
"TYPE_SCHEM",
|
||||
"TYPE_NAME",
|
||||
|
@ -1128,7 +1134,8 @@ class JdbcDatabaseMetaData implements DatabaseMetaData, JdbcWrapper {
|
|||
|
||||
@Override
|
||||
public ResultSet getFunctions(String catalog, String schemaPattern, String functionNamePattern) throws SQLException {
|
||||
return emptySet("FUNCTIONS",
|
||||
return emptySet(con.cfg,
|
||||
"FUNCTIONS",
|
||||
"FUNCTION_CAT",
|
||||
"FUNCTION_SCHEM",
|
||||
"FUNCTION_NAME",
|
||||
|
@ -1139,7 +1146,8 @@ class JdbcDatabaseMetaData implements DatabaseMetaData, JdbcWrapper {
|
|||
|
||||
@Override
|
||||
public ResultSet getFunctionColumns(String catalog, String schemaPattern, String functionNamePattern, String columnNamePattern) throws SQLException {
|
||||
return emptySet("FUNCTION_COLUMNS",
|
||||
return emptySet(con.cfg,
|
||||
"FUNCTION_COLUMNS",
|
||||
"FUNCTION_CAT",
|
||||
"FUNCTION_SCHEM",
|
||||
"FUNCTION_NAME",
|
||||
|
@ -1160,7 +1168,8 @@ class JdbcDatabaseMetaData implements DatabaseMetaData, JdbcWrapper {
|
|||
|
||||
@Override
|
||||
public ResultSet getPseudoColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException {
|
||||
return emptySet("PSEUDO_COLUMNS",
|
||||
return emptySet(con.cfg,
|
||||
"PSEUDO_COLUMNS",
|
||||
"TABLE_CAT",
|
||||
"TABLE_SCHEM",
|
||||
"TABLE_NAME",
|
||||
|
@ -1204,16 +1213,16 @@ class JdbcDatabaseMetaData implements DatabaseMetaData, JdbcWrapper {
|
|||
return columns;
|
||||
}
|
||||
|
||||
private static ResultSet emptySet(String tableName, Object... cols) {
|
||||
return new JdbcResultSet(null, new InMemoryCursor(columnInfo(tableName, cols), null));
|
||||
private static ResultSet emptySet(JdbcConfiguration cfg, String tableName, Object... cols) {
|
||||
return new JdbcResultSet(cfg, null, new InMemoryCursor(columnInfo(tableName, cols), null));
|
||||
}
|
||||
|
||||
private static ResultSet emptySet(List<ColumnInfo> columns) {
|
||||
return memorySet(columns, null);
|
||||
private static ResultSet emptySet(JdbcConfiguration cfg, List<ColumnInfo> columns) {
|
||||
return memorySet(cfg, columns, null);
|
||||
}
|
||||
|
||||
private static ResultSet memorySet(List<ColumnInfo> columns, Object[][] data) {
|
||||
return new JdbcResultSet(null, new InMemoryCursor(columns, data));
|
||||
private static ResultSet memorySet(JdbcConfiguration cfg, List<ColumnInfo> columns, Object[][] data) {
|
||||
return new JdbcResultSet(cfg, null, new InMemoryCursor(columns, data));
|
||||
}
|
||||
|
||||
static class InMemoryCursor implements Cursor {
|
||||
|
|
|
@ -7,6 +7,7 @@ package org.elasticsearch.xpack.sql.jdbc.jdbc;
|
|||
|
||||
import org.elasticsearch.xpack.sql.jdbc.net.client.Cursor;
|
||||
import org.elasticsearch.xpack.sql.jdbc.net.protocol.ColumnInfo;
|
||||
import org.elasticsearch.xpack.sql.protocol.shared.Nullable;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
|
@ -54,11 +55,12 @@ class JdbcResultSet implements ResultSet, JdbcWrapper {
|
|||
|
||||
private int rowNumber;
|
||||
|
||||
JdbcResultSet(JdbcStatement statement, Cursor cursor) {
|
||||
JdbcResultSet(JdbcConfiguration cfg, @Nullable JdbcStatement statement, Cursor cursor) {
|
||||
this.statement = statement;
|
||||
this.cursor = cursor;
|
||||
// statement can be null so we have to extract the timeZone from the non-nullable cfg
|
||||
// TODO: should we consider the locale as well?
|
||||
this.defaultCalendar = Calendar.getInstance(statement.cfg.timeZone(), Locale.ROOT);
|
||||
this.defaultCalendar = Calendar.getInstance(cfg.timeZone(), Locale.ROOT);
|
||||
|
||||
List<ColumnInfo> columns = cursor.columns();
|
||||
for (int i = 0; i < columns.size(); i++) {
|
||||
|
|
|
@ -156,7 +156,7 @@ class JdbcStatement implements Statement, JdbcWrapper {
|
|||
closeResultSet();
|
||||
|
||||
Cursor cursor = con.client.query(sql, requestMeta);
|
||||
rs = new JdbcResultSet(this, cursor);
|
||||
rs = new JdbcResultSet(cfg, this, cursor);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
*/
|
||||
package org.elasticsearch.xpack.sql.jdbc;
|
||||
|
||||
import org.apache.lucene.util.LuceneTestCase.AwaitsFix;
|
||||
import org.elasticsearch.common.CheckedSupplier;
|
||||
import org.elasticsearch.xpack.sql.jdbc.framework.JdbcIntegrationTestCase;
|
||||
import org.elasticsearch.xpack.sql.jdbc.framework.LocalH2;
|
||||
|
@ -20,7 +19,6 @@ import static org.elasticsearch.xpack.sql.jdbc.framework.JdbcAssert.assertResult
|
|||
/**
|
||||
* Tests for our implementation of {@link DatabaseMetaData}.
|
||||
*/
|
||||
@AwaitsFix(bugUrl = "https://github.com/elastic/x-pack-elasticsearch/issues/2074")
|
||||
public class DatabaseMetaDataIT extends JdbcIntegrationTestCase {
|
||||
/**
|
||||
* We do not support procedures so we return an empty set for
|
||||
|
|
|
@ -22,7 +22,7 @@ CREATE TABLE mock (
|
|||
SOURCE_DATA_TYPE SMALLINT,
|
||||
IS_AUTOINCREMENT VARCHAR,
|
||||
IS_GENERATEDCOLUMN VARCHAR
|
||||
) AS SELECT '', 'test.doc', 'name', 12, 'VARCHAR', 1, null, null,
|
||||
) AS SELECT '', 'test', 'name', 12, 'VARCHAR', 1, null, null,
|
||||
10, -- NOCOMMIT 10 seem wrong to hard code for stuff like strings
|
||||
2, -- columnNullableUnknown NOCOMMIT I think it'd be more correct to return columnNullable
|
||||
null, null, null, null, null, 1, '', null, null, null, null, '', ''
|
||||
|
|
|
@ -8,4 +8,4 @@ CREATE TABLE mock (
|
|||
TYPE_NAME VARCHAR,
|
||||
SELF_REFERENCING_COL_NAME VARCHAR,
|
||||
REF_GENERATION VARCHAR
|
||||
) AS SELECT '', 'test.doc', 'TABLE', '', null, null, null, null, null FROM DUAL;
|
||||
) AS SELECT '', 'test', 'TABLE', '', null, null, null, null, null FROM DUAL;
|
||||
|
|
Loading…
Reference in New Issue