import fs from 'node:fs'; import {spawnSync} from 'node:child_process'; const dir = new URL('./', import.meta.url); const schema=process.argv.includes('--firstleg')?'baiyue_firstleg':'baiyue_lastleg'; const prefix=schema==='baiyue_firstleg'?'firstleg-':''; function definitions(body) { let depth=0,quote='',start=0;const parts=[]; for(let i=0;i0 && /NOT NULL/i.test(definition) && !/DEFAULT|AUTO_INCREMENT/i.test(definition)) { unsafe.push({table,column:field[1],count,definition,handling:'历史行保留NULL,不伪造业务事实;新写入由应用校验'}); appliedDefinition=definition.replace(/NOT NULL/i,'NULL'); } plan.push('ALTER TABLE `'+table+'` ADD COLUMN '+appliedDefinition+';');addedColumns.push(table+'.'+field[1]); } } const report={baselineTables:tables.length,actualTables:current.size,addedTables,addedColumns,unsafe}; fs.writeFileSync(new URL(prefix+'plan.json',dir),JSON.stringify(report,null,2)); fs.writeFileSync(new URL(prefix+'incremental.sql',dir),'-- 本地服务结构补齐;仅创建缺失表、添加缺失字段,不删除现有数据。\nSET NAMES utf8mb4;\n'+plan.join('\n\n')+'\n'); console.log(JSON.stringify(report,null,2)); if(process.argv.includes('--apply')) { mysql('SET SESSION lock_wait_timeout=15;\n'+plan.join('\n'));fs.appendFileSync(new URL(prefix+'applied.log',dir),`${new Date().toISOString()} ${plan.length} DDL applied\n`); console.log('APPLIED '+plan.length); }