Guest User

Untitled

a guest
Apr 25th, 2018
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.99 KB | None | 0 0
  1. defmodule MarketData.Query do
  2. @moduledoc """
  3. Builds and executes a `MarketData.Repo` query from a `Map` of params..
  4. """
  5.  
  6. alias MarketData.Repo
  7.  
  8. import Ecto.Query
  9.  
  10. @namespace "Elixir.MarketData.Schemas"
  11.  
  12. @doc """
  13.  
  14. """
  15. def run(schema, params), do: schema |> schema(params) |> build() |> execute()
  16.  
  17. defp schema(schema, params) do
  18. try do
  19. {:ok, query(schema), params}
  20. rescue
  21. _ -> {:error, "Invalid schema", nil}
  22. end
  23. end
  24.  
  25. defp query(schema), do: from(:"#{@namespace}.#{schema}", order_by: [asc: :ticker])
  26.  
  27. defp build({:error, reason, _params}), do: {:error, reason, nil}
  28.  
  29. defp build({:ok, query, params}) when params == %{}, do: {:ok, query, params}
  30.  
  31. defp build({:ok, query, %{"limit" => limit} = params}),
  32. do: build({:ok, query_limit(query, limit), Map.delete(params, "limit")})
  33.  
  34. defp build({:ok, query, %{"order_by.asc" => order_by} = params}),
  35. do: build({:ok, query_order_by(query, order_by, :asc), Map.delete(params, "order_by.asc")})
  36.  
  37. defp build({:ok, query, %{"order_by.desc" => order_by} = params}),
  38. do: build({:ok, query_order_by(query, order_by, :desc), Map.delete(params, "order_by.desc")})
  39.  
  40. defp build({:ok, query, %{"select" => selects} = params}),
  41. do: build({:ok, query_select(query, selects), Map.delete(params, "select")})
  42.  
  43. defp build({:ok, query, wheres}), do: {:ok, build_where(query, Map.to_list(wheres)), %{}}
  44.  
  45. defp query_limit(query, limit), do: limit(query, ^limit)
  46.  
  47. defp query_order_by(query, order_by, :asc) do
  48. order_by = String.to_atom(order_by)
  49. query |> exclude(:order_by) |> from(order_by: [asc: ^order_by])
  50. end
  51.  
  52. defp query_order_by(query, order_by, :desc) do
  53. order_by = String.to_atom(order_by)
  54. query |> exclude(:order_by) |> from(order_by: [desc: ^order_by])
  55. end
  56.  
  57. defp query_select(query, selects) do
  58. selects = selects |> String.split(",") |> Enum.map(&String.to_atom/1)
  59. from(query, select: ^selects)
  60. end
  61.  
  62. defp build_where(query, wheres) when wheres == [], do: query
  63.  
  64. defp build_where(query, [{keys, value} | wheres]) do
  65. {key, operator} = parse_key_operator(keys)
  66. query |> where_clause(key, value, operator) |> build_where(wheres)
  67. end
  68.  
  69. defp where_clause(query, k, v, "not"), do: from(q in query, where: field(q, ^k) != ^v)
  70. defp where_clause(query, k, v, "lt"), do: from(q in query, where: field(q, ^k) < ^v)
  71. defp where_clause(query, k, v, "lte"), do: from(q in query, where: field(q, ^k) <= ^v)
  72. defp where_clause(query, k, v, "gt"), do: from(q in query, where: field(q, ^k) > ^v)
  73. defp where_clause(query, k, v, "gte"), do: from(q in query, where: field(q, ^k) >= ^v)
  74. defp where_clause(query, k, v, _), do: from(q in query, where: field(q, ^k) == ^v)
  75.  
  76. defp parse_key_operator(keys) do
  77. [key | operator] = String.split(keys, ".")
  78. {String.to_atom(key), Enum.at(operator, 0)}
  79. end
  80.  
  81. defp execute({:error, reason, _params}), do: {:error, reason}
  82.  
  83. defp execute({:ok, query, _params}) do
  84. try do
  85. {:ok, Repo.all(query)}
  86. rescue
  87. _ -> {:error, "Invalid query"}
  88. end
  89. end
  90. end
Add Comment
Please, Sign In to add comment