dirsql 0.4.23__tar.gz → 0.4.25__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.23 → dirsql-0.4.25}/Cargo.lock +1 -1
- {dirsql-0.4.23 → dirsql-0.4.25}/PKG-INFO +1 -1
- {dirsql-0.4.23 → dirsql-0.4.25}/dirsql/_dirsql.pyi +2 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/docs/.vitepress/config.ts +1 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/docs/getting-started.md +1 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/docs/howto/columns-from-paths.md +1 -0
- {dirsql-0.4.23/packages/python → dirsql-0.4.25}/docs/howto/define-tables.md +1 -0
- {dirsql-0.4.23/packages/python → dirsql-0.4.25}/docs/howto/embed.md +3 -0
- {dirsql-0.4.23/packages/rust → dirsql-0.4.25}/docs/howto/extract-from-contents.md +5 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/docs/howto/parse-files-into-columns.md +1 -0
- dirsql-0.4.25/docs/howto/query-json.md +197 -0
- {dirsql-0.4.23/packages/python → dirsql-0.4.25}/docs/howto/react-to-changes.md +1 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/docs/howto/skip-files.md +1 -0
- {dirsql-0.4.23/packages/rust → dirsql-0.4.25}/docs/howto/write-a-plugin.md +1 -0
- {dirsql-0.4.23/packages/rust → dirsql-0.4.25}/docs/index.md +3 -0
- {dirsql-0.4.23/packages/rust → dirsql-0.4.25}/docs/reference/config.md +16 -2
- {dirsql-0.4.23 → dirsql-0.4.25}/docs/reference/sdk.md +11 -8
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/Cargo.toml +1 -1
- dirsql-0.4.25/packages/python/changelog.d/2026-08-20-declared-table-name.md +3 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/docs/.vitepress/config.ts +1 -0
- {dirsql-0.4.23/packages/rust → dirsql-0.4.25/packages/python}/docs/getting-started.md +1 -0
- {dirsql-0.4.23/packages/rust → dirsql-0.4.25/packages/python}/docs/howto/columns-from-paths.md +1 -0
- {dirsql-0.4.23 → dirsql-0.4.25/packages/python}/docs/howto/define-tables.md +1 -0
- {dirsql-0.4.23 → dirsql-0.4.25/packages/python}/docs/howto/embed.md +3 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/docs/howto/extract-from-contents.md +5 -0
- {dirsql-0.4.23/packages/rust → dirsql-0.4.25/packages/python}/docs/howto/parse-files-into-columns.md +1 -0
- dirsql-0.4.25/packages/python/docs/howto/query-json.md +197 -0
- {dirsql-0.4.23/packages/rust → dirsql-0.4.25/packages/python}/docs/howto/react-to-changes.md +1 -0
- {dirsql-0.4.23/packages/rust → dirsql-0.4.25/packages/python}/docs/howto/skip-files.md +1 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/docs/howto/write-a-plugin.md +1 -0
- {dirsql-0.4.23 → dirsql-0.4.25/packages/python}/docs/index.md +3 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/docs/reference/config.md +16 -2
- {dirsql-0.4.23/packages/rust → dirsql-0.4.25/packages/python}/docs/reference/sdk.md +11 -8
- dirsql-0.4.25/packages/python/e2e-attestations/claude-issue-962-0jjrfv.json +7 -0
- dirsql-0.4.25/packages/python/migrations.d/2026-08-20-declared-table-name.md +52 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/src/lib.rs +8 -12
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/tests/e2e/fixtures/dirsql_plugin_fixture/dirsql.toml +1 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/Cargo.toml +6 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/benches/db_bench.rs +20 -8
- {dirsql-0.4.23/packages/python → dirsql-0.4.25/packages/rust}/docs/getting-started.md +1 -0
- {dirsql-0.4.23/packages/python → dirsql-0.4.25/packages/rust}/docs/howto/columns-from-paths.md +1 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/docs/howto/define-tables.md +1 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/docs/howto/embed.md +3 -0
- {dirsql-0.4.23 → dirsql-0.4.25/packages/rust}/docs/howto/extract-from-contents.md +5 -0
- {dirsql-0.4.23/packages/python → dirsql-0.4.25/packages/rust}/docs/howto/parse-files-into-columns.md +1 -0
- dirsql-0.4.25/packages/rust/docs/howto/query-json.md +197 -0
- {dirsql-0.4.23 → dirsql-0.4.25/packages/rust}/docs/howto/react-to-changes.md +1 -0
- {dirsql-0.4.23/packages/python → dirsql-0.4.25/packages/rust}/docs/howto/skip-files.md +1 -0
- {dirsql-0.4.23 → dirsql-0.4.25/packages/rust}/docs/howto/write-a-plugin.md +1 -0
- {dirsql-0.4.23/packages/python → dirsql-0.4.25/packages/rust}/docs/index.md +3 -0
- {dirsql-0.4.23 → dirsql-0.4.25/packages/rust}/docs/reference/config.md +16 -2
- {dirsql-0.4.23/packages/python → dirsql-0.4.25/packages/rust}/docs/reference/sdk.md +11 -8
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/src/cli/run.rs +1 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/src/config.rs +93 -32
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/src/db.rs +70 -351
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/src/default_config.toml +4 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/src/lib.rs +96 -27
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/src/persist.rs +10 -8
- dirsql-0.4.23/packages/rust/changelog.d/2026-07-13-batch-ingest-transaction.md +0 -1
- dirsql-0.4.23/packages/rust/changelog.d/2026-07-13-chained-pre-post-query-hooks.md +0 -3
- dirsql-0.4.23/packages/rust/changelog.d/2026-07-13-drop-cwd-config-auto-detect.md +0 -3
- dirsql-0.4.23/packages/rust/changelog.d/2026-07-13-fan-out-file-table-matching.md +0 -3
- dirsql-0.4.23/packages/rust/changelog.d/2026-07-13-persist-wal.md +0 -3
- dirsql-0.4.23/packages/rust/changelog.d/2026-07-13-rename-extract-to-on-file.md +0 -3
- dirsql-0.4.23/packages/rust/changelog.d/2026-07-13-repeatable-builder-config.md +0 -3
- dirsql-0.4.23/packages/rust/changelog.d/2026-07-13-repeatable-cli-config.md +0 -3
- dirsql-0.4.23/packages/rust/changelog.d/2026-07-13-sdk-default-baked-in-config.md +0 -3
- dirsql-0.4.23/packages/rust/changelog.d/2026-07-13-subcommand-local-config-flags.md +0 -1
- dirsql-0.4.23/packages/rust/changelog.d/2026-07-19-path-table-query-fallback.md +0 -10
- dirsql-0.4.23/packages/rust/changelog.d/2026-07-19-path-table-vtab.md +0 -7
- dirsql-0.4.23/packages/rust/changelog.d/2026-07-20-drop-implicit-files-table.md +0 -11
- dirsql-0.4.23/packages/rust/changelog.d/2026-07-20-path-table-glob-semantics.md +0 -11
- dirsql-0.4.23/packages/rust/changelog.d/2026-07-20-schema-inference.md +0 -12
- dirsql-0.4.23/packages/rust/changelog.d/2026-07-21-on-file-flag.md +0 -14
- dirsql-0.4.23/packages/rust/changelog.d/2026-07-21-remove-glob-captures.md +0 -3
- dirsql-0.4.23/packages/rust/changelog.d/2026-07-23-init-escalation-example.md +0 -10
- dirsql-0.4.23/packages/rust/changelog.d/2026-07-23-query-default-cli.md +0 -1
- dirsql-0.4.23/packages/rust/changelog.d/2026-07-24-hookless-table-config-error.md +0 -3
- dirsql-0.4.23/packages/rust/changelog.d/2026-07-24-remove-stat-fact-injection.md +0 -3
- dirsql-0.4.23/packages/rust/changelog.d/2026-07-29-on-file-failures-accumulate.md +0 -8
- dirsql-0.4.23/packages/rust/changelog.d/2026-08-02-drop-regex.md +0 -17
- dirsql-0.4.23/packages/rust/changelog.d/2026-08-02-per-file-scan-failures.md +0 -35
- dirsql-0.4.23/packages/rust/changelog.d/2026-08-02-release-profile.md +0 -7
- dirsql-0.4.23/packages/rust/changelog.d/2026-08-03-gitignore-by-default.md +0 -9
- dirsql-0.4.23/packages/rust/changelog.d/2026-08-03-nested-default-ignores.md +0 -11
- dirsql-0.4.23/packages/rust/changelog.d/2026-08-04-cast-lints.md +0 -1
- dirsql-0.4.23/packages/rust/changelog.d/2026-08-04-cli-run-shim.md +0 -3
- dirsql-0.4.23/packages/rust/changelog.d/2026-08-04-configless-extension.md +0 -1
- dirsql-0.4.23/packages/rust/changelog.d/2026-08-10-dirsql-function.md +0 -1
- dirsql-0.4.23/packages/rust/changelog.d/2026-08-10-remove-query-hooks.md +0 -3
- dirsql-0.4.23/packages/rust/changelog.d/2026-08-11-oneshot-query-no-timeout.md +0 -3
- dirsql-0.4.23/packages/rust/changelog.d/2026-08-11-persist-parsed-path-tables.md +0 -4
- dirsql-0.4.23/packages/rust/changelog.d/2026-08-11-retire-hook-timeout.md +0 -3
- dirsql-0.4.23/packages/rust/changelog.d/2026-08-12-unquote-inverts-quote-literal.md +0 -3
- dirsql-0.4.23/packages/rust/changelog.d/2026-08-20-unquoted-path-table-hint.md +0 -3
- dirsql-0.4.23/packages/rust/changelog.d/README.md +0 -17
- dirsql-0.4.23/packages/rust/migrations.d/2026-07-13-drop-cwd-config-auto-detect.md +0 -52
- dirsql-0.4.23/packages/rust/migrations.d/2026-07-13-fan-out-file-table-matching.md +0 -70
- dirsql-0.4.23/packages/rust/migrations.d/2026-07-13-persist-wal.md +0 -38
- dirsql-0.4.23/packages/rust/migrations.d/2026-07-13-rename-extract-to-on-file.md +0 -54
- dirsql-0.4.23/packages/rust/migrations.d/2026-07-13-sdk-default-baked-in-config.md +0 -46
- dirsql-0.4.23/packages/rust/migrations.d/2026-07-13-subcommand-local-config-flags.md +0 -50
- dirsql-0.4.23/packages/rust/migrations.d/2026-07-20-drop-implicit-files-table.md +0 -67
- dirsql-0.4.23/packages/rust/migrations.d/2026-07-20-path-table-glob-semantics.md +0 -57
- dirsql-0.4.23/packages/rust/migrations.d/2026-07-21-remove-glob-captures.md +0 -53
- dirsql-0.4.23/packages/rust/migrations.d/2026-07-23-init-escalation-example.md +0 -64
- dirsql-0.4.23/packages/rust/migrations.d/2026-07-23-query-default-cli.md +0 -55
- dirsql-0.4.23/packages/rust/migrations.d/2026-07-24-hookless-table-config-error.md +0 -51
- dirsql-0.4.23/packages/rust/migrations.d/2026-07-24-remove-stat-fact-injection.md +0 -55
- dirsql-0.4.23/packages/rust/migrations.d/2026-08-02-per-file-scan-failures.md +0 -100
- dirsql-0.4.23/packages/rust/migrations.d/2026-08-03-gitignore-by-default.md +0 -52
- dirsql-0.4.23/packages/rust/migrations.d/2026-08-03-nested-default-ignores.md +0 -46
- dirsql-0.4.23/packages/rust/migrations.d/2026-08-10-remove-query-hooks.md +0 -47
- dirsql-0.4.23/packages/rust/migrations.d/2026-08-11-oneshot-query-no-timeout.md +0 -46
- dirsql-0.4.23/packages/rust/migrations.d/2026-08-11-persist-parsed-path-tables.md +0 -58
- dirsql-0.4.23/packages/rust/migrations.d/2026-08-11-retire-hook-timeout.md +0 -51
- dirsql-0.4.23/packages/rust/migrations.d/README.md +0 -19
- {dirsql-0.4.23 → dirsql-0.4.25}/Cargo.toml +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/README.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/dirsql/__init__.py +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/dirsql/_async.py +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/dirsql/cli/__init__.py +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/dirsql/cli/discover_plugins/__init__.py +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/dirsql/cli/discover_plugins/discovered_fragments.py +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/dirsql/cli/discover_plugins/discovery_disabled.py +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/dirsql/cli/discover_plugins/fragment_path.py +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/dirsql/cli/discover_plugins/user_passed_config.py +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/dirsql/cli/discover_plugins/with_discovered_plugins.py +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/dirsql/cli/main.py +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/dirsql/cli/resolve_config_extensions.py +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/dirsql/py.typed +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/dirsql/resolve_config_extensions.py +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/dirsql/resolve_extension.py +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/docs/.claude/CLAUDE.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/docs/.vitepress/theme/index.ts +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/docs/.vitepress/theme/lang.ts +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/docs/AGENTS.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/docs/explanation.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/docs/howto/load-extension.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/docs/howto/persist.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/docs/howto/query-without-config.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/docs/howto/search-by-meaning.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/docs/package.json +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/docs/plugins.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/docs/pnpm-lock.yaml +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/docs/pnpm-workspace.yaml +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/docs/reference/cli.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/docs/reference/columns.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/docs/reference/hooks.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/docs/reference/http-api.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/docs/reference/path-tables.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/CHANGELOG.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/MIGRATIONS.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/README.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/changelog.d/2026-07-13-drop-cwd-config-auto-detect.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/changelog.d/2026-07-13-plugin-discovery.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/changelog.d/2026-07-13-rename-extract-to-on-file.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/changelog.d/2026-07-13-repeatable-config.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/changelog.d/2026-07-13-sdk-default-baked-in-config.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/changelog.d/2026-07-20-drop-implicit-files-table.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/changelog.d/2026-07-21-remove-glob-captures.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/changelog.d/2026-07-24-hookless-table-config-error.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/changelog.d/2026-07-24-remove-stat-fact-injection.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/changelog.d/2026-07-29-restore-python-310.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/changelog.d/2026-08-02-release-profile.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/changelog.d/2026-08-02-scan-failures.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/changelog.d/2026-08-03-discovery-ext-resolution.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/changelog.d/2026-08-03-manylinux-dynamic-binary.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/changelog.d/2026-08-03-python-no-ignore.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/changelog.d/2026-08-04-cast-lints.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/changelog.d/2026-08-04-cli-in-process.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/changelog.d/README.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/conftest.py +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/docs/.claude/CLAUDE.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/docs/.vitepress/theme/index.ts +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/docs/.vitepress/theme/lang.ts +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/docs/AGENTS.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/docs/explanation.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/docs/howto/load-extension.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/docs/howto/persist.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/docs/howto/query-without-config.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/docs/howto/search-by-meaning.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/docs/package.json +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/docs/plugins.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/docs/pnpm-lock.yaml +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/docs/pnpm-workspace.yaml +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/docs/reference/cli.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/docs/reference/columns.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/docs/reference/hooks.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/docs/reference/http-api.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/docs/reference/path-tables.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/e2e-attestations/claude-819-oneshot-timeout.json +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/e2e-attestations/claude-827-unquote-doubled-quotes.json +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/e2e-attestations/claude-github-issue-825-e4mhhp.json +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/e2e-attestations/claude-issue-951-0eease.json +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/migrations.d/2026-07-13-drop-cwd-config-auto-detect.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/migrations.d/2026-07-13-rename-extract-to-on-file.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/migrations.d/2026-07-13-sdk-default-baked-in-config.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/migrations.d/2026-07-20-drop-implicit-files-table.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/migrations.d/2026-07-21-remove-glob-captures.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/migrations.d/2026-07-24-hookless-table-config-error.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/migrations.d/2026-07-24-remove-stat-fact-injection.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/migrations.d/2026-07-29-restore-python-310.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/migrations.d/2026-08-04-cli-in-process.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/migrations.d/README.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/testing-conventions.toml +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/tests/__init__.py +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/tests/conftest.py +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/tests/e2e/__init__.py +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/tests/e2e/fixtures/dirsql_plugin_fixture/__init__.py +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/tests/integration/__init__.py +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/tests/integration/binding/__init__.py +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/python/tests/integration/hermetic/__init__.py +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/CHANGELOG.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/MIGRATIONS.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/README.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/benches/differ_bench.rs +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/benches/matcher_bench.rs +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/benches/scanner_bench.rs +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/docs/explanation.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/docs/howto/load-extension.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/docs/howto/persist.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/docs/howto/query-without-config.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/docs/howto/search-by-meaning.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/docs/plugins.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/docs/reference/cli.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/docs/reference/columns.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/docs/reference/hooks.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/docs/reference/http-api.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/docs/reference/path-tables.md +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/src/bin/dirsql.rs +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/src/cli/execute.rs +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/src/cli/init.rs +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/src/cli/mod.rs +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/src/cli/router.rs +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/src/cli/serialize.rs +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/src/cli/server.rs +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/src/command.rs +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/src/differ.rs +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/src/functions.rs +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/src/infer.rs +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/src/matcher.rs +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/src/parsed_cache.rs +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/src/parsed_vtab.rs +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/src/path_table.rs +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/src/scanner.rs +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/src/sql_literal.rs +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/src/vtab.rs +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/packages/rust/src/watcher.rs +0 -0
- {dirsql-0.4.23 → dirsql-0.4.25}/pyproject.toml +0 -0
|
@@ -30,6 +30,7 @@ class ExtensionSpec(TypedDict):
|
|
|
30
30
|
class Table:
|
|
31
31
|
"""A table definition. Construct via keyword arguments only."""
|
|
32
32
|
|
|
33
|
+
name: str
|
|
33
34
|
ddl: str
|
|
34
35
|
glob: str
|
|
35
36
|
strict: bool
|
|
@@ -37,6 +38,7 @@ class Table:
|
|
|
37
38
|
def __init__(
|
|
38
39
|
self,
|
|
39
40
|
*,
|
|
41
|
+
name: str,
|
|
40
42
|
ddl: str,
|
|
41
43
|
glob: str,
|
|
42
44
|
on_file: Callable[[str], list[Row]],
|
|
@@ -54,6 +54,7 @@ export default defineConfig({
|
|
|
54
54
|
{ text: 'Derive columns from file paths', link: '/howto/columns-from-paths' },
|
|
55
55
|
{ text: 'Extract rows from file contents', link: '/howto/extract-from-contents' },
|
|
56
56
|
{ text: 'Parse your files into columns', link: '/howto/parse-files-into-columns' },
|
|
57
|
+
{ text: 'Query JSON file contents', link: '/howto/query-json' },
|
|
57
58
|
{ text: 'Search documents by meaning', link: '/howto/search-by-meaning' },
|
|
58
59
|
{ text: "Skip files you don't want indexed", link: '/howto/skip-files' },
|
|
59
60
|
{ text: 'Load a SQLite extension', link: '/howto/load-extension' },
|
|
@@ -60,6 +60,7 @@ async def main() -> None:
|
|
|
60
60
|
"./comments-root",
|
|
61
61
|
tables=[
|
|
62
62
|
Table(
|
|
63
|
+
name="comments",
|
|
63
64
|
ddl="CREATE TABLE comments (thread TEXT, author TEXT, body TEXT)",
|
|
64
65
|
glob="comments/*/*.json",
|
|
65
66
|
on_file=on_file,
|
|
@@ -83,6 +84,7 @@ const db = new DirSQL({
|
|
|
83
84
|
root: "./comments-root",
|
|
84
85
|
tables: [
|
|
85
86
|
{
|
|
87
|
+
name: "comments",
|
|
86
88
|
ddl: "CREATE TABLE comments (thread TEXT, author TEXT, body TEXT)",
|
|
87
89
|
glob: "comments/*/*.json",
|
|
88
90
|
onFile: (path) => [
|
|
@@ -129,6 +131,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
|
129
131
|
let db = DirSQL::builder()
|
|
130
132
|
.root("./comments-root")
|
|
131
133
|
.table(Table::new(
|
|
134
|
+
"comments",
|
|
132
135
|
"CREATE TABLE comments (thread TEXT, author TEXT, body TEXT)",
|
|
133
136
|
"comments/*/*.json",
|
|
134
137
|
on_file,
|
|
@@ -18,6 +18,7 @@ stdout works. With [`jq`](https://jqlang.org/):
|
|
|
18
18
|
|
|
19
19
|
```toml
|
|
20
20
|
[[table]]
|
|
21
|
+
name = "books"
|
|
21
22
|
ddl = "CREATE TABLE books (title TEXT, author TEXT, year INTEGER)"
|
|
22
23
|
glob = "books/*.json"
|
|
23
24
|
on-file = "jq -c '[{title, author, year}]' {path}"
|
|
@@ -53,6 +54,7 @@ row per line, slurp it:
|
|
|
53
54
|
|
|
54
55
|
```toml
|
|
55
56
|
[[table]]
|
|
57
|
+
name = "events"
|
|
56
58
|
ddl = "CREATE TABLE events (event TEXT, user TEXT)"
|
|
57
59
|
glob = "logs/*.jsonl"
|
|
58
60
|
on-file = "jq -c -s '.' {path}"
|
|
@@ -77,6 +79,9 @@ SQLite value mapping is under
|
|
|
77
79
|
|
|
78
80
|
## Going further
|
|
79
81
|
|
|
82
|
+
- Just want to read a field or two out of some JSON files? SQLite's JSON
|
|
83
|
+
operators work directly on a path-table's `content` column, with no config
|
|
84
|
+
and no command — [Query JSON file contents](./query-json.md).
|
|
80
85
|
- The command re-runs on every startup and on every change to a matched
|
|
81
86
|
file. If it is expensive, [keep the index across restarts](./persist.md).
|
|
82
87
|
- Embedding `dirsql` in a program instead? The SDK's `on_file` callback
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
# Query JSON file contents
|
|
2
|
+
|
|
3
|
+
A tree of JSON files is already a table — you just have to ask for it. The
|
|
4
|
+
hidden [`content`](../reference/path-tables.md#columns) column holds each
|
|
5
|
+
file's raw text, and SQLite's JSON operators read fields straight out of it.
|
|
6
|
+
No config, no parser, no schema.
|
|
7
|
+
|
|
8
|
+
## 1. Pull a field out of `content`
|
|
9
|
+
|
|
10
|
+
Suppose each plugin ships a `metadata.json`:
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
plugins/alpha/metadata.json
|
|
14
|
+
plugins/beta/metadata.json
|
|
15
|
+
plugins/gamma/metadata.json
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
```json
|
|
19
|
+
{
|
|
20
|
+
"name": "alpha",
|
|
21
|
+
"version": "1.4.0",
|
|
22
|
+
"disabled": false,
|
|
23
|
+
"runtime": { "engine": "wasm", "memory_mb": 64 },
|
|
24
|
+
"tags": ["search", "index"]
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
The `->>` operator extracts a field. **The key is a string literal, not a bare
|
|
29
|
+
identifier** — this is the one thing that trips everyone up:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
dirsql query "SELECT content ->> disabled FROM './plugins/alpha/metadata.json'"
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
dirsql query: SQLite error: no such column: disabled in SELECT content ->> disabled FROM './plugins/alpha/metadata.json' at offset 19
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Unquoted, `disabled` is a column name to SQLite's parser, and no such column
|
|
40
|
+
exists. Quote it and the field comes back:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
dirsql query "SELECT content ->> 'disabled' FROM './plugins/alpha/metadata.json'"
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
```json
|
|
47
|
+
[{"content ->> 'disabled'":0}]
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
The expression becomes the column name, so alias it:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
dirsql query "SELECT content ->> 'disabled' AS disabled FROM './plugins/alpha/metadata.json'"
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
```json
|
|
57
|
+
[{"disabled":0}]
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## 2. Query the whole tree
|
|
61
|
+
|
|
62
|
+
`content` is a [path-table](../reference/path-tables.md) column, so the same
|
|
63
|
+
expression works over a glob — one row per file:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
dirsql query "SELECT content ->> 'name' AS name, content ->> 'version' AS version
|
|
67
|
+
FROM './**/metadata.json' ORDER BY name"
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
[{"name":"alpha","version":"1.4.0"},{"name":"beta","version":"0.9.2"},{"name":"gamma","version":"2.0.1"}]
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
`content` is read only when a query names it, so a glob over a large tree costs
|
|
75
|
+
nothing until you actually reach inside the files.
|
|
76
|
+
|
|
77
|
+
## 3. Reach nested keys
|
|
78
|
+
|
|
79
|
+
A key that starts with `$` is a **JSON path**: dotted for nested objects,
|
|
80
|
+
bracketed for array elements. It is still a string literal.
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
dirsql query "SELECT content ->> 'name' AS name,
|
|
84
|
+
content ->> '$.runtime.engine' AS engine,
|
|
85
|
+
content ->> '$.runtime.memory_mb' AS memory_mb
|
|
86
|
+
FROM './**/metadata.json' ORDER BY name"
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
```json
|
|
90
|
+
[{"engine":"wasm","memory_mb":64,"name":"alpha"},{"engine":"native","memory_mb":256,"name":"beta"},{"engine":"wasm","memory_mb":128,"name":"gamma"}]
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
`content ->> 'name'` and `content ->> '$.name'` are the same lookup — the bare
|
|
94
|
+
form is shorthand for a top-level key. `json_extract(content, '$.name')` is the
|
|
95
|
+
function spelling of the same thing and takes the same paths.
|
|
96
|
+
|
|
97
|
+
## 4. Filter and aggregate
|
|
98
|
+
|
|
99
|
+
Extracted fields are ordinary SQL values, so they work in `WHERE`, `GROUP BY`,
|
|
100
|
+
and joins:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
dirsql query "SELECT path FROM './**/metadata.json'
|
|
104
|
+
WHERE content ->> 'disabled' = 0 ORDER BY path"
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
```json
|
|
108
|
+
[{"path":"plugins/alpha/metadata.json"},{"path":"plugins/gamma/metadata.json"}]
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
To count across an array field, expand it with `json_each`:
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
dirsql query "SELECT t.value AS tag, COUNT(*) AS n
|
|
115
|
+
FROM './**/metadata.json' AS m, json_each(m.content, '$.tags') AS t
|
|
116
|
+
GROUP BY tag ORDER BY n DESC, tag"
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
```json
|
|
120
|
+
[{"n":2,"tag":"index"},{"n":2,"tag":"search"},{"n":1,"tag":"export"},{"n":1,"tag":"rerank"}]
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## `->` and `->>`
|
|
124
|
+
|
|
125
|
+
Both take the same paths; they differ in what they hand back. `->>` returns the
|
|
126
|
+
**SQL value**; `->` returns the **JSON text** of that value, quotes and all:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
dirsql query "SELECT content -> 'name' AS arrow, content ->> 'name' AS arrow2
|
|
130
|
+
FROM './plugins/alpha/metadata.json'"
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
```json
|
|
134
|
+
[{"arrow":"\"alpha\"","arrow2":"alpha"}]
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Reach for `->>` to get a value out, and `->` to keep drilling — its JSON result
|
|
138
|
+
is a valid left operand for another `->` or `->>`.
|
|
139
|
+
|
|
140
|
+
## How JSON types arrive
|
|
141
|
+
|
|
142
|
+
`->>` maps JSON types onto SQLite's, which has no boolean:
|
|
143
|
+
|
|
144
|
+
| In the file | In the row |
|
|
145
|
+
| --- | --- |
|
|
146
|
+
| `true` / `false` | `1` / `0` |
|
|
147
|
+
| `null` | `NULL` |
|
|
148
|
+
| number | INTEGER or REAL |
|
|
149
|
+
| string | TEXT, unquoted |
|
|
150
|
+
| object or array | its JSON text |
|
|
151
|
+
| key not present | `NULL` |
|
|
152
|
+
|
|
153
|
+
So `disabled: false` reads back as `0`, and `WHERE content ->> 'disabled' = 0`
|
|
154
|
+
is how you ask for the enabled ones — `= false` is not SQLite syntax.
|
|
155
|
+
|
|
156
|
+
A missing key and a `null` value both arrive as `NULL`. Use
|
|
157
|
+
`content -> 'key' IS NULL` to tell them apart: `->` yields the JSON text
|
|
158
|
+
`'null'` for a present null, and SQL `NULL` only when the key is absent.
|
|
159
|
+
|
|
160
|
+
## When a file isn't valid JSON
|
|
161
|
+
|
|
162
|
+
The JSON operators reject a non-JSON `content`, and that fails the **whole
|
|
163
|
+
query** — one stray file, no rows at all:
|
|
164
|
+
|
|
165
|
+
```
|
|
166
|
+
dirsql query: SQLite error: malformed JSON
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
An empty file counts too: `content` is `''`, which is not valid JSON. Guard the
|
|
170
|
+
scan with `json_valid` when the glob might catch something it shouldn't:
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
dirsql query "SELECT content ->> 'name' AS name FROM './**/metadata.json'
|
|
174
|
+
WHERE json_valid(content) ORDER BY name"
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Files that fail the guard drop out and the rest still answer. A file that is
|
|
178
|
+
unreadable or not UTF-8 has `NULL` content, which is not an error —
|
|
179
|
+
`json_valid(NULL)` is `NULL`, so the guard excludes those too.
|
|
180
|
+
|
|
181
|
+
## Going further
|
|
182
|
+
|
|
183
|
+
- Only path-tables expose `content`. A named `[[table]]` has exactly the columns
|
|
184
|
+
its hook emits ([columns reference](../reference/columns.md)) — reading a
|
|
185
|
+
field with `->>` there means the hook already emitted it.
|
|
186
|
+
- Doing this on every query re-reads and re-parses every file. When the same
|
|
187
|
+
tree is queried repeatedly, move the extraction into a table:
|
|
188
|
+
[Extract rows from file contents](./extract-from-contents.md) declares the
|
|
189
|
+
columns in a config, and [Parse your files into columns](./parse-files-into-columns.md)
|
|
190
|
+
prototypes the same parser inline with `--on-file`. Either way the parsed rows
|
|
191
|
+
are indexed, watched, and [persistable](./persist.md).
|
|
192
|
+
- One JSON file holding *many* records is a parser's job, not an operator's —
|
|
193
|
+
`json_each` expands an array within a row, but one row per record needs
|
|
194
|
+
[`on-file`](../reference/hooks.md#on-file).
|
|
195
|
+
- The full operator and function set is SQLite's own:
|
|
196
|
+
[JSON functions](https://sqlite.org/json1.html). `dirsql` adds nothing to it
|
|
197
|
+
and takes nothing away.
|
|
@@ -22,6 +22,7 @@ Exclude the noise in `.dirsql.toml`:
|
|
|
22
22
|
ignore = ["notes/drafts/**", "**/*.tmp"]
|
|
23
23
|
|
|
24
24
|
[[table]]
|
|
25
|
+
name = "notes"
|
|
25
26
|
ddl = "CREATE TABLE notes (basename TEXT)"
|
|
26
27
|
glob = "notes/**/*"
|
|
27
28
|
on-file = '''sh -c 'printf "[{\"basename\":\"%s\"}]" "${1##*/}"' sh {path}'''
|
|
@@ -108,6 +108,7 @@ path = "sqlite_vec"
|
|
|
108
108
|
entrypoint = "sqlite3_vec_init"
|
|
109
109
|
|
|
110
110
|
[[table]]
|
|
111
|
+
name = "notes"
|
|
111
112
|
ddl = "CREATE TABLE notes (path TEXT, text TEXT, embedding TEXT)"
|
|
112
113
|
glob = "notes/*.md"
|
|
113
114
|
on-file = "uv run --with model2vec python embed.py {path} {root}"
|
|
@@ -34,6 +34,7 @@ db = DirSQL(
|
|
|
34
34
|
"./my-project",
|
|
35
35
|
tables=[
|
|
36
36
|
Table(
|
|
37
|
+
name="records",
|
|
37
38
|
ddl="CREATE TABLE records (name TEXT, size INTEGER, type TEXT)",
|
|
38
39
|
glob="data/*.json",
|
|
39
40
|
on_file=lambda path: [json.loads(open(path, encoding="utf-8").read())],
|
|
@@ -52,6 +53,7 @@ let db = DirSQL::new(
|
|
|
52
53
|
"./my-project",
|
|
53
54
|
vec![
|
|
54
55
|
Table::new(
|
|
56
|
+
"records",
|
|
55
57
|
"CREATE TABLE records (name TEXT, size INTEGER, type TEXT)",
|
|
56
58
|
"data/*.json",
|
|
57
59
|
|path| vec![serde_json::from_str(&std::fs::read_to_string(path).unwrap()).unwrap()],
|
|
@@ -70,6 +72,7 @@ const db = new DirSQL({
|
|
|
70
72
|
root: './my-project',
|
|
71
73
|
tables: [
|
|
72
74
|
new Table({
|
|
75
|
+
name: 'records',
|
|
73
76
|
ddl: 'CREATE TABLE records (name TEXT, size INTEGER, type TEXT)',
|
|
74
77
|
glob: 'data/*.json',
|
|
75
78
|
onFile: (path) => [JSON.parse(readFileSync(path, 'utf8'))],
|
|
@@ -166,7 +166,8 @@ what its required `on-file` command emits — dirsql injects nothing (see
|
|
|
166
166
|
|
|
167
167
|
| Key | Required | Description |
|
|
168
168
|
|---|---|---|
|
|
169
|
-
| `
|
|
169
|
+
| `name` | yes | The table's SQL name — the name you query it by. Declared, never derived from `ddl`: dirsql does not read the DDL text. The `ddl` must create a table by this name; if it doesn't, loading fails. |
|
|
170
|
+
| `ddl` | yes | A SQLite `CREATE TABLE` statement, run verbatim. Only the columns declared here are kept; keys the `on-file` command emits that are not declared are dropped. |
|
|
170
171
|
| `glob` | yes | Glob pattern matched against root-relative paths. Every table whose glob matches a file receives that file's rows — a file can populate multiple tables. A `{name}` segment is rewritten to `*` (it matches one path segment but captures nothing). |
|
|
171
172
|
| `on-file` | **yes** | A command run once per matched file; its stdout (a JSON array of row objects) becomes the file's rows. Must be non-empty. A `[[table]]` with no `on-file` is a load error (see [parse errors](#parse-errors)). See [Command hooks](./hooks.md#on-file). |
|
|
172
173
|
| `strict` | no (default `false`) | When `true`, rows whose keys do not exactly match the declared columns are rejected with an error: extra keys error, and every declared column must be supplied by the `on-file` output. When `false`, extra keys are dropped and missing columns become `NULL`. |
|
|
@@ -180,11 +181,13 @@ instead of declaring a table.
|
|
|
180
181
|
|
|
181
182
|
```toml
|
|
182
183
|
[[table]]
|
|
184
|
+
name = "comments"
|
|
183
185
|
ddl = "CREATE TABLE comments (path TEXT, author TEXT, body TEXT)"
|
|
184
186
|
glob = "_comments/*/*.jsonl"
|
|
185
187
|
on-file = "jq -c -s '.' {path}"
|
|
186
188
|
|
|
187
189
|
[[table]]
|
|
190
|
+
name = "papers"
|
|
188
191
|
ddl = "CREATE TABLE papers (paper_id TEXT, title TEXT)"
|
|
189
192
|
glob = "**/meta.json"
|
|
190
193
|
on-file = "uv run python extract_papers.py {path}"
|
|
@@ -241,7 +244,16 @@ SDKs raise/reject) when:
|
|
|
241
244
|
- The TOML is malformed.
|
|
242
245
|
- Any table contains an unknown key (top level, `[dirsql]`, `[[table]]`, or
|
|
243
246
|
`[[dirsql.extension]]`). The error names the offending key.
|
|
244
|
-
- A `[[table]]` entry omits `ddl` or `
|
|
247
|
+
- A `[[table]]` entry omits `name`, `ddl`, or `glob` (or `name` is
|
|
248
|
+
empty/whitespace).
|
|
249
|
+
- A `[[table]]` entry's `ddl` runs but creates no table by its `name`. The
|
|
250
|
+
error carries the entry's name and points at the fix:
|
|
251
|
+
|
|
252
|
+
> `table 'messages': its `ddl` ran but created no table called 'messages'. Set `name` to the table the `ddl` creates.`
|
|
253
|
+
|
|
254
|
+
dirsql asks SQLite's catalog rather than interpreting the DDL, so quoted
|
|
255
|
+
(`CREATE TABLE "messages"`), schema-qualified (`main.messages`) and
|
|
256
|
+
`IF NOT EXISTS` forms all match a plain `name = "messages"`.
|
|
245
257
|
- A `[[table]]` entry omits `on-file` (or it is empty/whitespace). The error
|
|
246
258
|
names the offending glob and points at the fix:
|
|
247
259
|
|
|
@@ -275,11 +287,13 @@ deterministic = true
|
|
|
275
287
|
timeout = "600s"
|
|
276
288
|
|
|
277
289
|
[[table]]
|
|
290
|
+
name = "comments"
|
|
278
291
|
ddl = "CREATE TABLE comments (author TEXT, body TEXT)"
|
|
279
292
|
glob = "_comments/*/*.jsonl"
|
|
280
293
|
on-file = "jq -c -s '.' {path}"
|
|
281
294
|
|
|
282
295
|
[[table]]
|
|
296
|
+
name = "documents"
|
|
283
297
|
ddl = "CREATE TABLE documents (title TEXT, summary TEXT)"
|
|
284
298
|
glob = "**/index.md"
|
|
285
299
|
on-file = "uv run python extract_doc.py {path}"
|
|
@@ -317,27 +317,30 @@ rather than waiting — an intentional, language-idiomatic difference.
|
|
|
317
317
|
::: code-group
|
|
318
318
|
|
|
319
319
|
```python [Python]
|
|
320
|
-
Table(*, ddl: str, glob: str, on_file: Callable[[str], list[dict]], strict: bool = False)
|
|
320
|
+
Table(*, name: str, ddl: str, glob: str, on_file: Callable[[str], list[dict]], strict: bool = False)
|
|
321
321
|
```
|
|
322
322
|
|
|
323
323
|
```typescript [TypeScript]
|
|
324
|
-
new Table({ ddl, glob, onFile, strict? })
|
|
324
|
+
new Table({ name, ddl, glob, onFile, strict? })
|
|
325
325
|
// or a plain object — TableDef and Table are interchangeable:
|
|
326
|
-
{ ddl: string, glob: string, onFile: (path: string) => Record<string, unknown>[], strict?: boolean }
|
|
326
|
+
{ name: string, ddl: string, glob: string, onFile: (path: string) => Record<string, unknown>[], strict?: boolean }
|
|
327
327
|
```
|
|
328
328
|
|
|
329
329
|
```rust [Rust]
|
|
330
|
-
Table::new(ddl, glob, on_file) // on_file: Fn(&str) -> Vec<Row>, infallible
|
|
331
|
-
Table::try_new(ddl, glob, on_file) // on_file: Fn(&str) -> Result<Vec<Row>, _>
|
|
332
|
-
Table::strict(ddl, glob, on_file) // Table::new with strict = true
|
|
330
|
+
Table::new(name, ddl, glob, on_file) // on_file: Fn(&str) -> Vec<Row>, infallible
|
|
331
|
+
Table::try_new(name, ddl, glob, on_file) // on_file: Fn(&str) -> Result<Vec<Row>, _>
|
|
332
|
+
Table::strict(name, ddl, glob, on_file) // Table::new with strict = true
|
|
333
333
|
```
|
|
334
334
|
|
|
335
335
|
:::
|
|
336
336
|
|
|
337
337
|
Maps files to table rows.
|
|
338
338
|
|
|
339
|
-
- `
|
|
340
|
-
|
|
339
|
+
- `name` — The table's SQL name, declared rather than derived from `ddl`.
|
|
340
|
+
Must be unique across all tables. Building fails if the `ddl` creates no
|
|
341
|
+
table by this name (checked against SQLite's catalog, before any file is
|
|
342
|
+
indexed).
|
|
343
|
+
- `ddl` — A SQLite `CREATE TABLE` statement, run verbatim.
|
|
341
344
|
- `glob` — Glob pattern matched against root-relative paths. Every table whose
|
|
342
345
|
glob matches a file receives that file's rows — a file can populate multiple
|
|
343
346
|
tables. A `{name}` segment is rewritten to `*` (it matches one path segment
|
|
@@ -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.25"
|
|
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
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
**Changed**
|
|
2
|
+
|
|
3
|
+
- **A table's name is now declared, not derived from `ddl`.** `Table` takes a required keyword-only `name` (`Table(name=..., ddl=..., glob=..., on_file=...)`), and a `[[table]]` entry in a `.dirsql.toml` requires a `name` key. The core no longer parses the DDL text to find the name; a `name` its `ddl` does not create fails at load with an error naming the entry. `Table.name` is now the declared `str` rather than an `Optional[str]` parsed from the DDL. (#962)
|
|
@@ -54,6 +54,7 @@ export default defineConfig({
|
|
|
54
54
|
{ text: 'Derive columns from file paths', link: '/howto/columns-from-paths' },
|
|
55
55
|
{ text: 'Extract rows from file contents', link: '/howto/extract-from-contents' },
|
|
56
56
|
{ text: 'Parse your files into columns', link: '/howto/parse-files-into-columns' },
|
|
57
|
+
{ text: 'Query JSON file contents', link: '/howto/query-json' },
|
|
57
58
|
{ text: 'Search documents by meaning', link: '/howto/search-by-meaning' },
|
|
58
59
|
{ text: "Skip files you don't want indexed", link: '/howto/skip-files' },
|
|
59
60
|
{ text: 'Load a SQLite extension', link: '/howto/load-extension' },
|
|
@@ -60,6 +60,7 @@ async def main() -> None:
|
|
|
60
60
|
"./comments-root",
|
|
61
61
|
tables=[
|
|
62
62
|
Table(
|
|
63
|
+
name="comments",
|
|
63
64
|
ddl="CREATE TABLE comments (thread TEXT, author TEXT, body TEXT)",
|
|
64
65
|
glob="comments/*/*.json",
|
|
65
66
|
on_file=on_file,
|
|
@@ -83,6 +84,7 @@ const db = new DirSQL({
|
|
|
83
84
|
root: "./comments-root",
|
|
84
85
|
tables: [
|
|
85
86
|
{
|
|
87
|
+
name: "comments",
|
|
86
88
|
ddl: "CREATE TABLE comments (thread TEXT, author TEXT, body TEXT)",
|
|
87
89
|
glob: "comments/*/*.json",
|
|
88
90
|
onFile: (path) => [
|
|
@@ -129,6 +131,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
|
129
131
|
let db = DirSQL::builder()
|
|
130
132
|
.root("./comments-root")
|
|
131
133
|
.table(Table::new(
|
|
134
|
+
"comments",
|
|
132
135
|
"CREATE TABLE comments (thread TEXT, author TEXT, body TEXT)",
|
|
133
136
|
"comments/*/*.json",
|
|
134
137
|
on_file,
|
|
@@ -18,6 +18,7 @@ stdout works. With [`jq`](https://jqlang.org/):
|
|
|
18
18
|
|
|
19
19
|
```toml
|
|
20
20
|
[[table]]
|
|
21
|
+
name = "books"
|
|
21
22
|
ddl = "CREATE TABLE books (title TEXT, author TEXT, year INTEGER)"
|
|
22
23
|
glob = "books/*.json"
|
|
23
24
|
on-file = "jq -c '[{title, author, year}]' {path}"
|
|
@@ -53,6 +54,7 @@ row per line, slurp it:
|
|
|
53
54
|
|
|
54
55
|
```toml
|
|
55
56
|
[[table]]
|
|
57
|
+
name = "events"
|
|
56
58
|
ddl = "CREATE TABLE events (event TEXT, user TEXT)"
|
|
57
59
|
glob = "logs/*.jsonl"
|
|
58
60
|
on-file = "jq -c -s '.' {path}"
|
|
@@ -77,6 +79,9 @@ SQLite value mapping is under
|
|
|
77
79
|
|
|
78
80
|
## Going further
|
|
79
81
|
|
|
82
|
+
- Just want to read a field or two out of some JSON files? SQLite's JSON
|
|
83
|
+
operators work directly on a path-table's `content` column, with no config
|
|
84
|
+
and no command — [Query JSON file contents](./query-json.md).
|
|
80
85
|
- The command re-runs on every startup and on every change to a matched
|
|
81
86
|
file. If it is expensive, [keep the index across restarts](./persist.md).
|
|
82
87
|
- Embedding `dirsql` in a program instead? The SDK's `on_file` callback
|