Remove isValidIndex from SQL's Catalog interface (elastic/x-pack-elasticsearch#2195)
This moves validating that each index contains only a single type into EsCatalog which removes a race condition and removes a method from the Catalog interface. Removing methods from the Catalog interface is nice because the fewer methods that the interface has the fewer have to be secured. Original commit: elastic/x-pack-elasticsearch@85cd089e47
This commit is contained in:
parent
c47c66362e
commit
b31bc786d3
|
@ -30,6 +30,17 @@ public class AnalysisException extends SqlException {
|
||||||
this.column = loc.getColumnNumber();
|
this.column = loc.getColumnNumber();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AnalysisException(Node<?> source, String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
|
||||||
|
Location loc = Location.EMPTY;
|
||||||
|
if (source != null && source.location() != null) {
|
||||||
|
loc = source.location();
|
||||||
|
}
|
||||||
|
this.line = loc.getLineNumber();
|
||||||
|
this.column = loc.getColumnNumber();
|
||||||
|
}
|
||||||
|
|
||||||
public int getLineNumber() {
|
public int getLineNumber() {
|
||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +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.analysis;
|
|
||||||
|
|
||||||
import org.elasticsearch.xpack.sql.tree.Node;
|
|
||||||
|
|
||||||
public class InvalidIndexException extends AnalysisException {
|
|
||||||
|
|
||||||
public InvalidIndexException(String index, Node<?> source) {
|
|
||||||
super(source, "Invalid index %s; contains more than one type", index);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,8 +5,8 @@
|
||||||
*/
|
*/
|
||||||
package org.elasticsearch.xpack.sql.analysis.analyzer;
|
package org.elasticsearch.xpack.sql.analysis.analyzer;
|
||||||
|
|
||||||
|
import org.elasticsearch.xpack.sql.SqlIllegalArgumentException;
|
||||||
import org.elasticsearch.xpack.sql.analysis.AnalysisException;
|
import org.elasticsearch.xpack.sql.analysis.AnalysisException;
|
||||||
import org.elasticsearch.xpack.sql.analysis.InvalidIndexException;
|
|
||||||
import org.elasticsearch.xpack.sql.analysis.UnknownFunctionException;
|
import org.elasticsearch.xpack.sql.analysis.UnknownFunctionException;
|
||||||
import org.elasticsearch.xpack.sql.analysis.UnknownIndexException;
|
import org.elasticsearch.xpack.sql.analysis.UnknownIndexException;
|
||||||
import org.elasticsearch.xpack.sql.analysis.analyzer.Verifier.Failure;
|
import org.elasticsearch.xpack.sql.analysis.analyzer.Verifier.Failure;
|
||||||
|
@ -241,10 +241,12 @@ public class Analyzer extends RuleExecutor<LogicalPlan> {
|
||||||
@Override
|
@Override
|
||||||
protected LogicalPlan rule(UnresolvedRelation plan) {
|
protected LogicalPlan rule(UnresolvedRelation plan) {
|
||||||
TableIdentifier table = plan.table();
|
TableIdentifier table = plan.table();
|
||||||
if (!catalog.indexIsValid(table.index())) {
|
EsIndex found;
|
||||||
throw new InvalidIndexException(table.index(), plan);
|
try {
|
||||||
|
found = catalog.getIndex(table.index());
|
||||||
|
} catch (SqlIllegalArgumentException e) {
|
||||||
|
throw new AnalysisException(plan, e.getMessage(), e);
|
||||||
}
|
}
|
||||||
EsIndex found = catalog.getIndex(table.index());
|
|
||||||
if (found == null) {
|
if (found == null) {
|
||||||
throw new UnknownIndexException(table.index(), plan);
|
throw new UnknownIndexException(table.index(), plan);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,23 +6,19 @@
|
||||||
package org.elasticsearch.xpack.sql.analysis.catalog;
|
package org.elasticsearch.xpack.sql.analysis.catalog;
|
||||||
|
|
||||||
import org.elasticsearch.common.Nullable;
|
import org.elasticsearch.common.Nullable;
|
||||||
|
import org.elasticsearch.xpack.sql.SqlIllegalArgumentException;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
public interface Catalog {
|
public interface Catalog {
|
||||||
/**
|
|
||||||
* Check if an index is valid for sql.
|
|
||||||
*/
|
|
||||||
boolean indexIsValid(String index); // NOCOMMIT should probably be merged into EsCatalog's getIndex method.
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lookup the information for a table, returning {@code null} if
|
* Lookup the information for a table, returning {@code null} if
|
||||||
* the index is not found.
|
* the index is not found.
|
||||||
|
* @throws SqlIllegalArgumentException if the index is in some way invalid for use with sql
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
EsIndex getIndex(String index);
|
EsIndex getIndex(String index) throws SqlIllegalArgumentException;
|
||||||
|
|
||||||
List<EsIndex> listIndices(String pattern);
|
List<EsIndex> listIndices(String pattern);
|
||||||
// NOCOMMIT should these be renamed to getTable and listTables? That seems like a name given that this is a SQL Catalog abstraction.
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||||
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
|
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
|
||||||
import org.elasticsearch.cluster.metadata.MetaData;
|
import org.elasticsearch.cluster.metadata.MetaData;
|
||||||
import org.elasticsearch.common.inject.Inject;
|
import org.elasticsearch.common.inject.Inject;
|
||||||
|
import org.elasticsearch.xpack.sql.SqlIllegalArgumentException;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
@ -36,19 +37,16 @@ public class EsCatalog implements Catalog {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EsIndex getIndex(String index) {
|
public EsIndex getIndex(String index) throws SqlIllegalArgumentException {
|
||||||
MetaData metadata = metadata();
|
MetaData metadata = metadata();
|
||||||
if (false == metadata.hasIndex(index)) {
|
IndexMetaData idx = metadata.index(index);
|
||||||
|
if (idx == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return EsIndex.build(metadata.index(index));
|
if (false == indexHasOnlyOneType(idx)) {
|
||||||
}
|
throw new SqlIllegalArgumentException("index has more than one type");
|
||||||
|
}
|
||||||
@Override
|
return EsIndex.build(idx);
|
||||||
public boolean indexIsValid(String index) {
|
|
||||||
// NOCOMMIT there is a race condition here with indices being deleted. This should be moved into getIndex
|
|
||||||
IndexMetaData idx = metadata().index(index);
|
|
||||||
return idx == null || indexHasOnlyOneType(idx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -34,11 +34,6 @@ public class FilteredCatalog implements Catalog {
|
||||||
return delegate.listIndices(pattern);
|
return delegate.listIndices(pattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean indexIsValid(String index) {
|
|
||||||
return delegate.indexIsValid(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EsIndex getIndex(String index) {
|
public EsIndex getIndex(String index) {
|
||||||
// NOCOMMIT we need to think really carefully about how we deal with aliases that resolve into multiple indices.
|
// NOCOMMIT we need to think really carefully about how we deal with aliases that resolve into multiple indices.
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
*/
|
*/
|
||||||
package org.elasticsearch.xpack.sql.plan.logical.command;
|
package org.elasticsearch.xpack.sql.plan.logical.command;
|
||||||
|
|
||||||
|
import org.elasticsearch.xpack.sql.SqlIllegalArgumentException;
|
||||||
import org.elasticsearch.xpack.sql.analysis.catalog.Catalog;
|
import org.elasticsearch.xpack.sql.analysis.catalog.Catalog;
|
||||||
import org.elasticsearch.xpack.sql.analysis.catalog.EsIndex;
|
import org.elasticsearch.xpack.sql.analysis.catalog.EsIndex;
|
||||||
import org.elasticsearch.xpack.sql.expression.Attribute;
|
import org.elasticsearch.xpack.sql.expression.Attribute;
|
||||||
|
@ -48,7 +49,12 @@ public class ShowColumns extends Command {
|
||||||
protected RowSetCursor execute(SqlSession session) {
|
protected RowSetCursor execute(SqlSession session) {
|
||||||
Catalog catalog = session.catalog();
|
Catalog catalog = session.catalog();
|
||||||
List<List<?>> rows = new ArrayList<>();
|
List<List<?>> rows = new ArrayList<>();
|
||||||
EsIndex fetched = catalog.getIndex(index);
|
EsIndex fetched;
|
||||||
|
try {
|
||||||
|
fetched = catalog.getIndex(index);
|
||||||
|
} catch (SqlIllegalArgumentException e) {
|
||||||
|
throw new IllegalArgumentException(e);
|
||||||
|
}
|
||||||
if (fetched != null) {
|
if (fetched != null) {
|
||||||
fillInRows(fetched.mapping(), null, rows);
|
fillInRows(fetched.mapping(), null, rows);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,14 +34,8 @@ class InMemoryCatalog implements Catalog {
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean indexIsValid(String index) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EsIndex getIndex(String index) {
|
public EsIndex getIndex(String index) {
|
||||||
return indices.get(index);
|
return indices.get(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue