This is an automated email from the ASF dual-hosted git repository.

manishswaminathan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pinot.git


The following commit(s) were added to refs/heads/master by this push:
     new 9f248c52aff Add InMemoryColumnReader for testing and update 
PinotSegmentColumnReaderFactory to support configurable default value readers 
(#17415)
9f248c52aff is described below

commit 9f248c52aff01ff6740dfbab5a72d6b185ba1e2c
Author: Krishan Goyal <[email protected]>
AuthorDate: Mon Dec 29 14:39:40 2025 +0530

    Add InMemoryColumnReader for testing and update 
PinotSegmentColumnReaderFactory to support configurable default value readers 
(#17415)
    
    * Add InMemoryColumnReader for testing and update 
PinotSegmentColumnReaderFactory to support configurable default value readers
    
    * Remove default in PinotSegmentColumnarDataSource
---
 .../readers/PinotSegmentColumnReaderFactory.java   |  31 ++-
 .../readers/PinotSegmentColumnarDataSource.java    |   6 +-
 .../segment/readers/InMemoryColumnReader.java      | 258 +++++++++++++++++++++
 3 files changed, 288 insertions(+), 7 deletions(-)

diff --git 
a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/readers/PinotSegmentColumnReaderFactory.java
 
b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/readers/PinotSegmentColumnReaderFactory.java
index 2b40444a52a..b6eb206c31d 100644
--- 
a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/readers/PinotSegmentColumnReaderFactory.java
+++ 
b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/readers/PinotSegmentColumnReaderFactory.java
@@ -22,6 +22,7 @@ import java.io.IOException;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
+import javax.annotation.Nullable;
 import org.apache.pinot.segment.spi.IndexSegment;
 import org.apache.pinot.spi.data.FieldSpec;
 import org.apache.pinot.spi.data.Schema;
@@ -49,6 +50,7 @@ public class PinotSegmentColumnReaderFactory implements 
ColumnReaderFactory {
   private Schema _targetSchema;
   private Set<String> _colsToRead;
   private Map<String, ColumnReader> _columnReaders;
+  private final boolean _initializeDefaultValueReaders;
 
   /**
    * Create a PinotSegmentColumnReaderFactory.
@@ -56,8 +58,22 @@ public class PinotSegmentColumnReaderFactory implements 
ColumnReaderFactory {
    * @param indexSegment Source segment to read from
    */
   public PinotSegmentColumnReaderFactory(IndexSegment indexSegment) {
+    this(indexSegment, true);
+  }
+
+  /**
+   * Create a PinotSegmentColumnReaderFactory.
+   *
+   * @param indexSegment Source segment to read from
+   * @param initializeDefaultValueReaders Whether to initialize default value 
readers for missing columns
+   *           TODO - Ideally this factory shouldn't initialize default value 
readers.
+   *                  The clients of this factory should decide whether to 
create default value readers or not.
+   *                  This parameter is kept for backward compatibility and 
will be removed in future.
+   */
+  public PinotSegmentColumnReaderFactory(IndexSegment indexSegment, boolean 
initializeDefaultValueReaders) {
     _indexSegment = indexSegment;
     _columnReaders = new HashMap<>();
+    _initializeDefaultValueReaders = initializeDefaultValueReaders;
   }
 
   @Override
@@ -103,21 +119,24 @@ public class PinotSegmentColumnReaderFactory implements 
ColumnReaderFactory {
    * Internal method to create a column reader for the specified column.
    * This method is called during initialization to create all readers.
    */
+  @Nullable
   private ColumnReader createColumnReader(String columnName, FieldSpec 
targetFieldSpec) {
     if (targetFieldSpec.isVirtualColumn()) {
       throw new IllegalStateException("Target field spec is a virtual 
column.");
     }
 
-    ColumnReader columnReader;
+    ColumnReader columnReader = null;
 
     if (hasColumn(columnName)) {
       // Column exists in source segment - create a segment column reader
       LOGGER.debug("Creating segment column reader for existing column: {}", 
columnName);
       columnReader = new PinotSegmentColumnReaderImpl(_indexSegment, 
columnName);
     } else {
-      // New column - create a default value reader
-      LOGGER.debug("Creating default value reader for new column: {}", 
columnName);
-      columnReader = new DefaultValueColumnReader(columnName, getNumDocs(), 
targetFieldSpec);
+      if (_initializeDefaultValueReaders) {
+        // New column - create a default value reader
+        LOGGER.debug("Creating default value reader for new column: {}", 
columnName);
+        columnReader = new DefaultValueColumnReader(columnName, getNumDocs(), 
targetFieldSpec);
+      }
     }
 
     return columnReader;
@@ -146,7 +165,9 @@ public class PinotSegmentColumnReaderFactory implements 
ColumnReaderFactory {
         continue;
       }
       ColumnReader reader = createColumnReader(columnName, fieldSpec);
-      allReaders.put(columnName, reader);
+      if (reader != null) {
+        allReaders.put(columnName, reader);
+      }
     }
 
     return allReaders;
diff --git 
a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/readers/PinotSegmentColumnarDataSource.java
 
b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/readers/PinotSegmentColumnarDataSource.java
index 8b3306f6946..960dc7ebc4b 100644
--- 
a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/readers/PinotSegmentColumnarDataSource.java
+++ 
b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/readers/PinotSegmentColumnarDataSource.java
@@ -32,10 +32,12 @@ public class PinotSegmentColumnarDataSource implements 
ColumnarDataSource {
 
   private final IndexSegment _indexSegment;
   private final int _totalDocs;
+  private final boolean _initializeDefaultValueReaders;
 
-  public PinotSegmentColumnarDataSource(IndexSegment indexSegment) {
+  public PinotSegmentColumnarDataSource(IndexSegment indexSegment, boolean 
initializeDefaultValueReaders) {
     _indexSegment = indexSegment;
     _totalDocs = indexSegment.getSegmentMetadata().getTotalDocs();
+    _initializeDefaultValueReaders = initializeDefaultValueReaders;
   }
 
   @Override
@@ -45,7 +47,7 @@ public class PinotSegmentColumnarDataSource implements 
ColumnarDataSource {
 
   @Override
   public ColumnReaderFactory createColumnReaderFactory() {
-    return new PinotSegmentColumnReaderFactory(_indexSegment);
+    return new PinotSegmentColumnReaderFactory(_indexSegment, 
_initializeDefaultValueReaders);
   }
 
   @Override
diff --git 
a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/readers/InMemoryColumnReader.java
 
b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/readers/InMemoryColumnReader.java
new file mode 100644
index 00000000000..adda7e52286
--- /dev/null
+++ 
b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/readers/InMemoryColumnReader.java
@@ -0,0 +1,258 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.pinot.segment.local.segment.readers;
+
+import javax.annotation.Nullable;
+import org.apache.pinot.spi.data.readers.ColumnReader;
+import org.apache.pinot.spi.data.readers.MultiValueResult;
+
+
+/**
+ * Mock ColumnReader for testing with configurable data.
+ */
+public class InMemoryColumnReader implements ColumnReader {
+  private final String _columnName;
+  private final Object[] _values;
+  private final boolean[] _isNull;
+  private final boolean _isSingleValue;
+  private final Class<?> _dataType;
+  private int _currentIndex = 0;
+
+  public InMemoryColumnReader(String columnName, Object[] values, boolean[] 
isNull, boolean isSingleValue,
+      Class<?> dataType) {
+    _columnName = columnName;
+    _values = values;
+    _isNull = isNull;
+    _isSingleValue = isSingleValue;
+    _dataType = dataType;
+  }
+
+  @Override
+  public boolean hasNext() {
+    return _currentIndex < _values.length;
+  }
+
+  @Nullable
+  @Override
+  public Object next() {
+    if (!hasNext()) {
+      throw new IllegalStateException("No more values");
+    }
+    Object value = _values[_currentIndex];
+    _currentIndex++;
+    return value;
+  }
+
+  @Override
+  public boolean isNextNull() {
+    return hasNext() && _isNull[_currentIndex];
+  }
+
+  @Override
+  public void skipNext() {
+    if (hasNext()) {
+      _currentIndex++;
+    }
+  }
+
+  @Override
+  public boolean isSingleValue() {
+    return _isSingleValue;
+  }
+
+  @Override
+  public boolean isInt() {
+    return _dataType == Integer.class;
+  }
+
+  @Override
+  public boolean isLong() {
+    return _dataType == Long.class;
+  }
+
+  @Override
+  public boolean isFloat() {
+    return _dataType == Float.class;
+  }
+
+  @Override
+  public boolean isDouble() {
+    return _dataType == Double.class;
+  }
+
+  @Override
+  public boolean isString() {
+    return _dataType == String.class;
+  }
+
+  @Override
+  public boolean isBytes() {
+    return _dataType == byte[].class;
+  }
+
+  @Override
+  public int nextInt() {
+    return (Integer) next();
+  }
+
+  @Override
+  public long nextLong() {
+    return (Long) next();
+  }
+
+  @Override
+  public float nextFloat() {
+    return (Float) next();
+  }
+
+  @Override
+  public double nextDouble() {
+    return (Double) next();
+  }
+
+  @Override
+  public String nextString() {
+    return (String) next();
+  }
+
+  @Override
+  public byte[] nextBytes() {
+    return (byte[]) next();
+  }
+
+  @Override
+  public MultiValueResult<int[]> nextIntMV() {
+    return MultiValueResult.of((int[]) next(), null);
+  }
+
+  @Override
+  public MultiValueResult<long[]> nextLongMV() {
+    return MultiValueResult.of((long[]) next(), null);
+  }
+
+  @Override
+  public MultiValueResult<float[]> nextFloatMV() {
+    return MultiValueResult.of((float[]) next(), null);
+  }
+
+  @Override
+  public MultiValueResult<double[]> nextDoubleMV() {
+    return MultiValueResult.of((double[]) next(), null);
+  }
+
+  @Override
+  public String[] nextStringMV() {
+    return (String[]) next();
+  }
+
+  @Override
+  public byte[][] nextBytesMV() {
+    return (byte[][]) next();
+  }
+
+  @Override
+  public void rewind() {
+    _currentIndex = 0;
+  }
+
+  @Override
+  public String getColumnName() {
+    return _columnName;
+  }
+
+  @Override
+  public int getTotalDocs() {
+    return _values.length;
+  }
+
+  @Override
+  public boolean isNull(int docId) {
+    return _isNull[docId];
+  }
+
+  @Override
+  public int getInt(int docId) {
+    return (Integer) _values[docId];
+  }
+
+  @Override
+  public long getLong(int docId) {
+    return (Long) _values[docId];
+  }
+
+  @Override
+  public float getFloat(int docId) {
+    return (Float) _values[docId];
+  }
+
+  @Override
+  public double getDouble(int docId) {
+    return (Double) _values[docId];
+  }
+
+  @Override
+  public String getString(int docId) {
+    return (String) _values[docId];
+  }
+
+  @Override
+  public byte[] getBytes(int docId) {
+    return (byte[]) _values[docId];
+  }
+
+  @Override
+  public Object getValue(int docId) {
+    return _values[docId];
+  }
+
+  @Override
+  public MultiValueResult<int[]> getIntMV(int docId) {
+    return MultiValueResult.of((int[]) _values[docId], null);
+  }
+
+  @Override
+  public MultiValueResult<long[]> getLongMV(int docId) {
+    return MultiValueResult.of((long[]) _values[docId], null);
+  }
+
+  @Override
+  public MultiValueResult<float[]> getFloatMV(int docId) {
+    return MultiValueResult.of((float[]) _values[docId], null);
+  }
+
+  @Override
+  public MultiValueResult<double[]> getDoubleMV(int docId) {
+    return MultiValueResult.of((double[]) _values[docId], null);
+  }
+
+  @Override
+  public String[] getStringMV(int docId) {
+    return (String[]) _values[docId];
+  }
+
+  @Override
+  public byte[][] getBytesMV(int docId) {
+    return (byte[][]) _values[docId];
+  }
+
+  @Override
+  public void close() {
+    // No-op
+  }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to