Skip to main content

lib/quack_db/result_mapper.ex

defmodule QuackDB.ResultMapper do
  @moduledoc false

  @spec rows_to_structs(QuackDB.Result.t(), module()) :: [struct()]
  def rows_to_structs(%QuackDB.Result{columns: columns, rows: rows}, module)
      when is_list(columns) and is_list(rows) do
    fields = Map.keys(struct!(module)) -- [:__struct__]
    keys = Enum.map(columns, &normalize_key/1)

    Enum.map(rows, fn row ->
      keys
      |> Enum.zip(row)
      |> Map.new()
      |> Map.take(fields)
      |> then(&struct!(module, &1))
    end)
  end

  def rows_to_structs(%QuackDB.Result{}, _module), do: []

  defp normalize_key(key) when is_binary(key) do
    key
    |> Macro.underscore()
    |> String.to_existing_atom()
  rescue
    ArgumentError -> key
  end
end