use of io.crate.analyze.expressions.SubqueryAnalyzer in project crate by crate.
the class RelationAnalyzer method visitQuery.
@Override
protected AnalyzedRelation visitQuery(Query node, StatementAnalysisContext statementContext) {
AnalyzedRelation childRelation = node.getQueryBody().accept(this, statementContext);
if (node.getOrderBy().isEmpty() && node.getLimit().isEmpty() && node.getOffset().isEmpty()) {
return childRelation;
}
// In case of Set Operation (UNION, INTERSECT EXCEPT) or VALUES clause,
// the `node` contains the ORDER BY and/or LIMIT and/or OFFSET and wraps the
// actual operation (eg: UNION) which is parsed into the `queryBody` of the `node`.
// Use child relation to process expressions of the "root" Query node
statementContext.startRelation();
RelationAnalysisContext relationAnalysisContext = statementContext.currentRelationContext();
relationAnalysisContext.addSourceRelation(childRelation);
statementContext.endRelation();
List<Symbol> childRelationFields = childRelation.outputs();
var coordinatorTxnCtx = statementContext.transactionContext();
ExpressionAnalyzer expressionAnalyzer = new ExpressionAnalyzer(coordinatorTxnCtx, nodeCtx, statementContext.paramTyeHints(), new FullQualifiedNameFieldProvider(relationAnalysisContext.sources(), relationAnalysisContext.parentSources(), coordinatorTxnCtx.sessionContext().searchPath().currentSchema()), new SubqueryAnalyzer(this, statementContext));
ExpressionAnalysisContext expressionAnalysisContext = relationAnalysisContext.expressionAnalysisContext();
SelectAnalysis selectAnalysis = new SelectAnalysis(childRelationFields.size(), relationAnalysisContext.sources(), expressionAnalyzer, expressionAnalysisContext);
for (Symbol field : childRelationFields) {
selectAnalysis.add(Symbols.pathFromSymbol(field), field);
}
var normalizer = EvaluatingNormalizer.functionOnlyNormalizer(nodeCtx, f -> expressionAnalysisContext.isEagerNormalizationAllowed() && f.isDeterministic());
return new QueriedSelectRelation(false, List.of(childRelation), List.of(), selectAnalysis.outputSymbols(), Literal.BOOLEAN_TRUE, List.of(), null, analyzeOrderBy(selectAnalysis, node.getOrderBy(), expressionAnalyzer, expressionAnalysisContext, false, false), longSymbolOrNull(node.getLimit(), expressionAnalyzer, expressionAnalysisContext, normalizer, coordinatorTxnCtx), longSymbolOrNull(node.getOffset(), expressionAnalyzer, expressionAnalysisContext, normalizer, coordinatorTxnCtx));
}
use of io.crate.analyze.expressions.SubqueryAnalyzer in project crate by crate.
the class DeleteAnalyzer method analyze.
public AnalyzedDeleteStatement analyze(Delete delete, ParamTypeHints typeHints, CoordinatorTxnCtx txnContext) {
StatementAnalysisContext stmtCtx = new StatementAnalysisContext(typeHints, Operation.DELETE, txnContext);
final RelationAnalysisContext relationCtx = stmtCtx.startRelation();
AnalyzedRelation relation = relationAnalyzer.analyze(delete.getRelation(), stmtCtx);
stmtCtx.endRelation();
MaybeAliasedStatement maybeAliasedStatement = MaybeAliasedStatement.analyze(relation);
relation = maybeAliasedStatement.nonAliasedRelation();
if (!(relation instanceof DocTableRelation)) {
throw new UnsupportedOperationException("Cannot delete from relations other than base tables");
}
DocTableRelation table = (DocTableRelation) relation;
EvaluatingNormalizer normalizer = new EvaluatingNormalizer(nodeCtx, RowGranularity.CLUSTER, null, table);
ExpressionAnalyzer expressionAnalyzer = new ExpressionAnalyzer(txnContext, nodeCtx, typeHints, new FullQualifiedNameFieldProvider(relationCtx.sources(), relationCtx.parentSources(), txnContext.sessionContext().searchPath().currentSchema()), new SubqueryAnalyzer(relationAnalyzer, new StatementAnalysisContext(typeHints, Operation.READ, txnContext)));
Symbol query = Objects.requireNonNullElse(expressionAnalyzer.generateQuerySymbol(delete.getWhere(), new ExpressionAnalysisContext(txnContext.sessionContext())), Literal.BOOLEAN_TRUE);
query = maybeAliasedStatement.maybeMapFields(query);
Symbol normalizedQuery = normalizer.normalize(query, txnContext);
return new AnalyzedDeleteStatement(table, normalizedQuery);
}
use of io.crate.analyze.expressions.SubqueryAnalyzer in project crate by crate.
the class SQLExecutor method asSymbol.
/**
* Convert a expression to a symbol
* If tables are used here they must also be registered in the SQLExecutor having used {@link Builder#addTable(String)}
*/
public Symbol asSymbol(String expression) {
MapBuilder<RelationName, AnalyzedRelation> sources = MapBuilder.newMapBuilder();
for (SchemaInfo schemaInfo : schemas) {
for (TableInfo tableInfo : schemaInfo.getTables()) {
if (tableInfo instanceof DocTableInfo) {
RelationName relationName = tableInfo.ident();
sources.put(relationName, new DocTableRelation(schemas.getTableInfo(relationName)));
}
}
}
CoordinatorTxnCtx coordinatorTxnCtx = new CoordinatorTxnCtx(sessionContext);
ExpressionAnalyzer expressionAnalyzer = new ExpressionAnalyzer(coordinatorTxnCtx, nodeCtx, ParamTypeHints.EMPTY, new FullQualifiedNameFieldProvider(sources.immutableMap(), ParentRelations.NO_PARENTS, sessionContext.searchPath().currentSchema()), new SubqueryAnalyzer(relAnalyzer, new StatementAnalysisContext(ParamTypeHints.EMPTY, Operation.READ, coordinatorTxnCtx)));
ExpressionAnalysisContext expressionAnalysisContext = new ExpressionAnalysisContext(coordinatorTxnCtx.sessionContext());
return expressionAnalyzer.convert(SqlParser.createExpression(expression), expressionAnalysisContext);
}
use of io.crate.analyze.expressions.SubqueryAnalyzer in project crate by crate.
the class RelationAnalyzer method visitQuerySpecification.
@Override
protected AnalyzedRelation visitQuerySpecification(QuerySpecification node, StatementAnalysisContext statementContext) {
List<Relation> from = node.getFrom().isEmpty() ? EMPTY_ROW_TABLE_RELATION : node.getFrom();
RelationAnalysisContext currentRelationContext = statementContext.startRelation();
for (Relation relation : from) {
// different from relations have to be isolated from each other
RelationAnalysisContext innerContext = statementContext.startRelation();
relation.accept(this, statementContext);
statementContext.endRelation();
for (Map.Entry<RelationName, AnalyzedRelation> entry : innerContext.sources().entrySet()) {
currentRelationContext.addSourceRelation(entry.getValue());
}
for (JoinPair joinPair : innerContext.joinPairs()) {
currentRelationContext.addJoinPair(joinPair);
}
}
RelationAnalysisContext context = statementContext.currentRelationContext();
CoordinatorTxnCtx coordinatorTxnCtx = statementContext.transactionContext();
ExpressionAnalyzer expressionAnalyzer = new ExpressionAnalyzer(coordinatorTxnCtx, nodeCtx, statementContext.paramTyeHints(), new FullQualifiedNameFieldProvider(context.sources(), context.parentSources(), coordinatorTxnCtx.sessionContext().searchPath().currentSchema()), new SubqueryAnalyzer(this, statementContext));
ExpressionAnalysisContext expressionAnalysisContext = context.expressionAnalysisContext();
expressionAnalysisContext.windows(node.getWindows());
SelectAnalysis selectAnalysis = SelectAnalyzer.analyzeSelectItems(node.getSelect().getSelectItems(), context.sources(), expressionAnalyzer, expressionAnalysisContext);
List<Symbol> groupBy = analyzeGroupBy(selectAnalysis, node.getGroupBy(), expressionAnalyzer, expressionAnalysisContext);
if (!node.getGroupBy().isEmpty() || expressionAnalysisContext.hasAggregates()) {
GroupAndAggregateSemantics.validate(selectAnalysis.outputSymbols(), groupBy);
}
boolean isDistinct = node.getSelect().isDistinct();
Symbol where = expressionAnalyzer.generateQuerySymbol(node.getWhere(), expressionAnalysisContext);
WhereClauseValidator.validate(where);
var normalizer = EvaluatingNormalizer.functionOnlyNormalizer(nodeCtx, f -> expressionAnalysisContext.isEagerNormalizationAllowed() && f.isDeterministic());
QueriedSelectRelation relation = new QueriedSelectRelation(isDistinct, List.copyOf(context.sources().values()), context.joinPairs(), selectAnalysis.outputSymbols(), where, groupBy, analyzeHaving(node.getHaving(), groupBy, expressionAnalyzer, context.expressionAnalysisContext()), analyzeOrderBy(selectAnalysis, node.getOrderBy(), expressionAnalyzer, expressionAnalysisContext, expressionAnalysisContext.hasAggregates() || !groupBy.isEmpty(), isDistinct), longSymbolOrNull(node.getLimit(), expressionAnalyzer, expressionAnalysisContext, normalizer, coordinatorTxnCtx), longSymbolOrNull(node.getOffset(), expressionAnalyzer, expressionAnalysisContext, normalizer, coordinatorTxnCtx));
statementContext.endRelation();
return relation;
}
use of io.crate.analyze.expressions.SubqueryAnalyzer in project crate by crate.
the class RelationAnalyzer method visitJoin.
@Override
protected AnalyzedRelation visitJoin(Join node, StatementAnalysisContext statementContext) {
AnalyzedRelation leftRel = node.getLeft().accept(this, statementContext);
AnalyzedRelation rightRel = node.getRight().accept(this, statementContext);
RelationAnalysisContext relationContext = statementContext.currentRelationContext();
Optional<JoinCriteria> optCriteria = node.getCriteria();
Symbol joinCondition = null;
if (optCriteria.isPresent()) {
JoinCriteria joinCriteria = optCriteria.get();
if (joinCriteria instanceof JoinOn || joinCriteria instanceof JoinUsing) {
final CoordinatorTxnCtx coordinatorTxnCtx = statementContext.transactionContext();
ExpressionAnalyzer expressionAnalyzer = new ExpressionAnalyzer(coordinatorTxnCtx, nodeCtx, statementContext.paramTyeHints(), new FullQualifiedNameFieldProvider(relationContext.sources(), relationContext.parentSources(), coordinatorTxnCtx.sessionContext().searchPath().currentSchema()), new SubqueryAnalyzer(this, statementContext));
Expression expr;
if (joinCriteria instanceof JoinOn) {
expr = ((JoinOn) joinCriteria).getExpression();
} else {
expr = JoinUsing.toExpression(leftRel.relationName().toQualifiedName(), rightRel.relationName().toQualifiedName(), ((JoinUsing) joinCriteria).getColumns());
}
try {
joinCondition = expressionAnalyzer.convert(expr, relationContext.expressionAnalysisContext());
} catch (RelationUnknown e) {
throw new RelationValidationException(e.getTableIdents(), String.format(Locale.ENGLISH, "missing FROM-clause entry for relation '%s'", e.getTableIdents()));
}
} else {
throw new UnsupportedOperationException(String.format(Locale.ENGLISH, "join criteria %s not supported", joinCriteria.getClass().getSimpleName()));
}
}
relationContext.addJoinType(JoinType.values()[node.getType().ordinal()], joinCondition);
return null;
}
Aggregations