135 lines
5.5 KiB
PowerShell
135 lines
5.5 KiB
PowerShell
<#
|
||
从《FMS新系统核心表结构设计》第 16 节生成 sql/fms_workflow.sql
|
||
|
||
用法(任意目录均可执行):
|
||
pwsh -File sql/tools/gen_workflow_sql.ps1
|
||
|
||
约定:
|
||
- §16 是表结构的唯一来源;改完文档重跑本脚本,不要手改生成物;
|
||
- 生成物与 sql/fms_core.sql 同风格:GO 分隔、UTF-8 无 BOM;
|
||
- SQL Server 不支持建表内联注释,列注释同时写入扩展属性 MS_Description;
|
||
- 枚举在文档的列注释里按「编码(中文)」书写,脚本原样搬运到注释和扩展属性。
|
||
#>
|
||
[CmdletBinding()]
|
||
param(
|
||
[string]$Doc,
|
||
[string]$Section = '## 16. 工作流与审批',
|
||
[string]$Out
|
||
)
|
||
|
||
$ErrorActionPreference = 'Stop'
|
||
|
||
$root = Split-Path (Split-Path $PSScriptRoot)
|
||
if (-not $Doc) { $Doc = Join-Path $root 'FMS新系统核心表结构设计.md' }
|
||
if (-not $Out) { $Out = Join-Path $root 'sql\fms_workflow.sql' }
|
||
|
||
if (-not (Test-Path -LiteralPath $Doc)) { throw "找不到文档:$Doc" }
|
||
$text = Get-Content -Raw -Encoding UTF8 -LiteralPath $Doc
|
||
|
||
$start = $text.IndexOf($Section)
|
||
if ($start -lt 0) { throw "文档中找不到章节:$Section" }
|
||
$sec = $text.Substring($start)
|
||
|
||
$buf = [System.Collections.Generic.List[string]]::new()
|
||
$head = @(
|
||
'/* ============================================================================'
|
||
' FMS 工作流与审批表建表脚本(wf_*)'
|
||
''
|
||
' 依据文档:FMS新系统核心表结构设计.md §16 工作流与审批'
|
||
' 语义设计见 FMS工作流与审批设计.md'
|
||
''
|
||
' 使用说明:'
|
||
' 1. 执行前先切换到目标数据库(USE [数据库名])。'
|
||
' 2. 脚本只建表、索引和说明属性,不含初始化数据。'
|
||
' 3. 不使用外键、CHECK、触发器;关联完整性和业务校验由业务层处理。'
|
||
' 4. SQL Server 不支持建表内联注释,列注释通过扩展属性 MS_Description 持久化,'
|
||
' SSMS 的表设计器和列属性说明直接读取。'
|
||
' 5. 脚本按新建表编写;表已存在时需先删除后重新执行。'
|
||
' ============================================================================ */'
|
||
''
|
||
'SET NOCOUNT ON;'
|
||
'GO'
|
||
''
|
||
)
|
||
[void]$buf.AddRange([string[]]$head)
|
||
|
||
$rxSection = [regex]'(?s)### (16\.\d+) ([^\r\n]+)\r?\n.*?```sql\r?\n(.*?)```'
|
||
$tableCount = 0
|
||
$propCount = 0
|
||
|
||
foreach ($m in $rxSection.Matches($sec)) {
|
||
$num = $m.Groups[1].Value
|
||
$title = $m.Groups[2].Value.Trim()
|
||
$lines = $m.Groups[3].Value -split '\r?\n'
|
||
|
||
$ddl = [System.Collections.Generic.List[string]]::new()
|
||
$idx = [System.Collections.Generic.List[string]]::new()
|
||
$cols = [System.Collections.Generic.List[object]]::new()
|
||
$tbl = ''
|
||
$tblCmt = ''
|
||
$inTable = $false
|
||
|
||
for ($i = 0; $i -lt $lines.Count; $i++) {
|
||
$ln = $lines[$i]
|
||
|
||
if (-not $inTable -and $ln -match '^create table dbo\.(\w+) \(') {
|
||
$tbl = $Matches[1]
|
||
if ($i -gt 0 -and $lines[$i - 1] -match '^--\s*(.+)$') { $tblCmt = $Matches[1].Trim() }
|
||
$inTable = $true
|
||
$ddl.Add($ln)
|
||
continue
|
||
}
|
||
if ($inTable) {
|
||
$ddl.Add($ln)
|
||
if ($ln -match '^\);\s*$') { $inTable = $false; continue }
|
||
if ($ln -match '^\s*([a-z_][a-z0-9_]*)\s+.*?,\s*--\s*(.+?)\s*$') { $cols.Add([pscustomobject]@{ n = $Matches[1]; c = $Matches[2] }); continue }
|
||
if ($ln -match '^\s*([a-z_][a-z0-9_]*)\s+.*?\s+--\s*(.+?)\s*$') { $cols.Add([pscustomobject]@{ n = $Matches[1]; c = $Matches[2] }); continue }
|
||
continue
|
||
}
|
||
if ($ln -match '^create (unique )?index') { $idx.Add($ln); continue }
|
||
if ($ln -match '^\s+on dbo\.' -and $idx.Count -gt 0) { $idx[$idx.Count - 1] = $idx[$idx.Count - 1] + "`n" + $ln }
|
||
}
|
||
|
||
if (-not $tbl) { continue }
|
||
$tableCount++
|
||
|
||
$buf.Add('/* ============================================================================')
|
||
$buf.Add(" $num $title")
|
||
$buf.Add(' ============================================================================ */')
|
||
$buf.Add('')
|
||
foreach ($l in $ddl) { $buf.Add($l) }
|
||
$buf.Add('GO'); $buf.Add('')
|
||
foreach ($s in $idx) {
|
||
foreach ($sl in ($s -split "`n")) { $buf.Add($sl) }
|
||
$buf.Add('GO'); $buf.Add('')
|
||
}
|
||
|
||
$buf.Add('-- 说明属性(MS_Description):SSMS 表设计器与列属性说明的来源')
|
||
$val = $tblCmt.Replace("'", "''")
|
||
$buf.Add("exec sys.sp_addextendedproperty @name=N'MS_Description', @value=N'$val',")
|
||
$buf.Add(" @level0type=N'SCHEMA', @level0name=N'dbo', @level1type=N'TABLE', @level1name=N'$tbl';")
|
||
$propCount++
|
||
foreach ($c in $cols) {
|
||
$cv = $c.c.Replace("'", "''")
|
||
$buf.Add("exec sys.sp_addextendedproperty @name=N'MS_Description', @value=N'$cv',")
|
||
$buf.Add(" @level0type=N'SCHEMA', @level0name=N'dbo', @level1type=N'TABLE', @level1name=N'$tbl', @level2type=N'COLUMN', @level2name=N'$($c.n)';")
|
||
$propCount++
|
||
}
|
||
$buf.Add('GO'); $buf.Add('')
|
||
}
|
||
|
||
if ($tableCount -eq 0) { throw "章节 $Section 中没有解析到建表语句" }
|
||
|
||
$new = ($buf -join "`r`n") + "`r`n"
|
||
|
||
$changed = $true
|
||
if (Test-Path -LiteralPath $Out) {
|
||
$old = [System.IO.File]::ReadAllText($Out, [System.Text.Encoding]::UTF8)
|
||
$changed = ($old -ne $new)
|
||
}
|
||
|
||
[System.IO.File]::WriteAllText($Out, $new, (New-Object System.Text.UTF8Encoding($false)))
|
||
|
||
$state = if ($changed) { '已更新' } else { '无变化' }
|
||
Write-Output "$state:$Out"
|
||
Write-Output "表 $tableCount 张、说明属性 $propCount 条、生成 $($buf.Count) 行" |