Skip to content

7.1.0

Latest

Choose a tag to compare

@mtopolnik mtopolnik released this 19 Oct 13:51
· 1 commit to main since this release
6daaea4

Overview

7.1.0 adds native decimal and double-array column APIs and a non-blocking
completion poll, and fixes several QWP/WebSocket correctness and performance
issues. It also changes how UUID bytes and Arrow FixedSizeBinary columns are
interpreted: read "Breaking changes" before upgrading if you send or read
UUIDs as raw bytes or ingest Arrow, Polars, or NumPy data.

The C and C++ clients are distributed as source. No pre-built native binaries
are attached; use the tag's source archive.

Compatibility

  • QWP over WebSocket requires QuestDB 10.0 or newer. HTTP Basic auth and
    single-endpoint reconnect work with Open Source and Enterprise; bearer-token
    and OIDC auth, multi-host failover, and durable acknowledgement require
    QuestDB Enterprise.
  • Rust MSRV is 1.91.0, relaxed from 1.91.1 (#211).
  • The published questdb-rs crate supports Arrow >=58, <60 and Polars
    >=0.52, <0.55. The native (FFI) library pins Arrow =59.0.0 (#195).

See doc/COMPATIBILITY.md
for the full matrix.

Breaking changes

  • UUID byte order (#186). Raw UUID bytes are now in standard RFC-4122
    order, matching Python's uuid.bytes and Rust's Uuid::as_bytes(). This
    affects column_uuid() with a byte array, NumPy S16 (qwp_numpy_s16),
    bind_uuid, Arrow UUID columns, and every reader getter. Code that swapped
    bytes to match the previous order must stop doing so. The lo/hi integer
    UUID API is unchanged.
  • Arrow FixedSizeBinary columns ingest as BINARY unless tagged (#186).
    A UUID column needs the arrow.uuid or questdb.column_type=uuid field tag
    (16 bytes), or ArrowColumnOverride::Uuid at flush time; LONG256 needs
    questdb.column_type=long256 (32 bytes) or ArrowColumnOverride::Long256.
    A tag whose width doesn't match the column is an error.
  • Invalid Arrow column metadata is an error rather than being ignored
    (#186).
  • Arrow field metadata is capped at 64 MiB per batch through the C, C++,
    and Python APIs (#195). Larger batches are rejected and nothing is sent.
    Polars Enum columns with millions of categories should be cast to
    pl.Categorical. Rust flush_polars_dataframe is not affected.
  • A failed columnar batch can publish a prefix (#219). A batch of up to
    eight rows that contains an oversized row, other than the first, now sends
    the rows before it instead of being rejected whole. A store-and-forward
    sender commits those rows and reports the error as in doubt; a direct sender
    closes its connection, discarding its other uncommitted chunks, so the
    following commit fails with FailoverRetry. Check Error::in_doubt() before
    retrying the whole input.

New

  • Native Chunk column APIs for Decimal64, Decimal128, Decimal256, and
    fixed-shape DOUBLE arrays, in Rust, C, and C++ (#206). Buffers are borrowed
    through flush, with validation of scales, shapes, lengths, and validity
    bitmaps.
  • Sender::completed_fsn(AckLevel): a non-blocking poll of the completion
    watermark, the polling counterpart to Sender::wait (#190).
  • QWP row buffers accept symbols after other columns (#203), over both UDP and
    WebSocket. ILP still requires symbols before fields.
  • Polars Object columns fail with a clear error instead of ingesting
    meaningless bytes (#186).

Fixes

  • Columnar batches whose rows each fit max_buf_size are no longer rejected;
    splitting continues down to single rows (#219).
  • Error::in_doubt() on a failed QuestDb::flush_polars_dataframe() covers
    the whole DataFrame (#195): if any earlier batch was published, replaying the
    DataFrame could duplicate that prefix.
  • Byte-aligned GEOHASH maximum values are no longer encoded as NULL (#195).
  • Arrow C Data Interface inputs are validated before import: schema/array
    agreement, child counts, buffer layouts, offsets, and slice lengths (#195).
    On failure, inspect array->release to determine ownership; the error code
    alone does not.
  • Closing a connection pool (questdb_db_close) could block forever on a
    lost wakeup in the rejection-event dispatcher (#189).
  • In store-and-forward memory mode, a split chunk commits once at its last
    frame instead of once per frame, with a bounded deferred window (#178). The
    memory-mode default store-and-forward budget is at least five segments.
  • Buffer::bookmark() on a QWP/WebSocket buffer records lengths instead of
    cloning the buffered data, so bookmarking per row is no longer quadratic
    (#191).
  • QwpWsSizeHint::len() reuses its scratch allocation (#190).

Other changes

  • The InvalidApiCall message returned by wait for AckLevel::Durable
    without request_durable_ack=on has new text (#190). The error code is
    unchanged.

Full changelog: 7.0.0...7.1.0