Skip to content

Commit 44e31b7

Browse files
committed
Let QwpTableBuffer handle addSymbol fully
This required injecting the Sender into QwpTableBuffer, so it can add a symbol to the global symbol table
1 parent 749a53f commit 44e31b7

2 files changed

Lines changed: 46 additions & 15 deletions

File tree

core/src/main/java/io/questdb/client/cutlass/qwp/client/QwpWebSocketSender.java

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import io.questdb.client.std.ObjList;
4343
import io.questdb.client.std.bytes.DirectByteSlice;
4444
import org.jetbrains.annotations.NotNull;
45+
import org.jetbrains.annotations.TestOnly;
4546
import org.slf4j.Logger;
4647
import org.slf4j.LoggerFactory;
4748

@@ -696,6 +697,21 @@ public int getMaxSentSymbolId() {
696697
return maxSentSymbolId;
697698
}
698699

700+
/**
701+
* Registers a symbol value in the global dictionary and returns its global ID.
702+
* Called from {@link QwpTableBuffer.ColumnBuffer#addSymbol(CharSequence)}.
703+
*
704+
* @param symbol the symbol value to register
705+
* @return the global symbol ID
706+
*/
707+
public int getOrAddGlobalSymbol(String symbol) {
708+
int globalId = globalSymbolDictionary.getOrAddSymbol(symbol);
709+
if (globalId > currentBatchMaxSymbolId) {
710+
currentBatchMaxSymbolId = globalId;
711+
}
712+
return globalId;
713+
}
714+
699715
/**
700716
* Returns the number of pending rows not yet flushed.
701717
* For testing.
@@ -861,19 +877,7 @@ public QwpWebSocketSender symbol(CharSequence columnName, CharSequence value) {
861877
checkNotClosed();
862878
checkTableSelected();
863879
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(checkedColumnName(columnName), TYPE_SYMBOL, true);
864-
865-
if (value != null) {
866-
// Register symbol in global dictionary and track max ID for delta calculation
867-
String symbolValue = value.toString();
868-
int globalId = globalSymbolDictionary.getOrAddSymbol(symbolValue);
869-
if (globalId > currentBatchMaxSymbolId) {
870-
currentBatchMaxSymbolId = globalId;
871-
}
872-
// Store global ID in the column buffer
873-
col.addSymbolWithGlobalId(symbolValue, globalId);
874-
} else {
875-
col.addSymbol(null);
876-
}
880+
col.addSymbol(value);
877881
return this;
878882
}
879883

@@ -891,7 +895,7 @@ public QwpWebSocketSender table(CharSequence tableName) {
891895
currentTableName = tableName.toString();
892896
currentTableBuffer = tableBuffers.get(currentTableName);
893897
if (currentTableBuffer == null) {
894-
currentTableBuffer = new QwpTableBuffer(currentTableName);
898+
currentTableBuffer = new QwpTableBuffer(currentTableName, this);
895899
tableBuffers.put(currentTableName, currentTableBuffer);
896900
}
897901
// Both modes accumulate rows until flush

core/src/main/java/io/questdb/client/cutlass/qwp/protocol/QwpTableBuffer.java

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import io.questdb.client.cutlass.line.array.ArrayBufferAppender;
3030
import io.questdb.client.cutlass.line.array.DoubleArray;
3131
import io.questdb.client.cutlass.line.array.LongArray;
32+
import io.questdb.client.cutlass.qwp.client.QwpWebSocketSender;
3233
import io.questdb.client.std.CharSequenceIntHashMap;
3334
import io.questdb.client.std.Chars;
3435
import 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

Comments
 (0)