Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
126 commits
Select commit Hold shift + click to select a range
7ab41a1
Add QWP/UDP system test for f64 arrays
jerrinot Apr 14, 2026
ac5573d
test: add QWP/UDP e2e tests for timestamp, array, decimal, and string…
jerrinot Apr 14, 2026
0f65b5c
c client sub
jerrinot Apr 14, 2026
92bd99b
test: add QWP/UDP auto-flush, edge-case, and stress tests
jerrinot Apr 14, 2026
1550711
test: add QWP/UDP interval flush, datagram splitting, and more e2e tests
jerrinot Apr 14, 2026
bd6ba73
test: add QWP/UDP PyArrow decimal DataFrame e2e test
jerrinot Apr 14, 2026
48f6642
test: add QWP/UDP decimal edge-case tests
jerrinot Apr 14, 2026
0f9ec3c
test: add QWP/UDP QA edge-case tests
jerrinot Apr 14, 2026
f65a186
fix: correct f64_array test timestamp type assertion
jerrinot Apr 14, 2026
a139d18
docs: mention QWP/UDP in sender overview, tips, and protocol version
jerrinot Apr 15, 2026
fbf17de
docs: add dedicated QWP/UDP section with tradeoffs and gotchas
jerrinot Apr 15, 2026
4dc8144
Expose QWP WebSocket controls in Python
jerrinot May 4, 2026
e8eeb69
Expose QWP WebSocket rejection callbacks
jerrinot May 11, 2026
f3c22d9
Upgrade QWP FFI bindings
jerrinot May 25, 2026
34d2d88
Merge remote-tracking branch 'origin/main' into jh_experiment_new_ilp
jerrinot May 25, 2026
da27059
Add QWP system test coverage
jerrinot May 25, 2026
76f107f
Fix CI compatibility with current deps and QuestDB master
jerrinot May 26, 2026
b6c8b50
fix: reject bool sender duration options
jerrinot May 26, 2026
988fae5
Pin c-questdb-client column sender branch
jerrinot May 26, 2026
735aa96
Add Client.dataframe() pooled columnar ingest path
jerrinot May 27, 2026
39c8f51
Extend Client.dataframe() fuzz coverage
jerrinot May 27, 2026
9854f5e
Step 1: bind Client to qwpws_conn FFI rename
jerrinot May 27, 2026
66ba477
Step 2a: bind column_sender_chunk_append_arrow_column in Cython
jerrinot May 27, 2026
8c04c63
Step 2b: bump submodule for LargeUtf8 support
jerrinot May 27, 2026
ff0c909
Step 2c: route Arrow-backed columns through the new appender
jerrinot May 27, 2026
a02c280
Self-review fixes: plan doc + submodule bump
jerrinot May 27, 2026
0d3b1d5
Step 4-A: support str_pyobj (object-dtype string columns)
jerrinot May 27, 2026
e43783e
Step 4-BCD: support int/float/bool PyObject column sources
jerrinot May 27, 2026
10dba21
Review fixes: pyobj null-alignment + prebuilt NULL guards
jerrinot May 27, 2026
d420d79
Step 3: route narrow NumPy dtypes through column_numpy
jerrinot May 27, 2026
64cb920
Round-3 must_close fix: drop conn on mid-call error
jerrinot May 27, 2026
860c105
Plan doc completion + NaN-as-null docs
jerrinot May 27, 2026
392e05f
Pin c-questdb-client merge of arrow_polars (PR #150)
jerrinot May 28, 2026
89a2f43
Egress: Client.query() → pandas / pyarrow
jerrinot May 28, 2026
653caea
Egress cleanup: numpy_nullable, dead code, error mapping, docs
jerrinot May 28, 2026
9db3325
Egress null contract: tests + plan-doc precision
jerrinot May 28, 2026
e0fece8
Columnar v1 ingress: accept tz-aware timestamps
jerrinot May 28, 2026
fc5a027
update FFI sub
jerrinot May 28, 2026
ca106c4
Wire `Client.query` through the `questdb_db` reader pool
jerrinot May 28, 2026
8ed4d5d
dataframe ingress/egress comparison doc
jerrinot May 28, 2026
676d82d
Column-QWP narrow Arrow primitive dispatch (i8/i16/i32/f32)
jerrinot May 29, 2026
9c1e334
Refactor: path-parameterized _FIELD_TARGETS
jerrinot May 29, 2026
5cd5cc6
Column-QWP UUID dispatch (FSB(16) + arrow.uuid extension)
jerrinot May 29, 2026
ab7d952
Column-QWP IPV4 + LONG256 dispatch (GEOHASH deferred)
jerrinot May 29, 2026
f4aa5a1
Update c-questdb-client submodule
jerrinot Jun 1, 2026
23e6de1
Align Client.dataframe UInt32 Arrow policy
jerrinot Jun 1, 2026
a277ee5
Support Arrow wide numerics in Client.dataframe
jerrinot Jun 1, 2026
04d4090
Fix Python Arrow error code enum drift
jerrinot Jun 1, 2026
be13d6b
Preserve Arrow LargeUtf8 in dataframe planner
jerrinot Jun 1, 2026
4f424a7
Prototype Rust Arrow dataframe append path
jerrinot Jun 1, 2026
ce2b92e
Add dataframe payload round-trip coverage
jerrinot Jun 1, 2026
21f7d2e
Preserve LargeUtf8 categorical dataframe symbols
jerrinot Jun 1, 2026
2a63fc7
Refresh Client.dataframe findings
jerrinot Jun 1, 2026
31fa8c8
Route Client.dataframe through Rust Arrow path
jerrinot Jun 1, 2026
0df71ea
Reuse Arrow dataframe buffers across chunks
jerrinot Jun 1, 2026
ae5c8af
Route explicit dataframe symbols through Arrow
jerrinot Jun 3, 2026
a7ae730
Pin dataframe UInt64 semantics with real e2e
jerrinot Jun 3, 2026
ed64570
Fix no-pandas CI tests
jerrinot Jun 3, 2026
4e91a5f
Test QWP against QuestDB 9.4.1
jerrinot Jun 3, 2026
350cdc0
use java 25
jerrinot Jun 3, 2026
5b997a3
Fix dataframe auto-flush flag initialization
jerrinot Jun 3, 2026
93e2e29
use new c abi for arrow and numpy column
kafka1991 Jun 5, 2026
b32aa2f
Implement reusable Arrow dataframe imports
jerrinot Jun 5, 2026
4bd3a75
Route Arrow-backed pandas dataframes through Arrow ingestion
jerrinot Jun 5, 2026
a35f967
update c-abi
kafka1991 Jun 8, 2026
bc3d6dc
remove unused code
kafka1991 Jun 8, 2026
fff5c3c
update c module and fix tests on win32
kafka1991 Jun 8, 2026
80093d5
update c module and doc string
kafka1991 Jun 8, 2026
f6a1a24
update c api and code review
kafka1991 Jun 8, 2026
6aeb1ee
update c abi
kafka1991 Jun 8, 2026
079295e
update c module
kafka1991 Jun 15, 2026
5b7a268
fix compile issue
kafka1991 Jun 15, 2026
1564fd9
update c module
kafka1991 Jun 15, 2026
0b2eb96
update c module
kafka1991 Jun 15, 2026
7565680
add review skills
kafka1991 Jun 15, 2026
4675fde
code review 1
kafka1991 Jun 15, 2026
f30c0ad
code review 1
kafka1991 Jun 15, 2026
0b6ab20
code review and fix wip
kafka1991 Jun 15, 2026
129bcb3
update c module
kafka1991 Jun 16, 2026
93181a4
system test use new server release
kafka1991 Jun 16, 2026
ff78d2f
fix test and update c module
kafka1991 Jun 16, 2026
8d56064
fix one bug and update c-module
kafka1991 Jun 16, 2026
f970e62
update one c-module
kafka1991 Jun 16, 2026
d439229
remove dependency of pyarrow
kafka1991 Jun 16, 2026
a7f1eff
add pyarrow as a dependecny with install dataframe
kafka1991 Jun 16, 2026
85a7e54
add pyarrow as a dependecny with install dataframe
kafka1991 Jun 16, 2026
c598d05
update c submodule and fix one failed test
kafka1991 Jun 17, 2026
603d760
add more polars test
kafka1991 Jun 17, 2026
a74673d
add more test
kafka1991 Jun 17, 2026
cdac606
add more test
kafka1991 Jun 17, 2026
67d42b9
fix one system test
kafka1991 Jun 17, 2026
f7bc2c4
fix compile master in ci
kafka1991 Jun 17, 2026
c7f98da
better performance for egress to_pandas numpy
kafka1991 Jun 17, 2026
d62149f
fix serval failed tests
kafka1991 Jun 17, 2026
c1afdb8
update c module
kafka1991 Jun 17, 2026
379f87e
close conn when reject a frame
kafka1991 Jun 17, 2026
36894e3
fix schema override
kafka1991 Jun 18, 2026
dc4a8bb
fix pandas ingress path
kafka1991 Jun 18, 2026
409d135
fix arrow timestamp support mills and seconds
kafka1991 Jun 18, 2026
c03b525
init commit of failover
kafka1991 Jun 18, 2026
15994a4
update ffi sub
jerrinot Jun 18, 2026
05ca9b3
refactor failover
kafka1991 Jun 18, 2026
c0895cd
fix(egress): align failover retry budget
jerrinot Jun 18, 2026
9b26f22
feat(egress): distinguish role-mismatch failover from transport failures
jerrinot Jun 18, 2026
4e2f082
chore(submodule): bump c-questdb-client to merge origin/main
jerrinot Jun 18, 2026
f31200f
docs: add dataframe egress examples
jerrinot Jun 18, 2026
652e27c
Pin c client submodule
jerrinot Jun 18, 2026
c13ba57
Update c-questdb-client failover diagnostics
jerrinot Jun 18, 2026
54c0f2e
Align egress decode failover policy
jerrinot Jun 18, 2026
dab3613
update ffi sub
jerrinot Jun 19, 2026
83441b0
Pin column sender store-and-forward
jerrinot Jun 19, 2026
2568825
Add dataframe SFA test coverage
jerrinot Jun 19, 2026
cc21b66
Update column sender SFA test coverage
jerrinot Jun 19, 2026
54a53f7
update c module and update c
kafka1991 Jun 22, 2026
002563b
better egress to_polars performance
kafka1991 Jun 22, 2026
1a30880
Pin c-questdb-client submodule
jerrinot Jun 22, 2026
65ca92f
Update Cython bindings for new column_sender FFI ABI
jerrinot Jun 22, 2026
9ab8b48
QWP DataFrame benchmarks: pandas ingress + egress (#135)
jovfer Jun 22, 2026
d924409
update c-module
kafka1991 Jun 22, 2026
ffe244c
bench(egress): add Arrow-backed/nullable to_pandas paths + ascii/unic…
jovfer Jun 22, 2026
2353f9c
bench(s2): add S2-wide schema (Go qwp-egress-read-wide anchor) + knobs
jovfer Jun 22, 2026
0f82454
fix(egress): cache CategoricalDtype in the per-batch numpy iterator
jovfer Jun 22, 2026
b610640
enhance egress to dataframe perf
kafka1991 Jun 23, 2026
ae6fee7
egress to pandas perf enhancement part1
kafka1991 Jun 23, 2026
ed22a2f
fix one segmentFault
kafka1991 Jun 23, 2026
f760358
use last's chunk's dicts
kafka1991 Jun 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
377 changes: 377 additions & 0 deletions .claude/skills/review-pr/SKILL.md

Large diffs are not rendered by default.

117 changes: 117 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,123 @@ Changelog

=========

Unreleased
----------

Features
~~~~~~~~

QWP Ingestion Protocol
**********************

Adds support for the QuestDB Wire Protocol (QWP) alongside the existing
ILP transports.

- **QWP/UDP** (``qwpudp::``): fire-and-forget datagram ingestion,
defaulting to port 9007. New configuration keys ``max_datagram_size``
and ``multicast_ttl``; ``protocol_version`` does not apply.
- **QWP/WebSocket** (``qwpws::`` / ``qwpwss::``): acknowledged streaming
ingestion with frame-sequence-number (FSN) tracking. New ``Sender``
methods ``flush_and_get_fsn``, ``flush_and_keep_and_get_fsn``,
``published_fsn``, ``acked_fsn``, ``await_acked_fsn``, ``drive_once``,
``poll_qwp_ws_error``, ``qwp_ws_errors_dropped`` and ``close_drain``.
Server diagnostics are reported through a ``qwp_ws_error_handler``
callback or polled as :class:`QwpWsError` values; terminal server
rejections raise :class:`IngressServerRejectionError`.

Additional configuration keys ``tls_roots_password``,
``retry_max_backoff_millis`` and ``qwp_ws_progress`` are also accepted.
Every new key is equally available as a ``Sender`` / ``Sender.from_conf`` /
``Sender.from_env`` keyword argument (``max_datagram_size``,
``multicast_ttl``, ``tls_roots_password``, ``retry_max_backoff``,
``qwp_ws_progress`` and ``qwp_ws_error_handler``).

Buffer Factories
****************

``Buffer.ilp()`` and ``Buffer.qwp()`` construct protocol-specific
buffers. Direct ``Buffer(...)`` construction is deprecated in favour of
these factories and ``Sender.new_buffer()``.

Query Egress
************

Adds :class:`Client` with :meth:`Client.query`, returning a
:class:`QueryResult` that streams rows as Arrow record batches over the
QWP/WebSocket read endpoint. Results can be consumed via ``to_arrow``,
``to_pandas``, ``to_polars``, ``iter_arrow``, ``iter_pandas``,
``iter_polars`` or the Arrow C stream PyCapsule protocol
(``__arrow_c_stream__``). ``to_polars`` / ``iter_polars`` use pyarrow to
buffer failover-safe batches; ``__arrow_c_stream__`` (consumed as
``polars.from_arrow(result)``) is the pyarrow-free polars path. SYMBOL
columns are dictionary-encoded on the wire and map to a pandas
``Categorical`` (``to_pandas`` / ``iter_pandas``) or a polars
``Categorical`` (``to_polars`` / ``iter_polars``), the latter sharing one
persistent ``Categories`` identity across streamed batches so
``polars.concat`` stitches them without a categories-mismatch error.

``to_pandas`` / ``iter_pandas`` default to a native (no-pyarrow) build
straight from the QWP column buffers: a nullable integer column becomes a
pandas nullable ``Int*`` when it contains nulls and plain numpy otherwise,
``double`` stays numpy with ``NaN``, ``TIMESTAMP`` → ``datetime64``, and
the QuestDB column kinds are recorded in ``df.attrs['questdb']`` for a type
round-trip through :meth:`Client.dataframe`. Pass
``dtype_backend="pyarrow"`` / ``"numpy_nullable"`` (or ``types_mapper=``)
to select the pyarrow-backed conversion instead.

:class:`Client` is a context manager and exposes :meth:`Client.close` and
:meth:`Client.reap_idle` for pooled-connection lifecycle management.

Columnar DataFrame Ingestion
****************************

Adds :meth:`Client.dataframe`, ingesting pandas / polars / pyarrow and
any Arrow C Data Interface object over QWP/WebSocket. A
``schema_overrides`` keyword reclassifies columns as ``symbol``,
``ipv4``, ``char`` or ``geohash`` (e.g. ``{'addr': 'ipv4', 'loc':
('geohash', 20)}``).

The designated-timestamp argument ``at`` is the timestamp column itself,
given by name (``str``) or position (``int``); unlike
:meth:`Sender.dataframe` / :meth:`Buffer.dataframe` it does not accept a
scalar ``datetime`` / ``TimestampNanos`` / ``ServerTimestamp``. A frame
produced by :meth:`QueryResult.to_pandas` round-trips back to the same
QuestDB column types automatically: the kinds recorded in
``df.attrs['questdb']`` and pandas nullable extension dtypes are honoured.

Errors
******

Adds :class:`UnsupportedDataFrameShapeError` (raised when a DataFrame
cannot be expressed on the QWP columnar path) and the
:class:`IngressErrorCode` members ``ServerRejection``,
``ArrowUnsupportedColumnKind``, ``ArrowIngest`` and ``Cancelled``.
:class:`IngressError` gains a ``qwp_ws_error`` property exposing the
structured :class:`QwpWsError` view on a server-side QWP/WebSocket
rejection.

Build & dependencies
~~~~~~~~~~~~~~~~~~~~~~

- The minimum supported Python is raised from 3.8 to **3.10**; Python 3.8
and 3.9 are no longer supported.
- ``numpy>=1.21.0`` is now a hard runtime dependency (previously it was
pulled in only via the ``dataframe`` extra).
- **pyarrow is now optional.** It is imported lazily, only when actually
needed (``pd.ArrowDtype`` columns, pyarrow sources, ``schema_overrides``,
and the ``to_arrow`` / ``iter_arrow`` / ``dtype_backend`` helpers). The
``to_polars`` / ``__arrow_c_stream__`` egress paths and the default
``to_pandas`` / ``iter_pandas`` work without pyarrow.
- The ``dataframe`` extra now pins ``pandas>=1.3.5`` and
``pyarrow>=10.0.1``.

Deprecations
~~~~~~~~~~~~

- Direct ``Buffer(...)`` construction is deprecated and emits a
``DeprecationWarning``. Use ``Buffer.ilp()``, ``Buffer.qwp()`` or
``Sender.new_buffer()`` instead.

4.1.0 (2025-11-28)
------------------

Expand Down
Loading
Loading