AshScylla.DataLayer (AshScylla v0.10.2)

Copy Markdown View Source

An Ash data layer for ScyllaDB using Xandra (direct CQL driver).

This data layer implements the Ash.DataLayer behaviour to allow Ash resources to be backed by ScyllaDB/Cassandra.

Configuration

Configure your resource to use this data layer:

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

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

  relationships do
    # Define relationships as needed
  end
end

Features Supported

  • :create - Create records
  • :read - Read records with filtering
  • :update - Update records
  • :destroy - Delete records
  • :filter - Filter queries
  • :limit - Limit results
  • :select - Select specific fields
  • :multitenancy - Keyspace-based multitenancy
  • :upsert - Upsert records (INSERT IF NOT EXISTS with LWT)
  • :update_query - Bulk update via filtered queries
  • :destroy_query - Bulk delete via filtered queries
  • :keyset - Token-based keyset pagination (the default pagination mode)
  • :distinct - DISTINCT on partition key columns
  • {:aggregate, :count} - Per-partition COUNT aggregates
  • {:atomic, :update} - Atomic updates via LWT (IF clauses)
  • {:atomic, :upsert} - Atomic upserts via LWT
  • :boolean_filter - OR filter rewriting to IN where possible

Limitations

Since ScyllaDB/Cassandra is a wide-column store, not all SQL features are supported:

  • No JOINs (use denormalization or multiple queries)
  • Expression calculations are done in Elixir post-processing (not in-database)
  • DISTINCT only works on partition key columns
  • Limited aggregation support
  • Combination queries (UNION/INTERSECT) are not supported
  • No transactions across partitions (lightweight transactions only)
  • Locking is a no-op (use LWT for conditional operations)
  • No complex WHERE clauses on non-primary key columns without secondary indexes
  • Cross-partition aggregates require materialized views
  • CQL ORDER BY only works on clustering columns within a partition
  • OFFSET is not natively supported in ScyllaDB

Summary

Types

t()

@type t() :: %AshScylla.DataLayer{
  aggregates: [map()],
  atomic: atom() | nil,
  context: map(),
  distinct: [atom()] | nil,
  filters: list(),
  group_by: [atom()] | nil,
  keyset: term(),
  limit: pos_integer() | nil,
  offset: pos_integer() | nil,
  repo: module() | nil,
  resource: Ash.Resource.t(),
  select: [atom()] | nil,
  sorts: list(),
  table: String.t() | nil,
  tenant: term(),
  upsert?: boolean(),
  upsert_fields: [atom()],
  upsert_identity: atom() | nil
}

Functions

upsert(resource, changeset)

@spec upsert(Ash.Resource.t(), Ash.Changeset.t()) ::
  {:ok, Ash.Resource.t()} | {:error, term()}