Packages
clickhousex_test
0.4.1
ClickHouse driver for Elixir (uses HTTP). This package was created to support ecto with version > 3.0
Current section
Files
Jump to
Current section
Files
lib/clickhousex/codec/values.ex
defmodule Clickhousex.Codec.Values do
alias Clickhousex.Query
def encode(%Query{param_count: 0, type: :insert}, _, []) do
# An insert query's arguments go into the post body and the query part goes into the query string.
# If we don't have any arguments, we don't have to encode anything, but we don't want to return
# anything here because we'll duplicate the query into both the query string and post body
""
end
def encode(%Query{param_count: 0, statement: statement}, _, []) do
statement
end
def encode(%Query{param_count: 0}, _, _) do
raise ArgumentError, "Extra params! Query doesn't contain '?'"
end
def encode(%Query{param_count: param_count} = query, query_text, params) do
if length(params) != param_count do
raise ArgumentError,
"The number of parameters does not correspond to the number of question marks!"
end
query_parts = String.split(query_text, "?")
weave(query, query_parts, params)
end
defp weave(query, query_parts, params) do
weave(query, query_parts, params, [])
end
defp weave(_query, [part], [], acc) do
Enum.reverse([part | acc])
end
defp weave(query, [part | parts], [param | params], acc) do
weave(query, parts, params, [encode_param(query, param), part | acc])
end
@doc false
defp encode_param(query, param) when is_list(param) do
values = Enum.map_join(param, ",", &encode_param(query, &1))
case query.type do
:select ->
# We pass lists to in clauses, and they shouldn't have brackets around them.
values
_ ->
"[" <> values <> "]"
end
end
defp encode_param(_query, param) when is_integer(param) do
Integer.to_string(param)
end
defp encode_param(_query, true) do
"1"
end
defp encode_param(_query, false) do
"0"
end
defp encode_param(_query, param) when is_float(param) do
to_string(param)
end
defp encode_param(_query, param) when is_float(param) do
to_string(param)
end
defp encode_param(_query, nil) do
"NULL"
end
defp encode_param(_query, %DateTime{} = datetime) do
iso_date =
datetime
|> DateTime.truncate(:second)
|> DateTime.to_iso8601()
|> String.replace("Z", "")
"'#{iso_date}'"
end
defp encode_param(_query, %NaiveDateTime{} = naive_datetime) do
naive =
naive_datetime
|> NaiveDateTime.truncate(:second)
|> NaiveDateTime.to_iso8601()
"'#{naive}'"
end
defp encode_param(_query, %Date{} = date) do
"'#{Date.to_iso8601(date)}'"
end
defp encode_param(_query, param) do
"'" <> escape(param) <> "'"
end
defp escape(s) do
s
|> String.replace("_", "\_")
|> String.replace("'", "\'")
|> String.replace("%", "\%")
|> String.replace(~s("), ~s(\\"))
|> String.replace("\\", "\\\\")
end
end