feat(types)!: drop the blob column type (ADR-0005 Amendment 2)
blob was a dead-end: declarable but never fillable (no literal in either mode, seed-unsupported), so a blob column could only ever hold NULL. Remove Type::Blob + Value/CellValue::Blob + the base64 CSV path + the grammar slot + completion/render/type-change/seed handling + the binder refusal (whose message also carried a user-facing "DSL" copy-rule bug). The vocabulary is now nine types; base64 stays (clipboard OSC-52). Backward compat is the ADR-0015 migration framework's first real use: a v1->v2 format bump (CURRENT_SCHEMA_VERSION across serializer/parser/skeleton) with a migrator that rewrites `type: blob` -> `type: text`, and a forced .db rebuild from the migrated text when a blob column was actually converted (the stale .db keeps a STRICT BLOB engine column). Conversion to text is non-destructive and CSV-free. Covered by a full-stack integration test and a Tier-4 PTY test that opens a real legacy v1-blob project. Also sweeps the nine-type vocabulary through CLAUDE.md, requirements.md, the website (type reference, seed doc, highlight grammar), and the ADR-0030/0033/ 0035 cross-references; CHANGELOG Removed entry; handoff-79. BREAKING CHANGE: the `blob` column type is removed. Existing projects that declared a blob column are migrated on first open (the column becomes text; the original project.yaml is kept as a .v1.bak).
This commit is contained in:
@@ -32,6 +32,7 @@
|
||||
// (the guard *is* the serialization) or pointless here.
|
||||
#![allow(clippy::significant_drop_tightening)]
|
||||
|
||||
use std::fs;
|
||||
use std::io::{Read, Write};
|
||||
use std::path::Path;
|
||||
use std::sync::{Arc, Mutex, MutexGuard};
|
||||
@@ -404,6 +405,52 @@ fn back_to_back_insert_after_ddl_still_succeeds() {
|
||||
app.quit();
|
||||
}
|
||||
|
||||
/// Flow 6 — ADR-0005 Amendment 2 backward-compat: opening a **legacy v1
|
||||
/// project that declares a `blob` column** migrates it to `text` and opens
|
||||
/// cleanly. This drives the real runtime's migrate-on-open + rebuild path
|
||||
/// end-to-end — the post-removal binary would otherwise reject the v1/blob
|
||||
/// project file. (The integration test covers the migrator + rebuild via
|
||||
/// direct calls; this covers the runtime glue that decides to run them.)
|
||||
#[test]
|
||||
fn opens_a_legacy_v1_blob_project_by_migrating_to_text() {
|
||||
let dir = TempDir::new().expect("data dir");
|
||||
let root = dir.path();
|
||||
|
||||
// Seed a v1 project (the old format) with a `blob` column, under the
|
||||
// data root's projects/ dir, and point `--resume` at it. No
|
||||
// playground.db is shipped, so the open rebuilds from the migrated text.
|
||||
let proj = root.join("projects").join("Legacy");
|
||||
fs::create_dir_all(proj.join("data")).expect("create project dirs");
|
||||
fs::write(
|
||||
proj.join("project.yaml"),
|
||||
concat!(
|
||||
"version: 1\n",
|
||||
"project:\n created_at: 2026-01-01T00:00:00Z\n mode: simple\n",
|
||||
"tables:\n",
|
||||
" - name: Files\n",
|
||||
" primary_key: [id]\n",
|
||||
" columns:\n",
|
||||
" - { name: id, type: serial }\n",
|
||||
" - { name: payload, type: blob }\n",
|
||||
"relationships: []\n",
|
||||
"indexes: []\n",
|
||||
),
|
||||
)
|
||||
.expect("write project.yaml");
|
||||
fs::write(proj.join("data").join("Files.csv"), "id,payload\n1,aGVsbG8=\n").expect("write csv");
|
||||
fs::write(root.join("last_project"), format!("{}\n", proj.display())).expect("write resume");
|
||||
|
||||
// Open via --resume: the runtime migrates blob→text and rebuilds, so
|
||||
// the project opens and the table shows in the sidebar.
|
||||
let mut app = PtyApp::launch_in(root, &["--resume"]);
|
||||
app.wait_for_table("Files");
|
||||
// The former blob column is now a normal text column — `show data`
|
||||
// renders it (header + the base64 value preserved as text).
|
||||
app.submit("show data Files");
|
||||
app.wait_for("payload");
|
||||
app.quit();
|
||||
}
|
||||
|
||||
// ===================== NFR perf (measured, generous) ===================
|
||||
//
|
||||
// These run against the DEBUG binary, so the bounds are loose
|
||||
|
||||
Reference in New Issue
Block a user