NAME

DBIO::ClickHouse::Result - ClickHouse-specific Result component for DBIO

VERSION

version 0.900004

DESCRIPTION

DBIO::ClickHouse::Result is a DBIO Result component that adds the ClickHouse-native table metadata a CREATE TABLE cannot do without: the table engine and the MergeTree sorting key, plus the optional partition key, primary key and engine settings. It is the counterpart to DBIO::MySQL::Result / DBIO::PostgreSQL::Result and is read by DBIO::ClickHouse::DDL when generating install DDL.

Load it with:

package MyApp::DB::Result::Event;
use base 'DBIO::Core';
__PACKAGE__->load_components('ClickHouse::Result');

__PACKAGE__->table('events');
__PACKAGE__->add_columns(
  id   => { data_type => 'uuid',     is_auto_increment => 1 },
  ts   => { data_type => 'datetime', is_nullable => 0 },
  name => { data_type => 'varchar',  is_nullable => 0,
            extra => { low_cardinality => 1 } },
);
__PACKAGE__->set_primary_key('id');

__PACKAGE__->clickhouse_table({
  engine       => 'ReplacingMergeTree(ts)',
  order_by     => ['ts', 'id'],
  partition_by => 'toYYYYMM(ts)',
  settings     => { index_granularity => 8192 },
});

Why a Result component

The alternatives were a table_class override and a bare class accessor on the result class. A Result component is what the rest of the family already uses for driver-native table metadata (mysql_engine, pg_schema, sqlite_index), it is opt-in per result class, and it keeps the DDL layer's contract to a single duck-typed method call. DBIO::ClickHouse::DDL reads the options through $result_class->can('clickhouse_table'), so a schema that never loads this component is not broken by its absence -- every table simply gets the default ENGINE = MergeTree with ORDER BY = primary key.

METHODS

clickhouse_table

__PACKAGE__->clickhouse_table({
  engine       => 'MergeTree',
  order_by     => ['ts', 'id'],
  primary_key  => ['ts'],
  partition_by => 'toYYYYMM(ts)',
  settings     => { index_granularity => 8192 }
});

my $opts = $class->clickhouse_table;

Get or set this result class's ClickHouse table options. Returns a shallow copy of the stored options, or undef when none were declared. Recognised keys:

engine

The table engine, emitted verbatim after ENGINE = , so parameterized engines work ('ReplacingMergeTree(version)'). Defaults to MergeTree in the generated DDL when unset.

order_by

The MergeTree sorting key, as a column name or an arrayref of them. Entries are quoted as identifiers; pass a SCALAR ref for a raw expression (\'cityHash64(id)'). Defaults to the result class's primary key. An explicit empty arrayref renders ORDER BY tuple(), ClickHouse's spelling for "no sorting key".

Note that in ClickHouse the sorting key is the primary key -- there is no separate index structure, and no uniqueness is implied or enforced.

primary_key

Only needed when the primary key should be a strict prefix of order_by (a coarser index over a finer sort order). Same value shape as order_by. When omitted, ORDER BY alone defines the primary key, which is also how ClickHouse renders it back.

partition_by

A partition-key expression, emitted verbatim ('toYYYYMM(ts)'). It is not quoted as an identifier, because a partition key is nearly always a function call.

settings

Engine settings as a hashref. Names are emitted bare and sorted; numeric-looking values are emitted bare, SCALAR refs verbatim, everything else quoted.

TTL and SAMPLE BY are not modelled yet.

Invalid options are rejected at class-definition time through throw_exception, so a typo fails when the result class is compiled rather than when the DDL is deployed.

SEE ALSO

AUTHOR

DBIO Authors

COPYRIGHT AND LICENSE

Copyright (C) 2026 DBIO Authors

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.