use of io.crate.analyze.expressions.TableReferenceResolver in project crate by crate.
the class DocIndexMetaData method initializeGeneratedExpressions.
private void initializeGeneratedExpressions() {
if (generatedColumnReferences.isEmpty()) {
return;
}
Collection<Reference> references = this.references.values();
TableReferenceResolver tableReferenceResolver = new TableReferenceResolver(references);
ExpressionAnalyzer expressionAnalyzer = new ExpressionAnalyzer(functions, SessionContext.SYSTEM_SESSION, ParamTypeHints.EMPTY, tableReferenceResolver, null);
ExpressionAnalysisContext context = new ExpressionAnalysisContext();
for (Reference reference : generatedColumnReferences) {
GeneratedReference generatedReference = (GeneratedReference) reference;
Expression expression = SqlParser.createExpression(generatedReference.formattedGeneratedExpression());
generatedReference.generatedExpression(expressionAnalyzer.convert(expression, context));
generatedReference.referencedReferences(ImmutableList.copyOf(tableReferenceResolver.references()));
tableReferenceResolver.references().clear();
}
}
use of io.crate.analyze.expressions.TableReferenceResolver in project crate by crate.
the class AlterTableAddColumnAnalyzer method analyze.
public AnalyzedAlterTableAddColumn analyze(AlterTableAddColumn<Expression> alterTable, ParamTypeHints paramTypeHints, CoordinatorTxnCtx txnCtx) {
if (!alterTable.table().partitionProperties().isEmpty()) {
throw new UnsupportedOperationException("Adding a column to a single partition is not supported");
}
DocTableInfo tableInfo = (DocTableInfo) schemas.resolveTableInfo(alterTable.table().getName(), Operation.ALTER, txnCtx.sessionContext().sessionUser(), txnCtx.sessionContext().searchPath());
TableReferenceResolver referenceResolver = new TableReferenceResolver(tableInfo.columns(), tableInfo.ident());
var exprAnalyzerWithReferenceResolver = new ExpressionAnalyzer(txnCtx, nodeCtx, paramTypeHints, referenceResolver, null);
var exprAnalyzerWithFieldsAsString = new ExpressionAnalyzer(txnCtx, nodeCtx, paramTypeHints, FieldProvider.FIELDS_AS_LITERAL, null);
var exprCtx = new ExpressionAnalysisContext(txnCtx.sessionContext());
AddColumnDefinition<Expression> tableElement = alterTable.tableElement();
// convert and validate the column name
ExpressionToColumnIdentVisitor.convert(tableElement.name());
// 1st phase, exclude check constraints (their expressions contain column references) and generated expressions
AddColumnDefinition<Symbol> addColumnDefinition = new AddColumnDefinition<>(exprAnalyzerWithFieldsAsString.convert(tableElement.name(), exprCtx), // expression must be mapped later on using mapExpressions()
null, tableElement.type() == null ? null : tableElement.type().map(y -> exprAnalyzerWithFieldsAsString.convert(y, exprCtx)), tableElement.constraints().stream().filter(c -> false == c instanceof CheckColumnConstraint).map(x -> x.map(y -> exprAnalyzerWithFieldsAsString.convert(y, exprCtx))).collect(Collectors.toList()), false, tableElement.generatedExpression() != null);
AnalyzedTableElements<Symbol> analyzedTableElements = TableElementsAnalyzer.analyze(singletonList(addColumnDefinition), tableInfo.ident(), tableInfo);
// 2nd phase, analyze possible generated expressions
AddColumnDefinition<Symbol> addColumnDefinitionWithExpression = (AddColumnDefinition<Symbol>) tableElement.mapExpressions(addColumnDefinition, x -> exprAnalyzerWithReferenceResolver.convert(x, exprCtx));
AnalyzedTableElements<Symbol> analyzedTableElementsWithExpressions = TableElementsAnalyzer.analyze(singletonList(addColumnDefinitionWithExpression), tableInfo.ident(), tableInfo);
// now analyze possible check expressions
var checkColumnConstraintsAnalyzer = new ExpressionAnalyzer(txnCtx, nodeCtx, paramTypeHints, new SelfReferenceFieldProvider(tableInfo.ident(), referenceResolver, analyzedTableElements.columns()), null);
tableElement.constraints().stream().filter(CheckColumnConstraint.class::isInstance).map(x -> x.map(y -> checkColumnConstraintsAnalyzer.convert(y, exprCtx))).forEach(c -> {
CheckColumnConstraint<Symbol> check = (CheckColumnConstraint<Symbol>) c;
analyzedTableElements.addCheckColumnConstraint(tableInfo.ident(), check);
analyzedTableElementsWithExpressions.addCheckColumnConstraint(tableInfo.ident(), check);
});
return new AnalyzedAlterTableAddColumn(tableInfo, analyzedTableElements, analyzedTableElementsWithExpressions);
}
use of io.crate.analyze.expressions.TableReferenceResolver in project crate by crate.
the class DocIndexMetadata method build.
public DocIndexMetadata build() {
notNullColumns = getNotNullColumns();
columnPolicy = getColumnPolicy();
createColumnDefinitions();
indices = createIndexDefinitions();
references = new LinkedHashMap<>();
DocSysColumns.forTable(ident, references::put);
columns.sort(SORT_REFS_BY_POSTITON_THEN_NAME);
nestedColumns.sort(SORT_REFS_BY_POSTITON_THEN_NAME);
for (Reference ref : columns) {
references.put(ref.column(), ref);
for (Reference nestedColumn : nestedColumns) {
if (nestedColumn.column().getRoot().equals(ref.column())) {
references.put(nestedColumn.column(), nestedColumn);
}
}
}
// Order of the partitionedByColumns is important; Must be the same order as `partitionedBy` is in.
partitionedByColumns = Lists2.map(partitionedBy, references::get);
generatedColumnReferences = List.copyOf(generatedColumnReferencesBuilder);
primaryKey = getPrimaryKey();
routingCol = getRoutingCol();
Collection<Reference> references = this.references.values();
TableReferenceResolver tableReferenceResolver = new TableReferenceResolver(references, ident);
CoordinatorTxnCtx txnCtx = CoordinatorTxnCtx.systemTransactionContext();
ExpressionAnalyzer exprAnalyzer = new ExpressionAnalyzer(txnCtx, nodeCtx, ParamTypeHints.EMPTY, tableReferenceResolver, null);
ExpressionAnalysisContext analysisCtx = new ExpressionAnalysisContext(txnCtx.sessionContext());
ArrayList<CheckConstraint<Symbol>> checkConstraintsBuilder = null;
Map<String, Object> metaMap = Maps.get(mappingMap, "_meta");
if (metaMap != null) {
Map<String, String> checkConstraintsMap = Maps.get(metaMap, "check_constraints");
if (checkConstraintsMap != null) {
checkConstraintsBuilder = new ArrayList<>();
for (Map.Entry<String, String> entry : checkConstraintsMap.entrySet()) {
String name = entry.getKey();
String expressionStr = entry.getValue();
Expression expr = SqlParser.createExpression(expressionStr);
Symbol analyzedExpr = exprAnalyzer.convert(expr, analysisCtx);
checkConstraintsBuilder.add(new CheckConstraint<>(name, null, analyzedExpr, expressionStr));
}
}
}
checkConstraints = checkConstraintsBuilder != null ? List.copyOf(checkConstraintsBuilder) : List.of();
for (Reference reference : generatedColumnReferences) {
GeneratedReference generatedReference = (GeneratedReference) reference;
Expression expression = SqlParser.createExpression(generatedReference.formattedGeneratedExpression());
generatedReference.generatedExpression(exprAnalyzer.convert(expression, analysisCtx));
generatedReference.referencedReferences(List.copyOf(tableReferenceResolver.references()));
tableReferenceResolver.references().clear();
}
return this;
}
use of io.crate.analyze.expressions.TableReferenceResolver in project crate by crate.
the class AnalyzedTableElements method validateGeneratedColumns.
private void validateGeneratedColumns(TableIdent tableIdent, Collection<? extends Reference> existingColumns, Functions functions, ParameterContext parameterContext, SessionContext sessionContext) {
List<Reference> tableReferences = new ArrayList<>();
for (AnalyzedColumnDefinition columnDefinition : columns) {
buildReference(tableIdent, columnDefinition, tableReferences);
}
tableReferences.addAll(existingColumns);
TableReferenceResolver tableReferenceResolver = new TableReferenceResolver(tableReferences);
ExpressionAnalyzer expressionAnalyzer = new ExpressionAnalyzer(functions, sessionContext, parameterContext, tableReferenceResolver, null);
SymbolPrinter printer = new SymbolPrinter(functions);
ExpressionAnalysisContext expressionAnalysisContext = new ExpressionAnalysisContext();
for (AnalyzedColumnDefinition columnDefinition : columns) {
if (columnDefinition.generatedExpression() != null) {
processGeneratedExpression(expressionAnalyzer, printer, columnDefinition, expressionAnalysisContext);
}
}
}
use of io.crate.analyze.expressions.TableReferenceResolver in project crate by crate.
the class UserDefinedFunctionService method validateFunctionIsNotInUseByGeneratedColumn.
void validateFunctionIsNotInUseByGeneratedColumn(String schema, String functionName, UserDefinedFunctionsMetadata functionsMetadata, ClusterState currentState) {
// The iteration of schemas/tables must happen on the node context WITHOUT the UDF already removed.
// Otherwise the lazy table factories will already fail while evaluating generated functionsMetadata.
// To avoid that, a copy of the node context with the removed UDF function is used on concrete expression evaluation.
var nodeCtxWithRemovedFunction = new NodeContext(nodeCtx.functions().copyOf());
updateImplementations(schema, functionsMetadata.functionsMetadata().stream(), nodeCtxWithRemovedFunction);
var metadata = currentState.metadata();
var indices = Stream.of(metadata.getConcreteAllIndices()).filter(NO_BLOB_NOR_DANGLING).map(IndexParts::new).filter(indexParts -> !indexParts.isPartitioned()).collect(Collectors.toList());
var templates = metadata.getTemplates().keysIt();
while (templates.hasNext()) {
var indexParts = new IndexParts(templates.next());
if (indexParts.isPartitioned()) {
indices.add(indexParts);
}
}
var indexNameExpressionResolver = new IndexNameExpressionResolver();
for (var indexParts : indices) {
var tableInfo = new DocTableInfoBuilder(nodeCtx, indexParts.toRelationName(), currentState, indexNameExpressionResolver).build();
TableReferenceResolver tableReferenceResolver = new TableReferenceResolver(tableInfo.columns(), tableInfo.ident());
CoordinatorTxnCtx coordinatorTxnCtx = CoordinatorTxnCtx.systemTransactionContext();
ExpressionAnalyzer exprAnalyzer = new ExpressionAnalyzer(coordinatorTxnCtx, nodeCtxWithRemovedFunction, ParamTypeHints.EMPTY, tableReferenceResolver, null);
for (var ref : tableInfo.columns()) {
if (ref instanceof GeneratedReference) {
var genRef = (GeneratedReference) ref;
Expression expression = SqlParser.createExpression(genRef.formattedGeneratedExpression());
try {
exprAnalyzer.convert(expression, new ExpressionAnalysisContext(coordinatorTxnCtx.sessionContext()));
} catch (UnsupportedOperationException e) {
throw new IllegalArgumentException("Cannot drop function '" + functionName + "', it is still in use by '" + tableInfo + "." + genRef + "'");
}
}
}
}
}
Aggregations