Summary
Sender has no dateColumn() setter, so a Java producer cannot write a DATE column — even though the server accepts DATE on QWP ingress and this client reads it back fine on egress.
Current status: documented as a limitation
The client documentation already concedes it — documentation/connect/clients/java.md:532:
DATE is accepted on ingress server-side but the Java client does not yet expose a dateColumn() setter. All types are readable on the egress side.
Cross-client parity
DATE is the only type missing from Java's row-oriented ingestion API, and Java is the only QWP client missing DATE:
| Type |
Rust Buffer |
C/C++ line_sender_buffer |
.NET |
Java Sender |
Go QwpSender |
Python row() |
UUID |
✅ |
✅ |
✅ |
✅ |
✅ |
❌ |
GEOHASH |
✅ |
✅ |
✅ |
✅ |
✅ |
❌ |
LONG256 |
✅ |
✅ |
✅ |
✅ |
✅ |
❌ |
CHAR |
✅ |
✅ |
✅ |
✅ |
✅ |
❌ |
IPv4 |
✅ |
✅ |
✅ |
✅ |
❌ |
❌ |
BINARY |
✅ |
✅ |
✅ |
✅ |
❌ |
❌ |
DATE |
✅ |
✅ |
✅ |
❌ |
✅ |
❌ |
Sibling implementations, all taking milliseconds since epoch:
- Rust —
column_date(name, millis: i64) and column_date_opt (questdb-rs/src/ingress/buffer.rs:1393, :1418)
- C —
line_sender_buffer_column_date (include/questdb/ingress/line_sender.h:1086)
- Go —
DateColumn(name string, val time.Time) QwpSender (qwp_sender.go:61)
- .NET —
ColumnDate(name, long millisSinceEpoch)
Suggested shape
Matching the existing setter conventions on Sender (byteColumn, charColumn, timestampColumn, ipv4Column, …):
Sender dateColumn(CharSequence name, long millisSinceEpoch);
Sender dateColumn(CharSequence name, Instant value);
The long overload mirrors the other clients' wire-level form; the Instant overload matches how timestampColumn(name, Instant) already reads at the call site. As with every other column, a null is written by omitting the setter before at() / atNow().
Worth confirming the intended truncation behaviour for the Instant overload, since DATE is millisecond-resolution and Instant is not — silently truncating sub-millisecond precision versus rejecting it is a deliberate choice, and the other clients sidestep it by only accepting millis (except Go, which takes a time.Time).
Summary
Senderhas nodateColumn()setter, so a Java producer cannot write aDATEcolumn — even though the server acceptsDATEon QWP ingress and this client reads it back fine on egress.Current status: documented as a limitation
The client documentation already concedes it —
documentation/connect/clients/java.md:532:Cross-client parity
DATEis the only type missing from Java's row-oriented ingestion API, and Java is the only QWP client missingDATE:Bufferline_sender_bufferSenderQwpSenderrow()UUIDGEOHASHLONG256CHARIPv4BINARYDATESibling implementations, all taking milliseconds since epoch:
column_date(name, millis: i64)andcolumn_date_opt(questdb-rs/src/ingress/buffer.rs:1393,:1418)line_sender_buffer_column_date(include/questdb/ingress/line_sender.h:1086)DateColumn(name string, val time.Time) QwpSender(qwp_sender.go:61)ColumnDate(name, long millisSinceEpoch)Suggested shape
Matching the existing setter conventions on
Sender(byteColumn,charColumn,timestampColumn,ipv4Column, …):The
longoverload mirrors the other clients' wire-level form; theInstantoverload matches howtimestampColumn(name, Instant)already reads at the call site. As with every other column, a null is written by omitting the setter beforeat()/atNow().Worth confirming the intended truncation behaviour for the
Instantoverload, sinceDATEis millisecond-resolution andInstantis not — silently truncating sub-millisecond precision versus rejecting it is a deliberate choice, and the other clients sidestep it by only accepting millis (except Go, which takes atime.Time).