use of io.trino.sql.tree.Expression in project trino by trinodb.
the class InlineProjections method extractInliningTargets.
private static Set<Symbol> extractInliningTargets(PlannerContext plannerContext, ProjectNode parent, ProjectNode child, Session session, TypeAnalyzer typeAnalyzer, TypeProvider types) {
// candidates for inlining are
// 1. references to simple constants or symbol references
// 2. references to complex expressions that
// a. are not inputs to try() expressions
// b. appear only once across all expressions
// c. are not identity projections
// which come from the child, as opposed to an enclosing scope.
Set<Symbol> childOutputSet = ImmutableSet.copyOf(child.getOutputSymbols());
Map<Symbol, Long> dependencies = parent.getAssignments().getExpressions().stream().flatMap(expression -> SymbolsExtractor.extractAll(expression).stream()).filter(childOutputSet::contains).collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
// find references to simple constants or symbol references
Set<Symbol> basicReferences = dependencies.keySet().stream().filter(input -> isEffectivelyLiteral(plannerContext, session, child.getAssignments().get(input)) || child.getAssignments().get(input) instanceof SymbolReference).filter(// skip identities, otherwise, this rule will keep firing forever
input -> !child.getAssignments().isIdentity(input)).collect(toSet());
// exclude any complex inputs to TRY expressions. Inlining them would potentially
// change the semantics of those expressions
Set<Symbol> tryArguments = parent.getAssignments().getExpressions().stream().flatMap(expression -> extractTryArguments(expression).stream()).collect(toSet());
Set<Symbol> singletons = dependencies.entrySet().stream().filter(// reference appears just once across all expressions in parent project node
entry -> entry.getValue() == 1).filter(// they are not inputs to TRY. Otherwise, inlining might change semantics
entry -> !tryArguments.contains(entry.getKey())).filter(// skip identities, otherwise, this rule will keep firing forever
entry -> !child.getAssignments().isIdentity(entry.getKey())).filter(entry -> {
// skip dereferences, otherwise, inlining can cause conflicts with PushdownDereferences
Expression assignment = child.getAssignments().get(entry.getKey());
if (assignment instanceof SubscriptExpression) {
if (typeAnalyzer.getType(session, types, ((SubscriptExpression) assignment).getBase()) instanceof RowType) {
return false;
}
}
return true;
}).map(Map.Entry::getKey).collect(toSet());
return Sets.union(singletons, basicReferences);
}
use of io.trino.sql.tree.Expression in project trino by trinodb.
the class PruneApplyColumns method pushDownProjectOff.
@Override
protected Optional<PlanNode> pushDownProjectOff(Context context, ApplyNode applyNode, Set<Symbol> referencedOutputs) {
// remove unused apply node
if (intersection(applyNode.getSubqueryAssignments().getSymbols(), referencedOutputs).isEmpty()) {
return Optional.of(applyNode.getInput());
}
// extract referenced assignments
ImmutableSet.Builder<Symbol> requiredAssignmentsSymbols = ImmutableSet.builder();
Assignments.Builder newSubqueryAssignments = Assignments.builder();
for (Map.Entry<Symbol, Expression> entry : applyNode.getSubqueryAssignments().entrySet()) {
if (referencedOutputs.contains(entry.getKey())) {
requiredAssignmentsSymbols.addAll(extractUnique(entry.getValue()));
newSubqueryAssignments.put(entry);
}
}
// prune subquery symbols
Optional<PlanNode> newSubquery = restrictOutputs(context.getIdAllocator(), applyNode.getSubquery(), requiredAssignmentsSymbols.build());
// prune input symbols
Set<Symbol> requiredInputSymbols = ImmutableSet.<Symbol>builder().addAll(referencedOutputs).addAll(applyNode.getCorrelation()).addAll(requiredAssignmentsSymbols.build()).build();
Optional<PlanNode> newInput = restrictOutputs(context.getIdAllocator(), applyNode.getInput(), requiredInputSymbols);
boolean pruned = newSubquery.isPresent() || newInput.isPresent() || newSubqueryAssignments.build().size() < applyNode.getSubqueryAssignments().size();
if (pruned) {
return Optional.of(new ApplyNode(applyNode.getId(), newInput.orElse(applyNode.getInput()), newSubquery.orElse(applyNode.getSubquery()), newSubqueryAssignments.build(), applyNode.getCorrelation(), applyNode.getOriginSubquery()));
}
return Optional.empty();
}
use of io.trino.sql.tree.Expression in project trino by trinodb.
the class RevokeRolesTask method execute.
@Override
public ListenableFuture<Void> execute(RevokeRoles statement, QueryStateMachine stateMachine, List<Expression> parameters, WarningCollector warningCollector) {
Session session = stateMachine.getSession();
Set<String> roles = statement.getRoles().stream().map(role -> role.getValue().toLowerCase(Locale.ENGLISH)).collect(toImmutableSet());
Set<TrinoPrincipal> grantees = statement.getGrantees().stream().map(MetadataUtil::createPrincipal).collect(toImmutableSet());
boolean adminOption = statement.isAdminOption();
Optional<TrinoPrincipal> grantor = statement.getGrantor().map(specification -> createPrincipal(session, specification));
Optional<String> catalog = processRoleCommandCatalog(metadata, session, statement, statement.getCatalog().map(Identifier::getValue));
Set<String> specifiedRoles = new LinkedHashSet<>();
specifiedRoles.addAll(roles);
grantees.stream().filter(principal -> principal.getType() == ROLE).map(TrinoPrincipal::getName).forEach(specifiedRoles::add);
if (grantor.isPresent() && grantor.get().getType() == ROLE) {
specifiedRoles.add(grantor.get().getName());
}
for (String role : specifiedRoles) {
checkRoleExists(session, statement, metadata, role, catalog);
}
accessControl.checkCanRevokeRoles(session.toSecurityContext(), roles, grantees, adminOption, grantor, catalog);
metadata.revokeRoles(session, roles, grantees, adminOption, grantor, catalog);
return immediateVoidFuture();
}
use of io.trino.sql.tree.Expression in project trino by trinodb.
the class SetSchemaAuthorizationTask method execute.
@Override
public ListenableFuture<Void> execute(SetSchemaAuthorization statement, QueryStateMachine stateMachine, List<Expression> parameters, WarningCollector warningCollector) {
Session session = stateMachine.getSession();
CatalogSchemaName source = createCatalogSchemaName(session, statement, Optional.of(statement.getSource()));
if (!metadata.schemaExists(session, source)) {
throw semanticException(SCHEMA_NOT_FOUND, statement, "Schema '%s' does not exist", source);
}
TrinoPrincipal principal = createPrincipal(statement.getPrincipal());
checkRoleExists(session, statement, metadata, principal, Optional.of(source.getCatalogName()).filter(catalog -> metadata.isCatalogManagedSecurity(session, catalog)));
accessControl.checkCanSetSchemaAuthorization(session.toSecurityContext(), source, principal);
metadata.setSchemaAuthorization(session, source, principal);
return immediateVoidFuture();
}
use of io.trino.sql.tree.Expression in project trino by trinodb.
the class SetTableAuthorizationTask method execute.
@Override
public ListenableFuture<Void> execute(SetTableAuthorization statement, QueryStateMachine stateMachine, List<Expression> parameters, WarningCollector warningCollector) {
Session session = stateMachine.getSession();
QualifiedObjectName tableName = createQualifiedObjectName(session, statement, statement.getSource());
getRequiredCatalogHandle(metadata, session, statement, tableName.getCatalogName());
if (metadata.getTableHandle(session, tableName).isEmpty()) {
throw semanticException(TABLE_NOT_FOUND, statement, "Table '%s' does not exist", tableName);
}
TrinoPrincipal principal = createPrincipal(statement.getPrincipal());
checkRoleExists(session, statement, metadata, principal, Optional.of(tableName.getCatalogName()).filter(catalog -> metadata.isCatalogManagedSecurity(session, catalog)));
accessControl.checkCanSetTableAuthorization(session.toSecurityContext(), tableName, principal);
metadata.setTableAuthorization(session, tableName.asCatalogSchemaTableName(), principal);
return immediateVoidFuture();
}
Aggregations