engines: [postgres, mysql, mssql, mongo]
scenarios:
- id: keyset_auto_non_int_pk
what: "chunked + no chunk_column → auto-keyset on a single-column non-int unique/PK key"
postgres: { na: "PG refuses auto-keyset for non-int PK by design (ADR-0020); mode:full or explicit chunk_by_key" }
mysql: { test: keyset_varchar_pk_roundtrips_full_keyset_across_pages }
mssql: { na: "auto-keyset is MySQL-only (OPT-4/ADR-0020); MSSQL non-int PK needs explicit chunk_by_key or mode:full, like PG" }
mongo: { test: mongo_batch_keyset_no_loss_or_dup }
- id: keyset_explicit_chunk_by_key
what: "explicit chunk_by_key: pages by an index-backed unique key (any orderable type)"
postgres: { test: keyset_pg_uuid_pk_via_explicit_chunk_by_key_roundtrips_full_set }
mysql: { na: "auto-keyset path already covers MySQL non-int PK; explicit == same plan" }
mssql: { test: mssql_keyset_on_non_pk_unique_index }
mongo: { na: "Mongo always pages by _id; there is no user chunk_by_key knob" }
- id: keyset_resume_two_run
what: "keyset + chunk_checkpoint: persist max key, a re-run captures ONLY new keys (run→unchanged=0→insert→resume)"
postgres: { test: keyset_checkpoint_resume_pg_second_run_captures_only_new_keys }
mysql: { test: keyset_checkpoint_resume_second_run_captures_only_new_keys }
mssql: { test: keyset_checkpoint_resume_mssql_second_run_captures_only_new_keys }
mongo: { test: mongo_batch_resume_reads_only_new_since_last_run }
- id: keyset_init_generates_for_pk
what: "rivet init on a single-column-PK table scaffolds chunk_by_key (keyset), not range chunk_column"
postgres: { test: generate_config_chunked_single_pk_uses_keyset }
mysql: { test: generate_config_chunked_single_pk_uses_keyset }
mssql: { test: generate_config_chunked_single_pk_uses_keyset }
mongo: { na: "Mongo init scaffolds a collection scan, not a SQL keyset key" }
- id: range_auto_single_int_pk
what: "chunked + table: shortcut, no chunk_column → auto range-chunk on the single-integer PK"
postgres: { test: plan_and_apply_chunked_export_round_trip_uses_precomputed_ranges }
mysql: { test: mysql_chunked_auto_resolves_chunk_column_from_pk }
mssql: { test: mssql_chunked_auto_resolves_chunk_column_from_pk }
mongo: { test: mongo_batch_parallel_integer_id_no_loss_or_dup }
- id: range_chunk_size_memory_mb
what: "chunk_size_memory_mb derives the row-count chunk_size from a byte budget"
postgres: { test: stand_chunk_size_memory_mb_postgres }
mysql: { test: mysql_chunk_size_memory_mb_derives_chunk_size }
mssql: { test: mssql_chunk_size_memory_mb_derives_chunk_size }
mongo: { na: "no byte-budget chunking on Mongo" }
- id: range_sparse_gappy_key
what: "range chunk over a sparse/gappy integer key: empty middle windows do not lose or false-fail"
postgres: { test: gremlin_chunked_empty_middle_chunk_does_not_false_fire_row_count_min }
mysql: { test: stand_range_gappy_mysql }
mssql: { test: stand_range_gappy_mssql }
mongo: { na: "Mongo pages _id; no BETWEEN-over-span shape" }
- id: range_crash_resume_checkpoint
what: "range chunk + chunk_checkpoint: a crash mid-run resumes and re-runs the interrupted chunk at-least-once"
postgres: { test: chunked_crash_after_chunk_file_before_commit_resume_reruns_chunk_atleastonce }
mysql: { test: mysql_chunked_crash_after_chunk_file_before_commit_resume_reruns_chunk_atleastonce }
mssql: { test: mssql_chunked_crash_after_chunk_file_before_commit_resume_reruns_chunk_atleastonce }
mongo: { test: mongo_crash_after_file_write_recovers_without_loss }
- id: dense_chunk_dense
what: "chunk_dense: ROW_NUMBER windows on a non-unique chunk column (null-safe, tie-safe)"
postgres: { test: dense_ties_pg_sequential_no_loss_no_dup }
mysql: { test: dense_ties_mysql_sequential_no_loss_no_dup }
mssql: { test: dense_ties_mssql_sequential_no_loss_no_dup }
mongo: { na: "no ROW_NUMBER / dense concept in the Mongo reader" }
- id: chunk_count_n
what: "chunk_count: N divides the key range into exactly N windows"
postgres: { test: roast_small_table_escape_respects_explicit_chunk_count }
mysql: { test: stand_chunk_count_mysql }
mssql: { test: stand_chunk_count_mssql }
mongo: { na: "Mongo has no chunk_count knob; the analogue is parallel: N _id-range fan-out, covered by mongo_batch_parallel_integer_id_no_loss_or_dup" }
- id: chunk_by_days
what: "chunk_by_days: date-window chunking on a date/timestamp key"
postgres: { test: stand_chunk_by_days_postgres }
mysql: { test: stand_chunk_by_days_mysql }
mssql: { test: stand_chunk_by_days_mssql } mongo: { na: "no date-window chunking on Mongo" }
- id: snapshot_full
what: "mode: full — one bounded cursor, one file, re-read each run"
postgres: { test: full_mode_repeated_run_accumulates_manifest_entries }
mysql: { test: mysql_full_mode_repeated_run_accumulates_manifest_entries }
mssql: { test: mssql_full_mode_repeated_run_accumulates_manifest_entries }
mongo: { test: mongo_batch_two_rapid_runs_into_same_prefix_do_not_clobber }
- id: incremental_cursor
what: "mode: incremental — WHERE cursor > last_value, re-run picks up only new rows"
postgres: { test: incremental_third_run_picks_up_newly_inserted_rows }
mysql: { test: mysql_incremental_third_run_picks_up_newly_inserted_rows }
mssql: { test: mssql_incremental_third_run_picks_up_newly_inserted_rows }
mongo: { na: "Mongo has no SQL cursor-column incremental; keyset resume fills this role" }
- id: guard_sparse_bail_warn
what: "range on a PROVEN sparse key → bail (PG/MSSQL estimate) / warn (MySQL, unprovable) — the footgun guard"
postgres: { test: stand_sparse_guard_postgres }
mysql: { test: stand_sparse_guard_mysql }
mssql: { test: stand_sparse_guard_mssql }
mongo: { na: "Mongo pages _id; the BSON hetero/NaN guard is a separate family" }
- id: guard_null_keyed_range_bail
what: "range/date chunk over a nullable key with actual NULLs → bail (BETWEEN would silently drop NULL rows)"
postgres: { test: stand_null_keyed_bail_postgres }
mysql: { test: stand_null_keyed_bail_mysql }
mssql: { test: stand_null_keyed_bail_mssql }
mongo: { na: "no BETWEEN key predicate on Mongo" }
- id: guard_keyset_non_usable_key_bail
what: "chunk_by_key on a non-unique / nullable / heterogeneous key → loud refusal, not a filesort/silent-loss"
postgres: { test: stand_keyset_non_usable_bail_postgres }
mysql: { test: stand_keyset_non_usable_bail_mysql }
mssql: { na: "only the ACCEPT side is tested (mssql_keyset_on_non_pk_unique_index); refusal is engine-agnostic plan logic" }
mongo: { test: mongo_keyset_on_heterogeneous_id_errors_loudly_full_scan_still_works }
- id: guard_small_table_snapshot_escape
what: "chunked on a table whose reltuples < chunk_size downgrades to Snapshot (one file), unless an explicit knob pins chunked"
postgres: { test: roast_small_table_escape_respects_explicit_chunk_checkpoint }
mysql: { na: "escape is PG-only (build.rs step 3, reltuples-based); verified live — a 100-row MySQL table stays mode=chunked" }
mssql: { na: "escape is PG-only; verified live — a 100-row MSSQL table stays mode=chunked" }
mongo: { na: "no reltuples-based escape in the Mongo reader" }