package main import ( "database/sql" "flag" "fmt" "log" "os" "strings" _ "github.com/go-sql-driver/mysql" ) func main() { dsn := flag.String("dsn", os.Getenv("PPANEL_MYSQL_DSN"), "MySQL DSN; defaults to PPANEL_MYSQL_DSN") flag.Parse() if strings.TrimSpace(*dsn) == "" { log.Fatal("missing DSN: pass -dsn or set PPANEL_MYSQL_DSN") } db, err := sql.Open("mysql", *dsn) if err != nil { log.Fatal(err) } defer db.Close() if err = db.Ping(); err != nil { log.Fatal(err) } mustPrintRows(db, "db/info", ` SELECT NOW() AS db_now, (SELECT COUNT(*) FROM user) AS users, (SELECT COUNT(*) FROM user_subscribe) AS user_subscribes, (SELECT COUNT(*) FROM `+"`order`"+`) AS orders`) mustPrintRows(db, "bug1/confusable-email-trials", ` SELECT uam.user_id, uam.auth_identifier, us.id AS user_subscribe_id, us.order_id, us.status, us.expire_time, us.created_at FROM user_auth_methods uam JOIN user_subscribe us ON us.user_id = uam.user_id WHERE uam.auth_type = 'email' AND us.order_id = 0 AND ( uam.auth_identifier LIKE '%@gmaial.com' OR uam.auth_identifier LIKE '%@gmial.com' OR uam.auth_identifier LIKE '%@gamil.com' OR uam.auth_identifier LIKE '%+%@%' OR uam.auth_identifier REGEXP '^[^@]*\\.[^@]*@gmail\\.com$' ) ORDER BY us.created_at DESC LIMIT 50`) mustPrintRows(db, "bug2-visible-duplicate-subscriptions", ` SELECT scoped.owner_user_id, COUNT(*) AS visible_subscribe_count, GROUP_CONCAT(scoped.user_subscribe_id ORDER BY scoped.expire_time DESC) AS user_subscribe_ids, GROUP_CONCAT(scoped.subscribe_id ORDER BY scoped.expire_time DESC) AS subscribe_ids, MAX(scoped.expire_time) AS max_expire_time FROM ( SELECT us.id AS user_subscribe_id, us.user_id, COALESCE(uf.owner_user_id, us.user_id) AS owner_user_id, us.subscribe_id, us.status, us.expire_time, us.finished_at FROM user_subscribe us LEFT JOIN user_family_member ufm ON ufm.user_id = us.user_id AND ufm.deleted_at IS NULL AND ufm.status = 1 LEFT JOIN user_family uf ON uf.id = ufm.family_id AND uf.deleted_at IS NULL AND uf.status = 1 WHERE us.token <> '' AND us.status IN (0,1,2,3,4) AND (us.expire_time > NOW() OR us.finished_at >= DATE_SUB(NOW(), INTERVAL 7 DAY) OR us.expire_time = FROM_UNIXTIME(0)) ) scoped GROUP BY scoped.owner_user_id HAVING COUNT(*) > 1 ORDER BY visible_subscribe_count DESC, owner_user_id LIMIT 50`) mustPrintRows(db, "bug2-order-subscription-owner-mismatch", ` SELECT us.id AS user_subscribe_id, us.user_id AS subscribe_user_id, o.id AS order_id, o.order_no, o.user_id AS order_user_id, o.subscription_user_id, us.status, us.expire_time, us.created_at AS subscribe_created_at, o.created_at AS order_created_at FROM user_subscribe us JOIN `+"`order`"+` o ON o.id = us.order_id WHERE us.user_id <> o.subscription_user_id AND us.token <> '' AND us.status IN (0,1,2,3,4) ORDER BY us.updated_at DESC LIMIT 50`) mustPrintRows(db, "bug3-invite-first-orders-missing-gift-days", ` SELECT first_orders.user_id AS referee_id, referee.referer_id, first_orders.id AS order_id, first_orders.order_no, first_orders.amount, first_orders.created_at, referer.referral_percentage AS referer_referral_percentage, (SELECT COUNT(*) FROM system_logs sl WHERE sl.type = 34 AND sl.object_id = first_orders.user_id AND sl.content LIKE CONCAT('%', first_orders.order_no, '%')) AS referee_gift_logs, (SELECT COUNT(*) FROM system_logs sl WHERE sl.type = 34 AND sl.object_id = referee.referer_id AND sl.content LIKE CONCAT('%', first_orders.order_no, '%')) AS referer_gift_logs FROM ( SELECT o.* FROM `+"`order`"+` o JOIN ( SELECT user_id, MIN(id) AS first_order_id FROM `+"`order`"+` WHERE type IN (1,2) AND status IN (2,5) AND amount > 0 GROUP BY user_id ) fo ON fo.first_order_id = o.id ) first_orders JOIN user referee ON referee.id = first_orders.user_id AND referee.referer_id <> 0 JOIN user referer ON referer.id = referee.referer_id WHERE ( referer.referral_percentage = 0 AND ( (SELECT COUNT(*) FROM system_logs sl WHERE sl.type = 34 AND sl.object_id = first_orders.user_id AND sl.content LIKE CONCAT('%', first_orders.order_no, '%')) = 0 OR (SELECT COUNT(*) FROM system_logs sl WHERE sl.type = 34 AND sl.object_id = referee.referer_id AND sl.content LIKE CONCAT('%', first_orders.order_no, '%')) = 0 ) ) OR ( referer.referral_percentage > 0 AND (SELECT COUNT(*) FROM system_logs sl WHERE sl.type = 34 AND sl.object_id = first_orders.user_id AND sl.content LIKE CONCAT('%', first_orders.order_no, '%')) = 0 ) ORDER BY first_orders.created_at DESC LIMIT 50`) } func mustPrintRows(db *sql.DB, title string, query string) { fmt.Printf("\n== %s ==\n", title) rows, err := db.Query(query) if err != nil { log.Fatalf("%s: %v", title, err) } defer rows.Close() cols, err := rows.Columns() if err != nil { log.Fatalf("%s columns: %v", title, err) } fmt.Println(strings.Join(cols, "\t")) values := make([]sql.NullString, len(cols)) args := make([]any, len(cols)) for i := range values { args[i] = &values[i] } count := 0 for rows.Next() { if err := rows.Scan(args...); err != nil { log.Fatalf("%s scan: %v", title, err) } out := make([]string, len(cols)) for i, value := range values { if value.Valid { out[i] = value.String } else { out[i] = "NULL" } } fmt.Println(strings.Join(out, "\t")) count++ } if err := rows.Err(); err != nil { log.Fatalf("%s rows: %v", title, err) } if count == 0 { fmt.Println("(none)") } }