This is an automated email from the ASF dual-hosted git repository.

kturner pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/accumulo.git


The following commit(s) were added to refs/heads/main by this push:
     new 9c3497bfdc Constructed API methods for creating Mutations from 
key/value pairs (#5702)
9c3497bfdc is described below

commit 9c3497bfdc620308a89594c164ca2563b7483a72
Author: Imirie Billey <[email protected]>
AuthorDate: Thu Jul 17 12:33:42 2025 -0400

    Constructed API methods for creating Mutations from key/value pairs (#5702)
    
    
    Closes #1056
---
 .../org/apache/accumulo/core/data/Mutation.java    |  22 +++++
 .../apache/accumulo/core/data/MutationTest.java    | 107 +++++++++++++++++++++
 2 files changed, 129 insertions(+)

diff --git a/core/src/main/java/org/apache/accumulo/core/data/Mutation.java 
b/core/src/main/java/org/apache/accumulo/core/data/Mutation.java
index b8c6c22feb..9be3143480 100644
--- a/core/src/main/java/org/apache/accumulo/core/data/Mutation.java
+++ b/core/src/main/java/org/apache/accumulo/core/data/Mutation.java
@@ -28,6 +28,7 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.Objects;
 
 import org.apache.accumulo.core.dataImpl.thrift.TMutation;
 import org.apache.accumulo.core.security.ColumnVisibility;
@@ -777,6 +778,16 @@ public class Mutation implements Writable {
     QualifierOptions family(CharSequence colFam);
 
     QualifierOptions family(Text colFam);
+
+    /**
+     * Sets the column family, column qualifier, and column visibility of a 
mutation. All other
+     * fields in the key are ignored.
+     *
+     * @param key key
+     * @return a TimestampOptions object, advancing the method chain
+     * @since 4.0.0
+     */
+    TimestampOptions keyColumns(Key key);
   }
 
   /**
@@ -962,6 +973,17 @@ public class Mutation implements Writable {
       return family(colFam.getBytes(), colFam.getLength());
     }
 
+    @Override
+    public TimestampOptions keyColumns(Key key) {
+      Objects.requireNonNull(key, "key cannot be null");
+
+      byte[] colFam = key.getColumnFamilyData().toArray();
+      byte[] colQual = key.getColumnQualifierData().toArray();
+      byte[] colVis = key.getColumnVisibilityData().toArray();
+
+      return this.family(colFam).qualifier(colQual).visibility(colVis);
+    }
+
     /**
      * Sets the column qualifier of a mutation.
      *
diff --git a/core/src/test/java/org/apache/accumulo/core/data/MutationTest.java 
b/core/src/test/java/org/apache/accumulo/core/data/MutationTest.java
index fd2363d3d4..2d7289a20a 100644
--- a/core/src/test/java/org/apache/accumulo/core/data/MutationTest.java
+++ b/core/src/test/java/org/apache/accumulo/core/data/MutationTest.java
@@ -948,4 +948,111 @@ public class MutationTest {
 
     assertEquals(expected, m.prettyPrint());
   }
+
+  /**
+   * Test that the mutation is correctly updated to be added when a valid Key 
is passed through
+   * {@link Mutation.FamilyOptions#keyColumns(Key)}, and a valid Value is 
passed through
+   * {@link Mutation.TimestampOptions#put(Value)}.
+   */
+  @Test
+  public void testAddingKeyColumns() {
+    Mutation m = new Mutation(new Text("r1"));
+    Key k = new Key(nt("r1"), nt("cf1"), nt("cq1"), new 
ColumnVisibility("cv1"), 1L);
+    m.at().keyColumns(k).timestamp(k.getTimestamp()).put(nv("v1"));
+
+    Key k2 = new Key(nt("r1"), nt("cf2"), nt("cq2"), new 
ColumnVisibility("cv2"), 2L);
+    m.at().keyColumns(k2).put(nv("v2"));
+
+    assertEquals(2, m.size());
+
+    List<ColumnUpdate> updates = m.getUpdates();
+
+    assertEquals(2, m.size());
+    assertEquals(2, updates.size());
+
+    verifyColumnUpdate(updates.get(0), "cf1", "cq1", "cv1", 1L, true, false, 
"v1");
+    verifyColumnUpdate(updates.get(1), "cf2", "cq2", "cv2", 2L, false, false, 
"v2");
+  }
+
+  /**
+   * Test that the mutation is correctly updated to be deleted when a valid 
Key is passed through
+   * {@link Mutation.TimestampOptions#delete()}.
+   */
+  @Test
+  public void testDeletingKeyColumns() {
+    Mutation m = new Mutation(new Text("r1"));
+    Key k = new Key(nt("r1"), nt("cf1"), nt("cq1"), new 
ColumnVisibility("cv1"), 1L);
+    m.at().keyColumns(k).timestamp(k.getTimestamp()).put(nv("v1"));
+    m.at().keyColumns(k).delete();
+
+    Key k2 = new Key(nt("r1"), nt("cf2"), nt("cq2"), new 
ColumnVisibility("cv2"), 2L);
+    m.at().keyColumns(k2).delete();
+
+    assertEquals(3, m.size());
+
+    List<ColumnUpdate> updates = m.getUpdates();
+
+    assertEquals(3, m.size());
+    assertEquals(3, updates.size());
+
+    verifyColumnUpdate(updates.get(0), "cf1", "cq1", "cv1", 1L, true, false, 
"v1");
+    verifyColumnUpdate(updates.get(1), "cf1", "cq1", "cv1", 1L, false, true, 
"");
+    verifyColumnUpdate(updates.get(2), "cf2", "cq2", "cv2", 2L, false, true, 
"");
+  }
+
+  /**
+   * Test that mutations are correctly added back through after being 
previously deleted.
+   */
+  @Test
+  public void testAddingDeletedKeyColumnsBack() {
+    Mutation m = new Mutation(new Text("r1"));
+    Key k = new Key(nt("r1"), nt("cf1"), nt("cq1"), new 
ColumnVisibility("cv1"), 1L);
+    m.at().keyColumns(k).timestamp(k.getTimestamp()).put(nv("v1"));
+    m.at().keyColumns(k).delete();
+    m.at().keyColumns(k).timestamp(k.getTimestamp()).put(nv("v1"));
+
+    Key k2 = new Key(nt("r1"), nt("cf2"), nt("cq2"), new 
ColumnVisibility("cv2"), 2L);
+    m.at().keyColumns(k2).delete();
+    m.at().keyColumns(k2).put(nv("v1"));
+
+    assertEquals(5, m.size());
+
+    List<ColumnUpdate> updates = m.getUpdates();
+
+    assertEquals(5, m.size());
+    assertEquals(5, updates.size());
+
+    verifyColumnUpdate(updates.get(0), "cf1", "cq1", "cv1", 1L, true, false, 
"v1");
+    verifyColumnUpdate(updates.get(1), "cf1", "cq1", "cv1", 1L, false, true, 
"");
+    verifyColumnUpdate(updates.get(2), "cf1", "cq1", "cv1", 1L, true, false, 
"v1");
+    verifyColumnUpdate(updates.get(3), "cf2", "cq2", "cv2", 2L, false, true, 
"");
+    verifyColumnUpdate(updates.get(4), "cf2", "cq2", "cv2", 2L, false, false, 
"v1");
+  }
+
+  /**
+   * Test that a NullPointerException is thrown when passing a null Key through
+   * {@link Mutation.FamilyOptions#keyColumns(Key)}.
+   */
+  @Test
+  public void testKeyColumnsAddingNullKey() {
+    Mutation m = new Mutation(new Text("r1"));
+    Key k = null;
+    Value v = nv("v1");
+
+    assertThrows(NullPointerException.class, () -> 
m.at().keyColumns(k).put(v));
+  }
+
+  /**
+   * Test that a NullPointerException is thrown when passing a null Value 
through
+   * {@link Mutation.TimestampOptions#put(Value)}.
+   */
+  @Test
+  public void testKeyColumnsAddingNullValue() {
+    Mutation m = new Mutation(new Text("r1"));
+    Key k = new Key(nt("r1"), nt("cf1"), nt("cq1"), new 
ColumnVisibility("cv1"), 1L);
+    Value v = null;
+
+    assertThrows(NullPointerException.class, () -> 
m.at().keyColumns(k).put(v));
+  }
+
 }

Reply via email to