LuciferYang opened a new pull request, #9654:
URL: https://github.com/apache/paimon/pull/9654

   ### Purpose
   
   close #9645
   
   A BSI index maps TIMESTAMP through `Timestamp#toMicros()`, so on a column 
with precision above 6 two values that differ only below a microsecond share 
one indexed value. That would be harmless for a candidate set, but a 
`BitmapIndexResult` is not one: `RawFileSplitRead` hands the bitmap to 
`ApplyBitmapIndexRecordReader`, which reads exactly those rows. So `ts <> 
'...000000000'` drops a row whose nanoseconds differ from the literal, and `ts 
= '...'` selects it.
   
   This fixes it on the read side. When the value mapper truncates for the 
column's type, `createReader` wraps the reader so that only `IS NULL` and `IS 
NOT NULL` come from the index and every value predicate falls through to 
`FileIndexReader`'s `REMAIN` default, which leaves the file to be read and 
filtered normally. Null-ness does not depend on the truncated digits, so those 
two questions still prune. The index format and the writer are untouched, which 
also means index files already written are read correctly from now on.
   
   The alternative was to store nanos and bump the format version. I did not 
take it: it breaks old readers for every type that uses BSI, and nanoseconds 
since the epoch overflow int64 in 2262 while microseconds reach year 294247.
   
   The condition is `precision > 6`, matching what the declared type can 
represent rather than what the mapper keeps. A column declared TIMESTAMP(4..6) 
cannot hold sub-microsecond values in the first place, so an index that stores 
microseconds is faithful to it, and widening the condition to `> 3` would cost 
every correct TIMESTAMP(4..6) table its BSI pruning for nothing.
   
   One related thing I found while checking that boundary, and deliberately 
left alone here: nothing on the write path normalizes a value to its column's 
declared precision, and ORC round-trips whatever nanoseconds it was given. 
`FieldWriterFactory.visit(TimestampType)` writes full nanos via 
`toSQLTimestamp()`, and `OrcTimestampColumnVector` reads `vector.nanos[i] % 
1_000_000` without consulting the precision. Parquet does clamp (MILLIS at 
precision 3 and below, MICROS at 4 to 6), so on Parquet a precision-6 column 
can never read back sub-microsecond digits. That gap belongs to the write path 
or to the ORC reader, not to the file index, so it is out of scope for this PR.
   
   ### Tests
   
   `BitSliceIndexBitmapFileIndexTest` gets two cases. 
`testSubMicrosecondTimestampIndexAnswersNoValuePredicate` builds a TIMESTAMP(9) 
index over two values half a microsecond apart plus a null, asserts that equal, 
not-equal, in, not-in, less-than, greater-than and between all return `REMAIN`, 
and that `IS NULL` and `IS NOT NULL` still return exact bitmaps. 
`testMicrosecondTimestampIndexStillAnswersValuePredicates` pins the other side 
of the boundary: at precision 6 the index still answers value predicates with 
exact bitmaps.
   
   Verified both directions. With `BitSliceIndexBitmapFileIndex.java` reverted 
to master, the first assertion fails with `expected: FileIndexResult$1 but was: 
BitmapIndexResult`; with the change in place the class passes 7/7.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to