Skip to content

Commit f0c00e9

Browse files
committed
Reuse location when replacing view for Iceberg Rest
If replace and useUniqueTableLocation, load the existing view and reuse its location.
1 parent c45c360 commit f0c00e9

File tree

4 files changed

+100
-1
lines changed

4 files changed

+100
-1
lines changed

plugin/trino-iceberg/src/main/java/io/trino/plugin/iceberg/catalog/rest/TrinoRestCatalog.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -609,12 +609,19 @@ public void createView(ConnectorSession session, SchemaTableName schemaViewName,
609609
definition.getComment().ifPresent(comment -> properties.put(COMMENT, comment));
610610
Schema schema = IcebergUtil.schemaFromViewColumns(typeManager, definition.getColumns());
611611
ViewBuilder viewBuilder = restSessionCatalog.buildView(convert(session), toRemoteView(session, schemaViewName, true));
612+
String tableLocation = defaultTableLocation(session, schemaViewName);
613+
if (replace && useUniqueTableLocation) {
614+
Optional<View> view = getIcebergView(session, schemaViewName, true);
615+
if (view.isPresent()) {
616+
tableLocation = view.get().location();
617+
}
618+
}
612619
viewBuilder = viewBuilder.withSchema(schema)
613620
.withQuery("trino", definition.getOriginalSql())
614621
.withDefaultNamespace(toRemoteNamespace(session, toNamespace(schemaViewName.getSchemaName())))
615622
.withDefaultCatalog(definition.getCatalog().orElse(null))
616623
.withProperties(properties.buildOrThrow())
617-
.withLocation(defaultTableLocation(session, schemaViewName));
624+
.withLocation(tableLocation);
618625
try {
619626
if (replace) {
620627
viewBuilder.createOrReplace();

plugin/trino-iceberg/src/test/java/io/trino/plugin/iceberg/catalog/BaseTrinoCatalogTest.java

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,70 @@ public void testView()
423423
}
424424
}
425425

426+
@Test
427+
public void testViewUnique()
428+
throws IOException
429+
{
430+
TrinoCatalog catalog = createTrinoCatalog(true);
431+
Path tmpDirectory = Files.createTempDirectory("iceberg_catalog_test_create_view_");
432+
tmpDirectory.toFile().deleteOnExit();
433+
434+
String namespace = "test_create_view_" + randomNameSuffix();
435+
String viewName = "viewName";
436+
String renamedViewName = "renamedViewName";
437+
SchemaTableName schemaTableName = new SchemaTableName(namespace, viewName);
438+
SchemaTableName renamedSchemaTableName = new SchemaTableName(namespace, renamedViewName);
439+
ConnectorViewDefinition viewDefinition = new ConnectorViewDefinition(
440+
"SELECT name FROM local.tiny.nation",
441+
Optional.empty(),
442+
Optional.empty(),
443+
ImmutableList.of(
444+
new ConnectorViewDefinition.ViewColumn("name", VarcharType.createUnboundedVarcharType().getTypeId(), Optional.empty())),
445+
Optional.empty(),
446+
Optional.of(SESSION.getUser()),
447+
false,
448+
ImmutableList.of());
449+
450+
try {
451+
catalog.createNamespace(SESSION, namespace, defaultNamespaceProperties(namespace), new TrinoPrincipal(PrincipalType.USER, SESSION.getUser()));
452+
catalog.createView(SESSION, schemaTableName, viewDefinition, false);
453+
454+
assertThat(catalog.listTables(SESSION, Optional.of(namespace)).stream()).contains(new TableInfo(schemaTableName, getViewType()));
455+
456+
Map<SchemaTableName, ConnectorViewDefinition> views = catalog.getViews(SESSION, Optional.of(schemaTableName.getSchemaName()));
457+
assertThat(views).hasSize(1);
458+
assertViewDefinition(views.get(schemaTableName), viewDefinition);
459+
assertViewDefinition(catalog.getView(SESSION, schemaTableName).orElseThrow(), viewDefinition);
460+
461+
catalog.createView(SESSION, schemaTableName, viewDefinition, true);
462+
assertThat(catalog.listTables(SESSION, Optional.of(namespace)).stream()).contains(new TableInfo(schemaTableName, getViewType()));
463+
views = catalog.getViews(SESSION, Optional.of(schemaTableName.getSchemaName()));
464+
assertThat(views).hasSize(1);
465+
assertViewDefinition(views.get(schemaTableName), viewDefinition);
466+
assertViewDefinition(catalog.getView(SESSION, schemaTableName).orElseThrow(), viewDefinition);
467+
468+
catalog.renameView(SESSION, schemaTableName, renamedSchemaTableName);
469+
assertThat(catalog.listTables(SESSION, Optional.of(namespace)).stream().map(TableInfo::tableName).toList()).doesNotContain(schemaTableName);
470+
views = catalog.getViews(SESSION, Optional.of(schemaTableName.getSchemaName()));
471+
assertThat(views).hasSize(1);
472+
assertViewDefinition(views.get(renamedSchemaTableName), viewDefinition);
473+
assertViewDefinition(catalog.getView(SESSION, renamedSchemaTableName).orElseThrow(), viewDefinition);
474+
assertThat(catalog.getView(SESSION, schemaTableName)).isEmpty();
475+
476+
catalog.dropView(SESSION, renamedSchemaTableName);
477+
assertThat(catalog.listTables(SESSION, Optional.empty()).stream().map(TableInfo::tableName).toList())
478+
.doesNotContain(renamedSchemaTableName);
479+
}
480+
finally {
481+
try {
482+
catalog.dropNamespace(SESSION, namespace);
483+
}
484+
catch (Exception e) {
485+
LOG.warn("Failed to clean up namespace: %s", namespace);
486+
}
487+
}
488+
}
489+
426490
protected ExtendedRelationType getViewType()
427491
{
428492
return TRINO_VIEW;

plugin/trino-iceberg/src/test/java/io/trino/plugin/iceberg/catalog/nessie/TestTrinoNessieCatalog.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,14 @@ public void testView()
160160
.hasMessageContaining("createView is not supported for Iceberg Nessie catalogs");
161161
}
162162

163+
@Test
164+
@Override
165+
public void testViewUnique()
166+
{
167+
assertThatThrownBy(super::testView)
168+
.hasMessageContaining("createView is not supported for Iceberg Nessie catalogs");
169+
}
170+
163171
@Test
164172
@Override
165173
public void testNonLowercaseNamespace()

plugin/trino-iceberg/src/test/java/org/apache/iceberg/snowflake/TestTrinoSnowflakeCatalog.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,26 @@ public void testView()
349349
.hasMessageContaining("Views are not supported for the Snowflake Iceberg catalog");
350350
}
351351

352+
// Overridden to assert correct method calls as the tested feature is not supported
353+
@Test
354+
@Override
355+
public void testViewUnique()
356+
{
357+
ConnectorViewDefinition viewDefinition = new ConnectorViewDefinition(
358+
"SELECT name FROM local.tiny.%s".formatted(TpchTable.NATION.getTableName()),
359+
Optional.empty(),
360+
Optional.empty(),
361+
ImmutableList.of(
362+
new ConnectorViewDefinition.ViewColumn("name", VarcharType.createVarcharType(25).getTypeId(), Optional.empty())),
363+
Optional.empty(),
364+
Optional.of(SESSION.getUser()),
365+
false,
366+
ImmutableList.of());
367+
TrinoCatalog catalog = createTrinoCatalog(true);
368+
assertThatThrownBy(() -> catalog.createView(SESSION, SchemaTableName.schemaTableName(SNOWFLAKE_TEST_SCHEMA, TpchTable.NATION.getTableName()), viewDefinition, true))
369+
.hasMessageContaining("Views are not supported for the Snowflake Iceberg catalog");
370+
}
371+
352372
@Test
353373
@Override
354374
public void testListTables()

0 commit comments

Comments
 (0)