From b01ed29751d72b1876885d7703fe47a75d6cd76b Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 15 Aug 2026 14:17:53 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=BF=81=E7=A7=BB=E8=84=9A?= =?UTF-8?q?=E6=9C=AC:=20=E8=A1=A5=E5=85=A8CreateDb=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E8=B7=B3=E8=BF=87=E5=AF=BC=E8=87=B4=E7=BC=BA=E5=A4=B1=E7=9A=84?= =?UTF-8?q?=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CreateDb的多个建表函数(createTenantRegistry/createIMSecurityTables/ createIMNotificationTables/createIMRelationTables)只在全新库的建表路径里 调用;UpgradeDb对已存在且版本号已达标的库直接判定"无需升级"直接跳过, 不会补建任何表。我们这个tinode库版本号刚好已经等于目标版本,所以这几个 函数从未真正执行过。 补上迁移脚本里缺失的表(与adapter.go里的建表语句保持一致): tinode.im_tenant / im_tenant_config (原脚本假设已存在,直接ALTER导致报错) tinode.im_realname_verifications / im_action_tokens tinode.im_system_notifications tinode.im_friend_requests / im_friendships / im_user_blocks / im_favorites --- scripts/apply_hotgo_tenant_db.go | 153 +++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) diff --git a/scripts/apply_hotgo_tenant_db.go b/scripts/apply_hotgo_tenant_db.go index 816d89d..c6a1cba 100644 --- a/scripts/apply_hotgo_tenant_db.go +++ b/scripts/apply_hotgo_tenant_db.go @@ -57,6 +57,159 @@ func main() { CONSTRAINT fk_im_tenant_config_tenant FOREIGN KEY(tenant_id) REFERENCES hotgo.im_tenant(id) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci`, "CREATE DATABASE IF NOT EXISTS tinode CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci", + // The main server binary only creates tinode.im_tenant/im_tenant_config + // (see createTenantRegistry in server/db/mysql/adapter.go) as part of its + // version-gated schema upgrade chain. A tinode DB that was already at the + // target schema version before this table was introduced never runs that + // step, so the ALTERs below would otherwise fail with "table doesn't + // exist". Create it here too (schema kept identical to createTenantRegistry). + `CREATE TABLE IF NOT EXISTS tinode.im_tenant( + id BIGINT NOT NULL AUTO_INCREMENT, + code VARCHAR(64) NOT NULL, + name VARCHAR(128) NOT NULL, + tenant_desc VARCHAR(256), + db_name VARCHAR(128) NOT NULL DEFAULT '', + db_dsn VARCHAR(1024) NOT NULL DEFAULT '', + state SMALLINT NOT NULL, + created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + created_by BIGINT NOT NULL, + updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), + updated_by BIGINT NOT NULL, + PRIMARY KEY(id), + UNIQUE INDEX uk_im_tenant_code(code), + INDEX idx_im_tenant_db_name(db_name) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci`, + `CREATE TABLE IF NOT EXISTS tinode.im_tenant_config( + id BIGINT NOT NULL AUTO_INCREMENT, + tenant_id BIGINT NOT NULL, + max_users BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '0 means unlimited', + max_groups BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '0 means unlimited', + max_group_members INT UNSIGNED NOT NULL DEFAULT 0 COMMENT '0 means unlimited', + created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + created_by BIGINT NOT NULL, + updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), + updated_by BIGINT NOT NULL, + PRIMARY KEY(id), + UNIQUE INDEX uk_im_tenant_config_tenant_id(tenant_id), + CONSTRAINT fk_im_tenant_config_tenant FOREIGN KEY(tenant_id) REFERENCES tinode.im_tenant(id) ON DELETE CASCADE + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci`, + `INSERT INTO tinode.im_tenant(id,code,name,tenant_desc,db_name,db_dsn,state,created_by,updated_by) + VALUES(1,'default','Default Tenant',NULL,'tinode','',1,0,0) + ON DUPLICATE KEY UPDATE db_name=VALUES(db_name), updated_at=CURRENT_TIMESTAMP(3)`, + // Same root cause as im_tenant above: createIMSecurityTables, createIMNotificationTables + // and createIMRelationTables (server/db/mysql/adapter.go) are only reached from CreateDb's + // fresh-install path, which our pre-existing tinode DB never runs. Recreate their tables here. + `CREATE TABLE IF NOT EXISTS tinode.im_realname_verifications( + id BIGINT NOT NULL AUTO_INCREMENT, + user_id BIGINT NOT NULL, + submission_id VARCHAR(64) NOT NULL, + status VARCHAR(16) NOT NULL, + name_cipher TEXT NOT NULL, + id_type VARCHAR(32) NOT NULL, + id_number_cipher TEXT NOT NULL, + id_number_hash CHAR(64) NOT NULL, + masked_name VARCHAR(64) NOT NULL, + masked_id_number VARCHAR(64) NOT NULL, + review_reason VARCHAR(256), + verified_at DATETIME(3), + created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), + PRIMARY KEY(id), + UNIQUE INDEX uk_im_realname_submission(submission_id), + INDEX idx_im_realname_user_latest(user_id, created_at), + INDEX idx_im_realname_id_hash(id_number_hash) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci`, + `CREATE TABLE IF NOT EXISTS tinode.im_action_tokens( + id BIGINT NOT NULL AUTO_INCREMENT, + user_id BIGINT NOT NULL, + token_id VARCHAR(64) NOT NULL, + action VARCHAR(64) NOT NULL, + target VARCHAR(128) NOT NULL DEFAULT '', + token_hash CHAR(64) NOT NULL, + state SMALLINT NOT NULL, + expires_at DATETIME(3) NOT NULL, + consumed_at DATETIME(3), + created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), + PRIMARY KEY(id), + UNIQUE INDEX uk_im_action_tokens_token(token_id), + INDEX idx_im_action_tokens_user_action(user_id, action, target, state, expires_at) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci`, + `CREATE TABLE IF NOT EXISTS tinode.im_system_notifications( + id BIGINT NOT NULL AUTO_INCREMENT, + user_id BIGINT NOT NULL, + event_id VARCHAR(64) NOT NULL, + event_type VARCHAR(64) NOT NULL, + title VARCHAR(128) NOT NULL, + summary VARCHAR(512) NOT NULL, + action JSON, + read_at DATETIME(3), + created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), + PRIMARY KEY(id), + UNIQUE INDEX uk_im_system_notifications_event(user_id, event_id), + INDEX idx_im_system_notifications_inbox(user_id, id DESC) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci`, + `CREATE TABLE IF NOT EXISTS tinode.im_friend_requests( + id BIGINT NOT NULL AUTO_INCREMENT, + request_id VARCHAR(64) NOT NULL, + applicant_id BIGINT NOT NULL, + target_id BIGINT NOT NULL, + message VARCHAR(200) NOT NULL DEFAULT '', + source VARCHAR(32) NOT NULL DEFAULT '', + source_topic VARCHAR(64) NOT NULL DEFAULT '', + status VARCHAR(16) NOT NULL, + idempotency_key VARCHAR(128) NOT NULL DEFAULT '', + expires_at DATETIME(3) NOT NULL, + handled_at DATETIME(3), + created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), + PRIMARY KEY(id), + UNIQUE INDEX uk_im_friend_requests_request(request_id), + UNIQUE INDEX uk_im_friend_requests_idempotency(applicant_id, idempotency_key), + INDEX idx_im_friend_requests_pair(applicant_id, target_id, status, created_at), + INDEX idx_im_friend_requests_inbox(target_id, status, created_at) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci`, + `CREATE TABLE IF NOT EXISTS tinode.im_friendships( + user_id BIGINT NOT NULL, + peer_id BIGINT NOT NULL, + status VARCHAR(16) NOT NULL, + remark VARCHAR(64) NOT NULL DEFAULT '', + topic CHAR(25) NOT NULL DEFAULT '', + created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), + PRIMARY KEY(user_id, peer_id), + INDEX idx_im_friendships_peer(peer_id, status) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci`, + `CREATE TABLE IF NOT EXISTS tinode.im_user_blocks( + blocker_id BIGINT NOT NULL, + blocked_id BIGINT NOT NULL, + created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), + PRIMARY KEY(blocker_id, blocked_id), + INDEX idx_im_user_blocks_blocked(blocked_id) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci`, + `CREATE TABLE IF NOT EXISTS tinode.im_favorites( + id BIGINT NOT NULL AUTO_INCREMENT, + favorite_id VARCHAR(64) NOT NULL, + user_id BIGINT NOT NULL, + item_type VARCHAR(16) NOT NULL, + source_topic CHAR(25) NOT NULL, + source_seq INT NOT NULL, + snapshot JSON, + attachment_refs JSON, + availability VARCHAR(16) NOT NULL DEFAULT 'available', + idempotency_key VARCHAR(128) NOT NULL DEFAULT '', + collected_at DATETIME(3) NOT NULL, + created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), + PRIMARY KEY(id), + UNIQUE INDEX uk_im_favorites_favorite(favorite_id), + UNIQUE INDEX uk_im_favorites_source(user_id, source_topic, source_seq), + UNIQUE INDEX uk_im_favorites_idempotency(user_id, ((NULLIF(idempotency_key, '')))), + INDEX idx_im_favorites_inbox(user_id, id DESC), + INDEX idx_im_favorites_type(user_id, item_type, id DESC) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci`, `CREATE TABLE IF NOT EXISTS tinode.im_call_records( id BIGINT NOT NULL AUTO_INCREMENT, call_id VARCHAR(64) NOT NULL,