2026-05-03 23:02:31 +08:00
|
|
|
package db_test
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"testing"
|
2026-05-04 00:50:56 +08:00
|
|
|
|
2026-05-03 23:02:31 +08:00
|
|
|
"apigo.cc/go/db"
|
2026-05-14 00:35:47 +08:00
|
|
|
"apigo.cc/go/file"
|
2026-05-09 14:54:55 +08:00
|
|
|
"apigo.cc/go/log"
|
2026-05-03 23:02:31 +08:00
|
|
|
_ "modernc.org/sqlite"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func TestSmartDelete(t *testing.T) {
|
2026-05-09 14:54:55 +08:00
|
|
|
db.ResetAllForTest()
|
|
|
|
|
|
|
|
|
|
dbPath := "./test_smart_delete.db"
|
|
|
|
|
dbName := "test_delete"
|
2026-05-14 00:35:47 +08:00
|
|
|
file.Remove(dbPath)
|
2026-05-09 14:54:55 +08:00
|
|
|
|
|
|
|
|
db.SetConfigForTest(dbName, &db.Config{
|
|
|
|
|
Type: "sqlite",
|
|
|
|
|
Host: dbPath,
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
dbInst := db.GetDB(dbName, log.DefaultLogger)
|
|
|
|
|
if dbInst == nil {
|
|
|
|
|
t.Fatal("dbInst should not be nil")
|
|
|
|
|
}
|
|
|
|
|
defer func() {
|
|
|
|
|
dbInst.Destroy()
|
2026-05-14 00:35:47 +08:00
|
|
|
file.Remove(dbPath)
|
2026-05-09 14:54:55 +08:00
|
|
|
}()
|
2026-05-04 00:50:56 +08:00
|
|
|
|
2026-05-03 23:02:31 +08:00
|
|
|
// Create table and shadow table
|
|
|
|
|
dbInst.Exec("CREATE TABLE orders (id INTEGER PRIMARY KEY, item TEXT)")
|
|
|
|
|
dbInst.Exec("CREATE TABLE orders_deleted (id INTEGER PRIMARY KEY, item TEXT)")
|
|
|
|
|
|
|
|
|
|
t.Run("ShadowDelete", func(t *testing.T) {
|
|
|
|
|
dbInst.Exec("INSERT INTO orders (id, item) VALUES (1, 'Phone')")
|
2026-05-04 00:50:56 +08:00
|
|
|
|
2026-05-03 23:02:31 +08:00
|
|
|
res := dbInst.Delete("orders", "id = 1")
|
|
|
|
|
if res.Error != nil {
|
|
|
|
|
t.Fatalf("Delete failed: %v", res.Error)
|
|
|
|
|
}
|
|
|
|
|
if res.Changes() != 1 {
|
|
|
|
|
t.Errorf("Expected 1 change, got %d", res.Changes())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Verify it's gone from main table
|
|
|
|
|
qr := dbInst.Query("SELECT COUNT(*) FROM orders WHERE id = 1")
|
2026-05-04 00:50:56 +08:00
|
|
|
count, _ := db.To[int](qr)
|
2026-05-03 23:02:31 +08:00
|
|
|
if count != 0 {
|
|
|
|
|
t.Errorf("Expected 0 records in main table, got %d", count)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Verify it's in shadow table
|
|
|
|
|
qr2 := dbInst.Query("SELECT COUNT(*) FROM orders_deleted WHERE id = 1")
|
2026-05-04 00:50:56 +08:00
|
|
|
countDeleted, _ := db.To[int](qr2)
|
2026-05-03 23:02:31 +08:00
|
|
|
if countDeleted != 1 {
|
|
|
|
|
t.Errorf("Expected 1 record in shadow table, got %d", countDeleted)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("PhysicalDelete", func(t *testing.T) {
|
|
|
|
|
dbInst.Exec("CREATE TABLE logs (id INTEGER PRIMARY KEY, msg TEXT)")
|
|
|
|
|
dbInst.Exec("INSERT INTO logs (id, msg) VALUES (1, 'Login')")
|
|
|
|
|
|
|
|
|
|
dbInst.Delete("logs", "id = 1")
|
2026-05-04 00:50:56 +08:00
|
|
|
|
2026-05-03 23:02:31 +08:00
|
|
|
qr := dbInst.Query("SELECT COUNT(*) FROM logs WHERE id = 1")
|
2026-05-04 00:50:56 +08:00
|
|
|
count, _ := db.To[int](qr)
|
2026-05-03 23:02:31 +08:00
|
|
|
if count != 0 {
|
|
|
|
|
t.Errorf("Expected 0 records in logs, got %d", count)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|