defmodule PhaseDB.Client.Session do alias PhaseDB.Client.{CLI, Connection, Request, Session} defstruct connection_pid: nil, database_name: nil @moduledoc """ Implements a CLI session for users to interact with the server. """ def create uri do IO.puts CLI.version case Connection.find_or_create uri do {:ok, connection_pid} -> repl %Session{connection_pid: connection_pid} {:error, message} -> CLI.halt_with_message message end end def repl %Session{database_name: db}=state do IO.write "#{db}> " state = :line |> IO.read |> do_request(state) |> handle_response repl state end defp do_request query, %Session{connection_pid: pid}=state do query = String.strip query case Request.create query, pid do {:ok, request_pid} -> {Request.await(request_pid), state} {:error, reason} -> CLI.halt_with_message reason end end defp handle_response({%{status: :ok, rows: [], count: nil}, %Session{}=state}) do IO.puts "OK." state end defp handle_response({%{status: :ok, rows: [], count: i}, %Session{}=state}) do IO.puts "OK, #{i} rows." state end defp handle_response({%{status: :ok, fields: fields, rows: rows, count: i}=r, %Session{}=state}) do rows = Enum.map(rows, &rewrite_tags(&1)) TableRex.quick_render!(rows, fields) |> IO.puts IO.puts "OK, #{i} rows." state end defp handle_response({%{status: :error, message: nil}, %Session{}=state}) do IO.puts "ERROR." state end defp handle_response({%{status: :error, message: m}, %Session{}=state}) do IO.puts "ERROR, #{m}." state end defp rewrite_tags row do Enum.map row, fn map when is_map(map) -> Enum.map(map, fn {l,r} -> "#{l}=#{r}" end) |> Enum.join(", ") other -> other end end end