Skip to content

Commit 8197f0f

Browse files
committed
Remove legacy Iceberg MV separate storage table support
1 parent f53802d commit 8197f0f

23 files changed

+104
-181
lines changed

docs/src/main/sphinx/connector/iceberg.md

-15
Original file line numberDiff line numberDiff line change
@@ -151,16 +151,6 @@ implementation is used:
151151
* - `iceberg.hive-catalog-name`
152152
- Catalog to redirect to when a Hive table is referenced.
153153
-
154-
* - `iceberg.materialized-views.storage-schema`
155-
- Schema for creating materialized views storage tables. When this property is
156-
not configured, storage tables are created in the same schema as the
157-
materialized view definition. When the `storage_schema` materialized view
158-
property is specified, it takes precedence over this catalog property.
159-
- Empty
160-
* - `iceberg.materialized-views.hide-storage-table`
161-
- Hide the information about the storage table backing the materialized view
162-
in the metastore.
163-
- `true`
164154
* - `iceberg.register-table-procedure.enabled`
165155
- Enable to allow user to call `register_table` procedure.
166156
- `false`
@@ -1492,11 +1482,6 @@ for the data files and partition the storage per day using the column
14921482
WITH ( format = 'ORC', partitioning = ARRAY['event_date'] )
14931483
```
14941484

1495-
By default, the storage table is created in the same schema as the materialized
1496-
view definition. The `iceberg.materialized-views.storage-schema` catalog
1497-
configuration property or `storage_schema` materialized view property can be
1498-
used to specify the schema where the storage table is created.
1499-
15001485
Creating a materialized view does not automatically populate it with data. You
15011486
must run {doc}`/sql/refresh-materialized-view` to populate data in the
15021487
materialized view.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* You may obtain a copy of the License at
5+
*
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*/
14+
package io.trino.plugin.iceberg;
15+
16+
import com.google.inject.BindingAnnotation;
17+
18+
import java.lang.annotation.Retention;
19+
import java.lang.annotation.Target;
20+
21+
import static java.lang.annotation.ElementType.FIELD;
22+
import static java.lang.annotation.ElementType.METHOD;
23+
import static java.lang.annotation.ElementType.PARAMETER;
24+
import static java.lang.annotation.RetentionPolicy.RUNTIME;
25+
26+
@Retention(RUNTIME)
27+
@Target({FIELD, PARAMETER, METHOD})
28+
@BindingAnnotation
29+
public @interface EnableMaterializedViewSeparateStorageTable {}

plugin/trino-iceberg/src/main/java/io/trino/plugin/iceberg/IcebergConfig.java

-36
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import io.airlift.units.DataSize;
2121
import io.airlift.units.Duration;
2222
import io.trino.plugin.hive.HiveCompressionCodec;
23-
import jakarta.validation.constraints.AssertFalse;
2423
import jakarta.validation.constraints.DecimalMax;
2524
import jakarta.validation.constraints.DecimalMin;
2625
import jakarta.validation.constraints.Max;
@@ -74,8 +73,6 @@ public class IcebergConfig
7473
// to avoid deleting those files if Trino is unable to check.
7574
private boolean deleteSchemaLocationsFallback;
7675
private double minimumAssignedSplitWeight = 0.05;
77-
private boolean hideMaterializedViewStorageTable = true;
78-
private Optional<String> materializedViewsStorageSchema = Optional.empty();
7976
private boolean sortedWritingEnabled = true;
8077
private boolean queryPartitionFilterRequired;
8178
private int splitManagerThreads = Runtime.getRuntime().availableProcessors() * 2;
@@ -361,33 +358,6 @@ public double getMinimumAssignedSplitWeight()
361358
return minimumAssignedSplitWeight;
362359
}
363360

364-
public boolean isHideMaterializedViewStorageTable()
365-
{
366-
return hideMaterializedViewStorageTable;
367-
}
368-
369-
@Config("iceberg.materialized-views.hide-storage-table")
370-
@ConfigDescription("Hide materialized view storage tables in metastore")
371-
public IcebergConfig setHideMaterializedViewStorageTable(boolean hideMaterializedViewStorageTable)
372-
{
373-
this.hideMaterializedViewStorageTable = hideMaterializedViewStorageTable;
374-
return this;
375-
}
376-
377-
@NotNull
378-
public Optional<String> getMaterializedViewsStorageSchema()
379-
{
380-
return materializedViewsStorageSchema;
381-
}
382-
383-
@Config("iceberg.materialized-views.storage-schema")
384-
@ConfigDescription("Schema for creating materialized views storage tables")
385-
public IcebergConfig setMaterializedViewsStorageSchema(String materializedViewsStorageSchema)
386-
{
387-
this.materializedViewsStorageSchema = Optional.ofNullable(materializedViewsStorageSchema);
388-
return this;
389-
}
390-
391361
public boolean isSortedWritingEnabled()
392362
{
393363
return sortedWritingEnabled;
@@ -427,10 +397,4 @@ public IcebergConfig setSplitManagerThreads(int splitManagerThreads)
427397
this.splitManagerThreads = splitManagerThreads;
428398
return this;
429399
}
430-
431-
@AssertFalse(message = "iceberg.materialized-views.storage-schema may only be set when iceberg.materialized-views.hide-storage-table is set to false")
432-
public boolean isStorageSchemaSetWhenHidingIsEnabled()
433-
{
434-
return hideMaterializedViewStorageTable && materializedViewsStorageSchema.isPresent();
435-
}
436400
}

plugin/trino-iceberg/src/main/java/io/trino/plugin/iceberg/IcebergMaterializedViewProperties.java

+24-14
Original file line numberDiff line numberDiff line change
@@ -21,35 +21,45 @@
2121
import java.util.Map;
2222
import java.util.Optional;
2323

24-
import static io.trino.spi.session.PropertyMetadata.stringProperty;
24+
import static io.trino.spi.session.PropertyMetadata.booleanProperty;
2525

2626
public class IcebergMaterializedViewProperties
2727
{
28-
public static final String STORAGE_SCHEMA = "storage_schema";
28+
public static final String SEPARATE_STORAGE_TABLE = "separate_storage_table";
2929

3030
private final List<PropertyMetadata<?>> materializedViewProperties;
3131

3232
@Inject
33-
public IcebergMaterializedViewProperties(IcebergConfig icebergConfig, IcebergTableProperties tableProperties)
33+
public IcebergMaterializedViewProperties(
34+
@EnableMaterializedViewSeparateStorageTable boolean enableMaterializedViewSeparateStorageTable, // for tests of legacy materialized views
35+
IcebergTableProperties tableProperties)
3436
{
35-
materializedViewProperties = ImmutableList.<PropertyMetadata<?>>builder()
36-
.add(stringProperty(
37-
STORAGE_SCHEMA,
38-
"Schema for creating materialized view storage table",
39-
icebergConfig.getMaterializedViewsStorageSchema().orElse(null),
40-
false))
41-
// Materialized view should allow configuring all the supported iceberg table properties for the storage table
42-
.addAll(tableProperties.getTableProperties())
43-
.build();
37+
ImmutableList.Builder<PropertyMetadata<?>> materializedViewProperties = ImmutableList.builder();
38+
if (enableMaterializedViewSeparateStorageTable) {
39+
materializedViewProperties.add(booleanProperty(
40+
SEPARATE_STORAGE_TABLE,
41+
"Create separate storage table for materialized view",
42+
false,
43+
true));
44+
}
45+
// Materialized view should allow configuring all the supported iceberg table properties for the storage table
46+
materializedViewProperties.addAll(tableProperties.getTableProperties());
47+
this.materializedViewProperties = materializedViewProperties.build();
4448
}
4549

4650
public List<PropertyMetadata<?>> getMaterializedViewProperties()
4751
{
4852
return materializedViewProperties;
4953
}
5054

51-
public static Optional<String> getStorageSchema(Map<String, Object> materializedViewProperties)
55+
/**
56+
* @deprecated TODO creation of legacy materialized views with separate storage table to test code
57+
*/
58+
@Deprecated
59+
public static boolean isSeparateStorageTable(Map<String, Object> materializedViewProperties)
5260
{
53-
return Optional.ofNullable((String) materializedViewProperties.get(STORAGE_SCHEMA));
61+
return Optional.ofNullable(materializedViewProperties.get(SEPARATE_STORAGE_TABLE))
62+
.map(Boolean.class::cast)
63+
.orElse(false);
5464
}
5565
}

plugin/trino-iceberg/src/main/java/io/trino/plugin/iceberg/IcebergModule.java

+1
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ public void configure(Binder binder)
7676
newSetBinder(binder, SessionPropertiesProvider.class).addBinding().to(IcebergSessionProperties.class).in(Scopes.SINGLETON);
7777
binder.bind(IcebergTableProperties.class).in(Scopes.SINGLETON);
7878
binder.bind(IcebergMaterializedViewProperties.class).in(Scopes.SINGLETON);
79+
newOptionalBinder(binder, Key.get(boolean.class, EnableMaterializedViewSeparateStorageTable.class)).setDefault().toInstance(false);
7980
binder.bind(IcebergAnalyzeProperties.class).in(Scopes.SINGLETON);
8081

8182
binder.bind(ConnectorSplitManager.class).to(IcebergSplitManager.class).in(Scopes.SINGLETON);

plugin/trino-iceberg/src/main/java/io/trino/plugin/iceberg/catalog/AbstractTrinoCatalog.java

+5-17
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
import java.util.Set;
7070
import java.util.stream.Stream;
7171

72+
import static com.google.common.base.Preconditions.checkArgument;
7273
import static com.google.common.base.Throwables.throwIfUnchecked;
7374
import static com.google.common.collect.ImmutableList.toImmutableList;
7475
import static com.google.common.collect.ImmutableSet.toImmutableSet;
@@ -79,10 +80,8 @@
7980
import static io.trino.plugin.hive.metastore.glue.converter.GlueToTrinoConverter.mappedCopy;
8081
import static io.trino.plugin.hive.util.HiveUtil.escapeTableName;
8182
import static io.trino.plugin.iceberg.IcebergErrorCode.ICEBERG_FILESYSTEM_ERROR;
82-
import static io.trino.plugin.iceberg.IcebergErrorCode.ICEBERG_INVALID_METADATA;
8383
import static io.trino.plugin.iceberg.IcebergMaterializedViewDefinition.decodeMaterializedViewData;
84-
import static io.trino.plugin.iceberg.IcebergMaterializedViewProperties.STORAGE_SCHEMA;
85-
import static io.trino.plugin.iceberg.IcebergMaterializedViewProperties.getStorageSchema;
84+
import static io.trino.plugin.iceberg.IcebergMaterializedViewProperties.isSeparateStorageTable;
8685
import static io.trino.plugin.iceberg.IcebergTableName.tableNameWithType;
8786
import static io.trino.plugin.iceberg.IcebergTableProperties.getPartitioning;
8887
import static io.trino.plugin.iceberg.IcebergTableProperties.getSortOrder;
@@ -97,7 +96,6 @@
9796
import static io.trino.plugin.iceberg.SortFieldUtils.parseSortFields;
9897
import static io.trino.plugin.iceberg.TableType.MATERIALIZED_VIEW_STORAGE;
9998
import static io.trino.plugin.iceberg.TypeConverter.toTrinoType;
100-
import static io.trino.spi.StandardErrorCode.NOT_SUPPORTED;
10199
import static io.trino.spi.StandardErrorCode.TABLE_NOT_FOUND;
102100
import static io.trino.spi.type.IntegerType.INTEGER;
103101
import static io.trino.spi.type.SmallintType.SMALLINT;
@@ -211,16 +209,9 @@ public Optional<ConnectorMaterializedViewDefinition> getMaterializedView(Connect
211209
@Override
212210
public Map<String, Object> getMaterializedViewProperties(ConnectorSession session, SchemaTableName viewName, ConnectorMaterializedViewDefinition definition)
213211
{
214-
SchemaTableName storageTableName = definition.getStorageTable()
215-
.orElseThrow(() -> new TrinoException(ICEBERG_INVALID_METADATA, "Materialized view definition is missing a storage table"))
216-
.getSchemaTableName();
217-
218212
try {
219213
Table storageTable = loadTable(session, definition.getStorageTable().orElseThrow().getSchemaTableName());
220-
return ImmutableMap.<String, Object>builder()
221-
.putAll(getIcebergTableProperties(storageTable))
222-
.put(STORAGE_SCHEMA, storageTableName.getSchemaName())
223-
.buildOrThrow();
214+
return getIcebergTableProperties(storageTable);
224215
}
225216
catch (RuntimeException e) {
226217
throw new TrinoException(ICEBERG_FILESYSTEM_ERROR, "Unable to load storage table metadata for materialized view: " + viewName);
@@ -313,9 +304,7 @@ protected Location createMaterializedViewStorage(
313304
ConnectorMaterializedViewDefinition definition,
314305
Map<String, Object> materializedViewProperties)
315306
{
316-
if (getStorageSchema(materializedViewProperties).isPresent()) {
317-
throw new TrinoException(NOT_SUPPORTED, "Materialized view property '%s' is not supported when hiding materialized view storage tables is enabled".formatted(STORAGE_SCHEMA));
318-
}
307+
checkArgument(!isSeparateStorageTable(materializedViewProperties), "Invalid request to create hidden materialized view storage table when separate storage table is requested");
319308
SchemaTableName storageTableName = new SchemaTableName(viewName.getSchemaName(), tableNameWithType(viewName.getTableName(), MATERIALIZED_VIEW_STORAGE));
320309
String tableLocation = getTableLocation(materializedViewProperties)
321310
.orElseGet(() -> defaultTableLocation(session, viewName));
@@ -355,7 +344,7 @@ protected SchemaTableName createMaterializedViewStorageTable(
355344
// storage table as indicated in the materialized view definition.
356345
String storageTableName = "st_" + randomUUID().toString().replace("-", "");
357346

358-
String storageSchema = getStorageSchema(materializedViewProperties).orElse(viewName.getSchemaName());
347+
String storageSchema = viewName.getSchemaName();
359348
SchemaTableName storageTable = new SchemaTableName(storageSchema, storageTableName);
360349
List<ColumnMetadata> columns = columnsForMaterializedView(definition, materializedViewProperties);
361350

@@ -494,7 +483,6 @@ protected Map<String, String> createMaterializedViewProperties(ConnectorSession
494483
{
495484
return ImmutableMap.<String, String>builder()
496485
.put(TRINO_QUERY_ID_NAME, session.getQueryId())
497-
.put(STORAGE_SCHEMA, storageTableName.getSchemaName())
498486
.put(STORAGE_TABLE, storageTableName.getTableName())
499487
.put(PRESTO_VIEW_FLAG, "true")
500488
.put(TRINO_CREATED_BY, TRINO_CREATED_BY_VALUE)

plugin/trino-iceberg/src/main/java/io/trino/plugin/iceberg/catalog/glue/TrinoGlueCatalog.java

+5-10
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@
136136
import static io.trino.plugin.iceberg.IcebergMaterializedViewDefinition.decodeMaterializedViewData;
137137
import static io.trino.plugin.iceberg.IcebergMaterializedViewDefinition.encodeMaterializedViewData;
138138
import static io.trino.plugin.iceberg.IcebergMaterializedViewDefinition.fromConnectorMaterializedViewDefinition;
139-
import static io.trino.plugin.iceberg.IcebergMaterializedViewProperties.STORAGE_SCHEMA;
139+
import static io.trino.plugin.iceberg.IcebergMaterializedViewProperties.isSeparateStorageTable;
140140
import static io.trino.plugin.iceberg.IcebergSchemaProperties.LOCATION_PROPERTY;
141141
import static io.trino.plugin.iceberg.IcebergTableName.tableNameWithType;
142142
import static io.trino.plugin.iceberg.IcebergUtil.COLUMN_TRINO_NOT_NULL_PROPERTY;
@@ -179,7 +179,6 @@ public class TrinoGlueCatalog
179179
private final Optional<String> defaultSchemaLocation;
180180
private final AWSGlueAsync glueClient;
181181
private final GlueMetastoreStats stats;
182-
private final boolean hideMaterializedViewStorageTable;
183182
private final boolean isUsingSystemSecurity;
184183

185184
private final Cache<SchemaTableName, com.amazonaws.services.glue.model.Table> glueTableCache = EvictableCacheBuilder.newBuilder()
@@ -208,8 +207,7 @@ public TrinoGlueCatalog(
208207
GlueMetastoreStats stats,
209208
boolean isUsingSystemSecurity,
210209
Optional<String> defaultSchemaLocation,
211-
boolean useUniqueTableLocation,
212-
boolean hideMaterializedViewStorageTable)
210+
boolean useUniqueTableLocation)
213211
{
214212
super(catalogName, typeManager, tableOperationsProvider, fileSystemFactory, useUniqueTableLocation);
215213
this.trinoVersion = requireNonNull(trinoVersion, "trinoVersion is null");
@@ -220,7 +218,6 @@ public TrinoGlueCatalog(
220218
this.stats = requireNonNull(stats, "stats is null");
221219
this.isUsingSystemSecurity = isUsingSystemSecurity;
222220
this.defaultSchemaLocation = requireNonNull(defaultSchemaLocation, "defaultSchemaLocation is null");
223-
this.hideMaterializedViewStorageTable = hideMaterializedViewStorageTable;
224221
}
225222

226223
@Override
@@ -1123,7 +1120,7 @@ public void createMaterializedView(
11231120
}
11241121
}
11251122

1126-
if (hideMaterializedViewStorageTable) {
1123+
if (!isSeparateStorageTable(materializedViewProperties)) {
11271124
Location storageMetadataLocation = createMaterializedViewStorage(session, viewName, definition, materializedViewProperties);
11281125
TableInput materializedViewTableInput = getMaterializedViewTableInput(
11291126
viewName.getTableName(),
@@ -1253,8 +1250,7 @@ private void dropMaterializedViewStorage(ConnectorSession session, com.amazonaws
12531250
Map<String, String> parameters = getTableParameters(view);
12541251
String storageTableName = parameters.get(STORAGE_TABLE);
12551252
if (storageTableName != null) {
1256-
String storageSchema = Optional.ofNullable(parameters.get(STORAGE_SCHEMA))
1257-
.orElse(view.getDatabaseName());
1253+
String storageSchema = view.getDatabaseName();
12581254
try {
12591255
dropTable(session, new SchemaTableName(storageSchema, storageTableName));
12601256
}
@@ -1314,8 +1310,7 @@ private ConnectorMaterializedViewDefinition createMaterializedViewDefinition(
13141310
}
13151311

13161312
if (storageTable != null) {
1317-
String storageSchema = Optional.ofNullable(materializedViewParameters.get(STORAGE_SCHEMA))
1318-
.orElse(viewName.getSchemaName());
1313+
String storageSchema = viewName.getSchemaName();
13191314
SchemaTableName storageTableName = new SchemaTableName(storageSchema, storageTable);
13201315

13211316
String viewOriginalText = table.getViewOriginalText();

plugin/trino-iceberg/src/main/java/io/trino/plugin/iceberg/catalog/glue/TrinoGlueCatalogFactory.java

+1-4
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ public class TrinoGlueCatalogFactory
4747
private final Optional<String> defaultSchemaLocation;
4848
private final AWSGlueAsync glueClient;
4949
private final boolean isUniqueTableLocation;
50-
private final boolean hideMaterializedViewStorageTable;
5150
private final GlueMetastoreStats stats;
5251
private final boolean isUsingSystemSecurity;
5352

@@ -74,7 +73,6 @@ public TrinoGlueCatalogFactory(
7473
this.defaultSchemaLocation = glueConfig.getDefaultWarehouseDir();
7574
this.glueClient = requireNonNull(glueClient, "glueClient is null");
7675
this.isUniqueTableLocation = icebergConfig.isUniqueTableLocation();
77-
this.hideMaterializedViewStorageTable = icebergConfig.isHideMaterializedViewStorageTable();
7876
this.stats = requireNonNull(stats, "stats is null");
7977
this.isUsingSystemSecurity = securityConfig.getSecuritySystem() == SYSTEM;
8078
}
@@ -100,7 +98,6 @@ public TrinoCatalog create(ConnectorIdentity identity)
10098
stats,
10199
isUsingSystemSecurity,
102100
defaultSchemaLocation,
103-
isUniqueTableLocation,
104-
hideMaterializedViewStorageTable);
101+
isUniqueTableLocation);
105102
}
106103
}

0 commit comments

Comments
 (0)