/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.facebook.presto.spi.connector; import com.facebook.presto.spi.ColumnHandle; import com.facebook.presto.spi.ColumnIdentity; import com.facebook.presto.spi.ColumnMetadata; import com.facebook.presto.spi.ConnectorInsertTableHandle; import com.facebook.presto.spi.ConnectorNewTableLayout; import com.facebook.presto.spi.ConnectorOutputTableHandle; import com.facebook.presto.spi.ConnectorResolvedIndex; import com.facebook.presto.spi.ConnectorSession; import com.facebook.presto.spi.ConnectorTableHandle; import com.facebook.presto.spi.ConnectorTableLayout; import com.facebook.presto.spi.ConnectorTableLayoutHandle; import com.facebook.presto.spi.ConnectorTableLayoutResult; import com.facebook.presto.spi.ConnectorTableMetadata; import com.facebook.presto.spi.ConnectorViewDefinition; import com.facebook.presto.spi.Constraint; import com.facebook.presto.spi.PrestoException; import com.facebook.presto.spi.SchemaTableName; import com.facebook.presto.spi.SchemaTablePrefix; import com.facebook.presto.spi.TableIdentity; import com.facebook.presto.spi.predicate.TupleDomain; import com.facebook.presto.spi.security.GrantInfo; import com.facebook.presto.spi.security.Privilege; import io.airlift.slice.Slice; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.OptionalLong; import java.util.Set; import java.util.stream.Collectors; import static com.facebook.presto.spi.StandardErrorCode.GENERIC_INTERNAL_ERROR; import static com.facebook.presto.spi.StandardErrorCode.NOT_SUPPORTED; import static java.util.Collections.emptyList; import static java.util.Collections.emptyMap; import static java.util.stream.Collectors.toList; public interface ConnectorMetadata { /** * Checks if a schema exists. The connector may have schemas that exist * but are not enumerable via {@link #listSchemaNames}. */ default boolean schemaExists(ConnectorSession session, String schemaName) { return listSchemaNames(session).contains(schemaName); } /** * Returns the schemas provided by this connector. */ List<String> listSchemaNames(ConnectorSession session); /** * Returns a table handle for the specified table name, or null if the connector does not contain the table. */ ConnectorTableHandle getTableHandle(ConnectorSession session, SchemaTableName tableName); /** * Return a list of table layouts that satisfy the given constraint. * <p> * For each layout, connectors must return an "unenforced constraint" representing the part of the constraint summary that isn't guaranteed by the layout. */ List<ConnectorTableLayoutResult> getTableLayouts( ConnectorSession session, ConnectorTableHandle table, Constraint<ColumnHandle> constraint, Optional<Set<ColumnHandle>> desiredColumns); ConnectorTableLayout getTableLayout(ConnectorSession session, ConnectorTableLayoutHandle handle); /** * Return the metadata for the specified table handle. * * @throws RuntimeException if table handle is no longer valid */ ConnectorTableMetadata getTableMetadata(ConnectorSession session, ConnectorTableHandle table); /** * Return the connector-specific metadata for the specified table layout. This is the object that is passed to the event listener framework. * * @throws RuntimeException if table handle is no longer valid */ default Optional<Object> getInfo(ConnectorTableLayoutHandle layoutHandle) { return Optional.empty(); } /** * List table names, possibly filtered by schema. An empty list is returned if none match. */ List<SchemaTableName> listTables(ConnectorSession session, String schemaNameOrNull); /** * Gets all of the columns on the specified table, or an empty map if the columns can not be enumerated. * * @throws RuntimeException if table handle is no longer valid */ Map<String, ColumnHandle> getColumnHandles(ConnectorSession session, ConnectorTableHandle tableHandle); /** * Gets the metadata for the specified table column. * * @throws RuntimeException if table or column handles are no longer valid */ ColumnMetadata getColumnMetadata(ConnectorSession session, ConnectorTableHandle tableHandle, ColumnHandle columnHandle); /** * Gets the metadata for all columns that match the specified table prefix. */ Map<SchemaTableName, List<ColumnMetadata>> listTableColumns(ConnectorSession session, SchemaTablePrefix prefix); /** * Creates a schema. */ default void createSchema(ConnectorSession session, String schemaName, Map<String, Object> properties) { throw new PrestoException(NOT_SUPPORTED, "This connector does not support creating schemas"); } /** * Drops the specified schema. * * @throws PrestoException with {@code SCHEMA_NOT_EMPTY} if the schema is not empty */ default void dropSchema(ConnectorSession session, String schemaName) { throw new PrestoException(NOT_SUPPORTED, "This connector does not support dropping schemas"); } /** * Renames the specified schema. */ default void renameSchema(ConnectorSession session, String source, String target) { throw new PrestoException(NOT_SUPPORTED, "This connector does not support renaming schemas"); } /** * Creates a table using the specified table metadata. */ default void createTable(ConnectorSession session, ConnectorTableMetadata tableMetadata) { throw new PrestoException(NOT_SUPPORTED, "This connector does not support creating tables"); } /** * Drops the specified table * * @throws RuntimeException if the table can not be dropped or table handle is no longer valid */ default void dropTable(ConnectorSession session, ConnectorTableHandle tableHandle) { throw new PrestoException(NOT_SUPPORTED, "This connector does not support dropping tables"); } /** * Rename the specified table */ default void renameTable(ConnectorSession session, ConnectorTableHandle tableHandle, SchemaTableName newTableName) { throw new PrestoException(NOT_SUPPORTED, "This connector does not support renaming tables"); } /** * Add the specified column */ default void addColumn(ConnectorSession session, ConnectorTableHandle tableHandle, ColumnMetadata column) { throw new PrestoException(NOT_SUPPORTED, "This connector does not support adding columns"); } /** * Rename the specified column */ default void renameColumn(ConnectorSession session, ConnectorTableHandle tableHandle, ColumnHandle source, String target) { throw new PrestoException(NOT_SUPPORTED, "This connector does not support renaming columns"); } /** * Get the physical layout for a new table. */ default Optional<ConnectorNewTableLayout> getNewTableLayout(ConnectorSession session, ConnectorTableMetadata tableMetadata) { return Optional.empty(); } /** * Get the physical layout for a inserting into an existing table. */ default Optional<ConnectorNewTableLayout> getInsertLayout(ConnectorSession session, ConnectorTableHandle tableHandle) { List<ConnectorTableLayout> layouts = getTableLayouts(session, tableHandle, new Constraint<>(TupleDomain.all(), map -> true), Optional.empty()) .stream() .map(ConnectorTableLayoutResult::getTableLayout) .filter(layout -> layout.getNodePartitioning().isPresent()) .collect(toList()); if (layouts.isEmpty()) { return Optional.empty(); } if (layouts.size() > 1) { throw new PrestoException(NOT_SUPPORTED, "Tables with multiple layouts can not be written"); } ConnectorTableLayout layout = layouts.get(0); ConnectorPartitioningHandle partitioningHandle = layout.getNodePartitioning().get().getPartitioningHandle(); Map<ColumnHandle, String> columnNamesByHandle = getColumnHandles(session, tableHandle).entrySet().stream() .collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey)); List<String> partitionColumns = layout.getNodePartitioning().get().getPartitioningColumns().stream() .map(columnNamesByHandle::get) .collect(toList()); return Optional.of(new ConnectorNewTableLayout(partitioningHandle, partitionColumns)); } /** * Begin the atomic creation of a table with data. */ default ConnectorOutputTableHandle beginCreateTable(ConnectorSession session, ConnectorTableMetadata tableMetadata, Optional<ConnectorNewTableLayout> layout) { throw new PrestoException(NOT_SUPPORTED, "This connector does not support creating tables with data"); } /** * Finish a table creation with data after the data is written. */ default Optional<ConnectorOutputMetadata> finishCreateTable(ConnectorSession session, ConnectorOutputTableHandle tableHandle, Collection<Slice> fragments) { throw new PrestoException(GENERIC_INTERNAL_ERROR, "ConnectorMetadata beginCreateTable() is implemented without finishCreateTable()"); } /** * Start a SELECT/UPDATE/INSERT/DELETE query. This notification is triggered after the planning phase completes. */ default void beginQuery(ConnectorSession session) {} /** * Cleanup after a SELECT/UPDATE/INSERT/DELETE query. This is the very last notification after the query finishes, whether it succeeds or fails. * An exception thrown in this method will not affect the result of the query. */ default void cleanupQuery(ConnectorSession session) {} /** * Begin insert query */ default ConnectorInsertTableHandle beginInsert(ConnectorSession session, ConnectorTableHandle tableHandle) { throw new PrestoException(NOT_SUPPORTED, "This connector does not support inserts"); } /** * Finish insert query */ default Optional<ConnectorOutputMetadata> finishInsert(ConnectorSession session, ConnectorInsertTableHandle insertHandle, Collection<Slice> fragments) { throw new PrestoException(GENERIC_INTERNAL_ERROR, "ConnectorMetadata beginInsert() is implemented without finishInsert()"); } /** * Get the column handle that will generate row IDs for the delete operation. * These IDs will be passed to the {@code deleteRows()} method of the * {@link com.facebook.presto.spi.UpdatablePageSource} that created them. */ default ColumnHandle getUpdateRowIdColumnHandle(ConnectorSession session, ConnectorTableHandle tableHandle) { throw new PrestoException(NOT_SUPPORTED, "This connector does not support updates or deletes"); } /** * Begin delete query */ default ConnectorTableHandle beginDelete(ConnectorSession session, ConnectorTableHandle tableHandle) { throw new PrestoException(NOT_SUPPORTED, "This connector does not support deletes"); } /** * Finish delete query * * @param fragments all fragments returned by {@link com.facebook.presto.spi.UpdatablePageSource#finish()} */ default void finishDelete(ConnectorSession session, ConnectorTableHandle tableHandle, Collection<Slice> fragments) { throw new PrestoException(NOT_SUPPORTED, "This connector does not support deletes"); } /** * Create the specified view. The data for the view is opaque to the connector. */ default void createView(ConnectorSession session, SchemaTableName viewName, String viewData, boolean replace) { throw new PrestoException(NOT_SUPPORTED, "This connector does not support creating views"); } /** * Drop the specified view. */ default void dropView(ConnectorSession session, SchemaTableName viewName) { throw new PrestoException(NOT_SUPPORTED, "This connector does not support dropping views"); } /** * List view names, possibly filtered by schema. An empty list is returned if none match. */ default List<SchemaTableName> listViews(ConnectorSession session, String schemaNameOrNull) { return emptyList(); } /** * Gets the view data for views that match the specified table prefix. */ default Map<SchemaTableName, ConnectorViewDefinition> getViews(ConnectorSession session, SchemaTablePrefix prefix) { return emptyMap(); } /** * @return whether delete without table scan is supported */ default boolean supportsMetadataDelete(ConnectorSession session, ConnectorTableHandle tableHandle, ConnectorTableLayoutHandle tableLayoutHandle) { throw new PrestoException(NOT_SUPPORTED, "This connector does not support deletes"); } /** * Delete the provided table layout * * @return number of rows deleted, or null for unknown */ default OptionalLong metadataDelete(ConnectorSession session, ConnectorTableHandle tableHandle, ConnectorTableLayoutHandle tableLayoutHandle) { throw new PrestoException(NOT_SUPPORTED, "This connector does not support deletes"); } /** * Try to locate a table index that can lookup results by indexableColumns and provide the requested outputColumns. */ default Optional<ConnectorResolvedIndex> resolveIndex(ConnectorSession session, ConnectorTableHandle tableHandle, Set<ColumnHandle> indexableColumns, Set<ColumnHandle> outputColumns, TupleDomain<ColumnHandle> tupleDomain) { return Optional.empty(); } /** * Grants the specified privilege to the specified user on the specified table */ default void grantTablePrivileges(ConnectorSession session, SchemaTableName tableName, Set<Privilege> privileges, String grantee, boolean grantOption) { throw new PrestoException(NOT_SUPPORTED, "This connector does not support grants"); } /** * Revokes the specified privilege on the specified table from the specified user */ default void revokeTablePrivileges(ConnectorSession session, SchemaTableName tableName, Set<Privilege> privileges, String grantee, boolean grantOption) { throw new PrestoException(NOT_SUPPORTED, "This connector does not support revokes"); } /** * List the table privileges granted to the specified grantee for the tables that have the specified prefix */ default List<GrantInfo> listTablePrivileges(ConnectorSession session, SchemaTablePrefix prefix) { return emptyList(); } /** * Gets the table identity on the specified table */ default TableIdentity getTableIdentity(ConnectorTableHandle connectorTableHandle) { throw new PrestoException(NOT_SUPPORTED, "This connector does not support table identity"); } /** * Deserialize the specified bytes to TableIdentity */ default TableIdentity deserializeTableIdentity(byte[] bytes) { throw new PrestoException(NOT_SUPPORTED, "This connector does not support table identity"); } /** * Gets the column identity on the specified column */ default ColumnIdentity getColumnIdentity(ColumnHandle columnHandle) { throw new PrestoException(NOT_SUPPORTED, "This connector does not support column identity"); } /** * Deserialize the specified bytes to ColumnIdentity */ default ColumnIdentity deserializeColumnIdentity(byte[] bytes) { throw new PrestoException(NOT_SUPPORTED, "This connector does not support column identity"); } }