@@ -160,7 +160,7 @@ public QwpColumnDef[] getColumnDefs() {
160160 cachedColumnDefs = new QwpColumnDef [columns .size ()];
161161 for (int i = 0 ; i < columns .size (); i ++) {
162162 ColumnBuffer col = columns .get (i );
163- cachedColumnDefs [i ] = new QwpColumnDef (col .name , col .type , col .nullable );
163+ cachedColumnDefs [i ] = new QwpColumnDef (col .name , col .type , col .useNullBitmap );
164164 }
165165 columnDefsCacheValid = true ;
166166 }
@@ -507,11 +507,10 @@ void reset(boolean forLong) {
507507 */
508508 public static class ColumnBuffer implements QuietCloseable {
509509 private static final long DOUBLE_ARRAY_BASE_OFFSET = Unsafe .getUnsafe ().arrayBaseOffset (double [].class );
510- private static final long LONG_ARRAY_BASE_OFFSET = Unsafe .getUnsafe ().arrayBaseOffset (long [].class );
511510 final int elemSize ;
512511 final String name ;
513- final boolean nullable ;
514512 final byte type ;
513+ final boolean useNullBitmap ;
515514 private final Decimal256 rescaleTemp = new Decimal256 ();
516515 private ArrayCapture arrayCapture ;
517516 private int arrayDataOffset ;
@@ -545,18 +544,18 @@ public static class ColumnBuffer implements QuietCloseable {
545544 private StringSink symbolLookupSink ;
546545 private int valueCount ; // Actual stored values (excludes nulls)
547546
548- public ColumnBuffer (String name , byte type , boolean nullable ) {
547+ public ColumnBuffer (String name , byte type , boolean useNullBitmap ) {
549548 this .name = name ;
550549 this .type = type ;
551- this .nullable = nullable ;
550+ this .useNullBitmap = useNullBitmap ;
552551 this .elemSize = elementSizeInBuffer (type );
553552 this .size = 0 ;
554553 this .valueCount = 0 ;
555554 this .hasNulls = false ;
556555
557556 try {
558557 allocateStorage (type );
559- if (nullable ) {
558+ if (useNullBitmap ) {
560559 nullBufCapRows = 64 ; // multiple of 64
561560 long sizeBytes = (long ) nullBufCapRows >>> 3 ;
562561 nullBufPtr = Unsafe .calloc (sizeBytes , MemoryTag .NATIVE_ILP_RSS );
@@ -568,14 +567,14 @@ public ColumnBuffer(String name, byte type, boolean nullable) {
568567 }
569568
570569 public void addBoolean (boolean value ) {
571- ensureNullBitmapForNonNull ();
570+ ensureNullBitmapCapacity ();
572571 dataBuffer .putByte (value ? (byte ) 1 : (byte ) 0 );
573572 valueCount ++;
574573 size ++;
575574 }
576575
577576 public void addByte (byte value ) {
578- ensureNullBitmapForNonNull ();
577+ ensureNullBitmapCapacity ();
579578 dataBuffer .putByte (value );
580579 valueCount ++;
581580 size ++;
@@ -586,7 +585,7 @@ public void addDecimal128(Decimal128 value) {
586585 addNull ();
587586 return ;
588587 }
589- ensureNullBitmapForNonNull ();
588+ ensureNullBitmapCapacity ();
590589 if (decimalScale == -1 ) {
591590 decimalScale = (byte ) value .getScale ();
592591 } else if (decimalScale != value .getScale ()) {
@@ -619,7 +618,7 @@ public void addDecimal256(Decimal256 value) {
619618 addNull ();
620619 return ;
621620 }
622- ensureNullBitmapForNonNull ();
621+ ensureNullBitmapCapacity ();
623622 Decimal256 src = value ;
624623 if (decimalScale == -1 ) {
625624 decimalScale = (byte ) value .getScale ();
@@ -646,7 +645,7 @@ public void addDecimal64(Decimal64 value) {
646645 addNull ();
647646 return ;
648647 }
649- ensureNullBitmapForNonNull ();
648+ ensureNullBitmapCapacity ();
650649 if (decimalScale == -1 ) {
651650 decimalScale = (byte ) value .getScale ();
652651 dataBuffer .putLong (value .getValue ());
@@ -672,7 +671,7 @@ public void addDecimal64(Decimal64 value) {
672671 }
673672
674673 public void addDouble (double value ) {
675- ensureNullBitmapForNonNull ();
674+ ensureNullBitmapCapacity ();
676675 dataBuffer .putDouble (value );
677676 valueCount ++;
678677 size ++;
@@ -779,7 +778,7 @@ public void addDoubleArrayPayload(long ptr, long len) {
779778 }
780779
781780 public void addFloat (float value ) {
782- ensureNullBitmapForNonNull ();
781+ ensureNullBitmapCapacity ();
783782 dataBuffer .putFloat (value );
784783 valueCount ++;
785784 size ++;
@@ -802,28 +801,28 @@ public void addGeoHash(long value, int precision) {
802801 "GeoHash precision mismatch: column has " + geohashPrecision + " bits, got " + precision
803802 );
804803 }
805- ensureNullBitmapForNonNull ();
804+ ensureNullBitmapCapacity ();
806805 dataBuffer .putLong (value );
807806 valueCount ++;
808807 size ++;
809808 }
810809
811810 public void addInt (int value ) {
812- ensureNullBitmapForNonNull ();
811+ ensureNullBitmapCapacity ();
813812 dataBuffer .putInt (value );
814813 valueCount ++;
815814 size ++;
816815 }
817816
818817 public void addLong (long value ) {
819- ensureNullBitmapForNonNull ();
818+ ensureNullBitmapCapacity ();
820819 dataBuffer .putLong (value );
821820 valueCount ++;
822821 size ++;
823822 }
824823
825824 public void addLong256 (long l0 , long l1 , long l2 , long l3 ) {
826- ensureNullBitmapForNonNull ();
825+ ensureNullBitmapCapacity ();
827826 dataBuffer .putLong (l0 );
828827 dataBuffer .putLong (l1 );
829828 dataBuffer .putLong (l2 );
@@ -929,8 +928,8 @@ public void addLongArray(LongArray array) {
929928 }
930929
931930 public void addNull () {
932- if (nullable ) {
933- ensureNullCapacity ( size + 1 );
931+ if (useNullBitmap ) {
932+ ensureNullBitmapCapacity ( );
934933 markNull (size );
935934 } else {
936935 // For non-nullable columns, store a sentinel/default value
@@ -978,18 +977,18 @@ public void addNull() {
978977 }
979978
980979 public void addShort (short value ) {
981- ensureNullBitmapForNonNull ();
980+ ensureNullBitmapCapacity ();
982981 dataBuffer .putShort (value );
983982 valueCount ++;
984983 size ++;
985984 }
986985
987986 public void addString (CharSequence value ) {
988- if (value == null && nullable ) {
989- ensureNullCapacity ( size + 1 );
987+ if (value == null && useNullBitmap ) {
988+ ensureNullBitmapCapacity ( );
990989 markNull (size );
991990 } else {
992- ensureNullBitmapForNonNull ();
991+ ensureNullBitmapCapacity ();
993992 if (value != null ) {
994993 stringData .putUtf8 (value );
995994 }
@@ -999,27 +998,12 @@ public void addString(CharSequence value) {
999998 size ++;
1000999 }
10011000
1002- public void addStringUtf8 (long ptr , int len ) {
1003- if (len < 0 && nullable ) {
1004- ensureNullCapacity (size + 1 );
1005- markNull (size );
1006- } else {
1007- ensureNullBitmapForNonNull ();
1008- if (len > 0 ) {
1009- stringData .putBlockOfBytes (ptr , len );
1010- }
1011- stringOffsets .putInt ((int ) stringData .getAppendOffset ());
1012- valueCount ++;
1013- }
1014- size ++;
1015- }
1016-
10171001 public void addSymbol (CharSequence value ) {
10181002 if (value == null ) {
10191003 addNull ();
10201004 return ;
10211005 }
1022- ensureNullBitmapForNonNull ();
1006+ ensureNullBitmapCapacity ();
10231007 int idx = getOrAddLocalSymbol (value );
10241008 dataBuffer .putInt (idx );
10251009 valueCount ++;
@@ -1031,7 +1015,7 @@ public void addSymbolUtf8(long ptr, int len) {
10311015 addNull ();
10321016 return ;
10331017 }
1034- ensureNullBitmapForNonNull ();
1018+ ensureNullBitmapCapacity ();
10351019 StringSink lookupSink = symbolLookupSink ;
10361020 if (lookupSink == null ) {
10371021 symbolLookupSink = lookupSink = new StringSink (Math .max (16 , len ));
@@ -1054,7 +1038,7 @@ public void addSymbolWithGlobalId(String value, int globalId) {
10541038 addNull ();
10551039 return ;
10561040 }
1057- ensureNullBitmapForNonNull ();
1041+ ensureNullBitmapCapacity ();
10581042 int localIdx = getOrAddLocalSymbol (value );
10591043 dataBuffer .putInt (localIdx );
10601044
@@ -1072,7 +1056,7 @@ public void addSymbolWithGlobalId(String value, int globalId) {
10721056 }
10731057
10741058 public void addUuid (long high , long low ) {
1075- ensureNullBitmapForNonNull ();
1059+ ensureNullBitmapCapacity ();
10761060 // Store in wire order: lo first, hi second
10771061 dataBuffer .putLong (low );
10781062 dataBuffer .putLong (high );
@@ -1254,10 +1238,6 @@ public boolean isNull(int index) {
12541238 return (Unsafe .getUnsafe ().getLong (longAddr ) & (1L << bitIndex )) != 0 ;
12551239 }
12561240
1257- public boolean isNullable () {
1258- return nullable ;
1259- }
1260-
12611241 public void reset () {
12621242 size = 0 ;
12631243 valueCount = 0 ;
@@ -1324,7 +1304,7 @@ public void truncateTo(int newSize) {
13241304 }
13251305
13261306 int newValueCount = 0 ;
1327- if (nullable && nullBufPtr != 0 ) {
1307+ if (useNullBitmap && nullBufPtr != 0 ) {
13281308 for (int i = 0 ; i < newSize ; i ++) {
13291309 if (!isNull (i )) {
13301310 newValueCount ++;
@@ -1396,6 +1376,10 @@ public void truncateTo(int newSize) {
13961376 }
13971377 }
13981378
1379+ public boolean usesNullBitmap () {
1380+ return useNullBitmap ;
1381+ }
1382+
13991383 private static int checkedElementCount (long product ) {
14001384 if (product > Integer .MAX_VALUE ) {
14011385 throw new LineSenderException ("array too large: total element count exceeds int range" );
@@ -1570,8 +1554,8 @@ private void ensureArrayCapacity(int nDims, int dataElements) {
15701554 }
15711555
15721556 // Ensure null bitmap capacity
1573- if (nullable ) {
1574- ensureNullCapacity ( size + 1 );
1557+ if (useNullBitmap ) {
1558+ ensureNullBitmapCapacity ( );
15751559 }
15761560
15771561 // Ensure shape array capacity
@@ -1599,21 +1583,16 @@ private void ensureArrayCapacity(int nDims, int dataElements) {
15991583 }
16001584 }
16011585
1602- private void ensureNullBitmapForNonNull () {
1603- if (nullBufPtr != 0 ) {
1604- ensureNullCapacity (size + 1 );
1605- }
1606- }
1607-
1608- private void ensureNullCapacity (int rows ) {
1609- if (rows > nullBufCapRows ) {
1610- int newCapRows = Math .max (nullBufCapRows * 2 , ((rows + 63 ) >>> 6 ) << 6 );
1611- long newSizeBytes = (long ) newCapRows >>> 3 ;
1612- long oldSizeBytes = (long ) nullBufCapRows >>> 3 ;
1613- nullBufPtr = Unsafe .realloc (nullBufPtr , oldSizeBytes , newSizeBytes , MemoryTag .NATIVE_ILP_RSS );
1614- Vect .memset (nullBufPtr + oldSizeBytes , newSizeBytes - oldSizeBytes , 0 );
1615- nullBufCapRows = newCapRows ;
1586+ private void ensureNullBitmapCapacity () {
1587+ if (nullBufPtr == 0 || nullBufCapRows > size ) {
1588+ return ;
16161589 }
1590+ int newCapRows = Math .max (nullBufCapRows * 2 , ((size + 64 ) >>> 6 ) << 6 );
1591+ long newSizeBytes = (long ) newCapRows >>> 3 ;
1592+ long oldSizeBytes = (long ) nullBufCapRows >>> 3 ;
1593+ nullBufPtr = Unsafe .realloc (nullBufPtr , oldSizeBytes , newSizeBytes , MemoryTag .NATIVE_ILP_RSS );
1594+ Vect .memset (nullBufPtr + oldSizeBytes , newSizeBytes - oldSizeBytes , 0 );
1595+ nullBufCapRows = newCapRows ;
16171596 }
16181597
16191598 private int getOrAddLocalSymbol (CharSequence value ) {
0 commit comments