Written by

IRIS Developer Advocate, Software developer at CaretDev, Tabcorp
Discussion Dmitry Maslennikov · Nov 9, 2020

%session.Data with unlimited amount of indexes

Let's imagine you have to implement a method with a definition

/// Set value to %session.Data
ClassMethod setValue(params...) As %Status
{
}

How it should work

do ..setValue("key1", "val")

is equal to

set %session.Data("key1") = "val"

and 

do ..setValue("key1", "key2", "key3", "key4", "val")

is equal to 

set %session.Data("key1", "key2", "key3", "key4") = "val"

so, quite simple, any amount of arguments, while the latest one is a value, and any previous is an index, should accept at least 2 arguments.

How would you implement this method?

Comments

Robert Cemper · Nov 9, 2020
/// Set value to %session.Data 
ClassMethod setValue(params...) As %Status
{
 quit:params<2 0
 set var="%session.Data("
 for i=1:1:params-1 set var=var_""""_params(i)_""","
 set $e(var,*)=")"
 set @var=params(params)
 quit $$$OK
}
0
Dmitry Maslennikov  Nov 9, 2020 to Robert Cemper

Quite simple, but could be even better, with no useless quotations

0
Robert Cemper  Nov 9, 2020 to Dmitry Maslennikov

did you mean that ?

/// Set value to %session.Data 
ClassMethod setValue(params...) As %Status
{
quit:params<2 0
set var="%session.Data("
for i=1:1:params-1 set var=var_"params("_i_"),"
set $e(var,*)=")"
set @var=params(params)
quit $$$OK
}
0
Dmitry Maslennikov  Nov 9, 2020 to Robert Cemper

Nope, still not what I mean, I have a better solution, just would like to see if the community will find it.

0
Robert Cemper  Nov 9, 2020 to Robert Cemper

it doesn' trap this cases yet

do ..setValue("key1", "key2", , "key4", "val")
do ..setValue("key1", "key2", "", "key4", "val")
0
Sergey Mikhailenko · Nov 9, 2020

Hey.
It's easier ?
```
ClassMethod 
setValue(params...) As %Status
{
  quit:params<2 0
  s name="%session.Data"
  for i=1:1:params-1 set:$GET(params(i))'="" name=$NA(@name@(params(i)))
  set @name=params(params)
  quit $$$OK
}
```

0
Dmitry Maslennikov  Nov 9, 2020 to Sergey Mikhailenko

Yes, this is better, I would even use this

s name=$name(%session.Data)
0
Robert Cemper  Nov 9, 2020 to Alexander Klimov

with error trapping

/// Set value to %session.Data 
ClassMethod setValue(params...) As %Status
{
 try {
   set var=$name(%session.Data)
   for i=1:1:params-1 set var=$name(@var@(params(i)))
   set @var=$g(params(params))
   set status=$$$OK
  }
  catch { set status=$system.Status.Error(710)
  }
  quit status 
 }
0
Julius Kavay · Nov 9, 2020

I'm not sure about what you mean with "unlimited amount of indexes"...

first, there is a limit of 255 for the parameters, this means you can have 

do ..setValue(key1,key2,...key254,value)

but you can't have 

 do ..setValue(key1,key2,...key254,key255,value)

second, if you meant to have many-many values (in sense of, we have to much data)

  do ..setValue(key1,value1)
  do ..setValue(key2,value2)
  // etc.

then, at some point you will reach the and of the available RAM (incl. swap/paging space.  Usually swap/paging space is much less then the space for the real data).

thirdly, if you meant variable number of indexes (in sense of variable number of parameters) then I can just refine Robert's solution to

