feat: DSL→SQL teaching echo — Phase 3 cat-3 caveat (ADR-0038)
Lands the only piece of category-3 prose not already covered by the
existing `client_side.*` notes infrastructure: the `change column …
--dont-convert` *caveat* (ADR-0038 §6, the only Bucket A caveat —
every other category-3 line is illuminating).
`--dont-convert` skips the client-side layer entirely, so the headline
SQL echo (`ALTER TABLE … SET DATA TYPE …`) is the nearest SQL but
*not* equivalent: running the line in advanced mode would convert the
stored values, but the playground left them as-is. The new caveat
states that divergence explicitly.
* New i18n key `client_side.dont_convert_caveat` (no placeholders) —
registered in keys::KEYS_AND_PLACEHOLDERS.
* New `dont_convert_caveat: bool` field on DslChangeColumnSucceeded,
set in the runtime when submission_mode is advanced *and* the
command is ChangeColumnType { mode: DontConvert, .. }. Gated on
advanced mode because the caveat references "the line above" — the
echo, which only fires in advanced mode.
* App's handle_dsl_change_column_success emits the caveat line
between the existing client-side notes and the structure render,
so it reads alongside the echo, not after the table view.
The other two category-3 lines from §6 (shortid generation,
type-conversion transforms) were already in place via
`client_side.auto_fill_*` / `client_side.transformed*` — those notes
already render after the echo via handle_dsl_add_column_success /
handle_dsl_change_column_success, in the right position per the ADR.
This commit just adds the missing caveat.
Tests: 2014 passed / 0 failed / 1 ignored (pre-existing); clippy
clean. An App-level test pins the rendering order (caveat sits
after the echo, before the structure) and the simple-mode gate
(no caveat without an echo to refer to).
The §4 de-emphasised styled-runs rendering polish remains —
the echo + caveat lines are still plain `[system]` lines.
This commit is contained in:
+90
-1
@@ -539,9 +539,10 @@ impl App {
|
||||
command,
|
||||
result,
|
||||
echo,
|
||||
dont_convert_caveat,
|
||||
} => {
|
||||
self.pending_echo = echo;
|
||||
self.handle_dsl_change_column_success(&command, result);
|
||||
self.handle_dsl_change_column_success(&command, result, dont_convert_caveat);
|
||||
Vec::new()
|
||||
}
|
||||
AppEvent::DslAddColumnSucceeded {
|
||||
@@ -1529,6 +1530,7 @@ impl App {
|
||||
&mut self,
|
||||
command: &Command,
|
||||
result: ChangeColumnTypeResult,
|
||||
dont_convert_caveat: bool,
|
||||
) {
|
||||
self.note_ok_summary(command);
|
||||
if let Some(note) = result.client_side {
|
||||
@@ -1567,6 +1569,15 @@ impl App {
|
||||
));
|
||||
}
|
||||
}
|
||||
// ADR-0038 §6 category 3 caveat: `--dont-convert` skips the
|
||||
// client-side layer entirely, so the headline echo is the
|
||||
// nearest SQL but *not* equivalent (the only Bucket A caveat —
|
||||
// every other category-3 line is illuminating). Sits between
|
||||
// the client-side notes and the structure render so it reads
|
||||
// alongside the echo, not after the table view.
|
||||
if dont_convert_caveat {
|
||||
self.note_system(crate::t!("client_side.dont_convert_caveat"));
|
||||
}
|
||||
for line in crate::output_render::render_structure(&result.description) {
|
||||
self.note_system(line);
|
||||
}
|
||||
@@ -3050,10 +3061,88 @@ mod tests {
|
||||
client_side: None,
|
||||
},
|
||||
echo: Some(vec!["ALTER TABLE T ALTER COLUMN c SET DATA TYPE text".to_string()]),
|
||||
dont_convert_caveat: false,
|
||||
});
|
||||
assert_echo_beneath_ok(&app, "ALTER TABLE T ALTER COLUMN c SET DATA TYPE text");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn change_column_dont_convert_renders_the_caveat_between_notes_and_structure() {
|
||||
// ADR-0038 §6 category 3 (Phase 3): when `change column …
|
||||
// --dont-convert` ran in an advanced effective mode, the runtime
|
||||
// sets `dont_convert_caveat = true`; the App emits the prose
|
||||
// caveat between the existing client-side notes (none here, since
|
||||
// --dont-convert skips that layer entirely) and the structure
|
||||
// render, so it reads alongside the echo. Simple mode ⇒
|
||||
// `dont_convert_caveat = false` ⇒ no caveat line.
|
||||
use crate::db::ChangeColumnTypeResult;
|
||||
|
||||
use crate::dsl::ChangeColumnMode;
|
||||
|
||||
// Advanced mode + DontConvert → caveat fires.
|
||||
let mut app = App::new();
|
||||
app.update(AppEvent::DslChangeColumnSucceeded {
|
||||
command: Command::ChangeColumnType {
|
||||
table: "T".to_string(),
|
||||
column: "c".to_string(),
|
||||
ty: Type::Int,
|
||||
mode: ChangeColumnMode::DontConvert,
|
||||
},
|
||||
result: ChangeColumnTypeResult {
|
||||
description: sample_description("T"),
|
||||
// --dont-convert skips the client-side layer → None.
|
||||
client_side: None,
|
||||
},
|
||||
echo: Some(vec![
|
||||
"ALTER TABLE T ALTER COLUMN c SET DATA TYPE int".to_string(),
|
||||
]),
|
||||
dont_convert_caveat: true,
|
||||
});
|
||||
let texts: Vec<&str> = app.output.iter().map(|l| l.text.as_str()).collect();
|
||||
let echo_idx = texts
|
||||
.iter()
|
||||
.position(|t| t.contains("Executing SQL:"))
|
||||
.expect("echo line");
|
||||
let caveat_idx = texts
|
||||
.iter()
|
||||
.position(|t| t.contains("`--dont-convert` kept the stored values"))
|
||||
.expect("caveat line");
|
||||
assert!(
|
||||
caveat_idx > echo_idx,
|
||||
"caveat sits after the echo (reads alongside the line above): {texts:?}",
|
||||
);
|
||||
// And before the structure render (the structure shows column names).
|
||||
if let Some(structure_idx) = texts.iter().position(|t| t.contains("Columns")) {
|
||||
assert!(
|
||||
caveat_idx < structure_idx,
|
||||
"caveat sits before the structure render: {texts:?}",
|
||||
);
|
||||
}
|
||||
|
||||
// Simple mode → no echo, no caveat.
|
||||
let mut app = App::new();
|
||||
app.update(AppEvent::DslChangeColumnSucceeded {
|
||||
command: Command::ChangeColumnType {
|
||||
table: "T".to_string(),
|
||||
column: "c".to_string(),
|
||||
ty: Type::Int,
|
||||
mode: ChangeColumnMode::DontConvert,
|
||||
},
|
||||
result: ChangeColumnTypeResult {
|
||||
description: sample_description("T"),
|
||||
client_side: None,
|
||||
},
|
||||
echo: None,
|
||||
dont_convert_caveat: false,
|
||||
});
|
||||
assert!(
|
||||
!app.output
|
||||
.iter()
|
||||
.any(|l| l.text.contains("--dont-convert")),
|
||||
"no caveat in simple mode (no echo to refer to)",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bucket_b_multi_line_echo_renders_one_line_per_statement_beneath_ok() {
|
||||
// ADR-0038 §6 category 2 / §4 / Phase 2 Slice 2b: a `drop column
|
||||
|
||||
Reference in New Issue
Block a user