Skip to content

Commit 4fa9b95

Browse files
authored
feat: support get/put stmt (#198)
1 parent 5c39cc9 commit 4fa9b95

File tree

20 files changed

+273
-16
lines changed

20 files changed

+273
-16
lines changed

Cargo.toml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ members = [
1111
]
1212

1313
[workspace.package]
14-
version = "0.6.2"
14+
version = "0.6.3"
1515
edition = "2021"
1616
license = "Apache-2.0"
1717
authors = ["Databend Authors <[email protected]>"]
@@ -20,7 +20,7 @@ keywords = ["databend", "database"]
2020
repository = "https://github.com/datafuselabs/bendsql"
2121

2222
[workspace.dependencies]
23-
databend-client = { path = "core", version = "0.6.2" }
24-
databend-driver = { path = "driver", version = "0.6.2" }
25-
databend-driver-macros = { path = "macros", version = "0.6.2" }
26-
databend-sql = { path = "sql", version = "0.6.2" }
23+
databend-client = { path = "core", version = "0.6.3" }
24+
databend-driver = { path = "driver", version = "0.6.3" }
25+
databend-driver-macros = { path = "macros", version = "0.6.3" }
26+
databend-sql = { path = "sql", version = "0.6.3" }

bindings/nodejs/npm/darwin-arm64/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@databend-driver/lib-darwin-arm64",
33
"repository": "https://github.com/datafuselabs/bendsql.git",
4-
"version": "0.6.2",
4+
"version": "0.6.3",
55
"os": [
66
"darwin"
77
],

bindings/nodejs/npm/darwin-x64/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@databend-driver/lib-darwin-x64",
33
"repository": "https://github.com/datafuselabs/bendsql.git",
4-
"version": "0.6.2",
4+
"version": "0.6.3",
55
"os": [
66
"darwin"
77
],

bindings/nodejs/npm/linux-x64-gnu/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@databend-driver/lib-linux-x64-gnu",
33
"repository": "https://github.com/datafuselabs/bendsql.git",
4-
"version": "0.6.2",
4+
"version": "0.6.3",
55
"os": [
66
"linux"
77
],

bindings/nodejs/npm/win32-x64-msvc/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@databend-driver/lib-win32-x64-msvc",
33
"repository": "https://github.com/datafuselabs/bendsql.git",
4-
"version": "0.6.2",
4+
"version": "0.6.3",
55
"os": [
66
"win32"
77
],

bindings/nodejs/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "databend-driver",
33
"author": "Databend Authors <[email protected]>",
4-
"version": "0.6.2",
4+
"version": "0.6.3",
55
"license": "Apache-2.0",
66
"main": "index.js",
77
"types": "index.d.ts",

cli/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,13 @@ Bye
9090
2
9191
```
9292

93+
### Put local files into stage
94+
95+
```
96+
create stage s_temp;
97+
put fs:///tmp/a*.txt @s_temp/abc;
98+
```
99+
93100
## Features
94101

95102
- basic keywords highlight

cli/src/ast/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,13 @@ mod tokenizer;
1717
use sqlformat::{Indent, QueryParams};
1818
pub use tokenizer::*;
1919

20+
use crate::session::QueryKind;
21+
2022
pub fn format_query(query: &str) -> String {
23+
let kind = QueryKind::from(query);
24+
if kind == QueryKind::Put || kind == QueryKind::Get {
25+
return query.to_owned();
26+
}
2127
let options = sqlformat::FormatOptions {
2228
indent: Indent::Spaces(2),
2329
uppercase: true,

cli/src/ast/tokenizer.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,8 @@ pub enum TokenKind {
476476
TABLE_FUNCTIONS,
477477
#[token("FUSE", ignore(ascii_case))]
478478
FUSE,
479+
#[token("GET", ignore(ascii_case))]
480+
GET,
479481
#[token("GLOBAL", ignore(ascii_case))]
480482
GLOBAL,
481483
#[token("GRAPH", ignore(ascii_case))]
@@ -634,6 +636,8 @@ pub enum TokenKind {
634636
PROCESSLIST,
635637
#[token("PURGE", ignore(ascii_case))]
636638
PURGE,
639+
#[token("PUT", ignore(ascii_case))]
640+
PUT,
637641
#[token("QUARTER", ignore(ascii_case))]
638642
QUARTER,
639643
#[token("QUERY", ignore(ascii_case))]

cli/src/session.rs

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,12 @@ impl Session {
205205
return vec![];
206206
}
207207

208-
if self.query.is_empty() && (line.starts_with('.') || line == "exit" || line == "quit") {
208+
if self.query.is_empty()
209+
&& (line.starts_with('.')
210+
|| line == "exit"
211+
|| line == "quit"
212+
|| line.to_uppercase().starts_with("PUT"))
213+
{
209214
return vec![line.to_owned()];
210215
}
211216

@@ -316,13 +321,33 @@ impl Session {
316321
}
317322
Ok(false)
318323
}
319-
_ => {
324+
other => {
320325
let replace_newline = !if self.settings.replace_newline {
321326
false
322327
} else {
323328
replace_newline_in_box_display(query)
324329
};
325-
let (schema, data) = self.conn.query_iter_ext(query).await?;
330+
331+
let (schema, data) = match other.0 {
332+
QueryKind::Put => {
333+
let args: Vec<String> = get_put_get_args(query);
334+
if args.len() != 3 {
335+
eprintln!("Put args are invalid, must be 2 argruments");
336+
return Ok(false);
337+
}
338+
self.conn.put_files(&args[1], &args[2]).await?
339+
}
340+
QueryKind::Get => {
341+
let args: Vec<String> = get_put_get_args(query);
342+
if args.len() != 3 {
343+
eprintln!("Put args are invalid, must be 2 argruments");
344+
return Ok(false);
345+
}
346+
self.conn.get_files(&args[1], &args[2]).await?
347+
}
348+
_ => self.conn.query_iter_ext(query).await?,
349+
};
350+
326351
let mut displayer = FormatDisplay::new(
327352
&self.settings,
328353
query,
@@ -413,6 +438,8 @@ pub enum QueryKind {
413438
Query,
414439
Update,
415440
Explain,
441+
Put,
442+
Get,
416443
}
417444

418445
impl From<&str> for QueryKind {
@@ -421,6 +448,8 @@ impl From<&str> for QueryKind {
421448
match tz.next() {
422449
Some(Ok(t)) => match t.kind {
423450
TokenKind::EXPLAIN => QueryKind::Explain,
451+
TokenKind::PUT => QueryKind::Put,
452+
TokenKind::GET => QueryKind::Get,
424453
TokenKind::ALTER
425454
| TokenKind::DELETE
426455
| TokenKind::UPDATE
@@ -436,6 +465,13 @@ impl From<&str> for QueryKind {
436465
}
437466
}
438467

468+
fn get_put_get_args(query: &str) -> Vec<String> {
469+
query
470+
.split_ascii_whitespace()
471+
.map(|x| x.to_owned())
472+
.collect()
473+
}
474+
439475
fn replace_newline_in_box_display(query: &str) -> bool {
440476
let mut tz = Tokenizer::new(query);
441477
match tz.next() {

cli/tests/http/04-put.result

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/tmp/a1.txt SUCCESS
2+
/tmp/a2.txt SUCCESS
3+
/tmp/edf/a1.txt SUCCESS
4+
/tmp/edf/a2.txt SUCCESS

cli/tests/http/04-put.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/bin/bash
2+
3+
echo "CREATE STAGE ss_temp" | ${BENDSQL}
4+
5+
echo "ABCD" > /tmp/a1.txt
6+
echo "ABCD" > /tmp/a2.txt
7+
8+
echo 'put fs:///tmp/a*.txt @ss_temp/abc' | ${BENDSQL}
9+
echo 'get @ss_temp/abc fs:///tmp/edf' | ${BENDSQL}

core/src/client.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ impl TryFrom<&str> for StageLocation {
8080

8181
#[derive(Clone)]
8282
pub struct APIClient {
83-
cli: HttpClient,
83+
pub cli: HttpClient,
8484
endpoint: Url,
8585
pub host: String,
8686
pub port: u16,
@@ -437,7 +437,7 @@ impl APIClient {
437437
}
438438
}
439439

440-
async fn upload_to_stage_with_stream(
440+
pub async fn upload_to_stage_with_stream(
441441
&self,
442442
stage_location: &str,
443443
data: impl AsyncRead + Send + Sync + 'static,

driver/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ databend-sql = { workspace = true }
3333
async-trait = "0.1.68"
3434
chrono = { version = "0.4.26", default-features = false, features = ["clock"] }
3535
dyn-clone = "1.0.11"
36+
futures = "0.3.28"
37+
glob = "0.3.1"
3638
http = "0.2.9"
3739
percent-encoding = "2.3.0"
3840
serde = { version = "1.0.164", default-features = false, features = ["derive"] }

driver/src/conn.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,5 +97,25 @@ pub trait Connection: DynClone + Send + Sync {
9797
file_format_options: Option<BTreeMap<&str, &str>>,
9898
copy_options: Option<BTreeMap<&str, &str>>,
9999
) -> Result<QueryProgress>;
100+
101+
async fn put_files(
102+
&self,
103+
_local_file: &str,
104+
_stage_path: &str,
105+
) -> Result<(Schema, RowProgressIterator)> {
106+
Err(Error::IO(
107+
"PUT statement only available in HTTP API".to_owned(),
108+
))
109+
}
110+
111+
async fn get_files(
112+
&self,
113+
_stage_path: &str,
114+
_local_file: &str,
115+
) -> Result<(Schema, RowProgressIterator)> {
116+
Err(Error::IO(
117+
"GET statement only available in HTTP API".to_owned(),
118+
))
119+
}
100120
}
101121
dyn_clone::clone_trait_object!(Connection);

0 commit comments

Comments
 (0)