Skip to content

Instantly share code, notes, and snippets.

@SylvainGuilbaud
Last active February 21, 2022 14:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SylvainGuilbaud/a10efd6e995a39b5527d1b9c235609bd to your computer and use it in GitHub Desktop.
Save SylvainGuilbaud/a10efd6e995a39b5527d1b9c235609bd to your computer and use it in GitHub Desktop.
How to efficiently store historical data, similar to current data, without mixing physical storage ?
Class data.archive.person Extends (%Persistent, data.current.person)
{
Parameter DEFAULTGLOBAL = "^off.person";
/// Description
ClassMethod archive(purgeArchive As %Integer = 0, purgeSource As %Integer = 0) As %Status
{
set sc = $$$OK , tableName = ""
set (archived,archivedErrors, severity) = 0
set sourceClassName = $PIECE(##class(%Dictionary.ClassDefinition).%OpenId(..%ClassName(1)).Super,",",2)
set targetClassName = ..%ClassName(1)
set sourceClass = ##class(%Dictionary.ClassDefinition).%OpenId(sourceClassName)
set targetClass = ##class(%Dictionary.ClassDefinition).%OpenId(targetClassName)
set sourceDataLocation = sourceClass.Storages.GetAt(1).DataLocation
set sourceIndexLocation = sourceClass.Storages.GetAt(1).IndexLocation
set sourceStreamLocation = sourceClass.Storages.GetAt(1).StreamLocation
set targetDataLocation = targetClass.Storages.GetAt(1).DataLocation
set targetIndexLocation = targetClass.Storages.GetAt(1).IndexLocation
set targetStreamLocation = targetClass.Storages.GetAt(1).StreamLocation
set tableName = $$$CLASSsqlschemaname($$$gWRK,sourceClassName) _"."_ $$$CLASSsqltablename($$$gWRK,sourceClassName)
if $ISOBJECT(sourceClass)
& $ISOBJECT(targetClass)
& tableName '= "" {
if $ISOBJECT(sourceClass.Storages.GetAt(1))
& $ISOBJECT(targetClass.Storages.GetAt(1))
{
set tStatement=##class(%SQL.Statement).%New(1)
kill sql
set sql($i(sql)) = "SELECT"
set sql($i(sql)) = "id"
set sql($i(sql)) = "FROM"
set sql($i(sql)) = tableName
set sc = tStatement.%Prepare(.sql)
set result = tStatement.%Execute()
kill:purgeArchive @targetDataLocation, @targetIndexLocation, @targetStreamLocation
while result.%Next() {
set source = $CLASSMETHOD(sourceClassName,"%OpenId",result.%Get("id"))
if $ISOBJECT(source) {
set archive = $CLASSMETHOD(targetClassName,"%New")
for i = 1:1:sourceClass.Properties.Count() {
set propertyName = sourceClass.Properties.GetAt(i).Name
set $PROPERTY(archive,propertyName) = $PROPERTY(source,propertyName)
}
set sc = archive.%Save()
if sc {
set archived = archived + 1
} else {
set archivedErrors = archivedErrors + 1
}
}
}
kill:purgeSource @sourceDataLocation, @sourceIndexLocation, @sourceStreamLocation
set msg ="archive data from " _ sourceClassName _ " into "_ targetClassName _ " result:" _ archived _ " archived (errors:" _ archivedErrors _ ")"
} else {
set severity = 1
set msg = "ERROR WHILE ARCHIVING " _ sourceClassName _ " in "_ targetClassName _ " : " _ " classes have not storage definition"
}
} else {
set severity = 1
set msg = "ERROR WHILE ARCHIVING " _ sourceClassName _ " in "_ targetClassName _ " : " _ " classes not found in %Dictionary.ClassDefinition"
}
do ##class(%SYS.System).WriteToConsoleLog(msg,0,severity)
Return sc
}
Storage Default
{
<Data name="personDefaultData">
<Value name="1">
<Value>%%CLASSNAME</Value>
</Value>
<Value name="2">
<Value>name</Value>
</Value>
<Value name="3">
<Value>dob</Value>
</Value>
<Value name="4">
<Value>activ</Value>
</Value>
<Value name="5">
<Value>created</Value>
</Value>
</Data>
<DataLocation>^off.personD</DataLocation>
<DefaultData>personDefaultData</DefaultData>
<IdLocation>^off.personD</IdLocation>
<IndexLocation>^off.personI</IndexLocation>
<StreamLocation>^off.personS</StreamLocation>
<Type>%Storage.Persistent</Type>
}
}
Class data.current.person Extends (%Persistent, %Populate)
{
Parameter DEFAULTGLOBAL = "^on.person";
Property name As %String;
Property dob As %Date(FORMAT = 4);
Property activ As %Boolean [ InitialExpression = 1 ];
Property created As %TimeStamp [ InitialExpression = {$zdt($h,3)} ];
Storage Default
{
<Data name="personDefaultData">
<Value name="1">
<Value>%%CLASSNAME</Value>
</Value>
<Value name="2">
<Value>name</Value>
</Value>
<Value name="3">
<Value>dob</Value>
</Value>
<Value name="4">
<Value>activ</Value>
</Value>
<Value name="5">
<Value>created</Value>
</Value>
</Data>
<DataLocation>^on.personD</DataLocation>
<DefaultData>personDefaultData</DefaultData>
<IdLocation>^on.personD</IdLocation>
<IndexLocation>^on.personI</IndexLocation>
<StreamLocation>^on.personS</StreamLocation>
<Type>%Storage.Persistent</Type>
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment