Skip to content

CQLite v0.14.0

Read and query Apache Cassandra 5.0 SSTables through Arrow Flight and Trino — no cluster required. This release takes the Flight read path from working to field-validated: the round-9 field build ran against a live, at-scale Cassandra deployment (validation tracker #2367).

  • Streaming do_get scan — the scan path no longer materializes the whole SSTable before the first row. It walks the index lazily, applies LIMIT effectively, and tears producers down on cancel, so memory stays bounded (#2361).
  • Parse-once warm registry — the resolve phase stopped re-parsing per request at multi-million-partition scale. Single-flight parse plus rebind-by-inode removes the CPU spin that hung LIMIT, count(*), and point reads (#2383).
  • Predicate pushdowndo_get pushes WHERE pk = ? toward a partition point-read or prune instead of a full merge scan (#2207).
  • Cancellation that works — the snapshot-index reload loop honors cancellation, so LIMIT queries no longer hang and the in-flight gauge no longer sticks (#2264, #2157).
  • No silent multi-cell collapse — the Flight producer no longer overwrites multi-cell and collection columns through a HashMap (#2324).
  • Read-time reconciliation — a multi-generation SELECT applies read-time TTL, partition, and range-tombstone visibility (#1849).
  • TTL round-trips through compaction — the write path honors USING TTL and per-cell expiration; surviving live TTL cells stay byte-identical after compaction, including complex, collection, and UDT elements (#1743, #2038).
  • Float ordering matches CassandraValue comparison, ORDER BY, and MIN/MAX order floats as Cassandra does: NaN last, -0.0 < +0.0 (#2010, #1870).
  • No-heuristics hardening — blob decode no longer guesses from a byte pattern; recursion-depth guards and clamped capacities protect the parser (#1630, #1414).

The read, parse, and export hot paths from the audit epics landed: boxed Value variants (88B → ≤40B), byte-bounded result budgets in place of the 1M-row cliff, LIMIT/OFFSET pushed into the scan, streaming multi-generation merge and O(1) aggregates, a key→partition-offset cache, and one-walk zero-copy BTI trie descent (#1583, #1582, #1577, #1585).

  • Config schemaMemoryConfig collapsed to one real caching knob, block_cache.max_size. The decorative row_cache, query_cache, and allocator fields and the unused CachePolicy::Lfu/Arc variants were removed; a config that still names them now fails closed on deserialization (#1568).
  • Public API — the dead SSTable reader stacks flagged by the read-path audit were deleted: SchemaAwareReader, ChunkedDataReader, StreamingDecompressor, the duplicate legacy CompressionInfo/ChunkInfo parser, and the streaming half of CompressionReader. All had zero production consumers (#1597).
  • Cold first-query-per-table parse costSSTableReader::open parses Index.db super-linearly (and twice per open), so the first query against a large table pays a cold parse cost at field scale. Fixed in v0.14.1 (#2385, #2395).
  • Reads are single-node-bound under RF=N — under concurrency one pod does the work; throughput caps at one node (#2397).
Terminal window
brew install pmcfadin/cqlite/cqlite # CLI (macOS + Linux)
cargo add cqlite-core # Rust library
pip install cqlite-py # Python
npm install @cqlite/node # Node.js

Rust crates and the Python and Node bindings move 0.13.0 → 0.14.0 in lockstep. The Trino connector (in.mcfad:cqlite-trino) is versioned separately. Full detail in the CHANGELOG.