EV-ClickHouse

 view release on metacpan or  search on metacpan

lib/EV/ClickHouse.pm  view on Meta::CPAN

croaks rather than silently produce malformed TSV; use the native
protocol or pre-serialise nested types into ClickHouse TSV literal form.

    # Native: nested types encode directly.
    $ch->insert("my_table", [
        [1, "hello\tworld"],   # embedded tab
        [2, undef],            # null
        [3, [10, 20]],         # Array column   (native only)
        [4, { a => 1, b => 2 }],  # Map column  (native only)
    ], sub { ... });

The optional C<\%settings> hashref works exactly as in L</query>,
including C<query_id>, C<query_timeout>, and C<params>. Two extra
flags are recognised here:

=over 4

=item C<idempotent =E<gt> 1 | $token>

Auto-mints (or uses the supplied) C<insert_deduplication_token>, so a
reconnect-driven retry of the same insert doesn't double-write. Falsy
values are a no-op.

=item C<async_insert =E<gt> 1>

Enables ClickHouse server-side insert batching by setting
C<async_insert=1, wait_for_async_insert=0>. Both sub-settings can be
overridden by passing them explicitly.

=back

=head2 ping

    $ch->ping(sub { my ($result, $err) = @_ });

Send a no-op round trip to verify the connection is alive. On success
C<$result> is true, C<$err> is C<undef>. On error: C<(undef, $error)>.

=head2 is_healthy

    $ch->is_healthy(sub { my ($ok, $err) = @_ });
    $ch->is_healthy(sub { ... }, $timeout_seconds);

Bounded health probe: wraps L</ping> with a deadline (default 5s). The
callback receives C<(1, undef)> on a successful round trip, or
C<(0, $msg)> on ping error or timeout. Failure does B<not> tear down the
connection; recovery (C<reset>, host rotation, etc.) is the caller's
choice. Useful for L4 load-balancer probes and self-monitoring loops.

=head2 ping_round_trip

    $ch->ping_round_trip(sub {
        my ($seconds, $err) = @_;
        die "ping: $err" if $err;
        printf "rtt = %.3fms\n", $seconds * 1000;
    });

Issue a single PING and report wall-clock latency in seconds. Lighter
than installing L</track_query_durations> for a one-shot probe;
returns C<(undef, $err)> on transport failure. Pairs well with
L</is_healthy> for health-check endpoints that want both liveness and
latency.

=head2 slow_query_log

    my $prev = $ch->slow_query_log(0.1, sub {
        my ($qid, $rows, $bytes, $code, $dur, $err) = @_;
        warn sprintf("SLOW %.3fs %s\n", $dur, $qid // '?');
    });

Filtered variant of L</on_query_complete> that fires only when the
query took at least C<$threshold> seconds. Returns the previous
C<on_query_complete> so the caller can restore it. The previous
handler is also chained on every call, so installing this on top of
existing instrumentation is safe.

=head2 server_setting

    $ch->server_setting('max_threads', sub {
        my ($value, $err) = @_;
        warn "max_threads = $value\n";
    });

Looks one value up from C<system.settings>. Convenient one-liner for
"what's the server's effective C<$x>?". Returns C<undef> via the
callback if the setting name isn't present on this server.

=head2 row_count

    $ch->row_count('events', sub { ... });
    $ch->row_count('events', "ts > now() - interval 1 hour", sub { ... });

C<select count() from $table [where $where]>. C<$where> is interpolated
literally; use parameterized predicates via the L</query> C<params>
mechanism for user-supplied filters. Returns the row count or
C<(undef, $err)>.

=head2 table_size

    $ch->table_size('events', sub {
        my ($info, $err) = @_;
        # $info = { rows => N, bytes_on_disk => N, data_uncompressed_bytes => N }
    });

Sums C<system.parts> for the (optionally database-qualified) table
and returns a hashref. Active parts only - does not count detached
parts. Suitable for ops dashboards; not authoritative for per-row
billing (parts may double-count rows during MERGE).

=head2 ddl

    $ch->ddl("create table t (n UInt32) engine=Memory", sub {
        my (undef, $err) = @_; die "ddl: $err" if $err;
    });

Strict variant of L</query> for DDL/DML. Identical wire behaviour;
the separate name is a readability marker for migration scripts so
the intent of each call is obvious at the call site.

=head2 dictionary_reload



( run in 0.575 second using v1.01-cache-2.11-cpan-524268b4103 )