mod common;
use common::setup_users_table as setup_test_table;
use vibesql_executor::{ExecutorError, InsertExecutor};
#[test]
fn test_multi_row_insert_atomic_success() {
let mut db = vibesql_storage::Database::new();
setup_test_table(&mut db);
let stmt = vibesql_ast::InsertStmt {
with_clause: None,
schema_name: None,
schema_quoted: false,
table_quoted: false,
table_name: "users".to_string(),
columns: vec![],
source: vibesql_ast::InsertSource::Values(vec![
vec![
vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Integer(1)),
vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Varchar(
arcstr::ArcStr::from("Alice"),
)),
],
vec![
vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Integer(2)),
vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Varchar(
arcstr::ArcStr::from("Bob"),
)),
],
vec![
vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Integer(3)),
vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Varchar(
arcstr::ArcStr::from("Charlie"),
)),
],
]),
conflict_clause: None,
on_conflict: None,
on_duplicate_key_update: None,
returning: None,
};
let rows = InsertExecutor::execute(&mut db, &stmt).unwrap();
assert_eq!(rows, 3);
let table = db.get_table("users").unwrap();
assert_eq!(table.row_count(), 3);
}
#[test]
fn test_multi_row_insert_atomic_failure() {
let mut db = vibesql_storage::Database::new();
setup_test_table(&mut db);
let stmt = vibesql_ast::InsertStmt {
with_clause: None,
schema_name: None,
schema_quoted: false,
table_quoted: false,
table_name: "users".to_string(),
columns: vec![],
source: vibesql_ast::InsertSource::Values(vec![
vec![
vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Integer(1)),
vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Varchar(
arcstr::ArcStr::from("Alice"),
)),
],
vec![
vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Null),
vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Varchar(
arcstr::ArcStr::from("Bob"),
)),
],
vec![
vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Integer(3)),
vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Varchar(
arcstr::ArcStr::from("Charlie"),
)),
],
]),
conflict_clause: None,
on_conflict: None,
on_duplicate_key_update: None,
returning: None,
};
let result = InsertExecutor::execute(&mut db, &stmt);
assert!(result.is_err());
assert!(matches!(result.unwrap_err(), ExecutorError::ConstraintViolation(_)));
let table = db.get_table("users").unwrap();
assert_eq!(table.row_count(), 0);
}
#[test]
fn test_multi_row_insert_with_column_list() {
let mut db = vibesql_storage::Database::new();
setup_test_table(&mut db);
let stmt = vibesql_ast::InsertStmt {
with_clause: None,
schema_name: None,
schema_quoted: false,
table_quoted: false,
table_name: "users".to_string(),
columns: vec!["name".to_string(), "id".to_string()],
source: vibesql_ast::InsertSource::Values(vec![
vec![
vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Varchar(
arcstr::ArcStr::from("Alice"),
)),
vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Integer(1)),
],
vec![
vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Varchar(
arcstr::ArcStr::from("Bob"),
)),
vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Integer(2)),
],
]),
conflict_clause: None,
on_conflict: None,
on_duplicate_key_update: None,
returning: None,
};
let rows = InsertExecutor::execute(&mut db, &stmt).unwrap();
assert_eq!(rows, 2);
let table = db.get_table("users").unwrap();
assert_eq!(table.row_count(), 2);
}
#[test]
fn test_multi_row_insert_sqlite_type_affinity() {
let mut db = vibesql_storage::Database::new();
setup_test_table(&mut db);
let stmt = vibesql_ast::InsertStmt {
with_clause: None,
schema_name: None,
schema_quoted: false,
table_quoted: false,
table_name: "users".to_string(),
columns: vec![],
source: vibesql_ast::InsertSource::Values(vec![
vec![
vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Integer(1)),
vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Varchar(
arcstr::ArcStr::from("Alice"),
)),
],
vec![
vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Varchar(
arcstr::ArcStr::from("not_a_number"),
)), vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Varchar(
arcstr::ArcStr::from("Bob"),
)),
],
]),
conflict_clause: None,
on_conflict: None,
on_duplicate_key_update: None,
returning: None,
};
let result = InsertExecutor::execute(&mut db, &stmt);
assert!(result.is_ok(), "SQLite type affinity should accept any value type");
assert_eq!(result.unwrap(), 2);
let table = db.get_table("users").unwrap();
assert_eq!(table.row_count(), 2);
}
#[test]
fn test_multi_row_insert_various_data_types() {
let mut db = vibesql_storage::Database::new();
let schema = vibesql_catalog::TableSchema::new(
"test_types".to_string(),
vec![
vibesql_catalog::ColumnSchema::new(
"id".to_string(),
vibesql_types::DataType::Integer,
false,
),
vibesql_catalog::ColumnSchema::new(
"name".to_string(),
vibesql_types::DataType::Varchar { max_length: Some(50) },
true,
),
vibesql_catalog::ColumnSchema::new(
"active".to_string(),
vibesql_types::DataType::Boolean,
true,
),
vibesql_catalog::ColumnSchema::new(
"score".to_string(),
vibesql_types::DataType::Float { precision: 53 },
true,
),
],
);
db.create_table(schema).unwrap();
let stmt = vibesql_ast::InsertStmt {
with_clause: None,
schema_name: None,
schema_quoted: false,
table_quoted: false,
table_name: "test_types".to_string(),
columns: vec![],
source: vibesql_ast::InsertSource::Values(vec![
vec![
vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Integer(1)),
vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Varchar(
arcstr::ArcStr::from("Alice"),
)),
vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Boolean(true)),
vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Float(95.5)),
],
vec![
vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Integer(2)),
vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Varchar(
arcstr::ArcStr::from("Bob"),
)),
vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Boolean(false)),
vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Float(87.2)),
],
vec![
vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Integer(3)),
vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Null),
vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Null),
vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Null),
],
]),
conflict_clause: None,
on_conflict: None,
on_duplicate_key_update: None,
returning: None,
};
let rows = InsertExecutor::execute(&mut db, &stmt).unwrap();
assert_eq!(rows, 3);
let table = db.get_table("test_types").unwrap();
assert_eq!(table.row_count(), 3);
}
#[test]
fn test_multi_row_insert_primary_key_violation() {
let mut db = vibesql_storage::Database::new();
let schema = vibesql_catalog::TableSchema::with_primary_key(
"users".to_string(),
vec![
vibesql_catalog::ColumnSchema::new(
"id".to_string(),
vibesql_types::DataType::Integer,
false,
),
vibesql_catalog::ColumnSchema::new(
"name".to_string(),
vibesql_types::DataType::Varchar { max_length: Some(50) },
true,
),
],
vec!["id".to_string()],
);
db.create_table(schema).unwrap();
let stmt = vibesql_ast::InsertStmt {
with_clause: None,
schema_name: None,
schema_quoted: false,
table_quoted: false,
table_name: "users".to_string(),
columns: vec![],
source: vibesql_ast::InsertSource::Values(vec![
vec![
vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Integer(1)),
vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Varchar(
arcstr::ArcStr::from("Alice"),
)),
],
vec![
vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Integer(1)),
vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Varchar(
arcstr::ArcStr::from("Bob"),
)),
],
]),
conflict_clause: None,
on_conflict: None,
on_duplicate_key_update: None,
returning: None,
};
let result = InsertExecutor::execute(&mut db, &stmt);
assert!(result.is_err());
let err = result.unwrap_err();
assert!(
matches!(err, ExecutorError::ConstraintViolation(_) | ExecutorError::SqliteCompatError(_)),
"Expected ConstraintViolation or SqliteCompatError, got {:?}",
err
);
let table = db.get_table("users").unwrap();
assert_eq!(table.row_count(), 0);
}
#[test]
fn test_single_row_insert_no_transaction() {
let mut db = vibesql_storage::Database::new();
setup_test_table(&mut db);
let stmt = vibesql_ast::InsertStmt {
with_clause: None,
schema_name: None,
schema_quoted: false,
table_quoted: false,
table_name: "users".to_string(),
columns: vec![],
source: vibesql_ast::InsertSource::Values(vec![vec![
vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Integer(1)),
vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Varchar(
arcstr::ArcStr::from("Alice"),
)),
]]),
conflict_clause: None,
on_conflict: None,
on_duplicate_key_update: None,
returning: None,
};
let rows = InsertExecutor::execute(&mut db, &stmt).unwrap();
assert_eq!(rows, 1);
let table = db.get_table("users").unwrap();
assert_eq!(table.row_count(), 1);
}