Skip to content

Commit ab3d8b7

Browse files
committed
fix(databases): implement dot-notation schema parsing in create_database_request
The --table flag doc comments claimed that `schema.table` entries would land in the named schema, but the implementation was sending literal strings as table names inside a single schema. This implements the promised behavior: entries with a dot are split into (schema, table) and grouped accordingly, bare names fall back to the --schema default. Adds a test covering the multi-schema case. Also removes an extra blank line between resolve_database and schema_name.
1 parent 066dccf commit ab3d8b7

1 file changed

Lines changed: 46 additions & 8 deletions

File tree

src/databases.rs

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,6 @@ pub fn resolve_database(api: &ApiClient, id_or_name: &str) -> Database {
132132
}
133133
}
134134

135-
136135
fn schema_name(schema: Option<&str>) -> &str {
137136
schema.unwrap_or(DEFAULT_SCHEMA)
138137
}
@@ -162,14 +161,31 @@ pub fn create_database_request(
162161
}
163162

164163
if !tables.is_empty() {
165-
let table_objs: Vec<serde_json::Value> = tables
166-
.iter()
167-
.map(|t| serde_json::json!({ "name": t }))
164+
// Group tables by schema, preserving insertion order.
165+
// Dot-notation entries (e.g. "raw.raw_orders") use the named schema;
166+
// bare names fall back to the `schema` argument.
167+
let mut schema_tables: Vec<(String, Vec<String>)> = Vec::new();
168+
for t in tables {
169+
let (s, table_name) = match t.split_once('.') {
170+
Some((s, tbl)) => (s.to_string(), tbl.to_string()),
171+
None => (schema.to_string(), t.to_string()),
172+
};
173+
if let Some(entry) = schema_tables.iter_mut().find(|(n, _)| n == &s) {
174+
entry.1.push(table_name);
175+
} else {
176+
schema_tables.push((s, vec![table_name]));
177+
}
178+
}
179+
let schemas_json: Vec<serde_json::Value> = schema_tables
180+
.into_iter()
181+
.map(|(s, tbls)| {
182+
serde_json::json!({
183+
"name": s,
184+
"tables": tbls.iter().map(|t| serde_json::json!({ "name": t })).collect::<Vec<_>>()
185+
})
186+
})
168187
.collect();
169-
req.insert(
170-
"schemas".to_string(),
171-
serde_json::json!([{ "name": schema, "tables": table_objs }]),
172-
);
188+
req.insert("schemas".to_string(), serde_json::Value::Array(schemas_json));
173189
}
174190

175191
if let Some(exp) = expires_at {
@@ -764,6 +780,28 @@ mod tests {
764780
assert!(req.get("expires_at").is_none());
765781
}
766782

783+
#[test]
784+
fn create_database_request_dot_notation_groups_tables_by_schema() {
785+
let req = create_database_request(
786+
None,
787+
None,
788+
"public",
789+
&[
790+
"orders".to_string(),
791+
"raw.raw_orders".to_string(),
792+
"raw.raw_customers".to_string(),
793+
],
794+
None,
795+
);
796+
// bare "orders" → default schema "public"
797+
assert_eq!(req["schemas"][0]["name"], "public");
798+
assert_eq!(req["schemas"][0]["tables"][0]["name"], "orders");
799+
// dot-notation entries → "raw" schema, table name is the part after the dot
800+
assert_eq!(req["schemas"][1]["name"], "raw");
801+
assert_eq!(req["schemas"][1]["tables"][0]["name"], "raw_orders");
802+
assert_eq!(req["schemas"][1]["tables"][1]["name"], "raw_customers");
803+
}
804+
767805
fn full_detail(id: &str, name: &str, conn_id: &str) -> String {
768806
format!(
769807
r#"{{"id":"{id}","name":"{name}","default_connection_id":"{conn_id}","attachments":[]}}"#

0 commit comments

Comments
 (0)