/** * 恢复 GroupChat.guid 字段并回填数据 * 线上旧架构代码仍在使用 guid 做多租户隔离,误删除导致所有按 guid 查询的 SQL 报错 42703 * * 用法: cd backend && npx tsx scripts/restore-guid-field.ts */ import 'dotenv/config'; import Parse from '../src/db/parse-client.js'; const GUID = process.env.QIWE_GUID || 'B8591A9D-B540-44F9-9D74-B2EF5B419EAA'; async function main(): Promise { console.log(`=== 恢复 GroupChat.guid 字段 ===`); console.log(`GUID: ${GUID}\n`); // 1. 检查字段是否已存在 const schemas = await Parse.Schema.all({ useMasterKey: true }); const groupChatSchema = schemas.find((s: any) => s.className === 'GroupChat'); if (!groupChatSchema) { console.error('❌ GroupChat 表不存在'); process.exit(1); } const existingFields = Object.keys(groupChatSchema.fields).filter((k: string) => !k.startsWith('_')); console.log(`当前 GroupChat 字段: ${existingFields.join(', ')}`); if (existingFields.includes('guid')) { console.log('\n✅ guid 字段已存在,跳过 schema 更新'); } else { // 2. 添加 guid 字段 const schema = new Parse.Schema('GroupChat'); schema.addField('guid', 'String'); await schema.update({ useMasterKey: true }); console.log('\n✅ 已添加 guid (String) 字段到 GroupChat'); } // 3. 回填所有缺少 guid 的记录 console.log('\n开始回填数据...'); const q = new Parse.Query('GroupChat'); q.doesNotExist('guid'); q.limit(500); const groups = await q.find({ useMasterKey: true }); console.log(`找到 ${groups.length} 条缺少 guid 的记录`); if (groups.length > 0) { const toSave: Parse.Object[] = []; for (const g of groups) { g.set('guid', GUID); toSave.push(g); } // 分批保存 for (let i = 0; i < toSave.length; i += 100) { const batch = toSave.slice(i, i + 100); await Parse.Object.saveAll(batch, { useMasterKey: true }); console.log(` 已回填 ${Math.min(i + 100, toSave.length)}/${toSave.length}`); } } // 4. 验证 const verifyQ = new Parse.Query('GroupChat'); verifyQ.equalTo('guid', GUID); verifyQ.limit(1); const test = await verifyQ.first({ useMasterKey: true }); if (test) { console.log(`\n✅ 验证通过: 成功查询到 guid='${GUID}' 的记录 (roomId=${test.get('roomId')})`); } else { console.log('\n⚠️ 验证失败: 未查询到匹配记录'); } console.log('\n✅ 恢复完成!'); } main().catch((err) => { console.error('❌ 失败:', err); process.exit(1); });