2026-08-08 15:25:46 +08:00
param (
[ switch ] $DryRun ,
[ Alias ( 'Host' )][ string ] $TargetHost = '127.0.0.1' ,
[ int ] $Port = 3306 ,
[ string ] $MysqlExe = 'C:\Program Files\MySQL\MySQL Server 8.4\bin\mysql.exe' ,
2026-09-09 23:46:21 +08:00
[ string ] $User = 'root' ,
[ ValidateRange ( 1 , 10 )][ int ] $Rounds = 2
2026-08-08 15:25:46 +08:00
)
$ErrorActionPreference = 'Stop'
$Repo = ( Resolve-Path ( Join-Path $PSScriptRoot '..' )). Path
$Workspace = ( Resolve-Path ( Join-Path $Repo '..' )). Path
2026-09-09 23:46:21 +08:00
$ReportRoot = Join-Path $Workspace '.codex-tmp\local-db-full-acceptance'
$DomesticSql = Join-Path $Repo 'deploy\sql\头程数据库统一增量-MySQL8.sql'
$OverseasSql = Join-Path $Repo 'deploy\sql\海外区域统一增量-MySQL8.sql'
$Schemas = @ (
'baiyue_auth' , 'baiyue_iam' , 'baiyue_order' , 'baiyue_warehouse' ,
'baiyue_firstleg' , 'baiyue_file' , 'baiyue_audit' , 'baiyue_event_bridge' ,
'baiyue_finance' , 'baiyue_lastleg' , 'baiyue_lastlag_warehouse' ,
'baiyue_event_bridge_overseas'
)
2026-08-08 15:25:46 +08:00
if ( $TargetHost -notin @ ( '127.0.0.1' , 'localhost' )) {
[ Console ]:: Error . WriteLine ( 'Refusing non-local database; only 127.0.0.1 or localhost is allowed.' )
exit 2
}
2026-09-09 23:46:21 +08:00
if ( -not ( Test-Path -LiteralPath $MysqlExe )) {
[ Console ]:: Error . WriteLine ( "mysql executable does not exist: $MysqlExe " )
2026-08-08 15:25:46 +08:00
exit 2
}
2026-09-09 23:46:21 +08:00
foreach ( $sqlFile in @ ( $DomesticSql , $OverseasSql )) {
if ( -not ( Test-Path -LiteralPath $sqlFile )) {
[ Console ]:: Error . WriteLine ( "Unified SQL does not exist: $sqlFile " )
2026-08-11 18:06:26 +08:00
exit 2
}
}
2026-09-09 23:46:21 +08:00
$DomesticText = [ IO.File ]:: ReadAllText ( $DomesticSql )
$OverseasText = [ IO.File ]:: ReadAllText ( $OverseasSql )
if ( -not $DomesticText . Contains ( "SELECT 'PASS' AS migration_status" )) {
[ Console ]:: Error . WriteLine ( 'Domestic unified SQL is missing its final PASS statement.' )
2026-08-11 18:06:26 +08:00
exit 2
}
2026-09-09 23:46:21 +08:00
foreach ( $marker in @ (
'-- BEGIN INLINE EMPTY-DATABASE BASELINE: LASTLEG' ,
'-- BEGIN INLINE EMPTY-DATABASE BASELINE: OVERSEAS WAREHOUSE' ,
"SELECT 'PASS' AS migration_status"
)) {
if ( -not $OverseasText . Contains ( $marker )) {
[ Console ]:: Error . WriteLine ( "Overseas unified SQL is missing marker: $marker " )
exit 2
}
}
2026-08-08 15:25:46 +08:00
2026-09-09 23:46:21 +08:00
$DomesticHash = ( Get-FileHash -Algorithm SHA256 -LiteralPath $DomesticSql ). Hash
$OverseasHash = ( Get-FileHash -Algorithm SHA256 -LiteralPath $OverseasSql ). Hash
2026-08-08 15:25:46 +08:00
Write-Output "Target: $TargetHost `: $Port "
2026-09-09 23:46:21 +08:00
Write-Output "Rounds: $Rounds "
Write-Output "Domestic SQL: $DomesticHash / $([ IO.File ]:: ReadAllLines ( $DomesticSql ). Length ) lines"
Write-Output "Overseas SQL: $OverseasHash / $([ IO.File ]:: ReadAllLines ( $OverseasSql ). Length ) lines"
Write-Output "Reset scope: $( $Schemas -join ', ' ) "
Write-Output 'Execution order per round: clear exact schemas -> domestic unified SQL -> overseas unified SQL -> final PASS and schema checks'
if ( $DryRun ) {
Write-Output 'DRY-RUN PASS (mysql not contacted; no database writes)'
exit 0
}
2026-08-08 15:25:46 +08:00
2026-09-09 23:46:21 +08:00
New-Item -ItemType Directory -Path $ReportRoot -Force | Out-Null
$StagedDomestic = Join-Path $ReportRoot 'domestic.sql'
$StagedOverseas = Join-Path $ReportRoot 'overseas.sql'
Copy-Item -LiteralPath $DomesticSql -Destination $StagedDomestic -Force
Copy-Item -LiteralPath $OverseasSql -Destination $StagedOverseas -Force
if (( Get-FileHash -Algorithm SHA256 -LiteralPath $StagedDomestic ). Hash -ne $DomesticHash -or
( Get-FileHash -Algorithm SHA256 -LiteralPath $StagedOverseas ). Hash -ne $OverseasHash ) {
[ Console ]:: Error . WriteLine ( 'Failed to stage byte-identical SQL files under ASCII filenames.' )
2026-08-11 18:06:26 +08:00
exit 2
}
2026-09-09 23:46:21 +08:00
$MysqlCommon = @ (
'--protocol=TCP' , "--host= $TargetHost " , "--port= $Port " , "--user= $User " ,
'--default-character-set=utf8mb4' , '--batch'
)
& $MysqlExe @MysqlCommon '--skip-column-names' '--execute=SELECT VERSION(), @@hostname, @@port;' | Out-Null
if ( $LASTEXITCODE -ne 0 ) {
[ Console ]:: Error . WriteLine ( 'Cannot connect to the local MySQL target. Configure authentication outside this script, for example with MYSQL_PWD for the current process.' )
exit $LASTEXITCODE
2026-08-08 15:25:46 +08:00
}
2026-09-09 23:46:21 +08:00
$DropSql = ( $Schemas | ForEach-Object { "DROP DATABASE IF EXISTS `` $_ `` `;" }) -join ' '
for ( $round = 1 ; $round -le $Rounds ; $round ++) {
$RoundRoot = Join-Path $ReportRoot ( "round-{0}" -f $round )
New-Item -ItemType Directory -Path $RoundRoot -Force | Out-Null
$Stopwatch = [ Diagnostics.Stopwatch ]:: StartNew ()
& $MysqlExe @MysqlCommon "--execute= $DropSql " *> ( Join-Path $RoundRoot '00-clear.log' )
if ( $LASTEXITCODE -ne 0 ) {
[ Console ]:: Error . WriteLine ( "Round $round failed while clearing the exact project schemas." )
exit $LASTEXITCODE
}
$DomesticLog = Join-Path $RoundRoot '10-domestic.log'
$DomesticSource = $StagedDomestic . Replace ( '\' , '/' )
& $MysqlExe @MysqlCommon '--database=mysql' "--execute=source $DomesticSource " *> $DomesticLog
if ( $LASTEXITCODE -ne 0 -or -not ( Select-String -LiteralPath $DomesticLog -Pattern '^PASS\s+统一增量全部执行完成' -Quiet )) {
[ Console ]:: Error . WriteLine ( "Round $round domestic unified SQL failed. See $DomesticLog " )
exit $ ( if ( $LASTEXITCODE -ne 0 ) { $LASTEXITCODE } else { 2 })
}
$OverseasLog = Join-Path $RoundRoot '20-overseas.log'
$OverseasSource = $StagedOverseas . Replace ( '\' , '/' )
& $MysqlExe @MysqlCommon '--database=mysql' "--execute=source $OverseasSource " *> $OverseasLog
if ( $LASTEXITCODE -ne 0 -or -not ( Select-String -LiteralPath $OverseasLog -Pattern '^PASS\s+海外财务P0费用来源字段已就绪$' -Quiet )) {
[ Console ]:: Error . WriteLine ( "Round $round overseas unified SQL failed. See $OverseasLog " )
exit $ ( if ( $LASTEXITCODE -ne 0 ) { $LASTEXITCODE } else { 2 })
}
$SchemaList = "'" + ( $Schemas -join "','" ) + "'"
$SchemaCount = (& $MysqlExe @MysqlCommon '--skip-column-names' "--execute=SELECT COUNT(*) FROM information_schema.schemata WHERE schema_name IN ( $SchemaList );" ). Trim ()
if ( $LASTEXITCODE -ne 0 -or [ int ] $SchemaCount -ne $Schemas . Count ) {
[ Console ]:: Error . WriteLine ( "Round $round schema verification failed: $SchemaCount / $( $Schemas . Count ) " )
exit 2
}
$Stopwatch . Stop ()
Write-Output "ROUND $round PASS / $SchemaCount schemas / $([ Math ]:: Round ( $Stopwatch . Elapsed . TotalSeconds , 1 )) seconds"
}
Write-Output 'FULL LOCAL TWO-REGION DATABASE ACCEPTANCE PASS'
2026-08-08 15:25:46 +08:00
exit 0