defmodule ClickHouse.Format.Values do
@moduledoc """
An implementation of the ClickHouse `Values` format.
"""
@behaviour ClickHouse.Format
import ClickHouse.Utils, only: [intersperse_map: 3, escape: 1]
################################
# ClickHouse.Format Callbacks
################################
@impl ClickHouse.Format
@spec names() :: [binary()]
def names, do: ["Values"]
@impl ClickHouse.Format
@spec decode(raw :: iodata()) :: no_return()
def decode(_raw) do
raise RuntimeError, "Values decode not implemented."
end
@impl ClickHouse.Format
@spec encode(params :: list()) :: iodata()
def encode(params) do
intersperse_map(params, ",", fn row ->
["(", intersperse_map(row, ",", &encode_value/1), ")"]
end)
end
################################
# Private API
################################
defp encode_value(value) when is_binary(value) do
["'", escape(value), "'"]
end
defp encode_value(false), do: "0"
defp encode_value(true), do: "1"
defp encode_value(nil), do: "NULL"
defp encode_value(value) when is_atom(value) do
value = to_string(value)
["'", escape(value), "'"]
end
defp encode_value(value) when is_list(value) do
["[", intersperse_map(value, ",", &encode_value/1), "]"]
end
defp encode_value(value) when is_float(value), do: to_string(value)
defp encode_value(value) when is_integer(value), do: to_string(value)
defp encode_value(%Date{} = value), do: ["'", to_string(value), "'"]
defp encode_value(%DateTime{} = value) do
value =
value
|> DateTime.truncate(:second)
|> DateTime.to_iso8601()
|> String.replace("Z", "")
["'", value, "'"]
end
end