AshClickhouse.DataLayer (AshClickhouse v0.3.0)

Copy Markdown View Source

An Ash data layer for ClickHouse.

This data layer implements the Ash.DataLayer behaviour so that Ash resources can be backed by a ClickHouse columnar OLAP database. It uses the clickhouse client under the hood.

Configuration

defmodule MyApp.MyResource do
  use Ash.Resource,
    data_layer: AshClickhouse.DataLayer

  clickhouse do
    table "my_table"
    repo MyApp.Repo
  end

  attributes do
    uuid_primary_key :id
    attribute :name, :string
  end
end

Features Supported

  • :create / :read / :update / :destroy
  • :filter — full WHERE support
  • :limit / :offset — ClickHouse supports both natively
  • :select — column projection
  • :sortORDER BY
  • :distinctSELECT DISTINCT
  • :multitenancy — database- or attribute-based
  • :bulk_create — batch INSERT
  • :update_query / :destroy_queryALTER TABLE ... UPDATE/DELETE
  • :calculate — in-memory calculations
  • :composite_primary_key
  • :nested_expressions / :boolean_filter
  • :async_engine
  • :expression_calculation
  • {:aggregate, :count | :sum | :avg | :min | :max} — native aggregates

  • {:query_aggregate, :count | :sum | :avg | :min | :max}

  • Combination queries (UNION/INTERSECT) — executed by Ash in memory

Features NOT Supported

  • :transact — ClickHouse has no multi-statement transactions
  • :lock — locking is a no-op
  • :keyset — ClickHouse has no token-based keyset pagination
  • :upsert — ClickHouse has no ON CONFLICT (use :create + :update_query)
  • :expression_calculation_sort — not supported
  • :aggregate_filter / :aggregate_sort — not supported
  • :update_many — use :update_query
  • :composite_type / :through_relationship
  • :join — JOINs are not yet implemented
  • :filter_relationship / {:exists, :unrelated} / {:aggregate_relationship, _}
  • {:query_aggregate, :list | :first | :exists | :custom} — only count/sum/avg/min/max

Summary

Functions

Returns a stream of Ash records for the given query, consuming ClickHouse's native query stream instead of materializing every row into memory.

Types

t()

@type t() :: AshClickhouse.Query.t()

Functions

stream(data_layer_query, resource, opts \\ [])

@spec stream(t(), Ash.Resource.t(), keyword()) :: Enumerable.t(Ash.Resource.t())

Returns a stream of Ash records for the given query, consuming ClickHouse's native query stream instead of materializing every row into memory.

This is the natural read path for large OLAP scans/reports. The returned stream yields decoded Ash records one at a time as chunks arrive.

In-memory calculations and aggregates configured on the query are applied to each decoded chunk, so stream/3 returns results identical to run_query/2 (which applies them after fetching all rows). This keeps streaming and non-streaming reads behaviourally consistent.

Options

  • :mutations_sync is ignored for reads.
  • any other options are forwarded to the underlying ClickHouse client.