Skip to content
This repository was archived by the owner on Dec 15, 2023. It is now read-only.
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 11c8c85

Browse files
committedNov 26, 2021
feat: add subcommand
1 parent cc6f426 commit 11c8c85

File tree

6 files changed

+342
-98
lines changed

6 files changed

+342
-98
lines changed
 

‎.github/workflows/cargo_fmt.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@ jobs:
1313
- uses: actions/checkout@master
1414
- name: Install Rust
1515
run: rustup update stable && rustup default stable && rustup component add rustfmt
16-
- run: cargo fmt -- --check
16+
- run: cargo fmt -- --check && cargo clippy

‎Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,5 @@ path = "src/main.rs"
1818
dirs = "4.0.0"
1919
structopt = "0.3"
2020
rustyline = "9.0.0"
21-
iotdb = "0.0.5"
22-
#iotdb = { git = "https://github.com/francis-du/iotdb-rs.git", rev = "8551bd5" }
21+
#iotdb = "0.0.5"
22+
iotdb = { git = "https://github.com/francis-du/iotdb-rs.git", rev = "117158e"}

‎README.md

Lines changed: 154 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -50,30 +50,141 @@ FLAGS:
5050
-V, --version Prints version information
5151

5252
OPTIONS:
53-
--endpoint <endpoint> Set server endpoint, eg: host:port
54-
-H, --host <host> Set server hostname or IP
55-
--log-level <log-level> Set logger level
56-
-p, --password <password> Set user password
57-
-P, --port <port> Set server port
58-
-t, --timezone <timezone> Set timezone, eg: UTC+8
59-
-u, --user <user> Set user name
53+
-e, --endpoint <endpoint> Set server endpoint, eg: `localhost:6667`
54+
-H, --host <host> Set server hostname or ip address, eg: `127.0.0.1`
55+
-p, --password <password> Set user password
56+
-P, --port <port> Set server port
57+
-t, --timezone <timezone> Set timezone, eg: `UTC+8`
58+
-u, --user <user> Set user name
6059

6160
ARGS:
62-
<sql> Execute sql like `iotdb "SHOW STORAGE GROUP"`
61+
<sql> Execute single sql, eg: `iotdb "show storage group"`
6362

6463
SUBCOMMANDS:
65-
file TODO: Execute sql from file
64+
file Execute batch form sql file, eg: `iotdb file ddl.sql`
6665
help Prints this message or the help of the given subcommand(s)
6766

