package main import ( "encoding/json" "flag" "fmt" "os" "github.com/perfect-panel/server/internal/config" "github.com/perfect-panel/server/pkg/conf" "gorm.io/driver/mysql" "gorm.io/gorm" ) func main() { configPath := flag.String("config", "etc/ppanel.yaml", "config file path") query := flag.String("query", "", "sql query") flag.Parse() if *query == "" { fmt.Fprintln(os.Stderr, "query is required") os.Exit(1) } var cfg config.Config conf.MustLoad(*configPath, &cfg) dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s?%s", cfg.MySQL.Username, cfg.MySQL.Password, cfg.MySQL.Addr, cfg.MySQL.Dbname, cfg.MySQL.Config) db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) if err != nil { fmt.Fprintf(os.Stderr, "connect db failed: %v\n", err) os.Exit(1) } rows, err := db.Raw(*query).Rows() if err != nil { fmt.Fprintf(os.Stderr, "query failed: %v\n", err) os.Exit(1) } defer rows.Close() columns, err := rows.Columns() if err != nil { fmt.Fprintf(os.Stderr, "read columns failed: %v\n", err) os.Exit(1) } result := make([]map[string]interface{}, 0) for rows.Next() { values := make([]interface{}, len(columns)) pointers := make([]interface{}, len(columns)) for i := range values { pointers[i] = &values[i] } if err = rows.Scan(pointers...); err != nil { fmt.Fprintf(os.Stderr, "scan row failed: %v\n", err) os.Exit(1) } rowMap := make(map[string]interface{}, len(columns)) for i, col := range columns { v := values[i] if b, ok := v.([]byte); ok { rowMap[col] = string(b) continue } rowMap[col] = v } result = append(result, rowMap) } encoder := json.NewEncoder(os.Stdout) if err = encoder.Encode(result); err != nil { fmt.Fprintf(os.Stderr, "encode result failed: %v\n", err) os.Exit(1) } }