ITADN

Phase 3 follow-ups for auto-decompression (#1417): sftp, dc: derived caches, local-file streaming, dual-path unification

#3988Openjqnatividad 创建于 2026-06-13
J
jqnatividadcommented
Follow-up to #1417 (Phases 1 & 2 shipped in #3986 and #3987 — local & remote auto-decompression of zip/gz/zlib/zst/snappy for the `Config` reader, `luau`/`validate`/`describegpt` lookup tables, and `get`/`dc:` ingest). These items were explicitly scoped out of #1417 and are tracked here for a future pass. None are regressions. ### Remote / `get` sources - [ ] **`sftp://` sources** (behind a `get_sftp` sub-feature). - [ ] **HTTP/3** for downloads. - [ ] **Derived stats/frequency caches for `dc:` inputs** — persist computed stats/frequency alongside cached resources. - [x] **Streaming decompression for *local* compressed files** — `diskcache::ingest_local` still `fs::read`s the whole file then decompresses in memory (`decompress_source`). The remote path already streams (gz/zlib/zst via `IngestSink::Decode`); local large compressed ingests could OOM similarly. ✅ Done in #3990 — `ingest_local` now streams `.gz`/`.zlib`/`.zst` into `BlobSink` via the same `IngestSink` abstraction the remote paths use (bounded memory); zip/sz still full-buffer per `IngestSink`'s per-format policy. ### Decompression semantics (shared) - [x] **Unify the two zip/compressed-input paths.** `util::process_input` (command-level: extracts ALL entries) and `Config` special-format (reader-level: first tabular entry) disagree on multi-entry zip semantics. Decide a single multi-entry policy and converge. ✅ Done in #3995 (option D) — both paths now share one zip module with a single selection rule; entries are returned **tabular-first**, so a single-input command and a `Config`-only command pick the *same* first entry from a mixed multi-entry zip (they could previously read different entries). Multi-input commands (`cat`/`sqlp`/`to`/`validate`/`scoresql`) still receive every entry, nested special formats are preserved, and a zip with no supported entry now errors clearly. `QSV_SKIP_FORMAT_CHECK` is honored for zip members. - [x] **avro/jsonl conversion-error swallow.** A polars-native special-format conversion failure currently falls back to reading raw bytes (preserved historical behavior). `slice_from_avro`/`slice_from_jsonl_*` "pass" only because the asserted substring is embedded in the binary. Decide whether to surface these errors (and fix/replace the fragile fixtures) or keep the per-format swallow. ✅ Done in #3989 — conversion failures are now surfaced as hard errors for all special formats (escape hatch: `QSV_SKIP_FORMAT_CHECK`); regenerated the unreadable Avro fixture and reworked the two `slice` Decimal-pschema tests (which only passed via the swallow) onto the compressed-CSV path that genuinely applies a Decimal pschema. - [x] **Nested special formats** (e.g. a `.parquet` inside a `.zip`) are unsupported by design — document or support. ✅ **Decision: won't support — documented.** Parquet/Avro/Arrow are already compressed, so nesting them in a `.zip` is not a real-world workflow; provide such files directly (qsv reads them natively). Documented in the README "Extended Input Support" section and in `select_zip_entry`'s doc comment. ### Lookup-table caching - [x] A remote `.zip` whose inner tabular file is non-CSV-delimited can't have its delimiter inferred from the URL (the cache file defaults to `.csv`). `gz/zlib/zst/sz` already carry the inner extension via the URL stem. ✅ Done in #3991 — the downloader now names the cache file from the inner entry's extension discovered during extraction (resetting back to `.csv` on a later csv-inner refresh), and the cache-hit path probes the tabular extensions to find it. Generalized to `ckan://` too (its resolved data URL's extension isn't knowable up front); `dathere://` and explicit-extension URLs stay deterministic. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
2 条评论