Current section
Files
Jump to
Current section
Files
lib/snowflex.ex
defmodule Snowflex do
alias Snowflex.Worker
@moduledoc """
The client interface for connecting to the Snowflake data warehouse.
The main entry point to this module is `Snowflex.sql_query`. This function takes a string containing
a SQL query and returns a list of maps (one per row). NOTE: due to the way the Erlang ODBC works, all values comeback
as strings. You will need to cast values appropriately.
"""
@timeout :timer.seconds(60)
@type query_param :: {:odbc.odbc_data_type(), list(:odbc.value())}
@type sql_data :: list(%{optional(String.t()) => String.t()})
@spec sql_query(atom(), String.t(), non_neg_integer() | :infinity) ::
sql_data() | {:error, term}
def sql_query(pool_name, query, timeout \\ @timeout) do
case :poolboy.transaction(
pool_name,
fn pid -> Worker.sql_query(pid, query, timeout) end,
timeout
) do
{:ok, results} -> process_results(results)
err -> err
end
end
@spec param_query(atom(), String.t(), list(query_param()), non_neg_integer() | :infinity) ::
sql_data() | {:error, term}
def param_query(pool_name, query, params \\ [], timeout \\ @timeout) do
case :poolboy.transaction(
pool_name,
fn pid -> Worker.param_query(pid, query, params, timeout) end,
timeout
) do
{:ok, results} -> process_results(results)
err -> err
end
end
# Helpers
defp process_results(data) when is_list(data) do
Enum.map(data, &process_results(&1))
end
defp process_results({:selected, headers, rows}) do
bin_headers =
headers
|> Enum.map(fn header -> header |> to_string() |> String.downcase() end)
|> Enum.with_index()
Enum.map(rows, fn row ->
Enum.reduce(bin_headers, %{}, fn {col, index}, map ->
data =
row
|> elem(index)
|> to_string_if_charlist()
Map.put(map, col, data)
end)
end)
end
defp to_string_if_charlist(data) when is_list(data), do: to_string(data)
defp to_string_if_charlist(data), do: data
end