Current section
Files
Jump to
Current section
Files
lib/selecto/db/postgresql.ex
defmodule Selecto.DB.PostgreSQL do
@moduledoc """
PostgreSQL adapter for Selecto.
"""
@behaviour Selecto.DB.Adapter
@impl true
def name, do: :postgresql
@impl true
def connect({:pool, _} = pool_ref), do: {:ok, pool_ref}
def connect(connection) when is_pid(connection) or is_atom(connection), do: {:ok, connection}
def connect(opts) when is_map(opts), do: connect(Map.to_list(opts))
def connect(opts) when is_list(opts) do
case Postgrex.start_link(opts) do
{:ok, conn} -> {:ok, conn}
{:error, reason} -> {:error, reason}
end
end
def connect(other), do: {:error, {:invalid_connection_options, other}}
@impl true
def execute({:pool, pool_ref}, query, params, opts) do
case Selecto.ConnectionPool.execute(pool_ref, normalize_query(query), params, opts) do
{:ok, result} -> {:ok, normalize_result(result)}
{:error, reason} -> {:error, reason}
end
end
def execute(connection, query, params, opts) when is_pid(connection) or is_atom(connection) do
case Postgrex.query(connection, normalize_query(query), params, opts) do
{:ok, result} -> {:ok, normalize_result(result)}
{:error, reason} -> {:error, reason}
end
end
def execute(connection, _query, _params, _opts), do: {:error, {:invalid_connection, connection}}
@impl true
def placeholder(index), do: ["$", Integer.to_string(index)]
@impl true
def quote_identifier(identifier) when is_binary(identifier) do
escaped = String.replace(identifier, "\"", "\"\"")
"\"#{escaped}\""
end
def quote_identifier(identifier), do: identifier |> to_string() |> quote_identifier()
@impl true
def supports?(feature) do
feature in [:cte, :jsonb, :array_ops, :returning, :window_functions, :lateral_join, :prefix]
end
defp normalize_query(query) when is_binary(query), do: query
defp normalize_query(query), do: IO.iodata_to_binary(query)
defp normalize_result(%{rows: rows, columns: columns}) do
%{
rows: rows || [],
columns: Enum.map(columns || [], &to_string/1)
}
end
end