// Copyright (C) 2019 G.J.R. Timmer . // Copyright (C) 2018 segment.com // // Use of this source code is governed by an MIT-style // license that can be found in the LICENSE file. //go:build sqlite_preupdate_hook // +build sqlite_preupdate_hook package sqlite3 import ( "database/sql" "testing" ) type preUpdateHookDataForTest struct { databaseName string tableName string count int op int oldRow []any newRow []any } func TestPreUpdateHook(t *testing.T) { var events []preUpdateHookDataForTest sql.Register("sqlite3_PreUpdateHook", &SQLiteDriver{ ConnectHook: func(conn *SQLiteConn) error { conn.RegisterPreUpdateHook(func(data SQLitePreUpdateData) { eval := -1 oldRow := []any{eval} if data.Op != SQLITE_INSERT { err := data.Old(oldRow...) if err != nil { t.Fatalf("Unexpected error calling SQLitePreUpdateData.Old: %v", err) } } eval2 := -1 newRow := []any{eval2} if data.Op != SQLITE_DELETE { err := data.New(newRow...) if err != nil { t.Fatalf("Unexpected error calling SQLitePreUpdateData.New: %v", err) } } // tests dest bound checks in loop var tooSmallRow []any if data.Op != SQLITE_INSERT { err := data.Old(tooSmallRow...) if err != nil { t.Fatalf("Unexpected error calling SQLitePreUpdateData.Old: %v", err) } if len(tooSmallRow) != 0 { t.Errorf("Expected tooSmallRow to be empty, got: %v", tooSmallRow) } } events = append(events, preUpdateHookDataForTest{ databaseName: data.DatabaseName, tableName: data.TableName, count: data.Count(), op: data.Op, oldRow: oldRow, newRow: newRow, }) }) return nil }, }) db, err := sql.Open("sqlite3_PreUpdateHook", ":memory:") if err != nil { t.Fatal("Failed to open database:", err) } defer db.Close() statements := []string{ "create table foo (id integer primary key)", "insert into foo values (9)", "update foo set id = 99 where id = 9", "delete from foo where id = 99", } for _, statement := range statements { _, err = db.Exec(statement) if err != nil { t.Fatalf("Unable to prepare test data [%v]: %v", statement, err) } } if len(events) != 3 { t.Errorf("Events should be 3 entries, got: %d", len(events)) } if events[0].op != SQLITE_INSERT { t.Errorf("Op isn't as expected: %v", events[0].op) } if events[1].op != SQLITE_UPDATE { t.Errorf("Op isn't as expected: %v", events[1].op) } if events[1].count != 1 { t.Errorf("Expected event row 1 to have 1 column, had: %v", events[1].count) } newRow_0_0 := events[0].newRow[0].(int64) if newRow_0_0 != 9 { t.Errorf("Expected event row 0 new column 0 to be == 9, got: %v", newRow_0_0) } oldRow_1_0 := events[1].oldRow[0].(int64) if oldRow_1_0 != 9 { t.Errorf("Expected event row 1 old column 0 to be == 9, got: %v", oldRow_1_0) } newRow_1_0 := events[1].newRow[0].(int64) if newRow_1_0 != 99 { t.Errorf("Expected event row 1 new column 0 to be == 99, got: %v", newRow_1_0) } oldRow_2_0 := events[2].oldRow[0].(int64) if oldRow_2_0 != 99 { t.Errorf("Expected event row 1 new column 0 to be == 99, got: %v", oldRow_2_0) } }