-
Notifications
You must be signed in to change notification settings - Fork 2
/
chc.go
152 lines (120 loc) · 5 KB
/
chc.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
146
147
148
149
150
151
152
package main
// some inspirations:
// native clickhouse cli
// https://github.com/yandex/ClickHouse/blob/master/dbms/src/Server/Client.cpp
// python unofficial cli
// https://github.com/hatarist/clickhouse-cli
// https://github.com/kshvakov/clickhouse - binary, native protocol
// Other Go-based cli for (other ) databases
// https://github.com/influxdata/influxdb/blob/master/cmd/influx/main.go
// https://github.com/influxdata/influxdb/blob/master/cmd/influx/cli/cli.go
// https://github.com/rqlite/rqlite/blob/master/cmd/rqlite/main.go
// https://github.com/cockroachdb/cockroach/blob/master/pkg/cli/start.go
// TODO:
// promptForPassword, password from env
// configs?
// multiline / multiquery mode
// settings from command line
// native protocol support
import (
"fmt"
"log"
"os"
"strings"
"github.com/jessevdk/go-flags"
"github.com/mattn/go-isatty"
)
const (
formatTabSeparated = "TabSeparated"
formatVertical = "Vertical"
)
var opts struct {
Help bool `long:"help" description:"produce help message"`
Host string `long:"host" short:"h" default:"localhost" description:"server host"`
Port uint `long:"port" default:"8123" description:"server port"`
Protocol string `long:"protocol" default:"http" description:"protocol (http or https are supported)"`
User string `long:"user" short:"u" default:"default" description:"user"`
Password string `long:"password" description:"password"`
Query string `long:"query" short:"q" description:"query"`
Database string `long:"database" short:"d" default:"default" description:"database"`
Pager string `long:"pager" description:"pager"`
Multiline bool `long:"multiline" short:"m" description:"multiline"`
Multiquery bool `long:"multiquery" short:"n" description:"multiquery"`
Format string `long:"format" short:"f" description:"default output format"`
Vertical bool `long:"vertical" short:"E" description:"vertical output format, same as\n--format=Vertical or FORMAT Vertical or\n\\G at end of command"`
Time bool `long:"time" short:"t" description:"print query execution time to stderr in\nnon-interactive mode (for benchmarks)"`
Stacktrace bool `long:"stacktrace" description:"print stack traces of exceptions"`
Progress bool `long:"progress" description:"print progress even in non-interactive\nmode"`
Version bool `long:"version" short:"V" description:"print version information and exit"`
Echo bool `long:"echo" description:"in batch mode, print query before execution"`
}
var clickhouseSetting = make(map[string]string)
const versionString = "v0.1.6"
func parseArgs() {
argsParser := flags.NewNamedParser("chc (ClickHouse CLI portable)", flags.Default&^flags.HelpFlag) // , HelpFlag
argsParser.ShortDescription = "Unofficial portable ClickHouse CLI"
argsParser.LongDescription = "works with ClickHouse from MacOS/Windows/Linux without extra dependencies"
argsParser.AddGroup("Main Options", "Main Options", &opts)
args, err := argsParser.Parse()
if err != nil {
panic(err)
}
if opts.Help {
argsParser.WriteHelp(os.Stdout)
os.Exit(1)
}
if opts.Version {
println("chc " + versionString)
os.Exit(1)
}
if opts.Vertical && len(opts.Format) == 0 {
opts.Format = formatVertical
}
// if !opts.Multiline {
// chcOutput.printServiceMsg("Only multiline mode is currently supported\n")
// }
if opts.Multiquery {
chcOutput.printServiceMsg("Multiquery mode is not supported yet\n")
}
switch opts.Protocol {
case "https":
if argsParser.FindOptionByLongName("port").IsSetDefault() {
opts.Port = 8443
}
case "http":
default:
chcOutput.printServiceMsg("Protocol " + opts.Protocol + " is not supported.\n")
os.Exit(1)
}
if len(args) > 0 {
chcOutput.printServiceMsg("Following arguments were ignored:" + strings.Join(args, " ") + "\n")
}
}
/// TODO - process settings
func main() {
parseArgs()
if isatty.IsTerminal(os.Stdin.Fd()) && isatty.IsTerminal(os.Stdout.Fd()) && len(opts.Query) == 0 {
opts.Progress = true
opts.Time = true
fmt.Printf("chc (ClickHouse CLI portable) %s\n", versionString)
fmt.Printf("Connecting to database %s at %s as user %s.\n", opts.Database, getHost(), opts.User)
serverVersion, err := getServerVersion()
if err != nil {
log.Fatalln(err)
}
fmt.Printf("Connected to ClickHouse server version %s.\n\n", serverVersion)
if len(opts.Pager) > 0 {
chcOutput.setPager(opts.Pager)
}
if opts.Format == "" {
opts.Format = "PrettyCompact"
}
promptLoop()
fmt.Println("Bye.")
} else {
if opts.Format == "" {
opts.Format = formatTabSeparated
}
fireQuery(opts.Query, opts.Format, false)
}
}