[
https://issues.apache.org/jira/browse/HBASE-29217?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17938830#comment-17938830
]
Xuesen Liang commented on HBASE-29217:
--------------------------------------
Hi [~frostruan],
Thanks for your suggestion. I'd like to clarify that the _Filter_ mechanism
only matches when a row exists, meaning the row must have at least one column X.
To illustrate this behavior, here's the relevant logic from
{_}HRegion#checkAndMutateInternal{_}:
{code:java}
List<ExtendedCell> result = new ArrayList<>(1);
scanner.next(result);
if (filter != null) {
if (!result.isEmpty()) {
matches = true;
cellTs = result.get(0).getTimestamp();
}
}
...
{code}
This implementation shows that the filter only evaluates when the result set is
non-empty.
Additionally, I've created a unit test that demonstrates the behavior:
{code:java}
@Test
public void testFilterOfNonExistsRow() throws Throwable {
byte[] qualifier = Bytes.toBytes("Q");
// Filter 1: Check column absence
Filter existsFilter = new ValueFilter(CompareOperator.EQUAL, new
NullComparator());
// 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}
The error messages:
{code:java}
[ERROR]
org.apache.hadoop.hbase.client.TestCheckAndMutate.testFilterOfNonExistsRow
Time elapsed: 2.254 s <<< FAILURE!
java.lang.AssertionError: expected:<v1> but was:<null>
....
{code}
This test case fails as expected, demonstrating that the filter doesn't match
when the row doesn't exist. Let me know if you'd like to discuss this further
or explore alternative approaches.
> 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)