package main import ( "database/sql" "encoding/json" "fmt" "os" "strings" "inou/lib" _ "github.com/mattn/go-sqlite3" ) const dbPath = "/tank/inou/data/inou.db" func main() { if len(os.Args) < 2 { fmt.Fprintln(os.Stderr, "Usage: dbquery ") fmt.Fprintln(os.Stderr, " Runs SQL against inou.db, decrypts fields, outputs JSON.") fmt.Fprintln(os.Stderr, " Example: dbquery \"SELECT * FROM dossiers LIMIT 5\"") os.Exit(1) } query := strings.Join(os.Args[1:], " ") // Init crypto only (we open DB ourselves for raw queries) if err := lib.CryptoInit(lib.KeyPathDefault); err != nil { fmt.Fprintf(os.Stderr, "crypto init: %v\n", err) os.Exit(1) } db, err := sql.Open("sqlite3", dbPath) if err != nil { fmt.Fprintf(os.Stderr, "db open: %v\n", err) os.Exit(1) } defer db.Close() rows, err := db.Query(query) if err != nil { fmt.Fprintf(os.Stderr, "query: %v\n", err) os.Exit(1) } defer rows.Close() cols, err := rows.Columns() if err != nil { fmt.Fprintf(os.Stderr, "columns: %v\n", err) os.Exit(1) } var results []map[string]interface{} for rows.Next() { // Scan all as NullString scanDest := make([]interface{}, len(cols)) for i := range scanDest { scanDest[i] = new(sql.NullString) } if err := rows.Scan(scanDest...); err != nil { fmt.Fprintf(os.Stderr, "scan: %v\n", err) os.Exit(1) } row := make(map[string]interface{}) for i, col := range cols { ns := scanDest[i].(*sql.NullString) if !ns.Valid { row[col] = nil continue } val := ns.String // Try to decrypt — if it decrypts, use the decrypted value if decrypted := lib.CryptoDecrypt(val); decrypted != "" { // If decrypted looks like JSON, parse it if strings.HasPrefix(decrypted, "{") || strings.HasPrefix(decrypted, "[") { var parsed interface{} if json.Unmarshal([]byte(decrypted), &parsed) == nil { row[col] = parsed continue } } row[col] = decrypted } else { // Try parsing as number for cleaner output row[col] = val } } results = append(results, row) } if err := rows.Err(); err != nil { fmt.Fprintf(os.Stderr, "rows: %v\n", err) os.Exit(1) } out, _ := json.MarshalIndent(results, "", " ") fmt.Println(string(out)) }