dirsql 0.3.88__tar.gz → 0.3.90__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {dirsql-0.3.88 → dirsql-0.3.90}/Cargo.lock +1 -1
- {dirsql-0.3.88 → dirsql-0.3.90}/PKG-INFO +1 -1
- {dirsql-0.3.88/packages/python → dirsql-0.3.90}/docs/howto/extract-from-contents.md +1 -1
- {dirsql-0.3.88/packages/rust → dirsql-0.3.90}/docs/howto/persist.md +20 -9
- {dirsql-0.3.88/packages/rust → dirsql-0.3.90}/docs/reference/cli.md +5 -0
- {dirsql-0.3.88/packages/rust → dirsql-0.3.90}/docs/reference/config.md +5 -6
- {dirsql-0.3.88/packages/rust → dirsql-0.3.90}/docs/reference/hooks.md +2 -2
- {dirsql-0.3.88 → dirsql-0.3.90}/docs/reference/sdk.md +4 -5
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/python/Cargo.toml +1 -1
- {dirsql-0.3.88/packages/rust → dirsql-0.3.90/packages/python}/docs/howto/extract-from-contents.md +1 -1
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/python/docs/howto/persist.md +20 -9
- {dirsql-0.3.88 → dirsql-0.3.90/packages/python}/docs/reference/cli.md +5 -0
- {dirsql-0.3.88 → dirsql-0.3.90/packages/python}/docs/reference/config.md +5 -6
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/python/docs/reference/hooks.md +2 -2
- {dirsql-0.3.88/packages/rust → dirsql-0.3.90/packages/python}/docs/reference/sdk.md +4 -5
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/python/e2e-attestation.json +2 -2
- {dirsql-0.3.88 → dirsql-0.3.90/packages/rust}/docs/howto/extract-from-contents.md +1 -1
- {dirsql-0.3.88 → dirsql-0.3.90/packages/rust}/docs/howto/persist.md +20 -9
- {dirsql-0.3.88/packages/python → dirsql-0.3.90/packages/rust}/docs/reference/cli.md +5 -0
- {dirsql-0.3.88/packages/python → dirsql-0.3.90/packages/rust}/docs/reference/config.md +5 -6
- {dirsql-0.3.88 → dirsql-0.3.90/packages/rust}/docs/reference/hooks.md +2 -2
- {dirsql-0.3.88/packages/python → dirsql-0.3.90/packages/rust}/docs/reference/sdk.md +4 -5
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/rust/src/bin/dirsql.rs +61 -12
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/rust/src/config.rs +14 -110
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/rust/src/lib.rs +34 -29
- {dirsql-0.3.88 → dirsql-0.3.90}/Cargo.toml +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/README.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/dirsql/__init__.py +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/dirsql/_async.py +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/dirsql/_dirsql.pyi +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/dirsql/cli/__init__.py +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/dirsql/cli/binary_path.py +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/dirsql/cli/is_windows.py +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/dirsql/cli/main.py +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/dirsql/cli/resolve_config_extensions.py +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/dirsql/py.typed +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/dirsql/resolve_config_extensions.py +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/dirsql/resolve_extension.py +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/docs/.claude/CLAUDE.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/docs/.vitepress/config.ts +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/docs/.vitepress/theme/index.ts +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/docs/.vitepress/theme/lang.ts +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/docs/AGENTS.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/docs/explanation.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/docs/getting-started.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/docs/howto/columns-from-paths.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/docs/howto/define-tables.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/docs/howto/embed.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/docs/howto/load-extension.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/docs/howto/react-to-changes.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/docs/howto/search-by-meaning.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/docs/howto/skip-files.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/docs/index.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/docs/migrations.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/docs/package.json +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/docs/playwright.config.ts +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/docs/pnpm-lock.yaml +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/docs/pnpm-workspace.yaml +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/docs/reference/columns.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/docs/reference/http-api.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/docs/tests/integration/home.spec.ts +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/docs/tests/integration/language-flag.spec.ts +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/docs/tests/integration/sidebar.spec.ts +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/docs/tests/unit/config.test.ts +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/docs/tests/unit/lang.test.ts +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/docs/vitest.config.ts +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/python/README.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/python/conftest.py +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/python/docs/.claude/CLAUDE.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/python/docs/.vitepress/config.ts +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/python/docs/.vitepress/theme/index.ts +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/python/docs/.vitepress/theme/lang.ts +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/python/docs/AGENTS.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/python/docs/explanation.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/python/docs/getting-started.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/python/docs/howto/columns-from-paths.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/python/docs/howto/define-tables.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/python/docs/howto/embed.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/python/docs/howto/load-extension.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/python/docs/howto/react-to-changes.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/python/docs/howto/search-by-meaning.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/python/docs/howto/skip-files.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/python/docs/index.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/python/docs/migrations.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/python/docs/package.json +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/python/docs/playwright.config.ts +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/python/docs/pnpm-lock.yaml +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/python/docs/pnpm-workspace.yaml +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/python/docs/reference/columns.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/python/docs/reference/http-api.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/python/docs/tests/integration/home.spec.ts +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/python/docs/tests/integration/language-flag.spec.ts +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/python/docs/tests/integration/sidebar.spec.ts +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/python/docs/tests/unit/config.test.ts +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/python/docs/tests/unit/lang.test.ts +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/python/docs/vitest.config.ts +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/python/src/lib.rs +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/python/tests/__init__.py +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/python/tests/conftest.py +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/python/tests/e2e/__init__.py +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/python/tests/integration/__init__.py +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/python/tests/integration/binding/__init__.py +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/python/tests/integration/hermetic/__init__.py +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/rust/Cargo.toml +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/rust/README.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/rust/benches/db_bench.rs +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/rust/benches/differ_bench.rs +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/rust/benches/matcher_bench.rs +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/rust/benches/scanner_bench.rs +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/rust/docs/explanation.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/rust/docs/getting-started.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/rust/docs/howto/columns-from-paths.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/rust/docs/howto/define-tables.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/rust/docs/howto/embed.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/rust/docs/howto/load-extension.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/rust/docs/howto/react-to-changes.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/rust/docs/howto/search-by-meaning.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/rust/docs/howto/skip-files.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/rust/docs/index.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/rust/docs/migrations.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/rust/docs/reference/columns.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/rust/docs/reference/http-api.md +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/rust/src/cli/execute.rs +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/rust/src/cli/init.rs +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/rust/src/cli/mod.rs +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/rust/src/cli/router.rs +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/rust/src/cli/serialize.rs +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/rust/src/cli/server.rs +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/rust/src/command.rs +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/rust/src/db.rs +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/rust/src/default_config.toml +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/rust/src/differ.rs +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/rust/src/matcher.rs +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/rust/src/persist.rs +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/rust/src/scanner.rs +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/packages/rust/src/watcher.rs +0 -0
- {dirsql-0.3.88 → dirsql-0.3.90}/pyproject.toml +0 -0
|
@@ -23,7 +23,7 @@ glob = "books/*.json"
|
|
|
23
23
|
on-file = "jq -c '[{title, author, year}]' {path}"
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
`{path}` is the matched file
|
|
26
|
+
`{path}` is the matched file's absolute path — one of the
|
|
27
27
|
placeholders defined by the
|
|
28
28
|
[command hook contract](../reference/hooks.md#on-file), which also covers
|
|
29
29
|
the argv splitting, working directory, stdout protocol, and timeout shared
|
|
@@ -1,23 +1,34 @@
|
|
|
1
1
|
# Keep the index across restarts
|
|
2
2
|
|
|
3
3
|
By default the database is ephemeral: rebuilt from your files on every
|
|
4
|
-
startup and discarded on exit. [
|
|
5
|
-
SQLite index on disk instead, so a restart only re-parses
|
|
6
|
-
actually changed — the difference between seconds and
|
|
7
|
-
trees, and between re-running and skipping expensive
|
|
4
|
+
startup and discarded on exit. The [`--persist [PATH]`](../reference/cli.md#server-mode)
|
|
5
|
+
flag keeps the SQLite index on disk instead, so a restart only re-parses
|
|
6
|
+
files that actually changed — the difference between seconds and
|
|
7
|
+
milliseconds on large trees, and between re-running and skipping expensive
|
|
8
8
|
[`on-file`](./extract-from-contents.md) commands.
|
|
9
9
|
|
|
10
|
+
Whether and where to cache is a machine-local operational choice — it
|
|
11
|
+
belongs to the command you run, not to the shared `.dirsql.toml`. That is
|
|
12
|
+
why it is a CLI flag, not a config key.
|
|
13
|
+
|
|
10
14
|
## 1. Turn it on
|
|
11
15
|
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
persist = true
|
|
16
|
+
```bash
|
|
17
|
+
dirsql --persist
|
|
15
18
|
```
|
|
16
19
|
|
|
17
20
|
That's the whole change. On the next run the cache is written to
|
|
18
21
|
`.dirsql/cache.db` under the root; runs after that start from it. To put
|
|
19
|
-
the cache elsewhere (a CI cache dir, a tmpfs),
|
|
20
|
-
|
|
22
|
+
the cache elsewhere (a CI cache dir, a tmpfs), pass a path:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
dirsql --persist /var/cache/dirsql.db
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
The same flag works on [`dirsql query`](../reference/cli.md#dirsql-query);
|
|
29
|
+
put a bare `--persist` after the SQL there so it does not consume the query
|
|
30
|
+
argument. Embedding `dirsql`? The SDK constructors expose the same switch —
|
|
31
|
+
see [_Embedding `dirsql`?_](#embedding-dirsql) below.
|
|
21
32
|
|
|
22
33
|
## 2. Keep the cache out of git
|
|
23
34
|
|
|
@@ -48,6 +48,7 @@ requests, closes open `/events` streams, and exits.
|
|
|
48
48
|
| `-c, --config <path>` | `./.dirsql.toml` | Path to the [config file](./config.md). The index is rooted at the directory containing this file (unless the config sets `[dirsql].root`). When the file does not exist, the server runs in [zero-config mode](#zero-config-mode). |
|
|
49
49
|
| `--host <addr>` | `localhost` | Bind address. |
|
|
50
50
|
| `--port <n>` | `7117` | TCP port to bind. |
|
|
51
|
+
| `--persist [<path>]` | off | Keep the SQLite index on disk between runs so a restart only re-parses files that actually changed. Bare `--persist` caches at `<root>/.dirsql/cache.db`; `--persist <path>` caches at `<path>`. Off by default (the index is ephemeral). Global — also honored by [`dirsql query`](#dirsql-query). See [Keep the index across restarts](../howto/persist.md). |
|
|
51
52
|
| `--extension <path>` | none | Load a SQLite extension by literal path, overriding the config's `[[dirsql.extension]]` entries. Repeatable. Format: `<path>` or `<path>::<entrypoint>`. Internal plumbing for the pip/npm launchers, which resolve package-name extensions and pass the resolved paths here — not intended for direct use. When any `--extension` is present, the config file's own extension entries are not loaded. |
|
|
52
53
|
| `--version` | | Print the version and exit. |
|
|
53
54
|
| `--help` | | Print usage and exit. |
|
|
@@ -119,6 +120,10 @@ uses**, so behavior is identical to `POST /query` by construction:
|
|
|
119
120
|
- **Config discovery** honors `--config` (default `./.dirsql.toml`),
|
|
120
121
|
[zero-config mode](#zero-config-mode), and `--extension` overrides,
|
|
121
122
|
exactly as server mode does.
|
|
123
|
+
- **`--persist [<path>]`** is honored, so a repeated `dirsql query` reuses the
|
|
124
|
+
on-disk cache. Because its value is optional, place a bare `--persist` after
|
|
125
|
+
the SQL (`dirsql query "SELECT …" --persist`) or use the `=` form
|
|
126
|
+
(`--persist=/path`) so it does not swallow the SQL argument.
|
|
122
127
|
- **Hooks** ([`pre-query`](./hooks.md#pre-query) /
|
|
123
128
|
[`post-query`](./hooks.md#post-query)) and the
|
|
124
129
|
[`[dirsql].hook-timeout`](./config.md#dirsql-keys) apply identically.
|
|
@@ -11,7 +11,7 @@ The [CLI](./cli.md) loads `./.dirsql.toml` by default (`--config <path>`
|
|
|
11
11
|
overrides). The [SDKs](./sdk.md) load a config via the `config` constructor
|
|
12
12
|
parameter.
|
|
13
13
|
|
|
14
|
-
**Path resolution.** Relative paths in the config (`root`,
|
|
14
|
+
**Path resolution.** Relative paths in the config (`root`,
|
|
15
15
|
`[[dirsql.extension]]` `path`) resolve against the config file's parent
|
|
16
16
|
directory. The scan root defaults to that same directory when `root` is not
|
|
17
17
|
set.
|
|
@@ -22,8 +22,6 @@ set.
|
|
|
22
22
|
|---|---|---|---|
|
|
23
23
|
| `root` | string | config file's parent directory | Directory to index. Relative values resolve against the config file's parent. An explicit `root` passed to an SDK constructor overrides this (a warning is emitted on stderr). |
|
|
24
24
|
| `ignore` | array of strings | `[]` | Glob patterns matched against root-relative paths. Matched files are skipped entirely — excluded from the initial scan and from watch events. |
|
|
25
|
-
| `persist` | boolean | `false` | Keep the SQLite index on disk between runs. When `false`, the index is ephemeral: rebuilt from your files on every startup and discarded on exit. |
|
|
26
|
-
| `persist_path` | string | `<root>/.dirsql/cache.db` | Location of the on-disk cache. Relative values resolve against the config file's parent. Ignored unless `persist = true`. |
|
|
27
25
|
| `pre-query` | string | none | Server-wide command hook: the raw `POST /query` request body is passed to this command as `{args}`, and the plain-text SQL it prints is executed instead of parsing the body as `{"sql": …}`. CLI server only; the SDKs ignore it. Must be non-empty. See [Command hooks](./hooks.md#pre-query). |
|
|
28
26
|
| `post-query` | string | none | Server-wide command hook: each successful `POST /query` result set is handed to this command (as a JSON array on stdin, and as `{args}` up to 96 KiB), and the JSON body it prints is returned instead of the bare row array. CLI server only; the SDKs ignore it. Must be non-empty. See [Command hooks](./hooks.md#post-query). |
|
|
29
27
|
| `hook-timeout` | integer (seconds) | `30` | One global per-run timeout for every command hook — `on-file`, `pre-query`, and `post-query` alike. Positive whole seconds; zero and negative values are a config error. See [Command hooks](./hooks.md#timeout). |
|
|
@@ -38,11 +36,13 @@ directory.
|
|
|
38
36
|
[dirsql]
|
|
39
37
|
root = "../data"
|
|
40
38
|
ignore = ["node_modules/**", ".git/**"]
|
|
41
|
-
persist = true
|
|
42
|
-
persist_path = ".dirsql/cache.db" # the default; shown for illustration
|
|
43
39
|
hook-timeout = 300
|
|
44
40
|
```
|
|
45
41
|
|
|
42
|
+
Persistence is not a config key. Keep the SQLite index on disk between runs
|
|
43
|
+
with the [`--persist [PATH]` CLI flag](./cli.md#server-mode) — a machine-local
|
|
44
|
+
operational choice that belongs to the runner, not to shareable config.
|
|
45
|
+
|
|
46
46
|
## `[[dirsql.extension]]`
|
|
47
47
|
|
|
48
48
|
Each entry declares a SQLite extension to load at startup. Extensions are
|
|
@@ -150,7 +150,6 @@ SDKs raise/reject) when:
|
|
|
150
150
|
```toml
|
|
151
151
|
[dirsql]
|
|
152
152
|
ignore = ["node_modules/**", ".git/**", "dist/**"]
|
|
153
|
-
persist = true
|
|
154
153
|
pre-query = "uv run python to_sql.py {args}"
|
|
155
154
|
post-query = "jq -c '{results: .}'"
|
|
156
155
|
hook-timeout = 120
|
|
@@ -101,8 +101,8 @@ row-mapping rules.
|
|
|
101
101
|
|
|
102
102
|
| Placeholder | Value |
|
|
103
103
|
|---|---|
|
|
104
|
-
| `{path}` | The matched file's
|
|
105
|
-
| `{root}` | The index root directory. |
|
|
104
|
+
| `{path}` | The matched file's **absolute** path. `on-file = "extract.py {path}"` — self-sufficient from any working directory, so the command resolves it even when the config lives outside the index. |
|
|
105
|
+
| `{root}` | The index root directory. Derive a root-relative path with `relpath({path}, {root})`. |
|
|
106
106
|
|
|
107
107
|
### `pre-query`
|
|
108
108
|
|
|
@@ -111,11 +111,10 @@ directory" error.
|
|
|
111
111
|
- `persist` — Keep the SQLite index on disk between runs (default off:
|
|
112
112
|
ephemeral, rebuilt every startup). The cache lives at
|
|
113
113
|
`<root>/.dirsql/cache.db` by default; on restart, only files whose stat
|
|
114
|
-
changed are re-parsed.
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
persistence is off.
|
|
118
|
-
parent directory; constructor values are used as given.)
|
|
114
|
+
changed are re-parsed. (The CLI exposes the same switch as the
|
|
115
|
+
[`--persist [PATH]`](./cli.md#server-mode) flag; it is not a config key.)
|
|
116
|
+
- `persist_path` / `persistPath` — Override the cache location. Ignored when
|
|
117
|
+
persistence is off. Constructor values are used as given.
|
|
119
118
|
- `extensions` — SQLite extensions to load at startup, before any table
|
|
120
119
|
DDL (enable → load → disable, so SQL `load_extension()` is never
|
|
121
120
|
exposed). Each entry pairs a shared-library `path` with an optional
|
|
@@ -4,7 +4,7 @@ name = "dirsql-py-ext"
|
|
|
4
4
|
# pypi/maturin handler can rewrite it via `write-version` before
|
|
5
5
|
# `maturin build`. `pyproject.toml` declares `dynamic = ["version"]`
|
|
6
6
|
# and maturin reads this field. Mirrors `packages/rust/Cargo.toml`.
|
|
7
|
-
version = "0.3.
|
|
7
|
+
version = "0.3.90"
|
|
8
8
|
# abi3 note: the `abi3-py311` pyo3 feature (below) builds ONE stable-ABI
|
|
9
9
|
# `cp311-abi3` wheel per platform that loads on every CPython >= 3.11
|
|
10
10
|
# (matching `pyproject.toml`'s `requires-python = ">=3.11"`), instead of
|
{dirsql-0.3.88/packages/rust → dirsql-0.3.90/packages/python}/docs/howto/extract-from-contents.md
RENAMED
|
@@ -23,7 +23,7 @@ glob = "books/*.json"
|
|
|
23
23
|
on-file = "jq -c '[{title, author, year}]' {path}"
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
`{path}` is the matched file
|
|
26
|
+
`{path}` is the matched file's absolute path — one of the
|
|
27
27
|
placeholders defined by the
|
|
28
28
|
[command hook contract](../reference/hooks.md#on-file), which also covers
|
|
29
29
|
the argv splitting, working directory, stdout protocol, and timeout shared
|
|
@@ -1,23 +1,34 @@
|
|
|
1
1
|
# Keep the index across restarts
|
|
2
2
|
|
|
3
3
|
By default the database is ephemeral: rebuilt from your files on every
|
|
4
|
-
startup and discarded on exit. [
|
|
5
|
-
SQLite index on disk instead, so a restart only re-parses
|
|
6
|
-
actually changed — the difference between seconds and
|
|
7
|
-
trees, and between re-running and skipping expensive
|
|
4
|
+
startup and discarded on exit. The [`--persist [PATH]`](../reference/cli.md#server-mode)
|
|
5
|
+
flag keeps the SQLite index on disk instead, so a restart only re-parses
|
|
6
|
+
files that actually changed — the difference between seconds and
|
|
7
|
+
milliseconds on large trees, and between re-running and skipping expensive
|
|
8
8
|
[`on-file`](./extract-from-contents.md) commands.
|
|
9
9
|
|
|
10
|
+
Whether and where to cache is a machine-local operational choice — it
|
|
11
|
+
belongs to the command you run, not to the shared `.dirsql.toml`. That is
|
|
12
|
+
why it is a CLI flag, not a config key.
|
|
13
|
+
|
|
10
14
|
## 1. Turn it on
|
|
11
15
|
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
persist = true
|
|
16
|
+
```bash
|
|
17
|
+
dirsql --persist
|
|
15
18
|
```
|
|
16
19
|
|
|
17
20
|
That's the whole change. On the next run the cache is written to
|
|
18
21
|
`.dirsql/cache.db` under the root; runs after that start from it. To put
|
|
19
|
-
the cache elsewhere (a CI cache dir, a tmpfs),
|
|
20
|
-
|
|
22
|
+
the cache elsewhere (a CI cache dir, a tmpfs), pass a path:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
dirsql --persist /var/cache/dirsql.db
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
The same flag works on [`dirsql query`](../reference/cli.md#dirsql-query);
|
|
29
|
+
put a bare `--persist` after the SQL there so it does not consume the query
|
|
30
|
+
argument. Embedding `dirsql`? The SDK constructors expose the same switch —
|
|
31
|
+
see [_Embedding `dirsql`?_](#embedding-dirsql) below.
|
|
21
32
|
|
|
22
33
|
## 2. Keep the cache out of git
|
|
23
34
|
|
|
@@ -48,6 +48,7 @@ requests, closes open `/events` streams, and exits.
|
|
|
48
48
|
| `-c, --config <path>` | `./.dirsql.toml` | Path to the [config file](./config.md). The index is rooted at the directory containing this file (unless the config sets `[dirsql].root`). When the file does not exist, the server runs in [zero-config mode](#zero-config-mode). |
|
|
49
49
|
| `--host <addr>` | `localhost` | Bind address. |
|
|
50
50
|
| `--port <n>` | `7117` | TCP port to bind. |
|
|
51
|
+
| `--persist [<path>]` | off | Keep the SQLite index on disk between runs so a restart only re-parses files that actually changed. Bare `--persist` caches at `<root>/.dirsql/cache.db`; `--persist <path>` caches at `<path>`. Off by default (the index is ephemeral). Global — also honored by [`dirsql query`](#dirsql-query). See [Keep the index across restarts](../howto/persist.md). |
|
|
51
52
|
| `--extension <path>` | none | Load a SQLite extension by literal path, overriding the config's `[[dirsql.extension]]` entries. Repeatable. Format: `<path>` or `<path>::<entrypoint>`. Internal plumbing for the pip/npm launchers, which resolve package-name extensions and pass the resolved paths here — not intended for direct use. When any `--extension` is present, the config file's own extension entries are not loaded. |
|
|
52
53
|
| `--version` | | Print the version and exit. |
|
|
53
54
|
| `--help` | | Print usage and exit. |
|
|
@@ -119,6 +120,10 @@ uses**, so behavior is identical to `POST /query` by construction:
|
|
|
119
120
|
- **Config discovery** honors `--config` (default `./.dirsql.toml`),
|
|
120
121
|
[zero-config mode](#zero-config-mode), and `--extension` overrides,
|
|
121
122
|
exactly as server mode does.
|
|
123
|
+
- **`--persist [<path>]`** is honored, so a repeated `dirsql query` reuses the
|
|
124
|
+
on-disk cache. Because its value is optional, place a bare `--persist` after
|
|
125
|
+
the SQL (`dirsql query "SELECT …" --persist`) or use the `=` form
|
|
126
|
+
(`--persist=/path`) so it does not swallow the SQL argument.
|
|
122
127
|
- **Hooks** ([`pre-query`](./hooks.md#pre-query) /
|
|
123
128
|
[`post-query`](./hooks.md#post-query)) and the
|
|
124
129
|
[`[dirsql].hook-timeout`](./config.md#dirsql-keys) apply identically.
|
|
@@ -11,7 +11,7 @@ The [CLI](./cli.md) loads `./.dirsql.toml` by default (`--config <path>`
|
|
|
11
11
|
overrides). The [SDKs](./sdk.md) load a config via the `config` constructor
|
|
12
12
|
parameter.
|
|
13
13
|
|
|
14
|
-
**Path resolution.** Relative paths in the config (`root`,
|
|
14
|
+
**Path resolution.** Relative paths in the config (`root`,
|
|
15
15
|
`[[dirsql.extension]]` `path`) resolve against the config file's parent
|
|
16
16
|
directory. The scan root defaults to that same directory when `root` is not
|
|
17
17
|
set.
|
|
@@ -22,8 +22,6 @@ set.
|
|
|
22
22
|
|---|---|---|---|
|
|
23
23
|
| `root` | string | config file's parent directory | Directory to index. Relative values resolve against the config file's parent. An explicit `root` passed to an SDK constructor overrides this (a warning is emitted on stderr). |
|
|
24
24
|
| `ignore` | array of strings | `[]` | Glob patterns matched against root-relative paths. Matched files are skipped entirely — excluded from the initial scan and from watch events. |
|
|
25
|
-
| `persist` | boolean | `false` | Keep the SQLite index on disk between runs. When `false`, the index is ephemeral: rebuilt from your files on every startup and discarded on exit. |
|
|
26
|
-
| `persist_path` | string | `<root>/.dirsql/cache.db` | Location of the on-disk cache. Relative values resolve against the config file's parent. Ignored unless `persist = true`. |
|
|
27
25
|
| `pre-query` | string | none | Server-wide command hook: the raw `POST /query` request body is passed to this command as `{args}`, and the plain-text SQL it prints is executed instead of parsing the body as `{"sql": …}`. CLI server only; the SDKs ignore it. Must be non-empty. See [Command hooks](./hooks.md#pre-query). |
|
|
28
26
|
| `post-query` | string | none | Server-wide command hook: each successful `POST /query` result set is handed to this command (as a JSON array on stdin, and as `{args}` up to 96 KiB), and the JSON body it prints is returned instead of the bare row array. CLI server only; the SDKs ignore it. Must be non-empty. See [Command hooks](./hooks.md#post-query). |
|
|
29
27
|
| `hook-timeout` | integer (seconds) | `30` | One global per-run timeout for every command hook — `on-file`, `pre-query`, and `post-query` alike. Positive whole seconds; zero and negative values are a config error. See [Command hooks](./hooks.md#timeout). |
|
|
@@ -38,11 +36,13 @@ directory.
|
|
|
38
36
|
[dirsql]
|
|
39
37
|
root = "../data"
|
|
40
38
|
ignore = ["node_modules/**", ".git/**"]
|
|
41
|
-
persist = true
|
|
42
|
-
persist_path = ".dirsql/cache.db" # the default; shown for illustration
|
|
43
39
|
hook-timeout = 300
|
|
44
40
|
```
|
|
45
41
|
|
|
42
|
+
Persistence is not a config key. Keep the SQLite index on disk between runs
|
|
43
|
+
with the [`--persist [PATH]` CLI flag](./cli.md#server-mode) — a machine-local
|
|
44
|
+
operational choice that belongs to the runner, not to shareable config.
|
|
45
|
+
|
|
46
46
|
## `[[dirsql.extension]]`
|
|
47
47
|
|
|
48
48
|
Each entry declares a SQLite extension to load at startup. Extensions are
|
|
@@ -150,7 +150,6 @@ SDKs raise/reject) when:
|
|
|
150
150
|
```toml
|
|
151
151
|
[dirsql]
|
|
152
152
|
ignore = ["node_modules/**", ".git/**", "dist/**"]
|
|
153
|
-
persist = true
|
|
154
153
|
pre-query = "uv run python to_sql.py {args}"
|
|
155
154
|
post-query = "jq -c '{results: .}'"
|
|
156
155
|
hook-timeout = 120
|
|
@@ -101,8 +101,8 @@ row-mapping rules.
|
|
|
101
101
|
|
|
102
102
|
| Placeholder | Value |
|
|
103
103
|
|---|---|
|
|
104
|
-
| `{path}` | The matched file's
|
|
105
|
-
| `{root}` | The index root directory. |
|
|
104
|
+
| `{path}` | The matched file's **absolute** path. `on-file = "extract.py {path}"` — self-sufficient from any working directory, so the command resolves it even when the config lives outside the index. |
|
|
105
|
+
| `{root}` | The index root directory. Derive a root-relative path with `relpath({path}, {root})`. |
|
|
106
106
|
|
|
107
107
|
### `pre-query`
|
|
108
108
|
|
|
@@ -111,11 +111,10 @@ directory" error.
|
|
|
111
111
|
- `persist` — Keep the SQLite index on disk between runs (default off:
|
|
112
112
|
ephemeral, rebuilt every startup). The cache lives at
|
|
113
113
|
`<root>/.dirsql/cache.db` by default; on restart, only files whose stat
|
|
114
|
-
changed are re-parsed.
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
persistence is off.
|
|
118
|
-
parent directory; constructor values are used as given.)
|
|
114
|
+
changed are re-parsed. (The CLI exposes the same switch as the
|
|
115
|
+
[`--persist [PATH]`](./cli.md#server-mode) flag; it is not a config key.)
|
|
116
|
+
- `persist_path` / `persistPath` — Override the cache location. Ignored when
|
|
117
|
+
persistence is off. Constructor values are used as given.
|
|
119
118
|
- `extensions` — SQLite extensions to load at startup, before any table
|
|
120
119
|
DDL (enable → load → disable, so SQL `load_extension()` is never
|
|
121
120
|
exposed). Each entry pairs a shared-library `path` with an optional
|
|
@@ -23,7 +23,7 @@ glob = "books/*.json"
|
|
|
23
23
|
on-file = "jq -c '[{title, author, year}]' {path}"
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
`{path}` is the matched file
|
|
26
|
+
`{path}` is the matched file's absolute path — one of the
|
|
27
27
|
placeholders defined by the
|
|
28
28
|
[command hook contract](../reference/hooks.md#on-file), which also covers
|
|
29
29
|
the argv splitting, working directory, stdout protocol, and timeout shared
|
|
@@ -1,23 +1,34 @@
|
|
|
1
1
|
# Keep the index across restarts
|
|
2
2
|
|
|
3
3
|
By default the database is ephemeral: rebuilt from your files on every
|
|
4
|
-
startup and discarded on exit. [
|
|
5
|
-
SQLite index on disk instead, so a restart only re-parses
|
|
6
|
-
actually changed — the difference between seconds and
|
|
7
|
-
trees, and between re-running and skipping expensive
|
|
4
|
+
startup and discarded on exit. The [`--persist [PATH]`](../reference/cli.md#server-mode)
|
|
5
|
+
flag keeps the SQLite index on disk instead, so a restart only re-parses
|
|
6
|
+
files that actually changed — the difference between seconds and
|
|
7
|
+
milliseconds on large trees, and between re-running and skipping expensive
|
|
8
8
|
[`on-file`](./extract-from-contents.md) commands.
|
|
9
9
|
|
|
10
|
+
Whether and where to cache is a machine-local operational choice — it
|
|
11
|
+
belongs to the command you run, not to the shared `.dirsql.toml`. That is
|
|
12
|
+
why it is a CLI flag, not a config key.
|
|
13
|
+
|
|
10
14
|
## 1. Turn it on
|
|
11
15
|
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
persist = true
|
|
16
|
+
```bash
|
|
17
|
+
dirsql --persist
|
|
15
18
|
```
|
|
16
19
|
|
|
17
20
|
That's the whole change. On the next run the cache is written to
|
|
18
21
|
`.dirsql/cache.db` under the root; runs after that start from it. To put
|
|
19
|
-
the cache elsewhere (a CI cache dir, a tmpfs),
|
|
20
|
-
|
|
22
|
+
the cache elsewhere (a CI cache dir, a tmpfs), pass a path:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
dirsql --persist /var/cache/dirsql.db
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
The same flag works on [`dirsql query`](../reference/cli.md#dirsql-query);
|
|
29
|
+
put a bare `--persist` after the SQL there so it does not consume the query
|
|
30
|
+
argument. Embedding `dirsql`? The SDK constructors expose the same switch —
|
|
31
|
+
see [_Embedding `dirsql`?_](#embedding-dirsql) below.
|
|
21
32
|
|
|
22
33
|
## 2. Keep the cache out of git
|
|
23
34
|
|
|
@@ -48,6 +48,7 @@ requests, closes open `/events` streams, and exits.
|
|
|
48
48
|
| `-c, --config <path>` | `./.dirsql.toml` | Path to the [config file](./config.md). The index is rooted at the directory containing this file (unless the config sets `[dirsql].root`). When the file does not exist, the server runs in [zero-config mode](#zero-config-mode). |
|
|
49
49
|
| `--host <addr>` | `localhost` | Bind address. |
|
|
50
50
|
| `--port <n>` | `7117` | TCP port to bind. |
|
|
51
|
+
| `--persist [<path>]` | off | Keep the SQLite index on disk between runs so a restart only re-parses files that actually changed. Bare `--persist` caches at `<root>/.dirsql/cache.db`; `--persist <path>` caches at `<path>`. Off by default (the index is ephemeral). Global — also honored by [`dirsql query`](#dirsql-query). See [Keep the index across restarts](../howto/persist.md). |
|
|
51
52
|
| `--extension <path>` | none | Load a SQLite extension by literal path, overriding the config's `[[dirsql.extension]]` entries. Repeatable. Format: `<path>` or `<path>::<entrypoint>`. Internal plumbing for the pip/npm launchers, which resolve package-name extensions and pass the resolved paths here — not intended for direct use. When any `--extension` is present, the config file's own extension entries are not loaded. |
|
|
52
53
|
| `--version` | | Print the version and exit. |
|
|
53
54
|
| `--help` | | Print usage and exit. |
|
|
@@ -119,6 +120,10 @@ uses**, so behavior is identical to `POST /query` by construction:
|
|
|
119
120
|
- **Config discovery** honors `--config` (default `./.dirsql.toml`),
|
|
120
121
|
[zero-config mode](#zero-config-mode), and `--extension` overrides,
|
|
121
122
|
exactly as server mode does.
|
|
123
|
+
- **`--persist [<path>]`** is honored, so a repeated `dirsql query` reuses the
|
|
124
|
+
on-disk cache. Because its value is optional, place a bare `--persist` after
|
|
125
|
+
the SQL (`dirsql query "SELECT …" --persist`) or use the `=` form
|
|
126
|
+
(`--persist=/path`) so it does not swallow the SQL argument.
|
|
122
127
|
- **Hooks** ([`pre-query`](./hooks.md#pre-query) /
|
|
123
128
|
[`post-query`](./hooks.md#post-query)) and the
|
|
124
129
|
[`[dirsql].hook-timeout`](./config.md#dirsql-keys) apply identically.
|
|
@@ -11,7 +11,7 @@ The [CLI](./cli.md) loads `./.dirsql.toml` by default (`--config <path>`
|
|
|
11
11
|
overrides). The [SDKs](./sdk.md) load a config via the `config` constructor
|
|
12
12
|
parameter.
|
|
13
13
|
|
|
14
|
-
**Path resolution.** Relative paths in the config (`root`,
|
|
14
|
+
**Path resolution.** Relative paths in the config (`root`,
|
|
15
15
|
`[[dirsql.extension]]` `path`) resolve against the config file's parent
|
|
16
16
|
directory. The scan root defaults to that same directory when `root` is not
|
|
17
17
|
set.
|
|
@@ -22,8 +22,6 @@ set.
|
|
|
22
22
|
|---|---|---|---|
|
|
23
23
|
| `root` | string | config file's parent directory | Directory to index. Relative values resolve against the config file's parent. An explicit `root` passed to an SDK constructor overrides this (a warning is emitted on stderr). |
|
|
24
24
|
| `ignore` | array of strings | `[]` | Glob patterns matched against root-relative paths. Matched files are skipped entirely — excluded from the initial scan and from watch events. |
|
|
25
|
-
| `persist` | boolean | `false` | Keep the SQLite index on disk between runs. When `false`, the index is ephemeral: rebuilt from your files on every startup and discarded on exit. |
|
|
26
|
-
| `persist_path` | string | `<root>/.dirsql/cache.db` | Location of the on-disk cache. Relative values resolve against the config file's parent. Ignored unless `persist = true`. |
|
|
27
25
|
| `pre-query` | string | none | Server-wide command hook: the raw `POST /query` request body is passed to this command as `{args}`, and the plain-text SQL it prints is executed instead of parsing the body as `{"sql": …}`. CLI server only; the SDKs ignore it. Must be non-empty. See [Command hooks](./hooks.md#pre-query). |
|
|
28
26
|
| `post-query` | string | none | Server-wide command hook: each successful `POST /query` result set is handed to this command (as a JSON array on stdin, and as `{args}` up to 96 KiB), and the JSON body it prints is returned instead of the bare row array. CLI server only; the SDKs ignore it. Must be non-empty. See [Command hooks](./hooks.md#post-query). |
|
|
29
27
|
| `hook-timeout` | integer (seconds) | `30` | One global per-run timeout for every command hook — `on-file`, `pre-query`, and `post-query` alike. Positive whole seconds; zero and negative values are a config error. See [Command hooks](./hooks.md#timeout). |
|
|
@@ -38,11 +36,13 @@ directory.
|
|
|
38
36
|
[dirsql]
|
|
39
37
|
root = "../data"
|
|
40
38
|
ignore = ["node_modules/**", ".git/**"]
|
|
41
|
-
persist = true
|
|
42
|
-
persist_path = ".dirsql/cache.db" # the default; shown for illustration
|
|
43
39
|
hook-timeout = 300
|
|
44
40
|
```
|
|
45
41
|
|
|
42
|
+
Persistence is not a config key. Keep the SQLite index on disk between runs
|
|
43
|
+
with the [`--persist [PATH]` CLI flag](./cli.md#server-mode) — a machine-local
|
|
44
|
+
operational choice that belongs to the runner, not to shareable config.
|
|
45
|
+
|
|
46
46
|
## `[[dirsql.extension]]`
|
|
47
47
|
|
|
48
48
|
Each entry declares a SQLite extension to load at startup. Extensions are
|
|
@@ -150,7 +150,6 @@ SDKs raise/reject) when:
|
|
|
150
150
|
```toml
|
|
151
151
|
[dirsql]
|
|
152
152
|
ignore = ["node_modules/**", ".git/**", "dist/**"]
|
|
153
|
-
persist = true
|
|
154
153
|
pre-query = "uv run python to_sql.py {args}"
|
|
155
154
|
post-query = "jq -c '{results: .}'"
|
|
156
155
|
hook-timeout = 120
|
|
@@ -101,8 +101,8 @@ row-mapping rules.
|
|
|
101
101
|
|
|
102
102
|
| Placeholder | Value |
|
|
103
103
|
|---|---|
|
|
104
|
-
| `{path}` | The matched file's
|
|
105
|
-
| `{root}` | The index root directory. |
|
|
104
|
+
| `{path}` | The matched file's **absolute** path. `on-file = "extract.py {path}"` — self-sufficient from any working directory, so the command resolves it even when the config lives outside the index. |
|
|
105
|
+
| `{root}` | The index root directory. Derive a root-relative path with `relpath({path}, {root})`. |
|
|
106
106
|
|
|
107
107
|
### `pre-query`
|
|
108
108
|
|
|
@@ -111,11 +111,10 @@ directory" error.
|
|
|
111
111
|
- `persist` — Keep the SQLite index on disk between runs (default off:
|
|
112
112
|
ephemeral, rebuilt every startup). The cache lives at
|
|
113
113
|
`<root>/.dirsql/cache.db` by default; on restart, only files whose stat
|
|
114
|
-
changed are re-parsed.
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
persistence is off.
|
|
118
|
-
parent directory; constructor values are used as given.)
|
|
114
|
+
changed are re-parsed. (The CLI exposes the same switch as the
|
|
115
|
+
[`--persist [PATH]`](./cli.md#server-mode) flag; it is not a config key.)
|
|
116
|
+
- `persist_path` / `persistPath` — Override the cache location. Ignored when
|
|
117
|
+
persistence is off. Constructor values are used as given.
|
|
119
118
|
- `extensions` — SQLite extensions to load at startup, before any table
|
|
120
119
|
DDL (enable → load → disable, so SQL `load_extension()` is never
|
|
121
120
|
exposed). Each entry pairs a shared-library `path` with an optional
|
|
@@ -61,6 +61,28 @@ struct Cli {
|
|
|
61
61
|
/// subcommand.
|
|
62
62
|
#[arg(long = "extension", global = true)]
|
|
63
63
|
extension: Vec<String>,
|
|
64
|
+
|
|
65
|
+
/// Keep the SQLite index on disk between runs so a restart only re-parses
|
|
66
|
+
/// files that actually changed. Bare `--persist` caches at the default
|
|
67
|
+
/// location (`<root>/.dirsql/cache.db`); `--persist <path>` caches there.
|
|
68
|
+
/// Off by default (ephemeral index). Used by server mode and `query`.
|
|
69
|
+
#[arg(long, num_args = 0..=1, global = true)]
|
|
70
|
+
persist: Option<Option<PathBuf>>,
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
impl Cli {
|
|
74
|
+
/// Apply the `--persist [PATH]` flag to a builder. Absent → no change;
|
|
75
|
+
/// bare `--persist` → persist at the default location; `--persist <path>`
|
|
76
|
+
/// → persist at `<path>`.
|
|
77
|
+
fn apply_persist(&self, mut builder: dirsql::DirSQLBuilder) -> dirsql::DirSQLBuilder {
|
|
78
|
+
if let Some(path) = &self.persist {
|
|
79
|
+
builder = builder.persist(true);
|
|
80
|
+
if let Some(path) = path {
|
|
81
|
+
builder = builder.persist_path(path);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
builder
|
|
85
|
+
}
|
|
64
86
|
}
|
|
65
87
|
|
|
66
88
|
#[derive(Debug, Subcommand)]
|
|
@@ -216,7 +238,7 @@ fn load_state(cli: &Cli) -> AppState {
|
|
|
216
238
|
if !config_path.exists() {
|
|
217
239
|
// No config: serve a default `files` table so dirsql is queryable
|
|
218
240
|
// out of the box. A config file, when present, fully overrules this.
|
|
219
|
-
return load_default_state(config_path);
|
|
241
|
+
return load_default_state(cli, config_path);
|
|
220
242
|
}
|
|
221
243
|
|
|
222
244
|
// Canonicalize so the root (derived from the config's parent) is
|
|
@@ -237,16 +259,14 @@ fn load_state(cli: &Cli) -> AppState {
|
|
|
237
259
|
// resolved them (including package names the compiled binary can't
|
|
238
260
|
// resolve), so suppress the config's extension loading and supply the
|
|
239
261
|
// resolved literal paths instead.
|
|
240
|
-
let
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
DirSQL::builder()
|
|
244
|
-
.config(&resolved)
|
|
262
|
+
let mut builder = DirSQL::builder().config(&resolved);
|
|
263
|
+
if !cli.extension.is_empty() {
|
|
264
|
+
builder = builder
|
|
245
265
|
.extensions(parse_extension_specs(&cli.extension))
|
|
246
|
-
.suppress_config_extensions(true)
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
match build {
|
|
266
|
+
.suppress_config_extensions(true);
|
|
267
|
+
}
|
|
268
|
+
builder = cli.apply_persist(builder);
|
|
269
|
+
match builder.build() {
|
|
250
270
|
Ok(db) => AppState::Ready(db),
|
|
251
271
|
Err(err) => AppState::Unavailable(format!("failed to load config: {err}")),
|
|
252
272
|
}
|
|
@@ -324,7 +344,7 @@ fn load_post_query(cli: &Cli) -> Option<PostQuery> {
|
|
|
324
344
|
/// table — one row per file, columns drawn entirely from filesystem facts —
|
|
325
345
|
/// so `SELECT * FROM files` works immediately. A config file, when present,
|
|
326
346
|
/// fully overrules this default.
|
|
327
|
-
fn load_default_state(config_path: &Path) -> AppState {
|
|
347
|
+
fn load_default_state(cli: &Cli, config_path: &Path) -> AppState {
|
|
328
348
|
let dir = config_path
|
|
329
349
|
.parent()
|
|
330
350
|
.filter(|p| !p.as_os_str().is_empty())
|
|
@@ -340,7 +360,8 @@ fn load_default_state(config_path: &Path) -> AppState {
|
|
|
340
360
|
}
|
|
341
361
|
};
|
|
342
362
|
|
|
343
|
-
|
|
363
|
+
let builder = cli.apply_persist(DirSQL::builder().root(root).table(default_files_table()));
|
|
364
|
+
match builder.build() {
|
|
344
365
|
Ok(db) => AppState::Ready(db),
|
|
345
366
|
Err(err) => AppState::Unavailable(format!("failed to build default index: {err}")),
|
|
346
367
|
}
|
|
@@ -406,6 +427,34 @@ mod tests {
|
|
|
406
427
|
assert_eq!(query_body(" "), r#"{"sql":" "}"#);
|
|
407
428
|
}
|
|
408
429
|
|
|
430
|
+
#[test]
|
|
431
|
+
fn persist_flag_absent_is_none() {
|
|
432
|
+
let cli = Cli::parse_from(["dirsql"]);
|
|
433
|
+
assert_eq!(cli.persist, None);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
#[test]
|
|
437
|
+
fn persist_flag_bare_enables_default_location() {
|
|
438
|
+
// Bare `--persist` (no value) → `Some(None)`: persist at the default
|
|
439
|
+
// `<root>/.dirsql/cache.db`, no override path.
|
|
440
|
+
let cli = Cli::parse_from(["dirsql", "--persist"]);
|
|
441
|
+
assert_eq!(cli.persist, Some(None));
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
#[test]
|
|
445
|
+
fn persist_flag_with_path_carries_the_value() {
|
|
446
|
+
let cli = Cli::parse_from(["dirsql", "--persist", "/var/cache/x.db"]);
|
|
447
|
+
assert_eq!(cli.persist, Some(Some(PathBuf::from("/var/cache/x.db"))));
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
#[test]
|
|
451
|
+
fn persist_flag_is_global_on_the_query_subcommand() {
|
|
452
|
+
// `--persist` is global, so it attaches to `query` too; the flag sits
|
|
453
|
+
// after the positional SQL to avoid the num_args(0..=1) greedy grab.
|
|
454
|
+
let cli = Cli::parse_from(["dirsql", "query", "SELECT 1", "--persist"]);
|
|
455
|
+
assert_eq!(cli.persist, Some(None));
|
|
456
|
+
}
|
|
457
|
+
|
|
409
458
|
#[test]
|
|
410
459
|
fn parse_extension_specs_handles_bare_path_and_entrypoint() {
|
|
411
460
|
let specs = vec![
|