ClassMethod setValue(params...) As %Status
{
   set base=$name(%session.Data)
   for i=1:1:params-1 { set base=$name(@base@(params(i)))
   set @base=params(params)
   quit 1
}

In case, you have both, variable number of indices and too much data then you could use a mix of the above with data placed in a temp file.

Somewhere, at the program start, let you point %sessionData to a temp file

   set %sessionData=$nam(^||SessionTemp)

and then consider this in the setValue method

ClassMethod setValue(params...) As %Status
{
   set bas=%sessionData
   ...
}

Of course, in your application, you have to change only those %session.Data(...) to  @%sessionData@(...)  which uses the "variable-big-data" part of %session.Data(). All other (the standard ones) stay unchanged.

0
Dmitry Maslennikov  Nov 9, 2020 to Julius Kavay

For sure, you have good points, but some points just out of scope at all. Yes, it's limited anyway.

My main point is to not have a limited number of parameters like below

ClassMethod setValue(key1, key2, key3, key4, value) As %Status

And I was just curious if the community knows how to deal with MultiDimensional property, in such a case.

0
Julius Kavay  Nov 9, 2020 to Dmitry Maslennikov

Sorry, I don't quite get you.

One used to say, if I don't understand something, then this something is either too complicated or very simple. So where belongs your case?

0
Dmitry Maslennikov  Nov 9, 2020 to Julius Kavay

Sorry, it's just for discussion, to see how people would do some simple task.

0
Eduard Lebedyuk · Nov 9, 2020

I'd mimic %DispatchSetMultidimProperty signature. Shame local cannot be casted into a multi-argument call. Wrap in $g if values can be skipped.

/// do ##class().Test()
ClassMethod Test()
{
    kill ^data
    do ..setValue("val", "key1")
    do ..setValue("val", "key1", "key2", "key3", "key4")
    zw ^data
}

ClassMethod setValue(val, args...)
{
    if args=1 {
        set ^data(args(1)) = val
    } elseif args=2 {
        set ^data(args(1), args(2)) = val
    } elseif args=3 {
        set ^data(args(1), args(2), args(3)) = val
    } elseif args=4 {
        set ^data(args(1), args(2), args(3), args(4)) = val
    }
}
0
Vitaliy Serdtsev · Nov 9, 2020

Another option just for the fun:

<FONT COLOR="#000080">Include </FONT><FONT COLOR="#ff0000">%SYS</FONT><FONT COLOR="#000000">.</FONT><FONT COLOR="#ff0000">PTools</FONT><FONT COLOR="#000000">.</FONT><FONT COLOR="#ff0000">Stats

</FONT><FONT COLOR="#000080">Class dc.test </FONT><FONT COLOR="#000000">[ </FONT><FONT COLOR="#000080">Abstract </FONT><FONT COLOR="#000000">] {

</FONT><FONT COLOR="#000080">ClassMethod </FONT><FONT COLOR="#000000">setValue(</FONT><FONT COLOR="#ff00ff">args</FONT><FONT COLOR="#000000">...) </FONT><FONT COLOR="#000080">As %Status </FONT><FONT COLOR="#000000">{   </FONT><FONT COLOR="#0000ff">quit</FONT><FONT COLOR="#000000">:</FONT><FONT COLOR="#ff00ff">args</FONT><FONT COLOR="#000000"><2 </FONT><FONT COLOR="#0000ff">$$$ERROR</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#0000ff">$$$DataMissing</FONT><FONT COLOR="#000000">)

  </FONT><FONT COLOR="#0000ff">$$$convertArrayToList</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#ff00ff">args</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#800000">list</FONT><FONT COLOR="#000000">)   </FONT><FONT COLOR="#0000ff">quit</FONT><FONT COLOR="#000000">:</FONT><FONT COLOR="#0000ff">$listlength</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#800000">list</FONT><FONT COLOR="#000000">)'=</FONT><FONT COLOR="#ff00ff">args </FONT><FONT COLOR="#0000ff">$$$ERROR</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#0000ff">$$$RequiredArgumentMissing</FONT><FONT COLOR="#000000">)      </FONT><FONT COLOR="#0000ff">set $list</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#800000">list</FONT><FONT COLOR="#000000">,,)=</FONT><FONT COLOR="#008000">""</FONT><FONT COLOR="#000000">,          </FONT><FONT COLOR="#800000">var</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#000080">##class</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#008080">%Utility</FONT><FONT COLOR="#000000">).</FONT><FONT COLOR="#0000ff">FormatString</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#800000">list</FONT><FONT COLOR="#000000">),          </FONT><FONT COLOR="#0000ff">$extract</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#800000">var</FONT><FONT COLOR="#000000">,1,3)=</FONT><FONT COLOR="#0000ff">$name</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#800000">%sessionData</FONT><FONT COLOR="#000000">), </FONT><FONT COLOR="#008000">##; or $name(%session.Data)          </FONT><FONT COLOR="#000000">@</FONT><FONT COLOR="#800000">var</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#ff00ff">args</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#ff00ff">args</FONT><FONT COLOR="#000000">)   </FONT><FONT COLOR="#0000ff">quit $$$OK </FONT><FONT COLOR="#000000">}

</FONT><FONT COLOR="#000080">/// do ##class(dc.test).Test() ClassMethod </FONT><FONT COLOR="#000000">Test() {   </FONT><FONT COLOR="#0000ff">new </FONT><FONT COLOR="#800000">%sessionData

  </FONT><FONT COLOR="#0000ff">try</FONT><FONT COLOR="#800080">{

    </FONT><FONT COLOR="#0000ff">do $system</FONT><FONT COLOR="#008080">.OBJ</FONT><FONT COLOR="#000000">.</FONT><FONT COLOR="#0000ff">DisplayError</FONT><FONT COLOR="#000000">(..</FONT><FONT COLOR="#0000ff">setValue</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#008000">"key1"</FONT><FONT COLOR="#000000">, </FONT><FONT COLOR="#008000">"val1"</FONT><FONT COLOR="#000000">)),           </FONT><FONT COLOR="#0000ff">$system</FONT><FONT COLOR="#008080">.OBJ</FONT><FONT COLOR="#000000">.</FONT><FONT COLOR="#0000ff">DisplayError</FONT><FONT COLOR="#000000">(..</FONT><FONT COLOR="#0000ff">setValue</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#008000">"key1"</FONT><FONT COLOR="#000000">, </FONT><FONT COLOR="#008000">"key2"</FONT><FONT COLOR="#000000">, </FONT><FONT COLOR="#008000">"key3"</FONT><FONT COLOR="#000000">, </FONT><FONT COLOR="#008000">"key4"</FONT><FONT COLOR="#000000">, </FONT><FONT COLOR="#008000">"val2"</FONT><FONT COLOR="#000000">)),           </FONT><FONT COLOR="#0000ff">$system</FONT><FONT COLOR="#008080">.OBJ</FONT><FONT COLOR="#000000">.</FONT><FONT COLOR="#0000ff">DisplayError</FONT><FONT COLOR="#000000">(..</FONT><FONT COLOR="#0000ff">setValue</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#008000">"key1"</FONT><FONT COLOR="#000000">, </FONT><FONT COLOR="#008000">"key2"</FONT><FONT COLOR="#000000">, , </FONT><FONT COLOR="#008000">"key4"</FONT><FONT COLOR="#000000">, </FONT><FONT COLOR="#008000">"val3"</FONT><FONT COLOR="#000000">)),           </FONT><FONT COLOR="#0000ff">$system</FONT><FONT COLOR="#008080">.OBJ</FONT><FONT COLOR="#000000">.</FONT><FONT COLOR="#0000ff">DisplayError</FONT><FONT COLOR="#000000">(..</FONT><FONT COLOR="#0000ff">setValue</FONT><FONT COLOR="#000000">())          </FONT><FONT COLOR="#0000ff">write </FONT><FONT COLOR="#000000">!     </FONT><FONT COLOR="#0000ff">zwrite </FONT><FONT COLOR="#800000">%sessionData   </FONT><FONT COLOR="#800080">}   </FONT><FONT COLOR="#0000ff">catch</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#800000">ex</FONT><FONT COLOR="#000000">)</FONT><FONT COLOR="#800080">{     </FONT><FONT COLOR="#0000ff">write </FONT><FONT COLOR="#800000">ex</FONT><FONT COLOR="#000000">.</FONT><FONT COLOR="#0000ff">DisplayString</FONT><FONT COLOR="#000000">(),!   </FONT><FONT COLOR="#800080">} </FONT><FONT COLOR="#000000">}

}</FONT>

0