SQL: Prefer resultSets over exceptions in metadata (#40641)
Changed the JDBC metadata to return empty results sets instead of throwing SQLFeatureNotSupported as it seems a more safer/compatible approach for consumers. Fix #40533 (cherry picked from commit ef2d2527c2b5140556fd477e7ff6ea36966684da)
This commit is contained in:
parent
3e078b2026
commit
af874635ba
|
@ -162,7 +162,7 @@ class JdbcConfiguration extends ConnectionConfiguration {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Collection<? extends String> extraOptions() {
|
protected Collection<String> extraOptions() {
|
||||||
return OPTION_NAMES;
|
return OPTION_NAMES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,9 +192,8 @@ class JdbcConfiguration extends ConnectionConfiguration {
|
||||||
|
|
||||||
public DriverPropertyInfo[] driverPropertyInfo() {
|
public DriverPropertyInfo[] driverPropertyInfo() {
|
||||||
List<DriverPropertyInfo> info = new ArrayList<>();
|
List<DriverPropertyInfo> info = new ArrayList<>();
|
||||||
for (String option : OPTION_NAMES) {
|
for (String option : optionNames()) {
|
||||||
String value = null;
|
DriverPropertyInfo prop = new DriverPropertyInfo(option, null);
|
||||||
DriverPropertyInfo prop = new DriverPropertyInfo(option, value);
|
|
||||||
info.add(prop);
|
info.add(prop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,9 +45,12 @@ class JdbcConnection implements Connection, JdbcWrapper {
|
||||||
* If we remove it, we need to make sure no other types of Exceptions (runtime or otherwise) are thrown
|
* If we remove it, we need to make sure no other types of Exceptions (runtime or otherwise) are thrown
|
||||||
*/
|
*/
|
||||||
JdbcConnection(JdbcConfiguration connectionInfo) throws SQLException {
|
JdbcConnection(JdbcConfiguration connectionInfo) throws SQLException {
|
||||||
cfg = connectionInfo;
|
this(connectionInfo, true);
|
||||||
client = new JdbcHttpClient(connectionInfo);
|
}
|
||||||
|
|
||||||
|
JdbcConnection(JdbcConfiguration connectionInfo, boolean checkServer) throws SQLException {
|
||||||
|
cfg = connectionInfo;
|
||||||
|
client = new JdbcHttpClient(connectionInfo, checkServer);
|
||||||
url = connectionInfo.connectionString();
|
url = connectionInfo.connectionString();
|
||||||
userName = connectionInfo.authUser();
|
userName = connectionInfo.authUser();
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,15 +10,17 @@ import org.elasticsearch.xpack.sql.client.Version;
|
||||||
|
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.DatabaseMetaData;
|
import java.sql.DatabaseMetaData;
|
||||||
|
import java.sql.DriverPropertyInfo;
|
||||||
import java.sql.JDBCType;
|
import java.sql.JDBCType;
|
||||||
import java.sql.PreparedStatement;
|
import java.sql.PreparedStatement;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.RowIdLifetime;
|
import java.sql.RowIdLifetime;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.sql.SQLFeatureNotSupportedException;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static java.sql.JDBCType.BIGINT;
|
||||||
|
import static java.sql.JDBCType.BOOLEAN;
|
||||||
import static java.sql.JDBCType.INTEGER;
|
import static java.sql.JDBCType.INTEGER;
|
||||||
import static java.sql.JDBCType.SMALLINT;
|
import static java.sql.JDBCType.SMALLINT;
|
||||||
import static org.elasticsearch.xpack.sql.client.StringUtils.EMPTY;
|
import static org.elasticsearch.xpack.sql.client.StringUtils.EMPTY;
|
||||||
|
@ -209,7 +211,7 @@ class JdbcDatabaseMetaData implements DatabaseMetaData, JdbcWrapper {
|
||||||
@Override
|
@Override
|
||||||
public String getSystemFunctions() throws SQLException {
|
public String getSystemFunctions() throws SQLException {
|
||||||
// https://docs.microsoft.com/en-us/sql/odbc/reference/appendixes/system-functions?view=sql-server-2017
|
// https://docs.microsoft.com/en-us/sql/odbc/reference/appendixes/system-functions?view=sql-server-2017
|
||||||
return "DATABASE, IFNULL, USER";
|
return "DATABASE,IFNULL,USER";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -663,8 +665,7 @@ class JdbcDatabaseMetaData implements DatabaseMetaData, JdbcWrapper {
|
||||||
// https://www.postgresql.org/docs/9.0/static/infoschema-routines.html
|
// https://www.postgresql.org/docs/9.0/static/infoschema-routines.html
|
||||||
@Override
|
@Override
|
||||||
public ResultSet getProcedures(String catalog, String schemaPattern, String procedureNamePattern) throws SQLException {
|
public ResultSet getProcedures(String catalog, String schemaPattern, String procedureNamePattern) throws SQLException {
|
||||||
return emptySet(con.cfg,
|
return emptySet(con.cfg, "ROUTINES",
|
||||||
"ROUTINES",
|
|
||||||
"PROCEDURE_CAT",
|
"PROCEDURE_CAT",
|
||||||
"PROCEDURE_SCHEM",
|
"PROCEDURE_SCHEM",
|
||||||
"PROCEDURE_NAME",
|
"PROCEDURE_NAME",
|
||||||
|
@ -679,8 +680,7 @@ class JdbcDatabaseMetaData implements DatabaseMetaData, JdbcWrapper {
|
||||||
@Override
|
@Override
|
||||||
public ResultSet getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern, String columnNamePattern)
|
public ResultSet getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern, String columnNamePattern)
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
return emptySet(con.cfg,
|
return emptySet(con.cfg, "ROUTINES_COLUMNS",
|
||||||
"PARAMETERS",
|
|
||||||
"PROCEDURE_CAT",
|
"PROCEDURE_CAT",
|
||||||
"PROCEDURE_SCHEM",
|
"PROCEDURE_SCHEM",
|
||||||
"PROCEDURE_NAME",
|
"PROCEDURE_NAME",
|
||||||
|
@ -774,14 +774,14 @@ class JdbcDatabaseMetaData implements DatabaseMetaData, JdbcWrapper {
|
||||||
public ResultSet getCatalogs() throws SQLException {
|
public ResultSet getCatalogs() throws SQLException {
|
||||||
// TABLE_CAT is the first column
|
// TABLE_CAT is the first column
|
||||||
Object[][] data = queryColumn(con, "SYS TABLES CATALOG LIKE '%' LIKE ''", 1);
|
Object[][] data = queryColumn(con, "SYS TABLES CATALOG LIKE '%' LIKE ''", 1);
|
||||||
return memorySet(con.cfg, columnInfo("", "TABLE_CAT"), data);
|
return memorySet(con.cfg, columnInfo("CATALOGS", "TABLE_CAT"), data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResultSet getTableTypes() throws SQLException {
|
public ResultSet getTableTypes() throws SQLException {
|
||||||
// TABLE_TYPE (4)
|
// TABLE_TYPE (4)
|
||||||
Object[][] data = queryColumn(con, "SYS TABLES CATALOG LIKE '' LIKE '' TYPE '%'", 4);
|
Object[][] data = queryColumn(con, "SYS TABLES CATALOG LIKE '' LIKE '' TYPE '%'", 4);
|
||||||
return memorySet(con.cfg, columnInfo("", "TABLE_TYPE"), data);
|
return memorySet(con.cfg, columnInfo("TABLE_TYPES", "TABLE_TYPE"), data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -797,43 +797,128 @@ class JdbcDatabaseMetaData implements DatabaseMetaData, JdbcWrapper {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResultSet getColumnPrivileges(String catalog, String schema, String table, String columnNamePattern) throws SQLException {
|
public ResultSet getColumnPrivileges(String catalog, String schema, String table, String columnNamePattern) throws SQLException {
|
||||||
throw new SQLFeatureNotSupportedException("Privileges not supported");
|
return emptySet(con.cfg, "",
|
||||||
|
"TABLE_CAT",
|
||||||
|
"TABLE_SCHEM",
|
||||||
|
"TABLE_NAME",
|
||||||
|
"COLUMN_NAME",
|
||||||
|
"GRANTOR",
|
||||||
|
"GRANTEE",
|
||||||
|
"PRIVILEGE",
|
||||||
|
"IS_GRANTABLE");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResultSet getTablePrivileges(String catalog, String schemaPattern, String tableNamePattern) throws SQLException {
|
public ResultSet getTablePrivileges(String catalog, String schemaPattern, String tableNamePattern) throws SQLException {
|
||||||
throw new SQLFeatureNotSupportedException("Privileges not supported");
|
return emptySet(con.cfg, "",
|
||||||
|
"TABLE_CAT",
|
||||||
|
"TABLE_SCHEM",
|
||||||
|
"TABLE_NAME",
|
||||||
|
"GRANTOR",
|
||||||
|
"GRANTEE",
|
||||||
|
"PRIVILEGE",
|
||||||
|
"IS_GRANTABLE");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResultSet getBestRowIdentifier(String catalog, String schema, String table, int scope, boolean nullable) throws SQLException {
|
public ResultSet getBestRowIdentifier(String catalog, String schema, String table, int scope, boolean nullable) throws SQLException {
|
||||||
throw new SQLFeatureNotSupportedException("Row identifiers not supported");
|
return emptySet(con.cfg, "",
|
||||||
|
"SCOPE", SMALLINT,
|
||||||
|
"COLUMN_NAME",
|
||||||
|
"DATA_TYPE", INTEGER,
|
||||||
|
"TYPE_NAME",
|
||||||
|
"COLUMN_SIZE", INTEGER,
|
||||||
|
"BUFFER_LENGTH", INTEGER,
|
||||||
|
"DECIMAL_DIGITS", SMALLINT,
|
||||||
|
"PSEUDO_COLUMN", SMALLINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResultSet getVersionColumns(String catalog, String schema, String table) throws SQLException {
|
public ResultSet getVersionColumns(String catalog, String schema, String table) throws SQLException {
|
||||||
throw new SQLFeatureNotSupportedException("Version column not supported yet");
|
return emptySet(con.cfg, "",
|
||||||
|
"SCOPE", SMALLINT,
|
||||||
|
"COLUMN_NAME",
|
||||||
|
"DATA_TYPE", INTEGER,
|
||||||
|
"TYPE_NAME",
|
||||||
|
"COLUMN_SIZE", INTEGER,
|
||||||
|
"BUFFER_LENGTH", INTEGER,
|
||||||
|
"DECIMAL_DIGITS", SMALLINT,
|
||||||
|
"PSEUDO_COLUMN", SMALLINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResultSet getPrimaryKeys(String catalog, String schema, String table) throws SQLException {
|
public ResultSet getPrimaryKeys(String catalog, String schema, String table) throws SQLException {
|
||||||
throw new SQLFeatureNotSupportedException("Primary keys not supported");
|
return emptySet(con.cfg, "",
|
||||||
|
"TABLE_CAT",
|
||||||
|
"TABLE_SCHEM",
|
||||||
|
"TABLE_NAME",
|
||||||
|
"COLUMN_NAME",
|
||||||
|
"KEY_SEQ", SMALLINT,
|
||||||
|
"PK_NAME");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResultSet getImportedKeys(String catalog, String schema, String table) throws SQLException {
|
public ResultSet getImportedKeys(String catalog, String schema, String table) throws SQLException {
|
||||||
throw new SQLFeatureNotSupportedException("Imported keys not supported");
|
return emptySet(con.cfg, "",
|
||||||
|
"PKTABLE_CAT",
|
||||||
|
"PKTABLE_SCHEM",
|
||||||
|
"PKTABLE_NAME",
|
||||||
|
"PKCOLUMN_NAME",
|
||||||
|
"FKTABLE_CAT",
|
||||||
|
"FKTABLE_SCHEM",
|
||||||
|
"FKTABLE_NAME",
|
||||||
|
"FKCOLUMN_NAME",
|
||||||
|
"KEY_SEQ", SMALLINT,
|
||||||
|
"UPDATE_RULE ", SMALLINT,
|
||||||
|
"DELETE_RULE ", SMALLINT,
|
||||||
|
"FK_NAME",
|
||||||
|
"PK_NAME ",
|
||||||
|
"DEFERRABILITY", SMALLINT,
|
||||||
|
"IS_NULLABLE"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResultSet getExportedKeys(String catalog, String schema, String table) throws SQLException {
|
public ResultSet getExportedKeys(String catalog, String schema, String table) throws SQLException {
|
||||||
throw new SQLFeatureNotSupportedException("Exported keys not supported");
|
return emptySet(con.cfg, "",
|
||||||
|
"PKTABLE_CAT",
|
||||||
|
"PKTABLE_SCHEM",
|
||||||
|
"PKTABLE_NAME",
|
||||||
|
"PKCOLUMN_NAME",
|
||||||
|
"FKTABLE_CAT",
|
||||||
|
"FKTABLE_SCHEM",
|
||||||
|
"FKTABLE_NAME",
|
||||||
|
"FKCOLUMN_NAME",
|
||||||
|
"KEY_SEQ", SMALLINT,
|
||||||
|
"UPDATE_RULE ", SMALLINT,
|
||||||
|
"DELETE_RULE ", SMALLINT,
|
||||||
|
"FK_NAME",
|
||||||
|
"PK_NAME ",
|
||||||
|
"DEFERRABILITY", SMALLINT,
|
||||||
|
"IS_NULLABLE"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResultSet getCrossReference(String parentCatalog, String parentSchema, String parentTable, String foreignCatalog,
|
public ResultSet getCrossReference(String parentCatalog, String parentSchema, String parentTable, String foreignCatalog,
|
||||||
String foreignSchema, String foreignTable) throws SQLException {
|
String foreignSchema, String foreignTable) throws SQLException {
|
||||||
throw new SQLFeatureNotSupportedException("Cross reference not supported");
|
return emptySet(con.cfg, "",
|
||||||
|
"PKTABLE_CAT",
|
||||||
|
"PKTABLE_SCHEM",
|
||||||
|
"PKTABLE_NAME",
|
||||||
|
"PKCOLUMN_NAME",
|
||||||
|
"FKTABLE_CAT",
|
||||||
|
"FKTABLE_SCHEM",
|
||||||
|
"FKTABLE_NAME",
|
||||||
|
"FKCOLUMN_NAME",
|
||||||
|
"KEY_SEQ", SMALLINT,
|
||||||
|
"UPDATE_RULE ", SMALLINT,
|
||||||
|
"DELETE_RULE ", SMALLINT,
|
||||||
|
"FK_NAME",
|
||||||
|
"PK_NAME ",
|
||||||
|
"DEFERRABILITY", SMALLINT,
|
||||||
|
"IS_NULLABLE"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -843,7 +928,22 @@ class JdbcDatabaseMetaData implements DatabaseMetaData, JdbcWrapper {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResultSet getIndexInfo(String catalog, String schema, String table, boolean unique, boolean approximate) throws SQLException {
|
public ResultSet getIndexInfo(String catalog, String schema, String table, boolean unique, boolean approximate) throws SQLException {
|
||||||
throw new SQLFeatureNotSupportedException("Indicies not supported");
|
return emptySet(con.cfg, "",
|
||||||
|
"TABLE_CAT",
|
||||||
|
"TABLE_SCHEM",
|
||||||
|
"TABLE_NAME",
|
||||||
|
"NON_UNIQUE", BOOLEAN,
|
||||||
|
"INDEX_QUALIFIER",
|
||||||
|
"INDEX_NAME",
|
||||||
|
"TYPE", SMALLINT,
|
||||||
|
"ORDINAL_POSITION", SMALLINT,
|
||||||
|
"COLUMN_NAME",
|
||||||
|
"ASC_OR_DESC",
|
||||||
|
"CARDINALITY", BIGINT,
|
||||||
|
"PAGES", BIGINT,
|
||||||
|
"FILTER_CONDITION",
|
||||||
|
"TYPE_NAME"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -908,7 +1008,7 @@ class JdbcDatabaseMetaData implements DatabaseMetaData, JdbcWrapper {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResultSet getUDTs(String catalog, String schemaPattern, String typeNamePattern, int[] types) throws SQLException {
|
public ResultSet getUDTs(String catalog, String schemaPattern, String typeNamePattern, int[] types) throws SQLException {
|
||||||
return emptySet(con.cfg,
|
return emptySet(con.cfg, "",
|
||||||
"USER_DEFINED_TYPES",
|
"USER_DEFINED_TYPES",
|
||||||
"TYPE_CAT",
|
"TYPE_CAT",
|
||||||
"TYPE_SCHEM",
|
"TYPE_SCHEM",
|
||||||
|
@ -946,7 +1046,7 @@ class JdbcDatabaseMetaData implements DatabaseMetaData, JdbcWrapper {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResultSet getSuperTypes(String catalog, String schemaPattern, String typeNamePattern) throws SQLException {
|
public ResultSet getSuperTypes(String catalog, String schemaPattern, String typeNamePattern) throws SQLException {
|
||||||
return emptySet(con.cfg,
|
return emptySet(con.cfg, "",
|
||||||
"SUPER_TYPES",
|
"SUPER_TYPES",
|
||||||
"TYPE_CAT",
|
"TYPE_CAT",
|
||||||
"TYPE_SCHEM",
|
"TYPE_SCHEM",
|
||||||
|
@ -959,7 +1059,7 @@ class JdbcDatabaseMetaData implements DatabaseMetaData, JdbcWrapper {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern) throws SQLException {
|
public ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern) throws SQLException {
|
||||||
return emptySet(con.cfg, "SUPER_TABLES",
|
return emptySet(con.cfg, "",
|
||||||
"TABLE_CAT",
|
"TABLE_CAT",
|
||||||
"TABLE_SCHEM",
|
"TABLE_SCHEM",
|
||||||
"TABLE_NAME",
|
"TABLE_NAME",
|
||||||
|
@ -969,7 +1069,7 @@ class JdbcDatabaseMetaData implements DatabaseMetaData, JdbcWrapper {
|
||||||
@Override
|
@Override
|
||||||
public ResultSet getAttributes(String catalog, String schemaPattern, String typeNamePattern, String attributeNamePattern)
|
public ResultSet getAttributes(String catalog, String schemaPattern, String typeNamePattern, String attributeNamePattern)
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
return emptySet(con.cfg,
|
return emptySet(con.cfg, "",
|
||||||
"ATTRIBUTES",
|
"ATTRIBUTES",
|
||||||
"TYPE_CAT",
|
"TYPE_CAT",
|
||||||
"TYPE_SCHEM",
|
"TYPE_SCHEM",
|
||||||
|
@ -1056,12 +1156,27 @@ class JdbcDatabaseMetaData implements DatabaseMetaData, JdbcWrapper {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResultSet getClientInfoProperties() throws SQLException {
|
public ResultSet getClientInfoProperties() throws SQLException {
|
||||||
throw new SQLException("Client info not implemented yet");
|
DriverPropertyInfo[] info = con.cfg.driverPropertyInfo();
|
||||||
|
Object[][] data = new Object[info.length][];
|
||||||
|
|
||||||
|
for (int i = 0; i < data.length; i++) {
|
||||||
|
data[i] = new Object[4];
|
||||||
|
data[i][0] = info[i].name;
|
||||||
|
data[i][1] = Integer.valueOf(-1);
|
||||||
|
data[i][2] = EMPTY;
|
||||||
|
data[i][3] = EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return memorySet(con.cfg, columnInfo("",
|
||||||
|
"NAME",
|
||||||
|
"MAX_LEN", INTEGER,
|
||||||
|
"DEFAULT_VALUE",
|
||||||
|
"DESCRIPTION"), data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResultSet getFunctions(String catalog, String schemaPattern, String functionNamePattern) throws SQLException {
|
public ResultSet getFunctions(String catalog, String schemaPattern, String functionNamePattern) throws SQLException {
|
||||||
return emptySet(con.cfg,
|
return emptySet(con.cfg, "",
|
||||||
"FUNCTIONS",
|
"FUNCTIONS",
|
||||||
"FUNCTION_CAT",
|
"FUNCTION_CAT",
|
||||||
"FUNCTION_SCHEM",
|
"FUNCTION_SCHEM",
|
||||||
|
@ -1074,7 +1189,7 @@ class JdbcDatabaseMetaData implements DatabaseMetaData, JdbcWrapper {
|
||||||
@Override
|
@Override
|
||||||
public ResultSet getFunctionColumns(String catalog, String schemaPattern, String functionNamePattern, String columnNamePattern)
|
public ResultSet getFunctionColumns(String catalog, String schemaPattern, String functionNamePattern, String columnNamePattern)
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
return emptySet(con.cfg,
|
return emptySet(con.cfg, "",
|
||||||
"FUNCTION_COLUMNS",
|
"FUNCTION_COLUMNS",
|
||||||
"FUNCTION_CAT",
|
"FUNCTION_CAT",
|
||||||
"FUNCTION_SCHEM",
|
"FUNCTION_SCHEM",
|
||||||
|
@ -1097,7 +1212,7 @@ class JdbcDatabaseMetaData implements DatabaseMetaData, JdbcWrapper {
|
||||||
@Override
|
@Override
|
||||||
public ResultSet getPseudoColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern)
|
public ResultSet getPseudoColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern)
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
return emptySet(con.cfg,
|
return emptySet(con.cfg, "",
|
||||||
"PSEUDO_COLUMNS",
|
"PSEUDO_COLUMNS",
|
||||||
"TABLE_CAT",
|
"TABLE_CAT",
|
||||||
"TABLE_SCHEM",
|
"TABLE_SCHEM",
|
||||||
|
@ -1212,7 +1327,7 @@ class JdbcDatabaseMetaData implements DatabaseMetaData, JdbcWrapper {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int batchSize() {
|
public int batchSize() {
|
||||||
return data.length;
|
return ObjectUtils.isEmpty(data) ? 0 : data.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -30,17 +30,23 @@ import static org.elasticsearch.xpack.sql.client.StringUtils.EMPTY;
|
||||||
class JdbcHttpClient {
|
class JdbcHttpClient {
|
||||||
private final HttpClient httpClient;
|
private final HttpClient httpClient;
|
||||||
private final JdbcConfiguration conCfg;
|
private final JdbcConfiguration conCfg;
|
||||||
private final InfoResponse serverInfo;
|
private InfoResponse serverInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The SQLException is the only type of Exception the JDBC API can throw (and that the user expects).
|
* The SQLException is the only type of Exception the JDBC API can throw (and that the user expects).
|
||||||
* If we remove it, we need to make sure no other types of Exceptions (runtime or otherwise) are thrown
|
* If we remove it, we need to make sure no other types of Exceptions (runtime or otherwise) are thrown
|
||||||
*/
|
*/
|
||||||
JdbcHttpClient(JdbcConfiguration conCfg) throws SQLException {
|
JdbcHttpClient(JdbcConfiguration conCfg) throws SQLException {
|
||||||
|
this(conCfg, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
JdbcHttpClient(JdbcConfiguration conCfg, boolean checkServer) throws SQLException {
|
||||||
httpClient = new HttpClient(conCfg);
|
httpClient = new HttpClient(conCfg);
|
||||||
this.conCfg = conCfg;
|
this.conCfg = conCfg;
|
||||||
this.serverInfo = fetchServerInfo();
|
if (checkServer) {
|
||||||
checkServerVersion();
|
this.serverInfo = fetchServerInfo();
|
||||||
|
checkServerVersion();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean ping(long timeoutInMs) throws SQLException {
|
boolean ping(long timeoutInMs) throws SQLException {
|
||||||
|
@ -78,6 +84,9 @@ class JdbcHttpClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
InfoResponse serverInfo() throws SQLException {
|
InfoResponse serverInfo() throws SQLException {
|
||||||
|
if (serverInfo == null) {
|
||||||
|
serverInfo = fetchServerInfo();
|
||||||
|
}
|
||||||
return serverInfo;
|
return serverInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1224,6 +1224,7 @@ class JdbcResultSet implements ResultSet, JdbcWrapper {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return format(Locale.ROOT, "%s:row %d", getClass().getSimpleName(), rowNumber);
|
return format(Locale.ROOT, "%s:row %d:cursor size %d:%s", getClass().getSimpleName(), rowNumber, cursor.batchSize(),
|
||||||
|
cursor.columns());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,15 +6,119 @@
|
||||||
|
|
||||||
package org.elasticsearch.xpack.sql.jdbc;
|
package org.elasticsearch.xpack.sql.jdbc;
|
||||||
|
|
||||||
|
import org.elasticsearch.common.CheckedSupplier;
|
||||||
import org.elasticsearch.test.ESTestCase;
|
import org.elasticsearch.test.ESTestCase;
|
||||||
|
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
public class JdbcDatabaseMetaDataTests extends ESTestCase {
|
public class JdbcDatabaseMetaDataTests extends ESTestCase {
|
||||||
|
|
||||||
private JdbcDatabaseMetaData md = new JdbcDatabaseMetaData(null);
|
private JdbcDatabaseMetaData md = null;
|
||||||
|
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
md = new JdbcDatabaseMetaData(
|
||||||
|
new JdbcConnection(JdbcConfiguration.create("jdbc:es://localhost:9200/", new Properties(), 10), false));
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throw new RuntimeException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void testSeparators() throws Exception {
|
public void testSeparators() throws Exception {
|
||||||
assertEquals(":", md.getCatalogSeparator());
|
assertEquals(":", md.getCatalogSeparator());
|
||||||
assertEquals("\"", md.getIdentifierQuoteString());
|
assertEquals("\"", md.getIdentifierQuoteString());
|
||||||
assertEquals("\\", md.getSearchStringEscape());
|
assertEquals("\\", md.getSearchStringEscape());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testGetProcedures() throws Exception {
|
||||||
|
testEmptySet(() -> md.getProcedures(null, null, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetProcedureColumns() throws Exception {
|
||||||
|
testEmptySet(() -> md.getProcedureColumns(null, null, null, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetColumnPrivileges() throws Exception {
|
||||||
|
testEmptySet(() -> md.getColumnPrivileges(null, null, null, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetTablePrivileges() throws Exception {
|
||||||
|
testEmptySet(() -> md.getTablePrivileges(null, null, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetBestRowIdentifier() throws Exception {
|
||||||
|
testEmptySet(() -> md.getBestRowIdentifier(null, null, null, 0, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetVersionColumns() throws Exception {
|
||||||
|
testEmptySet(() -> md.getVersionColumns(null, null, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetPrimaryKeys() throws Exception {
|
||||||
|
testEmptySet(() -> md.getPrimaryKeys(null, null, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetImportedKeys() throws Exception {
|
||||||
|
testEmptySet(() -> md.getImportedKeys(null, null, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetExportedKeys() throws Exception {
|
||||||
|
testEmptySet(() -> md.getExportedKeys(null, null, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetCrossReference() throws Exception {
|
||||||
|
testEmptySet(() -> md.getCrossReference(null, null, null, null, null, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetIndexInfo() throws Exception {
|
||||||
|
testEmptySet(() -> md.getIndexInfo(null, null, null, false, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetUDTs() throws Exception {
|
||||||
|
testEmptySet(() -> md.getUDTs(null, null, null, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetSuperTypes() throws Exception {
|
||||||
|
testEmptySet(() -> md.getSuperTypes(null, null, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetSuperTables() throws Exception {
|
||||||
|
testEmptySet(() -> md.getSuperTables(null, null, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetAttributes() throws Exception {
|
||||||
|
testEmptySet(() -> md.getAttributes(null, null, null, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetFunctions() throws Exception {
|
||||||
|
testEmptySet(() -> md.getFunctions(null, null, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetFunctionColumns() throws Exception {
|
||||||
|
testEmptySet(() -> md.getFunctionColumns(null, null, null, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetPseudoColumns() throws Exception {
|
||||||
|
testEmptySet(() -> md.getPseudoColumns(null, null, null, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testEmptySet(CheckedSupplier<ResultSet, SQLException> supplier) throws SQLException {
|
||||||
|
try (ResultSet result = supplier.get()) {
|
||||||
|
assertNotNull(result);
|
||||||
|
assertFalse(result.next());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetClientInfoProperties() throws Exception {
|
||||||
|
try (ResultSet result = md.getClientInfoProperties()) {
|
||||||
|
assertNotNull(result);
|
||||||
|
assertTrue(result.next());
|
||||||
|
assertNotNull(result.getString(1));
|
||||||
|
assertEquals(-1, result.getInt(2));
|
||||||
|
assertEquals("", result.getString(3));
|
||||||
|
assertEquals("", result.getString(4));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -7,13 +7,13 @@ package org.elasticsearch.xpack.sql.client;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.TreeSet;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
@ -148,13 +148,13 @@ public class ConnectionConfiguration {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Collection<String> optionNames() {
|
protected Collection<String> optionNames() {
|
||||||
Collection<String> options = new ArrayList<>(OPTION_NAMES);
|
Set<String> options = new TreeSet<>(OPTION_NAMES);
|
||||||
options.addAll(extraOptions());
|
options.addAll(extraOptions());
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Collection<? extends String> extraOptions() {
|
protected Collection<String> extraOptions() {
|
||||||
return emptyList();
|
return emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue