Article
Evgeny Shvarov · Feb 19, 2022 2m read

Globals Data Storage Created via DDL and From ObjectScript Can be Different

Hey developers!

Sometimes we need to insert or refer to the data of classes directly in globals.

And maybe a lot of you expect that data structure of global with records is:

^Sample.Person(Id)=$listbuild("",col1,col2,...,coln).

And this article is a heads up, that this is not always true, don't expect it as granted!

To get the global structure try the following class code. Create a class in IRIS:

Class Sample.Person Extends %Persistent 
{
Property Surname As %Library.String(MAXLEN = 50) [ Required, SqlColumnNumber = 2 ];
Property Name As %Library.String(MAXLEN = 50) [ SqlColumnNumber = 3 ];
Parameter DEFAULTGLOBAL = "^Sample.Person";
Parameter USEEXTENTSET = 1;
}

And insert records via SQL (e.g. via DBeaver):

INSERT INTO Sample.Person VALUES ('Doe','John')

INSERT INTO Sample.Person VALUES ('Smith','Adam')

You can see the global via:

IRISAPP>zw ^Sample.Person.1
^Sample.Person.1=2
^Sample.Person.1(1)=$lb("","Doe","John")
^Sample.Person.1(2)=$lb(,"Smith","Adam")

Notice, the first segment of $LB is "- it's usually empty if your class is derived directly from %Persistent.

But if you create the class from DDL and insert a few lines you'll notice that the storage is different. It is:

^Sample.Person(Id)=$listbuild(col1,col,2,...,coln)

There is no first empty element. 

Reproducing. Let's first delete the class and data:

DROP TABLE Sample.Person

Create the same Class via DDL:

CREATE TABLE Sample.Person (

   Surname VARCHAR(50) NOT NULL,

   Name VARCHAR(50) 

)  WITH %CLASSPARAMETER DEFAULTGLOBAL = '^Sample.Person'

Insert records as above. Print the global:

IRISAPP>zw ^Sample.Person.1
^Sample.Person.1=2
^Sample.Person.1(1)=$lb("Doe","John")
^Sample.Person.1(2)=$lb("Smith","Adam")

IRISAPP>

Turned out that when a class is created via DDL it generates it with a Final clause, which means that classes inheritance is not allowed (why BTW?). 

Class Sample.Person Extends %Persistent [ ClassType = persistent, DdlAllowed, Final, Owner = {_SYSTEM}, ProcedureBlock, SqlRowIdPrivate, SqlTableName = Person ]

And means that in this case, this element is "useless".

But if you expected it this could be confusing.

8
0 263
Discussion (1)1
Log in or sign up to continue

Turned out, that this behavior can be adjusted by removing the Final clause from DDL generation via the following flag:

set sc=$SYSTEM.SQL.Util.SetOption("DDLFinal",0,.oldval)