Skip to content
Exposed docs1.11

Exposed ClickHouse Adapter

Latest stable Based on Exposed release 1.11.0

bluetape4k-exposed-clickhouse adapts Exposed JDBC queries and ClickHouse-specific table engines, types, aggregates, and date functions to ClickHouse’s autocommit OLAP model.

Exposed expects JDBC transaction and relational DDL conventions that ClickHouse does not share. The adapter registers a dialect, forces autocommit, sanitizes table DDL, and exposes ClickHouse-native engine and column DSLs.

Use it for analytical reads and append-oriented writes where ClickHouse is already the execution engine. Do not use an Exposed transaction {} block as an atomic multi-statement unit.

dependencies {
implementation(platform("io.github.bluetape4k:bluetape4k-dependencies:<version>"))
implementation("io.github.bluetape4k.exposed:bluetape4k-exposed-clickhouse")
}
  • ClickHouseDatabase registers the JDBC driver and dialect.
  • ClickHouseConnectionWrapper enforces autocommit; commit and rollback are no-ops.
  • ClickHouseTable keeps only CREATE TABLE, removes relational constraints/null tokens, and appends an engine clause.
  • The module supplies MergeTree DSL, unsigned/array/low-cardinality/time types, and analytical functions.
val db = ClickHouseDatabase.connect(
host = "localhost", port = 8123, database = "default",
user = "default", password = "",
)
transaction(db) {
Events.selectAll().limit(100).toList()
}
TaskAPI
ConnectClickHouseDatabase.connect(...)
Engine-aware DDLextend ClickHouseTable; configure mergeTree { ... }
Coroutine bridgesuspendTransaction
Materialized FlowqueryFlow
Explicitly reject invalid SQL patternsClickHouseUnsupported

Make each write independently retryable and idempotent where possible. Use batch inserts for ingestion and a MergeTree engine suited to the deduplication/order requirement. Apply paging or aggregation at the database; queryFlow materializes the result before emission.

The ClickHouse JDBC driver is bundled as an API dependency. Release tests use Testcontainers ClickHouse and cover connection validation, DDL, inserts, batch inserts, engine clauses, functions, and custom types. The runnable OLTP/OLAP comparison lives in examples-exposed-clickhouse-oltp-olap.

The convenience connection uses HTTP port 8123; a full jdbc:clickhouse://... URL is also accepted. Validate the chosen engine, ORDER BY, partition key, and server-side retention settings as part of schema review.

  • A later statement failure does not roll back earlier writes.
  • INSERT IGNORE, ON CONFLICT/upsert, and RETURNING are unsupported.
  • Primary keys, foreign keys, comments, sequences, and ALTER COLUMN TYPE are not emitted as ordinary relational DDL.
  • queryFlow can hold the full result in memory.

Observe insert batch size, rejected rows, query duration, parts/merges, and memory. Keep retry boundaries smaller than a logical batch and record a deduplication key when a producer may repeat writes.

Run integration tests against a disposable ClickHouse container. Assert both generated engine DDL and query results. Add a partial-write test for every workflow that contains more than one DML statement.

Use the adapter matrix, then run the ClickHouse OLTP/OLAP example. The OLTP vs OLAP guide explains when to keep transactional writes elsewhere.

The wrapper makes Exposed callable; it cannot add transactions, savepoints, relational constraints, or rollback to ClickHouse. Only the engine/type/function surface covered in release 1.11 should be treated as supported.

These diagrams are loaded directly from README assets published with the 1.11.0 release and pinned to its immutable commit. They describe this manual’s released structure and runtime flows, not later Snapshot changes. Select a preview to open the SVG at the same release commit.

ClickHouse Exposed integration architecture

Section titled “ClickHouse Exposed integration architecture”

ClickHouse Exposed integration architecture

Release README: exposed/clickhouse/README.md

ClickHouse DDL lifecycle

Release README: exposed/clickhouse/README.md