Question
· 22 hr ago

Data Repoint NULLS Data In New Class Table When Old Class Property Is Changed & Saved

We are attempting to "Repoint" old class data to new class data to save disk space and data redundancy across multiple tables. This works to a point.  In essence the two classes are sharing the same data / Index / stream globals.  But if an ID in the Old_Class is opened, a property is modified, and saved the property that is in the New_Class (but not in the Old_Class) is NULLed / blanked.

Simplified explanation of data and what’s occurring.

Old Class Values   New Class Values
First_Name John   First_Name John
Middle_Initial Q   Middle_Initial Q
Last_Name Public   Last_Name Public
Date_Of_Birth 1/1/1965   Date_Of_Birth 1/1/1965
SSN 123-45-6789   SSN 123-45-6789
      Marital_Status Married

When the Old_Class is opened and any field in the Old_Class is modified and a %Save is run the Marital_Status becomes NULL / Blank.

Why does a %Save on the Old_Class result in a NULL / Blank value in the data storage global and in the New_Class table?  We have already checked Journaling and it sets a null into the $List position for "Marital_Status".

Is there a means to open the record via the Old_Class alter a property value, and perform a %Save without “losing” the value in the Marital_Status field in the New_Class?

Product version: IRIS 2024.1
$ZV: IRIS for Windows (x86-64) 2024.1.4 (Build 512) Thu Apr 3 2025 11:46:12 EDT [Health:2.1.0+r1]
Discussion (9)3
Log in or sign up to continue
  • With %OpenId you create a complete internal local copy of your object
  • With %Save it is written back as complete as is was. NOT just changed properties as you might expect And non- defined properties vanish
  • Any change that happened in between from some other process is lost
  • You may need some locking logic to prevent simultaneous access by 2 instances  eg. locking the Id for exclusive access by 1 single  process.
  • In your case it may even happen in 1 process with Old_Class vs, New_Class

I'm not sure, do I understand you correctly... 
If you had a class and copied that class to a new class with some more properties, something like this

Class DC.OldData Extends %Persistent
{
Property FirstName As %String;
Property LastName As %String;

/// Redirect the %Open(), %OpenId() to the new class
///
ClassMethod %OnDetermineClass(oid As %ObjectIdentity, ByRef class As %String) As %Status [ ServerOnly = 1 ]
{
	Set class="DC.NewData"
	Quit $$$OK
}

/// Prevent creating a new instance of the old class
Method %OnNew() As %Status [ Private, ServerOnly = 1 ]
{
	Quit '$$$OK
}
}

Class DC.NewData Extends %Persistent
{
Property FirstName As %String;
Property LastName As %String;
Property MartialStatus As %String;
}

Robert,

We learned that when we were doing proof of concept on the idea of pointing an older class to the new classes data storage.

And I don't think locking is an issue, at least in my testing, because I was doing my testing on a local laptop install of IRIS so there was no contention with another process opening or changing the data.

I'm struggling to understand your original question "We are attempting to "Repoint" old class data to new class data to save disk space and data redundancy across multiple tables.  "

Will "Repoint"ing acutall save disk space?  At first glance it would be hard to see how that would make a significant difference.  It might be true that the old class has a number of properties that are no longer used so in the physical storage you have a number of unused storage element but I wouldnt think that would make a significant difference.  

One area that can make a difference is if your classes utilize bitmap indices and if you have rapidly changing data with fields are indexed.  IRIS delivers %SYS.Maint.Bitmap which is described as 

This utility is used to compact bitmap/bitslice indices. Over time in a volatile table (think lots of INSERTs and DELETEs) the storage for a bitmap index may become less efficient. To a lesser extent index value changes, i.e. UPDATES, can also degrade bitmap performance.

This utility can by run on a live system. It will loop over all bitmap/bitslice indices in a class or namespace and compact them by either removing a chunk that is all zeros or by using $BITLOGIC() to compact the bits.

Consider Ens.MessageHeader which has a bitmap index on Status where the Status values are 

1=Crerated

2=Queued

3=Delivered

4=Discarded

5=Suspended

6=Deferred

7=Aborted

8=Error

9=Completed

You can imagine that a Message Header is save with 

Event 1 Status=Created

Event 2  Status=Queued

Event 3  Status=Delivered

Event 4 Status = Completed

in the normal course of processing

This would have the side effect of 

1. Event 1 setting the Status =Created bit on

2. Event 2 Setting the Status=Created bit Off, Setting the Status=Queued On

3. Event 3 Setting the Status=Queued bit Off, Setting the Status=Delivered On

4. Event 4 Setting the Status=Delivered bit Off, Setting the Status=Completed On

all of this means that the bitmap index for 

Status=Created, Queued, Delivered over time is just a series of off bits and in many cases the entire bitchunk is just a bunch of off bits(although there is some compression here).

I have utilized  %SYS.Maint.Bitmap on systems that have existed for many years and saw some noticable space savings.  However, once run it doesnt seem to make a lot of sense to run very often.