defmodule AyeSQL.Runner do
@moduledoc """
This module defines an `AyeSQL.Runner`.
"""
alias AyeSQL.Query
@doc """
Callback to initialize the runner.
"""
@callback run(query :: Query.t(), options :: keyword()) ::
{:ok, term()} | {:error, term()}
@doc """
Uses the `AyeSQL.Runner` behaviour.
"""
defmacro __using__(_options) do
quote do
@behaviour AyeSQL.Runner
end
end
# Handles the result.
@doc false
@spec handle_result(map()) :: [map() | struct() | keyword()]
@spec handle_result(map(), map() | keyword()) ::
[map() | struct() | keyword()]
def handle_result(result, options \\ [])
def handle_result(data, options) when is_list(options) do
handle_result(data, Map.new(options))
end
def handle_result(raw_data, %{into: :raw}) do
raw_data
end
def handle_result(%{columns: nil}, _options) do
[]
end
def handle_result(%{columns: columns, rows: rows}, options) do
atom_columns = Stream.map(columns, &String.to_atom/1)
rows
|> Stream.map(&Stream.zip(atom_columns, &1))
|> Enum.map(fn row ->
case options[:into] do
struct when is_struct(struct) -> struct(struct, row)
[] -> Enum.into(row, [])
_ -> Enum.into(row, %{})
end
end)
end
end