[
https://issues.apache.org/jira/browse/PHOENIX-8045?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Andrew Kyle Purtell updated PHOENIX-8045:
-----------------------------------------
Description:
During server-side scan execution Phoenix builds result rows for aggregation
and state tracking using {{{}ByteUtil.getLargestPossibleRowKeyInRange(){}}}.
This utility should construct a synthetic key that falls within the active
scan's boundaries so that downstream client verification logic accepts the
payload. In the table's end region, the upper limit is an empty byte array
({{{}HConstants.EMPTY_END_ROW{}}}), conceptually representing positive infinity
rather than a literal byte sequence.
However, because lexicographical comparison places any non-empty byte array
after an empty array, the check misinterprets the conceptual indication of
positive infinity / no end to the range as a zero-length empty start of the
range. An assertion fails, logs a misleading error, and returns null. Callers
then fall back to degenerate keys, such as the start key, stop row, or an empty
key, which fail subsequent client side range checks and this can cause valid
results to be discarded during background workloads like index builds, dropping
out rows from the rebuild.
The fix makes {{ByteUtil}} consistent with the client side region boundary
contract defined in {{{}ScanUtil.verifyKeyInScanRange(){}}}. An empty end key
is treated as an unbounded range, skipping the upper limit comparison entirely.
was:
During server-side scan execution Phoenix builds result rows for aggregation
and state tracking using {{{}ByteUtil.getLargestPossibleRowKeyInRange(){}}}.
This utility should construct a synthetic key that falls within the active
scan's boundaries so that downstream client verification logic accepts the
payload. In the table's end region, the upper limit is an empty byte array
({{{}HConstants.EMPTY_END_ROW{}}}), conceptually representing positive infinity
rather than a literal byte sequence.
Because lexicographical comparison places any non-empty byte array after an
empty array, the check misinterprets the empty bound as a zero-length floor
rather than an unbounded ceiling. Consequently, the assertion fails, logs an
unexpected range error, and returns null. Callers then fall back to degenerate
keys, such as the start key, stop row, or an empty key, which fail subsequent
client side range checks and causes valid results to be discarded during
background workloads like index builds.
The fix makes {{ByteUtil}} consistent with the client side region boundary
contract defined in {{{}ScanUtil.verifyKeyInScanRange(){}}}. An empty end key
is treated as an unbounded range, skipping the upper limit comparison entirely.
> Treat an empty end key as no upper bound in getLargestPossibleRowKeyInRange
> ---------------------------------------------------------------------------
>
> Key: PHOENIX-8045
> URL: https://issues.apache.org/jira/browse/PHOENIX-8045
> Project: Phoenix
> Issue Type: Bug
> Components: core
> Affects Versions: 5.3.2
> Reporter: Andrew Kyle Purtell
> Assignee: Andrew Kyle Purtell
> Priority: Major
> Fix For: 5.4.0, 5.3.3
>
>
> During server-side scan execution Phoenix builds result rows for aggregation
> and state tracking using {{{}ByteUtil.getLargestPossibleRowKeyInRange(){}}}.
> This utility should construct a synthetic key that falls within the active
> scan's boundaries so that downstream client verification logic accepts the
> payload. In the table's end region, the upper limit is an empty byte array
> ({{{}HConstants.EMPTY_END_ROW{}}}), conceptually representing positive
> infinity rather than a literal byte sequence.
> However, because lexicographical comparison places any non-empty byte array
> after an empty array, the check misinterprets the conceptual indication of
> positive infinity / no end to the range as a zero-length empty start of the
> range. An assertion fails, logs a misleading error, and returns null. Callers
> then fall back to degenerate keys, such as the start key, stop row, or an
> empty key, which fail subsequent client side range checks and this can cause
> valid results to be discarded during background workloads like index builds,
> dropping out rows from the rebuild.
> The fix makes {{ByteUtil}} consistent with the client side region boundary
> contract defined in {{{}ScanUtil.verifyKeyInScanRange(){}}}. An empty end key
> is treated as an unbounded range, skipping the upper limit comparison
> entirely.
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)