Files
workspace/code/fms/sql/tools/gen_workflow_sql.ps1
2026-09-22 22:41:36 +08:00

135 lines
5.5 KiB
PowerShell
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<#
从《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) 行"