Repository navigation
File-backed query history, project-scoped config, edit-in-editor - #224
Closed
PeterAdams-ecitsolutions wants to merge 9 commits into
Closed
PeterAdams-ecitsolutions wants to merge 9 commits into
PeterAdams-ecitsolutions wants to merge 9 commits into
Conversation
History moves from a single `query_history.json` to per-query `.sql` files under `<config>/queries/<connection>/<timestamp>_<hash>.sql`, each with a small `-- sqlit:history` header (connection, database, timestamp). Files sort chronologically by name and grep cleanly. Re-running an existing query (same content after `strip()`) deletes the old file and writes a fresh one with the new timestamp, so dedup remains content-based and the most-recent timestamp wins. The 100- entry-per-connection cap is enforced by lex-order eviction. Public API (`HistoryStore` methods) is unchanged so existing callers in `query_execution.py` and `services.py` keep working. A one-time migration on first construct fans out any legacy `query_history.json` into the new tree and renames it to `.migrated`.
Passing a directory as the first positional arg routes connections, query history, and starred queries into `<dir>/.sqlit/` instead of the global config. Theme, settings, and credentials (keyring) stay global. `sqlit .` resolves to the current shell directory; a missing directory errors out cleanly with exit code 1. Use case: a team can commit `<repo>/.sqlit/connections.json` and useful saved queries to share project-specific db setup, while each developer keeps their personal theme/keyring out of the repo. `ConnectionStore` and `StarredStore` gain a `file_path` constructor arg; `HistoryStore` already accepts `base_dir`. `RuntimeConfig` gains `project_dir` plus a `project_config_dir` helper. `build_app_services` threads these into the stores when `project_dir` is set.
When the query editor has focus, the leader menu picks up a new "Edit in editor" entry. On first use (or when the saved preference is no longer installed) a picker pops up listing detected terminal editors (nvim, vim, helix, kakoune, micro, nano, emacs, vi). Missing ones are grayed out. The selection is saved to settings as `preferred_editor`. The action writes the current query buffer to a temp `.sql` file with a meaningful name (`sqlit-edit-<timestamp>-XXXX.sql`), suspends the TUI via `app.suspend()`, runs the editor blocking on that file, then loads the result back into the buffer. When the connection is saved, the edited text is also saved to history as a new entry — so edits land in the file-backed history regardless of whether they were executed. No-op edits short-circuit.
Capital `E` required Shift; `o` is unused in the global leader menu (e/f/c/x/z/t/h/space/slash/q are taken). Action and behavior unchanged.
The action was silent in the empty-state cases. Add user-visible notifications: - No installed editor anywhere → error notification with install hint; the picker no longer opens (all options would be disabled anyway). - Picker about to open → info notification explaining first-time setup. - Picker cancelled → warning notification. - Editor closed with no changes → info notification. - Buffer updated from editor → info notification.
When the guard failed (focus ≠ "query"), `resolve_action` returned None for the leader resolution, then `on_key` cancelled leader-pending and retried the raw key. In query NORMAL mode that retry resolved `o` to vim's `open_line_below` action, which silently inserted a blank line — looking like "nothing happened" to the user. The action handles an empty buffer fine, so the guard isn't needed. Drop it so space+o always reaches the editor regardless of which pane has focus.
The `-- database:` and `-- ran:` header lines were carrying data that
already had a natural home in the filesystem:
- `database` → subdirectory under the connection dir. Multi-database
connections (Postgres, MSSQL, etc.) get one subdir per db; single-
database engines (SQLite, DuckDB) keep files flat under the connection
dir. Loading walks both levels.
- `ran:` timestamp → already in the filename prefix
(`YYYY-MM-DDTHH-MM-SS_<hash>.sql`).
Header collapses to two lines:
-- sqlit:history
-- connection: postgres-prod
SELECT * FROM users
Eviction still operates per-connection (summing files across db subdirs);
re-running an existing query continues to dedup by query hash even when
the database moves between executions.
Files written under the previous v1 layout are migrated in-place: each
file's `-- database:` header is read, the file moves into the
appropriate subdir, and the header is rewritten in the trimmed form.
Nobody has v1 files in the wild — that layout only existed in the earlier commits of this PR. Removing the migration code and its tests. The legacy JSON migration is unrelated and stays.
The previous logic deleted any same-hash file across every database subdir on the connection, so running the same query against two databases silently destroyed the older entry. With database as a structural part of the path, the same query against different databases is two legitimately distinct events — dedup should be per (conn, db), matching the path layout. The test that locked in the wrong behavior is replaced with one asserting both entries are preserved, plus a complementary test that re-running the same query against the same database still collapses to a single file.
Owner
|
Reopening as a Maxteabag-authored PR — see #225. |
Owner
|
Correction: reopened as #226. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Three related changes that build on each other:
File-backed query history —
query_history.jsonbecomes per-query.sqlfiles under<config>/queries/<connection>/<timestamp>_<hash>.sqlwith a small-- sqlit:historyheader. Re-running the same query touches the existing file instead of duplicating. Old JSON is migrated once on first launch.Project-scoped config —
sqlit .orsqlit /path/to/reporoutes connections, history, and starred queries into<project>/.sqlit/so a team can commit shared db setup and useful queries to a repo. Theme, settings, and credentials stay global.space + Eto edit query in terminal editor — leader-menu command that opens the current query in your$VISUAL/$EDITOR(or a picker on first use). Edited content replaces the buffer and saves to history regardless of execution.Test coverage: 60+ new tests across
tests/unit/andtests/ui/covering the store, the project-dir routing, editor detection, and the leader-command guard.