         sqlite_error(err, s)
     end
   end
-
-  # defp handle_prepare(query, prepare, opts, %{buffer: buffer} = s) do
-  #   status = %{notify: notify(opts), prepare: prepare, sync: :sync}
-  #   prepare_send(%{s | buffer: nil}, status, query, buffer)
-  # end
-  #
-  # defp prepare_send(s, %{prepare: prepare} = status, query, buffer) do
-  #   %Query{name: name, statement: statement} = query
-  #   msgs =
-  #    case prepare do
-  #      :parse_describe ->
-  #         [msg_describe(type: :statement, name: name), msg_flush()]
-  #      :parse ->
-  #         [msg_flush()]
-  #     end
-  #   msgs = [msg_parse(name: name, statement: statement, type_oids: []) | msgs]
-  #   case msg_send(s, msgs, buffer) do
-  #     :ok ->
-  #       parse_recv(s, status, query, buffer)
-  #     {:disconnect, _, _} = dis ->
-  #       dis
-  #   end
-  # end
-  #
-  # defp parse_recv(s, %{prepare: prepare} = status, query, buffer) do
-  #   case msg_recv(s, :infinity, buffer) do
-  #     {:ok, msg_parse_complete(), buffer} when prepare == :parse_describe ->
-  #       describe_recv(s, status, %Query{query | types: s.types}, buffer)
-  #     {:ok, msg_parse_complete(), buffer} when prepare == :parse ->
-  #       ok(s, query, buffer)
-  #     {:ok, msg_error(fields: fields), buffer} ->
-  #       exception = Sqlite.DbConnection.Error.exception(postgres: fields)
-  #       close_sync(s, status, query, exception, buffer)
-  #     {:ok, msg, buffer} ->
-  #       parse_recv(handle_msg(s, status, msg), status, query, buffer)
-  #     {:disconnect, _, _} = dis ->
-  #       dis
-  #   end
-  # end
-  #
-  # defp describe_recv(s, status, query, buffer) do
-  #   case msg_recv(s, :infinity, buffer) do
-  #     {:ok, msg_no_data(), buffer} ->
-  #       ok(s, query, buffer)
-  #     {:ok, msg_parameter_desc(type_oids: param_oids), buffer} ->
-  #       describe_recv(s, status, %Query{query | encoders: param_oids}, buffer)
-  #     {:ok, msg_row_desc(fields: fields), buffer} ->
-  #       {col_oids, col_names} = columns(fields)
-  #       query = %Query{query | columns: col_names, decoders: col_oids}
-  #       ok(s, query, buffer)
-  #     {:ok, msg_error(fields: fields), buffer} ->
-  #       exception = Sqlite.DbConnection.Error.exception(postgres: fields)
-  #       close_sync(s, status, query, exception, buffer)
-  #     {:ok, msg, buffer} ->
-  #       describe_recv(handle_msg(s, status, msg), status, query, buffer)
-  #     {:disconnect, _, _} = dis ->
-  #       dis
-  #   end
-  # end
-  #
-  # defp close_sync(s, status, %Query{name: name}, result, buffer) do
-  #   msgs = [
-  #     msg_close(type: :statement, name: name),
-  #     msg_sync() ]
-  #   case msg_send(s, msgs, buffer) do
-  #     :ok                       -> sync_recv(s, status, result, buffer)
-  #     {:disconnect, _, _} = dis -> dis
-  #   end
-  # end
 
   ## execute
 

  defp command_from_words(words) when is_list(words), do:
    String.to_atom(List.first(words))

  # defp execute_send(s, %{sync: sync} = status, query, params, buffer) do
  #   %Query{param_formats: pfs, result_formats: rfs, name: name} = query
  #   msgs =
  #     case sync do
  #       :sync_close ->
  #         [msg_sync(), msg_close(type: :statement, name: name), msg_flush()]
  #       :sync ->
  #         [msg_sync()]
  #     end
  #   msgs = [
  #     msg_bind(name_port: "", name_stat: name, param_formats: pfs, params: params, result_formats: rfs),
  #     msg_execute(name_port: "", max_rows: 0) |
  #     msgs ]
  #   case msg_send(s, msgs, buffer) do
  #     :ok                       -> bind_recv(s, status, query, buffer)
  #     {:disconnect, _, _} = dis -> dis
  #   end
  # end
  #
  # defp bind_recv(s, status, query, buffer) do
  #   case msg_recv(s, :infinity, buffer) do
  #     {:ok, msg_bind_complete(), buffer} ->
  #       execute_recv(s, status, query, buffer)
  #     {:ok, msg_error(fields: fields), buffer} ->
  #       bind_error(s, status, fields, buffer)
  #     {:ok, msg, buffer} ->
  #       bind_recv(handle_msg(s, status, msg), status, query, buffer)
  #     {:disconnect, _, _} = dis ->
  #       dis
  #   end
  # end
  #
  # defp bind_error(s, status, fields, buffer) do
  #   case Sqlite.DbConnection.Error.exception(postgres: fields) do
  #     %Sqlite.DbConnection.Error{postgres: %{code: :invalid_sql_statement_name}} ->
  #       sync_recv(s, status, :prepare, buffer)
  #     err ->
  #       sync_recv(s, status, err, buffer)
  #   end
  # end
  #
  # defp execute_recv(s, status, query, buffer) do
  #   case msg_recv(s, :infinity, buffer) do
  #     {:ok, msg_data_row(values: values), buffer} ->
  #       execute_recv(s, status, query, [values], buffer)
  #     {:ok, msg_command_complete(tag: tag), buffer} ->
  #       complete(s, status, query, [], tag, buffer)
  #     {:ok, msg_empty_query(), buffer} ->
  #       sync_recv(s, status, %Sqlite.DbConnection.Result{}, buffer)
  #     {:ok, msg_error(fields: fields), buffer} ->
  #       sync_recv(s, status, Sqlite.DbConnection.Error.exception(postgres: fields), buffer)
  #     {:ok, msg, buffer} ->
  #       execute_recv(handle_msg(s, status, msg), status, query, buffer)
  #     {:disconnect, _, _} = dis ->
  #       dis
  #   end
  # end
  #
  # defp execute_recv(s, status, query, rows, buffer) do
  #   case msg_recv(s, :infinity, buffer) do
  #     {:ok, msg_data_row(values: values), buffer} ->
  #       execute_recv(s, status, query, [values | rows], buffer)
  #     {:ok, msg_command_complete(tag: tag), buffer} ->
  #       complete(s, status, query, rows, tag, buffer)
  #     {:ok, msg, buffer} ->
  #       execute_recv(handle_msg(s, status, msg), status, query, buffer)
  #     {:disconnect, _, _} = dis ->
  #       dis
  #   end
  # end
  #
  # defp complete(s, status, %Query{columns: nil}, [], tag, buffer) do
  #   {command, nrows} = decode_tag(tag)
  #   result =  %Sqlite.DbConnection.Result{command: command, num_rows: nrows || 0}
  #   sync_recv(s, status, result, buffer)
  # end
  # defp complete(s, status, query, rows, tag, buffer) do
  #   {command, nrows} = decode_tag(tag)
  #   %Query{columns: cols} = query
  #   # Fix for PostgreSQL 8.4 (doesn't include number of selected rows in tag)
  #   if is_nil(nrows) and command == :select do
  #     nrows = length(rows)
  #   end
  #   result = %Sqlite.DbConnection.Result{command: command, num_rows: nrows || 0,
  #                             rows: rows, columns: cols}
  #   sync_recv(s, status, result, buffer)
  # end
  #
  # ## close
  #
  # defp close(s, status, %Query{name: name}, result, buffer) do
  #   msgs = [
  #     msg_close(type: :statement, name: name),
  #     msg_flush() ]
  #   case msg_send(s, msgs, buffer) do
  #     :ok               -> close_recv(s, status, result, buffer)
  #     {:error, _} = err -> err
  #   end
  # end
  #
  # defp close_recv(s, status, result, buffer) do
  #   case msg_recv(s, :infinity, buffer) do
  #     {:ok, msg_close_complete(), buffer} ->
  #       ok(s, result, buffer)
  #     {:ok, msg_error(fields: fields), buffer} ->
  #       ok(s, Sqlite.DbConnection.Error.exception(postgres: fields), buffer)
  #     {:ok, msg, buffer} ->
  #       close_recv(handle_msg(s, status, msg), status, result, buffer)
  #     {:error, _} = err ->
  #       err
  #   end
  # end
  #
  # ## sync
  #
  # defp sync(s, status, buffer) do
  #   case msg_send(s, msg_sync(), buffer) do
  #     :ok               -> sync_recv(s, status, nil, buffer)
  #     {:error, _} = err -> err
  #   end
  # end
  #
  # ## transaction
  #
  # defp handle_transaction(name, postgres, opts, %{postgres: :naive} = s)
  # when postgres != :naive do
  #   handle_transaction(name, :naive, opts, s)
  # end
  # defp handle_transaction(name, postgres, opts, %{buffer: buffer} = s) do
  #   status = %{notify: notify(opts), sync: :sync}
  #   transaction_send(%{s | buffer: nil}, status, name, postgres, buffer)
  # end
  #
  # defp transaction_send(s, status, name, postgres, buffer) do
  #   msgs = [
  #     msg_bind(name_port: "", name_stat: name, param_formats: [], params: [], result_formats: []),
  #     msg_execute(name_port: "" , max_rows: 0),
  #     msg_sync()]
  #   case msg_send(s, msgs, buffer) do
  #     :ok ->
  #       transaction_recv(s, status, postgres, buffer)
  #     {:disconnect, _, _} = dis ->
  #       dis
  #   end
  # end
  #
  # defp transaction_recv(s, status, postgres, buffer) do
  #   case msg_recv(s, :infinity, buffer) do
  #     {:ok, msg_ready(), buffer} when postgres == :naive ->
  #       ok(s, nil, buffer)
  #     {:ok, msg_ready(status: ^postgres), buffer} ->
  #       ok(s, postgres, buffer)
  #     {:ok, msg_ready(status: postgres), buffer} ->
  #       sync_error(s, postgres, buffer)
  #     {:ok, msg_bind_complete(), buffer} ->
  #       transaction_recv(s, status, postgres, buffer)
  #     {:ok, msg_command_complete(), buffer} ->
  #       transaction_recv(s, status, postgres, buffer)
  #     {:ok, msg_error(fields: fields), buffer} when postgres == :naive ->
  #       err = Sqlite.DbConnection.Error.exception(postgres: fields)
  #       sync_recv(s, status, err, buffer)
  #     {:ok, msg_error(fields: fields), buffer} ->
  #       err = Sqlite.DbConnection.Error.exception(postgres: fields)
  #       disconnect(s, err, buffer)
  #     {:ok, msg, buffer} ->
  #       transaction_recv(handle_msg(s, status, msg), status, postgres, buffer)
  #     {:disconnect, _, _} = dis ->
  #       dis
  #   end
  # end
  #
  # ## data
  #
  # defp handle_data(s, opts, buffer) do
  #   data(s, %{notify: notify(opts)}, buffer)
  # end
  #
  # defp data(%{timeout: timeout} = s, status, buffer) do
  #   case msg_recv(s, timeout, buffer) do
  #     {:ok, msg_error(fields: fields), buffer} ->
  #       disconnect(s, Sqlite.DbConnection.Error.exception(postgres: fields), buffer)
  #     {:ok, msg, <<>>} ->
  #       activate(handle_msg(s, status, msg), <<>>)
  #     {:ok, msg, buffer} ->
  #       data(handle_msg(s, status, msg), status, buffer)
  #     {:disconnect, _, _} = dis ->
  #       dis
  #   end
  # end
  #
  # ## helpers
  #
  # defp notify(opts) do
  #   opts[:notify] || fn(_, _) -> :ok end
  # end
  #
  # defp columns(fields) do
  #   Enum.map(fields, fn row_field(type_oid: oid, name: name) ->
  #     {oid, name}
  #   end) |> :lists.unzip
  # end
  #
  # defp tag(:gen_tcp), do: :tcp
  # defp tag(:ssl), do: :ssl
  #
  # defp decode_tag(tag) do
  #   words = :binary.split(tag, " ", [:global])
  #   words = Enum.map(words, fn word ->
  #     case Integer.parse(word) do
  #       {num, ""} -> num
  #       :error -> word
  #     end
  #   end)
  #
  #   {command, nums} = Enum.split_while(words, &is_binary(&1))
  #   command = Enum.join(command, "_") |> String.downcase |> String.to_atom
  #   {command, List.last(nums)}
  # end
  #
  # # It is ok to use infinity timeout here if in client process as timer is
  # # running.
  # defp msg_recv(%{sock: {:gen_tcp, sock}} = s, timeout, :active_once) do
  #   receive do
  #     {:tcp, ^sock, buffer} ->
  #       msg_recv(s, timeout, buffer)
  #     {:tcp_closed, ^sock} ->
  #       disconnect(s, :tcp, "async_recv", :closed, :active_once)
  #     {:tcp_error, ^sock, reason} ->
  #       disconnect(s, :tcp, "async_recv", reason, :active_once)
  #   after
  #     timeout ->
  #       disconnect(s, :tcp, "async_recv", :timeout, :active_one)
  #   end
  # end
  # defp msg_recv(%{sock: {:ssl, sock}} = s, timeout, :active_once) do
  #   receive do
  #     {:ssl, ^sock, buffer} ->
  #       msg_recv(s, timeout, buffer)
  #     {:ssl_closed, ^sock} ->
  #       disconnect(s, :ssl, "async_recv", :closed, :active_once)
  #     {:ssl_error, ^sock, reason} ->
  #       disconnect(s, :ssl, "async_recv", reason, :active_once)
  #   after
  #     timeout ->
  #       disconnect(s, :ssl, "async_recv", :timeout, :active_once)
  #   end
  # end
  # defp msg_recv(s, timeout, buffer) do
  #   case msg_decode(buffer) do
  #     {:ok, _, _} = ok -> ok
  #     {:more, more}    -> msg_recv(s, timeout, buffer, more)
  #   end
  # end
  #
  # defp msg_recv(%{sock: {mod, sock}} = s, timeout, buffer, more) do
  #   case mod.recv(sock, more, timeout) do
  #     {:ok, data} ->
  #       msg_recv(s, timeout, buffer <> data)
  #     {:error, reason} ->
  #       disconnect(s, tag(mod), "recv", reason, buffer)
  #   end
  # end
  #
  # defp msg_decode(bin) when byte_size(bin) < 5 do
  #   {:more, 0}
  # end
  # defp msg_decode(<<type :: int8, size :: int32, rest :: binary>>) do
  #   size = size - 4
  #   case rest do
  #     <<body :: binary(size), rest :: binary>> ->
  #       {:ok, parse(body, type, size), rest}
  #     _ ->
  #       {:more, size - byte_size(rest)}
  #   end
  # end
  #
  # defp msg_send(s, msgs, buffer) when is_list(msgs) do
  #   binaries = Enum.reduce(msgs, [], &[&2 | encode_msg(&1)])
  #   do_send(s, binaries, buffer)
  # end
  #
  # defp msg_send(s, msg, buffer) do
  #   do_send(s, encode_msg(msg), buffer)
  # end
  #
  # defp do_send(%{sock: {mod, sock}} = s, data, buffer) do
  #   case mod.send(sock, data) do
  #     :ok ->
  #       :ok
  #     {:error, reason} ->
  #       disconnect(s, tag(mod), "send", reason, buffer)
  #   end
  # end
  #
  # defp handle_msg(s, _, msg_parameter(name: name, value: value)) do
  #   %{parameters: parameters} = s
  #   # Binaries likely part of much larger binary and only keeping name/value
  #   # over long term
  #   name = :binary.copy(name)
  #   value = :binary.copy(value)
  #   cond do
  #     is_reference(parameters) ->
  #       _ = Sqlite.DbConnection.Parameters.put(parameters, name, value)
  #       s
  #     is_map(parameters) ->
  #       %{s | parameters: Map.put(parameters, name, value)}
  #   end
  # end
  # defp handle_msg(s, status, msg_notify(channel: channel, payload: payload)) do
  #   %{notify: notify} = status
  #   notify.(channel, payload)
  #   s
  # end
  # defp handle_msg(s, _, msg_notice()) do
  #   # TODO: subscribers
  #   s
  # end
  #
  # defp ok(s, %Sqlite.DbConnection.Result{} = res, buffer) do
  #   {:ok, res, %{s | buffer: buffer}}
  # end
  # defp ok(s, %Sqlite.DbConnection.Query{} = query, buffer) do
  #   {:ok, query, %{s | buffer: buffer}}
  #  end
  # defp ok(s, nil, buffer) do
  #   {:ok, %{s | buffer: buffer}}
  # end
  # defp ok(s, %Sqlite.DbConnection.Error{} = err, buffer) do
  #   {:error, err, %{s | buffer: buffer}}
  # end
  # defp ok(s, :prepare, buffer) do
  #   {:prepare, %{s | buffer: buffer}}
  # end
  # defp ok(s, postgres, buffer) when postgres in [:idle, :transaction] do
  #   {:ok, %{s | postgres: postgres, buffer: buffer}}
  # end
  #
  # defp disconnect(s, tag, action, reason, buffer) do
  #   err = Sqlite.DbConnection.Error.exception(tag: tag, action: action, reason: reason)
  #   disconnect(s, err, buffer)
  # end
  #
  # defp disconnect(s, err, buffer) do
  #   {:disconnect, err, %{s | buffer: buffer}}
  # end

  defp reserved_error(query, s) do
    err = ArgumentError.exception("query #{inspect query} uses reserved name")
    {:error, err, s}
  end

  # # Query has completed so ok to use state timeout as message should either be
  # # buffer or in flight. sync_recv/4 used by simple queries so can't use
  # # :infinity.
  # defp sync_recv(s, %{sync: sync} = status, result, buffer) do
  #   %{postgres: postgres, timeout: timeout} = s
  #   case msg_recv(s, timeout, buffer) do
  #     {:ok, msg_ready(status: :idle), buffer} when postgres == :transaction ->
  #       sync_error(s, :idle, buffer)
  #     {:ok, msg_ready(status: :transaction), buffer} when postgres == :idle ->
  #       sync_error(s, :transaction, buffer)
  #     {:ok, msg_ready(status: :failed), buffer} when postgres == :idle ->
  #       sync_error(s, :failed, buffer)
  #     {:ok, msg_ready(), buffer} when sync == :sync ->
  #       ok(s, result, buffer)
  #     {:ok, msg_ready(), buffer} when sync == :sync_close ->
  #       close_recv(s, status, result, buffer)
  #     {:ok, msg, buffer} ->
  #       sync_recv(handle_msg(s, status, msg), status, result, buffer)
  #     {:disconnect, _, _} = dis ->
  #       dis
  #   end
  # end
  #
  # defp sync_error(s, postgres, buffer) do
  #   sync_error(%{s | buffer: buffer}, postgres)
  # end
  #
  # defp sync_error(s, postgres) do
  #   err = %Sqlite.DbConnection.Error{message: "unexpected postgres status: #{postgres}"}
  #   {:disconnect, err, s}
  # end
  #
  # defp recv_buffer(%{sock: {:gen_tcp, sock}} = s) do
  #   receive do
  #     {:tcp, ^sock, buffer} ->
  #       {:ok, %{s | buffer: buffer}}
  #     {:tcp_closed, ^sock} ->
  #       disconnect(s, :tcp, "async recv", :closed, "")
  #     {:tcp_error, ^sock, reason} ->
  #       disconnect(s, :tcp, "async_recv", reason, "")
  #   after
  #     0 ->
  #       {:ok, %{s | buffer: <<>>}}
  #   end
  # end
  # defp recv_buffer(%{sock: {:ssl, sock}} = s) do
  #   receive do
  #     {:ssl, ^sock, buffer} ->
  #       {:ok, %{s | buffer: buffer}}
  #     {:ssl_closed, ^sock} ->
  #       disconnect(s, :ssl, "async recv", :closed, "")
  #     {:ssl_error, ^sock, reason} ->
  #       disconnect(s, :ssl, "async recv", reason, "")
  #   after
  #     0 ->
  #       {:ok, %{s | buffer: <<>>}}
  #   end
  # end
  #
  # ## Fake [active: once] if buffer not empty
  # defp activate(s, <<>>) do
  #   case setopts(s, [active: :once], <<>>) do
  #     :ok  -> {:ok, %{s | buffer: :active_once}}
  #     other -> other
  #   end
  # end
  # defp activate(%{sock: {mod, sock}} = s, buffer) do
  #   _ = send(self(), {tag(mod), sock, buffer})
  #   {:ok, s}
  # end
  #
  # defp setopts(%{sock: {mod, sock}} = s, opts, buffer) do
  #   case setopts(mod, sock, opts) do
  #     :ok ->
  #       :ok
  #     {:error, reason} ->
  #       disconnect(s, tag(mod), "setopts", reason, buffer)
  #   end
  # end
  #
  # defp setopts(:gen_tcp, sock, opts), do: :inet.setopts(sock, opts)
  # defp setopts(:ssl, sock, opts), do: :ssl.setopts(sock, opts)
  #
  # defp sock_close(%{sock: {mod, sock}}), do: mod.close(sock)
  #
  # defp delete_parameters(%{parameters: ref}) when is_reference(ref) do
  #   Sqlite.DbConnection.Parameters.delete(ref)
  # end
  # defp delete_parameters(_), do: :ok
end

  #   end)
  #   {:ok, s}
  # end

  ## prepare

