func (n *NodeTx) RaftNodeFirst(address string) error {
	columns := []string{
		"id",
		"address",
	}
	values := []interface{}{
		int64(1),
		address,
	}
	id, err := n.query.UpsertObject(n.tx, "raft_nodes", columns, values)
	if err != nil {
		return errors.WithStack(err)
	}
	if id != 1 {
		return errors.Errorf("could not set raft node ID to 1")
	}
	return nil
}
RaftNodeFirst adds a the first node if the cluster. It ensures that the
database ID is 1, to match the server ID of first raft log entry.

This method is supposed to be called when there are no rows in raft_nodes,
and it will replace whatever existing row has ID 1.
package db
import (
	"github.com/pkg/errors"
	"github.com/spoke-d/thermionic/internal/db/database"
)
type RaftNode struct {
	ID      int64   
	Address string  
}
type NodeTx struct {
	tx    database.Tx  
	query Query
}
func NewNodeTx(tx database.Tx) *NodeTx {
	return NewNodeTxWithQuery(tx, queryShim{})
}
func NewNodeTxWithQuery(tx database.Tx, query Query) *NodeTx {
	return &NodeTx{
		tx:    tx,
		query: query,
	}
}
func (n *NodeTx) Config() (map[string]string, error) {
	return n.query.SelectConfig(n.tx, "config", "")
}
func (n *NodeTx) UpdateConfig(values map[string]string) error {
	return n.query.UpdateConfig(n.tx, "config", values)
}
func (n *NodeTx) RaftNodes() ([]RaftNode, error) {
	var nodes []RaftNode
	dest := func(i int) []interface{} {
		nodes = append(nodes, RaftNode{})
		return []interface{}{
			&nodes[i].ID,
			&nodes[i].Address,
		}
	}
	err := n.query.SelectObjects(n.tx, dest, "SELECT id, address FROM raft_nodes ORDER BY id")
	return nodes, errors.Wrap(err, "failed to fetch raft nodes")
}
func (n *NodeTx) RaftNodeAddresses() ([]string, error) {
	return n.query.SelectStrings(n.tx, "SELECT address FROM raft_nodes ORDER BY id")
}
func (n *NodeTx) RaftNodeAddress(id int64) (string, error) {
	stmt := "SELECT address FROM raft_nodes WHERE id=?"
	addresses, err := n.query.SelectStrings(n.tx, stmt, id)
	if err != nil {
		return "", errors.WithStack(err)
	}
	switch len(addresses) {
	case 0:
		return "", ErrNoSuchObject
	case 1:
		return addresses[0], nil
	default:
		return "", errors.Errorf("more than one match found")
	}
}