EV-ClickHouse

 view release on metacpan or  search on metacpan

README.md  view on Meta::CPAN


- 7. Inspect via `dump_state` and `pending_queries`

    When a connection seems stuck, `$ch->dump_state` returns a
    hashref snapshot (fd state, send/recv buffer pos, callback depth,
    pending\_count, ...) and `$ch->pending_queries` lists the
    in-flight + queued entries with their query\_ids and age. Both are
    read-only debug accessors - safe to call from a signal-handler-style
    dump path.

- 8. Don't fight the freelist

    The XS layer keeps freelists for both cb\_queue and send\_queue entries,
    so allocating callbacks is essentially free after warm-up. The
    implication: avoid wrapping the connection in heavy wrappers that
    clone the connection per call - there is no per-call setup cost worth
    amortising away.

# ARCHITECTURE

The client is a single state machine driven by an [EV](https://metacpan.org/pod/EV) event loop. Each
connection holds: a TCP fd (non-blocking), a send buffer, a receive
buffer, a callback queue (next-in-line per protocol), and a pending
send queue (buffered before connect).

State transitions:

    Connect TCP --> [TLS handshake] --> [Native ServerHello]
        --> Connected --> { dispatch from send_queue;
                            parse response; deliver via cb_queue }

The connect\_timeout timer covers all three pre-Connected stages.
auto\_reconnect re-runs the chain via `schedule_reconnect`.

Two key invariants:

- Native protocol is strictly request/response. Only one query is
in-flight per connection at a time. `insert_streamer` serialises
batches against this constraint.
- `callback_depth` guards against `self` being freed mid-callback.
Every callback dispatch increments it; `check_destroyed` defers the
final `Safefree` until depth returns to zero.

For deeper detail (state-machine table, queue semantics) see `CLAUDE.md`
in the source distribution.

# TYPES

Per-column wire format and Perl-side gotchas. All numeric types
round-trip stable raw values by default; opt into string forms via
`decode_datetime`, `decode_decimal`, `decode_enum`.

- Integers

    Int8..Int64 / UInt8..UInt64: native Perl IV/UV. Int128/UInt128/Int256/UInt256
    return decimal string representations on platforms with `__int128` (Int128/UInt128)
    or always for the 256-bit forms.

- Floats

    Float32/Float64 round-trip exactly within IEEE-754 limits. `NaN`/`+Inf`/
    `-Inf` are preserved.

- BFloat16

    Top 16 bits of a Float32. Encoded by truncation; decoded by zero-extension.
    Suitable for ML feature columns; not for accounting.

- Decimal32/64/128

    Decoded as IV (raw integer) or NV (scaled to N decimal digits if
    `decode_decimal => 1`). Decimal128 over very long precision may lose
    trailing digits in the NV form; pass `decode_decimal => 0` and divide
    yourself with [Math::BigInt](https://metacpan.org/pod/Math%3A%3ABigInt) for exact arithmetic.

- Decimal256

    Returns raw 32 LE bytes. Decode with [Math::BigInt](https://metacpan.org/pod/Math%3A%3ABigInt) (see
    `eg/decimal_bigmath.pl`).

- Date / Date32 / DateTime / DateTime64

    Default: integer (days since epoch / Unix seconds). With `decode_datetime`:
    `YYYY-MM-DD` or `YYYY-MM-DD HH:MM:SS` or `YYYY-MM-DD HH:MM:SS.ffffff`.
    DateTime carries a timezone string; the formatted output uses it.

- Bool

    Decoded as 0/1. Encoded from any truthy/falsy SV. ClickHouse stores
    internally as UInt8 0/1.

- String / FixedString

    Bytes-in, bytes-out. No UTF-8 transformation.

- UUID

    Canonical hex form `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`. Encode
    accepts the same.

- IPv4 / IPv6

    Dotted-quad / canonical IPv6 strings.

- Enum8 / Enum16

    Default: integer code. With `decode_enum => 1`: label string.

- Nullable(T)

    `undef` in Perl maps to null; otherwise the inner type's encoding.

- Array(T)

    Perl arrayref of inner-type values.

- Tuple(T1, T2, ...)

    Perl arrayref ordered as the type declaration. Named tuples
    (`Tuple(a Int32, b String)`) are still arrayref-positional;
    parse the name from `column_types` if you need it.



( run in 0.840 second using v1.01-cache-2.11-cpan-9581c071862 )