Packages
exqlite
0.2.0
0.39.0
0.38.0
0.37.0
0.36.0
0.35.0
0.34.0
0.33.1
0.33.0
0.32.1
0.32.0
0.31.0
0.30.1
0.30.0
0.29.0
0.28.0
0.27.1
0.27.0
0.26.0
0.25.0
0.24.2
0.24.1
0.24.0
0.23.0
0.22.0
0.21.0
0.20.0
0.19.0
0.18.0
0.17.0
0.16.2
0.16.1
0.16.0
0.15.0
0.14.0
0.13.15
0.13.14
0.13.13
0.13.12
0.13.11
0.13.10
0.13.9
0.13.8
0.13.7
0.13.6
0.13.5
0.13.4
0.13.3
0.13.2
0.13.1
0.13.0
0.12.0
0.11.9
0.11.8
0.11.7
0.11.6
0.11.5
0.11.4
0.11.3
0.11.2
0.11.1
0.11.0
0.10.3
0.10.2
0.10.1
0.10.0
0.9.3
0.9.2
0.9.1
0.9.0
0.8.7
0.8.6
0.8.5
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.9
0.7.8
0.7.7
0.7.6
0.7.5
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
0.5.11
0.5.10
0.5.9
0.5.8
0.5.7
0.5.6
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.9
0.4.8
0.4.7
0.4.6
0.4.5
0.4.4
0.4.2
0.4.1
0.4.0
0.3.6
0.3.5
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
0.2.2
0.2.1
0.2.0
0.1.1
0.1.0
An Elixir SQLite3 library
Current section
Files
Jump to
Current section
Files
lib/exqlite/queries.ex
defmodule Exqlite.Queries do
@moduledoc """
The interface to manage cached prepared queries.
"""
#
# TODO: We should probably do some tracking on the number of statements being
# generated and culling the oldest cached value (LRU). In its current
# implementation, this could just have a run away memory leak if we are
# not careful.
#
alias Exqlite.Query
@type t :: :ets.tid()
@spec new(atom()) :: t()
def new(name) do
# TODO: Should this be set to :private?
#
# Ideally the only process that will be accessing this ets table would be
# the connection that owns it.
:ets.new(name, [:set, :public])
end
@spec put(t(), Query.t()) :: :error
def put(_cache, %Query{name: ""}), do: :error
@spec put(t(), Query.t()) :: :error
def put(_cache, %Query{name: nil}), do: :error
@spec put(t(), Query.t()) :: :error
def put(_cache, %Query{ref: nil}), do: :error
@spec put(t(), Query.t()) :: :ok | :error
def put(cache, %Query{name: query_name, ref: ref}) do
try do
:ets.insert(cache, {query_name, {ref}})
rescue
ArgumentError -> :error
else
true -> :ok
end
end
@spec delete(nil) :: :ok
def delete(nil), do: :ok
@spec delete(t()) :: :ok
def delete(cache) do
:ets.delete(cache)
:ok
end
@spec delete(t(), Query.t()) :: :error
def delete(_cache, %Query{name: nil}), do: :error
@spec delete(t(), Query.t()) :: :error
def delete(_cache, %Query{name: ""}), do: :error
@spec delete(t(), Query.t()) :: :ok | :error
def delete(cache, %Query{name: query_name}) do
try do
:ets.delete(cache, query_name)
rescue
ArgumentError -> :error
else
true -> :ok
end
end
@spec get(t(), Query.t()) :: nil
def get(_cache, %Query{name: nil}), do: nil
@spec get(t(), Query.t()) :: nil
def get(_cache, %Query{name: ""}), do: nil
@doc """
Gets an existing prepared query if it exists. Otherwise `nil` is returned.
"""
@spec get(t(), Query.t()) :: Query.t() | nil
def get(cache, %Query{name: query_name} = query) do
try do
:ets.lookup_element(cache, query_name, 2)
rescue
ArgumentError -> nil
else
{ref} ->
%{query | ref: ref}
end
end
@doc """
Clears the entire prepared query cache.
"""
@spec clear(t()) :: :ok
def clear(cache) do
:ets.delete_all_objects(cache)
:ok
end
@spec size(nil) :: integer()
def size(nil), do: 0
@spec size(t()) :: integer()
def size(cache) do
:ets.info(cache) |> Keyword.get(:size, 0)
end
end