130 lines
6.0 KiB
PowerShell
130 lines
6.0 KiB
PowerShell
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',
|
|
[string]$User = 'root',
|
|
[ValidateRange(1, 10)][int]$Rounds = 2
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
$Repo = (Resolve-Path (Join-Path $PSScriptRoot '..')).Path
|
|
$Workspace = (Resolve-Path (Join-Path $Repo '..')).Path
|
|
$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'
|
|
)
|
|
|
|
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
|
|
}
|
|
if (-not (Test-Path -LiteralPath $MysqlExe)) {
|
|
[Console]::Error.WriteLine("mysql executable does not exist: $MysqlExe")
|
|
exit 2
|
|
}
|
|
foreach ($sqlFile in @($DomesticSql, $OverseasSql)) {
|
|
if (-not (Test-Path -LiteralPath $sqlFile)) {
|
|
[Console]::Error.WriteLine("Unified SQL does not exist: $sqlFile")
|
|
exit 2
|
|
}
|
|
}
|
|
|
|
$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.')
|
|
exit 2
|
|
}
|
|
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
|
|
}
|
|
}
|
|
|
|
$DomesticHash = (Get-FileHash -Algorithm SHA256 -LiteralPath $DomesticSql).Hash
|
|
$OverseasHash = (Get-FileHash -Algorithm SHA256 -LiteralPath $OverseasSql).Hash
|
|
Write-Output "Target: $TargetHost`:$Port"
|
|
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
|
|
}
|
|
|
|
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.')
|
|
exit 2
|
|
}
|
|
|
|
$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
|
|
}
|
|
|
|
$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'
|
|
exit 0
|