parameters.ex (1833B)
1 defmodule Postgrex.Parameters do 2 @moduledoc false 3 4 use GenServer 5 6 defstruct [] 7 @type t :: %__MODULE__{} 8 9 def start_link(_) do 10 GenServer.start_link(__MODULE__, nil, name: __MODULE__) 11 end 12 13 @spec insert(%{binary => binary}) :: reference 14 def insert(parameters) do 15 GenServer.call(__MODULE__, {:insert, parameters}) 16 end 17 18 @spec put(reference, binary, binary) :: boolean 19 def put(ref, name, value) do 20 try do 21 :ets.lookup_element(__MODULE__, ref, 2) 22 rescue 23 ArgumentError -> 24 false 25 else 26 parameters -> 27 parameters = Map.put(parameters, name, value) 28 :ets.update_element(__MODULE__, ref, {2, parameters}) 29 end 30 end 31 32 @spec delete(reference) :: :ok 33 def delete(ref) do 34 GenServer.cast(__MODULE__, {:delete, ref}) 35 end 36 37 @spec fetch(reference) :: {:ok, %{binary => binary}} | :error 38 def fetch(ref) do 39 try do 40 :ets.lookup_element(__MODULE__, ref, 2) 41 rescue 42 ArgumentError -> 43 :error 44 else 45 parameters -> 46 {:ok, parameters} 47 end 48 end 49 50 def init(nil) do 51 opts = [:public, :named_table, {:read_concurrency, true}, {:write_concurrency, true}] 52 state = :ets.new(__MODULE__, opts) 53 {:ok, state} 54 end 55 56 def handle_call({:insert, parameters}, {pid, _}, state) do 57 ref = Process.monitor(pid) 58 true = :ets.insert_new(state, {ref, parameters}) 59 {:reply, ref, state} 60 end 61 62 def handle_cast({:delete, ref}, state) do 63 :ets.delete(state, ref) 64 {:noreply, state} 65 end 66 67 def handle_info({:DOWN, ref, :process, _, _}, state) do 68 :ets.delete(state, ref) 69 {:noreply, state} 70 end 71 end 72 73 defimpl DBConnection.Query, for: Postgrex.Parameters do 74 def parse(query, _), do: query 75 def describe(query, _), do: query 76 def encode(_, nil, _), do: nil 77 def decode(_, parameters, _), do: parameters 78 end