use of io.trino.metadata.RedirectionAwareTableHandle in project trino by trinodb.
the class CreateTableTask method internalExecute.
@VisibleForTesting
ListenableFuture<Void> internalExecute(CreateTable statement, Session session, List<Expression> parameters, Consumer<Output> outputConsumer) {
checkArgument(!statement.getElements().isEmpty(), "no columns for table");
Map<NodeRef<Parameter>, Expression> parameterLookup = parameterExtractor(statement, parameters);
QualifiedObjectName tableName = createQualifiedObjectName(session, statement, statement.getName());
Optional<TableHandle> tableHandle = plannerContext.getMetadata().getTableHandle(session, tableName);
if (tableHandle.isPresent()) {
if (!statement.isNotExists()) {
throw semanticException(TABLE_ALREADY_EXISTS, statement, "Table '%s' already exists", tableName);
}
return immediateVoidFuture();
}
CatalogName catalogName = getRequiredCatalogHandle(plannerContext.getMetadata(), session, statement, tableName.getCatalogName());
LinkedHashMap<String, ColumnMetadata> columns = new LinkedHashMap<>();
Map<String, Object> inheritedProperties = ImmutableMap.of();
boolean includingProperties = false;
for (TableElement element : statement.getElements()) {
if (element instanceof ColumnDefinition) {
ColumnDefinition column = (ColumnDefinition) element;
String name = column.getName().getValue().toLowerCase(Locale.ENGLISH);
Type type;
try {
type = plannerContext.getTypeManager().getType(toTypeSignature(column.getType()));
} catch (TypeNotFoundException e) {
throw semanticException(TYPE_NOT_FOUND, element, "Unknown type '%s' for column '%s'", column.getType(), column.getName());
}
if (type.equals(UNKNOWN)) {
throw semanticException(COLUMN_TYPE_UNKNOWN, element, "Unknown type '%s' for column '%s'", column.getType(), column.getName());
}
if (columns.containsKey(name)) {
throw semanticException(DUPLICATE_COLUMN_NAME, column, "Column name '%s' specified more than once", column.getName());
}
if (!column.isNullable() && !plannerContext.getMetadata().getConnectorCapabilities(session, catalogName).contains(NOT_NULL_COLUMN_CONSTRAINT)) {
throw semanticException(NOT_SUPPORTED, column, "Catalog '%s' does not support non-null column for column name '%s'", catalogName.getCatalogName(), column.getName());
}
Map<String, Object> columnProperties = columnPropertyManager.getProperties(catalogName, column.getProperties(), session, plannerContext, accessControl, parameterLookup, true);
columns.put(name, ColumnMetadata.builder().setName(name).setType(type).setNullable(column.isNullable()).setComment(column.getComment()).setProperties(columnProperties).build());
} else if (element instanceof LikeClause) {
LikeClause likeClause = (LikeClause) element;
QualifiedObjectName originalLikeTableName = createQualifiedObjectName(session, statement, likeClause.getTableName());
if (plannerContext.getMetadata().getCatalogHandle(session, originalLikeTableName.getCatalogName()).isEmpty()) {
throw semanticException(CATALOG_NOT_FOUND, statement, "LIKE table catalog '%s' does not exist", originalLikeTableName.getCatalogName());
}
RedirectionAwareTableHandle redirection = plannerContext.getMetadata().getRedirectionAwareTableHandle(session, originalLikeTableName);
TableHandle likeTable = redirection.getTableHandle().orElseThrow(() -> semanticException(TABLE_NOT_FOUND, statement, "LIKE table '%s' does not exist", originalLikeTableName));
QualifiedObjectName likeTableName = redirection.getRedirectedTableName().orElse(originalLikeTableName);
if (!tableName.getCatalogName().equals(likeTableName.getCatalogName())) {
String message = "CREATE TABLE LIKE across catalogs is not supported";
if (!originalLikeTableName.equals(likeTableName)) {
message += format(". LIKE table '%s' redirected to '%s'.", originalLikeTableName, likeTableName);
}
throw semanticException(NOT_SUPPORTED, statement, message);
}
TableMetadata likeTableMetadata = plannerContext.getMetadata().getTableMetadata(session, likeTable);
Optional<LikeClause.PropertiesOption> propertiesOption = likeClause.getPropertiesOption();
if (propertiesOption.isPresent() && propertiesOption.get() == LikeClause.PropertiesOption.INCLUDING) {
if (includingProperties) {
throw semanticException(NOT_SUPPORTED, statement, "Only one LIKE clause can specify INCLUDING PROPERTIES");
}
includingProperties = true;
inheritedProperties = likeTableMetadata.getMetadata().getProperties();
}
try {
accessControl.checkCanSelectFromColumns(session.toSecurityContext(), likeTableName, likeTableMetadata.getColumns().stream().map(ColumnMetadata::getName).collect(toImmutableSet()));
} catch (AccessDeniedException e) {
throw new AccessDeniedException("Cannot reference columns of table " + likeTableName);
}
if (propertiesOption.orElse(EXCLUDING) == INCLUDING) {
try {
accessControl.checkCanShowCreateTable(session.toSecurityContext(), likeTableName);
} catch (AccessDeniedException e) {
throw new AccessDeniedException("Cannot reference properties of table " + likeTableName);
}
}
likeTableMetadata.getColumns().stream().filter(column -> !column.isHidden()).forEach(column -> {
if (columns.containsKey(column.getName().toLowerCase(Locale.ENGLISH))) {
throw semanticException(DUPLICATE_COLUMN_NAME, element, "Column name '%s' specified more than once", column.getName());
}
columns.put(column.getName().toLowerCase(Locale.ENGLISH), column);
});
} else {
throw new TrinoException(GENERIC_INTERNAL_ERROR, "Invalid TableElement: " + element.getClass().getName());
}
}
Map<String, Object> properties = tablePropertyManager.getProperties(catalogName, statement.getProperties(), session, plannerContext, accessControl, parameterLookup, true);
accessControl.checkCanCreateTable(session.toSecurityContext(), tableName, properties);
Set<String> specifiedPropertyKeys = statement.getProperties().stream().map(property -> property.getName().getValue()).collect(toImmutableSet());
Map<String, Object> finalProperties = combineProperties(specifiedPropertyKeys, properties, inheritedProperties);
ConnectorTableMetadata tableMetadata = new ConnectorTableMetadata(tableName.asSchemaTableName(), ImmutableList.copyOf(columns.values()), finalProperties, statement.getComment());
try {
plannerContext.getMetadata().createTable(session, tableName.getCatalogName(), tableMetadata, statement.isNotExists());
} catch (TrinoException e) {
// connectors are not required to handle the ignoreExisting flag
if (!e.getErrorCode().equals(ALREADY_EXISTS.toErrorCode()) || !statement.isNotExists()) {
throw e;
}
}
outputConsumer.accept(new Output(tableName.getCatalogName(), tableName.getSchemaName(), tableName.getObjectName(), Optional.of(tableMetadata.getColumns().stream().map(column -> new OutputColumn(new Column(column.getName(), column.getType().toString()), ImmutableSet.of())).collect(toImmutableList()))));
return immediateVoidFuture();
}
use of io.trino.metadata.RedirectionAwareTableHandle in project trino by trinodb.
the class DropTableTask method execute.
@Override
public ListenableFuture<Void> execute(DropTable statement, QueryStateMachine stateMachine, List<Expression> parameters, WarningCollector warningCollector) {
Session session = stateMachine.getSession();
QualifiedObjectName originalTableName = createQualifiedObjectName(session, statement, statement.getTableName());
if (metadata.isMaterializedView(session, originalTableName)) {
if (!statement.isExists()) {
throw semanticException(TABLE_NOT_FOUND, statement, "Table '%s' does not exist, but a materialized view with that name exists. Did you mean DROP MATERIALIZED VIEW %s?", originalTableName, originalTableName);
}
return immediateVoidFuture();
}
if (metadata.isView(session, originalTableName)) {
if (!statement.isExists()) {
throw semanticException(TABLE_NOT_FOUND, statement, "Table '%s' does not exist, but a view with that name exists. Did you mean DROP VIEW %s?", originalTableName, originalTableName);
}
return immediateVoidFuture();
}
RedirectionAwareTableHandle redirectionAwareTableHandle = metadata.getRedirectionAwareTableHandle(session, originalTableName);
if (redirectionAwareTableHandle.getTableHandle().isEmpty()) {
if (!statement.isExists()) {
throw semanticException(TABLE_NOT_FOUND, statement, "Table '%s' does not exist", originalTableName);
}
return immediateVoidFuture();
}
QualifiedObjectName tableName = redirectionAwareTableHandle.getRedirectedTableName().orElse(originalTableName);
accessControl.checkCanDropTable(session.toSecurityContext(), tableName);
metadata.dropTable(session, redirectionAwareTableHandle.getTableHandle().get());
return immediateVoidFuture();
}
use of io.trino.metadata.RedirectionAwareTableHandle in project trino by trinodb.
the class DropColumnTask method execute.
@Override
public ListenableFuture<Void> execute(DropColumn statement, QueryStateMachine stateMachine, List<Expression> parameters, WarningCollector warningCollector) {
Session session = stateMachine.getSession();
QualifiedObjectName tableName = createQualifiedObjectName(session, statement, statement.getTable());
RedirectionAwareTableHandle redirectionAwareTableHandle = metadata.getRedirectionAwareTableHandle(session, tableName);
if (redirectionAwareTableHandle.getTableHandle().isEmpty()) {
if (!statement.isTableExists()) {
throw semanticException(TABLE_NOT_FOUND, statement, "Table '%s' does not exist", tableName);
}
return immediateVoidFuture();
}
TableHandle tableHandle = redirectionAwareTableHandle.getTableHandle().get();
String column = statement.getColumn().getValue().toLowerCase(ENGLISH);
accessControl.checkCanDropColumn(session.toSecurityContext(), redirectionAwareTableHandle.getRedirectedTableName().orElse(tableName));
ColumnHandle columnHandle = metadata.getColumnHandles(session, tableHandle).get(column);
if (columnHandle == null) {
if (!statement.isColumnExists()) {
throw semanticException(COLUMN_NOT_FOUND, statement, "Column '%s' does not exist", column);
}
return immediateVoidFuture();
}
if (metadata.getColumnMetadata(session, tableHandle, columnHandle).isHidden()) {
throw semanticException(NOT_SUPPORTED, statement, "Cannot drop hidden column");
}
if (metadata.getTableMetadata(session, tableHandle).getColumns().stream().filter(info -> !info.isHidden()).count() <= 1) {
throw semanticException(NOT_SUPPORTED, statement, "Cannot drop the only column in a table");
}
metadata.dropColumn(session, tableHandle, columnHandle);
return immediateVoidFuture();
}
use of io.trino.metadata.RedirectionAwareTableHandle in project trino by trinodb.
the class RenameColumnTask method execute.
@Override
public ListenableFuture<Void> execute(RenameColumn statement, QueryStateMachine stateMachine, List<Expression> parameters, WarningCollector warningCollector) {
Session session = stateMachine.getSession();
QualifiedObjectName originalTableName = createQualifiedObjectName(session, statement, statement.getTable());
RedirectionAwareTableHandle redirectionAwareTableHandle = metadata.getRedirectionAwareTableHandle(session, originalTableName);
if (redirectionAwareTableHandle.getTableHandle().isEmpty()) {
if (!statement.isTableExists()) {
throw semanticException(TABLE_NOT_FOUND, statement, "Table '%s' does not exist", originalTableName);
}
return immediateVoidFuture();
}
TableHandle tableHandle = redirectionAwareTableHandle.getTableHandle().get();
String source = statement.getSource().getValue().toLowerCase(ENGLISH);
String target = statement.getTarget().getValue().toLowerCase(ENGLISH);
accessControl.checkCanRenameColumn(session.toSecurityContext(), redirectionAwareTableHandle.getRedirectedTableName().orElse(originalTableName));
Map<String, ColumnHandle> columnHandles = metadata.getColumnHandles(session, tableHandle);
ColumnHandle columnHandle = columnHandles.get(source);
if (columnHandle == null) {
if (!statement.isColumnExists()) {
throw semanticException(COLUMN_NOT_FOUND, statement, "Column '%s' does not exist", source);
}
return immediateVoidFuture();
}
if (columnHandles.containsKey(target)) {
throw semanticException(COLUMN_ALREADY_EXISTS, statement, "Column '%s' already exists", target);
}
if (metadata.getColumnMetadata(session, tableHandle, columnHandle).isHidden()) {
throw semanticException(NOT_SUPPORTED, statement, "Cannot rename hidden column");
}
metadata.renameColumn(session, tableHandle, columnHandle, target);
return immediateVoidFuture();
}
use of io.trino.metadata.RedirectionAwareTableHandle in project trino by trinodb.
the class AddColumnTask method execute.
@Override
public ListenableFuture<Void> execute(AddColumn statement, QueryStateMachine stateMachine, List<Expression> parameters, WarningCollector warningCollector) {
Session session = stateMachine.getSession();
QualifiedObjectName originalTableName = createQualifiedObjectName(session, statement, statement.getName());
RedirectionAwareTableHandle redirectionAwareTableHandle = plannerContext.getMetadata().getRedirectionAwareTableHandle(session, originalTableName);
if (redirectionAwareTableHandle.getTableHandle().isEmpty()) {
if (!statement.isTableExists()) {
throw semanticException(TABLE_NOT_FOUND, statement, "Table '%s' does not exist", originalTableName);
}
return immediateVoidFuture();
}
TableHandle tableHandle = redirectionAwareTableHandle.getTableHandle().get();
CatalogName catalogName = getRequiredCatalogHandle(plannerContext.getMetadata(), session, statement, tableHandle.getCatalogName().getCatalogName());
accessControl.checkCanAddColumns(session.toSecurityContext(), redirectionAwareTableHandle.getRedirectedTableName().orElse(originalTableName));
Map<String, ColumnHandle> columnHandles = plannerContext.getMetadata().getColumnHandles(session, tableHandle);
ColumnDefinition element = statement.getColumn();
Type type;
try {
type = plannerContext.getTypeManager().getType(toTypeSignature(element.getType()));
} catch (TypeNotFoundException e) {
throw semanticException(TYPE_NOT_FOUND, element, "Unknown type '%s' for column '%s'", element.getType(), element.getName());
}
if (type.equals(UNKNOWN)) {
throw semanticException(COLUMN_TYPE_UNKNOWN, element, "Unknown type '%s' for column '%s'", element.getType(), element.getName());
}
if (columnHandles.containsKey(element.getName().getValue().toLowerCase(ENGLISH))) {
if (!statement.isColumnNotExists()) {
throw semanticException(COLUMN_ALREADY_EXISTS, statement, "Column '%s' already exists", element.getName());
}
return immediateVoidFuture();
}
if (!element.isNullable() && !plannerContext.getMetadata().getConnectorCapabilities(session, catalogName).contains(NOT_NULL_COLUMN_CONSTRAINT)) {
throw semanticException(NOT_SUPPORTED, element, "Catalog '%s' does not support NOT NULL for column '%s'", catalogName.getCatalogName(), element.getName());
}
Map<String, Object> columnProperties = columnPropertyManager.getProperties(catalogName, element.getProperties(), session, plannerContext, accessControl, parameterExtractor(statement, parameters), true);
ColumnMetadata column = ColumnMetadata.builder().setName(element.getName().getValue()).setType(type).setNullable(element.isNullable()).setComment(element.getComment()).setProperties(columnProperties).build();
plannerContext.getMetadata().addColumn(session, tableHandle, column);
return immediateVoidFuture();
}
Aggregations