Skip to content

Commit 07e76bc

Browse files
committed
fix(search): scope index create to managed databases; guard sorted in run
Close the create/show/remove asymmetry the review flagged: `search create` resolved any catalog `connections::resolve_connection_id` matched — including a plain connection — while `search show`/`search remove` (via `locate_by_name`) require a managed database. An index created on a connection was therefore listable but neither showable nor removable, and top-level `indexes delete` is gone in this PR, so it had no deletion path. Indexes are a managed-database concept (connections are a legacy concept being removed), so `create` now resolves `--from`'s catalog through `databases::try_resolve_database` and uses the database's own `default_connection_id`; a plain connection is rejected with a clear message. create/show/remove now agree on managed databases. Also guard `search run` against a `sorted` index (not a retrieval type) — it previously fell into the vector branch and emitted an opaque `vector_distance` error; it now points the user at `hotdata query`. Docs: search SKILL notes indexes are managed-database only and adds the `search show` command block.
1 parent 476d7bf commit 07e76bc

2 files changed

Lines changed: 39 additions & 7 deletions

File tree

‎skills/hotdata/subskills/search/SKILL.md‎

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,20 +47,23 @@ hotdata search "<query>" --in <name>
4747

4848
## Indexes (text and vector)
4949

50-
Create names the index (positional) and attaches to a table via `--from <catalog.schema.table>` (a managed database or an attached catalog). `list` narrows to the **active database** when one is set; without one it scans the whole workspace. `remove` takes the index name.
50+
Indexes are a **managed-database** concept. Create names the index (positional) and attaches to a table on a managed database via `--from` — `catalog.schema.table` (the managed database's catalog), or `schema.table` with an active database set. A plain connection catalog is rejected. `list` narrows to the **active database** when one is set; without one it scans the whole workspace. `show`/`remove` resolve the index by name in the active database (or `--database <id>`).
5151

5252
```bash
5353
# List — active-database scope when a DB is set, else whole-workspace scan
5454
hotdata search list [--workspace-id <ws>] [--output table|json|yaml]
5555

56-
# Create — index name is positional; --from is catalog.schema.table
56+
# Create — index name is positional; --from is a managed database's table
5757
hotdata search create <name> --type text|vector --from <catalog.schema.table> \
5858
--column <col> \
5959
[--metric l2|cosine|dot] [--async] \
6060
[--provider <id>] [--dimensions <n>] [--output-column <name>] [--description <text>]
6161

62-
# Remove — by index name
63-
hotdata search remove <name>
62+
# Show — by index name, in the active database (or -d/--database <id>)
63+
hotdata search show <name> [-d <db-id>] [--output table|json|yaml]
64+
65+
# Remove — by index name, in the active database (or -d/--database <id>)
66+
hotdata search remove <name> [-d <db-id>]
6467
```
6568

6669
- **`--type` is required** on create: `text` (BM25; one or more text columns, comma-separated in `--column`) or `vector` (exactly one column; often embeddings or auto-embedded text). (`sorted` is also a valid `--type`, covered in **`hotdata-analytics`** — [`../analytics/SKILL.md`](../analytics/SKILL.md).)

‎src/commands/search.rs‎

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
use crate::client::sdk::Api;
1010
use crate::commands::embedding_providers::{self, EmbeddingProvidersCommands};
1111
use crate::commands::indexes::{self, IndexScope};
12-
use crate::commands::{connections, databases, query};
12+
use crate::commands::{databases, query};
1313

1414
/// Subcommands for `hotdata search`.
1515
#[derive(clap::Subcommand)]
@@ -240,9 +240,26 @@ fn create(
240240
"sorted" => "sorted",
241241
_ => "vector",
242242
};
243-
let (conn_name, schema, table) = parse_table(workspace_id, from);
243+
let (catalog, schema, table) = parse_table(workspace_id, from);
244244
let api = Api::new(Some(workspace_id));
245-
let conn_id = connections::resolve_connection_id(&api, &conn_name);
245+
// Indexes are a managed-database concept. Resolve --from's catalog to a
246+
// managed database and use its connection; reject a plain connection (a
247+
// legacy concept being removed) so create can't make an index that the
248+
// managed-database-only `search show`/`search remove` can't reach.
249+
let db = databases::try_resolve_database(&api, &catalog).unwrap_or_else(|_| {
250+
use crossterm::style::Stylize;
251+
eprintln!(
252+
"{}",
253+
format!(
254+
"error: '{catalog}' is not a managed database. Search indexes are created on \
255+
managed databases — pass a managed database's catalog, or 'schema.table' with an \
256+
active database set via 'hotdata databases use <id>'."
257+
)
258+
.red()
259+
);
260+
std::process::exit(1);
261+
});
262+
let conn_id = db.default_connection_id;
246263
let auto_name = format!("{table}_{}_{index_type}", column.replace(',', "_"));
247264
let index_name = name.unwrap_or(auto_name.as_str());
248265
indexes::create(
@@ -333,6 +350,18 @@ pub fn run(
333350
output: &str,
334351
) {
335352
let loc = locate_or_exit(workspace_id, database, name);
353+
if loc.index_type == "sorted" {
354+
use crossterm::style::Stylize;
355+
eprintln!(
356+
"{}",
357+
format!(
358+
"error: index '{name}' is a sorted index — not searchable. Use 'hotdata query' \
359+
with a WHERE/ORDER BY filter instead."
360+
)
361+
.red()
362+
);
363+
std::process::exit(1);
364+
}
336365
let table_fqn = format!("{}.{}.{}", loc.catalog, loc.schema, loc.table);
337366
let sql = build_search_sql(
338367
&loc.index_type,

0 commit comments

Comments
 (0)