dirsql 0.4.134__tar.gz → 0.4.135__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.134 → dirsql-0.4.135}/Cargo.lock +2 -2
- {dirsql-0.4.134 → dirsql-0.4.135}/PKG-INFO +1 -1
- {dirsql-0.4.134/packages/rust → dirsql-0.4.135}/docs/reference/cli.md +5 -0
- {dirsql-0.4.134/packages/rust → dirsql-0.4.135}/docs/reference/config.md +2 -2
- {dirsql-0.4.134/packages/rust → dirsql-0.4.135}/docs/reference/sdk.md +3 -1
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/Cargo.toml +1 -1
- {dirsql-0.4.134 → dirsql-0.4.135/packages/python}/docs/reference/cli.md +5 -0
- {dirsql-0.4.134 → dirsql-0.4.135/packages/python}/docs/reference/config.md +2 -2
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/docs/reference/sdk.md +3 -1
- dirsql-0.4.135/packages/python/e2e-attestations/bot-1580-abs-dotdot-1104.json +7 -0
- dirsql-0.4.135/packages/python/e2e-attestations/bot-1587-hook-key-case-1104.json +7 -0
- dirsql-0.4.135/packages/python/e2e-attestations/bot-1593-non-utf8-text-1104.json +7 -0
- dirsql-0.4.135/packages/python/e2e-attestations/bot-1594-duplicate-columns-1104.json +7 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/Cargo.toml +1 -1
- {dirsql-0.4.134/packages/python → dirsql-0.4.135/packages/rust}/docs/reference/cli.md +5 -0
- {dirsql-0.4.134/packages/python → dirsql-0.4.135/packages/rust}/docs/reference/config.md +2 -2
- {dirsql-0.4.134 → dirsql-0.4.135/packages/rust}/docs/reference/sdk.md +3 -1
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/db.rs +220 -27
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/path_table.rs +63 -12
- {dirsql-0.4.134 → dirsql-0.4.135}/Cargo.toml +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/README.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/dirsql/__init__.py +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/dirsql/_async.py +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/dirsql/_dirsql.pyi +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/dirsql/cli/__init__.py +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/dirsql/cli/discover_plugins/__init__.py +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/dirsql/cli/discover_plugins/discovered_fragments.py +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/dirsql/cli/discover_plugins/discovery_disabled.py +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/dirsql/cli/discover_plugins/fragment_path.py +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/dirsql/cli/discover_plugins/with_discovered_plugins.py +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/dirsql/cli/main.py +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/dirsql/cli/resolve_config_extensions.py +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/dirsql/plan_entry_path.py +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/dirsql/py.typed +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/dirsql/read_config.py +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/dirsql/resolve_configs_extension_specs.py +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/dirsql/resolve_extension.py +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/dirsql/resolve_package.py +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/docs/.claude/CLAUDE.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/docs/.vitepress/config.ts +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/docs/.vitepress/theme/index.ts +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/docs/.vitepress/theme/lang.ts +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/docs/AGENTS.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/docs/context/.gitattributes +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/docs/context/recipes.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/docs/context/troubleshooting.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/docs/context/usage.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/docs/explanation.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/docs/getting-started.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/docs/howto/agent-skill.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/docs/howto/columns-from-paths.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/docs/howto/define-tables.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/docs/howto/embed.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/docs/howto/extract-from-contents.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/docs/howto/load-extension.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/docs/howto/parse-files-into-columns.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/docs/howto/persist.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/docs/howto/query-json.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/docs/howto/query-without-config.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/docs/howto/react-to-changes.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/docs/howto/search-by-meaning.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/docs/howto/search-indexes.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/docs/howto/skip-files.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/docs/howto/write-a-plugin.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/docs/index.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/docs/package.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/docs/plugins.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/docs/pnpm-lock.yaml +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/docs/pnpm-workspace.yaml +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/docs/reference/columns.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/docs/reference/glob.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/docs/reference/hooks.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/docs/reference/http-api.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/docs/reference/path-tables.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/docs/speed.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/docs/speed.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/CHANGELOG.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/MIGRATIONS.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/README.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-07-13-drop-cwd-config-auto-detect.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-07-13-plugin-discovery.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-07-13-rename-extract-to-on-file.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-07-13-repeatable-config.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-07-13-sdk-default-baked-in-config.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-07-20-drop-implicit-files-table.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-07-21-remove-glob-captures.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-07-24-hookless-table-config-error.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-07-24-remove-stat-fact-injection.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-07-29-restore-python-310.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-08-02-release-profile.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-08-02-scan-failures.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-08-03-discovery-ext-resolution.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-08-03-manylinux-dynamic-binary.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-08-03-python-no-ignore.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-08-04-cast-lints.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-08-04-cli-in-process.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-08-20-curtaincall-dev-dependency.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-08-20-declared-table-name.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-09-04-config-paths-from-argv-module.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-09-05-config-extension-loader-split.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-09-05-resolve-config-extensions-split.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-09-05-resolve-extension-split.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-09-09-launcher-config-path-scan.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-09-17-extension-resolution-via-core.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-09-18-export-scan-failure.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-09-18-flatten-row-event-in-core.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-09-18-programmatic-extension-plan.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-09-20-sigint-ends-a-run-in-progress.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-09-24-query-rows-in-projection-order.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-10-02-readme-docs-host.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-10-03-one-glob-rule-for-config-globs.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-10-03-path-table-directory-one-level.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-10-04-path-table-dotfiles-hidden.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-10-05-brace-groups-follow-bash.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-10-05-cli-context.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-10-05-gitignore-requires-repo.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-10-05-path-table-node-modules-named.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-10-05-path-table-symlinks.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-10-05-path-table-trailing-slash.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-10-05-unbalanced-brackets-literal.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-10-06-config-braces.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-10-06-config-directory.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-10-06-config-dotnames.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-10-06-config-gitignore.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-10-06-config-globs-anchor-at-the-config.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-10-06-config-links.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-10-06-one-glob-compiler.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-10-06-plugin-no-default-records.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-10-06-watch-broadcast.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-10-06-zero-match-config-table-warning.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-10-07-bracket-slash-literal.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-10-07-dotdot-and-double-slashes.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-10-07-dotdot-as-written.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-10-07-glob-walks-node-modules.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-10-07-literal-gitignore.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-10-07-on-file-ndjson.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-10-07-parallel-hooks.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-10-07-persist-cache-outside-root.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-10-07-posix-classes-unicode.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-10-07-spread-few-large-files.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-10-08-small-walks-stay-on-one-thread.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-10-08-watch-requires-named-table.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-11-02-watch-dirs-created-mid-registration.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-11-02-watch-live-on-return.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-11-04-exact-json-floats.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/2026-11-04-query-bind-params.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/changelog.d/README.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/conftest.py +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/docs/.claude/CLAUDE.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/docs/.vitepress/config.ts +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/docs/.vitepress/theme/index.ts +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/docs/.vitepress/theme/lang.ts +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/docs/AGENTS.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/docs/context/.gitattributes +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/docs/context/recipes.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/docs/context/troubleshooting.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/docs/context/usage.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/docs/explanation.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/docs/getting-started.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/docs/howto/agent-skill.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/docs/howto/columns-from-paths.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/docs/howto/define-tables.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/docs/howto/embed.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/docs/howto/extract-from-contents.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/docs/howto/load-extension.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/docs/howto/parse-files-into-columns.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/docs/howto/persist.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/docs/howto/query-json.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/docs/howto/query-without-config.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/docs/howto/react-to-changes.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/docs/howto/search-by-meaning.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/docs/howto/search-indexes.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/docs/howto/skip-files.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/docs/howto/write-a-plugin.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/docs/index.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/docs/package.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/docs/plugins.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/docs/pnpm-lock.yaml +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/docs/pnpm-workspace.yaml +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/docs/reference/columns.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/docs/reference/glob.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/docs/reference/hooks.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/docs/reference/http-api.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/docs/reference/path-tables.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/docs/speed.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/docs/speed.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1334-listing-exemptions.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1397-watch-broadcast.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1398-inotify-error.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1399-server-cors.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1401-watch-scope.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1406-watch-no-tables-1008.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1407-child-place-depth.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1414-stat-speed.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1415-server-speed.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1416-watch-speed-1008.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1418-node-modules.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1419-dotdot-slashes.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1420-bracket-slash.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1421-posix-unicode.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1422-literal-gitignore.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1426-walk-spawn-threshold-1008.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1428-ndjson-hooks.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1429-parallel-hooks.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1430-dotdot-as-written.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1431-persist-cache-dir.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1437-test-cache-isolation.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1440-fix-main-build.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1448-wildcard-ignored-prefix.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1451-named-dir-never-hidden.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1454-split-few-files.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1457-incremental-refresh-1008.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1459-rescan-on-overflow-1008.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1461-chunked-read-1016.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1461-row-footprint-1008.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1461-step3-1020.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1461-wide-read-1015.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1462-paired-speed-harness-1008.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1464-fastest-native-1008.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1469-ci-speed-sanity-1009.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1470-perf-suite-1009.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1470-speed-page-1011.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1471-one-level-restore-1102.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1474-vtab-speed-1014.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1475-prefix-speed-1016.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1475-rowpath-1016.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1477-onelevel-speed-1015.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1477-onelevel-speed-1016.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1478-perdir-walk-1020.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1480-matcher-speed-1015.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1481-gitrepo-speed-1015.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1482-docs-fastest-bar-1102.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1483-fm-speed-1015.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1484-jsonl-speed-1015.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1487-frontend-query-1011.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1488-frontend-metadata-1011.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1489-frontend-browse-1013.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1503-bench-watch-1011.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1504-bench-names-1011.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1514-watch-rerun-inline-1015.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1524-path-eq-1016.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1526-main-red-1016.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1532-gitignore-fastest-bar-1016.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1534-fm-native-1016.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1534-fm-native-1102.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1538-onfile-order-1019.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1540-update-in-place-1019.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1541-defer-fk-1019.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1544-perfile-update-1020.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1552-watch-gap-1102.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1557-watch-rename-1102.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1560-scan-insert-1102.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1562-hook-savepoint-1102.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1562-watch-speed-1102.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1575-bind-params-1104.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-1586-float-roundtrip-1104.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-fix-main-place-depth-20261007.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-issue-1486-frontend-20261009.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-speed-gap-childpath-1011.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-speed-parse-overlap-1011.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-speed-parse-paths-1009.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-speed-parse-pragmas-1011.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-speed-sql-valueref-1013.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-speed-walk-components-1011.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-speed-walk-rowpath-1011.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-speed-walk-rows-1013.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/bot-speed-walk-sched-1009.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/cc-keen-knuth-f11gyq.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1056-py-ofpf9.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1066-p1-resolve-extension.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1078-argv-config-paths-core.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1079-p2-resolve-config-extensions.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1080-share-vtab-scaffolding.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1081-indicatif-progress.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1096-watch-moved-dir.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1109-watch-moved-out.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1119-ext-plan.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1120-py-ext.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1122-ext-cleanup.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1130-codec-crates.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1131-flatten-row-event.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1139-sse-flatten.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1140-scan-failure-export.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1148-clippy-all-targets.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1164-sigint-fatal.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1170-projection-order.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1172-on-file-path.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1173-py-projection-order.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1184-win-rel-paths.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1185-win-abs-table-names.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1186-win-test-harness.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1196-join-index.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1199-glob-prefix.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1201-single-walk.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1204-embed-batch.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1207-win-argv-quote.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1208-win-nonverbatim-paths.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1215-on-file-batch.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1216-on-file-cleanup.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1223-config-glob-rule.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1223-dir-one-level.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1225-plugin-no-default.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1226-stale-docs.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1232-anchor-plumbing.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1232-config-anchor.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1232-multi-watch.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1232-zero-match.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1238-parallel-walk.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1241-content-prefetch.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1243-ingest-perf.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1249-dotfiles.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1256-symlinks.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1257-trailing-slash.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1258-config-braces.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1258-config-directory.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1258-config-dotnames.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1258-config-gitignore.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1258-config-links.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1258-one-pattern.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1262-brace-literal.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1264-context.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1267-posix-classes.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1268-unbalanced-brackets.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1269-utf8-chars.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1271-node-modules-named.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1272-ancestor-gitignore.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1273-walk-prune.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1285-ingest-fast.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1286-nested-repo.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1305-glob-speed.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1308-glob-speed.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1310-glob-speed.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1311-glob-speed.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1312-glob-speed.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1318-lazy-stat.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1320-walk-speed.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1322-walk-readdir.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1325-parallel-walk.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1326-stream-rows.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1330-python-dirsql-patch.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1330-python-extensions-patch.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1330-scanner-effects.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1330-scanner-gitignore.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1330-vtab-prefetch-flag.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1330-vtab-read.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-1351-dot-dirs.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-819-oneshot-timeout.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-827-unquote-doubled-quotes.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-epic-953-slice2-reedline.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-epic-953-slice3-format.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-epic-953-stacked-prs-x59wm3.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-github-issue-825-e4mhhp.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-issue-951-0eease.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-issue-962-0jjrfv.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-issue-986-red-test-e7sjrb.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-tackle-1034-cachesplit.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-tackle-1042-py12.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-tackle-956-xzen74.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-tackle-957-lrm0z6-worker-calls.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-tackle-957-lrm0z6.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/e2e-attestations/claude-tackle-975-n8mc2h.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-07-13-drop-cwd-config-auto-detect.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-07-13-rename-extract-to-on-file.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-07-13-sdk-default-baked-in-config.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-07-20-drop-implicit-files-table.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-07-21-remove-glob-captures.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-07-24-hookless-table-config-error.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-07-24-remove-stat-fact-injection.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-07-29-restore-python-310.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-08-04-cli-in-process.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-08-20-declared-table-name.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-09-20-sigint-ends-a-run-in-progress.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-09-24-query-rows-in-projection-order.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-10-02-readme-docs-host.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-10-03-one-glob-rule-for-config-globs.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-10-03-path-table-directory-one-level.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-10-04-path-table-dotfiles-hidden.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-10-05-brace-groups-follow-bash.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-10-05-cli-context.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-10-05-gitignore-requires-repo.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-10-05-path-table-node-modules-named.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-10-05-path-table-symlinks.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-10-05-path-table-trailing-slash.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-10-05-unbalanced-brackets-literal.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-10-06-config-braces.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-10-06-config-directory.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-10-06-config-dotnames.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-10-06-config-gitignore.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-10-06-config-globs-anchor-at-the-config.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-10-06-config-links.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-10-06-one-glob-compiler.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-10-06-plugin-no-default-records.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-10-06-watch-broadcast.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-10-06-zero-match-config-table-warning.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-10-07-bracket-slash-literal.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-10-07-dotdot-and-double-slashes.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-10-07-dotdot-as-written.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-10-07-glob-walks-node-modules.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-10-07-literal-gitignore.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-10-07-on-file-ndjson.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-10-07-parallel-hooks.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-10-07-persist-cache-outside-root.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-10-07-posix-classes-unicode.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-10-07-spread-few-large-files.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-10-08-small-walks-stay-on-one-thread.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-10-08-watch-requires-named-table.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-11-02-watch-dirs-created-mid-registration.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-11-02-watch-live-on-return.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-11-04-exact-json-floats.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/2026-11-04-query-bind-params.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/migrations.d/README.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/src/lib.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/testing-conventions.toml +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/tests/__init__.py +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/tests/conftest.py +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/tests/e2e/__init__.py +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/tests/e2e/bench_report.py +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/tests/e2e/bench_suite.py +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/tests/e2e/fixtures/dirsql_plugin_fixture/__init__.py +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/tests/e2e/fixtures/dirsql_plugin_fixture/dirsql.toml +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/tests/e2e/speed_of_light.py +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/tests/integration/__init__.py +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/tests/integration/binding/__init__.py +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/python/tests/integration/hermetic/__init__.py +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/CHANGELOG.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/MIGRATIONS.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/README.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/benches/db_bench.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/benches/differ_bench.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/benches/matcher_bench.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/benches/scanner_bench.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/docs/context/.gitattributes +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/docs/context/recipes.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/docs/context/troubleshooting.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/docs/context/usage.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/docs/explanation.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/docs/getting-started.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/docs/howto/agent-skill.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/docs/howto/columns-from-paths.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/docs/howto/define-tables.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/docs/howto/embed.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/docs/howto/extract-from-contents.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/docs/howto/load-extension.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/docs/howto/parse-files-into-columns.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/docs/howto/persist.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/docs/howto/query-json.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/docs/howto/query-without-config.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/docs/howto/react-to-changes.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/docs/howto/search-by-meaning.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/docs/howto/search-indexes.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/docs/howto/skip-files.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/docs/howto/write-a-plugin.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/docs/index.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/docs/plugins.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/docs/reference/columns.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/docs/reference/glob.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/docs/reference/hooks.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/docs/reference/http-api.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/docs/reference/path-tables.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/docs/speed.json +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/docs/speed.md +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/bin/dirsql.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/brace.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/cli/context.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/cli/execute.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/cli/frontend.html +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/cli/frontend.js +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/cli/init.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/cli/mod.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/cli/repl.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/cli/router.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/cli/run.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/cli/serialize.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/cli/server.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/cli/table.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/command.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/config.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/default_config.toml +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/differ.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/extension_resolution.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/foreign_key.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/functions.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/gitignore_frame.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/infer.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/launcher.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/lib.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/listing.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/matcher.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/on_file.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/params.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/parsed_vtab.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/per_thread.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/persist.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/posix_class.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/progress.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/row_event_flat.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/row_stream.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/scanner.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/sql_literal.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/tree_walk.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/vtab.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/vtab_scaffold.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/packages/rust/src/watcher.rs +0 -0
- {dirsql-0.4.134 → dirsql-0.4.135}/pyproject.toml +0 -0
|
@@ -573,7 +573,7 @@ dependencies = [
|
|
|
573
573
|
|
|
574
574
|
[[package]]
|
|
575
575
|
name = "dirsql"
|
|
576
|
-
version = "0.4.
|
|
576
|
+
version = "0.4.135"
|
|
577
577
|
dependencies = [
|
|
578
578
|
"assert_cmd",
|
|
579
579
|
"axum",
|
|
@@ -625,7 +625,7 @@ dependencies = [
|
|
|
625
625
|
|
|
626
626
|
[[package]]
|
|
627
627
|
name = "dirsql-py-ext"
|
|
628
|
-
version = "0.4.
|
|
628
|
+
version = "0.4.135"
|
|
629
629
|
dependencies = [
|
|
630
630
|
"dirsql",
|
|
631
631
|
"pyo3",
|
|
@@ -128,6 +128,11 @@ several lines, and **anything longer than 60 characters is truncated with
|
|
|
128
128
|
`…`** so one column cannot set the width of every row. `--format json`
|
|
129
129
|
returns the values unaltered.
|
|
130
130
|
|
|
131
|
+
A text value that is not valid UTF-8 (`CAST(x'ff' AS TEXT)`, `char(55296)`)
|
|
132
|
+
fails the query in every format, with an error naming its column, rather
|
|
133
|
+
than printing replacement characters. Wrap it in `hex()` or `CAST(… AS BLOB)`
|
|
134
|
+
to read its bytes.
|
|
135
|
+
|
|
131
136
|
Laying the table out to the terminal's width, and paging a long result, are
|
|
132
137
|
both out of scope; pipe to `less` for the latter.
|
|
133
138
|
|
|
@@ -224,10 +224,10 @@ what its required `on-file` command emits — dirsql injects nothing (see
|
|
|
224
224
|
| Key | Required | Description |
|
|
225
225
|
|---|---|---|
|
|
226
226
|
| `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. |
|
|
227
|
-
| `ddl` | yes | A SQL batch, run verbatim — any number of statements. It must create a table called `name`; that table holds the file rows, and only the columns it declares are kept (
|
|
227
|
+
| `ddl` | yes | A SQL batch, run verbatim — any number of statements. It must create a table called `name`; that table holds the file rows, and only the columns it declares are kept (a key the `on-file` command emits fills the declared column it names, compared case-insensitively for ASCII letters as SQL identifiers are; a key naming no declared column is dropped). The rest of the batch is yours: indexes, virtual tables, triggers. See [Batch `ddl`](#batch-ddl). |
|
|
228
228
|
| `glob` | yes | Glob pattern, [anchored](#glob-anchor) at the config file's directory, under the [one glob rule](#glob-rule): `*` matches one level, `**` any depth. Every table whose glob matches a file receives that file's rows — a file can populate multiple tables. A `{name}` is a literal, as in bash and a path-table; the [glob page](./glob.md) has the syntax. |
|
|
229
229
|
| `on-file` | **yes** | A command run once per table, with every matched file's absolute path appended as a trailing argument; its stdout (one JSON object per line) is the table'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). |
|
|
230
|
-
| `strict` | no (default `false`) | When `true`, rows whose keys do not
|
|
230
|
+
| `strict` | no (default `false`) | When `true`, rows whose keys do not match the declared columns (compared case-insensitively, as above) 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`. |
|
|
231
231
|
|
|
232
232
|
`on-file` is required because a table's rows come from nowhere else. dirsql
|
|
233
233
|
does not read file contents or merge filesystem facts on your behalf: the
|
|
@@ -223,7 +223,9 @@ db.query_with(sql: &str, params: &Params) -> Result<Vec<Row>>
|
|
|
223
223
|
|
|
224
224
|
:::
|
|
225
225
|
|
|
226
|
-
Executes a SQL query and returns rows keyed by column name.
|
|
226
|
+
Executes a SQL query and returns rows keyed by column name. If a result repeats
|
|
227
|
+
a column name, later occurrences receive `:N` suffixes (for example, `a` and
|
|
228
|
+
`a:1`); suffixes avoid names already present in the result.
|
|
227
229
|
|
|
228
230
|
**Bind parameters.** `params` reaches SQLite's own parameter binding; the
|
|
229
231
|
values never enter the SQL text, so text holding quotes needs no escaping.
|
|
@@ -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.135"
|
|
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
|
|
@@ -128,6 +128,11 @@ several lines, and **anything longer than 60 characters is truncated with
|
|
|
128
128
|
`…`** so one column cannot set the width of every row. `--format json`
|
|
129
129
|
returns the values unaltered.
|
|
130
130
|
|
|
131
|
+
A text value that is not valid UTF-8 (`CAST(x'ff' AS TEXT)`, `char(55296)`)
|
|
132
|
+
fails the query in every format, with an error naming its column, rather
|
|
133
|
+
than printing replacement characters. Wrap it in `hex()` or `CAST(… AS BLOB)`
|
|
134
|
+
to read its bytes.
|
|
135
|
+
|
|
131
136
|
Laying the table out to the terminal's width, and paging a long result, are
|
|
132
137
|
both out of scope; pipe to `less` for the latter.
|
|
133
138
|
|
|
@@ -224,10 +224,10 @@ what its required `on-file` command emits — dirsql injects nothing (see
|
|
|
224
224
|
| Key | Required | Description |
|
|
225
225
|
|---|---|---|
|
|
226
226
|
| `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. |
|
|
227
|
-
| `ddl` | yes | A SQL batch, run verbatim — any number of statements. It must create a table called `name`; that table holds the file rows, and only the columns it declares are kept (
|
|
227
|
+
| `ddl` | yes | A SQL batch, run verbatim — any number of statements. It must create a table called `name`; that table holds the file rows, and only the columns it declares are kept (a key the `on-file` command emits fills the declared column it names, compared case-insensitively for ASCII letters as SQL identifiers are; a key naming no declared column is dropped). The rest of the batch is yours: indexes, virtual tables, triggers. See [Batch `ddl`](#batch-ddl). |
|
|
228
228
|
| `glob` | yes | Glob pattern, [anchored](#glob-anchor) at the config file's directory, under the [one glob rule](#glob-rule): `*` matches one level, `**` any depth. Every table whose glob matches a file receives that file's rows — a file can populate multiple tables. A `{name}` is a literal, as in bash and a path-table; the [glob page](./glob.md) has the syntax. |
|
|
229
229
|
| `on-file` | **yes** | A command run once per table, with every matched file's absolute path appended as a trailing argument; its stdout (one JSON object per line) is the table'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). |
|
|
230
|
-
| `strict` | no (default `false`) | When `true`, rows whose keys do not
|
|
230
|
+
| `strict` | no (default `false`) | When `true`, rows whose keys do not match the declared columns (compared case-insensitively, as above) 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`. |
|
|
231
231
|
|
|
232
232
|
`on-file` is required because a table's rows come from nowhere else. dirsql
|
|
233
233
|
does not read file contents or merge filesystem facts on your behalf: the
|
|
@@ -223,7 +223,9 @@ db.query_with(sql: &str, params: &Params) -> Result<Vec<Row>>
|
|
|
223
223
|
|
|
224
224
|
:::
|
|
225
225
|
|
|
226
|
-
Executes a SQL query and returns rows keyed by column name.
|
|
226
|
+
Executes a SQL query and returns rows keyed by column name. If a result repeats
|
|
227
|
+
a column name, later occurrences receive `:N` suffixes (for example, `a` and
|
|
228
|
+
`a:1`); suffixes avoid names already present in the result.
|
|
227
229
|
|
|
228
230
|
**Bind parameters.** `params` reaches SQLite's own parameter binding; the
|
|
229
231
|
values never enter the SQL text, so text holding quotes needs no escaping.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"command": "uv run python -m pytest tests/e2e/query_contract_test.py tests/e2e/on_file_query_test.py tests/e2e/use_case_join_test.py tests/e2e/glob_speed_symlink_test.py tests/e2e/fanout_test.py -x -q",
|
|
3
|
+
"ran_at": 1793815070,
|
|
4
|
+
"exit_code": 0,
|
|
5
|
+
"commit": "5fe39f0e3b4c76172402aa69ecb8b992265d9994",
|
|
6
|
+
"branch": "bot/1580-abs-dotdot-1104"
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"command": "uv run python -m pytest tests/e2e/on_file_query_test.py tests/e2e/declared_table_name_test.py tests/e2e/query_contract_test.py tests/e2e/jsonl_parse_speed_test.py tests/e2e/frontmatter_parse_speed_test.py -x -q",
|
|
3
|
+
"ran_at": 1793815109,
|
|
4
|
+
"exit_code": 0,
|
|
5
|
+
"commit": "e75ae037dafecb3da6314c6367f2a3618fa0586a",
|
|
6
|
+
"branch": "bot/1587-hook-key-case-1104"
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"command": "uv run python -m pytest tests/e2e/query_contract_test.py tests/e2e/on_file_query_test.py tests/e2e/cli_version_test.py -x -q",
|
|
3
|
+
"ran_at": 1793814772,
|
|
4
|
+
"exit_code": 0,
|
|
5
|
+
"commit": "43d8e7c1ebd157e80090a466348da1b9d5aafcda",
|
|
6
|
+
"branch": "bot/1593-non-utf8-text-1104"
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"command": "uv run python -m pytest tests/e2e/query_contract_test.py tests/e2e/use_case_join_test.py tests/e2e/on_file_query_test.py -q",
|
|
3
|
+
"ran_at": 1793815574,
|
|
4
|
+
"exit_code": 0,
|
|
5
|
+
"commit": "cc34ffac114dcf2d3dda9dca56e0a09353455ab3",
|
|
6
|
+
"branch": "bot/1594-duplicate-columns-1104"
|
|
7
|
+
}
|
|
@@ -6,7 +6,7 @@ description = "Ephemeral SQL index over a local directory"
|
|
|
6
6
|
# version stays for the binding crates (publish = false). The literal
|
|
7
7
|
# intentionally lags the published version: putitoutthere rewrites it to
|
|
8
8
|
# the planned release version at build time and never commits it back.
|
|
9
|
-
version = "0.4.
|
|
9
|
+
version = "0.4.135"
|
|
10
10
|
edition.workspace = true
|
|
11
11
|
# Literal `license` (not `license.workspace = true`) because
|
|
12
12
|
# putitoutthere's preflight check reads `[package].license` directly
|
|
@@ -128,6 +128,11 @@ several lines, and **anything longer than 60 characters is truncated with
|
|
|
128
128
|
`…`** so one column cannot set the width of every row. `--format json`
|
|
129
129
|
returns the values unaltered.
|
|
130
130
|
|
|
131
|
+
A text value that is not valid UTF-8 (`CAST(x'ff' AS TEXT)`, `char(55296)`)
|
|
132
|
+
fails the query in every format, with an error naming its column, rather
|
|
133
|
+
than printing replacement characters. Wrap it in `hex()` or `CAST(… AS BLOB)`
|
|
134
|
+
to read its bytes.
|
|
135
|
+
|
|
131
136
|
Laying the table out to the terminal's width, and paging a long result, are
|
|
132
137
|
both out of scope; pipe to `less` for the latter.
|
|
133
138
|
|
|
@@ -224,10 +224,10 @@ what its required `on-file` command emits — dirsql injects nothing (see
|
|
|
224
224
|
| Key | Required | Description |
|
|
225
225
|
|---|---|---|
|
|
226
226
|
| `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. |
|
|
227
|
-
| `ddl` | yes | A SQL batch, run verbatim — any number of statements. It must create a table called `name`; that table holds the file rows, and only the columns it declares are kept (
|
|
227
|
+
| `ddl` | yes | A SQL batch, run verbatim — any number of statements. It must create a table called `name`; that table holds the file rows, and only the columns it declares are kept (a key the `on-file` command emits fills the declared column it names, compared case-insensitively for ASCII letters as SQL identifiers are; a key naming no declared column is dropped). The rest of the batch is yours: indexes, virtual tables, triggers. See [Batch `ddl`](#batch-ddl). |
|
|
228
228
|
| `glob` | yes | Glob pattern, [anchored](#glob-anchor) at the config file's directory, under the [one glob rule](#glob-rule): `*` matches one level, `**` any depth. Every table whose glob matches a file receives that file's rows — a file can populate multiple tables. A `{name}` is a literal, as in bash and a path-table; the [glob page](./glob.md) has the syntax. |
|
|
229
229
|
| `on-file` | **yes** | A command run once per table, with every matched file's absolute path appended as a trailing argument; its stdout (one JSON object per line) is the table'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). |
|
|
230
|
-
| `strict` | no (default `false`) | When `true`, rows whose keys do not
|
|
230
|
+
| `strict` | no (default `false`) | When `true`, rows whose keys do not match the declared columns (compared case-insensitively, as above) 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`. |
|
|
231
231
|
|
|
232
232
|
`on-file` is required because a table's rows come from nowhere else. dirsql
|
|
233
233
|
does not read file contents or merge filesystem facts on your behalf: the
|
|
@@ -223,7 +223,9 @@ db.query_with(sql: &str, params: &Params) -> Result<Vec<Row>>
|
|
|
223
223
|
|
|
224
224
|
:::
|
|
225
225
|
|
|
226
|
-
Executes a SQL query and returns rows keyed by column name.
|
|
226
|
+
Executes a SQL query and returns rows keyed by column name. If a result repeats
|
|
227
|
+
a column name, later occurrences receive `:N` suffixes (for example, `a` and
|
|
228
|
+
`a:1`); suffixes avoid names already present in the result.
|
|
227
229
|
|
|
228
230
|
**Bind parameters.** `params` reaches SQLite's own parameter binding; the
|
|
229
231
|
values never enter the SQL text, so text holding quotes needs no escaping.
|
|
@@ -49,6 +49,9 @@ pub enum DbError {
|
|
|
49
49
|
|
|
50
50
|
#[error("{0}")]
|
|
51
51
|
Params(String),
|
|
52
|
+
|
|
53
|
+
#[error("column {0:?} holds text that is not valid UTF-8")]
|
|
54
|
+
NotUtf8(String),
|
|
52
55
|
}
|
|
53
56
|
|
|
54
57
|
/// The reserved namespace for dirsql's internal bookkeeping tables. Every
|
|
@@ -363,7 +366,7 @@ pub(crate) fn shape_json_rows(
|
|
|
363
366
|
.0
|
|
364
367
|
.iter()
|
|
365
368
|
.map(|(key, _)| &**key)
|
|
366
|
-
.filter(|key| !columns.iter().any(|c| c
|
|
369
|
+
.filter(|key| !columns.iter().any(|c| c.eq_ignore_ascii_case(key)))
|
|
367
370
|
.collect();
|
|
368
371
|
if !extra.is_empty() {
|
|
369
372
|
return Err(DbError::SchemaMismatch(format!(
|
|
@@ -375,7 +378,7 @@ pub(crate) fn shape_json_rows(
|
|
|
375
378
|
let missing: Vec<&str> = columns
|
|
376
379
|
.iter()
|
|
377
380
|
.map(String::as_str)
|
|
378
|
-
.filter(|c| !row.0.iter().any(|(key, _)|
|
|
381
|
+
.filter(|c| !row.0.iter().any(|(key, _)| key.eq_ignore_ascii_case(c)))
|
|
379
382
|
.collect();
|
|
380
383
|
if !missing.is_empty() {
|
|
381
384
|
return Err(DbError::SchemaMismatch(format!(
|
|
@@ -394,7 +397,7 @@ pub(crate) fn shape_json_rows(
|
|
|
394
397
|
}
|
|
395
398
|
let mut shaped = vec![Value::Null; columns.len()];
|
|
396
399
|
for (key, value) in row.0 {
|
|
397
|
-
if let Some(i) = columns.iter().position(|c|
|
|
400
|
+
if let Some(i) = columns.iter().position(|c| c.eq_ignore_ascii_case(&key)) {
|
|
398
401
|
emitted[i] = true;
|
|
399
402
|
shaped[i] = json_into_value(value);
|
|
400
403
|
}
|
|
@@ -755,7 +758,7 @@ impl Db {
|
|
|
755
758
|
let mut cells = Vec::with_capacity(rows.len());
|
|
756
759
|
for row in rows {
|
|
757
760
|
for (i, column) in columns.iter().enumerate() {
|
|
758
|
-
emitted[i] |= row.
|
|
761
|
+
emitted[i] |= row.keys().any(|key| key.eq_ignore_ascii_case(column));
|
|
759
762
|
}
|
|
760
763
|
let mut row = Self::normalize_against(table, &columns, row, strict)?;
|
|
761
764
|
cells.push(
|
|
@@ -782,11 +785,11 @@ impl Db {
|
|
|
782
785
|
for key in row.keys() {
|
|
783
786
|
validate_identifier(key)?;
|
|
784
787
|
}
|
|
785
|
-
let
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
788
|
+
let extra: Vec<&str> = row
|
|
789
|
+
.keys()
|
|
790
|
+
.map(String::as_str)
|
|
791
|
+
.filter(|key| !columns.iter().any(|c| c.eq_ignore_ascii_case(key)))
|
|
792
|
+
.collect();
|
|
790
793
|
if !extra.is_empty() {
|
|
791
794
|
return Err(DbError::SchemaMismatch(format!(
|
|
792
795
|
"extra columns not in table {}: {}",
|
|
@@ -794,7 +797,11 @@ impl Db {
|
|
|
794
797
|
extra.join(", ")
|
|
795
798
|
)));
|
|
796
799
|
}
|
|
797
|
-
let missing: Vec<&str> =
|
|
800
|
+
let missing: Vec<&str> = columns
|
|
801
|
+
.iter()
|
|
802
|
+
.map(String::as_str)
|
|
803
|
+
.filter(|c| !row.keys().any(|key| key.eq_ignore_ascii_case(c)))
|
|
804
|
+
.collect();
|
|
798
805
|
if !missing.is_empty() {
|
|
799
806
|
return Err(DbError::SchemaMismatch(format!(
|
|
800
807
|
"missing columns for table {}: {}",
|
|
@@ -802,15 +809,19 @@ impl Db {
|
|
|
802
809
|
missing.join(", ")
|
|
803
810
|
)));
|
|
804
811
|
}
|
|
805
|
-
Ok(row)
|
|
806
|
-
} else {
|
|
807
|
-
let mut normalized = HashMap::with_capacity(columns.len());
|
|
808
|
-
for col in columns {
|
|
809
|
-
let value = row.remove(col).unwrap_or(Value::Null);
|
|
810
|
-
normalized.insert(col.clone(), value);
|
|
811
|
-
}
|
|
812
|
-
Ok(normalized)
|
|
813
812
|
}
|
|
813
|
+
let mut normalized = HashMap::with_capacity(columns.len());
|
|
814
|
+
for col in columns {
|
|
815
|
+
let value = row.remove(col).or_else(|| {
|
|
816
|
+
let key = row
|
|
817
|
+
.keys()
|
|
818
|
+
.find(|key| key.eq_ignore_ascii_case(col))?
|
|
819
|
+
.clone();
|
|
820
|
+
row.remove(&key)
|
|
821
|
+
});
|
|
822
|
+
normalized.insert(col.clone(), value.unwrap_or(Value::Null));
|
|
823
|
+
}
|
|
824
|
+
Ok(normalized)
|
|
814
825
|
}
|
|
815
826
|
|
|
816
827
|
/// Insert a row into a table.
|
|
@@ -1565,8 +1576,8 @@ impl Db {
|
|
|
1565
1576
|
let mut spare: Vec<ValueRef<'_>> = Vec::with_capacity(column_names.len());
|
|
1566
1577
|
while let Some(row) = rows.next()? {
|
|
1567
1578
|
let mut cells = recycled(spare);
|
|
1568
|
-
for i in
|
|
1569
|
-
cells.push(row.get_ref(i)?);
|
|
1579
|
+
for (i, column) in column_names.iter().enumerate() {
|
|
1580
|
+
cells.push(utf8_checked(row.get_ref(i)?, column)?);
|
|
1570
1581
|
}
|
|
1571
1582
|
on_row(&mut state, &cells);
|
|
1572
1583
|
spare = recycled(cells);
|
|
@@ -1584,7 +1595,7 @@ impl Db {
|
|
|
1584
1595
|
while let Some(row) = rows.next()? {
|
|
1585
1596
|
let mut map = HashMap::new();
|
|
1586
1597
|
for (i, name) in column_names.iter().enumerate() {
|
|
1587
|
-
let val
|
|
1598
|
+
let val = rusqlite::types::Value::from(utf8_checked(row.get_ref(i)?, name)?);
|
|
1588
1599
|
map.insert(name.clone(), Value::from(val));
|
|
1589
1600
|
}
|
|
1590
1601
|
results.push(map);
|
|
@@ -1631,7 +1642,8 @@ impl Db {
|
|
|
1631
1642
|
return Err(DbError::WriteForbidden);
|
|
1632
1643
|
}
|
|
1633
1644
|
self.scope.warm(&reads);
|
|
1634
|
-
let column_names
|
|
1645
|
+
let column_names =
|
|
1646
|
+
unique_column_names(stmt.column_names().iter().map(|s| s.to_string()).collect());
|
|
1635
1647
|
Ok((stmt, column_names, reads))
|
|
1636
1648
|
}
|
|
1637
1649
|
|
|
@@ -1900,6 +1912,17 @@ fn fill_cell(cell: &mut Value, source: ValueRef<'_>) {
|
|
|
1900
1912
|
}
|
|
1901
1913
|
}
|
|
1902
1914
|
|
|
1915
|
+
/// `cell`, unless it is text that is not valid UTF-8: rusqlite panics
|
|
1916
|
+
/// converting such text to an owned value.
|
|
1917
|
+
fn utf8_checked<'a>(cell: ValueRef<'a>, column: &str) -> Result<ValueRef<'a>> {
|
|
1918
|
+
match cell {
|
|
1919
|
+
ValueRef::Text(bytes) if std::str::from_utf8(bytes).is_err() => {
|
|
1920
|
+
Err(DbError::NotUtf8(column.to_string()))
|
|
1921
|
+
}
|
|
1922
|
+
_ => Ok(cell),
|
|
1923
|
+
}
|
|
1924
|
+
}
|
|
1925
|
+
|
|
1903
1926
|
fn value_ref(value: &Value) -> ValueRef<'_> {
|
|
1904
1927
|
match value {
|
|
1905
1928
|
Value::Null => ValueRef::Null,
|
|
@@ -1991,6 +2014,27 @@ fn bind(stmt: &mut rusqlite::Statement<'_>, params: &Params) -> Result<()> {
|
|
|
1991
2014
|
Ok(())
|
|
1992
2015
|
}
|
|
1993
2016
|
|
|
2017
|
+
fn unique_column_names(names: Vec<String>) -> Vec<String> {
|
|
2018
|
+
let reserved: HashSet<String> = names.iter().cloned().collect();
|
|
2019
|
+
let mut used = HashSet::new();
|
|
2020
|
+
names
|
|
2021
|
+
.into_iter()
|
|
2022
|
+
.map(|name| {
|
|
2023
|
+
if used.insert(name.clone()) {
|
|
2024
|
+
return name;
|
|
2025
|
+
}
|
|
2026
|
+
let mut suffix = 1;
|
|
2027
|
+
loop {
|
|
2028
|
+
let candidate = format!("{name}:{suffix}");
|
|
2029
|
+
if !reserved.contains(&candidate) && used.insert(candidate.clone()) {
|
|
2030
|
+
return candidate;
|
|
2031
|
+
}
|
|
2032
|
+
suffix += 1;
|
|
2033
|
+
}
|
|
2034
|
+
})
|
|
2035
|
+
.collect()
|
|
2036
|
+
}
|
|
2037
|
+
|
|
1994
2038
|
/// `cells` emptied and free to borrow anew, keeping its allocation.
|
|
1995
2039
|
fn recycled<'a>(mut cells: Vec<ValueRef<'_>>) -> Vec<ValueRef<'a>> {
|
|
1996
2040
|
cells.clear();
|
|
@@ -2013,6 +2057,15 @@ impl From<rusqlite::types::Value> for Value {
|
|
|
2013
2057
|
mod tests {
|
|
2014
2058
|
use super::*;
|
|
2015
2059
|
|
|
2060
|
+
#[test]
|
|
2061
|
+
fn duplicate_result_names_avoid_existing_projection_names() {
|
|
2062
|
+
let names = ["a", "a", "a:1", "a"]
|
|
2063
|
+
.into_iter()
|
|
2064
|
+
.map(str::to_string)
|
|
2065
|
+
.collect();
|
|
2066
|
+
assert_eq!(unique_column_names(names), ["a", "a:2", "a:1", "a:3"]);
|
|
2067
|
+
}
|
|
2068
|
+
|
|
2016
2069
|
#[test]
|
|
2017
2070
|
fn text_and_blob_values_bind_without_copying() {
|
|
2018
2071
|
let text = Value::Text("abc".into());
|
|
@@ -2322,12 +2375,31 @@ mod tests {
|
|
|
2322
2375
|
}
|
|
2323
2376
|
|
|
2324
2377
|
#[test]
|
|
2325
|
-
fn
|
|
2378
|
+
fn query_each_fails_on_text_that_is_not_utf8() {
|
|
2326
2379
|
let db = titled_docs(&["a"]);
|
|
2327
2380
|
|
|
2328
|
-
let
|
|
2381
|
+
let error = db
|
|
2382
|
+
.query_each("SELECT CAST(x'ff41' AS TEXT) AS t", |_| (), |_, _| {})
|
|
2383
|
+
.unwrap_err();
|
|
2329
2384
|
|
|
2330
|
-
assert_eq!(
|
|
2385
|
+
assert_eq!(
|
|
2386
|
+
error.to_string(),
|
|
2387
|
+
"column \"t\" holds text that is not valid UTF-8"
|
|
2388
|
+
);
|
|
2389
|
+
}
|
|
2390
|
+
|
|
2391
|
+
#[test]
|
|
2392
|
+
fn query_ordered_fails_on_text_that_is_not_utf8() {
|
|
2393
|
+
let db = titled_docs(&["a"]);
|
|
2394
|
+
|
|
2395
|
+
let error = db
|
|
2396
|
+
.query_ordered("SELECT CAST(x'ff41' AS TEXT) AS t")
|
|
2397
|
+
.unwrap_err();
|
|
2398
|
+
|
|
2399
|
+
assert_eq!(
|
|
2400
|
+
error.to_string(),
|
|
2401
|
+
"column \"t\" holds text that is not valid UTF-8"
|
|
2402
|
+
);
|
|
2331
2403
|
}
|
|
2332
2404
|
|
|
2333
2405
|
fn owned(cell: &ValueRef<'_>) -> Value {
|
|
@@ -2376,7 +2448,7 @@ mod tests {
|
|
|
2376
2448
|
|
|
2377
2449
|
let held = db
|
|
2378
2450
|
.query_each_ref(
|
|
2379
|
-
"SELECT CAST(x'
|
|
2451
|
+
"SELECT CAST(x'c3a941' AS TEXT) AS t",
|
|
2380
2452
|
&Params::default(),
|
|
2381
2453
|
|_| Vec::new(),
|
|
2382
2454
|
|held: &mut Vec<Vec<u8>>, cells| match cells {
|
|
@@ -2386,7 +2458,7 @@ mod tests {
|
|
|
2386
2458
|
)
|
|
2387
2459
|
.unwrap();
|
|
2388
2460
|
|
|
2389
|
-
assert_eq!(held, [b"\
|
|
2461
|
+
assert_eq!(held, [b"\xc3\xa9A".to_vec()]);
|
|
2390
2462
|
}
|
|
2391
2463
|
|
|
2392
2464
|
#[test]
|
|
@@ -2963,6 +3035,64 @@ mod tests {
|
|
|
2963
3035
|
assert_eq!(normalized.len(), 2);
|
|
2964
3036
|
}
|
|
2965
3037
|
|
|
3038
|
+
#[test]
|
|
3039
|
+
fn normalize_row_keys_a_case_differing_key_by_its_column() {
|
|
3040
|
+
let db = Db::new().unwrap();
|
|
3041
|
+
db.create_table("t", "CREATE TABLE t (Name TEXT)").unwrap();
|
|
3042
|
+
let row = HashMap::from([("nAME".into(), Value::Text("apple".into()))]);
|
|
3043
|
+
for strict in [false, true] {
|
|
3044
|
+
let normalized = db.normalize_row("t", &row, strict).unwrap();
|
|
3045
|
+
assert_eq!(
|
|
3046
|
+
normalized,
|
|
3047
|
+
HashMap::from([("Name".into(), Value::Text("apple".into()))])
|
|
3048
|
+
);
|
|
3049
|
+
}
|
|
3050
|
+
}
|
|
3051
|
+
|
|
3052
|
+
#[test]
|
|
3053
|
+
fn normalize_row_prefers_the_exact_key_over_a_case_variant() {
|
|
3054
|
+
let db = Db::new().unwrap();
|
|
3055
|
+
db.create_table("t", "CREATE TABLE t (name TEXT)").unwrap();
|
|
3056
|
+
let row = HashMap::from([
|
|
3057
|
+
("NAME".into(), Value::Text("variant".into())),
|
|
3058
|
+
("name".into(), Value::Text("exact".into())),
|
|
3059
|
+
]);
|
|
3060
|
+
let normalized = db.normalize_row("t", &row, false).unwrap();
|
|
3061
|
+
assert_eq!(normalized["name"], Value::Text("exact".into()));
|
|
3062
|
+
}
|
|
3063
|
+
|
|
3064
|
+
#[test]
|
|
3065
|
+
fn normalize_row_does_not_fold_non_ascii_case() {
|
|
3066
|
+
let db = Db::new().unwrap();
|
|
3067
|
+
db.create_table("t", "CREATE TABLE t (\"é\" TEXT)").unwrap();
|
|
3068
|
+
let row = HashMap::from([("É".into(), Value::Text("x".into()))]);
|
|
3069
|
+
let normalized = db.normalize_row("t", &row, false).unwrap();
|
|
3070
|
+
assert_eq!(normalized["é"], Value::Null);
|
|
3071
|
+
}
|
|
3072
|
+
|
|
3073
|
+
#[test]
|
|
3074
|
+
fn normalize_row_strict_names_exactly_the_unmatched_keys_and_columns() {
|
|
3075
|
+
let db = Db::new().unwrap();
|
|
3076
|
+
db.create_table("t", "CREATE TABLE t (Name TEXT, n INTEGER)")
|
|
3077
|
+
.unwrap();
|
|
3078
|
+
let extra = HashMap::from([
|
|
3079
|
+
("NAME".into(), Value::Null),
|
|
3080
|
+
("N".into(), Value::Null),
|
|
3081
|
+
("color".into(), Value::Null),
|
|
3082
|
+
]);
|
|
3083
|
+
let err = db.normalize_row("t", &extra, true).unwrap_err();
|
|
3084
|
+
assert!(
|
|
3085
|
+
matches!(&err, DbError::SchemaMismatch(m) if m == "extra columns not in table t: color"),
|
|
3086
|
+
"got: {err}"
|
|
3087
|
+
);
|
|
3088
|
+
let missing = HashMap::from([("NAME".into(), Value::Null)]);
|
|
3089
|
+
let err = db.normalize_row("t", &missing, true).unwrap_err();
|
|
3090
|
+
assert!(
|
|
3091
|
+
matches!(&err, DbError::SchemaMismatch(m) if m == "missing columns for table t: n"),
|
|
3092
|
+
"got: {err}"
|
|
3093
|
+
);
|
|
3094
|
+
}
|
|
3095
|
+
|
|
2966
3096
|
#[test]
|
|
2967
3097
|
fn insert_and_query_real_value() {
|
|
2968
3098
|
let db = Db::new().unwrap();
|
|
@@ -3988,6 +4118,53 @@ mod tests {
|
|
|
3988
4118
|
);
|
|
3989
4119
|
}
|
|
3990
4120
|
|
|
4121
|
+
#[test]
|
|
4122
|
+
fn shape_rows_fills_a_column_from_a_key_differing_only_by_case() {
|
|
4123
|
+
let db = Db::new().unwrap();
|
|
4124
|
+
db.create_table("t", "CREATE TABLE t (Id TEXT, n INTEGER)")
|
|
4125
|
+
.unwrap();
|
|
4126
|
+
for strict in [false, true] {
|
|
4127
|
+
let out = db
|
|
4128
|
+
.shape_rows(
|
|
4129
|
+
"t",
|
|
4130
|
+
json_rows(serde_json::json!([{"N":1,"iD":"a"}])),
|
|
4131
|
+
strict,
|
|
4132
|
+
)
|
|
4133
|
+
.unwrap();
|
|
4134
|
+
assert_eq!(out.columns, vec!["Id", "n"]);
|
|
4135
|
+
assert_eq!(out.emitted, vec![true, true]);
|
|
4136
|
+
assert_eq!(
|
|
4137
|
+
out.cells,
|
|
4138
|
+
vec![vec![Value::Text("a".into()), Value::Integer(1)]]
|
|
4139
|
+
);
|
|
4140
|
+
}
|
|
4141
|
+
}
|
|
4142
|
+
|
|
4143
|
+
#[test]
|
|
4144
|
+
fn shape_rows_strict_names_exactly_the_unmatched_keys_and_columns() {
|
|
4145
|
+
let db = Db::new().unwrap();
|
|
4146
|
+
db.create_table("t", "CREATE TABLE t (Name TEXT, n INTEGER)")
|
|
4147
|
+
.unwrap();
|
|
4148
|
+
let err = db
|
|
4149
|
+
.shape_rows(
|
|
4150
|
+
"t",
|
|
4151
|
+
json_rows(serde_json::json!([{"NAME":"x","N":1,"color":"red"}])),
|
|
4152
|
+
true,
|
|
4153
|
+
)
|
|
4154
|
+
.unwrap_err();
|
|
4155
|
+
assert!(
|
|
4156
|
+
matches!(&err, DbError::SchemaMismatch(m) if m == "extra columns not in table t: color"),
|
|
4157
|
+
"got: {err}"
|
|
4158
|
+
);
|
|
4159
|
+
let err = db
|
|
4160
|
+
.shape_rows("t", json_rows(serde_json::json!([{"NAME":"x"}])), true)
|
|
4161
|
+
.unwrap_err();
|
|
4162
|
+
assert!(
|
|
4163
|
+
matches!(&err, DbError::SchemaMismatch(m) if m == "missing columns for table t: n"),
|
|
4164
|
+
"got: {err}"
|
|
4165
|
+
);
|
|
4166
|
+
}
|
|
4167
|
+
|
|
3991
4168
|
#[test]
|
|
3992
4169
|
fn shape_rows_strict_names_the_extra_columns() {
|
|
3993
4170
|
let db = Db::new().unwrap();
|
|
@@ -5504,6 +5681,22 @@ mod tests {
|
|
|
5504
5681
|
);
|
|
5505
5682
|
}
|
|
5506
5683
|
|
|
5684
|
+
#[test]
|
|
5685
|
+
fn shape_value_rows_marks_a_column_emitted_by_a_case_differing_key() {
|
|
5686
|
+
let db = Db::new().unwrap();
|
|
5687
|
+
db.create_table("t", "CREATE TABLE t (id INTEGER, Name TEXT)")
|
|
5688
|
+
.unwrap();
|
|
5689
|
+
let rows = vec![HashMap::from([(
|
|
5690
|
+
"nAME".to_string(),
|
|
5691
|
+
Value::Text("a".into()),
|
|
5692
|
+
)])];
|
|
5693
|
+
|
|
5694
|
+
let out = db.shape_value_rows("t", rows, false).unwrap();
|
|
5695
|
+
|
|
5696
|
+
assert_eq!(out.emitted, vec![false, true]);
|
|
5697
|
+
assert_eq!(out.cells, vec![vec![Value::Null, Value::Text("a".into())]]);
|
|
5698
|
+
}
|
|
5699
|
+
|
|
5507
5700
|
#[test]
|
|
5508
5701
|
fn shape_value_rows_strict_rejects_a_missing_column() {
|
|
5509
5702
|
let db = Db::new().unwrap();
|