feat(search): Add indexes and text search commands#22
Conversation
| let columns = match select.as_deref() { | ||
| Some(cols) => format!("{}, score", cols), |
There was a problem hiding this comment.
The columns value built from --select is interpolated directly into the SQL SELECT list without any sanitization, while table, column, and query are all escaped with replace('\'', "''"). Those three are escaped because they're SQL string literals inside bm25_search(...). columns is in the identifier position (SELECT clause) and needs different handling — either validate against a known-safe pattern (e.g., only [a-zA-Z0-9_, ]) or quote each identifier individually.
As-is, --select "1 FROM other_table --" produces:
SELECT 1 FROM other_table --, score FROM bm25_search(...)| let mut jobs = fetch_jobs(&client, &api_key, &api_url, workspace_id, job_type, Some("pending"), limit, offset); | ||
| jobs.extend(fetch_jobs(&client, &api_key, &api_url, workspace_id, job_type, Some("running"), limit, offset)); | ||
| jobs | ||
| fetch_jobs(&client, &api_key, &api_url, workspace_id, job_type, Some("pending,running"), limit, offset) |
There was a problem hiding this comment.
This collapses two explicit API calls (one for "pending", one for "running") into a single call with "pending,running". That's cleaner, but it implicitly depends on the API accepting comma-separated status values. If the API doesn't support that syntax it will silently return an empty or wrong result set rather than erroring.
Worth either confirming the API contract supports this, or adding a note/test that exercises the combined-status path.
| fn first_row_width(rows: &[Vec<String>], col: usize) -> usize { | ||
| rows.first() | ||
| .and_then(|r| r.get(col)) | ||
| .map(|s| s.len()) | ||
| .unwrap_or(0) | ||
| } |
There was a problem hiding this comment.
This samples only the first data row to determine how much space to reserve for ID columns. If later rows have longer IDs the column will still be allocated the first-row width and tabled will wrap or truncate them. Consider using rows.iter().map(|r| r.get(col).map_or(0, |s| s.len())).max().unwrap_or(0) to get the actual max width across all rows.
| let non_id_count = num_cols - id_col_indices.len(); | ||
| let overhead = 1; // final border character | ||
| let remaining = tw.saturating_sub(id_total + overhead); | ||
| let non_id_width = if non_id_count > 0 { remaining / non_id_count } else { 0 }; |
There was a problem hiding this comment.
If the terminal is very narrow relative to the ID columns, remaining saturates to 0 and non_id_width becomes 0. Passing Width::wrap(0) to tabled collapses those columns entirely. A small floor (e.g., non_id_width.max(8)) would degrade more gracefully.
No description provided.