-- MySQL 8.0. Runtime fixes for the shared meeting_im database. -- Execute with a privileged account that can read hotgo.im_tenant. CREATE TABLE IF NOT EXISTS im_user_account_sequences ( tenant_id BIGINT NOT NULL, id TINYINT UNSIGNED NOT NULL, next_value INT UNSIGNED NOT NULL, updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), PRIMARY KEY (tenant_id, id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; -- If this table was created by the older independent-database script, its -- primary key may still be only (id). Shared DB must key by tenant_id too. ALTER TABLE im_user_account_sequences DROP PRIMARY KEY, ADD PRIMARY KEY (tenant_id, id); INSERT INTO im_user_account_sequences (tenant_id, id, next_value) SELECT tenant_id, 1, GREATEST(COALESCE(MAX(account_no), 999), 999) FROM im_users WHERE tenant_id > 0 GROUP BY tenant_id ON DUPLICATE KEY UPDATE next_value = GREATEST(next_value, VALUES(next_value)); INSERT IGNORE INTO im_user_account_sequences (tenant_id, id, next_value) SELECT id, 1, 999 FROM hotgo.im_tenant WHERE state = 1; CREATE TABLE IF NOT EXISTS im_login_lockouts ( id BIGINT NOT NULL, user_id BIGINT NULL, account_hash CHAR(64) NOT NULL, failed_attempts INT NOT NULL DEFAULT 0, window_started_at DATETIME(3) NULL, locked_until DATETIME(3) NULL, last_attempt_at DATETIME(3) 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_login_lockouts_account (account_hash), INDEX idx_im_login_lockouts_user (user_id), INDEX idx_im_login_lockouts_locked (locked_until) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; -- HTTP write idempotency must be tenant scoped in the shared meeting_im DB. CREATE TABLE IF NOT EXISTS im_http_idempotency ( id BIGINT NOT NULL AUTO_INCREMENT, tenant_id BIGINT NOT NULL DEFAULT 0, user_id BIGINT NOT NULL, method VARCHAR(8) NOT NULL, route VARCHAR(512) NOT NULL, idempotency_key VARCHAR(128) NOT NULL, body_hash CHAR(64) NOT NULL, state VARCHAR(16) NOT NULL DEFAULT 'processing', response_status INT NOT NULL DEFAULT 0, response_body MEDIUMBLOB, expires_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_http_idempotency_scope (tenant_id, user_id, method, route, idempotency_key), INDEX idx_im_http_idempotency_expiry (expires_at) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; ALTER TABLE im_http_idempotency ADD COLUMN tenant_id BIGINT NOT NULL DEFAULT 0 AFTER id; ALTER TABLE im_http_idempotency DROP INDEX uk_im_http_idempotency_scope; ALTER TABLE im_http_idempotency ADD UNIQUE INDEX uk_im_http_idempotency_scope (tenant_id, user_id, method, route, idempotency_key); -- User identity indexes must be unique inside one tenant, not globally. ALTER TABLE im_users DROP INDEX uk_im_users_account_no, DROP INDEX users_phone, DROP INDEX users_username, ADD UNIQUE INDEX uk_im_users_tenant_account_no (tenant_id, account_no), ADD UNIQUE INDEX uk_im_users_tenant_phone (tenant_id, phone), ADD UNIQUE INDEX uk_im_users_tenant_username (tenant_id, username); ALTER TABLE im_auth DROP INDEX auth_userid, ADD UNIQUE INDEX auth_tenant_userid (tenant_id, userid); -- Default app release rows used by /v1/im/app/releases/latest. INSERT INTO hotgo.im_app_releases ( platform, channel, latest_version, min_supported_version, update_type, release_notes, remind_after_seconds ) VALUES ('ios', 'stable', '1.0.0', '1.0.0', 'none', '当前已是最新版本。', 0), ('android', 'stable', '1.0.0', '1.0.0', 'none', '当前已是最新版本。', 0), ('web', 'stable', '1.0.0', '1.0.0', 'none', '当前已是最新版本。', 0) ON DUPLICATE KEY UPDATE latest_version = VALUES(latest_version), min_supported_version = VALUES(min_supported_version), update_type = VALUES(update_type), release_notes = VALUES(release_notes), remind_after_seconds = VALUES(remind_after_seconds), updated_at = CURRENT_TIMESTAMP(3);