Packages
ecto_ch
0.1.10
0.10.0
0.9.4
0.9.3
0.9.2
0.9.1
0.9.0
0.8.9
0.8.8
0.8.7
0.8.6
0.8.5
retired
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.5
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.6
0.6.5
0.6.4
0.6.3
0.6.2
retired
0.6.1
retired
0.6.0
retired
0.5.1
0.5.0
retired
0.4.1
0.4.0
retired
0.3.10
0.3.9
0.3.8
0.3.7
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.11
0.1.10
0.1.9
0.1.8
0.1.7
0.1.6
0.1.5
0.1.4
0.1.3
0.1.2
0.1.1
0.1.0
ClickHouse adapter for Ecto
Current section
Files
Jump to
Current section
Files
lib/mix/tasks/schema.ex
defmodule Mix.Tasks.Ecto.Ch.Schema do
@moduledoc """
Shows an Ecto schema hint for a table.
Examples:
$ mix ecto.ch.schema
$ mix ecto.ch.schema system.numbers
"""
use Mix.Task
alias Ch.Connection, as: Conn
def run([]) do
IO.puts(@moduledoc)
end
def run([source]) do
[_, table] =
source =
case String.split(source, ".") do
[_table] = source -> [nil | source]
[_prefix, _table] = source -> source
end
{where, params} =
case source do
[nil, table] ->
{"where table = {table:String}", %{"table" => table}}
[database, table] ->
{"where database = {database:String} and table = {table:String}",
%{"database" => database, "table" => table}}
end
statement = "select name, type from system.columns " <> where
conn = connect(_config = [])
case query(conn, statement, params) do
{%Ch.Result{rows: [_ | _] = rows}, _conn} ->
schema = [
"""
@primary_key false
schema "#{table}" do
""",
Enum.map(rows, fn [name, type] -> [" ", build_field(name, type), ?\n] end),
"end"
]
IO.puts(schema)
{%Ch.Result{rows: []}, _conn} ->
raise "table not found"
end
end
defp connect(config) do
case Conn.connect(config) do
{:ok, conn} -> conn
{:error, reason} -> raise reason
end
end
defp query(conn, statement, params, opts \\ []) do
query = Ch.Query.build(statement)
params = DBConnection.Query.encode(query, params, opts)
case Conn.handle_execute(query, params, opts, conn) do
{:ok, query, result, conn} -> {DBConnection.Query.decode(query, result, opts), conn}
{:disconnect, reason, _conn} -> raise reason
{:error, reason, _conn} -> raise reason
end
end
@doc false
def build_field(name, type) do
type = Ch.Types.decode(type)
ecto_type = ecto_type(type)
clickhouse_type = clickhouse_type(type)
case {ecto_type, clickhouse_type} do
{ecto_type, nil} ->
~s[field :"#{name}", #{inspect(ecto_type)}]
{ecto_type, clickhouse_type} ->
~s[field :"#{name}", #{inspect(ecto_type)}, type: "#{clickhouse_type}"]
end
end
defp ecto_type({:array, type}), do: {:array, ecto_type(type)}
defp ecto_type(type) when type in [:string, :date, :boolean], do: type
defp ecto_type(:uuid), do: Ecto.UUID
defp ecto_type(_type), do: Ch
defp clickhouse_type({:array, type}), do: clickhouse_type(type)
defp clickhouse_type(type) when type in [:uuid, :string, :date, :boolean], do: nil
defp clickhouse_type(type), do: Ch.Types.encode(type)
end