-
Notifications
You must be signed in to change notification settings - Fork 8
/
message.go
145 lines (120 loc) · 3.52 KB
/
message.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package database
import (
"bytes"
"encoding/json"
"fmt"
"sort"
"github.com/kwilteam/kwil-db/core/types"
clientType "github.com/kwilteam/kwil-db/core/types/client"
"github.com/kwilteam/kwil-db/core/types/transactions"
"github.com/olekukonko/tablewriter"
)
// NOTE: I feel those types are better to be defined in the core/client package
// but also not sure, because how to display the response is a cli thing
//
// A possible way to do this is to define actual response types in core/client package
// and wrap them in cli package?
// respDBList represent databases belong to an owner in cli
type respDBList struct {
Info []*types.DatasetIdentifier
// owner is the owner configured in cli
owner []byte
}
func (d *respDBList) MarshalJSON() ([]byte, error) {
return json.Marshal(d.Info)
}
func (d *respDBList) MarshalText() ([]byte, error) {
if len(d.Info) == 0 {
return []byte(fmt.Sprintf("No databases found for '%x'.", d.owner)), nil
}
var msg bytes.Buffer
if len(d.owner) == 0 {
msg.WriteString("Databases:\n")
} else {
msg.WriteString(fmt.Sprintf("Databases belonging to '%x':\n", d.owner))
}
for i, db := range d.Info {
msg.WriteString(fmt.Sprintf(" DBID: %s\n", db.DBID))
msg.WriteString(fmt.Sprintf(" Name: %s\n", db.Name))
msg.WriteString(fmt.Sprintf(" Owner: %x", db.Owner))
if i != len(d.Info)-1 {
msg.WriteString("\n")
}
}
return msg.Bytes(), nil
}
// respRelations is a slice of maps that represent the relations(from set theory)
// of a database in cli
type respRelations struct {
// to avoid recursive call of MarshalJSON
Data *clientType.Records
}
func (r *respRelations) MarshalJSON() ([]byte, error) {
return json.Marshal(r.Data.ExportString())
}
func (r *respRelations) MarshalText() ([]byte, error) {
data := r.Data.ExportString()
if len(data) == 0 {
return []byte("No data to display."), nil
}
// collect headers
headers := make([]string, 0)
for k := range data[0] {
headers = append(headers, k)
}
// keep the headers in a sorted order
sort.Strings(headers)
var buf bytes.Buffer
table := tablewriter.NewWriter(&buf)
table.SetHeader(headers)
table.SetAutoFormatHeaders(false)
table.SetBorders(
tablewriter.Border{Left: true, Top: false, Right: true, Bottom: false})
for _, row := range data {
rs := make([]string, 0)
for _, h := range headers {
rs = append(rs, row[h])
}
table.Append(rs)
}
table.Render()
return buf.Bytes(), nil
}
// respSchema is used to represent a database schema in cli
type respSchema struct {
Schema *transactions.Schema
}
func (s *respSchema) MarshalJSON() ([]byte, error) {
return json.Marshal(s.Schema)
}
func (s *respSchema) MarshalText() ([]byte, error) {
// TODO: make output more readable
var msg bytes.Buffer
// now we print the metadata
msg.WriteString("Tables:\n")
for _, t := range s.Schema.Tables {
msg.WriteString(fmt.Sprintf(" %s\n", t.Name))
msg.WriteString(" Columns:\n")
for _, c := range t.Columns {
msg.WriteString(fmt.Sprintf(" %s\n", c.Name))
msg.WriteString(fmt.Sprintf(" Type: %s\n", c.Type))
for _, a := range c.Attributes {
msg.WriteString(fmt.Sprintf(" %s\n", a.Type))
if a.Value != "" {
msg.WriteString(fmt.Sprintf(" %s\n", fmt.Sprint(a.Value)))
}
}
}
}
// print queries
msg.WriteString("Actions:\n")
for _, q := range s.Schema.Actions {
public := "private"
if q.Public {
public = "public"
}
msg.WriteString(fmt.Sprintf(" %s (%s)\n", q.Name, public))
msg.WriteString(fmt.Sprintf(" Inputs: %s\n", q.Inputs))
}
return msg.Bytes(), nil
}