diff --git a/cmd/migrate/main.go b/cmd/migrate/main.go index 121d28b..4dfe929 100644 --- a/cmd/migrate/main.go +++ b/cmd/migrate/main.go @@ -141,6 +141,6 @@ func skipFriendDirected(gdb *gorm.DB, path string) bool { return false } var n int64 - err := gdb.Raw(`SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'friend_relations' AND column_name = 'user_id'`).Scan(&n).Error + err := gdb.Raw(`SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 't_friend_relations' AND column_name = 'user_id'`).Scan(&n).Error return err == nil && n > 0 } diff --git a/docs/architecture-v3.md b/docs/architecture-v3.md index f578b90..1ccc0fe 100644 --- a/docs/architecture-v3.md +++ b/docs/architecture-v3.md @@ -379,8 +379,8 @@ TaskPool: 2. 权限(见 9.4),失败不写库 3. MsgId = 请求带来的或 Snowflake 4. BEGIN - INSERT messages - UPDATE conversations.last_msg_id / last_msg_at + INSERT t_messages + UPDATE t_conversations.last_msg_id / last_msg_at COMMIT 5. DeliverQueue.Push // 可靠入队,失败则重试有限次 6. 仍失败 → 不 SEND_ACK,客户端用 client_msg_id 重试 @@ -406,7 +406,7 @@ P2P 好友关系、未拉黑、对方未禁你 ## 10.1 messages ```sql -CREATE TABLE messages ( +CREATE TABLE t_messages ( id BIGINT PRIMARY KEY COMMENT 'Snowflake MsgId,主键、排序键、同步游标', conversation_id BIGINT NOT NULL COMMENT '所属会话 id', sender_id BIGINT NOT NULL COMMENT '发送者 user_id', @@ -423,7 +423,7 @@ CREATE TABLE messages ( `message_type` 与 `content` 内 JSON 的 `t` 必须一致。正文用 `json.Marshal` 得到的 `[]byte` 写入 BLOB,不要把 Go `string` 当列类型。图片/语音/GIF/文件只存对象存储 key。完整 COMMENT 见 `migrations/0001_init.sql`。 ```sql -SELECT * FROM messages +SELECT * FROM t_messages WHERE conversation_id = ? AND id > ? ORDER BY id ASC LIMIT 200; ``` @@ -431,7 +431,7 @@ SELECT * FROM messages ## 10.2 conversations / P2P 唯一 / members ```sql -CREATE TABLE conversations ( +CREATE TABLE t_conversations ( id BIGINT PRIMARY KEY, type TINYINT NOT NULL, -- 1=P2P 2=GROUP last_msg_id BIGINT NOT NULL DEFAULT 0, @@ -440,7 +440,7 @@ CREATE TABLE conversations ( ); -- 两人永远同一条会话,学 BFF 小 uid : 大 uid -CREATE TABLE p2p_conversations ( +CREATE TABLE t_p2p_conversations ( id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, user_small BIGINT NOT NULL, user_big BIGINT NOT NULL, @@ -449,7 +449,7 @@ CREATE TABLE p2p_conversations ( UNIQUE KEY uk_conversation (conversation_id) ); -CREATE TABLE conversation_members ( +CREATE TABLE t_conversation_members ( id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, conversation_id BIGINT NOT NULL, user_id BIGINT NOT NULL, @@ -469,7 +469,7 @@ CREATE TABLE conversation_members ( ## 10.3 mailbox_events(失败邮箱 + 控制事件) ```sql -CREATE TABLE mailbox_events ( +CREATE TABLE t_mailbox_events ( id BIGINT PRIMARY KEY, user_id BIGINT NOT NULL, device_id BIGINT NOT NULL, -- 0 = 该用户所有设备 @@ -482,7 +482,7 @@ CREATE TABLE mailbox_events ( KEY idx_user_device (user_id, device_id, seq) ); -CREATE TABLE device_sync_cursors ( +CREATE TABLE t_device_sync_cursors ( id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, user_id BIGINT NOT NULL, device_id BIGINT NOT NULL, @@ -817,7 +817,7 @@ Client TLS :443 Nginx SNI im.example.com + PROXY gnet 读真实 IP → TLS → Frame TaskPool - 权限 → INSERT messages → RPUSH 可靠队列 → SEND_ACK + 权限 → INSERT t_messages → RPUSH 可靠队列 → SEND_ACK Deliver Worker 幂等 → ZSET 列表 → 在线 MESSAGE 失败 → mailbox + 可选系统推送 diff --git a/docs/devices.md b/docs/devices.md index 42a4d37..f80c13e 100644 --- a/docs/devices.md +++ b/docs/devices.md @@ -65,7 +65,7 @@ device_id = uint64(SHA256(fingerprint_hash)[0:8]),非 0 ## 表:`devices` ```sql -CREATE TABLE devices ( +CREATE TABLE t_devices ( device_id BIGINT UNSIGNED NOT NULL COMMENT 'JWT did;多 App 同机共用', fingerprint_hash CHAR(64) NOT NULL COMMENT '物理指纹,UNIQUE,不含 app_id', device_type TINYINT UNSIGNED NOT NULL COMMENT 'device_type 枚举', @@ -85,10 +85,10 @@ CREATE TABLE devices ( ## 表:`user_devices`(无 `app_id`) ```sql -CREATE TABLE user_devices ( +CREATE TABLE t_user_devices ( id BIGINT NOT NULL AUTO_INCREMENT COMMENT '行 id,表内自增', user_id BIGINT NOT NULL COMMENT '用户 uid', - device_id BIGINT UNSIGNED NOT NULL COMMENT 'devices.device_id', + device_id BIGINT UNSIGNED NOT NULL COMMENT 't_devices.device_id', last_login_at DATETIME(3) NOT NULL COMMENT '该用户在此设备最近登录成功', last_active_at DATETIME(3) NULL COMMENT '该用户在此设备最近活跃', created_at DATETIME(3) NOT NULL COMMENT '该用户首次在此设备绑定', @@ -110,7 +110,7 @@ CREATE TABLE user_devices ( ## 表:`user_login_logs` ```sql -ALTER TABLE user_login_logs +ALTER TABLE t_user_login_logs ADD COLUMN app_id TINYINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '当次登录 App,见 meta app_id' AFTER device_id; ``` @@ -169,9 +169,9 @@ ALTER TABLE user_login_logs 1. 校验 Body **`app_id`**、OTP 等。 2. **email** 查/建用户。 -3. 指纹 → **`device_id`** → UPSERT **`devices`**。 -4. UPSERT **`user_devices(user_id, device_id)`**。 -5. INSERT **`user_login_logs`**(含当次 **`app_id`**)。 +3. 指纹 → **`device_id`** → UPSERT **`t_devices`**。 +4. UPSERT **`t_user_devices(user_id, device_id)`**。 +5. INSERT **`t_user_login_logs`**(含当次 **`app_id`**)。 6. **`Issue(user_id, device_id, app_id)`**(Body `app_id` → JWT `aid`;PairStore 按 **`pair_key_mode`**)。 --- diff --git a/internal/module/admin/model/complaints.go b/internal/module/admin/model/complaints.go index 1066d98..45fd6a0 100644 --- a/internal/module/admin/model/complaints.go +++ b/internal/module/admin/model/complaints.go @@ -27,9 +27,9 @@ func (m *Repo) ListComplaints(ctx context.Context, limit int) ([]ComplaintRow, e err = db.Raw(` SELECT r.id, r.user_id, r.target_id, r.reason, r.detail, r.created_at, COALESCE(e.email,'') AS email, COALESCE(te.email,'') AS target_email -FROM friend_reports r -LEFT JOIN user_emails e ON e.user_id = r.user_id -LEFT JOIN user_emails te ON te.user_id = r.target_id +FROM t_friend_reports r +LEFT JOIN t_user_emails e ON e.user_id = r.user_id +LEFT JOIN t_user_emails te ON te.user_id = r.target_id ORDER BY r.id DESC LIMIT ?`, limit).Scan(&rows).Error if err != nil { @@ -53,6 +53,6 @@ func (m *Repo) InsertComplaint(ctx context.Context, r *friendentity.Report) erro if err != nil { return err } - return mapDBErr(db.Exec(`INSERT INTO friend_reports (id, user_id, target_id, reason, detail, created_at) VALUES (?,?,?,?,?,?)`, + return mapDBErr(db.Exec(`INSERT INTO t_friend_reports (id, user_id, target_id, reason, detail, created_at) VALUES (?,?,?,?,?,?)`, r.ID, r.UserID, r.TargetID, int(r.Reason), r.Detail, r.CreatedAt).Error) } diff --git a/internal/module/admin/model/groups.go b/internal/module/admin/model/groups.go index de40b2a..9eebe01 100644 --- a/internal/module/admin/model/groups.go +++ b/internal/module/admin/model/groups.go @@ -36,7 +36,7 @@ func (m *Repo) ListGroups(ctx context.Context, q string) ([]GroupRow, error) { if err != nil { return nil, err } - query := db.Table("`groups`").Where("status = ?", int(groupentity.StatusActive)) + query := db.Table("`t_groups`").Where("status = ?", int(groupentity.StatusActive)) q = strings.TrimSpace(q) if q != "" { like := "%" + q + "%" @@ -63,7 +63,7 @@ func (m *Repo) GroupByID(ctx context.Context, groupID int64) (*GroupRow, error) return nil, err } var r groupScanRow - if err := db.Table("`groups`").Where("id = ?", groupID).Take(&r).Error; err != nil { + if err := db.Table("`t_groups`").Where("id = ?", groupID).Take(&r).Error; err != nil { return nil, mapDBErr(err) } row := groupScanToRow(r) @@ -78,7 +78,7 @@ func (m *Repo) ActiveGroupOwner(ctx context.Context, groupID int64) (int64, erro var r struct { OwnerID int64 `gorm:"column:owner_id"` } - err = db.Table("`groups`").Select("owner_id"). + err = db.Table("`t_groups`").Select("owner_id"). Where("id = ? AND status = ?", groupID, int(groupentity.StatusActive)). Take(&r).Error if err != nil { @@ -105,9 +105,9 @@ func (m *Repo) ListGroupMembers(ctx context.Context, groupID int64) ([]GroupMemb var rows []scanRow err = db.Raw(` SELECT m.user_id, m.role, m.nickname, COALESCE(e.email,'') AS email, COALESCE(u.nickname,'') AS u_nickname -FROM group_members m -LEFT JOIN users u ON u.id = m.user_id -LEFT JOIN user_emails e ON e.user_id = m.user_id +FROM t_group_members m +LEFT JOIN t_users u ON u.id = m.user_id +LEFT JOIN t_user_emails e ON e.user_id = m.user_id WHERE m.group_id = ? ORDER BY m.role ASC, m.joined_at ASC LIMIT 500`, groupID).Scan(&rows).Error diff --git a/internal/module/admin/model/im.go b/internal/module/admin/model/im.go index c3dcea8..b45d17f 100644 --- a/internal/module/admin/model/im.go +++ b/internal/module/admin/model/im.go @@ -15,14 +15,14 @@ func (m *Repo) ImStats(ctx context.Context) (*adminentity.ImStats, error) { } out := &adminentity.ImStats{} var priv, grp, revokedPriv, revokedGrp int64 - _ = db.Table("private_message").Count(&priv).Error - _ = db.Table("group_message").Count(&grp).Error - _ = db.Table("private_message").Where("status = ?", msgentity.StatusRecalled).Count(&revokedPriv).Error - _ = db.Table("group_message").Where("status = ?", msgentity.StatusRecalled).Count(&revokedGrp).Error + _ = db.Table("t_private_message").Count(&priv).Error + _ = db.Table("t_group_message").Count(&grp).Error + _ = db.Table("t_private_message").Where("status = ?", msgentity.StatusRecalled).Count(&revokedPriv).Error + _ = db.Table("t_group_message").Where("status = ?", msgentity.StatusRecalled).Count(&revokedGrp).Error out.MessageCount = priv + grp out.RevokedCount = revokedPriv + revokedGrp - _ = db.Table("conversations").Count(&out.ConversationCount).Error - _ = db.Table("`groups`").Where("status = ?", 1).Count(&out.GroupCount).Error + _ = db.Table("t_conversations").Count(&out.ConversationCount).Error + _ = db.Table("`t_groups`").Where("status = ?", 1).Count(&out.GroupCount).Error return out, nil } @@ -33,10 +33,10 @@ func (m *Repo) ListRecentMessages(ctx context.Context, fetchLimit int) ([]Messag } sql := ` SELECT id, conversation_id, sender_id, receiver_id, 0 AS group_id, client_msg_id, message_type, content, status, created_at, 'private' AS chat_type -FROM private_message +FROM t_private_message UNION ALL SELECT id, conversation_id, sender_id, 0 AS receiver_id, group_id, client_msg_id, message_type, content, status, created_at, 'group' AS chat_type -FROM group_message` +FROM t_group_message` type scanRow struct { ID int64 `gorm:"column:id"` ConversationID int64 `gorm:"column:conversation_id"` @@ -87,10 +87,10 @@ func (m *Repo) ListUserConversations(ctx context.Context, userID int64) ([]Conve SELECT c.id, c.type, c.last_msg_id, c.last_msg_at, COALESCE(p.user_small, 0) AS user_small, COALESCE(p.user_big, 0) AS user_big, COALESCE(g.id, 0) AS group_id, COALESCE(g.name, '') AS group_name -FROM conversation_members cm -INNER JOIN conversations c ON c.id = cm.conversation_id -LEFT JOIN p2p_conversations p ON p.conversation_id = c.id -LEFT JOIN `+"`groups`"+` g ON g.conversation_id = c.id +FROM t_conversation_members cm +INNER JOIN t_conversations c ON c.id = cm.conversation_id +LEFT JOIN t_p2p_conversations p ON p.conversation_id = c.id +LEFT JOIN `+"`t_groups`"+` g ON g.conversation_id = c.id WHERE cm.user_id = ? ORDER BY c.last_msg_at DESC LIMIT 200`, userID).Scan(&rows).Error @@ -127,7 +127,7 @@ func (m *Repo) ListGroupMessages(ctx context.Context, groupID int64, limit int) var rows []scanRow err = db.Raw(` SELECT id, conversation_id, sender_id, group_id, client_msg_id, message_type, content, status, created_at, 'group' AS chat_type -FROM group_message WHERE group_id = ? ORDER BY created_at DESC LIMIT ?`, groupID, limit).Scan(&rows).Error +FROM t_group_message WHERE group_id = ? ORDER BY created_at DESC LIMIT ?`, groupID, limit).Scan(&rows).Error if err != nil { return nil, mapDBErr(err) } diff --git a/internal/module/admin/model/users.go b/internal/module/admin/model/users.go index c13378d..d4b61fa 100644 --- a/internal/module/admin/model/users.go +++ b/internal/module/admin/model/users.go @@ -14,7 +14,7 @@ func (m *Repo) ListUsers(ctx context.Context, emailLike string, page, size int) if err != nil { return nil, 0, err } - base := db.Table("users AS u").Joins("LEFT JOIN user_emails e ON e.user_id = u.id") + base := db.Table("t_users AS u").Joins("LEFT JOIN t_user_emails e ON e.user_id = u.id") emailLike = strings.TrimSpace(emailLike) if emailLike != "" { base = base.Where("e.email LIKE ?", "%"+emailLike+"%") @@ -30,8 +30,8 @@ func (m *Repo) ListUsers(ctx context.Context, emailLike string, page, size int) const userListSelect = `u.id, u.spark_id, u.nickname, u.avatar, u.status, u.last_active_at, u.created_at, COALESCE(e.email,'') AS email, - COALESCE((SELECT d.device_id FROM user_devices d WHERE d.user_id = u.id ORDER BY d.last_login_at DESC LIMIT 1), 0) AS device_id, - COALESCE((SELECT d.platform FROM user_devices d WHERE d.user_id = u.id ORDER BY d.last_login_at DESC LIMIT 1), '') AS platform` + COALESCE((SELECT d.device_id FROM t_user_devices d WHERE d.user_id = u.id ORDER BY d.last_login_at DESC LIMIT 1), 0) AS device_id, + COALESCE((SELECT CAST(dev.device_type AS CHAR) FROM t_user_devices d INNER JOIN t_devices dev ON dev.device_id = d.device_id WHERE d.user_id = u.id ORDER BY d.last_login_at DESC LIMIT 1), '') AS platform` func (m *Repo) UsersByEmail(ctx context.Context, email string) ([]UserRow, error) { db, err := m.session(ctx) @@ -42,10 +42,10 @@ func (m *Repo) UsersByEmail(ctx context.Context, email string) ([]UserRow, error err = db.Raw(` SELECT u.id, u.spark_id, u.nickname, u.avatar, u.status, u.last_active_at, u.created_at, e.email, - COALESCE((SELECT d.device_id FROM user_devices d WHERE d.user_id = u.id ORDER BY d.last_login_at DESC LIMIT 1), 0) AS device_id, - COALESCE((SELECT d.platform FROM user_devices d WHERE d.user_id = u.id ORDER BY d.last_login_at DESC LIMIT 1), '') AS platform -FROM user_emails e -INNER JOIN users u ON u.id = e.user_id + COALESCE((SELECT d.device_id FROM t_user_devices d WHERE d.user_id = u.id ORDER BY d.last_login_at DESC LIMIT 1), 0) AS device_id, + COALESCE((SELECT CAST(dev.device_type AS CHAR) FROM t_user_devices d INNER JOIN t_devices dev ON dev.device_id = d.device_id WHERE d.user_id = u.id ORDER BY d.last_login_at DESC LIMIT 1), '') AS platform +FROM t_user_emails e +INNER JOIN t_users u ON u.id = e.user_id WHERE e.email = ?`, email).Scan(&rows).Error if err != nil { return nil, mapDBErr(err) @@ -62,10 +62,10 @@ func (m *Repo) UserByID(ctx context.Context, id int64) (*UserRow, error) { err = db.Raw(` SELECT u.id, u.spark_id, u.nickname, u.avatar, u.status, u.last_active_at, u.created_at, COALESCE(e.email,'') AS email, - COALESCE((SELECT d.device_id FROM user_devices d WHERE d.user_id = u.id ORDER BY d.last_login_at DESC LIMIT 1), 0) AS device_id, - COALESCE((SELECT d.platform FROM user_devices d WHERE d.user_id = u.id ORDER BY d.last_login_at DESC LIMIT 1), '') AS platform -FROM users u -LEFT JOIN user_emails e ON e.user_id = u.id + COALESCE((SELECT d.device_id FROM t_user_devices d WHERE d.user_id = u.id ORDER BY d.last_login_at DESC LIMIT 1), 0) AS device_id, + COALESCE((SELECT CAST(dev.device_type AS CHAR) FROM t_user_devices d INNER JOIN t_devices dev ON dev.device_id = d.device_id WHERE d.user_id = u.id ORDER BY d.last_login_at DESC LIMIT 1), '') AS platform +FROM t_users u +LEFT JOIN t_user_emails e ON e.user_id = u.id WHERE u.id = ?`, id).Scan(&rows).Error if err != nil { return nil, mapDBErr(err) @@ -86,8 +86,8 @@ func (m *Repo) UsersByNickname(ctx context.Context, nickname string) ([]UserRow, err = db.Raw(` SELECT u.id, u.spark_id, u.nickname, u.avatar, u.status, u.last_active_at, u.created_at, COALESCE(e.email,'') AS email, 0 AS device_id, '' AS platform -FROM users u -LEFT JOIN user_emails e ON e.user_id = u.id +FROM t_users u +LEFT JOIN t_user_emails e ON e.user_id = u.id WHERE u.nickname LIKE ? ORDER BY u.id DESC LIMIT 50`, "%"+strings.TrimSpace(nickname)+"%").Scan(&rows).Error if err != nil { @@ -104,10 +104,11 @@ func (m *Repo) UsersByDevice(ctx context.Context, deviceID string, deviceIDNum u var rows []userScanRow err = db.Raw(` SELECT u.id, u.spark_id, u.nickname, u.avatar, u.status, u.last_active_at, u.created_at, - COALESCE(e.email,'') AS email, d.device_id, d.platform -FROM user_devices d -INNER JOIN users u ON u.id = d.user_id -LEFT JOIN user_emails e ON e.user_id = u.id + COALESCE(e.email,'') AS email, d.device_id, CAST(dev.device_type AS CHAR) AS platform +FROM t_user_devices d +INNER JOIN t_devices dev ON dev.device_id = d.device_id +INNER JOIN t_users u ON u.id = d.user_id +LEFT JOIN t_user_emails e ON e.user_id = u.id WHERE CAST(d.device_id AS CHAR) = ? OR d.device_id = ? ORDER BY d.last_login_at DESC LIMIT 50`, deviceID, deviceIDNum).Scan(&rows).Error if err != nil { @@ -124,11 +125,12 @@ func (m *Repo) UsersByIP(ctx context.Context, ip string) ([]UserRow, error) { var rows []userScanRow err = db.Raw(` SELECT DISTINCT u.id, u.spark_id, u.nickname, u.avatar, u.status, u.last_active_at, u.created_at, - COALESCE(e.email,'') AS email, d.device_id, d.platform -FROM user_devices d -INNER JOIN users u ON u.id = d.user_id -LEFT JOIN user_emails e ON e.user_id = u.id -WHERE d.last_ip = ? + COALESCE(e.email,'') AS email, d.device_id, CAST(dev.device_type AS CHAR) AS platform +FROM t_user_devices d +INNER JOIN t_devices dev ON dev.device_id = d.device_id +INNER JOIN t_users u ON u.id = d.user_id +LEFT JOIN t_user_emails e ON e.user_id = u.id +WHERE dev.last_client_ip = ? ORDER BY u.id DESC LIMIT 100`, ip).Scan(&rows).Error if err != nil { return nil, mapDBErr(err) @@ -142,8 +144,8 @@ func (m *Repo) SetUserStatusByEmail(ctx context.Context, email string, status us return err } res := db.Exec(` -UPDATE users u -INNER JOIN user_emails e ON e.user_id = u.id +UPDATE t_users u +INNER JOIN t_user_emails e ON e.user_id = u.id SET u.status = ?, u.updated_at = ? WHERE e.email = ?`, int(status), time.Now(), email) if res.Error != nil { @@ -161,8 +163,8 @@ func (m *Repo) SetNicknameByEmail(ctx context.Context, email, nickname string) e return err } res := db.Exec(` -UPDATE users u -INNER JOIN user_emails e ON e.user_id = u.id +UPDATE t_users u +INNER JOIN t_user_emails e ON e.user_id = u.id SET u.nickname = ?, u.updated_at = ? WHERE e.email = ?`, nickname, time.Now(), email) if res.Error != nil { @@ -180,8 +182,8 @@ func (m *Repo) ClearAvatarByEmail(ctx context.Context, email string) error { return err } res := db.Exec(` -UPDATE users u -INNER JOIN user_emails e ON e.user_id = u.id +UPDATE t_users u +INNER JOIN t_user_emails e ON e.user_id = u.id SET u.avatar = '', u.updated_at = ? WHERE e.email = ?`, time.Now(), email) if res.Error != nil { @@ -210,10 +212,11 @@ func (m *Repo) SameIPRank(ctx context.Context, limit int) ([]SameIPRankRow, erro DeviceCount int64 `gorm:"column:device_count"` } err = db.Raw(` -SELECT last_ip AS ip, COUNT(DISTINCT user_id) AS user_count, COUNT(*) AS device_count -FROM user_devices -WHERE last_ip IS NOT NULL AND last_ip <> '' AND last_ip NOT LIKE '127.%' AND last_ip <> '::1' -GROUP BY last_ip +SELECT dev.last_client_ip AS ip, COUNT(DISTINCT d.user_id) AS user_count, COUNT(*) AS device_count +FROM t_user_devices d +INNER JOIN t_devices dev ON dev.device_id = d.device_id +WHERE dev.last_client_ip IS NOT NULL AND dev.last_client_ip <> '' AND dev.last_client_ip NOT LIKE '127.%' AND dev.last_client_ip <> '::1' +GROUP BY dev.last_client_ip ORDER BY user_count DESC LIMIT ?`, limit).Scan(&rows).Error if err != nil { @@ -232,7 +235,7 @@ func (m *Repo) LookupUserIDByEmail(ctx context.Context, email string) (int64, er return 0, err } var id int64 - err = db.Table("user_emails").Select("user_id").Where("email = ?", email).Scan(&id).Error + err = db.Table("t_user_emails").Select("user_id").Where("email = ?", email).Scan(&id).Error return id, mapDBErr(err) } diff --git a/internal/module/conversation/model/conversation.go b/internal/module/conversation/model/conversation.go index e071606..2e37d76 100644 --- a/internal/module/conversation/model/conversation.go +++ b/internal/module/conversation/model/conversation.go @@ -12,4 +12,4 @@ type Conversation struct { CreatedAt time.Time `gorm:"column:created_at;comment:会话创建时间"` } -func (Conversation) TableName() string { return "conversations" } +func (Conversation) TableName() string { return "t_conversations" } diff --git a/internal/module/conversation/model/conversation_member.go b/internal/module/conversation/model/conversation_member.go index ad0d414..98a0cab 100644 --- a/internal/module/conversation/model/conversation_member.go +++ b/internal/module/conversation/model/conversation_member.go @@ -18,7 +18,7 @@ type ConversationMember struct { Muted int `gorm:"column:muted;comment:0=未静音 1=免打扰"` } -func (ConversationMember) TableName() string { return "conversation_members" } +func (ConversationMember) TableName() string { return "t_conversation_members" } func (r *ConversationMember) entity() *entity.Member { if r == nil { diff --git a/internal/module/conversation/model/p2p_conversation.go b/internal/module/conversation/model/p2p_conversation.go index b8efb12..f6eac4b 100644 --- a/internal/module/conversation/model/p2p_conversation.go +++ b/internal/module/conversation/model/p2p_conversation.go @@ -8,4 +8,4 @@ type P2PConversation struct { ConversationID int64 `gorm:"column:conversation_id;comment:对应 conversations.id"` } -func (P2PConversation) TableName() string { return "p2p_conversations" } +func (P2PConversation) TableName() string { return "t_p2p_conversations" } diff --git a/internal/module/device/model/registry.go b/internal/module/device/model/registry.go index 9272cfa..3e69cab 100644 --- a/internal/module/device/model/registry.go +++ b/internal/module/device/model/registry.go @@ -25,7 +25,7 @@ type DeviceRow struct { UpdatedAt time.Time `gorm:"column:updated_at;comment:最近 touch"` } -func (DeviceRow) TableName() string { return "devices" } +func (DeviceRow) TableName() string { return "t_devices" } type RegistryRepo struct { gdb *gorm.DB diff --git a/internal/module/favorite/model/favorite.go b/internal/module/favorite/model/favorite.go index 247860a..66b15a6 100644 --- a/internal/module/favorite/model/favorite.go +++ b/internal/module/favorite/model/favorite.go @@ -17,7 +17,7 @@ type Favorite struct { CreatedAt time.Time `gorm:"column:created_at;comment:收藏时间"` } -func (Favorite) TableName() string { return "favorites" } +func (Favorite) TableName() string { return "t_favorites" } func (r *Favorite) Entity() *entity.Favorite { if r == nil { diff --git a/internal/module/friend/model/friend_relation.go b/internal/module/friend/model/friend_relation.go index 207f38d..da3b83d 100644 --- a/internal/module/friend/model/friend_relation.go +++ b/internal/module/friend/model/friend_relation.go @@ -25,7 +25,7 @@ type FriendRelation struct { UpdatedAt time.Time `gorm:"column:updated_at;comment:最近更新时间"` } -func (FriendRelation) TableName() string { return "friend_relations" } +func (FriendRelation) TableName() string { return "t_friend_relations" } func (r *FriendRelation) entity() *entity.Relation { if r == nil { diff --git a/internal/module/friend/model/friend_report.go b/internal/module/friend/model/friend_report.go index 4d258ac..a404338 100644 --- a/internal/module/friend/model/friend_report.go +++ b/internal/module/friend/model/friend_report.go @@ -18,7 +18,7 @@ type FriendReport struct { CreatedAt time.Time `gorm:"column:created_at;comment:投诉时间"` } -func (FriendReport) TableName() string { return "friend_reports" } +func (FriendReport) TableName() string { return "t_friend_reports" } func (m *Repo) CreateReport(ctx context.Context, r *entity.Report) error { if r == nil || r.UserID <= 0 || r.TargetID <= 0 { diff --git a/internal/module/friend/model/friend_request.go b/internal/module/friend/model/friend_request.go index eeee5d3..004de8d 100644 --- a/internal/module/friend/model/friend_request.go +++ b/internal/module/friend/model/friend_request.go @@ -24,7 +24,7 @@ type FriendRequest struct { UpdatedAt time.Time `gorm:"column:updated_at;comment:最近一次申请或处理时间"` } -func (FriendRequest) TableName() string { return "friend_requests" } +func (FriendRequest) TableName() string { return "t_friend_requests" } func (r *FriendRequest) entity() *entity.Request { if r == nil { diff --git a/internal/module/group/model/find.go b/internal/module/group/model/find.go index e1c7aab..1b75154 100644 --- a/internal/module/group/model/find.go +++ b/internal/module/group/model/find.go @@ -17,7 +17,7 @@ func (m *Repo) FindByOwnerAndName(ctx context.Context, ownerID int64, name strin return nil, err } var row Group - err = db.Table("`groups`"). + err = db.Table("`t_groups`"). Where("owner_id = ? AND name = ? AND status = ?", ownerID, name, entity.StatusActive). Order("id ASC").Limit(1).Take(&row).Error if err != nil { diff --git a/internal/module/group/model/group.go b/internal/module/group/model/group.go index f2d7309..7474569 100644 --- a/internal/module/group/model/group.go +++ b/internal/module/group/model/group.go @@ -8,10 +8,10 @@ import ( "spark-server/internal/pkg/errs" ) -// Group maps table groups. +// Group maps table t_groups. type Group struct { ID int64 `gorm:"column:id;primaryKey;autoIncrement;comment:群号,表内自增,对外群 ID"` - ConversationID int64 `gorm:"column:conversation_id;uniqueIndex;comment:对应 conversations.id(Snowflake),发消息与同步用"` + ConversationID int64 `gorm:"column:conversation_id;uniqueIndex;comment:对应 t_conversations.id(Snowflake),发消息与同步用"` Name string `gorm:"column:name;comment:群名称"` Avatar string `gorm:"column:avatar;comment:群头像对象存储 key,空表示未设置"` Announcement string `gorm:"column:announcement;comment:群公告,仅群主/管理员可改"` @@ -23,7 +23,7 @@ type Group struct { UpdatedAt time.Time `gorm:"column:updated_at;comment:资料或成员变更时间"` } -func (Group) TableName() string { return "groups" } +func (Group) TableName() string { return "t_groups" } func (r *Group) entity() *entity.Group { if r == nil { @@ -98,8 +98,8 @@ func (m *Repo) ListByUser(ctx context.Context, userID int64, limit int) ([]*enti } limit = entity.ClampLimit(limit) var rows []Group - err = db.Table("`groups` AS g").Select("g.*"). - Joins("INNER JOIN group_members m ON m.group_id = g.id"). + err = db.Table("`t_groups` AS g").Select("g.*"). + Joins("INNER JOIN t_group_members m ON m.group_id = g.id"). Where("m.user_id = ? AND g.status = ?", userID, entity.StatusActive). Order("g.updated_at DESC").Limit(limit).Find(&rows).Error if err != nil { @@ -123,8 +123,8 @@ func (m *Repo) ListAllActiveByUser(ctx context.Context, userID int64) ([]*entity return nil, err } var rows []Group - err = db.Table("`groups` AS g").Select("g.*"). - Joins("INNER JOIN group_members m ON m.group_id = g.id"). + err = db.Table("`t_groups` AS g").Select("g.*"). + Joins("INNER JOIN t_group_members m ON m.group_id = g.id"). Where("m.user_id = ? AND g.status = ?", userID, entity.StatusActive). Order("g.updated_at DESC").Limit(purgeListCap).Find(&rows).Error if err != nil { @@ -166,7 +166,7 @@ func (m *Repo) UpdateLastMsg(ctx context.Context, conversationID, msgID, atMS in if err != nil { return err } - res := db.Table("conversations").Where("id = ?", conversationID).Updates(map[string]any{ + res := db.Table("t_conversations").Where("id = ?", conversationID).Updates(map[string]any{ "last_msg_id": msgID, "last_msg_at": msTime(atMS), }) diff --git a/internal/module/group/model/group_member.go b/internal/module/group/model/group_member.go index 696ad9b..9f02274 100644 --- a/internal/module/group/model/group_member.go +++ b/internal/module/group/model/group_member.go @@ -20,7 +20,7 @@ type GroupMember struct { JoinedAt time.Time `gorm:"column:joined_at;comment:入群时间"` } -func (GroupMember) TableName() string { return "group_members" } +func (GroupMember) TableName() string { return "t_group_members" } func (r *GroupMember) entity() *entity.Member { if r == nil { diff --git a/internal/module/message/model/message_delete.go b/internal/module/message/model/message_delete.go index 147262b..a2f1994 100644 --- a/internal/module/message/model/message_delete.go +++ b/internal/module/message/model/message_delete.go @@ -11,4 +11,4 @@ type MessageDelete struct { CreatedAt time.Time `gorm:"column:created_at;comment:删除时间"` } -func (MessageDelete) TableName() string { return "message_deletes" } +func (MessageDelete) TableName() string { return "t_message_deletes" } diff --git a/internal/module/message/model/repo.go b/internal/module/message/model/repo.go index 6f707d8..b665422 100644 --- a/internal/module/message/model/repo.go +++ b/internal/module/message/model/repo.go @@ -13,7 +13,7 @@ import ( "spark-server/internal/pkg/errs" ) -// Repo is MySQL persistence for private_message and group_message. +// Repo is MySQL persistence for t_private_message and t_group_message. type Repo struct { gdb *gorm.DB } @@ -45,7 +45,7 @@ func mapDBErr(err error) error { func (m *Repo) lookupKind(db *gorm.DB, conversationID int64) (entity.Kind, error) { var row struct{ Type int } - if err := db.Table("conversations").Select("type").Where("id = ?", conversationID).Take(&row).Error; err != nil { + if err := db.Table("t_conversations").Select("type").Where("id = ?", conversationID).Take(&row).Error; err != nil { return 0, mapDBErr(err) } if conventity.Type(row.Type) == conventity.TypeGroup { @@ -154,7 +154,7 @@ func (m *Repo) CreateAndBump(ctx context.Context, message *entity.Message) error if err := m.insertBody(tx, message, row); err != nil { return err } - res := tx.Table("conversations").Where("id = ?", message.ConversationID).Updates(map[string]any{ + res := tx.Table("t_conversations").Where("id = ?", message.ConversationID).Updates(map[string]any{ "last_msg_id": message.ID, "last_msg_at": row.CreatedAt, }) @@ -197,7 +197,7 @@ func (m *Repo) fillGroupID(db *gorm.DB, message *entity.Message) error { return nil } var gid int64 - if err := db.Table("`groups`").Select("id").Where("conversation_id = ?", message.ConversationID).Scan(&gid).Error; err != nil { + if err := db.Table("`t_groups`").Select("id").Where("conversation_id = ?", message.ConversationID).Scan(&gid).Error; err != nil { return mapDBErr(err) } if gid <= 0 { @@ -212,7 +212,7 @@ func (m *Repo) fillReceiverID(db *gorm.DB, message *entity.Message) error { return nil } var peer int64 - err := db.Table("conversation_members").Select("user_id"). + err := db.Table("t_conversation_members").Select("user_id"). Where("conversation_id = ? AND user_id <> ?", message.ConversationID, message.SenderID). Limit(1).Scan(&peer).Error if err != nil { diff --git a/internal/module/message/model/row.go b/internal/module/message/model/row.go index f39e5fd..15a3fb7 100644 --- a/internal/module/message/model/row.go +++ b/internal/module/message/model/row.go @@ -7,8 +7,8 @@ import ( ) const ( - tablePrivateMessage = "private_message" - tableGroupMessage = "group_message" + tablePrivateMessage = "t_private_message" + tableGroupMessage = "t_group_message" ) // MessageRow is shared columns for private_message and group_message. Must be exported so GORM can embed it. diff --git a/internal/module/moment/model/purge.go b/internal/module/moment/model/purge.go index 0e73b8b..ecf2eac 100644 --- a/internal/module/moment/model/purge.go +++ b/internal/module/moment/model/purge.go @@ -66,16 +66,16 @@ func purgeMomentUser(tx *gorm.DB, userID int64) error { } func bumpOffUserLikes(tx *gorm.DB, userID int64) error { - sql := `UPDATE moment_posts p -INNER JOIN (SELECT post_id, COUNT(*) AS n FROM moment_likes WHERE user_id = ? GROUP BY post_id) x ON p.id = x.post_id + sql := `UPDATE t_moment_posts p +INNER JOIN (SELECT post_id, COUNT(*) AS n FROM t_moment_likes WHERE user_id = ? GROUP BY post_id) x ON p.id = x.post_id SET p.like_count = CASE WHEN p.like_count < x.n THEN 0 ELSE p.like_count - x.n END WHERE p.user_id <> ?` return mapDBErr(tx.Exec(sql, userID, userID).Error) } func bumpOffUserComments(tx *gorm.DB, userID int64) error { - sql := `UPDATE moment_posts p -INNER JOIN (SELECT post_id, COUNT(*) AS n FROM moment_comments WHERE user_id = ? AND status = ? GROUP BY post_id) x ON p.id = x.post_id + sql := `UPDATE t_moment_posts p +INNER JOIN (SELECT post_id, COUNT(*) AS n FROM t_moment_comments WHERE user_id = ? AND status = ? GROUP BY post_id) x ON p.id = x.post_id SET p.comment_count = CASE WHEN p.comment_count < x.n THEN 0 ELSE p.comment_count - x.n END WHERE p.user_id <> ?` return mapDBErr(tx.Exec(sql, userID, entity.StatusNormal, userID).Error) diff --git a/internal/module/moment/model/row.go b/internal/module/moment/model/row.go index e93d704..c5c3bad 100644 --- a/internal/module/moment/model/row.go +++ b/internal/module/moment/model/row.go @@ -24,7 +24,7 @@ type Post struct { CreatedAt time.Time `gorm:"column:created_at;comment:发帖时间,visible_days 按此裁剪"` } -func (Post) TableName() string { return "moment_posts" } +func (Post) TableName() string { return "t_moment_posts" } func (r *Post) Entity() *entity.Post { if r == nil { @@ -61,7 +61,7 @@ type Audience struct { PeerID int64 `gorm:"column:peer_id;comment:白名单能看 / 黑名单不能看 的好友 uid"` } -func (Audience) TableName() string { return "moment_audience" } +func (Audience) TableName() string { return "t_moment_audience" } // Like maps table moment_likes. type Like struct { @@ -71,7 +71,7 @@ type Like struct { CreatedAt time.Time `gorm:"column:created_at;comment:点赞时间"` } -func (Like) TableName() string { return "moment_likes" } +func (Like) TableName() string { return "t_moment_likes" } func (r *Like) Entity() *entity.Like { if r == nil { @@ -92,7 +92,7 @@ type Comment struct { CreatedAt time.Time `gorm:"column:created_at;comment:评论时间"` } -func (Comment) TableName() string { return "moment_comments" } +func (Comment) TableName() string { return "t_moment_comments" } func (r *Comment) Entity() *entity.Comment { if r == nil { @@ -130,7 +130,7 @@ type Notice struct { CreatedAt time.Time `gorm:"column:created_at;comment:通知时间"` } -func (Notice) TableName() string { return "moment_notices" } +func (Notice) TableName() string { return "t_moment_notices" } func (r *Notice) Entity() *entity.Notice { if r == nil { @@ -156,7 +156,7 @@ type Setting struct { UpdatedAt time.Time `gorm:"column:updated_at;comment:最近更新时间"` } -func (Setting) TableName() string { return "moment_settings" } +func (Setting) TableName() string { return "t_moment_settings" } func (r *Setting) Entity() *entity.Settings { if r == nil { @@ -190,7 +190,7 @@ type Hide struct { HideMe bool `gorm:"column:hide_me;comment:1=不让他看"` } -func (Hide) TableName() string { return "moment_hides" } +func (Hide) TableName() string { return "t_moment_hides" } func (r *Hide) Entity() *entity.Hide { if r == nil { diff --git a/internal/module/music/model/repo.go b/internal/module/music/model/repo.go index c21d9ee..86d7681 100644 --- a/internal/module/music/model/repo.go +++ b/internal/module/music/model/repo.go @@ -40,7 +40,7 @@ type trackRow struct { UpdatedAt time.Time `gorm:"column:updated_at"` } -func (trackRow) TableName() string { return "music_tracks" } +func (trackRow) TableName() string { return "t_music_tracks" } type settingRow struct { SettingKey string `gorm:"column:setting_key;primaryKey"` @@ -48,7 +48,7 @@ type settingRow struct { UpdatedAt time.Time `gorm:"column:updated_at"` } -func (settingRow) TableName() string { return "music_settings" } +func (settingRow) TableName() string { return "t_music_settings" } func (r *Repo) ListAll(ctx context.Context) ([]entity.Track, error) { if !r.Ready() { diff --git a/internal/module/square/model/post.go b/internal/module/square/model/post.go index dbfad18..60483bc 100644 --- a/internal/module/square/model/post.go +++ b/internal/module/square/model/post.go @@ -27,7 +27,7 @@ type Post struct { CreatedAt time.Time `gorm:"column:created_at;comment:发帖时间"` } -func (Post) TableName() string { return "square_posts" } +func (Post) TableName() string { return "t_square_posts" } func (r *Post) Entity() *entity.Post { if r == nil { @@ -72,7 +72,7 @@ type Audience struct { PeerID int64 `gorm:"column:peer_id;primaryKey;comment:好友 uid"` } -func (Audience) TableName() string { return "square_audience" } +func (Audience) TableName() string { return "t_square_audience" } // Like maps square_likes. type Like struct { @@ -81,7 +81,7 @@ type Like struct { CreatedAt time.Time `gorm:"column:created_at;comment:点赞时间"` } -func (Like) TableName() string { return "square_likes" } +func (Like) TableName() string { return "t_square_likes" } func (r *Like) Entity() *entity.Like { if r == nil { @@ -102,7 +102,7 @@ type Comment struct { CreatedAt time.Time `gorm:"column:created_at;comment:评论时间"` } -func (Comment) TableName() string { return "square_comments" } +func (Comment) TableName() string { return "t_square_comments" } func (r *Comment) Entity() *entity.Comment { if r == nil { @@ -140,7 +140,7 @@ type Notice struct { CreatedAt time.Time `gorm:"column:created_at;comment:通知时间"` } -func (Notice) TableName() string { return "square_notices" } +func (Notice) TableName() string { return "t_square_notices" } func (r *Notice) Entity() *entity.Notice { if r == nil { @@ -163,7 +163,7 @@ type NoticeState struct { UpdatedAt time.Time `gorm:"column:updated_at;comment:更新时间"` } -func (NoticeState) TableName() string { return "square_notice_state" } +func (NoticeState) TableName() string { return "t_square_notice_state" } func (r *NoticeState) Entity() *entity.NoticeState { if r == nil { diff --git a/internal/module/square/model/purge.go b/internal/module/square/model/purge.go index 877bfab..e121b70 100644 --- a/internal/module/square/model/purge.go +++ b/internal/module/square/model/purge.go @@ -63,16 +63,16 @@ func purgeSquareUser(tx *gorm.DB, userID int64) error { } func bumpOffUserLikes(tx *gorm.DB, userID int64) error { - sql := `UPDATE square_posts p -INNER JOIN (SELECT post_id, COUNT(*) AS n FROM square_likes WHERE user_id = ? GROUP BY post_id) x ON p.id = x.post_id + sql := `UPDATE t_square_posts p +INNER JOIN (SELECT post_id, COUNT(*) AS n FROM t_square_likes WHERE user_id = ? GROUP BY post_id) x ON p.id = x.post_id SET p.like_count = CASE WHEN p.like_count < x.n THEN 0 ELSE p.like_count - x.n END WHERE p.user_id <> ?` return mapDBErr(tx.Exec(sql, userID, userID).Error) } func bumpOffUserComments(tx *gorm.DB, userID int64) error { - sql := `UPDATE square_posts p -INNER JOIN (SELECT post_id, COUNT(*) AS n FROM square_comments WHERE user_id = ? AND status = ? GROUP BY post_id) x ON p.id = x.post_id + sql := `UPDATE t_square_posts p +INNER JOIN (SELECT post_id, COUNT(*) AS n FROM t_square_comments WHERE user_id = ? AND status = ? GROUP BY post_id) x ON p.id = x.post_id SET p.comment_count = CASE WHEN p.comment_count < x.n THEN 0 ELSE p.comment_count - x.n END WHERE p.user_id <> ?` return mapDBErr(tx.Exec(sql, userID, entity.StatusNormal, userID).Error) diff --git a/internal/module/sync/model/device_sync_cursor.go b/internal/module/sync/model/device_sync_cursor.go index 4762288..c03fcf0 100644 --- a/internal/module/sync/model/device_sync_cursor.go +++ b/internal/module/sync/model/device_sync_cursor.go @@ -12,4 +12,4 @@ type DeviceSyncCursor struct { UpdatedAt time.Time `gorm:"column:updated_at;comment:游标更新时间"` } -func (DeviceSyncCursor) TableName() string { return "device_sync_cursors" } +func (DeviceSyncCursor) TableName() string { return "t_device_sync_cursors" } diff --git a/internal/module/sync/model/mailbox_event.go b/internal/module/sync/model/mailbox_event.go index 9d0db18..d363d73 100644 --- a/internal/module/sync/model/mailbox_event.go +++ b/internal/module/sync/model/mailbox_event.go @@ -15,4 +15,4 @@ type MailboxEvent struct { CreatedAt time.Time `gorm:"column:created_at;comment:写入时间"` } -func (MailboxEvent) TableName() string { return "mailbox_events" } +func (MailboxEvent) TableName() string { return "t_mailbox_events" } diff --git a/internal/module/user/model/list.go b/internal/module/user/model/list.go index 637a9e9..902c8a7 100644 --- a/internal/module/user/model/list.go +++ b/internal/module/user/model/list.go @@ -22,9 +22,9 @@ func (m *Repo) ListAccounts(ctx context.Context) ([]Account, error) { User Email string `gorm:"column:email"` } - err = db.Table("users AS u"). + err = db.Table("t_users AS u"). Select("u.*, e.email"). - Joins("INNER JOIN user_emails e ON e.user_id = u.id"). + Joins("INNER JOIN t_user_emails e ON e.user_id = u.id"). Order("u.id ASC"). Find(&rows).Error if err != nil { diff --git a/internal/module/user/model/user.go b/internal/module/user/model/user.go index 0f3349a..f579fed 100644 --- a/internal/module/user/model/user.go +++ b/internal/module/user/model/user.go @@ -24,7 +24,7 @@ type User struct { UpdatedAt time.Time `gorm:"column:updated_at;comment:资料最近更新时间(update_time)"` } -func (User) TableName() string { return "users" } +func (User) TableName() string { return "t_users" } func (r *User) entity() *entity.User { if r == nil { diff --git a/internal/module/user/model/user_delete.go b/internal/module/user/model/user_delete.go index 5a80fdd..14f8e3a 100644 --- a/internal/module/user/model/user_delete.go +++ b/internal/module/user/model/user_delete.go @@ -28,7 +28,7 @@ type UserDelete struct { DeletedAt time.Time `gorm:"column:deleted_at;comment:注销时间"` } -func (UserDelete) TableName() string { return "user_delete" } +func (UserDelete) TableName() string { return "t_user_delete" } func (r *UserDelete) entity() *entity.Deleted { if r == nil { diff --git a/internal/module/user/model/user_device.go b/internal/module/user/model/user_device.go index 30540de..b3921b5 100644 --- a/internal/module/user/model/user_device.go +++ b/internal/module/user/model/user_device.go @@ -18,7 +18,7 @@ type UserDevice struct { CreatedAt time.Time `gorm:"column:created_at;comment:该用户首次在此设备绑定"` } -func (UserDevice) TableName() string { return "user_devices" } +func (UserDevice) TableName() string { return "t_user_devices" } func (row *UserDevice) entity() *entity.UserDeviceLink { if row == nil { diff --git a/internal/module/user/model/user_email.go b/internal/module/user/model/user_email.go index 8b815b8..fcbb3d4 100644 --- a/internal/module/user/model/user_email.go +++ b/internal/module/user/model/user_email.go @@ -17,7 +17,7 @@ type UserEmail struct { CreatedAt time.Time `gorm:"column:created_at;comment:绑定时间"` } -func (UserEmail) TableName() string { return "user_emails" } +func (UserEmail) TableName() string { return "t_user_emails" } func (m *Repo) GetByEmail(ctx context.Context, email string) (*entity.User, error) { db, err := m.session(ctx) diff --git a/internal/module/user/model/user_login_log.go b/internal/module/user/model/user_login_log.go index 51b89f3..7e6ee18 100644 --- a/internal/module/user/model/user_login_log.go +++ b/internal/module/user/model/user_login_log.go @@ -21,7 +21,7 @@ type UserLoginLog struct { CreatedAt time.Time `gorm:"column:created_at;comment:本次登录时间"` } -func (UserLoginLog) TableName() string { return "user_login_logs" } +func (UserLoginLog) TableName() string { return "t_user_login_logs" } func (m *Repo) InsertLoginLog(ctx context.Context, log *entity.LoginLog) error { if log == nil { diff --git a/migrations/0000_table_prefix.sql b/migrations/0000_table_prefix.sql new file mode 100644 index 0000000..6261b00 --- /dev/null +++ b/migrations/0000_table_prefix.sql @@ -0,0 +1,39 @@ +-- Legacy databases: rename unprefixed tables to t_* (must run before 0001+ CREATE t_*). +-- No-op when tables already use t_ prefix (unknown source table → ignorable DDL). + +RENAME TABLE users TO t_users; +RENAME TABLE user_emails TO t_user_emails; +RENAME TABLE user_devices TO t_user_devices; +RENAME TABLE user_login_logs TO t_user_login_logs; +RENAME TABLE user_delete TO t_user_delete; +RENAME TABLE devices TO t_devices; +RENAME TABLE conversations TO t_conversations; +RENAME TABLE p2p_conversations TO t_p2p_conversations; +RENAME TABLE conversation_members TO t_conversation_members; +RENAME TABLE mailbox_events TO t_mailbox_events; +RENAME TABLE device_sync_cursors TO t_device_sync_cursors; +RENAME TABLE messages TO t_messages; +RENAME TABLE private_message TO t_private_message; +RENAME TABLE group_message TO t_group_message; +RENAME TABLE message_deletes TO t_message_deletes; +RENAME TABLE friend_relations TO t_friend_relations; +RENAME TABLE friend_requests TO t_friend_requests; +RENAME TABLE friend_reports TO t_friend_reports; +RENAME TABLE favorites TO t_favorites; +RENAME TABLE `groups` TO `t_groups`; +RENAME TABLE group_members TO t_group_members; +RENAME TABLE moment_posts TO t_moment_posts; +RENAME TABLE moment_audience TO t_moment_audience; +RENAME TABLE moment_likes TO t_moment_likes; +RENAME TABLE moment_comments TO t_moment_comments; +RENAME TABLE moment_notices TO t_moment_notices; +RENAME TABLE moment_settings TO t_moment_settings; +RENAME TABLE moment_hides TO t_moment_hides; +RENAME TABLE square_posts TO t_square_posts; +RENAME TABLE square_audience TO t_square_audience; +RENAME TABLE square_likes TO t_square_likes; +RENAME TABLE square_comments TO t_square_comments; +RENAME TABLE square_notices TO t_square_notices; +RENAME TABLE square_notice_state TO t_square_notice_state; +RENAME TABLE music_tracks TO t_music_tracks; +RENAME TABLE music_settings TO t_music_settings; diff --git a/migrations/0001_init.sql b/migrations/0001_init.sql index db65a27..84bd848 100644 --- a/migrations/0001_init.sql +++ b/migrations/0001_init.sql @@ -1,6 +1,6 @@ -- Spark IM V3 initial schema. Message body lives in MySQL; dialog list lives in Redis. -CREATE TABLE IF NOT EXISTS conversations ( +CREATE TABLE IF NOT EXISTS t_conversations ( id BIGINT PRIMARY KEY COMMENT 'Snowflake 会话 id,时间有序主键', type TINYINT NOT NULL COMMENT '会话类型:1=单聊 2=群聊', last_msg_id BIGINT NOT NULL DEFAULT 0 COMMENT '最新消息 Snowflake id,0 表示尚无消息', @@ -8,15 +8,15 @@ CREATE TABLE IF NOT EXISTS conversations ( created_at DATETIME(3) NOT NULL COMMENT '会话创建时间' ) COMMENT='会话。单聊/群聊共用一张表;列表与未读在 Redis,不在此表热更新'; -CREATE TABLE IF NOT EXISTS p2p_conversations ( +CREATE TABLE IF NOT EXISTS t_p2p_conversations ( user_small BIGINT NOT NULL COMMENT '两人中较小的 user_id,保证同一对用户只有一行', user_big BIGINT NOT NULL COMMENT '两人中较大的 user_id', - conversation_id BIGINT NOT NULL COMMENT '对应 conversations.id', + conversation_id BIGINT NOT NULL COMMENT '对应 t_conversations.id', PRIMARY KEY (user_small, user_big), UNIQUE KEY uk_conversation (conversation_id) ) COMMENT='单聊唯一索引。按 (较小 uid, 较大 uid) 定位会话,避免 A-B / B-A 两条记录'; -CREATE TABLE IF NOT EXISTS conversation_members ( +CREATE TABLE IF NOT EXISTS t_conversation_members ( conversation_id BIGINT NOT NULL COMMENT '会话 id', user_id BIGINT NOT NULL COMMENT '成员 user_id', last_read_msg_id BIGINT NOT NULL DEFAULT 0 COMMENT '该成员已读到的最大消息 id,未读真相;Redis 丢了可从此重建', @@ -26,7 +26,7 @@ CREATE TABLE IF NOT EXISTS conversation_members ( KEY idx_user_id (user_id) ) COMMENT='会话成员。热路径会话列表不扫此表;last_read_msg_id 是已读持久化'; -CREATE TABLE IF NOT EXISTS messages ( +CREATE TABLE IF NOT EXISTS t_messages ( id BIGINT PRIMARY KEY COMMENT 'Snowflake MsgId,主键、排序键、同步游标', conversation_id BIGINT NOT NULL COMMENT '所属会话 id', sender_id BIGINT NOT NULL COMMENT '发送者 user_id', @@ -39,7 +39,7 @@ CREATE TABLE IF NOT EXISTS messages ( KEY idx_conversation_id (conversation_id, id) ) COMMENT='消息正文。PK=MsgId;content 为序列化 BLOB,不存媒体二进制'; -CREATE TABLE IF NOT EXISTS mailbox_events ( +CREATE TABLE IF NOT EXISTS t_mailbox_events ( id BIGINT PRIMARY KEY COMMENT 'Snowflake 事件 id', user_id BIGINT NOT NULL COMMENT '接收用户', device_id BIGINT NOT NULL COMMENT '目标设备;0 表示该用户全部设备', @@ -52,10 +52,10 @@ CREATE TABLE IF NOT EXISTS mailbox_events ( KEY idx_user_device (user_id, device_id, seq) ) COMMENT='失败邮箱与控制事件。成功在线推送的新消息不写此表'; -CREATE TABLE IF NOT EXISTS device_sync_cursors ( +CREATE TABLE IF NOT EXISTS t_device_sync_cursors ( user_id BIGINT NOT NULL COMMENT '用户 id', device_id BIGINT NOT NULL COMMENT '设备 id', - mailbox_seq BIGINT NOT NULL DEFAULT 0 COMMENT '该设备已同步到的 mailbox_events.seq', + mailbox_seq BIGINT NOT NULL DEFAULT 0 COMMENT '该设备已同步到的 t_mailbox_events.seq', dialog_score BIGINT NOT NULL DEFAULT 0 COMMENT '会话列表 Redis ZSET 游标', updated_at DATETIME(3) NOT NULL COMMENT '游标更新时间', PRIMARY KEY (user_id, device_id) diff --git a/migrations/0002_users.sql b/migrations/0002_users.sql index 27a6b17..60ee9cc 100644 --- a/migrations/0002_users.sql +++ b/migrations/0002_users.sql @@ -1,6 +1,6 @@ --- Users: Snowflake PK (not AUTO_INCREMENT), public spark_id, email map, login devices. +-- Users: Snowflake PK (not AUTO_INCREMENT), public spark_id, email map, login t_devices. -CREATE TABLE IF NOT EXISTS users ( +CREATE TABLE IF NOT EXISTS t_users ( id BIGINT PRIMARY KEY COMMENT 'Snowflake 用户 id(uid),时间有序,非自增', spark_id VARCHAR(32) NOT NULL COMMENT '对外展示的账号,用户可改,全局唯一', nickname VARCHAR(64) NOT NULL DEFAULT '' COMMENT '昵称', @@ -14,28 +14,25 @@ CREATE TABLE IF NOT EXISTS users ( created_at DATETIME(3) NOT NULL COMMENT '注册时间(create_time)', updated_at DATETIME(3) NOT NULL COMMENT '资料最近更新时间(update_time)', UNIQUE KEY uk_spark_id (spark_id) -) COMMENT='用户账号。主键 Snowflake 即 uid;登录身份在 user_emails,设备在 user_devices'; +) COMMENT='用户账号。主键 Snowflake 即 uid;登录身份在 t_user_emails,设备在 t_user_devices'; -CREATE TABLE IF NOT EXISTS user_emails ( +CREATE TABLE IF NOT EXISTS t_user_emails ( email VARCHAR(255) NOT NULL COMMENT '规范化后的小写邮箱,登录账号', - user_id BIGINT NOT NULL COMMENT '绑定的 users.id,一对一', + user_id BIGINT NOT NULL COMMENT '绑定的 t_users.id,一对一', created_at DATETIME(3) NOT NULL COMMENT '绑定时间', PRIMARY KEY (email), UNIQUE KEY uk_user_id (user_id) -) COMMENT='邮箱与用户的一对一映射。登录用邮箱查此表再读 users'; +) COMMENT='邮箱与用户的一对一映射。登录用邮箱查此表再读 t_users'; -CREATE TABLE IF NOT EXISTS user_devices ( - id BIGINT NOT NULL AUTO_INCREMENT COMMENT '行 id,表内自增,仅内部用;业务唯一键是 (user_id, device_id)', - user_id BIGINT NOT NULL COMMENT '所属用户', - device_id BIGINT UNSIGNED NOT NULL COMMENT '客户端设备 id,写入 JWT did', - platform VARCHAR(32) NOT NULL DEFAULT '' COMMENT 'ios/android/web 等', - device_name VARCHAR(128) NOT NULL DEFAULT '' COMMENT '设备展示名', - app_version VARCHAR(32) NOT NULL DEFAULT '' COMMENT '最近一次登录的客户端版本', - language VARCHAR(16) NOT NULL DEFAULT '' COMMENT '最近一次登录语言,如 zh-CN', - last_ip VARCHAR(64) NOT NULL DEFAULT '' COMMENT '最近一次登录的 PROXY RealIP,禁止用环回地址', - last_login_at DATETIME(3) NOT NULL COMMENT '最近一次登录时间', - created_at DATETIME(3) NOT NULL COMMENT '该设备首次登录时间', +CREATE TABLE IF NOT EXISTS t_user_devices ( + id BIGINT NOT NULL AUTO_INCREMENT COMMENT '行 id,表内自增,仅内部用;业务唯一键是 (user_id, device_id)', + user_id BIGINT NOT NULL COMMENT '所属用户', + device_id BIGINT UNSIGNED NOT NULL COMMENT 't_devices.device_id,JWT did', + last_login_at DATETIME(3) NOT NULL COMMENT '该用户在此设备最近登录成功', + last_active_at DATETIME(3) NULL COMMENT '该用户在此设备最近活跃', + created_at DATETIME(3) NOT NULL COMMENT '该用户首次在此设备绑定', PRIMARY KEY (id), UNIQUE KEY uk_user_device (user_id, device_id), - KEY idx_user_id (user_id) -) COMMENT='登录过的设备。同 user+device 覆盖更新;踢人按 device_id'; + KEY idx_user_id (user_id), + KEY idx_device_id (device_id) +) COMMENT='用户与设备关系;设备属性见 t_devices,当前 App 见 JWT aid'; diff --git a/migrations/0003_table_comments.sql b/migrations/0003_table_comments.sql index 13f5137..552dc94 100644 --- a/migrations/0003_table_comments.sql +++ b/migrations/0003_table_comments.sql @@ -1,29 +1,29 @@ -- Add table/column comments for databases created before 0001/0002 carried COMMENT clauses. -ALTER TABLE conversations COMMENT = '会话。单聊/群聊共用一张表;列表与未读在 Redis,不在此表热更新'; -ALTER TABLE conversations +ALTER TABLE t_conversations COMMENT = '会话。单聊/群聊共用一张表;列表与未读在 Redis,不在此表热更新'; +ALTER TABLE t_conversations MODIFY COLUMN id BIGINT NOT NULL COMMENT 'Snowflake 会话 id,时间有序主键', MODIFY COLUMN type TINYINT NOT NULL COMMENT '会话类型:1=单聊 2=群聊', MODIFY COLUMN last_msg_id BIGINT NOT NULL DEFAULT 0 COMMENT '最新消息 Snowflake id,0 表示尚无消息', MODIFY COLUMN last_msg_at DATETIME(3) NOT NULL COMMENT '最新消息时间(毫秒精度)', MODIFY COLUMN created_at DATETIME(3) NOT NULL COMMENT '会话创建时间'; -ALTER TABLE p2p_conversations COMMENT = '单聊唯一索引。按 (较小 uid, 较大 uid) 定位会话,避免 A-B / B-A 两条记录'; -ALTER TABLE p2p_conversations +ALTER TABLE t_p2p_conversations COMMENT = '单聊唯一索引。按 (较小 uid, 较大 uid) 定位会话,避免 A-B / B-A 两条记录'; +ALTER TABLE t_p2p_conversations MODIFY COLUMN user_small BIGINT NOT NULL COMMENT '两人中较小的 user_id,保证同一对用户只有一行', MODIFY COLUMN user_big BIGINT NOT NULL COMMENT '两人中较大的 user_id', - MODIFY COLUMN conversation_id BIGINT NOT NULL COMMENT '对应 conversations.id'; + MODIFY COLUMN conversation_id BIGINT NOT NULL COMMENT '对应 t_conversations.id'; -ALTER TABLE conversation_members COMMENT = '会话成员。热路径会话列表不扫此表;last_read_msg_id 是已读持久化'; -ALTER TABLE conversation_members +ALTER TABLE t_conversation_members COMMENT = '会话成员。热路径会话列表不扫此表;last_read_msg_id 是已读持久化'; +ALTER TABLE t_conversation_members MODIFY COLUMN conversation_id BIGINT NOT NULL COMMENT '会话 id', MODIFY COLUMN user_id BIGINT NOT NULL COMMENT '成员 user_id', MODIFY COLUMN last_read_msg_id BIGINT NOT NULL DEFAULT 0 COMMENT '该成员已读到的最大消息 id,未读真相;Redis 丢了可从此重建', MODIFY COLUMN joined_at DATETIME(3) NOT NULL COMMENT '加入会话时间', MODIFY COLUMN muted TINYINT NOT NULL DEFAULT 0 COMMENT '0=未静音 1=免打扰'; -ALTER TABLE messages COMMENT = '消息正文。PK=MsgId;content 为序列化 BLOB,不存媒体二进制'; -ALTER TABLE messages +ALTER TABLE t_messages COMMENT = '消息正文。PK=MsgId;content 为序列化 BLOB,不存媒体二进制'; +ALTER TABLE t_messages MODIFY COLUMN id BIGINT NOT NULL COMMENT 'Snowflake MsgId,主键、排序键、同步游标', MODIFY COLUMN conversation_id BIGINT NOT NULL COMMENT '所属会话 id', MODIFY COLUMN sender_id BIGINT NOT NULL COMMENT '发送者 user_id', @@ -33,8 +33,8 @@ ALTER TABLE messages MODIFY COLUMN status TINYINT NOT NULL DEFAULT 1 COMMENT '1=正常 2=已撤回 3=审核隐藏', MODIFY COLUMN created_at DATETIME(3) NOT NULL COMMENT '服务端入库时间'; -ALTER TABLE mailbox_events COMMENT = '失败邮箱与控制事件。成功在线推送的新消息不写此表'; -ALTER TABLE mailbox_events +ALTER TABLE t_mailbox_events COMMENT = '失败邮箱与控制事件。成功在线推送的新消息不写此表'; +ALTER TABLE t_mailbox_events MODIFY COLUMN id BIGINT NOT NULL COMMENT 'Snowflake 事件 id', MODIFY COLUMN user_id BIGINT NOT NULL COMMENT '接收用户', MODIFY COLUMN device_id BIGINT NOT NULL COMMENT '目标设备;0 表示该用户全部设备', @@ -44,16 +44,16 @@ ALTER TABLE mailbox_events MODIFY COLUMN payload VARBINARY(4096) COMMENT '控制事件载荷(会话 id+消息 id 等),不含消息正文', MODIFY COLUMN created_at DATETIME(3) NOT NULL COMMENT '写入时间'; -ALTER TABLE device_sync_cursors COMMENT = '每设备同步游标。mailbox_seq 对邮箱,dialog_score 对会话列表'; -ALTER TABLE device_sync_cursors +ALTER TABLE t_device_sync_cursors COMMENT = '每设备同步游标。mailbox_seq 对邮箱,dialog_score 对会话列表'; +ALTER TABLE t_device_sync_cursors MODIFY COLUMN user_id BIGINT NOT NULL COMMENT '用户 id', MODIFY COLUMN device_id BIGINT NOT NULL COMMENT '设备 id', - MODIFY COLUMN mailbox_seq BIGINT NOT NULL DEFAULT 0 COMMENT '该设备已同步到的 mailbox_events.seq', + MODIFY COLUMN mailbox_seq BIGINT NOT NULL DEFAULT 0 COMMENT '该设备已同步到的 t_mailbox_events.seq', MODIFY COLUMN dialog_score BIGINT NOT NULL DEFAULT 0 COMMENT '会话列表 Redis ZSET 游标', MODIFY COLUMN updated_at DATETIME(3) NOT NULL COMMENT '游标更新时间'; -ALTER TABLE users COMMENT = '用户账号。主键 Snowflake;登录身份在 user_emails,设备在 user_devices'; -ALTER TABLE users +ALTER TABLE t_users COMMENT = '用户账号。主键 Snowflake;登录身份在 t_user_emails,设备在 t_user_devices'; +ALTER TABLE t_users MODIFY COLUMN id BIGINT NOT NULL COMMENT 'Snowflake 用户 id(uid),时间有序,非自增', MODIFY COLUMN spark_id VARCHAR(32) NOT NULL COMMENT '对外展示的账号,用户可改,全局唯一', MODIFY COLUMN nickname VARCHAR(64) NOT NULL DEFAULT '' COMMENT '昵称', @@ -62,21 +62,17 @@ ALTER TABLE users MODIFY COLUMN created_at DATETIME(3) NOT NULL COMMENT '注册时间', MODIFY COLUMN updated_at DATETIME(3) NOT NULL COMMENT '资料最近更新时间'; -ALTER TABLE user_emails COMMENT = '邮箱与用户的一对一映射。登录用邮箱查此表再读 users'; -ALTER TABLE user_emails +ALTER TABLE t_user_emails COMMENT = '邮箱与用户的一对一映射。登录用邮箱查此表再读 t_users'; +ALTER TABLE t_user_emails MODIFY COLUMN email VARCHAR(255) NOT NULL COMMENT '规范化后的小写邮箱,登录账号', - MODIFY COLUMN user_id BIGINT NOT NULL COMMENT '绑定的 users.id,一对一', + MODIFY COLUMN user_id BIGINT NOT NULL COMMENT '绑定的 t_users.id,一对一', MODIFY COLUMN created_at DATETIME(3) NOT NULL COMMENT '绑定时间'; -ALTER TABLE user_devices COMMENT = '登录过的设备。同 user+device 覆盖更新;踢人按 device_id'; -ALTER TABLE user_devices +ALTER TABLE t_user_devices COMMENT = '用户与设备关系;设备属性见 t_devices,当前 App 见 JWT aid'; +ALTER TABLE t_user_devices MODIFY COLUMN id BIGINT NOT NULL AUTO_INCREMENT COMMENT '行 id,表内自增,仅内部用;业务唯一键是 (user_id, device_id)', MODIFY COLUMN user_id BIGINT NOT NULL COMMENT '所属用户', - MODIFY COLUMN device_id BIGINT UNSIGNED NOT NULL COMMENT '客户端设备 id,写入 JWT did', - MODIFY COLUMN platform VARCHAR(32) NOT NULL DEFAULT '' COMMENT 'ios/android/web 等', - MODIFY COLUMN device_name VARCHAR(128) NOT NULL DEFAULT '' COMMENT '设备展示名', - MODIFY COLUMN app_version VARCHAR(32) NOT NULL DEFAULT '' COMMENT '最近一次登录的客户端版本', - MODIFY COLUMN language VARCHAR(16) NOT NULL DEFAULT '' COMMENT '最近一次登录语言,如 zh-CN', - MODIFY COLUMN last_ip VARCHAR(64) NOT NULL DEFAULT '' COMMENT '最近一次登录的 PROXY RealIP,禁止用环回地址', - MODIFY COLUMN last_login_at DATETIME(3) NOT NULL COMMENT '最近一次登录时间', - MODIFY COLUMN created_at DATETIME(3) NOT NULL COMMENT '该设备首次登录时间'; + MODIFY COLUMN device_id BIGINT UNSIGNED NOT NULL COMMENT 't_devices.device_id,JWT did', + MODIFY COLUMN last_login_at DATETIME(3) NOT NULL COMMENT '该用户在此设备最近登录成功', + MODIFY COLUMN last_active_at DATETIME(3) NULL COMMENT '该用户在此设备最近活跃', + MODIFY COLUMN created_at DATETIME(3) NOT NULL COMMENT '该用户首次在此设备绑定'; diff --git a/migrations/0004_user_devices_autoincrement.sql b/migrations/0004_user_devices_autoincrement.sql index b9cf0f5..74e0886 100644 --- a/migrations/0004_user_devices_autoincrement.sql +++ b/migrations/0004_user_devices_autoincrement.sql @@ -1,5 +1,5 @@ --- user_devices.id is a table-local AUTO_INCREMENT row key, not Snowflake. +-- t_user_devices.id is a table-local AUTO_INCREMENT row key, not Snowflake. -- Business identity remains (user_id, device_id). Existing Snowflake values stay; new rows continue from MAX(id)+1. -ALTER TABLE user_devices +ALTER TABLE t_user_devices MODIFY COLUMN id BIGINT NOT NULL AUTO_INCREMENT COMMENT '行 id,表内自增,仅内部用;业务唯一键是 (user_id, device_id)'; diff --git a/migrations/0005_user_profile.sql b/migrations/0005_user_profile.sql index 5750814..b61f836 100644 --- a/migrations/0005_user_profile.sql +++ b/migrations/0005_user_profile.sql @@ -1,9 +1,9 @@ --- Profile fields on users. One ADD per statement (stock MySQL has no ADD COLUMN IF NOT EXISTS). +-- Profile fields on t_users. One ADD per statement (stock MySQL has no ADD COLUMN IF NOT EXISTS). -- Re-running migrate ignores duplicate-column errors. -ALTER TABLE users ADD COLUMN qrcode VARCHAR(512) NOT NULL DEFAULT '' COMMENT '个人二维码对象存储 key 或 URL,不存图片二进制'; -ALTER TABLE users ADD COLUMN birthday DATE NULL COMMENT '生日,未填为空'; -ALTER TABLE users ADD COLUMN gender TINYINT NOT NULL DEFAULT 0 COMMENT '0=未知 1=男 2=女'; -ALTER TABLE users ADD COLUMN last_login_at DATETIME(3) NULL COMMENT '最近一次登录时间'; -ALTER TABLE users ADD COLUMN last_active_at DATETIME(3) NULL COMMENT '最近一次活跃时间(登录、心跳、发消息等)'; -ALTER TABLE users COMMENT = '用户账号。主键 Snowflake 即 uid;登录身份在 user_emails,设备在 user_devices'; +ALTER TABLE t_users ADD COLUMN qrcode VARCHAR(512) NOT NULL DEFAULT '' COMMENT '个人二维码对象存储 key 或 URL,不存图片二进制'; +ALTER TABLE t_users ADD COLUMN birthday DATE NULL COMMENT '生日,未填为空'; +ALTER TABLE t_users ADD COLUMN gender TINYINT NOT NULL DEFAULT 0 COMMENT '0=未知 1=男 2=女'; +ALTER TABLE t_users ADD COLUMN last_login_at DATETIME(3) NULL COMMENT '最近一次登录时间'; +ALTER TABLE t_users ADD COLUMN last_active_at DATETIME(3) NULL COMMENT '最近一次活跃时间(登录、心跳、发消息等)'; +ALTER TABLE t_users COMMENT = '用户账号。主键 Snowflake 即 uid;登录身份在 t_user_emails,设备在 t_user_devices'; diff --git a/migrations/0006_user_login_logs.sql b/migrations/0006_user_login_logs.sql index 7348598..9242307 100644 --- a/migrations/0006_user_login_logs.sql +++ b/migrations/0006_user_login_logs.sql @@ -1,6 +1,6 @@ --- user_login_logs: one row per successful login. user_devices.platform is the device type. +-- t_user_login_logs: one row per successful login. Device type lives on t_devices. -CREATE TABLE IF NOT EXISTS user_login_logs ( +CREATE TABLE IF NOT EXISTS t_user_login_logs ( id BIGINT NOT NULL AUTO_INCREMENT COMMENT '行 id,表内自增', user_id BIGINT NOT NULL COMMENT '登录用户', device_id BIGINT UNSIGNED NOT NULL COMMENT '客户端设备 id', @@ -12,7 +12,4 @@ CREATE TABLE IF NOT EXISTS user_login_logs ( created_at DATETIME(3) NOT NULL COMMENT '本次登录时间', PRIMARY KEY (id), KEY idx_user_created (user_id, created_at) -) COMMENT='用户登录记录。每次成功登录追加一行;当前设备以 user_devices 为准'; - -ALTER TABLE user_devices - MODIFY COLUMN platform VARCHAR(32) NOT NULL DEFAULT '' COMMENT '设备类型:ios/android/harmony/windows/macos/web'; +) COMMENT='用户登录记录。每次成功登录追加一行;当次 App 见 app_id'; diff --git a/migrations/0007_friends.sql b/migrations/0007_friends.sql index 597574f..953c143 100644 --- a/migrations/0007_friends.sql +++ b/migrations/0007_friends.sql @@ -1,6 +1,6 @@ -- Bidirectional friends as two directed rows, one pending request per pair, reports. -CREATE TABLE IF NOT EXISTS friend_relations ( +CREATE TABLE IF NOT EXISTS t_friend_relations ( id BIGINT NOT NULL AUTO_INCREMENT COMMENT '行 id,表内自增', user_id BIGINT NOT NULL COMMENT '关系所属用户', friend_id BIGINT NOT NULL COMMENT '对方 user_id', @@ -16,7 +16,7 @@ CREATE TABLE IF NOT EXISTS friend_relations ( KEY idx_user_status (user_id, status) ) COMMENT='单向好友边。A 与 B 互为好友时存两行,各自维护备注、拉黑、置顶'; -CREATE TABLE IF NOT EXISTS friend_requests ( +CREATE TABLE IF NOT EXISTS t_friend_requests ( id BIGINT PRIMARY KEY COMMENT 'Snowflake 申请 id', from_user BIGINT NOT NULL COMMENT '申请人 user_id', to_user BIGINT NOT NULL COMMENT '被申请人 user_id', @@ -30,7 +30,7 @@ CREATE TABLE IF NOT EXISTS friend_requests ( KEY idx_to_status (to_user, status, updated_at) ) COMMENT='好友申请。同一对 from→to 只保留一行,重复发起覆盖理由与备注'; -CREATE TABLE IF NOT EXISTS friend_reports ( +CREATE TABLE IF NOT EXISTS t_friend_reports ( id BIGINT PRIMARY KEY COMMENT 'Snowflake 投诉 id', user_id BIGINT NOT NULL COMMENT '投诉人 user_id', target_id BIGINT NOT NULL COMMENT '被投诉人 user_id', diff --git a/migrations/0008_favorites.sql b/migrations/0008_favorites.sql index 95e823f..f8171dd 100644 --- a/migrations/0008_favorites.sql +++ b/migrations/0008_favorites.sql @@ -1,11 +1,11 @@ -- 用户收藏。媒体对象复制到 perm/fav,不引用 chat/ 原 key;源对象过期则无法再收藏。 -CREATE TABLE IF NOT EXISTS favorites ( +CREATE TABLE IF NOT EXISTS t_favorites ( id BIGINT PRIMARY KEY COMMENT 'Snowflake 收藏 id', user_id BIGINT NOT NULL COMMENT '收藏者 user_id', msg_id BIGINT NOT NULL COMMENT '原消息 Snowflake id,仅作来源;撤回不影响收藏', conversation_id BIGINT NOT NULL COMMENT '原会话 id,仅作来源', - message_type SMALLINT NOT NULL COMMENT '消息类型,与 messages.message_type 一致', + message_type SMALLINT NOT NULL COMMENT '消息类型,与 t_messages.message_type 一致', content BLOB NOT NULL COMMENT '收藏快照(JSON 字节);媒体 key 已复制到 perm/fav/', created_at DATETIME(3) NOT NULL COMMENT '收藏时间', UNIQUE KEY uk_user_msg (user_id, msg_id), diff --git a/migrations/0009_groups.sql b/migrations/0009_groups.sql index 0fd3266..5668e53 100644 --- a/migrations/0009_groups.sql +++ b/migrations/0009_groups.sql @@ -1,8 +1,8 @@ --- Group id is a table-local AUTO_INCREMENT 群号. Chat / sync still use Snowflake conversations.id. +-- Group id is a table-local AUTO_INCREMENT 群号. Chat / sync still use Snowflake t_conversations.id. -CREATE TABLE IF NOT EXISTS `groups` ( +CREATE TABLE IF NOT EXISTS `t_groups` ( id BIGINT NOT NULL AUTO_INCREMENT COMMENT '群号,表内自增,对外群 ID', - conversation_id BIGINT NOT NULL COMMENT '对应 conversations.id(Snowflake),发消息与同步用', + conversation_id BIGINT NOT NULL COMMENT '对应 t_conversations.id(Snowflake),发消息与同步用', name VARCHAR(32) NOT NULL COMMENT '群名称', avatar VARCHAR(512) NOT NULL DEFAULT '' COMMENT '群头像对象存储 key,空表示未设置', owner_id BIGINT NOT NULL COMMENT '群主 user_id', @@ -17,8 +17,8 @@ CREATE TABLE IF NOT EXISTS `groups` ( KEY idx_status_updated (status, updated_at) ) COMMENT='群资料。id 是自增群号;会话列表与未读仍按 conversation_id 走 Redis'; -CREATE TABLE IF NOT EXISTS group_members ( - group_id BIGINT NOT NULL COMMENT '群号,groups.id', +CREATE TABLE IF NOT EXISTS t_group_members ( + group_id BIGINT NOT NULL COMMENT '群号,t_groups.id', user_id BIGINT NOT NULL COMMENT '成员 user_id', role TINYINT NOT NULL DEFAULT 3 COMMENT '1=群主 2=管理员 3=普通成员', nickname VARCHAR(32) NOT NULL DEFAULT '' COMMENT '群内昵称,空则用用户昵称', @@ -26,4 +26,4 @@ CREATE TABLE IF NOT EXISTS group_members ( joined_at DATETIME(3) NOT NULL COMMENT '入群时间', PRIMARY KEY (group_id, user_id), KEY idx_user_id (user_id) -) COMMENT='群成员与角色。热路径 MemberIDs 可短缓存;免打扰在 conversation_members'; +) COMMENT='群成员与角色。热路径 MemberIDs 可短缓存;免打扰在 t_conversation_members'; diff --git a/migrations/0010_message_deletes.sql b/migrations/0010_message_deletes.sql index 139ecc4..f00d47b 100644 --- a/migrations/0010_message_deletes.sql +++ b/migrations/0010_message_deletes.sql @@ -1,10 +1,10 @@ --- Per-user delete (hide). Does not change messages.status or the peer's history. +-- Per-user delete (hide). Does not change t_messages.status or the peer's history. -CREATE TABLE IF NOT EXISTS message_deletes ( +CREATE TABLE IF NOT EXISTS t_message_deletes ( user_id BIGINT NOT NULL COMMENT '删除者 user_id,仅该用户历史不可见', msg_id BIGINT NOT NULL COMMENT '被删除的 Snowflake MsgId', conversation_id BIGINT NOT NULL COMMENT '所属会话,便于按会话过滤', created_at DATETIME(3) NOT NULL COMMENT '删除时间', PRIMARY KEY (user_id, msg_id), KEY idx_user_conv_msg (user_id, conversation_id, msg_id) -) COMMENT='用户删除消息(只对自己隐藏)。对端仍可见;全员撤回走 messages.status=2'; +) COMMENT='用户删除消息(只对自己隐藏)。对端仍可见;全员撤回走 t_messages.status=2'; diff --git a/migrations/0011_split_messages.sql b/migrations/0011_split_messages.sql index 7c9791a..6f4acd0 100644 --- a/migrations/0011_split_messages.sql +++ b/migrations/0011_split_messages.sql @@ -1,6 +1,6 @@ -- Split message body by conversation type. Snowflake MsgId remains PK / sort / sync cursor. -CREATE TABLE IF NOT EXISTS private_message ( +CREATE TABLE IF NOT EXISTS t_private_message ( id BIGINT PRIMARY KEY COMMENT 'Snowflake MsgId,主键、排序键、同步游标', conversation_id BIGINT NOT NULL COMMENT '所属单聊会话 id', sender_id BIGINT NOT NULL COMMENT '发送者 user_id;系统消息为 0', @@ -13,12 +13,12 @@ CREATE TABLE IF NOT EXISTS private_message ( UNIQUE KEY uk_sender_conv_client_msg (sender_id, conversation_id, client_msg_id), KEY idx_conversation_id (conversation_id, id), KEY idx_receiver_id (receiver_id, id) -) COMMENT='单聊消息正文。PK=MsgId;与 group_message 分表存储'; +) COMMENT='单聊消息正文。PK=MsgId;与 t_group_message 分表存储'; -CREATE TABLE IF NOT EXISTS group_message ( +CREATE TABLE IF NOT EXISTS t_group_message ( id BIGINT PRIMARY KEY COMMENT 'Snowflake MsgId,主键、排序键、同步游标', conversation_id BIGINT NOT NULL COMMENT '所属群会话 id', - group_id BIGINT NOT NULL DEFAULT 0 COMMENT '群号 groups.id,便于按群查询', + group_id BIGINT NOT NULL DEFAULT 0 COMMENT '群号 t_groups.id,便于按群查询', sender_id BIGINT NOT NULL COMMENT '发送者 user_id;系统消息为 0', client_msg_id VARCHAR(64) NOT NULL COMMENT '客户端消息 id,与 sender+会话 组成幂等键', message_type SMALLINT NOT NULL COMMENT '消息类型:1文本 2图片 3语音 4视频 5表情 6GIF 7文件 8位置 9系统', @@ -30,7 +30,7 @@ CREATE TABLE IF NOT EXISTS group_message ( KEY idx_group_id (group_id, id) ) COMMENT='群聊消息正文。PK=MsgId;群热路径不写 MySQL inbox 行'; -CREATE TABLE IF NOT EXISTS messages ( +CREATE TABLE IF NOT EXISTS t_messages ( id BIGINT PRIMARY KEY COMMENT 'Snowflake MsgId,主键、排序键、同步游标', conversation_id BIGINT NOT NULL COMMENT '所属会话 id', sender_id BIGINT NOT NULL COMMENT '发送者 user_id', @@ -41,22 +41,22 @@ CREATE TABLE IF NOT EXISTS messages ( created_at DATETIME(3) NOT NULL COMMENT '服务端入库时间', UNIQUE KEY uk_sender_conv_client_msg (sender_id, conversation_id, client_msg_id), KEY idx_conversation_id (conversation_id, id) -) COMMENT='迁移中转表。0011 拷贝到 private_message / group_message 后删除'; +) COMMENT='迁移中转表。0011 拷贝到 t_private_message / t_group_message 后删除'; -INSERT IGNORE INTO private_message (id, conversation_id, sender_id, client_msg_id, message_type, content, status, created_at) +INSERT IGNORE INTO t_private_message (id, conversation_id, sender_id, client_msg_id, message_type, content, status, created_at) SELECT m.id, m.conversation_id, m.sender_id, m.client_msg_id, m.message_type, m.content, m.status, m.created_at -FROM messages m -INNER JOIN conversations c ON c.id = m.conversation_id AND c.type = 1; +FROM t_messages m +INNER JOIN t_conversations c ON c.id = m.conversation_id AND c.type = 1; -INSERT IGNORE INTO group_message (id, conversation_id, sender_id, client_msg_id, message_type, content, status, created_at) +INSERT IGNORE INTO t_group_message (id, conversation_id, sender_id, client_msg_id, message_type, content, status, created_at) SELECT m.id, m.conversation_id, m.sender_id, m.client_msg_id, m.message_type, m.content, m.status, m.created_at -FROM messages m -INNER JOIN conversations c ON c.id = m.conversation_id AND c.type = 2; +FROM t_messages m +INNER JOIN t_conversations c ON c.id = m.conversation_id AND c.type = 2; -INSERT IGNORE INTO private_message (id, conversation_id, sender_id, client_msg_id, message_type, content, status, created_at) +INSERT IGNORE INTO t_private_message (id, conversation_id, sender_id, client_msg_id, message_type, content, status, created_at) SELECT m.id, m.conversation_id, m.sender_id, m.client_msg_id, m.message_type, m.content, m.status, m.created_at -FROM messages m -LEFT JOIN conversations c ON c.id = m.conversation_id +FROM t_messages m +LEFT JOIN t_conversations c ON c.id = m.conversation_id WHERE c.id IS NULL; -DROP TABLE IF EXISTS messages; +DROP TABLE IF EXISTS t_messages; diff --git a/migrations/0012_group_profile.sql b/migrations/0012_group_profile.sql index c3d8212..0c768e8 100644 --- a/migrations/0012_group_profile.sql +++ b/migrations/0012_group_profile.sql @@ -1,7 +1,7 @@ -- Group announcement (owner/admin) and per-member remark (self only). -ALTER TABLE `groups` +ALTER TABLE `t_groups` ADD COLUMN announcement VARCHAR(1024) NOT NULL DEFAULT '' COMMENT '群公告,仅群主/管理员可改' AFTER avatar; -ALTER TABLE group_members +ALTER TABLE t_group_members ADD COLUMN remark VARCHAR(32) NOT NULL DEFAULT '' COMMENT '成员对该群的备注,仅自己可见' AFTER nickname; diff --git a/migrations/0013_friend_directed.sql b/migrations/0013_friend_directed.sql index d0b3baf..0191e20 100644 --- a/migrations/0013_friend_directed.sql +++ b/migrations/0013_friend_directed.sql @@ -1,7 +1,7 @@ --- Pair-shaped friend_relations (user_small, user_big) → two directed rows. --- Skipped by cmd/migrate when friend_relations.user_id already exists. +-- Pair-shaped t_friend_relations (user_small, user_big) → two directed rows. +-- Skipped by cmd/migrate when t_friend_relations.user_id already exists. -CREATE TABLE IF NOT EXISTS friend_relations_new ( +CREATE TABLE IF NOT EXISTS t_friend_relations_new ( id BIGINT NOT NULL AUTO_INCREMENT COMMENT '行 id,表内自增', user_id BIGINT NOT NULL COMMENT '关系所属用户', friend_id BIGINT NOT NULL COMMENT '对方 user_id', @@ -17,22 +17,22 @@ CREATE TABLE IF NOT EXISTS friend_relations_new ( KEY idx_user_status (user_id, status) ) COMMENT='单向好友边。A 与 B 互为好友时存两行,各自维护备注、拉黑、置顶'; -INSERT IGNORE INTO friend_relations_new (user_id, friend_id, status, remark, is_blocked, is_pinned, source, created_at, updated_at) +INSERT IGNORE INTO t_friend_relations_new (user_id, friend_id, status, remark, is_blocked, is_pinned, source, created_at, updated_at) SELECT r.user_small, r.user_big, 1, IFNULL(n.remark, ''), 0, 0, 0, r.created_at, r.created_at -FROM friend_relations r -LEFT JOIN friend_remarks n ON n.user_id = r.user_small AND n.friend_id = r.user_big; +FROM t_friend_relations r +LEFT JOIN t_friend_remarks n ON n.user_id = r.user_small AND n.friend_id = r.user_big; -INSERT IGNORE INTO friend_relations_new (user_id, friend_id, status, remark, is_blocked, is_pinned, source, created_at, updated_at) +INSERT IGNORE INTO t_friend_relations_new (user_id, friend_id, status, remark, is_blocked, is_pinned, source, created_at, updated_at) SELECT r.user_big, r.user_small, 1, IFNULL(n.remark, ''), 0, 0, 0, r.created_at, r.created_at -FROM friend_relations r -LEFT JOIN friend_remarks n ON n.user_id = r.user_big AND n.friend_id = r.user_small; +FROM t_friend_relations r +LEFT JOIN t_friend_remarks n ON n.user_id = r.user_big AND n.friend_id = r.user_small; -INSERT INTO friend_relations_new (user_id, friend_id, status, remark, is_blocked, is_pinned, source, created_at, updated_at) +INSERT INTO t_friend_relations_new (user_id, friend_id, status, remark, is_blocked, is_pinned, source, created_at, updated_at) SELECT b.user_id, b.blocked_id, 0, '', 1, 0, 0, b.created_at, b.created_at -FROM user_blocks b +FROM t_user_blocks b ON DUPLICATE KEY UPDATE is_blocked = 1, updated_at = VALUES(updated_at); -DROP TABLE IF EXISTS friend_remarks; -DROP TABLE IF EXISTS user_blocks; -DROP TABLE IF EXISTS friend_relations; -RENAME TABLE friend_relations_new TO friend_relations; +DROP TABLE IF EXISTS t_friend_remarks; +DROP TABLE IF EXISTS t_user_blocks; +DROP TABLE IF EXISTS t_friend_relations; +RENAME TABLE t_friend_relations_new TO t_friend_relations; diff --git a/migrations/0014_message_query_keys.sql b/migrations/0014_message_query_keys.sql index 50587fe..ba1b206 100644 --- a/migrations/0014_message_query_keys.sql +++ b/migrations/0014_message_query_keys.sql @@ -1,23 +1,23 @@ -- Add denormalized query keys. Ignored when 0011 already created the columns. -ALTER TABLE private_message +ALTER TABLE t_private_message ADD COLUMN receiver_id BIGINT NOT NULL DEFAULT 0 COMMENT '接收者 user_id;系统消息为 0'; -ALTER TABLE private_message +ALTER TABLE t_private_message ADD KEY idx_receiver_id (receiver_id, id); -UPDATE private_message pm -INNER JOIN p2p_conversations p ON p.conversation_id = pm.conversation_id +UPDATE t_private_message pm +INNER JOIN t_p2p_conversations p ON p.conversation_id = pm.conversation_id SET pm.receiver_id = IF(pm.sender_id = p.user_small, p.user_big, IF(pm.sender_id = p.user_big, p.user_small, 0)) WHERE pm.receiver_id = 0 AND pm.sender_id <> 0; -ALTER TABLE group_message - ADD COLUMN group_id BIGINT NOT NULL DEFAULT 0 COMMENT '群号 groups.id,便于按群查询'; +ALTER TABLE t_group_message + ADD COLUMN group_id BIGINT NOT NULL DEFAULT 0 COMMENT '群号 t_groups.id,便于按群查询'; -ALTER TABLE group_message +ALTER TABLE t_group_message ADD KEY idx_group_id (group_id, id); -UPDATE group_message gm -INNER JOIN `groups` g ON g.conversation_id = gm.conversation_id +UPDATE t_group_message gm +INNER JOIN `t_groups` g ON g.conversation_id = gm.conversation_id SET gm.group_id = g.id WHERE gm.group_id = 0; diff --git a/migrations/0015_moments.sql b/migrations/0015_moments.sql index 7aeee66..0fa3193 100644 --- a/migrations/0015_moments.sql +++ b/migrations/0015_moments.sql @@ -1,8 +1,8 @@ --- 朋友圈。独立于 messages;Snowflake post_id 是主键、排序和游标。媒体在 perm/moment/,不过期,删帖时删对象。 +-- 朋友圈。独立于 t_messages;Snowflake post_id 是主键、排序和游标。媒体在 perm/moment/,不过期,删帖时删对象。 -CREATE TABLE IF NOT EXISTS moment_posts ( +CREATE TABLE IF NOT EXISTS t_moment_posts ( id BIGINT PRIMARY KEY COMMENT 'Snowflake 帖 id,Feed/相册游标', - user_id BIGINT NOT NULL COMMENT '作者 users.id', + user_id BIGINT NOT NULL COMMENT '作者 t_users.id', kind SMALLINT NOT NULL COMMENT '1纯文 2图 3视频', text VARCHAR(1000) NOT NULL DEFAULT '' COMMENT '正文,可空;与媒体至少有一项', content BLOB NOT NULL COMMENT '图/视频 JSON 字节,不存媒体二进制', @@ -12,26 +12,26 @@ CREATE TABLE IF NOT EXISTS moment_posts ( poi_address VARCHAR(256) NOT NULL DEFAULT '' COMMENT '地点地址', visibility SMALLINT NOT NULL DEFAULT 0 COMMENT '0好友公开 1私密 2白名单 3黑名单', status SMALLINT NOT NULL DEFAULT 0 COMMENT '0正常 1已删', - like_count INT NOT NULL DEFAULT 0 COMMENT '点赞数,与 moment_likes 同事务维护', - comment_count INT NOT NULL DEFAULT 0 COMMENT '未删评论数,与 moment_comments 同事务维护', + like_count INT NOT NULL DEFAULT 0 COMMENT '点赞数,与 t_moment_likes 同事务维护', + comment_count INT NOT NULL DEFAULT 0 COMMENT '未删评论数,与 t_moment_comments 同事务维护', created_at DATETIME(3) NOT NULL COMMENT '发帖时间,visible_days 按此裁剪', KEY idx_user_id (user_id, id) ) COMMENT='朋友圈帖。读时按好友+可见性过滤,不写每好友 inbox'; -CREATE TABLE IF NOT EXISTS moment_audience ( +CREATE TABLE IF NOT EXISTS t_moment_audience ( post_id BIGINT NOT NULL COMMENT '帖 id', peer_id BIGINT NOT NULL COMMENT '白名单能看 / 黑名单不能看 的好友 uid', PRIMARY KEY (post_id, peer_id) ) COMMENT='部分可见名单。仅 visibility=2/3 有行'; -CREATE TABLE IF NOT EXISTS moment_likes ( +CREATE TABLE IF NOT EXISTS t_moment_likes ( post_id BIGINT NOT NULL COMMENT '帖 id', user_id BIGINT NOT NULL COMMENT '点赞人', created_at DATETIME(3) NOT NULL COMMENT '点赞时间', PRIMARY KEY (post_id, user_id) ) COMMENT='朋友圈点赞。重复 PUT 幂等'; -CREATE TABLE IF NOT EXISTS moment_comments ( +CREATE TABLE IF NOT EXISTS t_moment_comments ( id BIGINT PRIMARY KEY COMMENT 'Snowflake 评论 id', post_id BIGINT NOT NULL COMMENT '帖 id', user_id BIGINT NOT NULL COMMENT '评论人', @@ -43,7 +43,7 @@ CREATE TABLE IF NOT EXISTS moment_comments ( KEY idx_post (post_id, id) ) COMMENT='朋友圈评论。展示按共同好友过滤'; -CREATE TABLE IF NOT EXISTS moment_notices ( +CREATE TABLE IF NOT EXISTS t_moment_notices ( id BIGINT PRIMARY KEY COMMENT 'Snowflake 通知 id,列表游标', to_user_id BIGINT NOT NULL COMMENT '接收人', from_user_id BIGINT NOT NULL COMMENT '动作发起人', @@ -55,15 +55,15 @@ CREATE TABLE IF NOT EXISTS moment_notices ( KEY idx_to_user (to_user_id, id) ) COMMENT='朋友圈赞评通知。不进会话 mailbox'; -CREATE TABLE IF NOT EXISTS moment_settings ( - user_id BIGINT PRIMARY KEY COMMENT '用户 users.id', +CREATE TABLE IF NOT EXISTS t_moment_settings ( + user_id BIGINT PRIMARY KEY COMMENT '用户 t_users.id', cover_key VARCHAR(512) NOT NULL DEFAULT '' COMMENT '封面 object_key,空表示未设', visible_days SMALLINT NOT NULL DEFAULT 0 COMMENT '允许朋友查看范围:0全部 3/30/180 天', last_read_post_id BIGINT NOT NULL DEFAULT 0 COMMENT '发现页红点水位,只增不减', updated_at DATETIME(3) NOT NULL COMMENT '最近更新时间' ) COMMENT='朋友圈个人设置。无行则封面空、范围全部、水位 0'; -CREATE TABLE IF NOT EXISTS moment_hides ( +CREATE TABLE IF NOT EXISTS t_moment_hides ( user_id BIGINT NOT NULL COMMENT '设置方', peer_id BIGINT NOT NULL COMMENT '对方', hide_him TINYINT NOT NULL DEFAULT 0 COMMENT '1=不看他(Feed 去掉对方)', diff --git a/migrations/0016_row_autoincrement_id.sql b/migrations/0016_row_autoincrement_id.sql index 6680a4d..1143ec3 100644 --- a/migrations/0016_row_autoincrement_id.sql +++ b/migrations/0016_row_autoincrement_id.sql @@ -1,62 +1,62 @@ -- Junction / mapping tables get a table-local AUTO_INCREMENT row id. -- Business uniqueness stays UNIQUE (same columns as the old composite PK). --- Snowflake PKs (users / messages / conversations / moments posts) are unchanged. +-- Snowflake PKs (t_users / t_messages / t_conversations / moments posts) are unchanged. -ALTER TABLE user_emails +ALTER TABLE t_user_emails DROP PRIMARY KEY, ADD COLUMN id BIGINT NOT NULL AUTO_INCREMENT COMMENT '行 id,表内自增,仅内部用;业务唯一键是 email' FIRST, ADD PRIMARY KEY (id), ADD UNIQUE KEY uk_email (email); -ALTER TABLE p2p_conversations +ALTER TABLE t_p2p_conversations DROP PRIMARY KEY, ADD COLUMN id BIGINT NOT NULL AUTO_INCREMENT COMMENT '行 id,表内自增,仅内部用;业务唯一键是 (user_small, user_big)' FIRST, ADD PRIMARY KEY (id), ADD UNIQUE KEY uk_p2p_users (user_small, user_big); -ALTER TABLE conversation_members +ALTER TABLE t_conversation_members DROP PRIMARY KEY, ADD COLUMN id BIGINT NOT NULL AUTO_INCREMENT COMMENT '行 id,表内自增,仅内部用;业务唯一键是 (conversation_id, user_id)' FIRST, ADD PRIMARY KEY (id), ADD UNIQUE KEY uk_conversation_members (conversation_id, user_id); -ALTER TABLE device_sync_cursors +ALTER TABLE t_device_sync_cursors DROP PRIMARY KEY, ADD COLUMN id BIGINT NOT NULL AUTO_INCREMENT COMMENT '行 id,表内自增,仅内部用;业务唯一键是 (user_id, device_id)' FIRST, ADD PRIMARY KEY (id), ADD UNIQUE KEY uk_user_device (user_id, device_id); -ALTER TABLE group_members +ALTER TABLE t_group_members DROP PRIMARY KEY, ADD COLUMN id BIGINT NOT NULL AUTO_INCREMENT COMMENT '行 id,表内自增,仅内部用;业务唯一键是 (group_id, user_id)' FIRST, ADD PRIMARY KEY (id), ADD UNIQUE KEY uk_group_members (group_id, user_id); -ALTER TABLE message_deletes +ALTER TABLE t_message_deletes DROP PRIMARY KEY, ADD COLUMN id BIGINT NOT NULL AUTO_INCREMENT COMMENT '行 id,表内自增,仅内部用;业务唯一键是 (user_id, msg_id)' FIRST, ADD PRIMARY KEY (id), ADD UNIQUE KEY uk_user_msg (user_id, msg_id); -ALTER TABLE moment_audience +ALTER TABLE t_moment_audience DROP PRIMARY KEY, ADD COLUMN id BIGINT NOT NULL AUTO_INCREMENT COMMENT '行 id,表内自增,仅内部用;业务唯一键是 (post_id, peer_id)' FIRST, ADD PRIMARY KEY (id), ADD UNIQUE KEY uk_post_peer (post_id, peer_id); -ALTER TABLE moment_likes +ALTER TABLE t_moment_likes DROP PRIMARY KEY, ADD COLUMN id BIGINT NOT NULL AUTO_INCREMENT COMMENT '行 id,表内自增,仅内部用;业务唯一键是 (post_id, user_id)' FIRST, ADD PRIMARY KEY (id), ADD UNIQUE KEY uk_post_user (post_id, user_id); -ALTER TABLE moment_settings +ALTER TABLE t_moment_settings DROP PRIMARY KEY, ADD COLUMN id BIGINT NOT NULL AUTO_INCREMENT COMMENT '行 id,表内自增,仅内部用;业务唯一键是 user_id' FIRST, ADD PRIMARY KEY (id), ADD UNIQUE KEY uk_user_id (user_id); -ALTER TABLE moment_hides +ALTER TABLE t_moment_hides DROP PRIMARY KEY, ADD COLUMN id BIGINT NOT NULL AUTO_INCREMENT COMMENT '行 id,表内自增,仅内部用;业务唯一键是 (user_id, peer_id)' FIRST, ADD PRIMARY KEY (id), diff --git a/migrations/0017_user_delete.sql b/migrations/0017_user_delete.sql index 2bbab6b..7630ade 100644 --- a/migrations/0017_user_delete.sql +++ b/migrations/0017_user_delete.sql @@ -1,7 +1,7 @@ --- Archived accounts. Live rows stay in users; cancellation copies then deletes. +-- Archived accounts. Live rows stay in t_users; cancellation copies then deletes. -CREATE TABLE IF NOT EXISTS user_delete ( - id BIGINT PRIMARY KEY COMMENT '原 users.id(uid),Snowflake,不复用', +CREATE TABLE IF NOT EXISTS t_user_delete ( + id BIGINT PRIMARY KEY COMMENT '原 t_users.id(uid),Snowflake,不复用', spark_id VARCHAR(32) NOT NULL COMMENT '注销时的 Spark 账号', nickname VARCHAR(64) NOT NULL DEFAULT '' COMMENT '注销时的昵称', avatar VARCHAR(512) NOT NULL DEFAULT '' COMMENT '注销时的头像 object_key', @@ -18,4 +18,4 @@ CREATE TABLE IF NOT EXISTS user_delete ( KEY idx_email (email), KEY idx_spark_id (spark_id), KEY idx_deleted_at (deleted_at) -) COMMENT='已注销用户档案。从 users 迁入后删除原行,邮箱与 spark_id 可重新注册'; +) COMMENT='已注销用户档案。从 t_users 迁入后删除原行,邮箱与 spark_id 可重新注册'; diff --git a/migrations/0018_square.sql b/migrations/0018_square.sql index 091f660..7693bc1 100644 --- a/migrations/0018_square.sql +++ b/migrations/0018_square.sql @@ -1,8 +1,8 @@ -- 广场。Snowflake post_id;content 为 VARBINARY 序列化 JSON 字节。 -CREATE TABLE IF NOT EXISTS square_posts ( +CREATE TABLE IF NOT EXISTS t_square_posts ( id BIGINT PRIMARY KEY COMMENT 'Snowflake 帖 id,Feed 游标', - user_id BIGINT NOT NULL COMMENT '作者 users.id', + user_id BIGINT NOT NULL COMMENT '作者 t_users.id', kind SMALLINT NOT NULL COMMENT '1纯文 2图 3视频', text VARCHAR(1000) NOT NULL DEFAULT '' COMMENT '正文,可空;与媒体至少有一项', content VARBINARY(16384) NOT NULL COMMENT '序列化 JSON 字节(json.Marshal),图/视频只存 object_key', @@ -22,20 +22,20 @@ CREATE TABLE IF NOT EXISTS square_posts ( KEY idx_user (user_id, id) ) COMMENT='广场帖'; -CREATE TABLE IF NOT EXISTS square_audience ( +CREATE TABLE IF NOT EXISTS t_square_audience ( post_id BIGINT NOT NULL COMMENT '帖 id', peer_id BIGINT NOT NULL COMMENT '白名单能看 / 黑名单不能看 的好友 uid', PRIMARY KEY (post_id, peer_id) ) COMMENT='广场部分可见名单'; -CREATE TABLE IF NOT EXISTS square_likes ( +CREATE TABLE IF NOT EXISTS t_square_likes ( post_id BIGINT NOT NULL COMMENT '帖 id', user_id BIGINT NOT NULL COMMENT '点赞人', created_at DATETIME(3) NOT NULL COMMENT '点赞时间', PRIMARY KEY (post_id, user_id) ) COMMENT='广场点赞'; -CREATE TABLE IF NOT EXISTS square_comments ( +CREATE TABLE IF NOT EXISTS t_square_comments ( id BIGINT PRIMARY KEY COMMENT 'Snowflake 评论 id', post_id BIGINT NOT NULL COMMENT '帖 id', user_id BIGINT NOT NULL COMMENT '评论人', @@ -47,7 +47,7 @@ CREATE TABLE IF NOT EXISTS square_comments ( KEY idx_post (post_id, id) ) COMMENT='广场评论'; -CREATE TABLE IF NOT EXISTS square_notices ( +CREATE TABLE IF NOT EXISTS t_square_notices ( id BIGINT PRIMARY KEY COMMENT 'Snowflake 通知 id', to_user_id BIGINT NOT NULL COMMENT '接收人', from_user_id BIGINT NOT NULL COMMENT '动作发起人', @@ -59,8 +59,8 @@ CREATE TABLE IF NOT EXISTS square_notices ( KEY idx_to_user (to_user_id, id) ) COMMENT='广场赞评通知'; -CREATE TABLE IF NOT EXISTS square_notice_state ( - user_id BIGINT PRIMARY KEY COMMENT '用户 users.id', +CREATE TABLE IF NOT EXISTS t_square_notice_state ( + user_id BIGINT PRIMARY KEY COMMENT '用户 t_users.id', last_read_notice_id BIGINT NOT NULL DEFAULT 0 COMMENT '互动通知已读水位', updated_at DATETIME(3) NOT NULL COMMENT '更新时间' ) COMMENT='广场通知未读水位'; diff --git a/migrations/0019_devices.sql b/migrations/0019_devices.sql index 6eec77c..98cb78d 100644 --- a/migrations/0019_devices.sql +++ b/migrations/0019_devices.sql @@ -1,6 +1,6 @@ --- Physical devices registry + slim user_devices + login log app_id. +-- Physical t_devices registry + slim t_user_devices + login log app_id. -CREATE TABLE IF NOT EXISTS devices ( +CREATE TABLE IF NOT EXISTS t_devices ( device_id BIGINT UNSIGNED NOT NULL COMMENT 'JWT did;多 App 同机共用', fingerprint_hash CHAR(64) NOT NULL COMMENT '物理指纹 SHA256 hex,不含 app_id', device_type TINYINT UNSIGNED NOT NULL COMMENT 'device_type 枚举 1=ios 2=android …', @@ -14,15 +14,15 @@ CREATE TABLE IF NOT EXISTS devices ( UNIQUE KEY uk_fingerprint (fingerprint_hash) ) COMMENT='物理设备;与用户、App 无关'; -ALTER TABLE user_login_logs +ALTER TABLE t_user_login_logs ADD COLUMN app_id TINYINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '当次登录 app_id' AFTER device_id; -ALTER TABLE user_devices +ALTER TABLE t_user_devices ADD COLUMN last_active_at DATETIME(3) NULL COMMENT '该用户在此设备最近活跃' AFTER last_login_at; -ALTER TABLE user_devices DROP COLUMN platform; -ALTER TABLE user_devices DROP COLUMN device_name; -ALTER TABLE user_devices DROP COLUMN app_version; -ALTER TABLE user_devices DROP COLUMN language; -ALTER TABLE user_devices DROP COLUMN last_ip; +ALTER TABLE t_user_devices DROP COLUMN platform; +ALTER TABLE t_user_devices DROP COLUMN device_name; +ALTER TABLE t_user_devices DROP COLUMN app_version; +ALTER TABLE t_user_devices DROP COLUMN language; +ALTER TABLE t_user_devices DROP COLUMN last_ip; diff --git a/migrations/0020_music.sql b/migrations/0020_music.sql index 205c7cb..0de4d25 100644 --- a/migrations/0020_music.sql +++ b/migrations/0020_music.sql @@ -1,6 +1,6 @@ -- 运营音乐列表 + 全局会员试听时长。 -CREATE TABLE IF NOT EXISTS music_tracks ( +CREATE TABLE IF NOT EXISTS t_music_tracks ( id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '曲目自增 id', title VARCHAR(256) NOT NULL DEFAULT '' COMMENT '曲名', cover_key VARCHAR(512) NOT NULL DEFAULT '' COMMENT '封面 object_key(sparkr)', @@ -15,12 +15,12 @@ CREATE TABLE IF NOT EXISTS music_tracks ( KEY idx_music_list (enabled, sort_order, id) ) COMMENT='运营音乐曲目'; -CREATE TABLE IF NOT EXISTS music_settings ( +CREATE TABLE IF NOT EXISTS t_music_settings ( setting_key VARCHAR(64) PRIMARY KEY COMMENT '配置键', setting_value VARCHAR(256) NOT NULL DEFAULT '' COMMENT '配置值', updated_at DATETIME(3) NOT NULL COMMENT '更新时间' ) COMMENT='音乐全局配置(如会员免费试听秒数)'; -INSERT INTO music_settings (setting_key, setting_value, updated_at) +INSERT INTO t_music_settings (setting_key, setting_value, updated_at) VALUES ('member_preview_seconds', '30', CURRENT_TIMESTAMP(3)) ON DUPLICATE KEY UPDATE setting_key = setting_key;