From ffff375c402b37ae0382d8448d4c52b2750aad4c Mon Sep 17 00:00:00 2001 From: francis-du Date: Sun, 28 Nov 2021 07:08:18 +0800 Subject: [PATCH 01/13] feat: refactored the cli, and added new sub-commands and usage --- .github/workflows/cargo_fmt.yml | 4 +- Cargo.toml | 6 +- README.md | 28 +++- docs/src/get-started.md | 28 +++- src/cmd.rs | 250 ++++++++++++++++++++++++++++++++ src/main.rs | 224 ++-------------------------- src/opt.rs | 63 ++++++++ src/static/usage_info | 49 +++++++ src/sub_cmd.rs | 54 +++++++ 9 files changed, 479 insertions(+), 227 deletions(-) create mode 100644 src/cmd.rs create mode 100644 src/opt.rs create mode 100644 src/static/usage_info create mode 100644 src/sub_cmd.rs diff --git a/.github/workflows/cargo_fmt.yml b/.github/workflows/cargo_fmt.yml index 85768a2..b9460bc 100644 --- a/.github/workflows/cargo_fmt.yml +++ b/.github/workflows/cargo_fmt.yml @@ -13,4 +13,6 @@ jobs: - uses: actions/checkout@master - name: Install Rust run: rustup update stable && rustup default stable && rustup component add rustfmt - - run: cargo fmt -- --check && cargo clippy \ No newline at end of file + - run: | + cargo fmt -- --check + cargo clippy \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 97aa7f1..ff40eab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ version = "0.0.2" edition = "2021" license = "Apache-2.0" readme = "README.md" -authors = ["francis-du "] +authors = ["github.com/francis-du "] repository = "https://github.com/francis-du/iotdb-cli" documentation = "https://docs.rs/iotdb-cli" description = "Apache IotDB CLI Client written in Rust" @@ -18,5 +18,5 @@ path = "src/main.rs" dirs = "4.0.0" structopt = "0.3" rustyline = "9.0.0" -iotdb = "0.0.6" -#iotdb = { git = "https://github.com/francis-du/iotdb-rs.git", rev = "117158e"} \ No newline at end of file +#iotdb = "0.0.6" +iotdb = { git = "https://github.com/francis-du/iotdb-rs.git", rev = "1572bb5"} \ No newline at end of file diff --git a/README.md b/README.md index 0b24d36..c1c9c54 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,10 @@ iotdb -h ██ ▄█▀ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██▀▀▀█▄ ██ ▀█▄ ██ ██ ██ ██ ██ ██ -▄██▄ ▀▀█▄▄▄█▀ ▄██▄ ▄██▄▄▄█▀ ▄██▄▄▄█▀ 0.0.1 +▄██▄ ▀▀█▄▄▄█▀ ▄██▄ ▄██▄▄▄█▀ ▄██▄▄▄█▀ + +Author: github.com/francis-du +Version: iotdb-cli 0.0.2 USAGE: iotdb [FLAGS] [OPTIONS] [sql] [SUBCOMMAND] @@ -51,6 +54,7 @@ FLAGS: OPTIONS: -e, --endpoint Set server endpoint, eg: `localhost:6667` + -f, --file Execute batch form sql file, eg: `iotdb -f ddl.sql` -H, --host Set server hostname or ip address, eg: `127.0.0.1` -p, --password Set user password -P, --port Set server port @@ -61,8 +65,10 @@ ARGS: Execute single sql, eg: `iotdb "show storage group"` SUBCOMMANDS: - file Execute batch form sql file, eg: `iotdb file ddl.sql` - help Prints this message or the help of the given subcommand(s) + file Execute batch form sql file, eg: `iotdb file ddl.sql` + help Prints this message or the help of the given subcommand(s) + update Update binary(TODO) + usage Print usage info ``` @@ -101,6 +107,12 @@ $ iotdb -u root -p root --e 127.0.0.1:6667 -t UTC+8 ██ ▀█▄ ██ ██ ██ ██ ██ ██ ▄██▄ ▀▀█▄▄▄█▀ ▄██▄ ▄██▄▄▄█▀ ▄██▄▄▄█▀ +Author: github.com/francis-du +Version: iotdb-cli v0.0.2 +Usage: + 1. Print usage info: `?` or `help` + 2. Exec system command on OS: `!ps` + 3. Exit: `exit` or `quit` or `Ctrl-C` or `Ctrl-D` IOTDB#(127.0.0.1:6667)> SHOW STORAGE GROUP +---------------+ | storage group | @@ -114,6 +126,8 @@ IOTDB#(127.0.0.1:6667)> SHOW STORAGE GROUP ```shell $ iotdb file tests/create_and_insert.sql +$ iotdb -file tests/create_and_insert.sql +$ iotdb -f tests/create_and_insert.sql Statements: [ "DELETE STORAGE GROUP root.test;", "CREATE TIMESERIES root.test.status WITH DATATYPE=BOOLEAN, ENCODING=PLAIN;", @@ -125,7 +139,13 @@ Statements: [ "INSERT INTO root.test(timestamp, status, temperature)\n values (1637960272492, true, 22.61);", "INSERT INTO root.test(timestamp, status, temperature)\n values (1637960296493, false, 28.66);", ] -22:00:54 [INFO] Execute statements "Execute batch statements successfully" +23:00:23 [INFO] Execute batch statements successfully +``` + +4. Print usage info + +```shell +$ iotdb usage ``` # License diff --git a/docs/src/get-started.md b/docs/src/get-started.md index 0b24d36..c1c9c54 100644 --- a/docs/src/get-started.md +++ b/docs/src/get-started.md @@ -39,7 +39,10 @@ iotdb -h ██ ▄█▀ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██▀▀▀█▄ ██ ▀█▄ ██ ██ ██ ██ ██ ██ -▄██▄ ▀▀█▄▄▄█▀ ▄██▄ ▄██▄▄▄█▀ ▄██▄▄▄█▀ 0.0.1 +▄██▄ ▀▀█▄▄▄█▀ ▄██▄ ▄██▄▄▄█▀ ▄██▄▄▄█▀ + +Author: github.com/francis-du +Version: iotdb-cli 0.0.2 USAGE: iotdb [FLAGS] [OPTIONS] [sql] [SUBCOMMAND] @@ -51,6 +54,7 @@ FLAGS: OPTIONS: -e, --endpoint Set server endpoint, eg: `localhost:6667` + -f, --file Execute batch form sql file, eg: `iotdb -f ddl.sql` -H, --host Set server hostname or ip address, eg: `127.0.0.1` -p, --password Set user password -P, --port Set server port @@ -61,8 +65,10 @@ ARGS: Execute single sql, eg: `iotdb "show storage group"` SUBCOMMANDS: - file Execute batch form sql file, eg: `iotdb file ddl.sql` - help Prints this message or the help of the given subcommand(s) + file Execute batch form sql file, eg: `iotdb file ddl.sql` + help Prints this message or the help of the given subcommand(s) + update Update binary(TODO) + usage Print usage info ``` @@ -101,6 +107,12 @@ $ iotdb -u root -p root --e 127.0.0.1:6667 -t UTC+8 ██ ▀█▄ ██ ██ ██ ██ ██ ██ ▄██▄ ▀▀█▄▄▄█▀ ▄██▄ ▄██▄▄▄█▀ ▄██▄▄▄█▀ +Author: github.com/francis-du +Version: iotdb-cli v0.0.2 +Usage: + 1. Print usage info: `?` or `help` + 2. Exec system command on OS: `!ps` + 3. Exit: `exit` or `quit` or `Ctrl-C` or `Ctrl-D` IOTDB#(127.0.0.1:6667)> SHOW STORAGE GROUP +---------------+ | storage group | @@ -114,6 +126,8 @@ IOTDB#(127.0.0.1:6667)> SHOW STORAGE GROUP ```shell $ iotdb file tests/create_and_insert.sql +$ iotdb -file tests/create_and_insert.sql +$ iotdb -f tests/create_and_insert.sql Statements: [ "DELETE STORAGE GROUP root.test;", "CREATE TIMESERIES root.test.status WITH DATATYPE=BOOLEAN, ENCODING=PLAIN;", @@ -125,7 +139,13 @@ Statements: [ "INSERT INTO root.test(timestamp, status, temperature)\n values (1637960272492, true, 22.61);", "INSERT INTO root.test(timestamp, status, temperature)\n values (1637960296493, false, 28.66);", ] -22:00:54 [INFO] Execute statements "Execute batch statements successfully" +23:00:23 [INFO] Execute batch statements successfully +``` + +4. Print usage info + +```shell +$ iotdb usage ``` # License diff --git a/src/cmd.rs b/src/cmd.rs new file mode 100644 index 0000000..fbcaaab --- /dev/null +++ b/src/cmd.rs @@ -0,0 +1,250 @@ +use crate::opt::{Cli, SubCmd}; +use crate::sub_cmd::{sql_file_reader, update}; +use crate::{ASCII_NAME, AUTHORS, PKG_NAME, VERSION}; +use iotdb::{Config, ConfigBuilder, Endpoint, Session}; +use rustyline::error::ReadlineError; +use rustyline::Editor; +use std::io; +use std::io::Write; +use std::path::{Path, PathBuf}; +use std::process::{Command, Output, Stdio}; + +/// Run IoTDB CLI +pub fn run() { + let Cli { + sql, + file, + host, + port, + user, + password, + endpoint, + timezone, + debug, + sub_cmd, + } = Cli::new(); + + let mut conf_builder = ConfigBuilder::new(); + // set endpoint + if let Some(endpoint) = endpoint { + let endpoint = endpoint.as_str().parse::().unwrap(); + conf_builder.endpoint(endpoint.host.as_str(), endpoint.port.as_str()); + } else if let Some(host) = host { + if let Some(port) = port { + conf_builder.endpoint(host.as_str(), port.as_str()); + } + } + + // user and password + if let Some(user) = user { + if let Some(password) = password { + conf_builder.user(user.as_str()); + conf_builder.password(password.as_str()); + } + } + + // timezone + if let Some(timezone) = timezone { + conf_builder.time_zone(timezone.as_str()); + } + + // enable debug mode + conf_builder.debug(debug); + let conf = conf_builder.build(); + + // exec batch + if let Some(file_path) = file { + exec_batch_from_file(conf, file_path.as_str()); + std::process::exit(0); + } + + // open session + let prompt = format!("IOTDB#({})> ", conf.endpoint.to_string()); + let mut session = open_session(conf.clone()); + + // sub command + match sub_cmd { + None => { + if let Some(sql) = sql { + session.sql(sql.as_str()).unwrap().show() + } else { + readline(session, prompt) + } + } + Some(sub_cmd) => match sub_cmd { + // exec batch + SubCmd::File { file_path } => { + if let Some(file_path) = file_path { + exec_batch_from_file(conf, &file_path); + } + } + SubCmd::Usage => { + print_usage_info(); + } + SubCmd::Update => { + update(); + } + }, + } +} + +/// Open a IoTDB session +fn open_session(config: Config) -> Session { + Session::new(config).open().unwrap() +} + +/// readline +fn readline(mut session: Session, prompt: String) { + let fore_space = " "; + println!( + "{}\nAuthor: {}\nVersion: {} v{}\nUsage:\n{}\ + 1. Print usage info: `?` or `help` \n{}\ + 2. Exec system command on OS: `!ps`\n{}\ + 3. Exit: `exit` or `quit` or `Ctrl-C` or `Ctrl-D`", + ASCII_NAME, AUTHORS, PKG_NAME, VERSION, fore_space, fore_space, fore_space + ); + let his_file: PathBuf = dirs::home_dir() + .unwrap_or_else(|| PathBuf::from("/home")) + .join(".iotdb_his"); + + let mut rl = Editor::<()>::new(); + if his_file.as_path().exists() { + rl.load_history(his_file.as_path()).unwrap(); + } + + let mut tmp_sql: String = String::new(); + loop { + // TODO: is_open is invalid and needs to be fixed in iotdb-rs + if session.is_close() { + session = session.open().unwrap(); + } + let readline; + if !tmp_sql.is_empty() { + readline = rl.readline(">> "); + } else { + readline = rl.readline(prompt.as_str()); + } + + match readline { + Ok(mut sql) => { + if sql.contains("exit") || sql.contains("quit") { + session.close().unwrap(); + rl.add_history_entry(sql.as_str()); + rl.save_history(his_file.as_path()).unwrap(); + break; + } + + if sql.trim().is_empty() { + continue; + } + + if sql.eq("?") || sql.eq("help") { + rl.add_history_entry(sql.as_str()); + print_usage_info(); + continue; + } + + if sql.starts_with('!') { + rl.add_history_entry(sql.as_str()); + sql.remove(0); + exec_shell_cmd(sql); + continue; + } + + if sql.ends_with(';') { + if tmp_sql.is_empty() { + if let Ok(mut ds) = session.sql(sql.as_str()) { + ds.show() + } + } else { + sql = format!("{}{}", tmp_sql, sql); + println!("```sql\n{}\n```", sql); + if let Ok(mut ds) = session.sql(sql.as_str()) { + ds.show() + } + tmp_sql.clear(); + } + rl.add_history_entry(sql.as_str()); + } else { + tmp_sql.push_str(sql.trim()); + tmp_sql.push('\n') + } + } + Err(ReadlineError::Interrupted) => { + session.close().unwrap(); + println!("Ctrl-C"); + break; + } + Err(ReadlineError::Eof) => { + session.close().unwrap(); + println!("Ctrl-D"); + break; + } + Err(err) => { + session.close().unwrap(); + println!("Error: {:?}", err); + break; + } + } + rl.save_history(his_file.as_path()).unwrap(); + } +} + +// Exec batch from sql file +fn exec_batch_from_file(conf: Config, file_path: &str) { + let file = Path::new(&file_path); + let mut session = open_session(conf); + if file.exists() { + if !file.is_file() || !file_path.ends_with(".sql") { + println!("ERROR: {:?} is not a sql file", file_path); + } else { + println!("Statements: {:#?}", sql_file_reader(file_path)); + session.exec_batch(sql_file_reader(file_path)); + session.close().unwrap(); + } + } else { + println!("ERROR: {:?} not exist", file_path); + } +} + +/// Print help info +fn print_usage_info() { + let help_info = include_str!("static/usage_info"); + println!("{}", help_info); +} + +/// Exec shell command +#[allow(unused_assignments)] +fn exec_shell_cmd(cmd_str: String) { + let mut cmd_str = cmd_str; + if cfg!(target_os = "windows") { + cmd_str = "dir c:\\tmp".to_string(); + } + + if cfg!(target_os = "windows") { + let output = Command::new("cmd") + .arg("/c") + .arg(cmd_str) + .stdout(Stdio::piped()) + .output() + .expect("cmd exec error!"); + output_to_stdout(output); + } else { + let output = Command::new("sh") + .arg("-c") + .arg(cmd_str) + .stdout(Stdio::piped()) + .output() + .expect("sh exec error!"); + output_to_stdout(output); + }; +} + +/// Command output to stdout +fn output_to_stdout(output: Output) { + if output.status.success() { + io::stdout().write_all(&output.stdout).unwrap(); + } else { + io::stdout().write_all(&output.stderr).unwrap(); + } +} diff --git a/src/main.rs b/src/main.rs index c177e4b..2ca129d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,10 +1,11 @@ -use iotdb::{Config, ConfigBuilder, Endpoint, Session}; -use rustyline::error::ReadlineError; -use rustyline::Editor; -use std::path::{Path, PathBuf}; -use structopt::StructOpt; - -const ASCII_NAME: &str = " +mod cmd; +mod opt; +mod sub_cmd; + +pub const VERSION: &str = env!("CARGO_PKG_VERSION"); +pub const AUTHORS: &str = env!("CARGO_PKG_AUTHORS"); +pub const PKG_NAME: &str = env!("CARGO_PKG_NAME"); +pub const ASCII_NAME: &str = " ▀██▀ ▄▄█▀▀██ █▀▀██▀▀█ ▀██▀▀█▄ ▀██▀▀█▄ ██ ▄█▀ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██▀▀▀█▄ @@ -12,213 +13,6 @@ const ASCII_NAME: &str = " ▄██▄ ▀▀█▄▄▄█▀ ▄██▄ ▄██▄▄▄█▀ ▄██▄▄▄█▀\t "; -#[derive(StructOpt, Debug)] -#[structopt(name = ASCII_NAME)] -struct Opt { - /// Execute single sql, eg: `iotdb "show storage group"` - sql: Option, - - /// Set server hostname or ip address, eg: `127.0.0.1` - #[structopt(short = "H", long)] - host: Option, - - /// Set server port - #[structopt(short = "P", long)] - port: Option, - - /// Set user name - #[structopt(short, long)] - user: Option, - - /// Set user password - #[structopt(short, long)] - password: Option, - - /// Set server endpoint, eg: `localhost:6667` - #[structopt(short, long)] - endpoint: Option, - - /// Set timezone, eg: `UTC+8` - #[structopt(short, long)] - timezone: Option, - - /// Enable debug mode - #[structopt(short, long)] - debug: bool, - - /// Subcommands - #[structopt(subcommand)] - command: Option, -} - -#[derive(Debug, StructOpt)] -enum Command { - /// Execute batch form sql file, eg: `iotdb file ddl.sql` - File { path: String }, -} - fn main() { - let mut builder = ConfigBuilder::new(); - // match Opt::from_args() { - let Opt { - sql, - host, - port, - user, - password, - endpoint, - timezone, - debug, - command, - } = Opt::from_args(); - - // set endpoint - if let Some(endpoint) = endpoint { - let endpoint = endpoint.as_str().parse::().unwrap(); - builder.endpoint(endpoint.host.as_str(), endpoint.port.as_str()); - } else if let Some(host) = host { - if let Some(port) = port { - builder.endpoint(host.as_str(), port.as_str()); - } - } - - // user and password - if let Some(user) = user { - if let Some(password) = password { - builder.user(user.as_str()); - builder.password(password.as_str()); - } - } - - // timezone - if let Some(timezone) = timezone { - builder.time_zone(timezone.as_str()); - } - - // enable debug mode - builder.debug(debug); - - let prompt = format!("IOTDB#({})> ", builder.build().endpoint.to_string()); - let mut session = open_session(builder.build()); - - match command { - None => { - if let Some(sql) = sql { - session.sql(sql.as_str()).unwrap().show() - } else { - readline(session, prompt) - } - } - Some(command) => match command { - Command::File { path } => { - let sql_file = Path::new(&path); - if sql_file.exists() { - if !sql_file.is_file() || !path.ends_with(".sql") { - println!("ERROR: {:?} is not a sql file", sql_file); - } else { - println!("Statements: {:#?}", sql_file_reader(sql_file)); - session.exec_batch(sql_file_reader(sql_file)); - } - } else { - println!("ERROR: {:?} not exist", sql_file); - } - } - }, - } -} - -fn open_session(config: Config) -> Session { - Session::new(config).open().unwrap() -} - -fn readline(mut session: Session, prompt: String) { - println!("{}", ASCII_NAME); - let his_file: PathBuf = dirs::home_dir() - .unwrap_or_else(|| PathBuf::from("/home")) - .join(".iotdb_his"); - - let mut rl = Editor::<()>::new(); - if his_file.as_path().exists() { - rl.load_history(his_file.as_path()).unwrap(); - } - loop { - let readline = rl.readline(prompt.as_str()); - match readline { - Ok(sql) => { - if sql.trim().is_empty() { - continue; - } - - rl.add_history_entry(sql.as_str()); - if sql.contains("exit") || sql.contains("quit") { - session.close().unwrap(); - break; - } - - if let Ok(mut ds) = session.sql(sql.as_str()) { - ds.show() - } - } - Err(ReadlineError::Interrupted) => { - session.close().unwrap(); - println!("Ctrl-C"); - break; - } - Err(ReadlineError::Eof) => { - session.close().unwrap(); - println!("Ctrl-D"); - break; - } - Err(err) => { - session.close().unwrap(); - println!("Error: {:?}", err); - break; - } - } - rl.save_history(his_file.as_path()).unwrap(); - } -} - -fn sql_file_reader(path: &Path) -> Vec { - use std::fs; - use std::io; - use std::io::BufRead; - - let mut batch_sql: Vec = vec![]; - match fs::File::open(path) { - Ok(file) => { - let sql_lines = io::BufReader::new(file) - .lines() - .map(|s| s.unwrap_or_default()) - .filter(|s| !s.is_empty()) - .filter(|s| !s.starts_with("--")) - .filter(|s| s.len() != 1) - .map(|s| s.trim().to_string()) - .collect::>(); - - let mut tmp_string: String = String::new(); - let mut is_tmp = false; - for line in sql_lines { - if line.ends_with(';') { - if is_tmp { - tmp_string.push_str(line.as_str()); - batch_sql.push(tmp_string.clone()); - tmp_string.clear(); - is_tmp = false; - } else { - batch_sql.push(line); - } - } else { - tmp_string.push_str(line.as_str()); - tmp_string.push_str("\n "); - is_tmp = true; - } - } - batch_sql - } - Err(error) => { - println!("ERROR: {:?}", error); - vec![] - } - } + cmd::run(); } diff --git a/src/opt.rs b/src/opt.rs new file mode 100644 index 0000000..b593079 --- /dev/null +++ b/src/opt.rs @@ -0,0 +1,63 @@ +use crate::{ASCII_NAME, AUTHORS, PKG_NAME}; +use structopt::StructOpt; + +#[derive(StructOpt, Debug)] +#[structopt(name = format ! ("{}\nAuthor: {}\nVersion: {}", ASCII_NAME, AUTHORS, PKG_NAME))] +pub struct Cli { + /// Execute single sql, eg: `iotdb "show storage group"` + pub sql: Option, + + /// Execute batch form sql file, eg: `iotdb -f ddl.sql` + #[structopt(short = "f", long)] + pub file: Option, + + /// Set server hostname or ip address, eg: `127.0.0.1` + #[structopt(short = "H", long)] + pub host: Option, + + /// Set server port + #[structopt(short = "P", long)] + pub port: Option, + + /// Set user name + #[structopt(short, long)] + pub user: Option, + + /// Set user password + #[structopt(short, long)] + pub password: Option, + + /// Set server endpoint, eg: `localhost:6667` + #[structopt(short, long)] + pub endpoint: Option, + + /// Set timezone, eg: `UTC+8` + #[structopt(short, long)] + pub timezone: Option, + + /// Enable debug mode + #[structopt(short, long)] + pub debug: bool, + + /// Subcommands + #[structopt(subcommand)] + pub sub_cmd: Option, +} + +#[derive(Debug, StructOpt)] +pub enum SubCmd { + /// Execute batch form sql file, eg: `iotdb file ddl.sql` + File { file_path: Option }, + + /// Print usage info + Usage, + + /// Update binary(TODO) + Update, +} + +impl Cli { + pub fn new() -> Self { + Cli::from_args() + } +} diff --git a/src/static/usage_info b/src/static/usage_info new file mode 100644 index 0000000..b28d18a --- /dev/null +++ b/src/static/usage_info @@ -0,0 +1,49 @@ +Usage info: + DDL & DQL: + 01. `set storage group to root.ln` + 02. `show storage group` | `show storage group root.*` + 03. `DELETE STORAGE GROUP root.ln` | `DELETE STORAGE GROUP root.*` + 04. `create timeseries root.ln.wf01.wt01.status with datatype=BOOLEAN,encoding=PLAIN` + 05. `CREATE ALIGNED TIMESERIES root.ln.wf01.GPS(latitude FLOAT encoding=PLAIN compressor=SNAPPY, longitude FLOAT encoding=PLAIN compressor=SNAPPY)` + 06. `delete timeseries root.ln.wf01.wt01.status` | `delete timeseries root.ln.wf01.wt01.*` + 07. `show timeseries root.*` + 08. `COUNT TIMESERIES root.*` + 09. `SHOW CHILD PATHS pathPattern` + 10. `SHOW CHILD NODES pathPattern` + 11. `COUNT NODES root.** LEVEL=2` + 12. `show devices` | `show devices root.ln.*` + 13. `create schema template temp1(GPS(lat FLOAT encoding=Gorilla, lon FLOAT encoding=Gorilla) compression=SNAPPY, status BOOLEAN encoding=PLAIN compression=SNAPPY)` + 14. `set schema template temp1 to root.ln.wf01` + 15. `unset schema template temp1 from root.beijing` + 16. `set ttl to root.ln 3600000` + 17. `unset ttl to root.ln` + 18. `SHOW ALL TTL` | `SHOW TTL ON StorageGroupNames` + DML: + 01. `insert into root.ln.wf02.wt02(timestamp,status) values(1,true)` + 02. `select temperature from root.ln.wf01.wt01 where time < 2017-11-01T00:08:00.000` + 03. `select s1, - s1, s2, + s2, s1 + s2, s1 - s2, s1 * s2, s1 / s2, s1 % s2 from root.sg.d1` + 04. `select count(status) from root.ln.wf01.wt01` + 05. `select from where time = fill([previous, ], …)` + 06. `select last [COMMA ]* from < PrefixPath > [COMMA < PrefixPath >]* ` + 07. `select * from root.sg.device where value like '%cc%'` + 08. `select s1 as temperature, s2 as speed from root.ln.wf01.wt01` + 09. `select status, temperature from root.ln.wf01.wt01 limit 10` + 10. `select * from root.ln.* where time <= 2017-11-01T00:01:00 WITHOUT NULL ANY` + 11. `select * from root.ln.* where time <= 2017-11-01T00:01:00 align by device` + 12. `delete from root.ln.wf02.wt02.status where time<=2017-11-01T16:26:00` + 13. `delete from root.ln.wf02.wt02 where time <= 2017-11-01T16:26:00` + 14. `DELETE PARTITION root.ln 0,1,2` + Other: + 01. `FLUSH` | `FLUSH root.ln` + 02. `MERGE` | `FULL MERGE` + 03. `CLEAR CACHE` + 04. `SET SYSTEM TO READONLY` + 05. `CREATE SNAPSHOT FOR SCHEMA` + 06. `KILL QUERY ` +Useful links: + 01. What is IoTDB: https://iotdb.apache.org/UserGuide/Master/IoTDB-Introduction/What-is-IoTDB.html + 02. SQL guide: https://iotdb.apache.org/UserGuide/Master/IoTDB-SQL-Language/DDL-Data-Definition-Language.html + 03. Data concept: https://iotdb.apache.org/UserGuide/Master/Data-Concept/Data-Model-and-Terminology.html + 04. Advanced features: https://iotdb.apache.org/UserGuide/Master/Advanced-Features/UDF-User-Defined-Function.html + 04. About iotdb-rs: https://github.com/francis-du/iotdb-rs + 05. About iotdb-cli: https://github.com/francis-du/iotdb-cli \ No newline at end of file diff --git a/src/sub_cmd.rs b/src/sub_cmd.rs new file mode 100644 index 0000000..aebced1 --- /dev/null +++ b/src/sub_cmd.rs @@ -0,0 +1,54 @@ +use std::fs; +use std::io; +use std::io::BufRead; + +pub fn sql_file_reader(file_path: &str) -> Vec { + let mut batch_sql: Vec = vec![]; + match fs::File::open(file_path) { + Ok(file) => { + let sql_lines = io::BufReader::new(file) + .lines() + .map(|s| s.unwrap_or_default()) + .filter(|s| !s.is_empty()) + .filter(|s| !s.starts_with("--")) + .filter(|s| s.len() != 1) + .map(|s| s.trim().to_string()) + .collect::>(); + + let mut tmp_str: String = String::new(); + for line in sql_lines { + if line.ends_with(';') { + if tmp_str.is_empty() { + batch_sql.push(line); + } else { + batch_sql.push(format!("{}{}", tmp_str, line)); + tmp_str.clear(); + } + } else { + tmp_str.push_str(line.as_str()); + tmp_str.push_str("\n "); + } + } + batch_sql + } + Err(error) => { + println!("ERROR: {:?}", error); + vec![] + } + } +} + +#[allow(dead_code)] +pub fn update() { + todo!() +} + +#[allow(dead_code)] +pub fn download_latest() { + todo!() +} + +#[allow(dead_code)] +pub fn replace_binary() { + todo!() +} From 9f7583ad6b30444fe9634d17fdf39f0d87245e12 Mon Sep 17 00:00:00 2001 From: francis-du Date: Sun, 28 Nov 2021 07:17:02 +0800 Subject: [PATCH 02/13] fix: readme and doc install with cargo --- README.md | 10 +++++++++- docs/src/get-started.md | 10 +++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c1c9c54..d55a699 100644 --- a/README.md +++ b/README.md @@ -19,8 +19,16 @@ 1. Using `Cargo` +- Latest released version + +```shell +cargo install -f iotdb-cli +``` + +- Latest dev version + ```shell -cargo install iotdb-cli +cargo install -f --git https://github.com/francis-du/iotdb-cli.git ``` 2. From binary diff --git a/docs/src/get-started.md b/docs/src/get-started.md index c1c9c54..d55a699 100644 --- a/docs/src/get-started.md +++ b/docs/src/get-started.md @@ -19,8 +19,16 @@ 1. Using `Cargo` +- Latest released version + +```shell +cargo install -f iotdb-cli +``` + +- Latest dev version + ```shell -cargo install iotdb-cli +cargo install -f --git https://github.com/francis-du/iotdb-cli.git ``` 2. From binary From 70af54b7bf617d01f26687402b4c205fbc1f8b6b Mon Sep 17 00:00:00 2001 From: francis-du Date: Sun, 28 Nov 2021 16:24:09 +0800 Subject: [PATCH 03/13] feat: add install script --- install.sh | 141 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100755 install.sh diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..86f1fe9 --- /dev/null +++ b/install.sh @@ -0,0 +1,141 @@ +#!/bin/sh + +NO_COLOR=$'\e[0m' +ERROR=$'\e[0;31m'"ERROR: " +INFO=$'\e[0;32m'"INFO: " +WARN=$'\e[0;33m'"WARN: " +LATEST_RELEASE="https://api.github.com/repos/francis-du/iotdb-cli/releases/latest" +BIN_PATH="/usr/local/bin" +VERSION=$1 + +set_version() { + if [ ! -n "${VERSION}" ]; then + status=$(curl -Is ${LATEST_RELEASE} | grep 'HTTP' | awk '{print $2}') + if [ $status != 200 ]; then + echo "${ERROR}Install failed, reason: $(curl -s ${LATEST_RELEASE} | grep '"message":' | awk '{print $0}')" + exit 1 + fi + + if command -v curl &>/dev/null; then + VERSION=$(curl -s ${LATEST_RELEASE} | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/') + else + if command -v wget &>/dev/null; then + VERSION=$(wget ${LATEST_RELEASE} | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/') + else + echo "${ERROR}Please install wget or curl${NO_COLOR}" + exit 1 + fi + fi + fi +} + +download() { + local url=$1 + local file_name=$2 + + if command -v curl &>/dev/null; then + if [ -n $file_name ]; then + if [ ! -f $file_name ]; then + curl -L -f -# -C0 -o $file_name "$url" + else + command $file_name -h + echo "${WARN}'$file_name' exists" + echo "${WARN}Please run command 'iotdb' or '${file_name}'" + exit 1 + fi + else + curl -L -f -# -OC0 "$url" --progress-bar + fi + else + if command -v wget &>/dev/null; then + command wget --spider -q "$url" + if [ $? == 0 ]; then + wget --spider -q "$url" + if [ -n $file_name ]; then + if [ ! -f $file_name ]; then + wget -q -c --show-progress "$url" -O $file_name + else + command $file_name -h + echo "${WARN}'$file_name' exists" + echo "${WARN}Please run command 'iotdb' or '${file_name}'" + exit 1 + fi + else + wget -q -c --show-progress "$url" + fi + else + echo "${ERROR}Download failed from $url" + exit 1 + fi + else + echo "${ERROR}Please install wget or curl${NO_COLOR}" + exit 1 + fi + fi +} + +function install() { + set_version + echo "${INFO}Version: ${VERSION}" + echo "${INFO}Download from '${LATEST_RELEASE}'" + asset_base_url="https://github.com/francis-du/iotdb-cli/releases/download/${VERSION}" + case "$(uname -s)" in + Linux*) + bin_name="${BIN_PATH}/iotdb" + asset_url="$asset_base_url/iotdb-linux" + echo "${INFO}Assert url '${asset_url}'" + download $asset_url $bin_name + + if [ -f "${bin_name}" ]; then + chmod +x $bin_name + echo "${INFO}Please run command 'iotdb' or '${bin_name}'" + else + echo "${ERROR}Install failed" + fi + ;; + Darwin*) + bin_name="${BIN_PATH}/iotdb" + asset_url="${asset_base_url}/iotdb-mac" + echo "${INFO}Assert url '${asset_url}'" + download $asset_url $bin_name + + if [ -f "${bin_name}" ]; then + chmod +x $bin_name + echo "${INFO}Please run command 'iotdb' or '${bin_name}'" + else + echo "${ERROR}Install failed" + fi + ;; + CYGWIN*) + # TODO: Need to be test + bin_name="${BIN_PATH}/iotdb.exe" + asset_url="$asset_base_url/iotdb.exe" + echo "${INFO}Assert url '${asset_url}'" + download $asset_url $bin_name + + if [ -f "${bin_name}" ]; then + echo "${INFO}Please run command 'iotdb.exe' or '${bin_name}'" + else + echo "${ERROR}Install failed" + fi + ;; + MINGW*) + # TODO: Need to be test + bin_name="${BIN_PATH}/iotdb.exe" + asset_url=$asset_base_url"/iotdb.exe" + echo "${INFO}Assert url '${asset_url}'" + download $asset_url $bin_name + + if [ -f "${bin_name}" ]; then + echo "${INFO}Please run command 'iotdb.exe' or '${bin_name}'" + else + echo "${ERROR}Install failed" + fi + ;; + *) + echo "${ERROR}Unknown OS" + ;; + esac +} + +install From 5f4d7f3d27c27e411f04c9dbf3b7a606b13f1dc0 Mon Sep 17 00:00:00 2001 From: francis-du Date: Sun, 28 Nov 2021 16:44:41 +0800 Subject: [PATCH 04/13] doc: add download shell command --- README.md | 14 ++++++++++++-- docs/src/get-started.md | 14 ++++++++++++-- install.sh | 13 +++++++------ 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index d55a699..7a739e2 100644 --- a/README.md +++ b/README.md @@ -31,9 +31,19 @@ cargo install -f iotdb-cli cargo install -f --git https://github.com/francis-du/iotdb-cli.git ``` -2. From binary +2. From [binary](https://github.com/francis-du/iotdb-cli/releases/latest) -Download latest `iotdb` binary from [here](https://github.com/francis-du/iotdb-cli/releases/latest/). +```shell +curl -s https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | sh + +curl -s https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | sh -s -- x.x.x +``` + +```shell +wget -qO- https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | sh + +wget -qO- https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | sh -s -- x.x.x +``` ## Usage diff --git a/docs/src/get-started.md b/docs/src/get-started.md index d55a699..7a739e2 100644 --- a/docs/src/get-started.md +++ b/docs/src/get-started.md @@ -31,9 +31,19 @@ cargo install -f iotdb-cli cargo install -f --git https://github.com/francis-du/iotdb-cli.git ``` -2. From binary +2. From [binary](https://github.com/francis-du/iotdb-cli/releases/latest) -Download latest `iotdb` binary from [here](https://github.com/francis-du/iotdb-cli/releases/latest/). +```shell +curl -s https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | sh + +curl -s https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | sh -s -- x.x.x +``` + +```shell +wget -qO- https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | sh + +wget -qO- https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | sh -s -- x.x.x +``` ## Usage diff --git a/install.sh b/install.sh index 86f1fe9..b44ee88 100755 --- a/install.sh +++ b/install.sh @@ -4,6 +4,7 @@ NO_COLOR=$'\e[0m' ERROR=$'\e[0;31m'"ERROR: " INFO=$'\e[0;32m'"INFO: " WARN=$'\e[0;33m'"WARN: " +LATEST="https://github.com/francis-du/iotdb-cli/releases/latest" LATEST_RELEASE="https://api.github.com/repos/francis-du/iotdb-cli/releases/latest" BIN_PATH="/usr/local/bin" VERSION=$1 @@ -68,7 +69,7 @@ download() { exit 1 fi else - echo "${ERROR}Please install wget or curl${NO_COLOR}" + echo "${ERROR}Please install 'wget' or 'curl'" exit 1 fi fi @@ -77,13 +78,13 @@ download() { function install() { set_version echo "${INFO}Version: ${VERSION}" - echo "${INFO}Download from '${LATEST_RELEASE}'" + echo "${INFO}Latest release '${LATEST}'" asset_base_url="https://github.com/francis-du/iotdb-cli/releases/download/${VERSION}" case "$(uname -s)" in Linux*) bin_name="${BIN_PATH}/iotdb" asset_url="$asset_base_url/iotdb-linux" - echo "${INFO}Assert url '${asset_url}'" + echo "${INFO}Download from '${asset_url}'" download $asset_url $bin_name if [ -f "${bin_name}" ]; then @@ -96,7 +97,7 @@ function install() { Darwin*) bin_name="${BIN_PATH}/iotdb" asset_url="${asset_base_url}/iotdb-mac" - echo "${INFO}Assert url '${asset_url}'" + echo "${INFO}Download from '${asset_url}'" download $asset_url $bin_name if [ -f "${bin_name}" ]; then @@ -110,7 +111,7 @@ function install() { # TODO: Need to be test bin_name="${BIN_PATH}/iotdb.exe" asset_url="$asset_base_url/iotdb.exe" - echo "${INFO}Assert url '${asset_url}'" + echo "${INFO}Download from '${asset_url}'" download $asset_url $bin_name if [ -f "${bin_name}" ]; then @@ -123,7 +124,7 @@ function install() { # TODO: Need to be test bin_name="${BIN_PATH}/iotdb.exe" asset_url=$asset_base_url"/iotdb.exe" - echo "${INFO}Assert url '${asset_url}'" + echo "${INFO}Download from '${asset_url}'" download $asset_url $bin_name if [ -f "${bin_name}" ]; then From 2b739e52aa7154880221a69f606f43d73217875a Mon Sep 17 00:00:00 2001 From: francis-du Date: Sun, 28 Nov 2021 16:46:41 +0800 Subject: [PATCH 05/13] doc: fix typo --- README.md | 8 +------- docs/src/get-started.md | 8 +------- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 7a739e2..0629148 100644 --- a/README.md +++ b/README.md @@ -19,22 +19,16 @@ 1. Using `Cargo` -- Latest released version - ```shell cargo install -f iotdb-cli -``` -- Latest dev version - -```shell cargo install -f --git https://github.com/francis-du/iotdb-cli.git ``` 2. From [binary](https://github.com/francis-du/iotdb-cli/releases/latest) ```shell -curl -s https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | sh +curl -s https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | sh curl -s https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | sh -s -- x.x.x ``` diff --git a/docs/src/get-started.md b/docs/src/get-started.md index 7a739e2..0629148 100644 --- a/docs/src/get-started.md +++ b/docs/src/get-started.md @@ -19,22 +19,16 @@ 1. Using `Cargo` -- Latest released version - ```shell cargo install -f iotdb-cli -``` -- Latest dev version - -```shell cargo install -f --git https://github.com/francis-du/iotdb-cli.git ``` 2. From [binary](https://github.com/francis-du/iotdb-cli/releases/latest) ```shell -curl -s https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | sh +curl -s https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | sh curl -s https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | sh -s -- x.x.x ``` From 3f1508990507cf9279226d24c46a29f3b72795e0 Mon Sep 17 00:00:00 2001 From: francis-du Date: Mon, 29 Nov 2021 14:15:30 +0800 Subject: [PATCH 06/13] fix: sun cmd session bug --- .github/workflows/cargo_fmt.yml | 1 + Cargo.toml | 2 +- src/cmd.rs | 38 ++++++++++++++++----------------- src/opt.rs | 16 ++++++++++++-- src/sub_cmd.rs | 3 ++- 5 files changed, 37 insertions(+), 23 deletions(-) diff --git a/.github/workflows/cargo_fmt.yml b/.github/workflows/cargo_fmt.yml index b9460bc..57e8bfc 100644 --- a/.github/workflows/cargo_fmt.yml +++ b/.github/workflows/cargo_fmt.yml @@ -14,5 +14,6 @@ jobs: - name: Install Rust run: rustup update stable && rustup default stable && rustup component add rustfmt - run: | + cargo fmt --all cargo fmt -- --check cargo clippy \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index ff40eab..c95a87a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "iotdb-cli" -version = "0.0.2" +version = "0.0.3-alpha" edition = "2021" license = "Apache-2.0" readme = "README.md" diff --git a/src/cmd.rs b/src/cmd.rs index fbcaaab..f0ac15f 100644 --- a/src/cmd.rs +++ b/src/cmd.rs @@ -58,33 +58,33 @@ pub fn run() { std::process::exit(0); } - // open session - let prompt = format!("IOTDB#({})> ", conf.endpoint.to_string()); - let mut session = open_session(conf.clone()); - - // sub command + // No session sub command match sub_cmd { None => { + // open session + let prompt = format!("IOTDB#({})> ", conf.endpoint.to_string()); + let mut session = open_session(conf); + if let Some(sql) = sql { session.sql(sql.as_str()).unwrap().show() } else { readline(session, prompt) } } - Some(sub_cmd) => match sub_cmd { - // exec batch - SubCmd::File { file_path } => { - if let Some(file_path) = file_path { - exec_batch_from_file(conf, &file_path); + Some(sub_cmd) => { + match sub_cmd { + // exec sql form file + SubCmd::File { file_path } => { + if let Some(file_path) = file_path { + exec_batch_from_file(conf, &file_path); + } } + SubCmd::Usage => print_usage_info(), + SubCmd::Update => update(), + SubCmd::Csv { .. } => {} + SubCmd::Load => {} } - SubCmd::Usage => { - print_usage_info(); - } - SubCmd::Update => { - update(); - } - }, + } } } @@ -100,7 +100,7 @@ fn readline(mut session: Session, prompt: String) { "{}\nAuthor: {}\nVersion: {} v{}\nUsage:\n{}\ 1. Print usage info: `?` or `help` \n{}\ 2. Exec system command on OS: `!ps`\n{}\ - 3. Exit: `exit` or `quit` or `Ctrl-C` or `Ctrl-D`", + 3. Exit: `exit` or `quit` or `Ctrl-C` or `Ctrl-D`\n", ASCII_NAME, AUTHORS, PKG_NAME, VERSION, fore_space, fore_space, fore_space ); let his_file: PathBuf = dirs::home_dir() @@ -158,7 +158,7 @@ fn readline(mut session: Session, prompt: String) { } } else { sql = format!("{}{}", tmp_sql, sql); - println!("```sql\n{}\n```", sql); + println!("```\n{}\n```", sql); if let Ok(mut ds) = session.sql(sql.as_str()) { ds.show() } diff --git a/src/opt.rs b/src/opt.rs index b593079..693f6e6 100644 --- a/src/opt.rs +++ b/src/opt.rs @@ -1,7 +1,7 @@ use crate::{ASCII_NAME, AUTHORS, PKG_NAME}; use structopt::StructOpt; -#[derive(StructOpt, Debug)] +#[derive(Debug, Clone, StructOpt)] #[structopt(name = format ! ("{}\nAuthor: {}\nVersion: {}", ASCII_NAME, AUTHORS, PKG_NAME))] pub struct Cli { /// Execute single sql, eg: `iotdb "show storage group"` @@ -44,11 +44,23 @@ pub struct Cli { pub sub_cmd: Option, } -#[derive(Debug, StructOpt)] +#[derive(Debug, Clone, StructOpt)] pub enum SubCmd { /// Execute batch form sql file, eg: `iotdb file ddl.sql` File { file_path: Option }, + /// Csv util(TODO) + Csv { + #[structopt(short, long)] + import: Option, + + #[structopt(short, long)] + export: Option, + }, + + /// Load TsFile util(TODO) + Load, + /// Print usage info Usage, diff --git a/src/sub_cmd.rs b/src/sub_cmd.rs index aebced1..4fed411 100644 --- a/src/sub_cmd.rs +++ b/src/sub_cmd.rs @@ -1,3 +1,4 @@ +use crate::VERSION; use std::fs; use std::io; use std::io::BufRead; @@ -40,7 +41,7 @@ pub fn sql_file_reader(file_path: &str) -> Vec { #[allow(dead_code)] pub fn update() { - todo!() + println!("Update to {:?}", VERSION) } #[allow(dead_code)] From 8b0d14662db38179c761d14873e15969dcd0231d Mon Sep 17 00:00:00 2001 From: francis-du Date: Mon, 29 Nov 2021 15:58:03 +0800 Subject: [PATCH 07/13] feat: re-impl cmd and sub_cmd --- src/cmd.rs | 424 +++++++++++++++++++++++++------------------------ src/common.rs | 68 ++++++++ src/main.rs | 13 +- src/opt.rs | 13 +- src/sub_cmd.rs | 66 +++----- 5 files changed, 320 insertions(+), 264 deletions(-) create mode 100644 src/common.rs diff --git a/src/cmd.rs b/src/cmd.rs index f0ac15f..3be6b7b 100644 --- a/src/cmd.rs +++ b/src/cmd.rs @@ -1,250 +1,254 @@ +use crate::common; use crate::opt::{Cli, SubCmd}; -use crate::sub_cmd::{sql_file_reader, update}; -use crate::{ASCII_NAME, AUTHORS, PKG_NAME, VERSION}; +use crate::slogan; use iotdb::{Config, ConfigBuilder, Endpoint, Session}; use rustyline::error::ReadlineError; use rustyline::Editor; use std::io; use std::io::Write; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; use std::process::{Command, Output, Stdio}; -/// Run IoTDB CLI -pub fn run() { - let Cli { - sql, - file, - host, - port, - user, - password, - endpoint, - timezone, - debug, - sub_cmd, - } = Cli::new(); - - let mut conf_builder = ConfigBuilder::new(); - // set endpoint - if let Some(endpoint) = endpoint { - let endpoint = endpoint.as_str().parse::().unwrap(); - conf_builder.endpoint(endpoint.host.as_str(), endpoint.port.as_str()); - } else if let Some(host) = host { - if let Some(port) = port { - conf_builder.endpoint(host.as_str(), port.as_str()); - } - } +impl Cli { + pub fn run(&self) { + let Cli { + sql, file, sub_cmd, .. + } = self; - // user and password - if let Some(user) = user { - if let Some(password) = password { - conf_builder.user(user.as_str()); - conf_builder.password(password.as_str()); - } - } + let conf = self.session_conf(); - // timezone - if let Some(timezone) = timezone { - conf_builder.time_zone(timezone.as_str()); - } + // exec batch + if let Some(file_path) = file { + common::exec_batch_from_file(conf, file_path.as_str()); + std::process::exit(0); + } - // enable debug mode - conf_builder.debug(debug); - let conf = conf_builder.build(); + // sub command + match sub_cmd { + None => { + // open session + let prompt = format!("IOTDB#({})> ", conf.endpoint.to_string()); + let mut session = common::get_session(conf); - // exec batch - if let Some(file_path) = file { - exec_batch_from_file(conf, file_path.as_str()); - std::process::exit(0); + if let Some(sql) = sql { + session.sql(sql.as_str()).unwrap().show() + } else { + self.readline(session, prompt) + } + } + Some(sub_cmd) => { + match sub_cmd { + // exec sql form file + SubCmd::File { file_path } => { + if let Some(file_path) = file_path { + common::exec_batch_from_file(conf, file_path); + } + } + SubCmd::Usage => sub_cmd.usage(), + SubCmd::Update => sub_cmd.update(), + SubCmd::Csv { .. } => {} + SubCmd::Load => {} + SubCmd::Version => println!("{}", slogan()), + } + } + } } - // No session sub command - match sub_cmd { - None => { - // open session - let prompt = format!("IOTDB#({})> ", conf.endpoint.to_string()); - let mut session = open_session(conf); - - if let Some(sql) = sql { - session.sql(sql.as_str()).unwrap().show() - } else { - readline(session, prompt) + /// Set session conf + pub fn session_conf(&self) -> Config { + let Cli { + host, + port, + user, + password, + endpoint, + timezone, + debug, + .. + } = self; + + let mut builder = ConfigBuilder::new(); + // enable debug mode + builder.debug(*debug); + + // set endpoint + if let Some(endpoint) = endpoint { + let endpoint = endpoint.as_str().parse::().unwrap(); + builder.endpoint(endpoint.host.as_str(), endpoint.port.as_str()); + } else if let Some(host) = host { + if let Some(port) = port { + builder.endpoint(host.as_str(), port.as_str()); } } - Some(sub_cmd) => { - match sub_cmd { - // exec sql form file - SubCmd::File { file_path } => { - if let Some(file_path) = file_path { - exec_batch_from_file(conf, &file_path); - } - } - SubCmd::Usage => print_usage_info(), - SubCmd::Update => update(), - SubCmd::Csv { .. } => {} - SubCmd::Load => {} + + // user and password + if let Some(user) = user { + if let Some(password) = password { + builder.user(user.as_str()); + builder.password(password.as_str()); } } + + // timezone + if let Some(timezone) = timezone { + builder.time_zone(timezone.as_str()); + } + + builder.build() } -} -/// Open a IoTDB session -fn open_session(config: Config) -> Session { - Session::new(config).open().unwrap() -} + /// Exec shell command + fn exec_shell_cmd(&self, cmd_str: String) { + let mut cmd_str = cmd_str; + if cfg!(target_os = "windows") { + cmd_str = "dir C:\\tmp".to_string(); + } + + if cfg!(target_os = "windows") { + let output = Command::new("cmd") + .arg("/c") + .arg(cmd_str) + .stdout(Stdio::piped()) + .output() + .expect("cmd exec error!"); + self.output_to_stdout(output); + } else { + let output = Command::new("sh") + .arg("-c") + .arg(cmd_str) + .stdout(Stdio::piped()) + .output() + .expect("sh exec error!"); + self.output_to_stdout(output); + }; + } + + /// Command output to stdout + fn output_to_stdout(&self, output: Output) { + if output.status.success() { + io::stdout().write_all(&output.stdout).unwrap(); + } else { + io::stdout().write_all(&output.stderr).unwrap(); + } + } -/// readline -fn readline(mut session: Session, prompt: String) { - let fore_space = " "; - println!( - "{}\nAuthor: {}\nVersion: {} v{}\nUsage:\n{}\ + /// Usage info + fn cli_usage(&self) -> String { + let fore_space = " "; + format!( + "Usage:\n{}\ 1. Print usage info: `?` or `help` \n{}\ - 2. Exec system command on OS: `!ps`\n{}\ + 2. Exec system command on local machine, eg: `!ps -ef`\n{}\ 3. Exit: `exit` or `quit` or `Ctrl-C` or `Ctrl-D`\n", - ASCII_NAME, AUTHORS, PKG_NAME, VERSION, fore_space, fore_space, fore_space - ); - let his_file: PathBuf = dirs::home_dir() - .unwrap_or_else(|| PathBuf::from("/home")) - .join(".iotdb_his"); - - let mut rl = Editor::<()>::new(); - if his_file.as_path().exists() { - rl.load_history(his_file.as_path()).unwrap(); + fore_space, fore_space, fore_space + ) } - let mut tmp_sql: String = String::new(); - loop { - // TODO: is_open is invalid and needs to be fixed in iotdb-rs - if session.is_close() { - session = session.open().unwrap(); - } - let readline; - if !tmp_sql.is_empty() { - readline = rl.readline(">> "); - } else { - readline = rl.readline(prompt.as_str()); + /// Print help info + pub fn help(&self) { + common::print_usage(); + } + + /// readline + fn readline(&self, mut session: Session, prompt: String) { + println!("{}\n{}", slogan(), self.cli_usage()); + let his_file: PathBuf = dirs::home_dir() + .unwrap_or_else(|| PathBuf::from("/home")) + .join(".iotdb_his"); + + let mut rl = Editor::<()>::new(); + if his_file.as_path().exists() { + rl.load_history(his_file.as_path()).unwrap(); } - match readline { - Ok(mut sql) => { - if sql.contains("exit") || sql.contains("quit") { - session.close().unwrap(); - rl.add_history_entry(sql.as_str()); - rl.save_history(his_file.as_path()).unwrap(); - break; - } + let mut tmp_sql: String = String::new(); + let mut max_str_len = 0; + loop { + // TODO: is_open is invalid and needs to be fixed in iotdb-rs + if session.is_close() { + session = session.open().unwrap(); + } + let readline; + if !tmp_sql.is_empty() { + readline = rl.readline(">> "); + } else { + readline = rl.readline(prompt.as_str()); + } - if sql.trim().is_empty() { - continue; - } + match readline { + Ok(mut sql) => { + if sql.contains("exit") || sql.contains("quit") { + session.close().unwrap(); + rl.add_history_entry(sql.as_str()); + rl.save_history(his_file.as_path()).unwrap(); + break; + } - if sql.eq("?") || sql.eq("help") { - rl.add_history_entry(sql.as_str()); - print_usage_info(); - continue; - } + if sql.trim().is_empty() { + continue; + } - if sql.starts_with('!') { - rl.add_history_entry(sql.as_str()); - sql.remove(0); - exec_shell_cmd(sql); - continue; - } + if sql.eq("?") || sql.eq("help") { + rl.add_history_entry(sql.as_str()); + self.help(); + continue; + } + + if sql.starts_with('!') { + rl.add_history_entry(sql.as_str()); + sql.remove(0); + self.exec_shell_cmd(sql); + continue; + } - if sql.ends_with(';') { - if tmp_sql.is_empty() { - if let Ok(mut ds) = session.sql(sql.as_str()) { - ds.show() + if sql.ends_with(';') { + if tmp_sql.is_empty() { + if let Ok(mut ds) = session.sql(sql.as_str()) { + ds.show() + } + } else { + sql = format!("{}{}", tmp_sql, sql); + + let mut split_line = String::new(); + for _i in 0..max_str_len { + split_line.push('+') + } + println!("{}\n{}\n{}", split_line, sql, split_line); + + if let Ok(mut ds) = session.sql(sql.as_str()) { + ds.show() + } + + tmp_sql.clear(); + max_str_len = 0; } + rl.add_history_entry(sql.as_str()); } else { - sql = format!("{}{}", tmp_sql, sql); - println!("```\n{}\n```", sql); - if let Ok(mut ds) = session.sql(sql.as_str()) { - ds.show() + tmp_sql.push_str(sql.trim()); + tmp_sql.push('\n'); + + if sql.len() > max_str_len { + max_str_len = sql.len(); } - tmp_sql.clear(); } - rl.add_history_entry(sql.as_str()); - } else { - tmp_sql.push_str(sql.trim()); - tmp_sql.push('\n') + } + Err(ReadlineError::Interrupted) => { + session.close().unwrap(); + println!("Ctrl-C"); + break; + } + Err(ReadlineError::Eof) => { + session.close().unwrap(); + println!("Ctrl-D"); + break; + } + Err(err) => { + session.close().unwrap(); + println!("Error: {:?}", err); + break; } } - Err(ReadlineError::Interrupted) => { - session.close().unwrap(); - println!("Ctrl-C"); - break; - } - Err(ReadlineError::Eof) => { - session.close().unwrap(); - println!("Ctrl-D"); - break; - } - Err(err) => { - session.close().unwrap(); - println!("Error: {:?}", err); - break; - } - } - rl.save_history(his_file.as_path()).unwrap(); - } -} - -// Exec batch from sql file -fn exec_batch_from_file(conf: Config, file_path: &str) { - let file = Path::new(&file_path); - let mut session = open_session(conf); - if file.exists() { - if !file.is_file() || !file_path.ends_with(".sql") { - println!("ERROR: {:?} is not a sql file", file_path); - } else { - println!("Statements: {:#?}", sql_file_reader(file_path)); - session.exec_batch(sql_file_reader(file_path)); - session.close().unwrap(); + rl.save_history(his_file.as_path()).unwrap(); } - } else { - println!("ERROR: {:?} not exist", file_path); - } -} - -/// Print help info -fn print_usage_info() { - let help_info = include_str!("static/usage_info"); - println!("{}", help_info); -} - -/// Exec shell command -#[allow(unused_assignments)] -fn exec_shell_cmd(cmd_str: String) { - let mut cmd_str = cmd_str; - if cfg!(target_os = "windows") { - cmd_str = "dir c:\\tmp".to_string(); - } - - if cfg!(target_os = "windows") { - let output = Command::new("cmd") - .arg("/c") - .arg(cmd_str) - .stdout(Stdio::piped()) - .output() - .expect("cmd exec error!"); - output_to_stdout(output); - } else { - let output = Command::new("sh") - .arg("-c") - .arg(cmd_str) - .stdout(Stdio::piped()) - .output() - .expect("sh exec error!"); - output_to_stdout(output); - }; -} - -/// Command output to stdout -fn output_to_stdout(output: Output) { - if output.status.success() { - io::stdout().write_all(&output.stdout).unwrap(); - } else { - io::stdout().write_all(&output.stderr).unwrap(); } } diff --git a/src/common.rs b/src/common.rs new file mode 100644 index 0000000..831ebc5 --- /dev/null +++ b/src/common.rs @@ -0,0 +1,68 @@ +use iotdb::{Config, Session}; +use std::io::BufRead; +use std::path::Path; +use std::{fs, io}; + +// Exec batch from sql file +pub fn exec_batch_from_file(conf: Config, file_path: &str) { + let file = Path::new(&file_path); + let mut session = get_session(conf); + if file.exists() { + if !file.is_file() || !file_path.ends_with(".sql") { + println!("ERROR: {:?} is not a sql file", file_path); + } else { + println!("Statements: {:#?}", sql_file_reader(file_path)); + session.exec_batch(sql_file_reader(file_path)); + session.close().unwrap(); + } + } else { + println!("ERROR: {:?} not exist", file_path); + } +} + +/// Open a IoTDB session +pub fn get_session(conf: Config) -> Session { + Session::new(conf).open().unwrap() +} + +/// SQL file reader +pub fn sql_file_reader(file_path: &str) -> Vec { + let mut batch_sql: Vec = vec![]; + match fs::File::open(file_path) { + Ok(file) => { + let sql_lines = io::BufReader::new(file) + .lines() + .map(|s| s.unwrap_or_default()) + .filter(|s| !s.is_empty()) + .filter(|s| !s.starts_with("--")) + .filter(|s| s.len() != 1) + .map(|s| s.trim().to_string()) + .collect::>(); + + let mut tmp_str: String = String::new(); + for line in sql_lines { + if line.ends_with(';') { + if tmp_str.is_empty() { + batch_sql.push(line); + } else { + batch_sql.push(format!("{}{}", tmp_str, line)); + tmp_str.clear(); + } + } else { + tmp_str.push_str(line.as_str()); + tmp_str.push_str("\n "); + } + } + batch_sql + } + Err(error) => { + println!("ERROR: {:?}", error); + vec![] + } + } +} + +pub fn print_usage() { + let help_info = include_str!("static/usage_info"); + println!("{}", help_info); +} diff --git a/src/main.rs b/src/main.rs index 2ca129d..a4f2064 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,7 @@ +use crate::opt::Cli; + mod cmd; +mod common; mod opt; mod sub_cmd; @@ -13,6 +16,14 @@ pub const ASCII_NAME: &str = " ▄██▄ ▀▀█▄▄▄█▀ ▄██▄ ▄██▄▄▄█▀ ▄██▄▄▄█▀\t "; +/// Run IoTDB CLI fn main() { - cmd::run(); + Cli::new().run(); +} + +pub fn slogan() -> String { + format!( + "{}\nAuthor: {}\nVersion: {} v{}", + ASCII_NAME, AUTHORS, PKG_NAME, VERSION, + ) } diff --git a/src/opt.rs b/src/opt.rs index 693f6e6..02a7860 100644 --- a/src/opt.rs +++ b/src/opt.rs @@ -44,6 +44,12 @@ pub struct Cli { pub sub_cmd: Option, } +impl Cli { + pub fn new() -> Self { + Cli::from_args() + } +} + #[derive(Debug, Clone, StructOpt)] pub enum SubCmd { /// Execute batch form sql file, eg: `iotdb file ddl.sql` @@ -66,10 +72,7 @@ pub enum SubCmd { /// Update binary(TODO) Update, -} -impl Cli { - pub fn new() -> Self { - Cli::from_args() - } + /// Prints version information + Version, } diff --git a/src/sub_cmd.rs b/src/sub_cmd.rs index 4fed411..87230d1 100644 --- a/src/sub_cmd.rs +++ b/src/sub_cmd.rs @@ -1,55 +1,25 @@ +use crate::common; +use crate::opt::SubCmd; use crate::VERSION; -use std::fs; -use std::io; -use std::io::BufRead; -pub fn sql_file_reader(file_path: &str) -> Vec { - let mut batch_sql: Vec = vec![]; - match fs::File::open(file_path) { - Ok(file) => { - let sql_lines = io::BufReader::new(file) - .lines() - .map(|s| s.unwrap_or_default()) - .filter(|s| !s.is_empty()) - .filter(|s| !s.starts_with("--")) - .filter(|s| s.len() != 1) - .map(|s| s.trim().to_string()) - .collect::>(); - - let mut tmp_str: String = String::new(); - for line in sql_lines { - if line.ends_with(';') { - if tmp_str.is_empty() { - batch_sql.push(line); - } else { - batch_sql.push(format!("{}{}", tmp_str, line)); - tmp_str.clear(); - } - } else { - tmp_str.push_str(line.as_str()); - tmp_str.push_str("\n "); - } - } - batch_sql - } - Err(error) => { - println!("ERROR: {:?}", error); - vec![] - } +impl SubCmd { + /// Print help info + pub fn usage(&self) { + common::print_usage(); } -} -#[allow(dead_code)] -pub fn update() { - println!("Update to {:?}", VERSION) -} + #[allow(dead_code)] + pub fn update(&self) { + println!("Update to {:?}", VERSION) + } -#[allow(dead_code)] -pub fn download_latest() { - todo!() -} + #[allow(dead_code)] + pub fn download_latest(&self) { + todo!() + } -#[allow(dead_code)] -pub fn replace_binary() { - todo!() + #[allow(dead_code)] + pub fn replace_binary(&self) { + todo!() + } } From 7ea82cc9d1d3b7cf0333fc6100496ff6b2f75694 Mon Sep 17 00:00:00 2001 From: francis-du Date: Mon, 29 Nov 2021 23:53:55 +0800 Subject: [PATCH 08/13] fix: improve install script --- install.sh | 193 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 136 insertions(+), 57 deletions(-) diff --git a/install.sh b/install.sh index b44ee88..baacf8c 100755 --- a/install.sh +++ b/install.sh @@ -1,4 +1,5 @@ #!/bin/sh +# shellcheck disable=SC3003 NO_COLOR=$'\e[0m' ERROR=$'\e[0;31m'"ERROR: " @@ -17,10 +18,14 @@ set_version() { exit 1 fi - if command -v curl &>/dev/null; then + if + command -v curl >/dev/null + then VERSION=$(curl -s ${LATEST_RELEASE} | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/') else - if command -v wget &>/dev/null; then + if + command -v wget >/dev/null + then VERSION=$(wget ${LATEST_RELEASE} | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/') else echo "${ERROR}Please install wget or curl${NO_COLOR}" @@ -31,39 +36,20 @@ set_version() { } download() { - local url=$1 - local file_name=$2 + url=$1 + file_name=$2 - if command -v curl &>/dev/null; then - if [ -n $file_name ]; then - if [ ! -f $file_name ]; then - curl -L -f -# -C0 -o $file_name "$url" - else - command $file_name -h - echo "${WARN}'$file_name' exists" - echo "${WARN}Please run command 'iotdb' or '${file_name}'" - exit 1 - fi - else - curl -L -f -# -OC0 "$url" --progress-bar - fi + if + command -v curl >/dev/null + then + curl -L -f -# -C0 -o "$file_name" "$url" else - if command -v wget &>/dev/null; then - command wget --spider -q "$url" - if [ $? == 0 ]; then - wget --spider -q "$url" - if [ -n $file_name ]; then - if [ ! -f $file_name ]; then - wget -q -c --show-progress "$url" -O $file_name - else - command $file_name -h - echo "${WARN}'$file_name' exists" - echo "${WARN}Please run command 'iotdb' or '${file_name}'" - exit 1 - fi - else - wget -q -c --show-progress "$url" - fi + if + command -v wget >/dev/null + then + wget --spider -q "$url" + if [ $? = 0 ]; then + wget -q -c --show-progress "$url" -O "$file_name" else echo "${ERROR}Download failed from $url" exit 1 @@ -75,62 +61,155 @@ download() { fi } -function install() { +bin="iotdb" +win_bin="iotdb.exe" +install() { set_version echo "${INFO}Version: ${VERSION}" echo "${INFO}Latest release '${LATEST}'" asset_base_url="https://github.com/francis-du/iotdb-cli/releases/download/${VERSION}" + case "$(uname -s)" in Linux*) - bin_name="${BIN_PATH}/iotdb" asset_url="$asset_base_url/iotdb-linux" echo "${INFO}Download from '${asset_url}'" - download $asset_url $bin_name - if [ -f "${bin_name}" ]; then - chmod +x $bin_name - echo "${INFO}Please run command 'iotdb' or '${bin_name}'" + if [ -w ${BIN_PATH} ] && [ -x ${BIN_PATH} ]; then + bin="${BIN_PATH}/$bin" + if [ -f $bin ]; then + command "$bin" -h + echo "${WARN}'$bin' exists" + echo "${WARN}Please run '$bin -h' to get help information" + else + download "$asset_url" "$bin" + if [ -f "$bin" ]; then + chmod +x $bin + echo "${WARN}Please run '$bin -h' to get help information" + else + echo "${ERROR}Install failed" + fi + fi else - echo "${ERROR}Install failed" + if [ -f $bin ]; then + command "./$bin" -h + echo "${WARN}'$bin' exists" + echo "${WARN}Please run './$bin -h' to get help information" + else + download "$asset_url" "$bin" + if [ -f "$bin" ]; then + chmod +x $bin + echo "${WARN}Please run './$bin -h' to get help information" + else + echo "${ERROR}Install failed" + fi + fi fi ;; Darwin*) - bin_name="${BIN_PATH}/iotdb" asset_url="${asset_base_url}/iotdb-mac" echo "${INFO}Download from '${asset_url}'" - download $asset_url $bin_name - if [ -f "${bin_name}" ]; then - chmod +x $bin_name - echo "${INFO}Please run command 'iotdb' or '${bin_name}'" + if [ -w ${BIN_PATH} ] && [ -x ${BIN_PATH} ]; then + bin="${BIN_PATH}/$bin" + if [ -f $bin ]; then + command "$bin" -h + echo "${WARN}'$bin' exists" + echo "${WARN}Please run '$bin -h' to get help information" + else + download "$asset_url" "$bin" + if [ -f "$bin" ]; then + chmod +x $bin + echo "${WARN}Please run '$bin -h' to get help information" + else + echo "${ERROR}Install failed" + fi + fi else - echo "${ERROR}Install failed" + if [ -f $bin ]; then + command "./$bin" -h + echo "${WARN}'$bin' exists" + echo "${WARN}Please run './$bin -h' to get help information" + else + download "$asset_url" "$bin" + if [ -f "$bin" ]; then + chmod +x $bin + echo "${WARN}Please run './$bin -h' to get help information" + else + echo "${ERROR}Install failed" + fi + fi fi ;; CYGWIN*) # TODO: Need to be test - bin_name="${BIN_PATH}/iotdb.exe" asset_url="$asset_base_url/iotdb.exe" echo "${INFO}Download from '${asset_url}'" - download $asset_url $bin_name - if [ -f "${bin_name}" ]; then - echo "${INFO}Please run command 'iotdb.exe' or '${bin_name}'" + if [ -w ${BIN_PATH} ] && [ -x ${BIN_PATH} ]; then + win_bin="${BIN_PATH}/$win_bin" + if [ -f $win_bin ]; then + command "$win_bin" -h + echo "${WARN}'$win_bin' exists" + echo "${WARN}Please run '$win_bin -h' to get help information" + else + download "$asset_url" "$win_bin" + if [ -f "$win_bin" ]; then + chmod +x $win_bin + echo "${WARN}Please run '$win_bin -h' to get help information" + else + echo "${ERROR}Install failed" + fi + fi else - echo "${ERROR}Install failed" + if [ -f $win_bin ]; then + command "./$win_bin" -h + echo "${WARN}'$win_bin' exists" + echo "${WARN}Please run './$win_bin -h' to get help information" + else + download "$asset_url" "$win_bin" + if [ -f "$win_bin" ]; then + chmod +x $win_bin + echo "${WARN}Please run './$win_bin -h' to get help information" + else + echo "${ERROR}Install failed" + fi + fi fi ;; MINGW*) # TODO: Need to be test - bin_name="${BIN_PATH}/iotdb.exe" - asset_url=$asset_base_url"/iotdb.exe" + asset_url="$asset_base_url/iotdb.exe" echo "${INFO}Download from '${asset_url}'" - download $asset_url $bin_name - if [ -f "${bin_name}" ]; then - echo "${INFO}Please run command 'iotdb.exe' or '${bin_name}'" + if [ -w ${BIN_PATH} ] && [ -x ${BIN_PATH} ]; then + win_bin="${BIN_PATH}/$win_bin" + if [ -f $win_bin ]; then + command "$win_bin" -h + echo "${WARN}'$win_bin' exists" + echo "${WARN}Please run '$win_bin -h' to get help information" + else + download "$asset_url" "$win_bin" + if [ -f "$win_bin" ]; then + chmod +x $win_bin + echo "${WARN}Please run '$win_bin -h' to get help information" + else + echo "${ERROR}Install failed" + fi + fi else - echo "${ERROR}Install failed" + if [ -f $win_bin ]; then + command "./$win_bin" -h + echo "${WARN}'$win_bin' exists" + echo "${WARN}Please run './$win_bin -h' to get help information" + else + download "$asset_url" "$win_bin" + if [ -f "$win_bin" ]; then + chmod +x $win_bin + echo "${WARN}Please run './$win_bin -h' to get help information" + else + echo "${ERROR}Install failed" + fi + fi fi ;; *) From 04be89ecfb4c67a91b74fb976a372a24783d9f9e Mon Sep 17 00:00:00 2001 From: francis-du Date: Tue, 30 Nov 2021 00:08:30 +0800 Subject: [PATCH 09/13] feat: add install script test ci --- .github/workflows/test_install_script.yaml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 .github/workflows/test_install_script.yaml diff --git a/.github/workflows/test_install_script.yaml b/.github/workflows/test_install_script.yaml new file mode 100644 index 0000000..5da7b1f --- /dev/null +++ b/.github/workflows/test_install_script.yaml @@ -0,0 +1,22 @@ +name: test-install-script + +on: + pull_request: + push: + branches: [ main ] + +jobs: + test-install-script: + name: Test install script for ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + include: + - os: ubuntu-latest + - os: windows-latest + - os: macos-latest + steps: + - uses: actions/checkout@v2 + - name: test install script + run: | + curl -s https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | sh \ No newline at end of file From a3d93f07e6a1ff0a933563f2c37ed2becdae1fa1 Mon Sep 17 00:00:00 2001 From: francis-du Date: Tue, 30 Nov 2021 00:11:22 +0800 Subject: [PATCH 10/13] fix: install script test ci --- .github/workflows/test_install_script.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test_install_script.yaml b/.github/workflows/test_install_script.yaml index 5da7b1f..a311d3c 100644 --- a/.github/workflows/test_install_script.yaml +++ b/.github/workflows/test_install_script.yaml @@ -19,4 +19,5 @@ jobs: - uses: actions/checkout@v2 - name: test install script run: | + curl -s https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | sh curl -s https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | sh \ No newline at end of file From 60d363d4fe8f53245167818d2770c7294e0ea279 Mon Sep 17 00:00:00 2001 From: francis-du Date: Tue, 30 Nov 2021 00:15:54 +0800 Subject: [PATCH 11/13] fix: test install ci issue --- .github/workflows/test_install_linux.yaml | 21 +++++++++++++++++++ .github/workflows/test_install_mac.yaml | 21 +++++++++++++++++++ ...tall_script.yaml => test_install_win.yaml} | 4 +--- 3 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/test_install_linux.yaml create mode 100644 .github/workflows/test_install_mac.yaml rename .github/workflows/{test_install_script.yaml => test_install_win.yaml} (85%) diff --git a/.github/workflows/test_install_linux.yaml b/.github/workflows/test_install_linux.yaml new file mode 100644 index 0000000..ea9206b --- /dev/null +++ b/.github/workflows/test_install_linux.yaml @@ -0,0 +1,21 @@ +name: test-install-linux + +on: + pull_request: + push: + branches: [ main ] + +jobs: + test-install-script: + name: Test install script for ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + include: + - os: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: test install script + run: | + curl -s https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | sh + curl -s https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | sh \ No newline at end of file diff --git a/.github/workflows/test_install_mac.yaml b/.github/workflows/test_install_mac.yaml new file mode 100644 index 0000000..1901506 --- /dev/null +++ b/.github/workflows/test_install_mac.yaml @@ -0,0 +1,21 @@ +name: test-install-mac + +on: + pull_request: + push: + branches: [ main ] + +jobs: + test-install-script: + name: Test install script for ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + include: + - os: macos-latest + steps: + - uses: actions/checkout@v2 + - name: test install script + run: | + curl -s https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | sh + curl -s https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | sh \ No newline at end of file diff --git a/.github/workflows/test_install_script.yaml b/.github/workflows/test_install_win.yaml similarity index 85% rename from .github/workflows/test_install_script.yaml rename to .github/workflows/test_install_win.yaml index a311d3c..363f928 100644 --- a/.github/workflows/test_install_script.yaml +++ b/.github/workflows/test_install_win.yaml @@ -1,4 +1,4 @@ -name: test-install-script +name: test-install-win on: pull_request: @@ -12,9 +12,7 @@ jobs: strategy: matrix: include: - - os: ubuntu-latest - os: windows-latest - - os: macos-latest steps: - uses: actions/checkout@v2 - name: test install script From 337426fd4b5ba31b65ca7c16a0ff5c7ac2848f86 Mon Sep 17 00:00:00 2001 From: francis-du Date: Tue, 30 Nov 2021 00:34:43 +0800 Subject: [PATCH 12/13] fix: ci and docs --- .github/workflows/test_install_linux.yaml | 4 +-- .github/workflows/test_install_mac.yaml | 4 +-- .github/workflows/test_install_win.yaml | 4 +-- README.md | 36 +++++++++++++++-------- docs/src/get-started.md | 36 +++++++++++++++-------- install.sh | 2 +- 6 files changed, 53 insertions(+), 33 deletions(-) diff --git a/.github/workflows/test_install_linux.yaml b/.github/workflows/test_install_linux.yaml index ea9206b..1593193 100644 --- a/.github/workflows/test_install_linux.yaml +++ b/.github/workflows/test_install_linux.yaml @@ -17,5 +17,5 @@ jobs: - uses: actions/checkout@v2 - name: test install script run: | - curl -s https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | sh - curl -s https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | sh \ No newline at end of file + curl -s https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | bash -ex + curl -s https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | bash -ex \ No newline at end of file diff --git a/.github/workflows/test_install_mac.yaml b/.github/workflows/test_install_mac.yaml index 1901506..dac9d58 100644 --- a/.github/workflows/test_install_mac.yaml +++ b/.github/workflows/test_install_mac.yaml @@ -17,5 +17,5 @@ jobs: - uses: actions/checkout@v2 - name: test install script run: | - curl -s https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | sh - curl -s https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | sh \ No newline at end of file + curl -s https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | bash -ex + curl -s https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | bash -ex \ No newline at end of file diff --git a/.github/workflows/test_install_win.yaml b/.github/workflows/test_install_win.yaml index 363f928..5ccbbe4 100644 --- a/.github/workflows/test_install_win.yaml +++ b/.github/workflows/test_install_win.yaml @@ -17,5 +17,5 @@ jobs: - uses: actions/checkout@v2 - name: test install script run: | - curl -s https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | sh - curl -s https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | sh \ No newline at end of file + curl -s https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | bash -ex + curl -s https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | bash -ex \ No newline at end of file diff --git a/README.md b/README.md index 0629148..9f62fa4 100644 --- a/README.md +++ b/README.md @@ -5,18 +5,27 @@

