原文链接
修改后代码
Class WYJ.ToolsMethod Extends %RegisteredObject
{
/// Description: 通过journal日志文件恢复删除的global
/// Creator: YX
/// Modify: WYJ
/// Input: filepath-journal文件全名,为空则打开最后一个journal(windos:d:\journal\journal\20230221.001
/// globalName-要恢复的global名
/// offset-开始偏移量
/// end-结束偏移量
/// w ##class(WYJ.ToolsMethod).RestoreGlobal("d:\journal\journal\20230221.001", "^DHCINPO",22253844, 22255216)
ClassMethod RestoreGlobal(filepath As %String = "", globalName As %String, offset As %Integer = 0, end As %Integer = 100000) As %Status [ ProcedureBlock = 0 ]
{
i filepath = "" {
s filepath = ##class(%SYS.Journal.System).GetCurrentFileName()
}
s obj = ##class(%SYS.Journal.File).%OpenId(filepath)
q:('$IsObject(obj)) "打开journal文件 "_filepath_" 失败,请检查日志文件名是否正确"
q:(globalName = "") "目标global为空不允许恢复"
# dim mSetKillRecordObj as %SYS.Journal.SetKillRecord
#; 为空则从头开始找
s:(offset = 0) mSetKillRecordObj = obj.FirstRecord
s:(offset > 0) mSetKillRecordObj = obj.GetRecordAt(offset)
#; 如果输入的Offset不存在,则寻找下一条记录
s:(mSetKillRecordObj = "") mSetKillRecordObj = obj.GetRecordAfter(offset)
s currentAddress = offset
while($isobject(mSetKillRecordObj) = 1)
{
#; 说明已经是最后一条,退出循环
q:($g(mSetKillRecordObj) = "")
#;说明已经是最后一个偏移量,退出循环
if ((end '= "")&&(mSetKillRecordObj.Address > end)) {
q
}
#; 过滤Begintrans\EndTrans\SET,只留下KILL
if ((mSetKillRecordObj.TypeName '= "KILL"))
{
#;跳到下一条记录
s mSetKillRecordObj = obj.GetRecordAfter(mSetKillRecordObj.Address)
continue
}
#; 取GlobalNode节点
s globalNode = mSetKillRecordObj.GlobalNode
#; 取global的名字
s masterGlobal = $p(globalNode,"(",1)
#; 过滤非目标Global 如果主数据和索引global不一样这里可以改为判断包含关系
if (masterGlobal '= globalName)
{
#; 跳到下一条记录
s mSetKillRecordObj = obj.GetRecordAfter(mSetKillRecordObj.Address)
continue
}
#; 取新值,删除的话为空
s newValue = mSetKillRecordObj.NewValue
#; 取旧值,需要回复的数据
s oldValue = mSetKillRecordObj.OldValue
#; 取Global下标节点,也就是ID
//s id = $qsubscript(globalNode, 1)
#; 给ID赋值,否则ID顺序自增
//s @masterGlobal = (id - 1)
s str = "s "_globalNode _"="""_oldValue_""""
//重新set global x 前建议先把 str write出来看下对着没
w str,!
x str //确定没问题了再放开
s mSetKillRecordObj = obj.GetRecordAfter(mSetKillRecordObj.Address)
}
q $$$OK
}
}
希望以后不要再用到了…