if Code.ensure_loaded?(Ecto.Adapters.SQL) do
defmodule Ecto.Adapters.QuackDB do
@moduledoc """
Minimal Ecto SQL adapter for QuackDB.
Ecto SQL adapter for DuckDB over QuackDB. Supports raw SQL, analytical query
generation, insert paths, common mutations, and basic migration DDL.
## Configuration
config :my_app, MyApp.AnalyticsRepo,
adapter: Ecto.Adapters.QuackDB,
uri: "http://[::1]:9494",
token: "super_secret"
"""
use Ecto.Adapters.SQL,
driver: :quackdb
@impl Ecto.Adapter.Migration
def supports_ddl_transaction?, do: true
@impl Ecto.Adapter.Migration
def lock_for_migrations(_meta, _options, fun), do: fun.()
@impl Ecto.Adapter.Schema
def autogenerate(:id), do: nil
def autogenerate(:embed_id), do: Ecto.UUID.generate()
def autogenerate(:binary_id), do: Ecto.UUID.bingenerate()
def loaders({:map, _}, type), do: [&json_decode/1, &Ecto.Type.embedded_load(type, &1, :json)]
def loaders(:map, type), do: [&json_decode/1, type]
def loaders(:binary_id, type), do: [Ecto.UUID, type]
def loaders(_, type), do: [type]
def dumpers({:map, _}, type), do: [&Ecto.Type.embedded_dump(type, &1, :json)]
def dumpers(:binary_id, type), do: [type, Ecto.UUID]
def dumpers(_, type), do: [type]
@impl Ecto.Adapter.Schema
def insert_all(
adapter_meta,
schema_meta,
header,
rows,
on_conflict,
returning,
placeholders,
opts
) do
case Keyword.get(opts, :insert_method, :sql) do
:sql ->
sql_insert_all(
adapter_meta,
schema_meta,
header,
rows,
on_conflict,
returning,
placeholders,
opts
)
:append ->
Ecto.Adapters.QuackDB.AppendInsert.run(
adapter_meta,
schema_meta,
header,
rows,
on_conflict,
returning,
placeholders,
opts
)
other ->
unsupported!(
:schema_inserts,
"unsupported insert_method for QuackDB: #{inspect(other)}"
)
end
end
defp sql_insert_all(
adapter_meta,
schema_meta,
header,
rows,
on_conflict,
returning,
placeholders,
opts
) do
Ecto.Adapters.SQL.insert_all(
adapter_meta,
schema_meta,
@conn,
header,
rows,
on_conflict,
returning,
placeholders,
opts
)
end
defp json_decode(value) when is_binary(value), do: JSON.decode(value)
defp json_decode(value), do: {:ok, value}
defp unsupported!(feature, message) do
raise QuackDB.Error.new(:ecto_feature_not_supported, message,
source: :client,
metadata: %{feature: feature}
)
end
end
end