dirsql 0.4.18__tar.gz → 0.4.19__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.4.18 → dirsql-0.4.19}/Cargo.lock +1 -1
- {dirsql-0.4.18 → dirsql-0.4.19}/PKG-INFO +1 -1
- {dirsql-0.4.18/packages/rust → dirsql-0.4.19}/docs/howto/persist.md +13 -0
- {dirsql-0.4.18/packages/rust → dirsql-0.4.19}/docs/reference/path-tables.md +14 -6
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/Cargo.toml +1 -1
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/docs/howto/persist.md +13 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/docs/reference/path-tables.md +14 -6
- dirsql-0.4.19/packages/python/e2e-attestations/claude-github-issue-825-e4mhhp.json +7 -0
- dirsql-0.4.19/packages/rust/changelog.d/2026-08-11-persist-parsed-path-tables.md +4 -0
- {dirsql-0.4.18 → dirsql-0.4.19/packages/rust}/docs/howto/persist.md +13 -0
- {dirsql-0.4.18 → dirsql-0.4.19/packages/rust}/docs/reference/path-tables.md +14 -6
- dirsql-0.4.19/packages/rust/migrations.d/2026-08-11-persist-parsed-path-tables.md +58 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/src/db.rs +87 -7
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/src/lib.rs +50 -20
- dirsql-0.4.19/packages/rust/src/parsed_cache.rs +454 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/src/parsed_vtab.rs +547 -19
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/src/persist.rs +76 -31
- {dirsql-0.4.18 → dirsql-0.4.19}/Cargo.toml +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/README.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/dirsql/__init__.py +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/dirsql/_async.py +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/dirsql/_dirsql.pyi +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/dirsql/cli/__init__.py +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/dirsql/cli/discover_plugins/__init__.py +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/dirsql/cli/discover_plugins/discovered_fragments.py +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/dirsql/cli/discover_plugins/discovery_disabled.py +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/dirsql/cli/discover_plugins/fragment_path.py +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/dirsql/cli/discover_plugins/user_passed_config.py +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/dirsql/cli/discover_plugins/with_discovered_plugins.py +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/dirsql/cli/main.py +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/dirsql/cli/resolve_config_extensions.py +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/dirsql/py.typed +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/dirsql/resolve_config_extensions.py +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/dirsql/resolve_extension.py +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/docs/.claude/CLAUDE.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/docs/.vitepress/config.ts +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/docs/.vitepress/theme/index.ts +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/docs/.vitepress/theme/lang.ts +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/docs/AGENTS.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/docs/explanation.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/docs/getting-started.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/docs/howto/columns-from-paths.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/docs/howto/define-tables.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/docs/howto/embed.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/docs/howto/extract-from-contents.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/docs/howto/load-extension.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/docs/howto/parse-files-into-columns.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/docs/howto/query-without-config.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/docs/howto/react-to-changes.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/docs/howto/search-by-meaning.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/docs/howto/skip-files.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/docs/howto/write-a-plugin.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/docs/index.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/docs/migrations.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/docs/package.json +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/docs/plugins.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/docs/pnpm-lock.yaml +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/docs/pnpm-workspace.yaml +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/docs/reference/cli.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/docs/reference/columns.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/docs/reference/config.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/docs/reference/hooks.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/docs/reference/http-api.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/docs/reference/sdk.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/CHANGELOG.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/MIGRATIONS.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/README.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/changelog.d/2026-07-13-drop-cwd-config-auto-detect.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/changelog.d/2026-07-13-plugin-discovery.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/changelog.d/2026-07-13-rename-extract-to-on-file.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/changelog.d/2026-07-13-repeatable-config.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/changelog.d/2026-07-13-sdk-default-baked-in-config.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/changelog.d/2026-07-20-drop-implicit-files-table.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/changelog.d/2026-07-21-remove-glob-captures.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/changelog.d/2026-07-24-hookless-table-config-error.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/changelog.d/2026-07-24-remove-stat-fact-injection.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/changelog.d/2026-07-29-restore-python-310.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/changelog.d/2026-08-02-release-profile.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/changelog.d/2026-08-02-scan-failures.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/changelog.d/2026-08-03-discovery-ext-resolution.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/changelog.d/2026-08-03-manylinux-dynamic-binary.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/changelog.d/2026-08-03-python-no-ignore.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/changelog.d/2026-08-04-cast-lints.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/changelog.d/2026-08-04-cli-in-process.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/changelog.d/README.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/conftest.py +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/docs/.claude/CLAUDE.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/docs/.vitepress/config.ts +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/docs/.vitepress/theme/index.ts +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/docs/.vitepress/theme/lang.ts +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/docs/AGENTS.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/docs/explanation.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/docs/getting-started.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/docs/howto/columns-from-paths.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/docs/howto/define-tables.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/docs/howto/embed.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/docs/howto/extract-from-contents.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/docs/howto/load-extension.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/docs/howto/parse-files-into-columns.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/docs/howto/query-without-config.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/docs/howto/react-to-changes.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/docs/howto/search-by-meaning.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/docs/howto/skip-files.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/docs/howto/write-a-plugin.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/docs/index.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/docs/migrations.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/docs/package.json +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/docs/plugins.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/docs/pnpm-lock.yaml +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/docs/pnpm-workspace.yaml +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/docs/reference/cli.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/docs/reference/columns.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/docs/reference/config.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/docs/reference/hooks.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/docs/reference/http-api.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/docs/reference/sdk.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/e2e-attestations/claude-819-oneshot-timeout.json +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/migrations.d/2026-07-13-drop-cwd-config-auto-detect.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/migrations.d/2026-07-13-rename-extract-to-on-file.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/migrations.d/2026-07-13-sdk-default-baked-in-config.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/migrations.d/2026-07-20-drop-implicit-files-table.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/migrations.d/2026-07-21-remove-glob-captures.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/migrations.d/2026-07-24-hookless-table-config-error.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/migrations.d/2026-07-24-remove-stat-fact-injection.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/migrations.d/2026-07-29-restore-python-310.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/migrations.d/2026-08-04-cli-in-process.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/migrations.d/README.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/src/lib.rs +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/tests/__init__.py +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/tests/conftest.py +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/tests/e2e/__init__.py +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/tests/e2e/fixtures/dirsql_plugin_fixture/__init__.py +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/tests/e2e/fixtures/dirsql_plugin_fixture/dirsql.toml +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/tests/integration/__init__.py +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/tests/integration/binding/__init__.py +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/python/tests/integration/hermetic/__init__.py +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/CHANGELOG.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/Cargo.toml +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/MIGRATIONS.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/README.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/benches/db_bench.rs +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/benches/differ_bench.rs +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/benches/matcher_bench.rs +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/benches/scanner_bench.rs +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/changelog.d/2026-07-13-batch-ingest-transaction.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/changelog.d/2026-07-13-chained-pre-post-query-hooks.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/changelog.d/2026-07-13-drop-cwd-config-auto-detect.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/changelog.d/2026-07-13-fan-out-file-table-matching.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/changelog.d/2026-07-13-persist-wal.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/changelog.d/2026-07-13-rename-extract-to-on-file.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/changelog.d/2026-07-13-repeatable-builder-config.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/changelog.d/2026-07-13-repeatable-cli-config.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/changelog.d/2026-07-13-sdk-default-baked-in-config.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/changelog.d/2026-07-13-subcommand-local-config-flags.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/changelog.d/2026-07-19-path-table-query-fallback.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/changelog.d/2026-07-19-path-table-vtab.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/changelog.d/2026-07-20-drop-implicit-files-table.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/changelog.d/2026-07-20-path-table-glob-semantics.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/changelog.d/2026-07-20-schema-inference.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/changelog.d/2026-07-21-on-file-flag.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/changelog.d/2026-07-21-remove-glob-captures.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/changelog.d/2026-07-23-init-escalation-example.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/changelog.d/2026-07-23-query-default-cli.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/changelog.d/2026-07-24-hookless-table-config-error.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/changelog.d/2026-07-24-remove-stat-fact-injection.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/changelog.d/2026-07-29-on-file-failures-accumulate.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/changelog.d/2026-08-02-drop-regex.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/changelog.d/2026-08-02-per-file-scan-failures.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/changelog.d/2026-08-02-release-profile.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/changelog.d/2026-08-03-gitignore-by-default.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/changelog.d/2026-08-03-nested-default-ignores.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/changelog.d/2026-08-04-cast-lints.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/changelog.d/2026-08-04-cli-run-shim.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/changelog.d/2026-08-04-configless-extension.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/changelog.d/2026-08-10-dirsql-function.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/changelog.d/2026-08-10-remove-query-hooks.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/changelog.d/2026-08-11-oneshot-query-no-timeout.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/changelog.d/2026-08-11-retire-hook-timeout.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/changelog.d/README.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/docs/explanation.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/docs/getting-started.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/docs/howto/columns-from-paths.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/docs/howto/define-tables.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/docs/howto/embed.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/docs/howto/extract-from-contents.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/docs/howto/load-extension.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/docs/howto/parse-files-into-columns.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/docs/howto/query-without-config.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/docs/howto/react-to-changes.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/docs/howto/search-by-meaning.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/docs/howto/skip-files.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/docs/howto/write-a-plugin.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/docs/index.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/docs/migrations.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/docs/plugins.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/docs/reference/cli.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/docs/reference/columns.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/docs/reference/config.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/docs/reference/hooks.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/docs/reference/http-api.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/docs/reference/sdk.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/migrations.d/2026-07-13-drop-cwd-config-auto-detect.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/migrations.d/2026-07-13-fan-out-file-table-matching.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/migrations.d/2026-07-13-persist-wal.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/migrations.d/2026-07-13-rename-extract-to-on-file.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/migrations.d/2026-07-13-sdk-default-baked-in-config.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/migrations.d/2026-07-13-subcommand-local-config-flags.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/migrations.d/2026-07-20-drop-implicit-files-table.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/migrations.d/2026-07-20-path-table-glob-semantics.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/migrations.d/2026-07-21-remove-glob-captures.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/migrations.d/2026-07-23-init-escalation-example.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/migrations.d/2026-07-23-query-default-cli.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/migrations.d/2026-07-24-hookless-table-config-error.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/migrations.d/2026-07-24-remove-stat-fact-injection.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/migrations.d/2026-08-02-per-file-scan-failures.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/migrations.d/2026-08-03-gitignore-by-default.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/migrations.d/2026-08-03-nested-default-ignores.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/migrations.d/2026-08-10-remove-query-hooks.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/migrations.d/2026-08-11-oneshot-query-no-timeout.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/migrations.d/2026-08-11-retire-hook-timeout.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/migrations.d/README.md +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/src/bin/dirsql.rs +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/src/cli/execute.rs +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/src/cli/init.rs +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/src/cli/mod.rs +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/src/cli/router.rs +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/src/cli/run.rs +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/src/cli/serialize.rs +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/src/cli/server.rs +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/src/command.rs +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/src/config.rs +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/src/default_config.toml +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/src/differ.rs +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/src/functions.rs +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/src/infer.rs +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/src/matcher.rs +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/src/path_table.rs +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/src/scanner.rs +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/src/vtab.rs +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/packages/rust/src/watcher.rs +0 -0
- {dirsql-0.4.18 → dirsql-0.4.19}/pyproject.toml +0 -0
|
@@ -55,6 +55,19 @@ can't be trusted at all — the table/ignore configuration changed, or the
|
|
|
55
55
|
automatically. You never need to delete it by hand; a full rebuild costs
|
|
56
56
|
exactly what a non-persistent startup does.
|
|
57
57
|
|
|
58
|
+
A run that changes nothing writes nothing: the cache file is read and left
|
|
59
|
+
exactly as it was.
|
|
60
|
+
|
|
61
|
+
This covers both kinds of table. Declared tables keep their indexed rows, and
|
|
62
|
+
a [path-table](../reference/path-tables.md) parsed with `--on-file` keeps each
|
|
63
|
+
file's parser output — so the second run over an unchanged tree spawns no
|
|
64
|
+
parser process at all. A path-table's cached rows are keyed by the tree, the
|
|
65
|
+
glob, the parser command and the `dirsql` version together, so changing any of
|
|
66
|
+
them parses afresh rather than serving rows the current command never
|
|
67
|
+
produced. A *stat* path-table caches nothing, because there is nothing to
|
|
68
|
+
save: its columns are the metadata the scan already collected, and `content`
|
|
69
|
+
is read live by design.
|
|
70
|
+
|
|
58
71
|
Persistence is a startup-time optimization, not a change in meaning: the
|
|
59
72
|
database remains a derived view of your files, and queries return the same
|
|
60
73
|
rows either way ([how `dirsql` thinks](../explanation.md)).
|
|
@@ -140,6 +140,12 @@ the table:
|
|
|
140
140
|
scan continues. The schema is inferred from the files that did parse.
|
|
141
141
|
- **The skip rules still apply.** A parsed scan honors the same `node_modules`
|
|
142
142
|
/`.git`/`ignore` rules a stat scan does (see below).
|
|
143
|
+
- **`--persist` skips the parser for unchanged files.** With a
|
|
144
|
+
[persistent cache](/howto/persist), each file's parser output is stored
|
|
145
|
+
against its stat metadata, so a later run over an unchanged tree serves the
|
|
146
|
+
rows from the cache and spawns no process. Change the file, the glob, the
|
|
147
|
+
parser command, or the dirsql version and that file (or that whole table) is
|
|
148
|
+
parsed again.
|
|
143
149
|
|
|
144
150
|
`--on-file` applies to **every** path-table in the query and may be given **at
|
|
145
151
|
most once**. For different parsers per file set, define named tables in a
|
|
@@ -160,15 +166,17 @@ deleted *after* the scan finds it but *before* its `content` is read yields
|
|
|
160
166
|
than failing the query. This is an accepted consequence of reading live, not a
|
|
161
167
|
bug to design around.
|
|
162
168
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
169
|
+
The table itself is per-connection: it lives in `temp`, so it cannot leak into
|
|
170
|
+
`sqlite_master` or survive a restart. Under `--persist` a *parsed* table's rows
|
|
171
|
+
outlive the connection in the cache (above), but the table is still minted
|
|
172
|
+
fresh each run and the scan still decides what exists. The reserved top-level
|
|
173
|
+
`.dirsql/` directory is excluded from the scan, as everywhere else.
|
|
166
174
|
|
|
167
175
|
### When to promote to a declared table
|
|
168
176
|
|
|
169
|
-
Every query re-scans the filesystem: a path-table has no index
|
|
170
|
-
|
|
171
|
-
|
|
177
|
+
Every query re-scans the filesystem: a path-table has no index and no watcher.
|
|
178
|
+
That is the right trade for a hundreds-of-files, run-it-once question. When the
|
|
179
|
+
same tree is queried repeatedly, or is large, declare a
|
|
172
180
|
[table](/reference/config) for it instead — a declared table is indexed on
|
|
173
181
|
build, kept fresh by the watcher, and (with `--persist`) survives restarts, so
|
|
174
182
|
its rows are read from SQLite rather than re-walked each time.
|
|
@@ -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.4.
|
|
7
|
+
version = "0.4.19"
|
|
8
8
|
# abi3 note: the `abi3-py310` pyo3 feature (below) builds ONE stable-ABI
|
|
9
9
|
# `cp310-abi3` wheel per platform that loads on every CPython >= 3.10
|
|
10
10
|
# (matching `pyproject.toml`'s `requires-python = ">=3.10"`), instead of
|
|
@@ -55,6 +55,19 @@ can't be trusted at all — the table/ignore configuration changed, or the
|
|
|
55
55
|
automatically. You never need to delete it by hand; a full rebuild costs
|
|
56
56
|
exactly what a non-persistent startup does.
|
|
57
57
|
|
|
58
|
+
A run that changes nothing writes nothing: the cache file is read and left
|
|
59
|
+
exactly as it was.
|
|
60
|
+
|
|
61
|
+
This covers both kinds of table. Declared tables keep their indexed rows, and
|
|
62
|
+
a [path-table](../reference/path-tables.md) parsed with `--on-file` keeps each
|
|
63
|
+
file's parser output — so the second run over an unchanged tree spawns no
|
|
64
|
+
parser process at all. A path-table's cached rows are keyed by the tree, the
|
|
65
|
+
glob, the parser command and the `dirsql` version together, so changing any of
|
|
66
|
+
them parses afresh rather than serving rows the current command never
|
|
67
|
+
produced. A *stat* path-table caches nothing, because there is nothing to
|
|
68
|
+
save: its columns are the metadata the scan already collected, and `content`
|
|
69
|
+
is read live by design.
|
|
70
|
+
|
|
58
71
|
Persistence is a startup-time optimization, not a change in meaning: the
|
|
59
72
|
database remains a derived view of your files, and queries return the same
|
|
60
73
|
rows either way ([how `dirsql` thinks](../explanation.md)).
|
|
@@ -140,6 +140,12 @@ the table:
|
|
|
140
140
|
scan continues. The schema is inferred from the files that did parse.
|
|
141
141
|
- **The skip rules still apply.** A parsed scan honors the same `node_modules`
|
|
142
142
|
/`.git`/`ignore` rules a stat scan does (see below).
|
|
143
|
+
- **`--persist` skips the parser for unchanged files.** With a
|
|
144
|
+
[persistent cache](/howto/persist), each file's parser output is stored
|
|
145
|
+
against its stat metadata, so a later run over an unchanged tree serves the
|
|
146
|
+
rows from the cache and spawns no process. Change the file, the glob, the
|
|
147
|
+
parser command, or the dirsql version and that file (or that whole table) is
|
|
148
|
+
parsed again.
|
|
143
149
|
|
|
144
150
|
`--on-file` applies to **every** path-table in the query and may be given **at
|
|
145
151
|
most once**. For different parsers per file set, define named tables in a
|
|
@@ -160,15 +166,17 @@ deleted *after* the scan finds it but *before* its `content` is read yields
|
|
|
160
166
|
than failing the query. This is an accepted consequence of reading live, not a
|
|
161
167
|
bug to design around.
|
|
162
168
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
169
|
+
The table itself is per-connection: it lives in `temp`, so it cannot leak into
|
|
170
|
+
`sqlite_master` or survive a restart. Under `--persist` a *parsed* table's rows
|
|
171
|
+
outlive the connection in the cache (above), but the table is still minted
|
|
172
|
+
fresh each run and the scan still decides what exists. The reserved top-level
|
|
173
|
+
`.dirsql/` directory is excluded from the scan, as everywhere else.
|
|
166
174
|
|
|
167
175
|
### When to promote to a declared table
|
|
168
176
|
|
|
169
|
-
Every query re-scans the filesystem: a path-table has no index
|
|
170
|
-
|
|
171
|
-
|
|
177
|
+
Every query re-scans the filesystem: a path-table has no index and no watcher.
|
|
178
|
+
That is the right trade for a hundreds-of-files, run-it-once question. When the
|
|
179
|
+
same tree is queried repeatedly, or is large, declare a
|
|
172
180
|
[table](/reference/config) for it instead — a declared table is indexed on
|
|
173
181
|
build, kept fresh by the watcher, and (with `--persist`) survives restarts, so
|
|
174
182
|
its rows are read from SQLite rather than re-walked each time.
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
**Fixed**
|
|
2
|
+
|
|
3
|
+
- **`--persist` now caches a parsed path-table's rows, so a second run over an unchanged tree re-runs the `on-file` parser for no file.** Previously the persistent cache only covered declared `[[table]]` entries: a path-table (`SELECT ... FROM './**/*.json' --on-file '<command>'`) re-scanned, re-read and re-parsed every file on every run, which made `--persist` pure overhead on the surface a configless `dirsql --persist` actually queries — measured 2.7s cold and 2.7s warm over a 2,000-file tree, versus 2.7s → 0.04s now. Each file's parser output is stored in the cache against its stat tuple (`_dirsql_parsed_rows`, reconciled by the same racy-stat rule declared tables use), keyed by the tree, glob, parser command and `dirsql` version together, so changed files re-parse and a changed command or glob starts fresh. A cache that cannot be updated costs the run its speedup, not its rows: the failure is a one-line stderr warning and the next run re-parses. A *stat* path-table is unaffected either way: its columns are the scan's own metadata and `content` stays a live read. (#825)
|
|
4
|
+
- **A run that changes nothing no longer rewrites the cache file.** The `_dirsql_meta` block was rewritten on every startup, so `cache.db` changed even when the tree had not; it is now written only when the meta actually differs, leaving an unchanged warm start byte-for-byte identical. (#825)
|
|
@@ -55,6 +55,19 @@ can't be trusted at all — the table/ignore configuration changed, or the
|
|
|
55
55
|
automatically. You never need to delete it by hand; a full rebuild costs
|
|
56
56
|
exactly what a non-persistent startup does.
|
|
57
57
|
|
|
58
|
+
A run that changes nothing writes nothing: the cache file is read and left
|
|
59
|
+
exactly as it was.
|
|
60
|
+
|
|
61
|
+
This covers both kinds of table. Declared tables keep their indexed rows, and
|
|
62
|
+
a [path-table](../reference/path-tables.md) parsed with `--on-file` keeps each
|
|
63
|
+
file's parser output — so the second run over an unchanged tree spawns no
|
|
64
|
+
parser process at all. A path-table's cached rows are keyed by the tree, the
|
|
65
|
+
glob, the parser command and the `dirsql` version together, so changing any of
|
|
66
|
+
them parses afresh rather than serving rows the current command never
|
|
67
|
+
produced. A *stat* path-table caches nothing, because there is nothing to
|
|
68
|
+
save: its columns are the metadata the scan already collected, and `content`
|
|
69
|
+
is read live by design.
|
|
70
|
+
|
|
58
71
|
Persistence is a startup-time optimization, not a change in meaning: the
|
|
59
72
|
database remains a derived view of your files, and queries return the same
|
|
60
73
|
rows either way ([how `dirsql` thinks](../explanation.md)).
|
|
@@ -140,6 +140,12 @@ the table:
|
|
|
140
140
|
scan continues. The schema is inferred from the files that did parse.
|
|
141
141
|
- **The skip rules still apply.** A parsed scan honors the same `node_modules`
|
|
142
142
|
/`.git`/`ignore` rules a stat scan does (see below).
|
|
143
|
+
- **`--persist` skips the parser for unchanged files.** With a
|
|
144
|
+
[persistent cache](/howto/persist), each file's parser output is stored
|
|
145
|
+
against its stat metadata, so a later run over an unchanged tree serves the
|
|
146
|
+
rows from the cache and spawns no process. Change the file, the glob, the
|
|
147
|
+
parser command, or the dirsql version and that file (or that whole table) is
|
|
148
|
+
parsed again.
|
|
143
149
|
|
|
144
150
|
`--on-file` applies to **every** path-table in the query and may be given **at
|
|
145
151
|
most once**. For different parsers per file set, define named tables in a
|
|
@@ -160,15 +166,17 @@ deleted *after* the scan finds it but *before* its `content` is read yields
|
|
|
160
166
|
than failing the query. This is an accepted consequence of reading live, not a
|
|
161
167
|
bug to design around.
|
|
162
168
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
169
|
+
The table itself is per-connection: it lives in `temp`, so it cannot leak into
|
|
170
|
+
`sqlite_master` or survive a restart. Under `--persist` a *parsed* table's rows
|
|
171
|
+
outlive the connection in the cache (above), but the table is still minted
|
|
172
|
+
fresh each run and the scan still decides what exists. The reserved top-level
|
|
173
|
+
`.dirsql/` directory is excluded from the scan, as everywhere else.
|
|
166
174
|
|
|
167
175
|
### When to promote to a declared table
|
|
168
176
|
|
|
169
|
-
Every query re-scans the filesystem: a path-table has no index
|
|
170
|
-
|
|
171
|
-
|
|
177
|
+
Every query re-scans the filesystem: a path-table has no index and no watcher.
|
|
178
|
+
That is the right trade for a hundreds-of-files, run-it-once question. When the
|
|
179
|
+
same tree is queried repeatedly, or is large, declare a
|
|
172
180
|
[table](/reference/config) for it instead — a declared table is indexed on
|
|
173
181
|
build, kept fresh by the watcher, and (with `--persist`) survives restarts, so
|
|
174
182
|
its rows are read from SQLite rather than re-walked each time.
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
### Persisted path-tables reuse a parser's output across runs
|
|
2
|
+
|
|
3
|
+
#### Summary
|
|
4
|
+
|
|
5
|
+
Under `--persist`, a path-table parsed with `--on-file` now serves an unchanged
|
|
6
|
+
file's rows from the cache instead of re-running the parser (dirsql#825). No
|
|
7
|
+
API changed and no call site moves; what changes is how often your parser
|
|
8
|
+
command runs. A parser whose output is a function of the file it is handed —
|
|
9
|
+
the documented `on-file` contract, and what declared `[[table]]` hooks have
|
|
10
|
+
always assumed under `--persist` — sees no difference beyond speed. A parser
|
|
11
|
+
that returns something different for the same unchanged file (it reads the
|
|
12
|
+
clock, a network service, or an environment variable) will now be observed
|
|
13
|
+
returning the *previous* run's answer until the file itself changes.
|
|
14
|
+
|
|
15
|
+
#### Required changes
|
|
16
|
+
|
|
17
|
+
_None._ Nothing to update: the fix restores the behavior
|
|
18
|
+
`docs/howto/persist.md` already documented.
|
|
19
|
+
|
|
20
|
+
| Surface | Before | After |
|
|
21
|
+
| ------- | ------ | ----- |
|
|
22
|
+
| `dirsql query "… FROM './**/*.json'" --on-file '<cmd>' --persist` | the parser ran once per file on every run | the parser runs only for files whose stat metadata moved |
|
|
23
|
+
|
|
24
|
+
#### Deprecations removed
|
|
25
|
+
|
|
26
|
+
_None._
|
|
27
|
+
|
|
28
|
+
#### Behavior changes without code changes
|
|
29
|
+
|
|
30
|
+
- **Parsed path-tables under `--persist`**: previously the parser ran once per
|
|
31
|
+
matched file on every run; now a file whose size/mtime/ctime/inode/device
|
|
32
|
+
tuple matches the cache serves its cached rows and the process is not
|
|
33
|
+
spawned. Cached rows are keyed by the scan root, the glob, the parser command
|
|
34
|
+
and the `dirsql` version together, so changing any of them re-parses. A
|
|
35
|
+
parser that is not a pure function of its input file should either be run
|
|
36
|
+
without `--persist` or made to vary with the file.
|
|
37
|
+
- **The cache file on an unchanged run**: previously every startup rewrote the
|
|
38
|
+
`_dirsql_meta` block, so `cache.db` changed even when nothing about the tree
|
|
39
|
+
had; now a run that changes nothing writes nothing and the file is left
|
|
40
|
+
byte-for-byte identical. Tooling that watched the cache's mtime as a
|
|
41
|
+
"dirsql ran" signal needs a different signal.
|
|
42
|
+
- **The internal `dirsql_parsed` vtab module** takes a fifth fixed argument
|
|
43
|
+
(the cache path, empty for none) between the gitignore switch and the ignore
|
|
44
|
+
patterns. It is `#[doc(hidden)]` plumbing that `dirsql` mints for itself; a
|
|
45
|
+
hand-written `CREATE VIRTUAL TABLE … USING dirsql_parsed(…)` must add the
|
|
46
|
+
argument.
|
|
47
|
+
|
|
48
|
+
#### Verification
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
mkdir -p /tmp/dirsql-825 && cd /tmp/dirsql-825
|
|
52
|
+
printf '[{"id":1}]' > a.json
|
|
53
|
+
dirsql query "SELECT id FROM './*.json'" --on-file 'cat {path}' --persist
|
|
54
|
+
md5sum .dirsql/cache.db
|
|
55
|
+
time dirsql query "SELECT id FROM './*.json'" --on-file 'cat {path}' --persist
|
|
56
|
+
md5sum .dirsql/cache.db
|
|
57
|
+
# expected: the same rows, the second run near-instant, the same md5 both times
|
|
58
|
+
```
|
|
@@ -114,12 +114,18 @@ fn quote_identifier(s: &str) -> String {
|
|
|
114
114
|
/// the parsed module instead: its rows and schema come from the parser, not
|
|
115
115
|
/// the stat columns, and the `path_prefix` is irrelevant (a parser wanting a
|
|
116
116
|
/// path emits it). Both forms carry the same ignore rules.
|
|
117
|
+
///
|
|
118
|
+
/// A parsed table also carries `cache` — the persistent cache path when the
|
|
119
|
+
/// index has one — so it can serve an unchanged file's rows without re-running
|
|
120
|
+
/// the parser. The stat module takes no such argument: its columns are the
|
|
121
|
+
/// stat tuple the scan already has, so there is nothing to save.
|
|
117
122
|
fn path_table_ddl(
|
|
118
123
|
name: &str,
|
|
119
124
|
table: &PathTable,
|
|
120
125
|
ignore: &[String],
|
|
121
126
|
gitignore: bool,
|
|
122
127
|
parser: Option<&str>,
|
|
128
|
+
cache: Option<&Path>,
|
|
123
129
|
) -> String {
|
|
124
130
|
let (module, mut args) = match parser {
|
|
125
131
|
Some(command) => (
|
|
@@ -144,6 +150,13 @@ fn path_table_ddl(
|
|
|
144
150
|
} else {
|
|
145
151
|
scanner::NO_GITIGNORE_ARG
|
|
146
152
|
}));
|
|
153
|
+
if parser.is_some() {
|
|
154
|
+
args.push(quote_literal(
|
|
155
|
+
&cache
|
|
156
|
+
.map(|p| p.to_string_lossy().into_owned())
|
|
157
|
+
.unwrap_or_default(),
|
|
158
|
+
));
|
|
159
|
+
}
|
|
147
160
|
args.extend(ignore.iter().map(|p| quote_literal(p)));
|
|
148
161
|
|
|
149
162
|
format!(
|
|
@@ -222,6 +235,9 @@ pub struct Db {
|
|
|
222
235
|
/// parser instead of the stat columns: its rows and schema come from the
|
|
223
236
|
/// command's output. `None` keeps the stat path-table behavior.
|
|
224
237
|
path_table_parser: Option<String>,
|
|
238
|
+
/// The persistent cache a parsed path-table reuses across runs. `None` for
|
|
239
|
+
/// an ephemeral index, which has nowhere to cache to.
|
|
240
|
+
path_table_cache: Option<PathBuf>,
|
|
225
241
|
}
|
|
226
242
|
|
|
227
243
|
/// The skip rules a fresh `Db` starts with.
|
|
@@ -256,6 +272,7 @@ impl Db {
|
|
|
256
272
|
path_table_ignore: default_path_table_ignore(),
|
|
257
273
|
path_table_gitignore: true,
|
|
258
274
|
path_table_parser: None,
|
|
275
|
+
path_table_cache: None,
|
|
259
276
|
})
|
|
260
277
|
}
|
|
261
278
|
|
|
@@ -277,6 +294,7 @@ impl Db {
|
|
|
277
294
|
path_table_ignore: default_path_table_ignore(),
|
|
278
295
|
path_table_gitignore: true,
|
|
279
296
|
path_table_parser: None,
|
|
297
|
+
path_table_cache: None,
|
|
280
298
|
})
|
|
281
299
|
}
|
|
282
300
|
|
|
@@ -313,6 +331,14 @@ impl Db {
|
|
|
313
331
|
self.path_table_parser = Some(command);
|
|
314
332
|
}
|
|
315
333
|
|
|
334
|
+
/// Point every parsed path-table minted on this connection at the
|
|
335
|
+
/// persistent cache, so an unchanged file's rows are served from it
|
|
336
|
+
/// instead of re-running the parser. Set only when the index persists;
|
|
337
|
+
/// an ephemeral index has nowhere to cache to.
|
|
338
|
+
pub fn set_path_table_cache(&mut self, path: PathBuf) {
|
|
339
|
+
self.path_table_cache = Some(path);
|
|
340
|
+
}
|
|
341
|
+
|
|
316
342
|
/// Borrow the underlying SQLite connection. Internal use only — exposed
|
|
317
343
|
/// to the `persist` module so it can manage the sidecar tables.
|
|
318
344
|
#[doc(hidden)]
|
|
@@ -783,6 +809,7 @@ impl Db {
|
|
|
783
809
|
&self.path_table_ignore,
|
|
784
810
|
self.path_table_gitignore,
|
|
785
811
|
self.path_table_parser.as_deref(),
|
|
812
|
+
self.path_table_cache.as_deref(),
|
|
786
813
|
))?;
|
|
787
814
|
Ok(())
|
|
788
815
|
}
|
|
@@ -2167,7 +2194,7 @@ mod tests {
|
|
|
2167
2194
|
|
|
2168
2195
|
#[test]
|
|
2169
2196
|
fn path_table_ddl_creates_in_temp_if_not_exists() {
|
|
2170
|
-
let ddl = path_table_ddl("./docs/*.md", &docs_path_table(), &[], true, None);
|
|
2197
|
+
let ddl = path_table_ddl("./docs/*.md", &docs_path_table(), &[], true, None, None);
|
|
2171
2198
|
assert_eq!(
|
|
2172
2199
|
ddl,
|
|
2173
2200
|
"CREATE VIRTUAL TABLE IF NOT EXISTS temp.\"./docs/*.md\" \
|
|
@@ -2183,16 +2210,16 @@ mod tests {
|
|
|
2183
2210
|
path_prefix: "/var/log".to_string(),
|
|
2184
2211
|
};
|
|
2185
2212
|
assert!(
|
|
2186
|
-
path_table_ddl("/var/log/*.log", &table, &[], true, None)
|
|
2213
|
+
path_table_ddl("/var/log/*.log", &table, &[], true, None, None)
|
|
2187
2214
|
.contains("'/var/log', '*.log', '/var/log', 'gitignore')"),
|
|
2188
2215
|
"got: {}",
|
|
2189
|
-
path_table_ddl("/var/log/*.log", &table, &[], true, None)
|
|
2216
|
+
path_table_ddl("/var/log/*.log", &table, &[], true, None, None)
|
|
2190
2217
|
);
|
|
2191
2218
|
}
|
|
2192
2219
|
|
|
2193
2220
|
#[test]
|
|
2194
2221
|
fn path_table_ddl_carries_the_no_gitignore_switch() {
|
|
2195
|
-
let ddl = path_table_ddl("./", &docs_path_table(), &[], false, None);
|
|
2222
|
+
let ddl = path_table_ddl("./", &docs_path_table(), &[], false, None, None);
|
|
2196
2223
|
assert!(
|
|
2197
2224
|
ddl.ends_with("'', 'no-gitignore')"),
|
|
2198
2225
|
"gitignore off must emit the no-gitignore switch, got: {ddl}"
|
|
@@ -2207,6 +2234,7 @@ mod tests {
|
|
|
2207
2234
|
&["node_modules/**".to_string(), "*.tmp".to_string()],
|
|
2208
2235
|
true,
|
|
2209
2236
|
None,
|
|
2237
|
+
None,
|
|
2210
2238
|
);
|
|
2211
2239
|
assert!(
|
|
2212
2240
|
ddl.ends_with("'', 'gitignore', 'node_modules/**', '*.tmp')"),
|
|
@@ -2222,11 +2250,44 @@ mod tests {
|
|
|
2222
2250
|
&[],
|
|
2223
2251
|
true,
|
|
2224
2252
|
Some("cat {path}"),
|
|
2253
|
+
None,
|
|
2225
2254
|
);
|
|
2226
2255
|
assert_eq!(
|
|
2227
2256
|
ddl,
|
|
2228
2257
|
"CREATE VIRTUAL TABLE IF NOT EXISTS temp.\"./docs/*.md\" \
|
|
2229
|
-
USING dirsql_parsed('/root', 'docs/*.md', 'cat {path}', 'gitignore')"
|
|
2258
|
+
USING dirsql_parsed('/root', 'docs/*.md', 'cat {path}', 'gitignore', '')"
|
|
2259
|
+
);
|
|
2260
|
+
}
|
|
2261
|
+
|
|
2262
|
+
#[test]
|
|
2263
|
+
fn path_table_ddl_parser_form_carries_the_cache_path() {
|
|
2264
|
+
let ddl = path_table_ddl(
|
|
2265
|
+
"./docs/*.md",
|
|
2266
|
+
&docs_path_table(),
|
|
2267
|
+
&[],
|
|
2268
|
+
true,
|
|
2269
|
+
Some("cat {path}"),
|
|
2270
|
+
Some(Path::new("/cache/dirsql.db")),
|
|
2271
|
+
);
|
|
2272
|
+
assert!(
|
|
2273
|
+
ddl.ends_with("'cat {path}', 'gitignore', '/cache/dirsql.db')"),
|
|
2274
|
+
"a persisted index points the parsed module at its cache, got: {ddl}"
|
|
2275
|
+
);
|
|
2276
|
+
}
|
|
2277
|
+
|
|
2278
|
+
#[test]
|
|
2279
|
+
fn path_table_ddl_stat_form_takes_no_cache_path() {
|
|
2280
|
+
let ddl = path_table_ddl(
|
|
2281
|
+
"./docs/*.md",
|
|
2282
|
+
&docs_path_table(),
|
|
2283
|
+
&[],
|
|
2284
|
+
true,
|
|
2285
|
+
None,
|
|
2286
|
+
Some(Path::new("/cache/dirsql.db")),
|
|
2287
|
+
);
|
|
2288
|
+
assert!(
|
|
2289
|
+
ddl.ends_with("'', 'gitignore')"),
|
|
2290
|
+
"the stat form has nothing to cache, got: {ddl}"
|
|
2230
2291
|
);
|
|
2231
2292
|
}
|
|
2232
2293
|
|
|
@@ -2243,11 +2304,12 @@ mod tests {
|
|
|
2243
2304
|
&["node_modules/**".to_string()],
|
|
2244
2305
|
true,
|
|
2245
2306
|
Some("parse.py {path}"),
|
|
2307
|
+
None,
|
|
2246
2308
|
);
|
|
2247
2309
|
assert!(
|
|
2248
2310
|
ddl.ends_with(
|
|
2249
2311
|
"USING dirsql_parsed('/var/log', '*.log', 'parse.py {path}', 'gitignore', \
|
|
2250
|
-
'node_modules/**')"
|
|
2312
|
+
'', 'node_modules/**')"
|
|
2251
2313
|
),
|
|
2252
2314
|
"the parser form drops the path prefix and keeps ignore rules, got: {ddl}"
|
|
2253
2315
|
);
|
|
@@ -2255,7 +2317,14 @@ mod tests {
|
|
|
2255
2317
|
|
|
2256
2318
|
#[test]
|
|
2257
2319
|
fn path_table_ddl_parser_form_quotes_a_command_with_a_quote() {
|
|
2258
|
-
let ddl = path_table_ddl(
|
|
2320
|
+
let ddl = path_table_ddl(
|
|
2321
|
+
"./",
|
|
2322
|
+
&docs_path_table(),
|
|
2323
|
+
&[],
|
|
2324
|
+
true,
|
|
2325
|
+
Some("sh -c 'echo hi'"),
|
|
2326
|
+
None,
|
|
2327
|
+
);
|
|
2259
2328
|
assert!(
|
|
2260
2329
|
ddl.contains("'sh -c ''echo hi'''"),
|
|
2261
2330
|
"an embedded quote must be doubled, got: {ddl}"
|
|
@@ -2269,6 +2338,17 @@ mod tests {
|
|
|
2269
2338
|
assert_eq!(db.path_table_parser.as_deref(), Some("cat {path}"));
|
|
2270
2339
|
}
|
|
2271
2340
|
|
|
2341
|
+
#[test]
|
|
2342
|
+
fn set_path_table_cache_points_parsed_tables_at_the_cache() {
|
|
2343
|
+
let mut db = Db::new().unwrap();
|
|
2344
|
+
assert_eq!(db.path_table_cache, None, "an ephemeral index has no cache");
|
|
2345
|
+
db.set_path_table_cache(PathBuf::from("/cache/dirsql.db"));
|
|
2346
|
+
assert_eq!(
|
|
2347
|
+
db.path_table_cache.as_deref(),
|
|
2348
|
+
Some(Path::new("/cache/dirsql.db"))
|
|
2349
|
+
);
|
|
2350
|
+
}
|
|
2351
|
+
|
|
2272
2352
|
#[test]
|
|
2273
2353
|
fn path_table_gitignore_defaults_on() {
|
|
2274
2354
|
let db = Db::new().unwrap();
|