diff --git a/core/trino-main/src/test/java/io/trino/connector/MockConnector.java b/core/trino-main/src/test/java/io/trino/connector/MockConnector.java index b1cb9e1ee65b..7a1364e8044e 100644 --- a/core/trino-main/src/test/java/io/trino/connector/MockConnector.java +++ b/core/trino-main/src/test/java/io/trino/connector/MockConnector.java @@ -68,6 +68,7 @@ import io.trino.spi.security.Privilege; import io.trino.spi.security.RoleGrant; import io.trino.spi.security.TrinoPrincipal; +import io.trino.spi.session.PropertyMetadata; import io.trino.spi.statistics.ComputedStatistics; import io.trino.spi.transaction.IsolationLevel; import io.trino.spi.type.Type; @@ -124,6 +125,8 @@ public class MockConnector private final Function>> data; private final Set procedures; private final boolean allowMissingColumnsOnInsert; + private final Supplier>> schemaProperties; + private final Supplier>> tableProperties; MockConnector( Function> listSchemaNames, @@ -150,7 +153,9 @@ public class MockConnector Optional accessControl, Function>> data, Set procedures, - boolean allowMissingColumnsOnInsert) + boolean allowMissingColumnsOnInsert, + Supplier>> schemaProperties, + Supplier>> tableProperties) { this.listSchemaNames = requireNonNull(listSchemaNames, "listSchemaNames is null"); this.listTables = requireNonNull(listTables, "listTables is null"); @@ -177,6 +182,8 @@ public class MockConnector this.data = requireNonNull(data, "data is null"); this.procedures = requireNonNull(procedures, "procedures is null"); this.allowMissingColumnsOnInsert = allowMissingColumnsOnInsert; + this.schemaProperties = requireNonNull(schemaProperties, "schemaProperties is null"); + this.tableProperties = requireNonNull(tableProperties, "tableProperties is null"); } @Override @@ -234,6 +241,18 @@ public Set getProcedures() return procedures; } + @Override + public List> getSchemaProperties() + { + return schemaProperties.get(); + } + + @Override + public List> getTableProperties() + { + return tableProperties.get(); + } + private class MockConnectorMetadata implements ConnectorMetadata { diff --git a/core/trino-main/src/test/java/io/trino/connector/MockConnectorFactory.java b/core/trino-main/src/test/java/io/trino/connector/MockConnectorFactory.java index ff03c71bde71..c34c9fc2288e 100644 --- a/core/trino-main/src/test/java/io/trino/connector/MockConnectorFactory.java +++ b/core/trino-main/src/test/java/io/trino/connector/MockConnectorFactory.java @@ -50,6 +50,7 @@ import io.trino.spi.procedure.Procedure; import io.trino.spi.security.RoleGrant; import io.trino.spi.security.ViewExpression; +import io.trino.spi.session.PropertyMetadata; import java.util.List; import java.util.Map; @@ -94,6 +95,8 @@ public class MockConnectorFactory private final Function>> data; private final Set procedures; private final boolean allowMissingColumnsOnInsert; + private final Supplier>> schemaProperties; + private final Supplier>> tableProperties; // access control private final ListRoleGrants roleGrants; @@ -123,6 +126,8 @@ private MockConnectorFactory( Supplier> eventListeners, Function>> data, Set procedures, + Supplier>> schemaProperties, + Supplier>> tableProperties, ListRoleGrants roleGrants, Optional accessControl, boolean allowMissingColumnsOnInsert) @@ -148,6 +153,8 @@ private MockConnectorFactory( this.getNewTableLayout = requireNonNull(getNewTableLayout, "getNewTableLayout is null"); this.getTableProperties = requireNonNull(getTableProperties, "getTableProperties is null"); this.eventListeners = requireNonNull(eventListeners, "eventListeners is null"); + this.schemaProperties = requireNonNull(schemaProperties, "schemaProperties is null"); + this.tableProperties = requireNonNull(tableProperties, "tableProperties is null"); this.roleGrants = requireNonNull(roleGrants, "roleGrants is null"); this.accessControl = requireNonNull(accessControl, "accessControl is null"); this.data = requireNonNull(data, "data is null"); @@ -195,7 +202,9 @@ public Connector create(String catalogName, Map config, Connecto accessControl, data, procedures, - allowMissingColumnsOnInsert); + allowMissingColumnsOnInsert, + schemaProperties, + tableProperties); } public static Builder builder() @@ -291,6 +300,8 @@ public static final class Builder private BiFunction> redirectTable = (session, tableName) -> Optional.empty(); private Function>> data = schemaTableName -> ImmutableList.of(); private Set procedures = ImmutableSet.of(); + private Supplier>> schemaProperties = ImmutableList::of; + private Supplier>> tableProperties = ImmutableList::of; // access control private boolean provideAccessControl; @@ -445,11 +456,22 @@ public Builder withData(Function>> data) public Builder withProcedures(Set procedures) { - provideAccessControl = true; this.procedures = procedures; return this; } + public Builder withSchemaProperties(Supplier>> schemaProperties) + { + this.schemaProperties = requireNonNull(schemaProperties, "schemaProperties is null"); + return this; + } + + public Builder withTableProperties(Supplier>> tableProperties) + { + this.tableProperties = requireNonNull(tableProperties, "tableProperties is null"); + return this; + } + public Builder withListRoleGrants(ListRoleGrants roleGrants) { provideAccessControl = true; @@ -521,6 +543,8 @@ public MockConnectorFactory build() eventListeners, data, procedures, + schemaProperties, + tableProperties, roleGrants, accessControl, allowMissingColumnsOnInsert); diff --git a/testing/trino-tests/src/test/java/io/trino/tests/TestMockConnector.java b/testing/trino-tests/src/test/java/io/trino/tests/TestMockConnector.java index ad87c6508bc4..9693d78e66cb 100644 --- a/testing/trino-tests/src/test/java/io/trino/tests/TestMockConnector.java +++ b/testing/trino-tests/src/test/java/io/trino/tests/TestMockConnector.java @@ -26,6 +26,7 @@ import io.trino.spi.connector.ConnectorMaterializedViewDefinition; import io.trino.spi.connector.ConnectorMaterializedViewDefinition.Column; import io.trino.spi.connector.SchemaTableName; +import io.trino.spi.session.PropertyMetadata; import io.trino.testing.AbstractTestQueryFramework; import io.trino.testing.DistributedQueryRunner; import io.trino.testing.QueryRunner; @@ -35,6 +36,8 @@ import static io.trino.connector.MockConnectorEntities.TPCH_NATION_DATA; import static io.trino.connector.MockConnectorEntities.TPCH_NATION_SCHEMA; +import static io.trino.spi.session.PropertyMetadata.booleanProperty; +import static io.trino.spi.session.PropertyMetadata.integerProperty; import static io.trino.spi.type.BigintType.BIGINT; import static io.trino.testing.TestingSession.testSessionBuilder; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -60,7 +63,12 @@ protected QueryRunner createQueryRunner() } return ImmutableList.of(new ColumnMetadata("nationkey", BIGINT)); }) - .withGetTableHandle((session, tableName) -> new MockConnectorTableHandle(tableName)) + .withGetTableHandle((session, tableName) -> { + if (tableName.equals(new SchemaTableName("default", "new_table"))) { + return null; + } + return new MockConnectorTableHandle(tableName); + }) .withGetMaterializedViews((session, schemaTablePrefix) -> ImmutableMap.of( new SchemaTableName("default", "test_materialized_view"), new ConnectorMaterializedViewDefinition( @@ -79,6 +87,12 @@ protected QueryRunner createQueryRunner() throw new UnsupportedOperationException(); }) .withProcedures(ImmutableSet.of(new TestProcedure().get())) + .withSchemaProperties(() -> ImmutableList.>builder() + .add(booleanProperty("boolean_schema_property", "description", false, false)) + .build()) + .withTableProperties(() -> ImmutableList.>builder() + .add(integerProperty("integer_table_property", "description", 0, false)) + .build()) .build())); queryRunner.createCatalog("mock", "mock"); return queryRunner; @@ -180,4 +194,20 @@ public void testProcedure() assertThatThrownBy(() -> assertUpdate("CALL mock.default.non_exist_procedure()")) .hasMessage("Procedure not registered: default.non_exist_procedure"); } + + @Test + public void testSchemaProperties() + { + assertUpdate("CREATE SCHEMA mock.test_schema WITH (boolean_schema_property = true)"); + assertThatThrownBy(() -> assertUpdate("CREATE SCHEMA mock.test_schema WITH (unknown_property = true)")) + .hasMessage("Catalog 'mock' does not support schema property 'unknown_property'"); + } + + @Test + public void testTableProperties() + { + assertUpdate("CREATE TABLE mock.default.new_table (c int) WITH (integer_table_property = 1)"); + assertThatThrownBy(() -> assertUpdate("CREATE TABLE mock.default.new_table (c int) WITH (unknown_property = 1)")) + .hasMessage("Catalog 'mock' does not support table property 'unknown_property'"); + } }