Skip to content

Commit f7c2d85

Browse files
a bit more explicit (#1)
unquote set params
1 parent 56101cf commit f7c2d85

File tree

2 files changed

+43
-16
lines changed

2 files changed

+43
-16
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ Positional arguments:
4747
Optional arguments:
4848
-c, --command COMMAND Run a single command and exit
4949
-C, --core Preset of settings to connect to Firebolt Core
50-
-h, --host HOSTNAME Hostname to connect to
50+
-h, --host HOSTNAME Hostname (and port) to connect to
5151
-d, --database DATABASE Database name to use
5252
-f, --format FORMAT Output format (e.g., TabSeparatedWithNames, PSQL, JSONLines_Compact, Vertical, ...)
5353
-e, --extra EXTRA Extra settings in the form --extra <name>=<value>

src/args.rs

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use gumdrop::Options;
22
use serde::{Deserialize, Serialize};
3-
use std::collections::HashMap;
3+
use std::collections::BTreeMap;
44
use std::fs;
55

66
use crate::utils::{config_path, init_root_path};
@@ -30,12 +30,12 @@ pub struct Args {
3030
#[serde(skip_serializing, skip_deserializing)]
3131
pub core: bool,
3232

33-
#[options(help = "Hostname to connect to", meta = "HOSTNAME")]
33+
#[options(help = "Hostname (and port) to connect to", meta = "HOSTNAME")]
3434
#[serde(default)]
3535
pub host: String,
3636

3737
#[options(help = "Database name to use")]
38-
#[serde(default)]
38+
#[serde(skip_serializing, skip_deserializing)]
3939
pub database: String,
4040

4141
#[options(help = "Output format (e.g., TabSeparatedWithNames, PSQL, JSONLines_Compact, Vertical, ...)")]
@@ -112,15 +112,27 @@ pub struct Args {
112112
}
113113

114114
pub fn normalize_extras(extras: Vec<String>, encode: bool) -> Result<Vec<String>, Box<dyn std::error::Error>> {
115-
let x: HashMap<&str, String> = HashMap::from_iter(extras.iter().map(|e| {
115+
let mut x: BTreeMap<String, String> = BTreeMap::new();
116+
117+
for e in &extras {
116118
let kv: Vec<&str> = e.split('=').collect();
117119
if kv.len() < 2 {
118-
panic!("Cannot parse '{}': expected key=value format", e)
120+
return Err(format!("Cannot parse '{}': expected key=value format", e).into());
119121
}
120-
let value = kv[1..].join("=").to_string();
121-
// uri encode params
122-
(kv[0], if encode { urlencoding::encode(&value).into_owned() } else { value })
123-
}));
122+
123+
let key = kv[0].to_string();
124+
let value = kv[1..].join("=").trim().to_string();
125+
let value = if value.starts_with('\'') && value.ends_with('\'') || value.starts_with('"') && value.ends_with('"') {
126+
value[1..value.len() - 1].to_string()
127+
} else {
128+
value
129+
};
130+
131+
let value = if encode { urlencoding::encode(&value).into_owned() } else { value };
132+
133+
x.insert(key, value);
134+
}
135+
124136
let mut new_extras: Vec<String> = vec![];
125137
for (key, value) in &x {
126138
new_extras.push(format!("{key}={value}"))
@@ -164,7 +176,6 @@ pub fn get_args() -> Result<Args, Box<dyn std::error::Error>> {
164176

165177
if args.update_defaults {
166178
args.host = args.host.or(default_host);
167-
args.database = args.database.or(String::from("local_dev_db"));
168179
if args.core {
169180
args.format = args.format.or(String::from("PSQL"));
170181
} else {
@@ -179,11 +190,6 @@ pub fn get_args() -> Result<Args, Box<dyn std::error::Error>> {
179190
args.concise = args.concise || defaults.concise;
180191
args.hide_pii = args.hide_pii || defaults.hide_pii;
181192

182-
args.database = args
183-
.database
184-
.or(args.core.then(|| String::from("firebolt")).unwrap_or(defaults.database))
185-
.or(String::from("local_dev_db"));
186-
187193
if args.core {
188194
args.host = args.host.or(String::from("localhost:3473"));
189195
args.jwt = String::from("");
@@ -313,4 +319,25 @@ mod tests {
313319
assert!(url.contains("param=value%20with%20spaces"));
314320
assert!(!url.contains("param=value%2520with%2520spaces")); // No double encoding
315321
}
322+
323+
#[test]
324+
fn test_params_with_quotes() {
325+
let extras = vec!["param1='value with spaces'".to_string(), "param2=\"value with spaces\"".to_string()];
326+
let result = normalize_extras(extras, true).unwrap();
327+
assert_eq!(result[0], "param1=value%20with%20spaces");
328+
assert_eq!(result[1], "param2=value%20with%20spaces");
329+
}
330+
331+
#[test]
332+
fn test_params_with_spaces() {
333+
let extras = vec![
334+
"param1= value with spaces ".to_string(),
335+
"param2= \"value with spaces\" ".to_string(),
336+
"param3=\" value with spaces \"".to_string(),
337+
];
338+
let result = normalize_extras(extras, true).unwrap();
339+
assert_eq!(result[0], "param1=value%20with%20spaces");
340+
assert_eq!(result[1], "param2=value%20with%20spaces");
341+
assert_eq!(result[2], "param3=%20%20value%20with%20spaces%20");
342+
}
316343
}

0 commit comments

Comments
 (0)