use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.tools.ValidationException in project druid by druid-io.
the class DruidPlanner method validate.
/**
* Validates a SQL query and populates {@link PlannerContext#getResourceActions()}.
*
* @return set of {@link Resource} corresponding to any Druid datasources or views which are taking part in the query.
*/
public ValidationResult validate() throws SqlParseException, ValidationException {
resetPlanner();
final ParsedNodes parsed = ParsedNodes.create(planner.parse(plannerContext.getSql()));
final SqlValidator validator = getValidator();
final SqlNode validatedQueryNode;
try {
validatedQueryNode = validator.validate(rewriteDynamicParameters(parsed.getQueryNode()));
} catch (RuntimeException e) {
throw new ValidationException(e);
}
SqlResourceCollectorShuttle resourceCollectorShuttle = new SqlResourceCollectorShuttle(validator, plannerContext);
validatedQueryNode.accept(resourceCollectorShuttle);
final Set<ResourceAction> resourceActions = new HashSet<>(resourceCollectorShuttle.getResourceActions());
if (parsed.getInsertNode() != null) {
final String targetDataSource = validateAndGetDataSourceForInsert(parsed.getInsertNode());
resourceActions.add(new ResourceAction(new Resource(targetDataSource, ResourceType.DATASOURCE), Action.WRITE));
}
plannerContext.setResourceActions(resourceActions);
return new ValidationResult(resourceActions);
}
use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.tools.ValidationException in project druid by druid-io.
the class DruidPlanner method validateAndGetDataSourceForInsert.
/**
* Extract target datasource from a {@link SqlInsert}, and also validate that the INSERT is of a form we support.
* Expects the INSERT target to be either an unqualified name, or a name qualified by the default schema.
*/
private String validateAndGetDataSourceForInsert(final SqlInsert insert) throws ValidationException {
if (insert.isUpsert()) {
throw new ValidationException("UPSERT is not supported.");
}
if (insert.getTargetColumnList() != null) {
throw new ValidationException("INSERT with target column list is not supported.");
}
final SqlIdentifier tableIdentifier = (SqlIdentifier) insert.getTargetTable();
final String dataSource;
if (tableIdentifier.names.isEmpty()) {
// I don't think this can happen, but include a branch for it just in case.
throw new ValidationException("INSERT requires target table.");
} else if (tableIdentifier.names.size() == 1) {
// Unqualified name.
dataSource = Iterables.getOnlyElement(tableIdentifier.names);
} else {
// Qualified name.
final String defaultSchemaName = Iterables.getOnlyElement(CalciteSchema.from(frameworkConfig.getDefaultSchema()).path(null));
if (tableIdentifier.names.size() == 2 && defaultSchemaName.equals(tableIdentifier.names.get(0))) {
dataSource = tableIdentifier.names.get(1);
} else {
throw new ValidationException(StringUtils.format("Cannot INSERT into [%s] because it is not a Druid datasource.", tableIdentifier));
}
}
try {
IdUtils.validateId("INSERT dataSource", dataSource);
} catch (IllegalArgumentException e) {
throw new ValidationException(e.getMessage());
}
return dataSource;
}
use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.tools.ValidationException in project druid by druid-io.
the class DruidPlanner method plan.
public PlannerResult plan(final String sql) throws SqlParseException, ValidationException, RelConversionException {
SqlExplain explain = null;
SqlNode parsed = planner.parse(sql);
if (parsed.getKind() == SqlKind.EXPLAIN) {
explain = (SqlExplain) parsed;
parsed = explain.getExplicandum();
}
final SqlNode validated = planner.validate(parsed);
final RelRoot root = planner.rel(validated);
try {
return planWithDruidConvention(explain, root);
} catch (RelOptPlanner.CannotPlanException e) {
// Try again with BINDABLE convention. Used for querying Values, metadata tables, and fallback.
try {
return planWithBindableConvention(explain, root);
} catch (Exception e2) {
e.addSuppressed(e2);
throw e;
}
}
}
use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.tools.ValidationException in project calcite by apache.
the class PlannerImpl method validate.
public SqlNode validate(SqlNode sqlNode) throws ValidationException {
ensure(State.STATE_3_PARSED);
final SqlConformance conformance = conformance();
final CalciteCatalogReader catalogReader = createCatalogReader();
this.validator = new CalciteSqlValidator(operatorTable, catalogReader, typeFactory, conformance);
this.validator.setIdentifierExpansion(true);
try {
validatedSqlNode = validator.validate(sqlNode);
} catch (RuntimeException e) {
throw new ValidationException(e);
}
state = State.STATE_4_VALIDATED;
return validatedSqlNode;
}
use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.tools.ValidationException in project druid by druid-io.
the class DruidPlanner method plan.
/**
* Plan an SQL query for execution, returning a {@link PlannerResult} which can be used to actually execute the query.
*
* Ideally, the query can be planned into a native Druid query, using {@link #planWithDruidConvention}, but will
* fall-back to {@link #planWithBindableConvention} if this is not possible.
*
* In some future this could perhaps re-use some of the work done by {@link #validate()}
* instead of repeating it, but that day is not today.
*/
public PlannerResult plan() throws SqlParseException, ValidationException, RelConversionException {
resetPlanner();
final ParsedNodes parsed = ParsedNodes.create(planner.parse(plannerContext.getSql()));
try {
if (parsed.getIngestionGranularity() != null) {
plannerContext.getQueryContext().put(DruidSqlInsert.SQL_INSERT_SEGMENT_GRANULARITY, plannerContext.getJsonMapper().writeValueAsString(parsed.getIngestionGranularity()));
}
} catch (JsonProcessingException e) {
throw new ValidationException("Unable to serialize partition granularity.");
}
// the planner's type factory is not available until after parsing
this.rexBuilder = new RexBuilder(planner.getTypeFactory());
final SqlNode parameterizedQueryNode = rewriteDynamicParameters(parsed.getQueryNode());
final SqlNode validatedQueryNode = planner.validate(parameterizedQueryNode);
final RelRoot rootQueryRel = planner.rel(validatedQueryNode);
try {
return planWithDruidConvention(rootQueryRel, parsed.getExplainNode(), parsed.getInsertNode());
} catch (Exception e) {
Throwable cannotPlanException = Throwables.getCauseOfType(e, RelOptPlanner.CannotPlanException.class);
if (null == cannotPlanException) {
// Not a CannotPlanningException, rethrow without trying with bindable
throw e;
}
// any error, if it is plannable by the bindable convention
if (parsed.getInsertNode() == null) {
// Try again with BINDABLE convention. Used for querying Values and metadata tables.
try {
return planWithBindableConvention(rootQueryRel, parsed.getExplainNode());
} catch (Exception e2) {
e.addSuppressed(e2);
}
}
Logger logger = log;
if (!QueryContexts.isDebug(plannerContext.getQueryContext())) {
logger = log.noStackTrace();
}
String errorMessage = buildSQLPlanningErrorMessage(cannotPlanException);
logger.warn(e, errorMessage);
throw new UnsupportedSQLQueryException(errorMessage);
}
}
Aggregations