Skip to content

Commit

Permalink
Core: Improve view/table detection when replacing a table/view
Browse files Browse the repository at this point in the history
  • Loading branch information
nastra committed Nov 9, 2023
1 parent 5754ddb commit c63be65
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
import org.apache.iceberg.catalog.Namespace;
import org.apache.iceberg.catalog.TableCommit;
import org.apache.iceberg.catalog.TableIdentifier;
import org.apache.iceberg.exceptions.AlreadyExistsException;
import org.apache.iceberg.exceptions.NoSuchNamespaceException;
import org.apache.iceberg.exceptions.NoSuchTableException;
import org.apache.iceberg.exceptions.NoSuchViewException;
Expand Down Expand Up @@ -702,6 +703,10 @@ public Transaction createTransaction() {

@Override
public Transaction replaceTransaction() {
if (viewExists(context, ident)) {
throw new AlreadyExistsException("View with same name already exists: %s", ident);
}

LoadTableResponse response = loadInternal(context, ident, snapshotMode);
String fullName = fullTableName(ident);

Expand Down Expand Up @@ -1170,6 +1175,10 @@ public View createOrReplace() {

@Override
public View replace() {
if (tableExists(context, identifier)) {
throw new AlreadyExistsException("Table with same name already exists: %s", identifier);
}

return replace(loadView());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.apache.iceberg.BaseMetastoreCatalog;
import org.apache.iceberg.EnvironmentContext;
import org.apache.iceberg.Schema;
import org.apache.iceberg.Transaction;
import org.apache.iceberg.catalog.Namespace;
import org.apache.iceberg.catalog.TableIdentifier;
import org.apache.iceberg.catalog.ViewCatalog;
Expand Down Expand Up @@ -182,6 +183,10 @@ private View create(ViewOperations ops) {
}

private View replace(ViewOperations ops) {
if (tableExists(identifier)) {
throw new AlreadyExistsException("Table with same name already exists: %s", identifier);
}

if (null == ops.current()) {
throw new NoSuchViewException("View does not exist: %s", identifier);
}
Expand Down Expand Up @@ -230,4 +235,28 @@ private View replace(ViewOperations ops) {
return new BaseView(ops, ViewUtil.fullViewName(name(), identifier));
}
}

@Override
public TableBuilder buildTable(TableIdentifier identifier, Schema schema) {
return new BaseMetastoreViewCatalogTableBuilder(identifier, schema);
}

/** The purpose of this class is to add view detection when replacing a table */
protected class BaseMetastoreViewCatalogTableBuilder extends BaseMetastoreCatalogTableBuilder {
private final TableIdentifier identifier;

public BaseMetastoreViewCatalogTableBuilder(TableIdentifier identifier, Schema schema) {
super(identifier, schema);
this.identifier = identifier;
}

@Override
public Transaction replaceTransaction() {
if (viewExists(identifier)) {
throw new AlreadyExistsException("View with same name already exists: %s", identifier);
}

return super.replaceTransaction();
}
}
}
13 changes: 4 additions & 9 deletions core/src/test/java/org/apache/iceberg/view/ViewCatalogTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
import org.apache.iceberg.catalog.ViewCatalog;
import org.apache.iceberg.exceptions.AlreadyExistsException;
import org.apache.iceberg.exceptions.NoSuchNamespaceException;
import org.apache.iceberg.exceptions.NoSuchTableException;
import org.apache.iceberg.exceptions.NoSuchViewException;
import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
import org.apache.iceberg.types.Types;
Expand Down Expand Up @@ -396,16 +395,14 @@ public void replaceTableViaTransactionThatAlreadyExistsAsView() {

assertThat(catalog().viewExists(viewIdentifier)).as("View should exist").isTrue();

// replace transaction requires table existence
// TODO: replace should check whether the table exists as a view
assertThatThrownBy(
() ->
tableCatalog()
.buildTable(viewIdentifier, SCHEMA)
.replaceTransaction()
.commitTransaction())
.isInstanceOf(NoSuchTableException.class)
.hasMessageStartingWith("Table does not exist: ns.view");
.isInstanceOf(AlreadyExistsException.class)
.hasMessageStartingWith("View with same name already exists: ns.view");
}

@Test
Expand Down Expand Up @@ -459,8 +456,6 @@ public void replaceViewThatAlreadyExistsAsTable() {

assertThat(tableCatalog().tableExists(tableIdentifier)).as("Table should exist").isTrue();

// replace view requires the view to exist
// TODO: replace should check whether the view exists as a table
assertThatThrownBy(
() ->
catalog()
Expand All @@ -469,8 +464,8 @@ public void replaceViewThatAlreadyExistsAsTable() {
.withDefaultNamespace(tableIdentifier.namespace())
.withQuery("spark", "select * from ns.tbl")
.replace())
.isInstanceOf(NoSuchViewException.class)
.hasMessageStartingWith("View does not exist: ns.table");
.isInstanceOf(AlreadyExistsException.class)
.hasMessageContaining("Table with same name already exists: ns.table");
}

@Test
Expand Down

0 comments on commit c63be65

Please sign in to comment.