Packages

ETS backend for kura

Current section

Files

Jump to
kura_ets src kura_ets_dialect.erl
Raw

src/kura_ets_dialect.erl

-module(kura_ets_dialect).
-moduledoc """
"Dialect" for the ETS backend. There is no SQL to emit: each callback
wraps the portable `#kura_query{}` AST (or the operation data) into an
opaque `{kura_ets, Plan}` term that `kura_ets_driver` hands to
`kura_ets_query` for interpretation against ETS tables.
The parameter list is always `[]`: values stay embedded in the plan.
This keeps the plan a pure function of the query AST, so kura's query
cache (`kura_query_compiler:to_sql_cached/2`, keyed on the hashed AST)
remains correct.
One observable difference vs SQL dialects: kura's query telemetry and
legacy logging stringify the compiled statement with
`iolist_to_binary/1`, which does not accept a plan tuple; those events
are skipped for this backend (kura wraps emission in a catch).
""".
-behaviour(kura_dialect).
-include_lib("kura/include/kura.hrl").
-export([
to_sql/1,
to_sql_from/2,
insert/3,
insert/4,
update/4,
delete/2,
update_all/2,
delete_all/1,
insert_all/3,
insert_all/4
]).
-type plan() ::
{select, #kura_query{}}
| {insert, atom() | module(), map(), map()}
| {update, atom() | module(), map(), [{atom(), term()}]}
| {delete, atom() | module(), [{atom(), term()}]}
| {update_all, #kura_query{}, map()}
| {delete_all, #kura_query{}}
| {insert_all, atom() | module(), [map()], map()}.
-export_type([plan/0]).
%%----------------------------------------------------------------------
%% kura_dialect callbacks
%%----------------------------------------------------------------------
-spec to_sql(#kura_query{}) -> {dynamic(), [term()]}.
to_sql(Query) ->
{{kura_ets, {select, Query}}, []}.
-spec to_sql_from(#kura_query{}, pos_integer()) -> {dynamic(), [term()], pos_integer()}.
to_sql_from(Query, StartCounter) ->
%% Sub-query composition (CTEs, IN (subquery)) is rejected at
%% execution time; the callback exists to satisfy the behaviour.
{{kura_ets, {select, Query}}, [], StartCounter}.
-spec insert(atom() | module(), [atom()], map()) -> {dynamic(), [term()]}.
insert(SchemaOrTable, Fields, Data) ->
insert(SchemaOrTable, Fields, Data, #{}).
-spec insert(atom() | module(), [atom()], map(), map()) -> {dynamic(), [term()]}.
insert(SchemaOrTable, _Fields, Data, Opts) ->
{{kura_ets, {insert, SchemaOrTable, Data, Opts}}, []}.
-spec update(atom() | module(), [atom()], map(), [{atom(), term()}]) -> {dynamic(), [term()]}.
update(SchemaOrTable, _Fields, Changes, KeyClauses) ->
{{kura_ets, {update, SchemaOrTable, Changes, KeyClauses}}, []}.
-spec delete(atom() | module(), [{atom(), term()}]) -> {dynamic(), [term()]}.
delete(SchemaOrTable, KeyClauses) ->
{{kura_ets, {delete, SchemaOrTable, KeyClauses}}, []}.
-spec update_all(#kura_query{}, map()) -> {dynamic(), [term()]}.
update_all(Query, SetMap) ->
{{kura_ets, {update_all, Query, SetMap}}, []}.
-spec delete_all(#kura_query{}) -> {dynamic(), [term()]}.
delete_all(Query) ->
{{kura_ets, {delete_all, Query}}, []}.
-spec insert_all(atom() | module(), [atom()], [map()]) -> {dynamic(), [term()]}.
insert_all(SchemaOrTable, Fields, Rows) ->
insert_all(SchemaOrTable, Fields, Rows, #{}).
-spec insert_all(atom() | module(), [atom()], [map()], map()) -> {dynamic(), [term()]}.
insert_all(SchemaOrTable, _Fields, Rows, Opts) ->
{{kura_ets, {insert_all, SchemaOrTable, Rows, Opts}}, []}.