defmodule Couchx.QueryHandler do
@empty_response [
%{"rows" => []},
%{"docs" => []},
%{"bookmark" => "nil", "docs" => []}
]
def query_results([], _, _), do: {0, []}
def query_results({:error, reason}, _, _), do: raise Couchx.DbError, message: "#{reason}"
def query_results({:ok, response}, _, _) when response in @empty_response do
{0, []}
end
def query_results({:ok, response}, fields, metadata) do
query_results(response, fields, metadata)
end
def query_results(%{"rows" => rows}, fields, metadata) do
Enum.map(rows, &query_results(&1, fields, metadata))
|> execute_response
end
def query_results(%{"docs" => docs}, fields, metadata) do
Enum.map(docs, &process_docs(&1, fields, metadata))
|> execute_response
end
def query_results(%{"doc" => doc}, fields, metadata) do
process_docs(doc, fields, metadata)
end
def query_results(doc, fields, metadata) do
process_docs(doc, fields, metadata)
|> execute_response
end
defp execute_response([]), do: {0, []}
defp execute_response([item | _] = values) when is_list(item) do
{length(values), values}
end
defp execute_response(value), do: {1, [value]}
defp process_docs(rows, fields, meta) when is_list(rows) do
Enum.map(rows, &process_docs(&1, fields, meta))
end
defp process_docs(doc, fields, nil) do
Enum.reduce(fields, [], fn({key, value}, acc) ->
confirmed_value = if doc[key], do: value, else: nil
acc ++ confirmed_value
end)
end
defp process_docs(doc, _fields, meta) do
Enum.reduce(meta, [], fn({key, type}, acc) ->
value = Map.get(doc, to_string(key))
acc ++ [Ecto.Type.cast(type, value) |> elem(1)]
end)
end
end