4343import org .apache .lucene .util .compress .LZ4 ;
4444import org .apache .lucene .util .packed .DirectMonotonicReader ;
4545import org .apache .lucene .util .packed .PackedInts ;
46+ import org .elasticsearch .core .Assertions ;
4647import org .elasticsearch .core .IOUtils ;
4748import org .elasticsearch .index .codec .tsdb .TSDBDocValuesEncoder ;
4849import org .elasticsearch .index .mapper .BlockDocValuesReader ;
@@ -388,6 +389,7 @@ public BlockLoader.Block tryRead(
388389 BlockLoader .BlockFactory factory ,
389390 BlockLoader .Docs docs ,
390391 int offset ,
392+ boolean nullsFiltered ,
391393 BlockDocValuesReader .ToDouble toDouble
392394 ) throws IOException {
393395 assert toDouble == null ;
@@ -468,6 +470,7 @@ public BlockLoader.Block tryRead(
468470 BlockLoader .BlockFactory factory ,
469471 BlockLoader .Docs docs ,
470472 int offset ,
473+ boolean nullsFiltered ,
471474 BlockDocValuesReader .ToDouble toDouble
472475 ) throws IOException {
473476 return null ;
@@ -520,6 +523,7 @@ public BlockLoader.Block tryRead(
520523 BlockLoader .BlockFactory factory ,
521524 BlockLoader .Docs docs ,
522525 int offset ,
526+ boolean nullsFiltered ,
523527 BlockDocValuesReader .ToDouble toDouble
524528 ) throws IOException {
525529 return null ;
@@ -532,7 +536,7 @@ BlockLoader.Block tryRead(BlockLoader.SingletonLongBuilder builder, BlockLoader.
532536 }
533537 }
534538
535- abstract static class BaseSparseNumericValues extends NumericDocValues {
539+ abstract static class BaseSparseNumericValues extends NumericDocValues implements BlockLoader . OptionalColumnAtATimeReader {
536540 protected final IndexedDISI disi ;
537541
538542 BaseSparseNumericValues (IndexedDISI disi ) {
@@ -563,6 +567,17 @@ public final int docID() {
563567 public final long cost () {
564568 return disi .cost ();
565569 }
570+
571+ @ Override
572+ public BlockLoader .Block tryRead (
573+ BlockLoader .BlockFactory factory ,
574+ BlockLoader .Docs docs ,
575+ int offset ,
576+ boolean nullsFiltered ,
577+ BlockDocValuesReader .ToDouble toDouble
578+ ) throws IOException {
579+ return null ;
580+ }
566581 }
567582
568583 abstract static class BaseSortedSetDocValues extends SortedSetDocValues {
@@ -1386,16 +1401,11 @@ public BlockLoader.Block tryRead(
13861401 BlockLoader .BlockFactory factory ,
13871402 BlockLoader .Docs docs ,
13881403 int offset ,
1404+ boolean nullsFiltered ,
13891405 BlockDocValuesReader .ToDouble toDouble
13901406 ) throws IOException {
1391- if (toDouble != null ) {
1392- try (BlockLoader .SingletonDoubleBuilder builder = factory .singletonDoubles (docs .count () - offset )) {
1393- SingletonLongToDoubleDelegate delegate = new SingletonLongToDoubleDelegate (builder , toDouble );
1394- return tryRead (delegate , docs , offset );
1395- }
1396- }
1397- try (BlockLoader .SingletonLongBuilder builder = factory .singletonLongs (docs .count () - offset )) {
1398- return tryRead (builder , docs , offset );
1407+ try (var singletonLongBuilder = singletonLongBuilder (factory , toDouble , docs .count () - offset )) {
1408+ return tryRead (singletonLongBuilder , docs , offset );
13991409 }
14001410 }
14011411
@@ -1484,6 +1494,7 @@ static boolean isDense(int firstDocId, int lastDocId, int length) {
14841494 );
14851495 return new BaseSparseNumericValues (disi ) {
14861496 private final TSDBDocValuesEncoder decoder = new TSDBDocValuesEncoder (ES819TSDBDocValuesFormat .NUMERIC_BLOCK_SIZE );
1497+ private IndexedDISI lookAheadDISI ;
14871498 private long currentBlockIndex = -1 ;
14881499 private final long [] currentBlock = new long [ES819TSDBDocValuesFormat .NUMERIC_BLOCK_SIZE ];
14891500
@@ -1507,6 +1518,74 @@ public long longValue() throws IOException {
15071518 }
15081519 return currentBlock [blockInIndex ];
15091520 }
1521+
1522+ @ Override
1523+ public BlockLoader .Block tryRead (
1524+ BlockLoader .BlockFactory factory ,
1525+ BlockLoader .Docs docs ,
1526+ int offset ,
1527+ boolean nullsFiltered ,
1528+ BlockDocValuesReader .ToDouble toDouble
1529+ ) throws IOException {
1530+ if (nullsFiltered == false ) {
1531+ return null ;
1532+ }
1533+ final int firstDoc = docs .get (offset );
1534+ if (disi .advanceExact (firstDoc ) == false ) {
1535+ assert false : "nullsFiltered is true, but doc [" + firstDoc + "] has no value" ;
1536+ throw new IllegalStateException ("nullsFiltered is true, but doc [" + firstDoc + "] has no value" );
1537+ }
1538+ if (lookAheadDISI == null ) {
1539+ lookAheadDISI = new IndexedDISI (
1540+ data ,
1541+ entry .docsWithFieldOffset ,
1542+ entry .docsWithFieldLength ,
1543+ entry .jumpTableEntryCount ,
1544+ entry .denseRankPower ,
1545+ entry .numValues
1546+ );
1547+ }
1548+ final int lastDoc = docs .get (docs .count () - 1 );
1549+ if (lookAheadDISI .advanceExact (lastDoc ) == false ) {
1550+ assert false : "nullsFiltered is true, but doc [" + lastDoc + "] has no value" ;
1551+ throw new IllegalStateException ("nullsFiltered is true, but doc [" + lastDoc + "] has no value" );
1552+ }
1553+ // Assumes docIds are unique - if the number of value indices between the first
1554+ // and last doc equals the doc count, all values can be read and converted in bulk
1555+ // TODO: Pass docCount attr for enrich and lookup.
1556+ final int firstIndex = disi .index ();
1557+ final int lastIndex = lookAheadDISI .index ();
1558+ final int valueCount = lastIndex - firstIndex + 1 ;
1559+ if (valueCount != docs .count ()) {
1560+ return null ;
1561+ }
1562+ if (Assertions .ENABLED ) {
1563+ for (int i = 0 ; i < docs .count (); i ++) {
1564+ final int doc = docs .get (i + offset );
1565+ assert disi .advanceExact (doc ) : "nullsFiltered is true, but doc [" + doc + "] has no value" ;
1566+ assert disi .index () == firstIndex + i : "unexpected disi index " + (firstIndex + i ) + "!=" + disi .index ();
1567+ }
1568+ }
1569+ try (var singletonLongBuilder = singletonLongBuilder (factory , toDouble , valueCount )) {
1570+ for (int i = 0 ; i < valueCount ;) {
1571+ final int index = firstIndex + i ;
1572+ final int blockIndex = index >>> ES819TSDBDocValuesFormat .NUMERIC_BLOCK_SHIFT ;
1573+ final int blockStartIndex = index & ES819TSDBDocValuesFormat .NUMERIC_BLOCK_MASK ;
1574+ if (blockIndex != currentBlockIndex ) {
1575+ assert blockIndex > currentBlockIndex : blockIndex + "<=" + currentBlockIndex ;
1576+ if (currentBlockIndex + 1 != blockIndex ) {
1577+ valuesData .seek (indexReader .get (blockIndex ));
1578+ }
1579+ currentBlockIndex = blockIndex ;
1580+ decoder .decode (valuesData , currentBlock );
1581+ }
1582+ final int count = Math .min (ES819TSDBDocValuesFormat .NUMERIC_BLOCK_SIZE - blockStartIndex , valueCount - i );
1583+ singletonLongBuilder .appendLongs (currentBlock , blockStartIndex , count );
1584+ i += count ;
1585+ }
1586+ return singletonLongBuilder .build ();
1587+ }
1588+ }
15101589 };
15111590 }
15121591 }
@@ -1802,11 +1881,22 @@ public BlockLoader.Builder endPositionEntry() {
18021881 public void close () {}
18031882 }
18041883
1884+ static BlockLoader .SingletonLongBuilder singletonLongBuilder (
1885+ BlockLoader .BlockFactory factory ,
1886+ BlockDocValuesReader .ToDouble toDouble ,
1887+ int valueCount
1888+ ) {
1889+ if (toDouble != null ) {
1890+ return new SingletonLongToDoubleDelegate (factory .singletonDoubles (valueCount ), toDouble );
1891+ } else {
1892+ return factory .singletonLongs (valueCount );
1893+ }
1894+ }
1895+
18051896 // Block builder that consumes long values and converts them to double using the provided converter function.
18061897 static final class SingletonLongToDoubleDelegate implements BlockLoader .SingletonLongBuilder {
18071898 private final BlockLoader .SingletonDoubleBuilder doubleBuilder ;
18081899 private final BlockDocValuesReader .ToDouble toDouble ;
1809- private final double [] buffer = new double [ES819TSDBDocValuesFormat .NUMERIC_BLOCK_SIZE ];
18101900
18111901 // The passed builder is used to store the converted double values and produce the final block containing them.
18121902 SingletonLongToDoubleDelegate (BlockLoader .SingletonDoubleBuilder doubleBuilder , BlockDocValuesReader .ToDouble toDouble ) {
@@ -1821,11 +1911,7 @@ public BlockLoader.SingletonLongBuilder appendLong(long value) {
18211911
18221912 @ Override
18231913 public BlockLoader .SingletonLongBuilder appendLongs (long [] values , int from , int length ) {
1824- assert length <= buffer .length : "length " + length + " > " + buffer .length ;
1825- for (int i = 0 ; i < length ; i ++) {
1826- buffer [i ] = toDouble .convert (values [from + i ]);
1827- }
1828- doubleBuilder .appendDoubles (buffer , 0 , length );
1914+ doubleBuilder .appendLongs (toDouble , values , from , length );
18291915 return this ;
18301916 }
18311917
@@ -1850,7 +1936,9 @@ public BlockLoader.Builder endPositionEntry() {
18501936 }
18511937
18521938 @ Override
1853- public void close () {}
1939+ public void close () {
1940+ doubleBuilder .close ();
1941+ }
18541942 }
18551943
18561944}
0 commit comments