[ 
https://issues.apache.org/jira/browse/HBASE-29217?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17938931#comment-17938931
 ] 

ruanhui commented on HBASE-29217:
---------------------------------

Thanks for your reply. After revisiting HRegion#checkAndMutateInternal, I think 
you are right and I agree with your solution.
 
Here is my opinion. I think the problem is that when filters are set, an empty 
cell can also meet some of the filter requirements, such as EQUAL NULL. But 
currently, once the result is empty, we think it's unmatched, so the example I 
gave above does not work. I think we can still determine whether the filter 
requirements are met when the result is empty like this:
{code:java}
if (filter != null) {
  if (!result.isEmpty()) {
    matches = true;
    cellTs = result.get(0).getTimestamp();
  } else {
    // here we create a special 'empty' cell and determine whether the filter 
requirements are met     
   Cell emptyCell = new KeyValue(HConstants.EMPTY_BYTE_ARRAY,
      HConstants.EMPTY_BYTE_ARRAY,
      HConstants.EMPTY_BYTE_ARRAY,
      HConstants.EMPTY_BYTE_ARRAY);
    matches = !filter.filterRowKey(emptyCell);
  }
} {code}
And Here is a passed UT
{code:java}
@Test
public void testFilterOfNonExistsRow() throws Throwable {
  byte[] qualifier = Bytes.toBytes("Q");

  // Filter 1: Check column absence
  Filter existsFilter = new RowFilter(CompareOperator.EQUAL, new 
BinaryComparator(HConstants.EMPTY_BYTE_ARRAY));
  // Filter 2: Check value condition if Step 1 fails
  Filter valueFilter = new ValueFilter(CompareOperator.EQUAL, new 
BinaryComparator(Bytes.toBytes("v1")));
  // Parent Filter: compose Filter 1 and Filter 2 with Or
  FilterList filterList = new FilterList(
    FilterList.Operator.MUST_PASS_ONE, Arrays.asList(existsFilter, 
valueFilter));

  CheckAndMutate checkAndMutate1 = CheckAndMutate.newBuilder(ROWKEY)
    .ifMatches(filterList)
    .build(new Put(ROWKEY).addColumn(FAMILY, qualifier, Bytes.toBytes("v1")));

  try (Table table = createTable()) {
    table.checkAndMutate(checkAndMutate1);
    assertEquals("v1", Bytes.toString(
      table.get(new Get(ROWKEY).addColumn(FAMILY, qualifier)).getValue(FAMILY, 
qualifier)));
  }
} {code}
This is just a rough idea, not yet polished, not sure if there are any problems 
...
 
Thanks.
 

> Enhancement for CheckAndMutate
> ------------------------------
>
>                 Key: HBASE-29217
>                 URL: https://issues.apache.org/jira/browse/HBASE-29217
>             Project: HBase
>          Issue Type: Improvement
>          Components: Client, regionserver
>            Reporter: Xuesen Liang
>            Assignee: Xuesen Liang
>            Priority: Major
>              Labels: pull-request-available
>
> The current implementation of _CheckAndMutate_ operation provides two 
> conditional verification modes:
> 1. Column Non-exists:
> {code:java}
> ifMatches(family, qualifier, CompareOperator.EQUAL, null)
> {code}
> Validates that the specified column does not exist.
> 2. Column Value Comparison/Filter
> {code:java}
> ifMatches(family, qualifier, CompareOperator, value) 
> {code}
> OR
> {code:java}
> ifMatches(Filter)
> {code}
> Verifies that the column exists and satisfies the defined comparison/filter 
> logic.
>  
> *Limitation:*
> The existing API lacks support for composite conditional checks of the form:
> _"Column X either does not exist, OR exists and meets comparison condition"._
>  
> *Current Workaround & Risks:*
> To implement this logic, developers must:
> {code:java}
> // Step 1: Check column absence
> checkAndMutate.ifMatches(family, qualifier, CompareOperator.EQUAL, null)
> // Step 2: Check value condition if Step 1 fails 
> checkAndMutate.ifMatches(family, qualifier, CompareOperator, value)
> {code}
> This approach introduces following critical issues:
>  * Non-atomic Execution: The two-phase check creates race conditions.
>  * API Complexity: Forces developers to implement client-side synchronization 
> logic.
>  * Performance: There are two RPC calls.
>  
> *Proposed Solution:*
> Introduce a composite conditional operator:
> {code:java}
> ifNotExistsOr(family, qualifier, CompareOperator, value)
> {code}
>  
> *Implementation Benefits:*
>  * Atomic Guarantee: Executes the "NOT EXISTS OR SATISFIES" logic in a single 
> RPC call.
>  * API Simplification: Reduces client-side code complexity.
> This enhancement would align HBase's conditional mutation capabilities with 
> modern database systems supporting compound atomic predicates, while 
> maintaining backward compatibility.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to