clickhouse 0.1.1 copy "clickhouse: ^0.1.1" to clipboard
clickhouse: ^0.1.1 copied to clipboard

A fast, native Dart driver for ClickHouse over the TCP binary protocol — queries, batch inserts, connection pooling, LZ4 compression, and full column-type support.

clickhouse #

A native Dart driver for ClickHouse over the TCP binary protocol.

clickhouse is a pure-Dart client for querying ClickHouse, streaming result rows, batch inserting data, pooling connections, using LZ4 compression, and reading/writing ClickHouse column types without going through HTTP.

Features #

  • Native TCP protocol on port 9000
  • Queries, exec statements, async inserts, and external tables
  • Streaming Rows API with typed getters, scans, maps, and row records
  • Batch inserts with row-wise, named, map, struct, and columnar append APIs
  • Connection pooling with bounded open/idle connections and health checks
  • Per-query settings, query parameters, client-side binding, query IDs, quotas, and timeouts
  • LZ4/LZ4HC compression with pluggable codecs for additional methods
  • Progress, profile info, profile events, server logs, and structured errors
  • Broad ClickHouse type support, including arrays, maps, tuples, nullable, low-cardinality, decimals, dates/times, UUID, IPv4/IPv6, enums, JSON, Dynamic, Variant, intervals, and geo types

Installation #

Add the package to your pubspec.yaml:

dependencies:
  clickhouse: ^0.1.0

Then run:

dart pub get

Quick Start #

import 'package:clickhouse/clickhouse.dart';

Future<void> main() async {
  final conn = await ClickHouseConnection.connect(const ClickHouseOptions(
    host: 'localhost',
    port: 9000,
    database: 'default',
    username: 'default',
    password: '',
    compress: true,
  ));

  await conn.exec('''
    CREATE TABLE IF NOT EXISTS dart_demo (
      id UInt32,
      name String,
      score Float64
    ) ENGINE = MergeTree()
    ORDER BY id
  ''');

  final batch = await conn.prepareBatch('INSERT INTO dart_demo');
  batch.addRow([1, 'Alice', 9.5]);
  batch.addRow([2, 'Bob', 8.2]);
  await batch.send();

  final rows = await conn.query(
    'SELECT id, name, score FROM dart_demo ORDER BY id',
  );

  try {
    while (await rows.next()) {
      final id = rows.getByName<int>('id');
      final name = rows.getByName<String>('name');
      final score = rows.getByName<double>('score');
      print('$id $name $score');
    }
  } finally {
    await rows.close();
  }

  await conn.exec('DROP TABLE IF EXISTS dart_demo');
  await conn.close();
}

Connection Options #

Create a connection directly:

final conn = await ClickHouseConnection.connect(const ClickHouseOptions(
  host: 'localhost',
  port: 9000,
  database: 'default',
  username: 'default',
  password: '',
));

Or parse a DSN:

final options = ClickHouseOptions.fromDsn(
  'clickhouse://default@localhost:9000/default?compress=true',
);
final conn = await ClickHouseConnection.connect(options);

TLS is enabled with secure: true or the clickhouses:// DSN scheme.

Querying #

query returns streaming Rows. Always close rows if you do not fully drain the result.

final rows = await conn.query(
  'SELECT number, toString(number) AS label FROM numbers(3)',
);

try {
  while (await rows.next()) {
    print(rows.toMap());
  }
} finally {
  await rows.close();
}

Useful row accessors:

final number = rows.getByName<int>('number');
final label = rows.tryGetByName<String>('label');
final pair = rows.row2<int, String>();
final map = rows.toMap();

For one-row and all-row helpers:

final row = await conn.queryRow('SELECT 1 AS value');

final values = await conn.selectAll(
  'SELECT number FROM numbers(5)',
  (row) => row['number'] as int,
);

Inserts #

Use batches for inserts:

final batch = await conn.prepareBatch('INSERT INTO events');
batch.addRow([1, 'created']);
batch.appendFromMap({'id': 2, 'name': 'updated'});
await batch.send();

Columnar append is also supported:

final batch = await conn.prepareBatch('INSERT INTO events');
batch.columnByName('id').appendSlice([1, 2, 3]);
batch.columnByName('name').appendSlice(['a', 'b', 'c']);
await batch.send();

For fire-and-forget style inserts:

await conn.asyncInsert(
  "INSERT INTO events VALUES (1, 'created')",
  wait: true,
);

Connection Pooling #

final pool = ClickHousePool(
  options: const ClickHouseOptions(host: 'localhost'),
  maxOpen: 10,
  maxIdle: 5,
);

final rows = await pool.query('SELECT version()');
await rows.close();

await pool.close();

The pool exposes query, exec, asyncInsert, prepareBatch, ping, and serverVersion.

Settings and Parameters #

Per-query settings:

final rows = await conn.query(
  'SELECT number FROM system.numbers LIMIT 10',
  settings: {
    'max_result_rows': 5,
    'result_overflow_mode': 'break',
  },
);
await rows.close();

Use ImportantSetting for normal ClickHouse settings and CustomSetting for settings that should be forwarded without server validation.

Server-side query parameters:

final rows = await conn.query(
  'SELECT {name:String} AS name',
  parameters: {'name': 'Alice'},
);
await rows.close();

Client-side binding is also available:

final sql = bind(
  'SELECT * FROM users WHERE id = ? AND status = @status',
  [42, const NamedValue('status', 'active')],
);

External Tables #

final ids = ExternalTable('ids')
  ..addColumn('id', 'UInt32')
  ..addRow([1])
  ..addRow([2]);

final rows = await conn.query(
  'SELECT id FROM ids ORDER BY id',
  externalTables: [ids],
);
await rows.close();

Observability #

Callbacks are available for server progress, profile info, profile events, and logs:

final rows = await conn.query(
  'SELECT sum(number) FROM numbers(1000000)',
  onProgress: (progress) => print(progress.readRows),
  onLog: (logs) => logs.forEach((log) => print(log.message)),
);
await rows.close();

ClickHouse server exceptions are surfaced as ClickHouseException with a code, name, message, stack trace, and nested cause when available.

Compression #

Enable LZ4 compression with:

final conn = await ClickHouseConnection.connect(const ClickHouseOptions(
  host: 'localhost',
  compress: true,
));

Additional compression methods can be plugged in with registerCodec.

Local Testing #

Start ClickHouse:

docker run -d --name clickhouse-dart-test \
  -p 9000:9000 -p 8123:8123 \
  -e CLICKHOUSE_SKIP_USER_SETUP=1 \
  clickhouse/clickhouse-server:latest

Run tests:

dart test

Integration tests read these environment variables:

  • CLICKHOUSE_HOST
  • CLICKHOUSE_PORT
  • CLICKHOUSE_USERNAME
  • CLICKHOUSE_PASSWORD
  • CLICKHOUSE_DATABASE

Current Scope #

This package targets the native TCP interface only. HTTP transport is not included.

0
likes
150
points
129
downloads

Documentation

API reference

Publisher

verified publishershreyanshchaudhary.in

Weekly Downloads

A fast, native Dart driver for ClickHouse over the TCP binary protocol — queries, batch inserts, connection pooling, LZ4 compression, and full column-type support.

Repository (GitHub)
View/report issues
Contributing

License

MIT (license)

Dependencies

meta, timezone

More

Packages that depend on clickhouse