Behaviour describing what analysis capabilities a given Ash data layer supports.
AshDyan ships with implementations for AshPostgres, AshClickhouse,
AshScylla, AshSqlite, and Ash.DataLayer.Simple (ETS). Other data layers
fall back to a conservative default that supports only :frequency and
:aggregate.
The capability check is surfaced explicitly via AshDyan.supports?/2 so
callers can discover data-layer limits before issuing a query.
Custom capability modules may also implement capabilities/1 to describe
the query primitives and aggregation strategy their adapter provides. This
metadata is available through capabilities/1; supports?/2 remains the
boolean gate used by the engine.
Extending with third-party data layers
The mapping from an Ash data-layer module to its AshDyan.DataLayer
capability implementation is config-mergeable, so a downstream app can register
its own data layer without patching AshDyan:
config :ash_dyan, :data_layer_capabilities, %{
MyApp.CustomDataLayer => MyApp.AshDyan.CustomCapabilities
}Or via an extension:
defmodule MyApp.AshDyan.Extension do
@behaviour AshDyan.Extension
def data_layer_capabilities do
%{
MyApp.CustomDataLayer => MyApp.AshDyan.CustomCapabilities
}
end
end
config :ash_dyan, :extensions, [MyApp.AshDyan.Extension]
Summary
Callbacks
Describe query and aggregation primitives supplied by the adapter.
Optional callback for SQL-pushdown of time bucketing.
Functions
Return normalized query and aggregation metadata for a resource's data layer.
Return capability metadata for an explicit data-layer module.
Resolve the capability module for a data-layer module.
Resolve the data-layer capability module for a resource.
Returns true if the resource's data layer supports the capability.
Types
@type capability_info() :: %{ analyses: %{optional(AshDyan.capability()) => boolean()}, query: %{optional(:filter | :select | :limit | :timeout | :sort) => boolean()}, aggregation: %{ optional(:mode) => :in_memory | :pushdown | :hybrid, optional(:functions) => [atom()] } }
Callbacks
@callback capabilities(module()) :: capability_info()
Describe query and aggregation primitives supplied by the adapter.
@callback paginate(Ash.Query.t(), pos_integer(), pos_integer()) :: {:ok, Ash.Query.t()} | {:error, term()}
@callback pushdown_aggregate(Ash.Query.t(), atom(), atom()) :: {:ok, Ash.Query.t()} | :not_supported
@callback pushdown_time_bucket(Ash.Query.t(), atom(), AshDyan.time_bucket()) :: {:ok, Ash.Query.t()} | :not_supported
Optional callback for SQL-pushdown of time bucketing.
A data layer that can express a time bucket natively (e.g. Postgres
date_trunc) implements this and returns {:ok, query}. The default returns
:not_supported, in which case the engine falls back to in-memory bucketing.
@callback stream(Ash.Query.t(), keyword(), keyword()) :: {:ok, Enumerable.t()} | {:error, term()}
@callback supports?(module(), AshDyan.capability()) :: boolean()
Functions
@spec capabilities(module()) :: capability_info()
Return normalized query and aggregation metadata for a resource's data layer.
Custom capability modules can implement capabilities/1 and return partial
sections; omitted sections are filled with conservative defaults. This lets
an adapter advertise native aggregate functions or query features without
changing AshDyan's public request format.
@spec capabilities_for_data_layer(module(), module()) :: capability_info()
Return capability metadata for an explicit data-layer module.
Resolve the capability module for a data-layer module.
Resolve the data-layer capability module for a resource.
Built-in mappings are merged with config :ash_dyan, :data_layer_capabilities
and extension configurations, so third-party data layers can register their
own capability module.
@spec supports?(module(), AshDyan.capability()) :: boolean()
Returns true if the resource's data layer supports the capability.