Skip to content

Commit

Permalink
Update OpenAPI docs for Put + Delete
Browse files Browse the repository at this point in the history
and some left-over inline comments cleaned up
  • Loading branch information
snazy committed Mar 29, 2023
1 parent dc53e95 commit 7199cd5
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 9 deletions.
36 changes: 33 additions & 3 deletions api/model/src/main/java/org/projectnessie/model/Operation.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@
@Schema(
type = SchemaType.OBJECT,
title = "Operation",
description =
"Describes an operation to be performed against one content object.\n"
+ "\n"
+ "The Nessie backend will perform validations against the correctness of the "
+ "operations. Note that the amount and strictness of validations depends on the Nessie "
+ "version and potentially the Nessie configuration.",
oneOf = {Operation.Put.class, Operation.Unchanged.class, Operation.Delete.class},
discriminatorMapping = {
@DiscriminatorMapping(value = "PUT", schema = Operation.Put.class),
Expand All @@ -53,9 +59,24 @@ public interface Operation {
type = SchemaType.OBJECT,
title = "Put-'Content'-operation for a 'ContentKey'.",
description =
"Add or replace (put) a 'Content' object for a 'ContentKey'. "
+ "If the actual table type tracks the 'global state' of individual tables (Iceberg "
+ "as of today), every 'Put'-operation must contain a non-null value for 'expectedContent'.")
"Used to add new content or to update existing content.\n"
+ "\n"
+ "A new content object is created by populating only the `value` field, the "
+ "content-id in the content object must not be present (null).\n"
+ "\n"
+ "A content object is updated by populating both the `value` and `expeectedValue` "
+ "fields, the content-id in both content objects must be the same.\n"
+ "\n"
+ "If the key for a content shall change (aka a rename), then use a `Delete` "
+ "operation using the current (old) key and a `Put` operation using the new key "
+ "populating both the `value` and `expectedValue` fields. Both operations must "
+ "happen in the same commit.\n"
+ "\n"
+ "A content object can be replaced (think: `DROP TABLE xyz` + `CREATE TABLE xyz`) "
+ "with a `Delete` operation and a `Put` operation for a content (without "
+ "`expectedValue` and no content-id present in `value`) in the same commit.\n"
+ "\n"
+ "Updating existing content without expectedValue will result in an error.")
@Value.Immutable
@JsonSerialize(as = ImmutablePut.class)
@JsonDeserialize(as = ImmutablePut.class)
Expand All @@ -82,6 +103,15 @@ static Put of(ContentKey key, Content content, Content expectedContent) {
}
}

@Schema(
type = SchemaType.OBJECT,
title = "Delete-'Content'-operation for a 'ContentKey'.",
description =
"Used to delete an existing content key.\n"
+ "\n"
+ "If the key for a content shall change (aka a rename), then use a `Delete` "
+ "operation using the current (old) key and a `Put` operation using the new key "
+ "populating both the `value` and `expectedValue` fields. See `Put` operation.")
@Value.Immutable
@JsonSerialize(as = ImmutableDelete.class)
@JsonDeserialize(as = ImmutableDelete.class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ public Stream<FileReference> extractFiles(ContentReference contentReference) {
contentReference.snapshotId(),
"Iceberg content is expected to have a non-null snapshot-ID");

// This is to respect Nessie's global state
Snapshot snapshot =
snapshotId < 0L ? tableMetadata.currentSnapshot() : tableMetadata.snapshot(snapshotId);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,6 @@ static Stream<RenameTable> commitRenameTableParams() {
.boxed()
.flatMap(i -> Stream.of(new RenameTable(i, i, i, i), new RenameTable(0, 0, 0, 0)));

// duplicate all params to use and not use global state
return Stream.concat(zero, intervals);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import javax.annotation.Nonnull;
import org.immutables.value.Value;
import org.projectnessie.model.Content;
import org.projectnessie.model.ContentKey;

/** A delete operation. */
Expand All @@ -26,6 +27,10 @@ public interface Delete extends Operation {
/**
* Creates a delete operation for the given key.
*
* <p>If the key for a content shall change (aka a rename), then use a {@link Delete} operation
* using the current (old) key and a {@link Put} operation using the new key providing both {@code
* value} and {@code expectedValue}, see {@link Put#of( ContentKey, Content, Content)}.
*
* @param key the key impacted by the operation
* @return a delete operation for the key
*/
Expand Down
20 changes: 16 additions & 4 deletions versioned/spi/src/main/java/org/projectnessie/versioned/Put.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,13 @@ public interface Put extends Operation {
* Creates a put-operation for the given key and value without an expected-value so the returned
* put-operation is unconditional.
*
* <p>Unconditional put-operations must be used for content-types that do not support global-state
* and for those that do support global-state when a new content object is added.
* <p>Using only {@code value} without {@code expectedValue} is <em>required</em> when
* creating/adding new content.
*
* <p>Updating existing content without {@code expectedValue} will result in an error.
*
* <p>A content object is considered to be the same using the {@link ContentKey content-key} and
* the {@link Content#getId() content-id}.
*
* @param key the key impacted by the operation
* @param value the new value associated with the key
Expand All @@ -60,8 +65,15 @@ static Put of(
* returned put-operation will check whether the current state in Nessie matches the expected
* state in {@code expectedValue}.
*
* <p>Using a conditional put-operation for a content-type that does not support global-state
* results in an error.
* <p>Using both {@code value} and {@code expectedValue} is <em>required</em> when an existing
* content is updated.
*
* <p>A content object is considered to be the same using the {@link ContentKey content-key} and
* the {@link Content#getId() content-id}.
*
* <p>If the key for a content shall change (aka a rename), then use a {@link Delete} operation
* using the current (old) key and a {@link Put} operation using the new key providing both {@code
* value} and {@code expectedValue}.
*
* @param key the key impacted by the operation
* @param value the new value associated with the key
Expand Down

0 comments on commit 7199cd5

Please sign in to comment.