scripts/j22-introspect.ps1
@@ -40,6 +40,10 @@
# 只允许常规库名/表名:库名与表名会被拼进查询(标识符不能用参数),异常字符一律跳过。
function Test-SafeName([string]$name) { return $name -match '^[A-Za-z0-9_$]+$' }
# 测试库是 DB_<起始时间>:取数程序只读这些,其余库从来没有看过,所以本探查只看其余库。
# 注意这里用的是 PowerShell 通配符:* 才是"任意字符",% 只是普通字符——不要照抄 SQL 的 LIKE 写法。
function Test-TestDatabase([string]$name) { return $name -like 'DB_*' }
# 所有查询都经过这里:显式设 CommandTimeout,读满即断,不发加锁读、不开启事务。
function Invoke-ReadOnlyQuery($connection, [string]$sql) {
    $command = $connection.CreateCommand()
@@ -88,7 +92,7 @@
    $tests = New-Object System.Collections.ArrayList
    $others = New-Object System.Collections.ArrayList
    foreach ($row in $all) {
        if ([string]$row[0] -like 'DB[_]%') { [void]$tests.Add($row) } else { [void]$others.Add($row) }
        if (Test-TestDatabase ([string]$row[0])) { [void]$tests.Add($row) } else { [void]$others.Add($row) }
    }
    if ($Database) {
@@ -108,8 +112,11 @@
            [void]$targets.Add([string]$row[0])
            $index++
        }
        if ($others.Count -gt 0 -and $others.Count -le 20) {
            Say ("  其他库清单:" + (($others | ForEach-Object { [string]$_[0] }) -join '、'))
        if ($others.Count -gt 0) {
            # 前几个名字一定打出来:库名本身就能看出这批库是干什么的。
            $preview = ($others | Select-Object -First 10 | ForEach-Object { [string]$_[0] }) -join '、'
            $suffix = if ($others.Count -gt 10) { ' …' } else { '' }
            Say ("  其他库前 10 个:" + $preview + $suffix)
        }
    }
    if ($targets.Count -eq 0) {