iotdb-cli

Apache IotDB CLI Client written in Rust

-[![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) +[![Contribute](https://img.shields.io/badge/contribute-now-a94064?color=%23E5531A&)](https://gitpod.io/#https://github.com/francis-du/iotdb-cli) +[![downloads](https://img.shields.io/crates/d/iotdb-cli?style=flat-square&color=%23E5531A)](https://crates.io/crates/iotdb-cli) +[![GitHub Release](https://img.shields.io/github/v/release/francis-du/iotdb-cli?include_prereleases&sort=semver&color=%23E5531A&style=flat-square)](https://github.com/francis-du/iotdb-cli/releases) +![Top Lang](https://img.shields.io/github/languages/top/trisasnava/koifish?color=%23E5531A&style=flat-square) [![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) +[![Docs Build](https://img.shields.io/github/workflow/status/francis-du/iotdb-cli/mdbook-deploy?label=docs%20build&style=flat-square)](https://github.com/francis-du/iotdb-cli/actions?query=workflow:mdbook-deploy) +[![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) [![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) --- -![Alt](https://repobeats.axiom.co/api/embed/86055cf67fcaac9e6e93c64c9a7a1630686ceda1.svg "Repobeats analytics image") +[![Alt](https://repobeats.axiom.co/api/embed/86055cf67fcaac9e6e93c64c9a7a1630686ceda1.svg "Repobeats analytics image")](https://github.com/francis-du/iotdb-cli/pulse) ## Installation +[![Linux supported](https://img.shields.io/badge/Linux%20x86__64-supported%20✓-228B22?style=flat-square&logo=linux)](https://github.com/francis-du/iotdb-cli/releases/latest) +[![macOS supported](https://img.shields.io/badge/macOS%20x86__64-supported%20✓-228B22?style=flat-square&logo=apple)](https://github.com/francis-du/iotdb-cli/releases/latest) +[![Windows supported](https://img.shields.io/badge/Windows%20x86__64-supported%20✓-228B22?style=flat-square&logo=windows)](https://github.com/francis-du/iotdb-cli/releases/latest) + 1. Using `Cargo` ```shell @@ -28,15 +37,15 @@ cargo install -f --git https://github.com/francis-du/iotdb-cli.git 2. From [binary](https://github.com/francis-du/iotdb-cli/releases/latest) ```shell -curl -s https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | sh +curl -s https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | bash -curl -s https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | sh -s -- x.x.x +curl -s https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | bash -s -- x.x.x ``` ```shell -wget -qO- https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | sh +wget -qO- https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | bash -wget -qO- https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | sh -s -- x.x.x +wget -qO- https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | bash -s -- x.x.x ``` ## Usage @@ -46,7 +55,6 @@ iotdb -h ``` ```shell - ▀██▀ ▄▄█▀▀██ █▀▀██▀▀█ ▀██▀▀█▄ ▀██▀▀█▄ ██ ▄█▀ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██▀▀▀█▄ @@ -54,7 +62,7 @@ iotdb -h ▄██▄ ▀▀█▄▄▄█▀ ▄██▄ ▄██▄▄▄█▀ ▄██▄▄▄█▀ Author: github.com/francis-du -Version: iotdb-cli 0.0.2 +Version: iotdb-cli 0.0.3-alpha USAGE: iotdb [FLAGS] [OPTIONS] [sql] [SUBCOMMAND] @@ -77,11 +85,13 @@ ARGS: Execute single sql, eg: `iotdb "show storage group"` SUBCOMMANDS: - file Execute batch form sql file, eg: `iotdb file ddl.sql` - help Prints this message or the help of the given subcommand(s) - update Update binary(TODO) - usage Print usage info - + csv Csv util(TODO) + file Execute batch form sql file, eg: `iotdb file ddl.sql` + help Prints this message or the help of the given subcommand(s) + load Load TsFile util(TODO) + update Update binary(TODO) + usage Print usage info + version Prints version information ``` 1. Connect to IoTDB server diff --git a/docs/src/get-started.md b/docs/src/get-started.md index 0629148..9f62fa4 100644 --- a/docs/src/get-started.md +++ b/docs/src/get-started.md @@ -5,18 +5,27 @@

iotdb-cli

Apache IotDB CLI Client written in Rust

-[![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) +[![Contribute](https://img.shields.io/badge/contribute-now-a94064?color=%23E5531A&)](https://gitpod.io/#https://github.com/francis-du/iotdb-cli) +[![downloads](https://img.shields.io/crates/d/iotdb-cli?style=flat-square&color=%23E5531A)](https://crates.io/crates/iotdb-cli) +[![GitHub Release](https://img.shields.io/github/v/release/francis-du/iotdb-cli?include_prereleases&sort=semver&color=%23E5531A&style=flat-square)](https://github.com/francis-du/iotdb-cli/releases) +![Top Lang](https://img.shields.io/github/languages/top/trisasnava/koifish?color=%23E5531A&style=flat-square) [![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) +[![Docs Build](https://img.shields.io/github/workflow/status/francis-du/iotdb-cli/mdbook-deploy?label=docs%20build&style=flat-square)](https://github.com/francis-du/iotdb-cli/actions?query=workflow:mdbook-deploy) +[![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) [![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) --- -![Alt](https://repobeats.axiom.co/api/embed/86055cf67fcaac9e6e93c64c9a7a1630686ceda1.svg "Repobeats analytics image") +[![Alt](https://repobeats.axiom.co/api/embed/86055cf67fcaac9e6e93c64c9a7a1630686ceda1.svg "Repobeats analytics image")](https://github.com/francis-du/iotdb-cli/pulse) ## Installation +[![Linux supported](https://img.shields.io/badge/Linux%20x86__64-supported%20✓-228B22?style=flat-square&logo=linux)](https://github.com/francis-du/iotdb-cli/releases/latest) +[![macOS supported](https://img.shields.io/badge/macOS%20x86__64-supported%20✓-228B22?style=flat-square&logo=apple)](https://github.com/francis-du/iotdb-cli/releases/latest) +[![Windows supported](https://img.shields.io/badge/Windows%20x86__64-supported%20✓-228B22?style=flat-square&logo=windows)](https://github.com/francis-du/iotdb-cli/releases/latest) + 1. Using `Cargo` ```shell @@ -28,15 +37,15 @@ cargo install -f --git https://github.com/francis-du/iotdb-cli.git 2. From [binary](https://github.com/francis-du/iotdb-cli/releases/latest) ```shell -curl -s https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | sh +curl -s https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | bash -curl -s https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | sh -s -- x.x.x +curl -s https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | bash -s -- x.x.x ``` ```shell -wget -qO- https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | sh +wget -qO- https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | bash -wget -qO- https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | sh -s -- x.x.x +wget -qO- https://raw.githubusercontent.com/francis-du/iotdb-cli/main/install.sh | bash -s -- x.x.x ``` ## Usage @@ -46,7 +55,6 @@ iotdb -h ``` ```shell - ▀██▀ ▄▄█▀▀██ █▀▀██▀▀█ ▀██▀▀█▄ ▀██▀▀█▄ ██ ▄█▀ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██▀▀▀█▄ @@ -54,7 +62,7 @@ iotdb -h ▄██▄ ▀▀█▄▄▄█▀ ▄██▄ ▄██▄▄▄█▀ ▄██▄▄▄█▀ Author: github.com/francis-du -Version: iotdb-cli 0.0.2 +Version: iotdb-cli 0.0.3-alpha USAGE: iotdb [FLAGS] [OPTIONS] [sql] [SUBCOMMAND] @@ -77,11 +85,13 @@ ARGS: Execute single sql, eg: `iotdb "show storage group"` SUBCOMMANDS: - file Execute batch form sql file, eg: `iotdb file ddl.sql` - help Prints this message or the help of the given subcommand(s) - update Update binary(TODO) - usage Print usage info - + csv Csv util(TODO) + file Execute batch form sql file, eg: `iotdb file ddl.sql` + help Prints this message or the help of the given subcommand(s) + load Load TsFile util(TODO) + update Update binary(TODO) + usage Print usage info + version Prints version information ``` 1. Connect to IoTDB server diff --git a/install.sh b/install.sh index baacf8c..f86f87d 100755 --- a/install.sh +++ b/install.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # shellcheck disable=SC3003 NO_COLOR=$'\e[0m' From 5009a0b5d2fdd28658db8e6f57cbf90ca00dcc8a Mon Sep 17 00:00:00 2001 From: francis-du Date: Tue, 30 Nov 2021 02:34:53 +0800 Subject: [PATCH 13/13] fix: conf issue --- src/cmd.rs | 43 +++++++++++++++------------ src/opt.rs | 11 +++++-- src/static/usage_info | 68 +++++++++++++++++++++---------------------- 3 files changed, 66 insertions(+), 56 deletions(-) diff --git a/src/cmd.rs b/src/cmd.rs index 3be6b7b..cdd4bc4 100644 --- a/src/cmd.rs +++ b/src/cmd.rs @@ -40,8 +40,8 @@ impl Cli { match sub_cmd { // exec sql form file SubCmd::File { file_path } => { - if let Some(file_path) = file_path { - common::exec_batch_from_file(conf, file_path); + if let Some(file) = file_path { + common::exec_batch_from_file(conf, file); } } SubCmd::Usage => sub_cmd.usage(), @@ -57,6 +57,7 @@ impl Cli { /// Set session conf pub fn session_conf(&self) -> Config { let Cli { + dev, host, port, user, @@ -68,30 +69,34 @@ impl Cli { } = self; let mut builder = ConfigBuilder::new(); - // enable debug mode - builder.debug(*debug); - // set endpoint - if let Some(endpoint) = endpoint { - let endpoint = endpoint.as_str().parse::().unwrap(); - builder.endpoint(endpoint.host.as_str(), endpoint.port.as_str()); - } else if let Some(host) = host { - if let Some(port) = port { - builder.endpoint(host.as_str(), port.as_str()); - } + // timezone + if let Some(timezone) = timezone { + builder.time_zone(timezone.as_str()); } + // enable debug mode + builder.debug(*debug); + // user and password if let Some(user) = user { - if let Some(password) = password { - builder.user(user.as_str()); - builder.password(password.as_str()); - } + builder.user(user.as_str()); + } + if let Some(password) = password { + builder.password(password.as_str()); } - // timezone - if let Some(timezone) = timezone { - builder.time_zone(timezone.as_str()); + // set endpoint + if host.is_some() && port.is_some() { + builder.endpoint( + host.as_ref().unwrap().as_str(), + port.as_ref().unwrap().as_str(), + ); + } else if let Some(endpoint) = endpoint { + let endpoint = endpoint.as_str().parse::().unwrap(); + builder.endpoint(endpoint.host.as_str(), endpoint.port.as_str()); + } else if *dev { + builder.endpoint("119.84.128.59", "6667"); } builder.build() diff --git a/src/opt.rs b/src/opt.rs index 02a7860..11d1890 100644 --- a/src/opt.rs +++ b/src/opt.rs @@ -2,11 +2,15 @@ use crate::{ASCII_NAME, AUTHORS, PKG_NAME}; use structopt::StructOpt; #[derive(Debug, Clone, StructOpt)] -#[structopt(name = format ! ("{}\nAuthor: {}\nVersion: {}", ASCII_NAME, AUTHORS, PKG_NAME))] +#[structopt(name = format!("{}\nAuthor: {}\nVersion: {}", ASCII_NAME, AUTHORS, PKG_NAME))] pub struct Cli { /// Execute single sql, eg: `iotdb "show storage group"` pub sql: Option, + /// Dev server + #[structopt(long)] + pub dev: bool, + /// Execute batch form sql file, eg: `iotdb -f ddl.sql` #[structopt(short = "f", long)] pub file: Option, @@ -51,6 +55,7 @@ impl Cli { } #[derive(Debug, Clone, StructOpt)] +#[structopt(name = format ! ("{}\nAuthor: {}\nVersion: {}", ASCII_NAME, AUTHORS, PKG_NAME))] pub enum SubCmd { /// Execute batch form sql file, eg: `iotdb file ddl.sql` File { file_path: Option }, @@ -64,13 +69,13 @@ pub enum SubCmd { export: Option, }, - /// Load TsFile util(TODO) + /// Load TsFile util (TODO) Load, /// Print usage info Usage, - /// Update binary(TODO) + /// Update binary (TODO) Update, /// Prints version information diff --git a/src/static/usage_info b/src/static/usage_info index b28d18a..0d0a01c 100644 --- a/src/static/usage_info +++ b/src/static/usage_info @@ -1,49 +1,49 @@ -Usage info: - DDL & DQL: +usage info: + ddl & dql: 01. `set storage group to root.ln` 02. `show storage group` | `show storage group root.*` - 03. `DELETE STORAGE GROUP root.ln` | `DELETE STORAGE GROUP root.*` - 04. `create timeseries root.ln.wf01.wt01.status with datatype=BOOLEAN,encoding=PLAIN` - 05. `CREATE ALIGNED TIMESERIES root.ln.wf01.GPS(latitude FLOAT encoding=PLAIN compressor=SNAPPY, longitude FLOAT encoding=PLAIN compressor=SNAPPY)` + 03. `delete storage group root.ln` | `delete storage group root.*` + 04. `create timeseries root.ln.wf01.wt01.status with datatype=boolean,encoding=plain` + 05. `create aligned timeseries root.ln.wf01.gps(latitude float encoding=plain compressor=snappy, longitude float encoding=plain compressor=snappy)` 06. `delete timeseries root.ln.wf01.wt01.status` | `delete timeseries root.ln.wf01.wt01.*` 07. `show timeseries root.*` - 08. `COUNT TIMESERIES root.*` - 09. `SHOW CHILD PATHS pathPattern` - 10. `SHOW CHILD NODES pathPattern` - 11. `COUNT NODES root.** LEVEL=2` + 08. `count timeseries root.*` + 09. `show child paths pathpattern` + 10. `show child nodes pathpattern` + 11. `count nodes root.** level=2` 12. `show devices` | `show devices root.ln.*` - 13. `create schema template temp1(GPS(lat FLOAT encoding=Gorilla, lon FLOAT encoding=Gorilla) compression=SNAPPY, status BOOLEAN encoding=PLAIN compression=SNAPPY)` + 13. `create schema template temp1(gps(lat float encoding=gorilla, lon float encoding=gorilla) compression=snappy, status boolean encoding=plain compression=snappy)` 14. `set schema template temp1 to root.ln.wf01` 15. `unset schema template temp1 from root.beijing` 16. `set ttl to root.ln 3600000` 17. `unset ttl to root.ln` - 18. `SHOW ALL TTL` | `SHOW TTL ON StorageGroupNames` - DML: + 18. `show all ttl` | `show ttl on storagegroupnames` + dml: 01. `insert into root.ln.wf02.wt02(timestamp,status) values(1,true)` - 02. `select temperature from root.ln.wf01.wt01 where time < 2017-11-01T00:08:00.000` + 02. `select temperature from root.ln.wf01.wt01 where time < 2017-11-01t00:08:00.000` 03. `select s1, - s1, s2, + s2, s1 + s2, s1 - s2, s1 * s2, s1 / s2, s1 % s2 from root.sg.d1` 04. `select count(status) from root.ln.wf01.wt01` - 05. `select from where time = fill([previous, ], …)` - 06. `select last [COMMA ]* from < PrefixPath > [COMMA < PrefixPath >]* ` + 05. `select from where time = fill([previous, ], …)` + 06. `select last [comma ]* from < prefixpath > [comma < prefixpath >]* ` 07. `select * from root.sg.device where value like '%cc%'` 08. `select s1 as temperature, s2 as speed from root.ln.wf01.wt01` 09. `select status, temperature from root.ln.wf01.wt01 limit 10` - 10. `select * from root.ln.* where time <= 2017-11-01T00:01:00 WITHOUT NULL ANY` - 11. `select * from root.ln.* where time <= 2017-11-01T00:01:00 align by device` - 12. `delete from root.ln.wf02.wt02.status where time<=2017-11-01T16:26:00` - 13. `delete from root.ln.wf02.wt02 where time <= 2017-11-01T16:26:00` - 14. `DELETE PARTITION root.ln 0,1,2` - Other: - 01. `FLUSH` | `FLUSH root.ln` - 02. `MERGE` | `FULL MERGE` - 03. `CLEAR CACHE` - 04. `SET SYSTEM TO READONLY` - 05. `CREATE SNAPSHOT FOR SCHEMA` - 06. `KILL QUERY ` -Useful links: - 01. What is IoTDB: https://iotdb.apache.org/UserGuide/Master/IoTDB-Introduction/What-is-IoTDB.html - 02. SQL guide: https://iotdb.apache.org/UserGuide/Master/IoTDB-SQL-Language/DDL-Data-Definition-Language.html - 03. Data concept: https://iotdb.apache.org/UserGuide/Master/Data-Concept/Data-Model-and-Terminology.html - 04. Advanced features: https://iotdb.apache.org/UserGuide/Master/Advanced-Features/UDF-User-Defined-Function.html - 04. About iotdb-rs: https://github.com/francis-du/iotdb-rs - 05. About iotdb-cli: https://github.com/francis-du/iotdb-cli \ No newline at end of file + 10. `select * from root.ln.* where time <= 2017-11-01t00:01:00 without null any` + 11. `select * from root.ln.* where time <= 2017-11-01t00:01:00 align by device` + 12. `delete from root.ln.wf02.wt02.status where time<=2017-11-01t16:26:00` + 13. `delete from root.ln.wf02.wt02 where time <= 2017-11-01t16:26:00` + 14. `delete partition root.ln 0,1,2` + other: + 01. `flush` | `flush root.ln` + 02. `merge` | `full merge` + 03. `clear cache` + 04. `set system to readonly` + 05. `create snapshot for schema` + 06. `kill query ` +useful links: + 01. what is iotdb: https://iotdb.apache.org/userguide/master/iotdb-introduction/what-is-iotdb.html + 02. sql guide: https://iotdb.apache.org/userguide/master/iotdb-sql-language/ddl-data-definition-language.html + 03. data concept: https://iotdb.apache.org/userguide/master/data-concept/data-model-and-terminology.html + 04. advanced features: https://iotdb.apache.org/userguide/master/advanced-features/udf-user-defined-function.html + 04. about iotdb-rs: https://github.com/francis-du/iotdb-rs + 05. about iotdb-cli: https://github.com/francis-du/iotdb-cli \ No newline at end of file