6867
```
6968

70-
1. Connect to server
69+
1. Connect to IoTDB server
70+
71+
- Use default username and password
72+
73+
```shell
74+
$ iotdb "SHOW STORAGE GROUP"
75+
+---------------+
76+
| storage group |
77+
+---------------+
78+
| root.ln |
79+
| root.sg1 |
80+
+---------------+
81+
```
82+
83+
- Specify parameters
84+
85+
```shell
86+
iotdb -u root -p root -e 127.0.0.1:6667 -t UTC+8
87+
88+
or
89+
90+
iotdb -u root -p root -H 127.0.0.1 -P 6667 -t UTC+8
91+
```
92+
93+
2. Execute single SQL interactively
94+
95+
```shell
96+
$ iotdb -u root -p root --e 127.0.0.1:6667 -t UTC+8
97+
98+
▀██▀ ▄▄█▀▀██ █▀▀██▀▀█ ▀██▀▀█▄ ▀██▀▀█▄
99+
██ ▄█▀ ██ ██ ██ ██ ██ ██
100+
██ ██ ██ ██ ██ ██ ██▀▀▀█▄
101+
██ ▀█▄ ██ ██ ██ ██ ██ ██
102+
▄██▄ ▀▀█▄▄▄█▀ ▄██▄ ▄██▄▄▄█▀ ▄██▄▄▄█▀
103+
104+
IOTDB#(127.0.0.1:6667)> SHOW STORAGE GROUP
105+
+---------------+
106+
| storage group |
107+
+---------------+
108+
| root.ln |
109+
| root.sg1 |
110+
+---------------+
111+
```
112+
113+
3. Execute sql from the specified sql file
114+
115+
```shell
116+
$iotdb file tests/create_and_insert.sql
117+
<div align="center">
118+
119+
![Logo](https://raw.githubusercontent.com/francis-du/iotdb-rs/main/iotdb-rs.png)
120+
121+
<h1>iotdb-cli</h1>
122+
<h3>Apache IotDB CLI Client written in Rust</h3>
123+
124+
[![License](https://img.shields.io/badge/license-Apache%202.0-blue?style=flat-square&color=%23E5531A)](https://github.com/francis-du/iotdb-cli/blob/main/LICENSE)
125+
[![Rust Build](https://img.shields.io/github/workflow/status/francis-du/iotdb-cli/cargo-test?label=build&style=flat-square)](https://github.com/francis-du/iotdb-cli/actions?query=workflow%3Acargo-test)
126+
[![Crates Publish](https://img.shields.io/github/workflow/status/francis-du/iotdb-cli/cargo-publish?label=publish&style=flat-square)](https://github.com/francis-du/iotdb-cli/actions?query=workflow%3Acargo-publish)
127+
128+
</div>
129+
130+
---
131+
132+
![Alt](https://repobeats.axiom.co/api/embed/86055cf67fcaac9e6e93c64c9a7a1630686ceda1.svg "Repobeats analytics image")
133+
134+
## Installation
135+
136+
1. Using `Cargo`
71137

72138
```shell
73-
iotdb -u root -p root --endpoint 127.0.0.1:6667 -t UTC+8
139+
cargo install iotdb-cli
74140
```
75141

76-
2. Exec SQL
142+
2. From binary
143+
144+
Download latest `iotdb` binary from [here](https://github.com/francis-du/iotdb-cli/releases/latest/).
145+
146+
## Usage
147+
148+
```shell
149+
iotdb -h
150+
```
151+
152+
```shell
153+
154+
▀██▀ ▄▄█▀▀██ █▀▀██▀▀█ ▀██▀▀█▄ ▀██▀▀█▄
155+
██ ▄█▀ ██ ██ ██ ██ ██ ██
156+
██ ██ ██ ██ ██ ██ ██▀▀▀█▄
157+
██ ▀█▄ ██ ██ ██ ██ ██ ██
158+
▄██▄ ▀▀█▄▄▄█▀ ▄██▄ ▄██▄▄▄█▀ ▄██▄▄▄█▀ 0.0.1
159+
160+
USAGE:
161+
iotdb [FLAGS] [OPTIONS] [sql] [SUBCOMMAND]
162+
163+
FLAGS:
164+
-d, --debug Enable debug mode
165+
-h, --help Prints help information
166+
-V, --version Prints version information
167+
168+
OPTIONS:
169+
-e, --endpoint <endpoint> Set server endpoint, eg: `localhost:6667`
170+
-H, --host <host> Set server hostname or ip address, eg: `127.0.0.1`
171+
-p, --password <password> Set user password
172+
-P, --port <port> Set server port
173+
-t, --timezone <timezone> Set timezone, eg: `UTC+8`
174+
-u, --user <user> Set user name
175+
176+
ARGS:
177+
<sql> Execute single sql, eg: `iotdb "show storage group"`
178+
179+
SUBCOMMANDS:
180+
file Execute batch form sql file, eg: `iotdb file ddl.sql`
181+
help Prints this message or the help of the given subcommand(s)
182+
183+
```
184+
185+
1. Connect to IoTDB server
186+
187+
- Use default username and password
77188

78189
```shell
79190
$ iotdb "SHOW STORAGE GROUP"
@@ -85,8 +196,20 @@ $ iotdb "SHOW STORAGE GROUP"
85196
+---------------+
86197
```
87198

199+
- Specify parameters
200+
88201
```shell
89-
$ iotdb -u root -p root --endpoint 127.0.0.1:6667 -t UTC+8
202+
iotdb -u root -p root -e 127.0.0.1:6667 -t UTC+8
203+
204+
or
205+
206+
iotdb -u root -p root -H 127.0.0.1 -P 6667 -t UTC+8
207+
```
208+
209+
2. Execute single SQL interactively
210+
211+
```shell
212+
$ iotdb -u root -p root --e 127.0.0.1:6667 -t UTC+8
90213
91214
▀██▀ ▄▄█▀▀██ █▀▀██▀▀█ ▀██▀▀█▄ ▀██▀▀█▄
92215
██ ▄█▀ ██ ██ ██ ██ ██ ██
@@ -103,6 +226,24 @@ IOTDB#(127.0.0.1:6667)> SHOW STORAGE GROUP
103226
+---------------+
104227
```
105228

229+
3. Execute sql from the specified sql file
230+
231+
```shell
232+
$iotdb file tests/create_and_insert.sql
233+
Statements: [
234+
"DELETE STORAGE GROUP root.test;",
235+
"CREATE TIMESERIES root.test.status WITH DATATYPE=BOOLEAN, ENCODING=PLAIN;",
236+
"CREATE TIMESERIES root.test.temperature WITH DATATYPE=FLOAT, ENCODING=RLE;",
237+
"INSERT INTO root.test(timestamp, status)\n values (1637960249484, true);",
238+
"INSERT INTO root.test(timestamp, status, temperature)\n values (1637960256493, false, 20.71);",
239+
"INSERT INTO root.test(timestamp, status, temperature)\n values (1637960261494, true, 32.43);",
240+
"INSERT INTO root.test(timestamp, status, temperature)\n values (1637960272492, false, 28.66);",
241+
"INSERT INTO root.test(timestamp, status, temperature)\n values (1637960272492, true, 22.61);",
242+
"INSERT INTO root.test(timestamp, status, temperature)\n values (1637960296493, false, 28.66);",
243+
]
244+
22:00:54 [INFO] Execute statements "Execute batch statements successfully"
245+
```
246+
106247
# License
107248

108249
[Apache License 2.0](LICENSE)

‎docs/src/get-started.md

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -50,30 +50,25 @@ FLAGS:
5050
-V, --version Prints version information
5151

5252
OPTIONS:
53-
--endpoint <endpoint> Set server endpoint, eg: host:port
54-
-H, --host <host> Set server hostname or IP
55-
--log-level <log-level> Set logger level
56-
-p, --password <password> Set user password
57-
-P, --port <port> Set server port
58-
-t, --timezone <timezone> Set timezone, eg: UTC+8
59-
-u, --user <user> Set user name
53+
-e, --endpoint <endpoint> Set server endpoint, eg: `localhost:6667`
54+
-H, --host <host> Set server hostname or ip address, eg: `127.0.0.1`
55+
-p, --password <password> Set user password
56+
-P, --port <port> Set server port
57+
-t, --timezone <timezone> Set timezone, eg: `UTC+8`
58+
-u, --user <user> Set user name
6059

6160
ARGS:
62-
<sql> Execute sql like `iotdb "SHOW STORAGE GROUP"`
61+
<sql> Execute single sql, eg: `iotdb "show storage group"`
6362

6463
SUBCOMMANDS:
65-
file TODO: Execute sql from file
64+
file Execute batch form sql file, eg: `iotdb file ddl.sql`
6665
help Prints this message or the help of the given subcommand(s)
6766

6867
```
6968

70-
1. Connect to server
69+
1. Connect to IoTDB server
7170

72-
```shell
73-
iotdb -u root -p root --endpoint 127.0.0.1:6667 -t UTC+8
74-
```
75-
76-
2. Exec SQL
71+
- Use default username and password
7772

7873
```shell
7974
$ iotdb "SHOW STORAGE GROUP"
@@ -85,8 +80,20 @@ $ iotdb "SHOW STORAGE GROUP"
8580
+---------------+
8681
```
8782

83+
- Specify parameters
84+
85+
```shell
86+
iotdb -u root -p root -e 127.0.0.1:6667 -t UTC+8
87+
88+
or
89+
90+
iotdb -u root -p root -H 127.0.0.1 -P 6667 -t UTC+8
91+
```
92+
93+
2. Execute single SQL interactively
94+
8895
```shell
89-
$ iotdb -u root -p root --endpoint 127.0.0.1:6667 -t UTC+8
96+
$ iotdb -u root -p root --e 127.0.0.1:6667 -t UTC+8
9097

9198
▀██▀ ▄▄█▀▀██ █▀▀██▀▀█ ▀██▀▀█▄ ▀██▀▀█▄
9299
██ ▄█▀ ██ ██ ██ ██ ██ ██
@@ -103,6 +110,24 @@ IOTDB#(127.0.0.1:6667)> SHOW STORAGE GROUP
103110
+---------------+
104111
```
105112

113+
3. Execute sql from the specified sql file
114+
115+
```shell
116+
$iotdb file tests/create_and_insert.sql
117+
Statements: [
118+
"DELETE STORAGE GROUP root.test;",
119+
"CREATE TIMESERIES root.test.status WITH DATATYPE=BOOLEAN, ENCODING=PLAIN;",
120+
"CREATE TIMESERIES root.test.temperature WITH DATATYPE=FLOAT, ENCODING=RLE;",
121+
"INSERT INTO root.test(timestamp, status)\n values (1637960249484, true);",
122+
"INSERT INTO root.test(timestamp, status, temperature)\n values (1637960256493, false, 20.71);",
123+
"INSERT INTO root.test(timestamp, status, temperature)\n values (1637960261494, true, 32.43);",
124+
"INSERT INTO root.test(timestamp, status, temperature)\n values (1637960272492, false, 28.66);",
125+
"INSERT INTO root.test(timestamp, status, temperature)\n values (1637960272492, true, 22.61);",
126+
"INSERT INTO root.test(timestamp, status, temperature)\n values (1637960296493, false, 28.66);",
127+
]
128+
22:00:54 [INFO] Execute statements "Execute batch statements successfully"
129+
```
130+
106131
# License
107132

108-
[Apache License 2.0](LICENSE)
133+
[Apache License 2.0](LICENSE)

‎src/main.rs

Lines changed: 113 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
use iotdb::{Config, Endpoint, Session};
1+
use iotdb::{Config, ConfigBuilder, Endpoint, Session};
22
use rustyline::error::ReadlineError;
33
use rustyline::Editor;
4-
use std::path::PathBuf;
4+
use std::path::{Path, PathBuf};
55
use structopt::StructOpt;
66

77
const ASCII_NAME: &str = "
@@ -15,10 +15,10 @@ const ASCII_NAME: &str = "
1515
#[derive(StructOpt, Debug)]
1616
#[structopt(name = ASCII_NAME)]
1717
struct Opt {
18-
/// Execute sql like `iotdb "SHOW STORAGE GROUP"`
18+
/// Execute single sql, eg: `iotdb "show storage group"`
1919
sql: Option<String>,
2020

21-
/// Set server hostname or IP
21+
/// Set server hostname or ip address, eg: `127.0.0.1`
2222
#[structopt(short = "H", long)]
2323
host: Option<String>,
2424

@@ -34,18 +34,14 @@ struct Opt {
3434
#[structopt(short, long)]
3535
password: Option<String>,
3636

37-
/// Set server endpoint, eg: host:port
38-
#[structopt(long)]
37+
/// Set server endpoint, eg: `localhost:6667`
38+
#[structopt(short, long)]
3939
endpoint: Option<String>,
4040

41-
/// Set timezone, eg: UTC+8
41+
/// Set timezone, eg: `UTC+8`
4242
#[structopt(short, long)]
4343
timezone: Option<String>,
4444

45-
/// Set logger level
46-
#[structopt(long)]
47-
log_level: Option<String>,
48-
4945
/// Enable debug mode
5046
#[structopt(short, long)]
5147
debug: bool,
@@ -57,79 +53,88 @@ struct Opt {
5753

5854
#[derive(Debug, StructOpt)]
5955
enum Command {
60-
///TODO: Execute sql from file
56+
/// Execute batch form sql file, eg: `iotdb file ddl.sql`
6157
File { path: String },
6258
}
6359

6460
fn main() {
65-
let mut config = Config::new();
66-
match Opt::from_args() {
67-
Opt {
68-
sql,
69-
host,
70-
port,
71-
user,
72-
password,
73-
endpoint,
74-
timezone,
75-
log_level,
76-
debug,
77-
command,
78-
} => {
79-
// set endpoint
80-
if host.is_some() && port.is_some() {
81-
config.endpoint(host.unwrap().as_str(), port.unwrap().as_str());
82-
}
83-
84-
if endpoint.is_some() {
85-
let endpoint = endpoint.unwrap().as_str().parse::<Endpoint>().unwrap();
86-
config.endpoint(endpoint.host.as_str(), endpoint.port.as_str());
87-
}
61+
let mut builder = ConfigBuilder::new();
62+
// match Opt::from_args() {
63+
let Opt {
64+
sql,
65+
host,
66+
port,
67+
user,
68+
password,
69+
endpoint,
70+
timezone,
71+
debug,
72+
command,
73+
} = Opt::from_args();
74+
75+
// set endpoint
76+
if let Some(endpoint) = endpoint {
77+
let endpoint = endpoint.as_str().parse::<Endpoint>().unwrap();
78+
builder.endpoint(endpoint.host.as_str(), endpoint.port.as_str());
79+
} else if let Some(host) = host {
80+
if let Some(port) = port {
81+
builder.endpoint(host.as_str(), port.as_str());
82+
}
83+
}
8884

89-
// user and password
90-
if user.is_some() && password.is_some() {
91-
config.user(user.unwrap().as_str());
92-
config.password(password.unwrap().as_str());
93-
}
85+
// user and password
86+
if let Some(user) = user {
87+
if let Some(password) = password {
88+
builder.user(user.as_str());
89+
builder.password(password.as_str());
90+
}
91+
}
9492

95-
// timezone
96-
if timezone.is_some() {
97-
config.zone_id(timezone.unwrap().as_str());
98-
}
93+
// timezone
94+
if let Some(timezone) = timezone {
95+
builder.time_zone(timezone.as_str());
96+
}
9997

100-
// log level
101-
if log_level.is_some() {
102-
config.log_level(log_level.unwrap().as_str());
103-
}
104-
config.debug(debug).build();
98+
// enable debug mode
99+
builder.debug(debug);
105100

106-
let prompt = format!("IOTDB#({})> ", config.clone().endpoint.to_string());
107-
let mut session = open_session(config);
101+
let prompt = format!("IOTDB#({})> ", builder.build().endpoint.to_string());
102+
let mut session = open_session(builder.build());
108103

109-
match command {
110-
None => {
111-
if sql.is_none() {
112-
readline(session, prompt)
104+
match command {
105+
None => {
106+
if let Some(sql) = sql {
107+
session.sql(sql.as_str()).unwrap().show()
108+
} else {
109+
readline(session, prompt)
110+
}
111+
}
112+
Some(command) => match command {
113+
Command::File { path } => {
114+
let sql_file = Path::new(&path);
115+
if sql_file.exists() {
116+
if !sql_file.is_file() || !path.ends_with(".sql") {
117+
println!("ERROR: {:?} is not a sql file", sql_file);
113118
} else {
114-
session.sql(sql.unwrap().as_str()).unwrap().show()
119+
println!("Statements: {:#?}", sql_file_reader(sql_file));
120+
session.exec_batch(sql_file_reader(sql_file));
115121
}
122+
} else {
123+
println!("ERROR: {:?} not exist", sql_file);
116124
}
117-
Some(command) => match command {
118-
Command::File { .. } => todo!(),
119-
},
120125
}
121-
}
126+
},
122127
}
123128
}
124129

125130
fn open_session(config: Config) -> Session {
126-
Session::new(config.clone()).open().unwrap()
131+
Session::new(config).open().unwrap()
127132
}
128133

129134
fn readline(mut session: Session, prompt: String) {
130135
println!("{}", ASCII_NAME);
131136
let his_file: PathBuf = dirs::home_dir()
132-
.unwrap_or(PathBuf::from("/home"))
137+
.unwrap_or_else(|| PathBuf::from("/home"))
133138
.join(".iotdb_his");
134139

135140
let mut rl = Editor::<()>::new();
@@ -150,9 +155,8 @@ fn readline(mut session: Session, prompt: String) {
150155
break;
151156
}
152157

153-
match session.sql(sql.as_str()) {
154-
Ok(mut ds) => ds.show(),
155-
Err(_) => {}
158+
if let Ok(mut ds) = session.sql(sql.as_str()) {
159+
ds.show()
156160
}
157161
}
158162
Err(ReadlineError::Interrupted) => {
@@ -174,3 +178,47 @@ fn readline(mut session: Session, prompt: String) {
174178
rl.save_history(his_file.as_path()).unwrap();
175179
}
176180
}
181+
182+
fn sql_file_reader(path: &Path) -> Vec<String> {
183+
use std::fs;
184+
use std::io;
185+
use std::io::BufRead;
186+
187+
let mut batch_sql: Vec<String> = vec![];
188+
match fs::File::open(path) {
189+
Ok(file) => {
190+
let sql_lines = io::BufReader::new(file)
191+
.lines()
192+
.map(|s| s.unwrap_or_default())
193+
.filter(|s| !s.is_empty())
194+
.filter(|s| !s.starts_with("--"))
195+
.filter(|s| s.len() != 1)
196+
.map(|s| s.trim().to_string())
197+
.collect::<Vec<String>>();
198+
199+
let mut tmp_string: String = String::new();
200+
let mut is_tmp = false;
201+
for line in sql_lines {
202+
if line.ends_with(';') {
203+
if is_tmp {
204+
tmp_string.push_str(line.as_str());
205+
batch_sql.push(tmp_string.clone());
206+
tmp_string.clear();
207+
is_tmp = false;
208+
} else {
209+
batch_sql.push(line);
210+
}
211+
} else {
212+
tmp_string.push_str(line.as_str());
213+
tmp_string.push_str("\n ");
214+
is_tmp = true;
215+
}
216+
}
217+
batch_sql
218+
}
219+
Err(error) => {
220+
println!("ERROR: {:?}", error);
221+
vec![]
222+
}
223+
}
224+
}

‎tests/create_and_insert.sql

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
-- DELETE STORAGE GROUP
2+
DELETE STORAGE GROUP root.test;
3+
4+
-- CREATE TIMESERIES
5+
CREATE TIMESERIES root.test.status WITH DATATYPE=BOOLEAN, ENCODING=PLAIN;
6+
CREATE TIMESERIES root.test.temperature WITH DATATYPE=FLOAT, ENCODING=RLE;
7+
8+
-- INSERT INTO DATA
9+
INSERT INTO root.test(timestamp, status)
10+
values (1637960249484, true);
11+
12+
-- INSERT INTO DATA
13+
INSERT INTO root.test(timestamp, status, temperature)
14+
values (1637960256493, false, 20.71);
15+
16+
-- INSERT INTO DATA
17+
INSERT INTO root.test(timestamp, status, temperature)
18+
values (1637960261494, true, 32.43);
19+
20+
-- INSERT INTO DATA
21+
INSERT INTO root.test(timestamp, status, temperature)
22+
values (1637960272492, false, 28.66);
23+
24+
-- INSERT INTO DATA
25+
INSERT INTO root.test(timestamp, status, temperature)
26+
values (1637960272492, true, 22.61);
27+
28+
-- INSERT INTO DATA
29+
INSERT INTO root.test(timestamp, status, temperature)
30+
values (1637960296493, false, 28.66);

0 commit comments

Comments
 (0)
This repository has been archived.