Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 111 additions & 9 deletions src/commands/indexes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,19 +81,29 @@ pub enum IndexesCommands {

/// Delete an index from a table
///
/// Pass connection scope: --connection-id + --schema + --table.
/// Scope with `--catalog <alias>` (the same flag as `indexes create`) or
/// `--connection-id <id>`, plus `--table` (and `--schema`, default `public`).
Delete {
/// Connection ID (use with --schema and --table)
#[arg(long, short = 'c', requires_all = ["schema", "table"])]
/// SQL catalog alias of the target database (e.g. `--catalog airbnb`) —
/// resolved to the backing connection, the same flag `indexes create` uses
#[arg(
long,
conflicts_with = "connection_id",
required_unless_present = "connection_id"
)]
catalog: Option<String>,

/// Connection ID (advanced; prefer --catalog)
#[arg(long, short = 'c', required_unless_present = "catalog")]
connection_id: Option<String>,

/// Schema name (requires --connection-id)
#[arg(long, requires = "connection_id")]
schema: Option<String>,
/// Schema name (default: public)
#[arg(long, default_value = "public")]
schema: String,

/// Table name (requires --connection-id)
#[arg(long, requires = "connection_id")]
table: Option<String>,
/// Table name
#[arg(long)]
table: String,

/// Index name
#[arg(long)]
Expand Down Expand Up @@ -1325,4 +1335,96 @@ mod tests {
assert!(result.is_err());
assert!(result.unwrap_err().contains("has no columns"));
}

mod delete_args {
use crate::commands::indexes::IndexesCommands;
use clap::Parser;

#[derive(Parser)]
struct Wrapper {
#[command(subcommand)]
cmd: IndexesCommands,
}

fn parse(args: &[&str]) -> Result<IndexesCommands, clap::Error> {
Wrapper::try_parse_from(std::iter::once("t").chain(args.iter().copied())).map(|w| w.cmd)
}

#[test]
fn delete_catalog_defaults_schema_to_public() {
let cmd = parse(&[
"delete",
"--catalog",
"vtest",
"--table",
"hits",
"--name",
"idx",
])
.unwrap();
match cmd {
IndexesCommands::Delete {
catalog,
connection_id,
schema,
table,
name,
} => {
assert_eq!(catalog.as_deref(), Some("vtest"));
assert_eq!(connection_id, None);
assert_eq!(schema, "public"); // defaulted, parity with `create`
assert_eq!(table, "hits");
assert_eq!(name, "idx");
}
_ => panic!("expected Delete"),
}
}

#[test]
fn delete_accepts_raw_connection_id() {
let cmd = parse(&[
"delete",
"--connection-id",
"conn_x",
"--table",
"hits",
"--name",
"idx",
])
.unwrap();
assert!(matches!(
cmd,
IndexesCommands::Delete { connection_id, catalog: None, .. } if connection_id.as_deref() == Some("conn_x")
));
}

#[test]
fn delete_requires_a_scope_flag() {
// neither --catalog nor --connection-id
assert!(parse(&["delete", "--table", "hits", "--name", "idx"]).is_err());
}

#[test]
fn delete_rejects_catalog_and_connection_id_together() {
assert!(
parse(&[
"delete",
"--catalog",
"x",
"--connection-id",
"c",
"--table",
"t",
"--name",
"n"
])
.is_err()
);
}

#[test]
fn delete_requires_table() {
assert!(parse(&["delete", "--catalog", "x", "--name", "idx"]).is_err());
}
}
}
39 changes: 23 additions & 16 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -651,29 +651,36 @@ fn main() {
)
}
IndexesCommands::Delete {
catalog,
connection_id,
schema,
table,
name,
} => {
let scope = match (
connection_id.as_deref(),
schema.as_deref(),
table.as_deref(),
) {
(Some(cid), Some(sch), Some(tbl)) => indexes::IndexScope::Connection {
connection_id: cid,
schema: sch,
table: tbl,
},
_ => {
eprintln!(
"error: provide all three of --connection-id, --schema, --table"
);
std::process::exit(1);
// clap guarantees exactly one of --catalog / --connection-id
// plus --table and --name; --schema defaults to "public".
// A `--catalog` alias resolves to the backing connection
// (incl. a managed database's default connection), the same
// way `indexes create` does; `--connection-id` is used as-is.
let conn_id = match (catalog, connection_id) {
(Some(cat), _) => {
let api = sdk::Api::new(Some(&workspace_id));
connections::resolve_connection_id(&api, &cat)
}
(None, Some(cid)) => cid,
(None, None) => {
unreachable!("clap requires --catalog or --connection-id")
}
};
indexes::delete(&workspace_id, scope, &name);
indexes::delete(
&workspace_id,
indexes::IndexScope::Connection {
connection_id: &conn_id,
schema: &schema,
table: &table,
},
&name,
);
}
}
}
Expand Down
Loading