package main import ( "database/sql" "fmt" "log" "strings" _ "modernc.org/sqlite" ) func main() { fmt.Println("==================================================") fmt.Println(" CHALLENGER POS - DATABASE RESCUE & REBUILD") fmt.Println("==================================================") oldDBPath := "C:/D3/PRM/CHALLENGER.db" newDBPath := "C:/D3/PRM/CHALLENGER_NEW.db" oldDB, err := sql.Open("sqlite", oldDBPath) if err != nil { log.Fatalf("FATAL: Could not open corrupted database: %v", err) } defer oldDB.Close() newDB, err := sql.Open("sqlite", newDBPath) if err != nil { log.Fatalf("FATAL: Could not create new database: %v", err) } defer newDB.Close() fmt.Println("[*] Step 1: Cloning Architecture...") rows, err := oldDB.Query("SELECT name, sql FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'") if err != nil { log.Fatalf("FATAL: Could not read schema: %v", err) } var tables []string for rows.Next() { var name, tableSQL sql.NullString rows.Scan(&name, &tableSQL) if name.Valid && tableSQL.Valid { tables = append(tables, name.String) newDB.Exec(tableSQL.String) } } rows.Close() fmt.Println("[*] Step 2: Rescuing Data (This will take a moment)...") for _, table := range tables { fmt.Printf(" -> Rescuing table: %s... ", table) // Get column names colRows, _ := oldDB.Query("PRAGMA table_info(" + table + ")") var cols []string var placeholders []string for colRows.Next() { var cid, nn, pk int var cname, ctype string var dflt interface{} colRows.Scan(&cid, &cname, &ctype, &nn, &dflt, &pk) cols = append(cols, cname) placeholders = append(placeholders, "?") } colRows.Close() insertSQL := "INSERT INTO " + table + " (" + strings.Join(cols, ", ") + ") VALUES (" + strings.Join(placeholders, ", ") + ")" dataRows, err := oldDB.Query("SELECT * FROM " + table) if err != nil { fmt.Printf("FAILED TO READ (Corruption blocking access): %v\n", err) continue } successCount := 0 failCount := 0 for dataRows.Next() { vals := make([]interface{}, len(cols)) valPtrs := make([]interface{}, len(cols)) for i := range cols { valPtrs[i] = &vals[i] } if err := dataRows.Scan(valPtrs...); err != nil { failCount++ continue } _, err = newDB.Exec(insertSQL, vals...) if err != nil { failCount++ } else { successCount++ } } dataRows.Close() fmt.Printf("Done. (Rescued: %d, Corrupted/Dropped: %d)\n", successCount, failCount) } fmt.Println("\n==================================================") fmt.Println(" RESCUE COMPLETE!") fmt.Println(" Your healthy data is now safely inside:") fmt.Println(" C:\\D3\\PRM\\CHALLENGER_NEW.db") fmt.Println("==================================================") }