From 1c2a8e62ca730ba1702143c6d78187e4c78dd2e4 Mon Sep 17 00:00:00 2001 From: Jussi Saurio Date: Mon, 3 Nov 2025 11:41:07 +0200 Subject: [PATCH] Fix: return error on provided insert column count mismatch --- core/translate/insert.rs | 20 ++++++++++++ testing/insert.test | 67 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) diff --git a/core/translate/insert.rs b/core/translate/insert.rs index b5b7b7519..c6c9e90a8 100644 --- a/core/translate/insert.rs +++ b/core/translate/insert.rs @@ -1059,6 +1059,20 @@ fn init_source_emission<'a>( body: InsertBody, columns: &'a [ast::Name], ) -> Result { + let required_column_count = if columns.is_empty() { + table.columns().len() + } else { + columns.len() + }; + if !values.is_empty() { + // If we had a single tuple in VALUES, it was inserted into the values vector parameter. + if values.len() != required_column_count { + crate::bail_parse_error!( + "{} values for {required_column_count} columns", + values.len() + ); + } + } let (num_values, cursor_id) = match body { InsertBody::Select(select, _) => { // Simple common case of INSERT INTO VALUES (...) without compounds. @@ -1088,6 +1102,12 @@ fn init_source_emission<'a>( program.incr_nesting(); let result = translate_select(select, resolver, program, query_destination, connection)?; + if result.num_result_cols != required_column_count { + crate::bail_parse_error!( + "{} values for {required_column_count} columns", + result.num_result_cols, + ); + } program = result.program; program.decr_nesting(); diff --git a/testing/insert.test b/testing/insert.test index 3eaa44bc0..e8c270aeb 100755 --- a/testing/insert.test +++ b/testing/insert.test @@ -798,3 +798,70 @@ do_execsql_test_on_specific_db {:memory:} ignore-intra-statement-dups { SELECT a,b FROM t ORDER BY a; } {5|first 6|x} + +# Tests for incorrect provided column count + +do_execsql_test_in_memory_any_error wrong-column-count-values-too-few { + CREATE TABLE t(a, b, c); + INSERT INTO t VALUES (1, 2); +} + +do_execsql_test_in_memory_any_error wrong-column-count-values-too-many { + CREATE TABLE t(a, b); + INSERT INTO t VALUES (1, 2, 3); +} + +do_execsql_test_in_memory_any_error wrong-column-count-values-specified-columns-too-few { + CREATE TABLE t(a, b, c); + INSERT INTO t(a, b, c) VALUES (1, 2); +} + +do_execsql_test_in_memory_any_error wrong-column-count-values-specified-columns-too-many { + CREATE TABLE t(a, b); + INSERT INTO t(a, b) VALUES (1, 2, 3); +} + +do_execsql_test_in_memory_any_error wrong-column-count-select-named-too-few { + CREATE TABLE src(x, y); + INSERT INTO src VALUES (1, 2); + CREATE TABLE dst(a, b, c); + INSERT INTO dst SELECT x, y FROM src; +} + +do_execsql_test_in_memory_any_error wrong-column-count-select-named-too-many { + CREATE TABLE src(x, y, z); + INSERT INTO src VALUES (1, 2, 3); + CREATE TABLE dst(a, b); + INSERT INTO dst SELECT x, y, z FROM src; +} + +do_execsql_test_in_memory_any_error wrong-column-count-select-star-too-few { + CREATE TABLE src(x, y); + INSERT INTO src VALUES (1, 2); + CREATE TABLE dst(a, b, c); + INSERT INTO dst SELECT * FROM src; +} + +do_execsql_test_in_memory_any_error wrong-column-count-select-star-too-many { + CREATE TABLE src(x, y, z); + INSERT INTO src VALUES (1, 2, 3); + CREATE TABLE dst(a, b); + INSERT INTO dst SELECT * FROM src; +} + +do_execsql_test_in_memory_any_error wrong-column-count-specified-columns-select-mismatch { + CREATE TABLE src(x, y, z); + INSERT INTO src VALUES (1, 2, 3); + CREATE TABLE dst(a, b, c, d); + INSERT INTO dst(a, b) SELECT x, y, z FROM src; +} + +do_execsql_test_in_memory_any_error wrong-column-count-partial-columns-values-too-few { + CREATE TABLE t(a, b, c); + INSERT INTO t(b, c) VALUES (2); +} + +do_execsql_test_in_memory_any_error wrong-column-count-partial-columns-values-too-many { + CREATE TABLE t(a, b, c); + INSERT INTO t(a) VALUES (1, 2); +}