2929import io .questdb .client .cutlass .line .array .ArrayBufferAppender ;
3030import io .questdb .client .cutlass .line .array .DoubleArray ;
3131import io .questdb .client .cutlass .line .array .LongArray ;
32+ import io .questdb .client .cutlass .qwp .client .QwpWebSocketSender ;
3233import io .questdb .client .std .CharSequenceIntHashMap ;
3334import io .questdb .client .std .Chars ;
3435import io .questdb .client .std .Decimal128 ;
@@ -59,6 +60,7 @@ public class QwpTableBuffer implements QuietCloseable {
5960
6061 private final CharSequenceIntHashMap columnNameToIndex ;
6162 private final ObjList <ColumnBuffer > columns ;
63+ private final QwpWebSocketSender sender ;
6264 private final String tableName ;
6365 private QwpColumnDef [] cachedColumnDefs ;
6466 private int columnAccessCursor ; // tracks expected next column index
@@ -70,7 +72,18 @@ public class QwpTableBuffer implements QuietCloseable {
7072 private boolean schemaHashComputed ;
7173
7274 public QwpTableBuffer (String tableName ) {
75+ this (tableName , null );
76+ }
77+
78+ /**
79+ * Use this constructor overload to allow writing to a symbol column.
80+ * {@link ColumnBuffer#addSymbol(CharSequence)} needs the sender to
81+ * call {@link QwpWebSocketSender#getOrAddGlobalSymbol(String)}, registering
82+ * the symbol in the global dictionary shared with the server.
83+ */
84+ public QwpTableBuffer (String tableName , QwpWebSocketSender sender ) {
7385 this .tableName = tableName ;
86+ this .sender = sender ;
7487 this .columns = new ObjList <>();
7588 this .columnNameToIndex = new CharSequenceIntHashMap ();
7689 this .rowCount = 0 ;
@@ -322,6 +335,7 @@ private static void assertColumnType(CharSequence name, byte type, ColumnBuffer
322335
323336 private ColumnBuffer createColumn (CharSequence name , byte type , boolean nullable ) {
324337 ColumnBuffer col = new ColumnBuffer (Chars .toString (name ), type , nullable );
338+ col .sender = sender ;
325339 int index = columns .size ();
326340 col .index = index ;
327341 columns .add (col );
@@ -534,6 +548,7 @@ public static class ColumnBuffer implements QuietCloseable {
534548 private int nullBufCapRows ;
535549 // Off-heap null bitmap (bit-packed, 1 bit per row)
536550 private long nullBufPtr ;
551+ private QwpWebSocketSender sender ;
537552 private int size ; // Total row count (including nulls)
538553 private OffHeapAppendMemory stringData ;
539554 // Off-heap storage for string/varchar column data
@@ -1003,6 +1018,12 @@ public void addSymbol(CharSequence value) {
10031018 addNull ();
10041019 return ;
10051020 }
1021+ if (sender != null ) {
1022+ String symbolValue = value .toString ();
1023+ int globalId = sender .getOrAddGlobalSymbol (symbolValue );
1024+ addSymbolWithGlobalId (symbolValue , globalId );
1025+ return ;
1026+ }
10061027 ensureNullBitmapCapacity ();
10071028 int idx = getOrAddLocalSymbol (value );
10081029 dataBuffer .putInt (idx );
@@ -1015,7 +1036,6 @@ public void addSymbolUtf8(long ptr, int len) {
10151036 addNull ();
10161037 return ;
10171038 }
1018- ensureNullBitmapCapacity ();
10191039 StringSink lookupSink = symbolLookupSink ;
10201040 if (lookupSink == null ) {
10211041 symbolLookupSink = lookupSink = new StringSink (Math .max (16 , len ));
@@ -1027,6 +1047,13 @@ public void addSymbolUtf8(long ptr, int len) {
10271047 Utf8s .stringFromUtf8Bytes (ptr , ptr + len );
10281048 throw new AssertionError ("unreachable" );
10291049 }
1050+ if (sender != null ) {
1051+ String symbolValue = lookupSink .toString ();
1052+ int globalId = sender .getOrAddGlobalSymbol (symbolValue );
1053+ addSymbolWithGlobalId (symbolValue , globalId );
1054+ return ;
1055+ }
1056+ ensureNullBitmapCapacity ();
10301057 int idx = getOrAddLocalSymbol (lookupSink );
10311058 dataBuffer .putInt (idx );
10321059 valueCount ++;
0 commit comments