use iridium_core::{types::Value, Engine};
#[test]
fn test_state_restoration_on_savepoint_rollback() {
let engine = Engine::new();
engine
.exec("CREATE TABLE t (id INT IDENTITY(1,1) PRIMARY KEY, val INT)")
.unwrap();
engine.exec("DECLARE @x INT = 10").unwrap();
engine.exec("BEGIN TRANSACTION").unwrap();
engine.exec("SET @x = 20").unwrap();
engine.exec("INSERT INTO t (val) VALUES (100)").unwrap();
let r = engine.query("SELECT @x, SCOPE_IDENTITY()").unwrap();
assert_eq!(r.rows[0][0], Value::Int(20));
assert_eq!(r.rows[0][1], Value::BigInt(1));
engine.exec("SAVE TRANSACTION sp1").unwrap();
engine.exec("SET @x = 30").unwrap();
engine.exec("INSERT INTO t (val) VALUES (200)").unwrap();
let r = engine.query("SELECT @x, SCOPE_IDENTITY()").unwrap();
assert_eq!(r.rows[0][0], Value::Int(30));
assert_eq!(r.rows[0][1], Value::BigInt(2));
engine.exec("ROLLBACK TRANSACTION sp1").unwrap();
let r = engine.query("SELECT @x, SCOPE_IDENTITY()").unwrap();
assert_eq!(r.rows[0][0], Value::Int(20));
assert_eq!(r.rows[0][1], Value::BigInt(1));
let r = engine.query("SELECT val FROM t ORDER BY val").unwrap();
assert_eq!(r.rows, vec![vec![Value::Int(100)]]);
engine.exec("COMMIT").unwrap();
}
#[test]
fn test_state_restoration_on_full_rollback() {
let engine = Engine::new();
engine.exec("DECLARE @x INT = 10").unwrap();
engine.exec("BEGIN TRANSACTION").unwrap();
engine.exec("SET @x = 20").unwrap();
engine.exec("ROLLBACK TRANSACTION").unwrap();
let r = engine.query("SELECT @x").unwrap();
assert_eq!(r.rows[0][0], Value::Int(10));
}
#[test]
fn test_table_var_restoration_on_savepoint_rollback() {
let engine = Engine::new();
engine.exec("BEGIN TRANSACTION").unwrap();
engine.exec("DECLARE @tv TABLE (id INT)").unwrap();
engine.exec("INSERT INTO @tv VALUES (1)").unwrap();
engine.exec("SAVE TRANSACTION sp1").unwrap();
engine.exec("INSERT INTO @tv VALUES (2)").unwrap();
let r = engine.query("SELECT COUNT(*) FROM @tv").unwrap();
assert_eq!(r.rows[0][0], Value::BigInt(2));
engine.exec("ROLLBACK TRANSACTION sp1").unwrap();
let r = engine.query("SELECT COUNT(*) FROM @tv").unwrap();
assert_eq!(r.rows[0][0], Value::BigInt(1));
engine.exec("COMMIT").unwrap();
}
#[test]
fn test_nested_begin_transaction_state_restoration() {
let engine = Engine::new();
engine.exec("DECLARE @x INT = 10").unwrap();
engine.exec("BEGIN TRANSACTION").unwrap(); engine.exec("SET @x = 20").unwrap();
engine.exec("BEGIN TRANSACTION").unwrap(); engine.exec("SET @x = 30").unwrap();
engine.exec("ROLLBACK TRANSACTION").unwrap();
assert_eq!(
engine.query("SELECT @@TRANCOUNT").unwrap().rows[0][0],
Value::Int(0)
);
assert_eq!(
engine.query("SELECT @x").unwrap().rows[0][0],
Value::Int(10)
);
}