Packages

Elixir Azure Storage REST Client support Blob, Queue, Fileshare and TableStorage service

Current section

Files

Jump to
ex_azure_storage lib azure_storage table query_builder.ex
Raw

lib/azure_storage/table/query_builder.ex

defmodule AzureStorage.Table.QueryBuilder do
@moduledoc """
Azure Table Storage Query Builder
"""
alias AzureStorage.Table.Query
@comparition [
:eq,
:ne,
:le,
:ge,
:lt,
:le
]
@spec where(Query.t(), String.t()) :: Query.t()
def where(%Query{} = query, criteria) when is_bitstring(criteria) do
add_filter(query, :and, criteria)
end
@spec where(Query.t(), String.t(), atom(), any()) :: Query.t()
def where(%Query{} = query, field, comparition, value)
when comparition in @comparition do
criteria = field(field, comparition, value)
add_filter(query, :and, criteria)
end
@doc """
Build or expression
"""
@spec or_where(Query.t(), String.t()) :: Query.t()
def or_where(%Query{} = query, criteria) when is_bitstring(criteria) do
add_filter(query, :or, criteria)
end
@doc """
Build or expression
"""
def or_where(%Query{} = query, field, comparition, value)
when comparition in @comparition do
criteria = field(field, comparition, value)
add_filter(query, :or, criteria)
end
@doc """
Select top entities
"""
@spec top(Query.t(), integer) :: Query.t()
def top(%Query{} = query, count) do
%{query | top: count}
end
@doc """
Generate query path from `AzureStorage.Table.Query`
"""
def compile(%Query{filter: filter, table: table, top: top}) do
filter =
filter
|> Enum.reverse()
|> Enum.join("%20")
"#{table}?$filter=#{filter}&$top=#{top}"
end
defp add_filter(%Query{filter: filter} = query, connector, criteria)
when is_bitstring(criteria) and
connector in [:and, :or] do
filter =
case filter do
nil -> ["(#{criteria})"]
_ -> ["#{Atom.to_string(connector)}%20(#{criteria})" | filter]
end
%{query | filter: filter}
end
# ----------------------
defp field(field, comparition, value)
when comparition in @comparition do
field_value = field_value(value)
"#{field}%20#{Atom.to_string(comparition)}%20#{field_value}"
end
defp field_value(value) when is_number(value) or is_boolean(value), do: "#{value}"
defp field_value(value) do
cond do
is_date?(value) -> "datetime'#{value}'"
is_guid?(value) -> "guid'#{value}'"
true -> "'#{value |> escape}'"
end
end
defp is_guid?(value) do
String.match?(value, ~r/^[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}$/)
end
defp is_date?(date) do
case date do
%NaiveDateTime{} -> true
%DateTime{} -> true
_ -> false
end
end
defp escape(value) do
value |> URI.encode()
end
end