db: 3d fix — don't let shortid auto-fill mask INSERT arity mismatch
plan_shortid_autofill read exactly listed_columns.len() cells from the materialised row source. When the row source produced a different column count than the user's list, the extra columns were silently dropped (wider → wrong data, insert succeeded) or read out of range (narrower). Guard: if the materialised statement's column_count differs from the listed-column count, skip auto-fill and execute the verbatim statement so the engine reports the mismatch — matching the non-auto-fill path. A friendly pre-flight diagnostic remains sub-phase 3i. Tests: VALUES with too many values; INSERT…SELECT with a wider and a narrower projection — each rejected with nothing persisted.
This commit is contained in:
@@ -5832,6 +5832,15 @@ fn plan_shortid_autofill(
|
||||
// as concrete rows for the listed columns.
|
||||
let listed_count = listed_columns.len();
|
||||
let mut stmt = conn.prepare(row_source).map_err(DbError::from_rusqlite)?;
|
||||
// Arity guard: if the row source's column count disagrees with
|
||||
// the user's column list, do NOT auto-fill — reading
|
||||
// `listed_count` cells would silently drop extra columns (or
|
||||
// error opaquely on too few). Defer to the verbatim statement
|
||||
// so the engine reports the mismatch as it does on the
|
||||
// non-auto-fill path (a friendly pre-flight lands in 3i).
|
||||
if stmt.column_count() != listed_count {
|
||||
return Ok((sql.to_string(), Vec::new()));
|
||||
}
|
||||
let mut rows: Vec<Vec<rusqlite::types::Value>> = Vec::new();
|
||||
{
|
||||
let mut q = stmt.query([]).map_err(DbError::from_rusqlite)?;
|
||||
|
||||
Reference in New Issue
Block a user