Skip to content

Commit 96021be

Browse files
committed
Validate only new column names
1 parent 0053579 commit 96021be

2 files changed

Lines changed: 49 additions & 44 deletions

File tree

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

Lines changed: 31 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,9 @@ public class QwpWebSocketSender implements Sender {
9393
public static final int DEFAULT_AUTO_FLUSH_ROWS = 1_000;
9494
public static final int DEFAULT_IN_FLIGHT_WINDOW_SIZE = 128;
9595
private static final int DEFAULT_BUFFER_SIZE = 8192;
96-
private static final int DEFAULT_MAX_NAME_LENGTH = 127;
9796
private static final int DEFAULT_MICROBATCH_BUFFER_SIZE = 1024 * 1024; // 1MB
9897
private static final Logger LOG = LoggerFactory.getLogger(QwpWebSocketSender.class);
98+
private static final int MAX_TABLE_NAME_LENGTH = 127;
9999
private static final String WRITE_PATH = "/write/v4";
100100
private final AckFrameHandler ackHandler = new AckFrameHandler(this);
101101
private final WebSocketResponse ackResponse = new WebSocketResponse();
@@ -342,7 +342,7 @@ public void atNow() {
342342
public QwpWebSocketSender boolColumn(CharSequence columnName, boolean value) {
343343
checkNotClosed();
344344
checkTableSelected();
345-
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(checkedColumnName(columnName), TYPE_BOOLEAN, false);
345+
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(columnName, TYPE_BOOLEAN, false);
346346
if (col != null) {
347347
col.addBoolean(value);
348348
}
@@ -364,7 +364,7 @@ public DirectByteSlice bufferView() {
364364
public QwpWebSocketSender byteColumn(CharSequence columnName, byte value) {
365365
checkNotClosed();
366366
checkTableSelected();
367-
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(checkedColumnName(columnName), TYPE_BYTE, false);
367+
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(columnName, TYPE_BYTE, false);
368368
if (col != null) {
369369
col.addByte(value);
370370
}
@@ -391,7 +391,7 @@ public void cancelRow() {
391391
public QwpWebSocketSender charColumn(CharSequence columnName, char value) {
392392
checkNotClosed();
393393
checkTableSelected();
394-
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(checkedColumnName(columnName), TYPE_CHAR, false);
394+
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(columnName, TYPE_CHAR, false);
395395
if (col != null) {
396396
col.addShort((short) value);
397397
}
@@ -474,7 +474,7 @@ public Sender decimalColumn(CharSequence name, Decimal64 value) {
474474
if (value == null || value.isNull()) return this;
475475
checkNotClosed();
476476
checkTableSelected();
477-
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(checkedColumnName(name), TYPE_DECIMAL64, true);
477+
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(name, TYPE_DECIMAL64, true);
478478
if (col != null) {
479479
col.addDecimal64(value);
480480
}
@@ -486,7 +486,7 @@ public Sender decimalColumn(CharSequence name, Decimal128 value) {
486486
if (value == null || value.isNull()) return this;
487487
checkNotClosed();
488488
checkTableSelected();
489-
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(checkedColumnName(name), TYPE_DECIMAL128, true);
489+
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(name, TYPE_DECIMAL128, true);
490490
if (col != null) {
491491
col.addDecimal128(value);
492492
}
@@ -498,7 +498,7 @@ public Sender decimalColumn(CharSequence name, Decimal256 value) {
498498
if (value == null || value.isNull()) return this;
499499
checkNotClosed();
500500
checkTableSelected();
501-
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(checkedColumnName(name), TYPE_DECIMAL256, true);
501+
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(name, TYPE_DECIMAL256, true);
502502
if (col != null) {
503503
col.addDecimal256(value);
504504
}
@@ -512,7 +512,7 @@ public Sender decimalColumn(CharSequence name, CharSequence value) {
512512
checkTableSelected();
513513
try {
514514
currentDecimal256.ofString(value);
515-
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(checkedColumnName(name), TYPE_DECIMAL256, true);
515+
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(name, TYPE_DECIMAL256, true);
516516
if (col != null) {
517517
col.addDecimal256(currentDecimal256);
518518
}
@@ -527,7 +527,7 @@ public Sender doubleArray(@NotNull CharSequence name, double[] values) {
527527
if (values == null) return this;
528528
checkNotClosed();
529529
checkTableSelected();
530-
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(checkedColumnName(name), TYPE_DOUBLE_ARRAY, true);
530+
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(name, TYPE_DOUBLE_ARRAY, true);
531531
if (col != null) {
532532
col.addDoubleArray(values);
533533
}
@@ -539,7 +539,7 @@ public Sender doubleArray(@NotNull CharSequence name, double[][] values) {
539539
if (values == null) return this;
540540
checkNotClosed();
541541
checkTableSelected();
542-
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(checkedColumnName(name), TYPE_DOUBLE_ARRAY, true);
542+
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(name, TYPE_DOUBLE_ARRAY, true);
543543
if (col != null) {
544544
col.addDoubleArray(values);
545545
}
@@ -551,7 +551,7 @@ public Sender doubleArray(@NotNull CharSequence name, double[][][] values) {
551551
if (values == null) return this;
552552
checkNotClosed();
553553
checkTableSelected();
554-
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(checkedColumnName(name), TYPE_DOUBLE_ARRAY, true);
554+
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(name, TYPE_DOUBLE_ARRAY, true);
555555
if (col != null) {
556556
col.addDoubleArray(values);
557557
}
@@ -563,7 +563,7 @@ public Sender doubleArray(CharSequence name, DoubleArray array) {
563563
if (array == null) return this;
564564
checkNotClosed();
565565
checkTableSelected();
566-
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(checkedColumnName(name), TYPE_DOUBLE_ARRAY, true);
566+
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(name, TYPE_DOUBLE_ARRAY, true);
567567
if (col != null) {
568568
col.addDoubleArray(array);
569569
}
@@ -574,7 +574,7 @@ public Sender doubleArray(CharSequence name, DoubleArray array) {
574574
public QwpWebSocketSender doubleColumn(CharSequence columnName, double value) {
575575
checkNotClosed();
576576
checkTableSelected();
577-
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(checkedColumnName(columnName), TYPE_DOUBLE, true);
577+
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(columnName, TYPE_DOUBLE, true);
578578
if (col != null) {
579579
col.addDouble(value);
580580
}
@@ -591,7 +591,7 @@ public QwpWebSocketSender doubleColumn(CharSequence columnName, double value) {
591591
public QwpWebSocketSender floatColumn(CharSequence columnName, float value) {
592592
checkNotClosed();
593593
checkTableSelected();
594-
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(checkedColumnName(columnName), TYPE_FLOAT, true);
594+
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(columnName, TYPE_FLOAT, true);
595595
if (col != null) {
596596
col.addFloat(value);
597597
}
@@ -703,7 +703,7 @@ public QwpTableBuffer getTableBuffer(String tableName) {
703703
public QwpWebSocketSender intColumn(CharSequence columnName, int value) {
704704
checkNotClosed();
705705
checkTableSelected();
706-
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(checkedColumnName(columnName), TYPE_INT, true);
706+
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(columnName, TYPE_INT, true);
707707
if (col != null) {
708708
col.addInt(value);
709709
}
@@ -730,7 +730,7 @@ public boolean isGorillaEnabled() {
730730
public QwpWebSocketSender long256Column(CharSequence columnName, long l0, long l1, long l2, long l3) {
731731
checkNotClosed();
732732
checkTableSelected();
733-
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(checkedColumnName(columnName), TYPE_LONG256, true);
733+
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(columnName, TYPE_LONG256, true);
734734
if (col != null) {
735735
col.addLong256(l0, l1, l2, l3);
736736
}
@@ -742,7 +742,7 @@ public Sender longArray(@NotNull CharSequence name, long[] values) {
742742
if (values == null) return this;
743743
checkNotClosed();
744744
checkTableSelected();
745-
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(checkedColumnName(name), TYPE_LONG_ARRAY, true);
745+
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(name, TYPE_LONG_ARRAY, true);
746746
if (col != null) {
747747
col.addLongArray(values);
748748
}
@@ -754,7 +754,7 @@ public Sender longArray(@NotNull CharSequence name, long[][] values) {
754754
if (values == null) return this;
755755
checkNotClosed();
756756
checkTableSelected();
757-
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(checkedColumnName(name), TYPE_LONG_ARRAY, true);
757+
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(name, TYPE_LONG_ARRAY, true);
758758
if (col != null) {
759759
col.addLongArray(values);
760760
}
@@ -766,7 +766,7 @@ public Sender longArray(@NotNull CharSequence name, long[][][] values) {
766766
if (values == null) return this;
767767
checkNotClosed();
768768
checkTableSelected();
769-
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(checkedColumnName(name), TYPE_LONG_ARRAY, true);
769+
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(name, TYPE_LONG_ARRAY, true);
770770
if (col != null) {
771771
col.addLongArray(values);
772772
}
@@ -778,7 +778,7 @@ public Sender longArray(@NotNull CharSequence name, LongArray array) {
778778
if (array == null) return this;
779779
checkNotClosed();
780780
checkTableSelected();
781-
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(checkedColumnName(name), TYPE_LONG_ARRAY, true);
781+
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(name, TYPE_LONG_ARRAY, true);
782782
if (col != null) {
783783
col.addLongArray(array);
784784
}
@@ -789,7 +789,7 @@ public Sender longArray(@NotNull CharSequence name, LongArray array) {
789789
public QwpWebSocketSender longColumn(CharSequence columnName, long value) {
790790
checkNotClosed();
791791
checkTableSelected();
792-
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(checkedColumnName(columnName), TYPE_LONG, true);
792+
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(columnName, TYPE_LONG, true);
793793
if (col != null) {
794794
col.addLong(value);
795795
}
@@ -834,7 +834,7 @@ public void setGorillaEnabled(boolean enabled) {
834834
public QwpWebSocketSender shortColumn(CharSequence columnName, short value) {
835835
checkNotClosed();
836836
checkTableSelected();
837-
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(checkedColumnName(columnName), TYPE_SHORT, false);
837+
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(columnName, TYPE_SHORT, false);
838838
if (col != null) {
839839
col.addShort(value);
840840
}
@@ -845,7 +845,7 @@ public QwpWebSocketSender shortColumn(CharSequence columnName, short value) {
845845
public QwpWebSocketSender stringColumn(CharSequence columnName, CharSequence value) {
846846
checkNotClosed();
847847
checkTableSelected();
848-
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(checkedColumnName(columnName), TYPE_STRING, true);
848+
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(columnName, TYPE_STRING, true);
849849
if (col != null) {
850850
col.addString(value);
851851
}
@@ -856,7 +856,7 @@ public QwpWebSocketSender stringColumn(CharSequence columnName, CharSequence val
856856
public QwpWebSocketSender symbol(CharSequence columnName, CharSequence value) {
857857
checkNotClosed();
858858
checkTableSelected();
859-
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(checkedColumnName(columnName), TYPE_SYMBOL, true);
859+
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(columnName, TYPE_SYMBOL, true);
860860
if (col != null) {
861861
col.addSymbol(value);
862862
}
@@ -889,13 +889,13 @@ public QwpWebSocketSender timestampColumn(CharSequence columnName, long value, C
889889
checkNotClosed();
890890
checkTableSelected();
891891
if (unit == ChronoUnit.NANOS) {
892-
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(checkedColumnName(columnName), TYPE_TIMESTAMP_NANOS, true);
892+
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(columnName, TYPE_TIMESTAMP_NANOS, true);
893893
if (col != null) {
894894
col.addLong(value);
895895
}
896896
} else {
897897
long micros = toMicros(value, unit);
898-
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(checkedColumnName(columnName), TYPE_TIMESTAMP, true);
898+
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(columnName, TYPE_TIMESTAMP, true);
899899
if (col != null) {
900900
col.addLong(micros);
901901
}
@@ -908,7 +908,7 @@ public QwpWebSocketSender timestampColumn(CharSequence columnName, Instant value
908908
checkNotClosed();
909909
checkTableSelected();
910910
long micros = value.getEpochSecond() * 1_000_000L + value.getNano() / 1000L;
911-
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(checkedColumnName(columnName), TYPE_TIMESTAMP, true);
911+
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(columnName, TYPE_TIMESTAMP, true);
912912
if (col != null) {
913913
col.addLong(micros);
914914
}
@@ -926,7 +926,7 @@ public QwpWebSocketSender timestampColumn(CharSequence columnName, Instant value
926926
public QwpWebSocketSender uuidColumn(CharSequence columnName, long lo, long hi) {
927927
checkNotClosed();
928928
checkTableSelected();
929-
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(checkedColumnName(columnName), TYPE_UUID, true);
929+
QwpTableBuffer.ColumnBuffer col = currentTableBuffer.getOrCreateColumn(columnName, TYPE_UUID, true);
930930
if (col != null) {
931931
col.addUuid(hi, lo);
932932
}
@@ -965,19 +965,6 @@ private void checkTableSelected() {
965965
}
966966
}
967967

968-
private CharSequence checkedColumnName(CharSequence name) {
969-
if (name == null || !TableUtils.isValidColumnName(name, DEFAULT_MAX_NAME_LENGTH)) {
970-
if (name == null || name.length() == 0) {
971-
throw new LineSenderException("column name cannot be empty");
972-
}
973-
if (name.length() > DEFAULT_MAX_NAME_LENGTH) {
974-
throw new LineSenderException("column name too long [maxLength=" + DEFAULT_MAX_NAME_LENGTH + "]");
975-
}
976-
throw new LineSenderException("column name contains illegal characters: " + name);
977-
}
978-
return name;
979-
}
980-
981968
/**
982969
* Ensures the active buffer is ready for writing (in FILLING state).
983970
* If the buffer is in RECYCLED state, resets it. If it's in use, waits for it.
@@ -1365,12 +1352,12 @@ private long toMicros(long value, ChronoUnit unit) {
13651352
}
13661353

13671354
private void validateTableName(CharSequence name) {
1368-
if (name == null || !TableUtils.isValidTableName(name, DEFAULT_MAX_NAME_LENGTH)) {
1355+
if (name == null || !TableUtils.isValidTableName(name, MAX_TABLE_NAME_LENGTH)) {
13691356
if (name == null || name.length() == 0) {
13701357
throw new LineSenderException("table name cannot be empty");
13711358
}
1372-
if (name.length() > DEFAULT_MAX_NAME_LENGTH) {
1373-
throw new LineSenderException("table name too long [maxLength=" + DEFAULT_MAX_NAME_LENGTH + "]");
1359+
if (name.length() > MAX_TABLE_NAME_LENGTH) {
1360+
throw new LineSenderException("table name too long [maxLength=" + MAX_TABLE_NAME_LENGTH + "]");
13741361
}
13751362
throw new LineSenderException("table name contains illegal characters: " + name);
13761363
}

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
package io.questdb.client.cutlass.qwp.protocol;
2626

2727
import io.questdb.client.cairo.ColumnType;
28+
import io.questdb.client.cairo.TableUtils;
2829
import io.questdb.client.cutlass.line.LineSenderException;
2930
import io.questdb.client.cutlass.line.array.ArrayBufferAppender;
3031
import io.questdb.client.cutlass.line.array.DoubleArray;
@@ -59,6 +60,7 @@
5960
*/
6061
public class QwpTableBuffer implements QuietCloseable {
6162

63+
private static final int MAX_COLUMN_NAME_LENGTH = 127;
6264
private final LowerCaseAsciiCharSequenceIntHashMap columnNameToIndex;
6365
private final ObjList<ColumnBuffer> columns;
6466
private final QwpWebSocketSender sender;
@@ -343,6 +345,10 @@ private static void assertColumnType(CharSequence name, byte type, ColumnBuffer
343345
}
344346

345347
private ColumnBuffer createColumn(CharSequence name, byte type, boolean nullable) {
348+
// empty name is the designated timestamp sentinel — skip validation
349+
if (name.length() > 0) {
350+
validateColumnName(name);
351+
}
346352
ColumnBuffer col = new ColumnBuffer(Chars.toString(name), type, nullable);
347353
col.sender = sender;
348354
int index = columns.size();
@@ -415,6 +421,18 @@ private void rebuildColumnAccessStructures() {
415421
cachedColumnDefs = null;
416422
}
417423

424+
private static void validateColumnName(CharSequence name) {
425+
if (name == null || !TableUtils.isValidColumnName(name, MAX_COLUMN_NAME_LENGTH)) {
426+
if (name == null || name.length() == 0) {
427+
throw new LineSenderException("column name cannot be empty");
428+
}
429+
if (name.length() > MAX_COLUMN_NAME_LENGTH) {
430+
throw new LineSenderException("column name too long [maxLength=" + MAX_COLUMN_NAME_LENGTH + "]");
431+
}
432+
throw new LineSenderException("column name contains illegal characters: " + name);
433+
}
434+
}
435+
418436
/**
419437
* Returns the in-memory buffer element stride in bytes. This is the size used
420438
* to store each value in the client's off-heap {@link OffHeapAppendMemory} buffer.

0 commit comments

Comments
 (0)