Current section
Files
Jump to
Current section
Files
lib/sqlitex/row.ex
defmodule Sqlitex.Row do
def from(types, columns, rows, into) do
for row <- rows do
build_row(types, columns, row, into)
end
end
defp build_row(types, columns, row, into) do
types = Enum.map(types, fn type ->
type |> Atom.to_string |> String.downcase
end)
values = row |> Tuple.to_list |> Enum.zip(types) |> Enum.map(&translate_value/1)
columns
|> Enum.zip(values)
|> Enum.into(into)
end
## Convert SQLite values/types to Elixir types
defp translate_value({:undefined, _type}) do
nil
end
defp translate_value({date, "date"}) when is_binary(date), do: to_date(date)
defp translate_value({time, "time"}) when is_binary(time), do: to_time(time)
# datetime format is "YYYY-MM-DD HH:MM:SS.FFFFFF"
defp translate_value({datetime, "datetime"}) when is_binary(datetime) do
[date, time] = String.split(datetime)
{to_date(date), to_time(time)}
end
defp translate_value({0, "boolean"}), do: false
defp translate_value({1, "boolean"}), do: true
defp translate_value({int, type=<<"decimal", _::binary>>}) when is_integer(int) do
{result, _} = int |> Integer.to_string |> Float.parse
translate_value({result, type})
end
defp translate_value({float, "decimal"}), do: Decimal.new(float)
defp translate_value({float, "decimal(" <> rest}) do
[precision, scale] = rest |> String.rstrip(?)) |> String.split(",") |> Enum.map(&String.to_integer/1)
Decimal.with_context %Decimal.Context{precision: precision, rounding: :down}, fn ->
float |> Float.round(scale) |> Decimal.new |> Decimal.plus
end
end
defp translate_value({val, _type}) do
val
end
defp to_date(date) do
<<yr::binary-size(4), "-", mo::binary-size(2), "-", da::binary-size(2)>> = date
{String.to_integer(yr), String.to_integer(mo), String.to_integer(da)}
end
defp to_time(time) do
<<hr::binary-size(2), ":", mi::binary-size(2), ":", se::binary-size(2), ".", fr::binary-size(6)>> = time
{String.to_integer(hr), String.to_integer(mi), String.to_integer(se), String.to_integer(fr)}
end
end