mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-02-09 14:35:04 +00:00
SQL: add catalog filter to SYS COLUMNS command (elastic/x-pack-elasticsearch#3978)
Add basic support for catalog parameters in SYS COLUMN Pass an empty string instead of a null inside the prepared statement Don't use pattern for catalog in getColumns Original commit: elastic/x-pack-elasticsearch@17e9e851a0
This commit is contained in:
parent
b2631f9ac8
commit
b8c9c5325c
@ -759,9 +759,11 @@ class JdbcDatabaseMetaData implements DatabaseMetaData, JdbcWrapper {
|
|||||||
@Override
|
@Override
|
||||||
public ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern)
|
public ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern)
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
PreparedStatement ps = con.prepareStatement("SYS COLUMNS TABLE LIKE ? LIKE ?");
|
PreparedStatement ps = con.prepareStatement("SYS COLUMNS CATALOG ? TABLE LIKE ? LIKE ?");
|
||||||
ps.setString(1, tableNamePattern != null ? tableNamePattern.trim() : "%");
|
// TODO: until passing null works, pass an empty string
|
||||||
ps.setString(2, columnNamePattern != null ? columnNamePattern.trim() : "%");
|
ps.setString(1, catalog != null ? catalog.trim() : "");
|
||||||
|
ps.setString(2, tableNamePattern != null ? tableNamePattern.trim() : "%");
|
||||||
|
ps.setString(3, columnNamePattern != null ? columnNamePattern.trim() : "%");
|
||||||
return ps.executeQuery();
|
return ps.executeQuery();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +59,8 @@ statement
|
|||||||
| SYS TABLES (CATALOG LIKE? clusterPattern=pattern)?
|
| SYS TABLES (CATALOG LIKE? clusterPattern=pattern)?
|
||||||
(LIKE? tablePattern=pattern)?
|
(LIKE? tablePattern=pattern)?
|
||||||
(TYPE STRING (',' STRING)* )? #sysTables
|
(TYPE STRING (',' STRING)* )? #sysTables
|
||||||
| SYS COLUMNS (TABLE LIKE? indexPattern=pattern)?
|
| SYS COLUMNS (CATALOG cluster=STRING)?
|
||||||
|
(TABLE LIKE? indexPattern=pattern)?
|
||||||
(LIKE? columnPattern=pattern)? #sysColumns
|
(LIKE? columnPattern=pattern)? #sysColumns
|
||||||
| SYS TYPES #sysTypes
|
| SYS TYPES #sysTypes
|
||||||
| SYS TABLE TYPES #sysTableTypes
|
| SYS TABLE TYPES #sysTableTypes
|
||||||
@ -286,7 +287,9 @@ ASC: 'ASC';
|
|||||||
BETWEEN: 'BETWEEN';
|
BETWEEN: 'BETWEEN';
|
||||||
BY: 'BY';
|
BY: 'BY';
|
||||||
CAST: 'CAST';
|
CAST: 'CAST';
|
||||||
CATALOG: 'CATALOG';CATALOGS: 'CATALOGS';COLUMNS: 'COLUMNS';
|
CATALOG: 'CATALOG';
|
||||||
|
CATALOGS: 'CATALOGS';
|
||||||
|
COLUMNS: 'COLUMNS';
|
||||||
DEBUG: 'DEBUG';
|
DEBUG: 'DEBUG';
|
||||||
DESC: 'DESC';
|
DESC: 'DESC';
|
||||||
DESCRIBE: 'DESCRIBE';
|
DESCRIBE: 'DESCRIBE';
|
||||||
|
@ -160,7 +160,7 @@ abstract class CommandBuilder extends LogicalPlanBuilder {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object visitSysColumns(SysColumnsContext ctx) {
|
public Object visitSysColumns(SysColumnsContext ctx) {
|
||||||
return new SysColumns(source(ctx), visitPattern(ctx.indexPattern), visitPattern(ctx.columnPattern));
|
return new SysColumns(source(ctx), string(ctx.cluster), visitPattern(ctx.indexPattern), visitPattern(ctx.columnPattern));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -6,6 +6,7 @@
|
|||||||
package org.elasticsearch.xpack.sql.plan.logical.command.sys;
|
package org.elasticsearch.xpack.sql.plan.logical.command.sys;
|
||||||
|
|
||||||
import org.elasticsearch.action.ActionListener;
|
import org.elasticsearch.action.ActionListener;
|
||||||
|
import org.elasticsearch.common.Strings;
|
||||||
import org.elasticsearch.xpack.sql.analysis.index.EsIndex;
|
import org.elasticsearch.xpack.sql.analysis.index.EsIndex;
|
||||||
import org.elasticsearch.xpack.sql.expression.Attribute;
|
import org.elasticsearch.xpack.sql.expression.Attribute;
|
||||||
import org.elasticsearch.xpack.sql.expression.regex.LikePattern;
|
import org.elasticsearch.xpack.sql.expression.regex.LikePattern;
|
||||||
@ -37,26 +38,20 @@ import static org.elasticsearch.xpack.sql.type.DataType.SHORT;
|
|||||||
*/
|
*/
|
||||||
public class SysColumns extends Command {
|
public class SysColumns extends Command {
|
||||||
|
|
||||||
|
private final String catalog;
|
||||||
private final LikePattern indexPattern;
|
private final LikePattern indexPattern;
|
||||||
private final LikePattern columnPattern;
|
private final LikePattern columnPattern;
|
||||||
|
|
||||||
public SysColumns(Location location, LikePattern indexPattern, LikePattern columnPattern) {
|
public SysColumns(Location location, String catalog, LikePattern indexPattern, LikePattern columnPattern) {
|
||||||
super(location);
|
super(location);
|
||||||
|
this.catalog = catalog;
|
||||||
this.indexPattern = indexPattern;
|
this.indexPattern = indexPattern;
|
||||||
this.columnPattern = columnPattern;
|
this.columnPattern = columnPattern;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LikePattern indexPattern() {
|
|
||||||
return indexPattern;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LikePattern columnPattern() {
|
|
||||||
return columnPattern;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected NodeInfo<SysColumns> info() {
|
protected NodeInfo<SysColumns> info() {
|
||||||
return NodeInfo.create(this, SysColumns::new, indexPattern, columnPattern);
|
return NodeInfo.create(this, SysColumns::new, catalog, indexPattern, columnPattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -91,12 +86,18 @@ public class SysColumns extends Command {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(SqlSession session, ActionListener<SchemaRowSet> listener) {
|
public void execute(SqlSession session, ActionListener<SchemaRowSet> listener) {
|
||||||
|
String cluster = session.indexResolver().clusterName();
|
||||||
|
|
||||||
|
// bail-out early if the catalog is present but differs
|
||||||
|
if (Strings.hasText(catalog) && !cluster.equals(catalog)) {
|
||||||
|
listener.onResponse(Rows.empty(output()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
String index = indexPattern != null ? indexPattern.asIndexNameWildcard() : "*";
|
String index = indexPattern != null ? indexPattern.asIndexNameWildcard() : "*";
|
||||||
String regex = indexPattern != null ? indexPattern.asJavaRegex() : null;
|
String regex = indexPattern != null ? indexPattern.asJavaRegex() : null;
|
||||||
|
|
||||||
Pattern columnMatcher = columnPattern != null ? Pattern.compile(columnPattern.asJavaRegex()) : null;
|
Pattern columnMatcher = columnPattern != null ? Pattern.compile(columnPattern.asJavaRegex()) : null;
|
||||||
|
|
||||||
String cluster = session.indexResolver().clusterName();
|
|
||||||
|
|
||||||
session.indexResolver().resolveAsSeparateMappings(index, regex, ActionListener.wrap(esIndices -> {
|
session.indexResolver().resolveAsSeparateMappings(index, regex, ActionListener.wrap(esIndices -> {
|
||||||
List<List<?>> rows = new ArrayList<>();
|
List<List<?>> rows = new ArrayList<>();
|
||||||
@ -168,7 +169,7 @@ public class SysColumns extends Command {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(indexPattern, columnPattern);
|
return Objects.hash(catalog, indexPattern, columnPattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -182,7 +183,8 @@ public class SysColumns extends Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SysColumns other = (SysColumns) obj;
|
SysColumns other = (SysColumns) obj;
|
||||||
return Objects.equals(indexPattern, other.indexPattern)
|
return Objects.equals(catalog, other.catalog)
|
||||||
|
&& Objects.equals(indexPattern, other.indexPattern)
|
||||||
&& Objects.equals(columnPattern, other.columnPattern);
|
&& Objects.equals(columnPattern, other.columnPattern);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -75,6 +75,24 @@ public class SysParserTests extends ESTestCase {
|
|||||||
runSysColumns("SYS COLUMNS");
|
runSysColumns("SYS COLUMNS");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testSysColumnEmptyCatalog() throws Exception {
|
||||||
|
Tuple<Command, SqlSession> sql = sql("SYS COLUMNS CATALOG '' TABLE LIKE '%' LIKE '%'");
|
||||||
|
|
||||||
|
sql.v1().execute(sql.v2(), ActionListener.wrap(r -> {
|
||||||
|
assertEquals(24, r.columnCount());
|
||||||
|
assertEquals(22, r.size());
|
||||||
|
}, ex -> fail(ex.getMessage())));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSysColsTableOnlyCatalog() throws Exception {
|
||||||
|
Tuple<Command, SqlSession> sql = sql("SYS COLUMNS CATALOG 'catalog'");
|
||||||
|
|
||||||
|
sql.v1().execute(sql.v2(), ActionListener.wrap(r -> {
|
||||||
|
assertEquals(24, r.columnCount());
|
||||||
|
assertEquals(0, r.size());
|
||||||
|
}, ex -> fail(ex.getMessage())));
|
||||||
|
}
|
||||||
|
|
||||||
public void testSysColsTableOnlyPattern() throws Exception {
|
public void testSysColsTableOnlyPattern() throws Exception {
|
||||||
runSysColumns("SYS COLUMNS TABLE LIKE 'test'");
|
runSysColumns("SYS COLUMNS TABLE LIKE 'test'");
|
||||||
}
|
}
|
||||||
|
@ -286,9 +286,9 @@ public class JdbcSecurityIT extends SqlSecurityTestCase {
|
|||||||
createUser("full_access", "cli_or_jdbc_minimal");
|
createUser("full_access", "cli_or_jdbc_minimal");
|
||||||
|
|
||||||
expectActionMatchesAdmin(
|
expectActionMatchesAdmin(
|
||||||
con -> con.getMetaData().getColumns("%", "%", "%t", "%"),
|
con -> con.getMetaData().getColumns(null, "%", "%t", "%"),
|
||||||
"full_access",
|
"full_access",
|
||||||
con -> con.getMetaData().getColumns("%", "%", "%", "%"));
|
con -> con.getMetaData().getColumns(null, "%", "%", "%"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testMetaDataGetColumnsWithNoAccess() throws Exception {
|
public void testMetaDataGetColumnsWithNoAccess() throws Exception {
|
||||||
@ -301,18 +301,18 @@ public class JdbcSecurityIT extends SqlSecurityTestCase {
|
|||||||
createUser("wrong_access", "read_something_else");
|
createUser("wrong_access", "read_something_else");
|
||||||
|
|
||||||
expectActionMatchesAdmin(
|
expectActionMatchesAdmin(
|
||||||
con -> con.getMetaData().getColumns("%", "%", "not_created", "%"),
|
con -> con.getMetaData().getColumns(null, "%", "not_created", "%"),
|
||||||
"wrong_access",
|
"wrong_access",
|
||||||
con -> con.getMetaData().getColumns("%", "%", "test", "%"));
|
con -> con.getMetaData().getColumns(null, "%", "test", "%"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testMetaDataGetColumnsSingleFieldGranted() throws Exception {
|
public void testMetaDataGetColumnsSingleFieldGranted() throws Exception {
|
||||||
createUser("only_a", "read_test_a");
|
createUser("only_a", "read_test_a");
|
||||||
|
|
||||||
expectActionMatchesAdmin(
|
expectActionMatchesAdmin(
|
||||||
con -> con.getMetaData().getColumns("%", "%", "test", "a"),
|
con -> con.getMetaData().getColumns(null, "%", "test", "a"),
|
||||||
"only_a",
|
"only_a",
|
||||||
con -> con.getMetaData().getColumns("%", "%", "test", "%"));
|
con -> con.getMetaData().getColumns(null, "%", "test", "%"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testMetaDataGetColumnsSingleFieldExcepted() throws Exception {
|
public void testMetaDataGetColumnsSingleFieldExcepted() throws Exception {
|
||||||
@ -322,7 +322,7 @@ public class JdbcSecurityIT extends SqlSecurityTestCase {
|
|||||||
* both 'a' and 'b' we'll have to roll our own assertion here, but we
|
* both 'a' and 'b' we'll have to roll our own assertion here, but we
|
||||||
* are intentionally much less restrictive then the tests elsewhere. */
|
* are intentionally much less restrictive then the tests elsewhere. */
|
||||||
try (Connection con = es(userProperties("not_c"))) {
|
try (Connection con = es(userProperties("not_c"))) {
|
||||||
ResultSet result = con.getMetaData().getColumns("%", "%", "test", "%");
|
ResultSet result = con.getMetaData().getColumns(null, "%", "test", "%");
|
||||||
assertTrue(result.next());
|
assertTrue(result.next());
|
||||||
String columnName = result.getString(4);
|
String columnName = result.getString(4);
|
||||||
assertEquals("a", columnName);
|
assertEquals("a", columnName);
|
||||||
@ -337,8 +337,8 @@ public class JdbcSecurityIT extends SqlSecurityTestCase {
|
|||||||
createUser("no_3s", "read_test_without_c_3");
|
createUser("no_3s", "read_test_without_c_3");
|
||||||
|
|
||||||
expectActionMatchesAdmin(
|
expectActionMatchesAdmin(
|
||||||
con -> con.getMetaData().getColumns("%", "%", "test", "%"),
|
con -> con.getMetaData().getColumns(null, "%", "test", "%"),
|
||||||
"no_3s",
|
"no_3s",
|
||||||
con -> con.getMetaData().getColumns("%", "%", "test", "%"));
|
con -> con.getMetaData().getColumns(null, "%", "test", "%"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ public class DatabaseMetaDataTestCase extends JdbcIntegrationTestCase {
|
|||||||
h2.createStatement().executeUpdate("RUNSCRIPT FROM 'classpath:/setup_mock_metadata_get_columns.sql'");
|
h2.createStatement().executeUpdate("RUNSCRIPT FROM 'classpath:/setup_mock_metadata_get_columns.sql'");
|
||||||
|
|
||||||
ResultSet expected = h2.createStatement().executeQuery("SELECT '" + clusterName() + "' AS TABLE_CAT, * FROM mock");
|
ResultSet expected = h2.createStatement().executeQuery("SELECT '" + clusterName() + "' AS TABLE_CAT, * FROM mock");
|
||||||
assertResultSets(expected, es.getMetaData().getColumns("%", "%", "%", null));
|
assertResultSets(expected, es.getMetaData().getColumns(null, "%", "%", null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user