Sometimes, like now, it's a good idea to give a variable an initial value...
set %out="", key="" for {...
- Log in to post comments
Sometimes, like now, it's a good idea to give a variable an initial value...
set %out="", key="" for {...
One more comment, I'm not sure about the "quit" command after the closing curly brace, I think you don't need it (because it's outside of the FOR loop, hence it will stop the flow of your application)!
I would say, a little bit to much "set" command.
Instead of: Set tQStr = $$$ArrayToString(pQArray,tQStr,"##")
try this one: $$$ArrayToString(pQArray,tQStr,"##")
Your version gives something like: Set tQStr = set %out="" for { ...
as you see, %out isn't a command (and set would be undefined, but that isn't the problem)
By the way, the second line of your macro should be:
set key=$order(%array(key)) quit:key="" ##continue
else you have the perfect endless loop
Why do you need an AI for those questions?
4) and 5) I'm pretty sure, both questions were already answered by the creators of MUMPS back in the 60es, without AI
ClassMethod MAX(a,b,c,d)
{
quit $$max($$max(a,b),$$max(c,d))
max(x,y) quit $s(x>y:x,1:y)
}
/// Compare alphanumeric data
/// OUT: a<b --> -1
/// a=b --> 0
/// a>b --> 1
ClassMethod AlphaCompare(a,b)
{
quit $s(a=b:0, a]b:1, 1:-1)
}
6) CPU for this process - What do you mean by that?
a) on a multicore CPU, you ask for the core number for your process?
If yes, I think, you won't get that number, because
usually, a process runs on the same core, the emphasis is on "usually" but the OS may shift a process, according to load, to another core.
If you could have a code like:
set currentCore=$$GetTheCurrentCore($j)
write "Current core: ",currentCore,!
in the next point of time that information could be wrong
b) do $system.CPU.Dump()
gives you an info about the CPU, your proces runs on
c) write ##class(%SYS.ProcessQuery).GetCPUTime()
gives you two CPU-times, system- and user-time in milliseconds
Tipp #10 gives us plenty of opportunity for discussions like
a) may that %DynArray have an embedded %DynArrays [1, 2, ["a", "b"], 4, 5]
b) may an element contain a comma [1, 2, "a,b", 4]
etc.
instead of the original solution: Set str = $TRANSLATE(jsonArray.%ToJSON(), "[]")
I would use a more accurate way : set str = $e(jsonArray.%ToJSON(),2,*-1)That's neither a trick nor a feature but an intended behavoir (for what feels like 100 years).
Each unique index over one or more table columns can be used to open that object just by using the column(s) from that index.
class DC.Example2 Extends %Persistent {
Property Column1 As %String;
Property Column2 As %String;
Property Column3 As %String;
Property Column4 As %String;
Index one On Column1 [Unique];
Index two On (Column2,Column3) [Unique];
}
set obj=##class(DC.Example2).oneOpen(colValue1) // default lock, or
set obj=##class(DC.Example2).oneOpen(colValue1,0) // without lock
if (obj) { write obj.%Id() } else { write "Record does not exist or the index one is corrupted" }
set obj=##class(DC.Example2).twoOpen(colValue2,colValue3) // default lock, or
set obj=##class(DC.Example2).twoOpen(colValue2,colValue3,0) // without lock
if (obj) { write obj.%Id() } else { write "Record does not exist or the index two is corrupted" } Some time ago I noticed (rather by chance) the presence of some other (new) types, but I did not look more closely into the what and why of those codes - I'm just happay with the "old ones", that I use as menitioned above.
Thank you for the explanation.
I know that the $lb() representation of a null string is $c(2,1) on all instances (8-bit or Unicode), but passing the argument $c(2,2) to $list() is still correctly interpreted (respectively extracted) as a null string by the function.
set result = $c(3,4,125,2,2,5,1,97,98,99) // return value from a C-program
set mylist = $lb(125,"","abc")
zwrite result --> result=$lb(125,"","abc") // correct
write $listsame(result,mylist) --> 0 // because the type bytes are differentbut after executing the following
if $list(result,2) = $list(mylist,2) { write "YES" } else { write "NO" }
if $list(result,2) = "" { write "YES" } else { write "NO" }you will see two YESes which proofs my answer from 18. Apr.
Just two comments:
"Observations: ... payload grows only when required" is correct but a more correct explanation would be "the whole list structure is created with a minimum memory usage in mind".
The above note (minimum storage size) leads to special cases:
1) an integer 0 is stored in two bytes only
02 04 (length, type) and not
03 04 00 (length, type, data) which is also accepted(*)
The same goes for nullstring (which is obvious)
02 01 (length, type and, of course, no data), ASCII nullstring
02 02 (length, type) a "Unicode" nullstring,
2) If only the length component is present and equals 1,
then this indicates a NULL element (i.e. a missing element):
set x=$lb(85,,,0,"","abc")
zzdump x --> 03 04 55 01 01 02 04 02 01 05 01 61 62 63
which breaks down into
03 04 55 $li(x,1) = 85
01 $li(x,2) = <NULL VALUE>
01 $li(x,3) = <NULL VALUE>
02 04 $li(x,4) = 0
02 01 $li(x,5) = "" / nullstring
05 01 61 62 63 $li(x,6) = "abc"
(*) I use this side effect (list use minimal bytes for integers) and ASCII strings are accepted even if their type is unicode) in some of my CallOuts to return results (as an IRIS-List) without explicitly converting C's two byte string into one byte ASCII where it aplies and I return integer values either as four or eith bytes even if the value would fit in two, three or five bytes.
For example, the ReadColumn() method of the excel library class could return something like
set colData = %exl.ReadColumn(3)
zzdump colData
08 02 61 00 62 00 63 00 06 04 55 00 00 00 (ASCII "as" Unicode, 1 byte integer in 4 bytes)
zwrite colData
colData=$lb("abc",85)
Thank you guys at ISC for this wise implementation!
In the history of mankind there were three great inventions
- to light a fire
- the wheel
- and of course, the ^globals
There is nothing more to say.
The problem is NOT the QUIT in an IF statement, the problem is, using a QUIT WITH ARGUMENT in a TRY/CATCH statement.
First, there is no NaN in JSON.
set dynObj = {"val":($double("NAN"))}
write dynObj.val + 123 ---> "NAN
zwrite dynObj
dynObj={"val":($double("NAN"))} ; <DYNAMIC OBJECT>
/* Question @devcommunity manager: how to exit the "insert code block" function? */
Second, red this for more understanding
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;
}Assuming, your XML stream never has more then MAXSTRING characters AND if you can live with a "quick-and-dirty" solution then try this one
Class DC.XML.abc Extends (%RegisteredObject, %XML.Adaptor)
{
Property def As %String;
Property ghi As %String;
Property jkl As jkl;
ClassMethod Test(str)
{
if $isobject(str) { set:str.Rewind() xml=str.Read(str.Size) } else { set xml=str }
for{set i=$f(xml,"<![CDATA[",$g(i)) q:'i
set j=$f(xml,"]]>",i) zt:'j "XMLE"
set $e(xml,j-3,j-1)="", $e(xml,i-9,i-1)="", i=i-9
}
set rdr=##class(%XML.Reader).%New()
if 'rdr.OpenString(xml) write "OpenErr",! quit
do rdr.Correlate("abc","DC.XML.abc")
while rdr.Next(.abc,.st) { zzdo abc }
}
}
Class DC.XML.jkl Extends (%RegisteredObject, %XML.Adaptor)
{
Property mno As mno;
}
Class DC.XML.mno Extends (%RegisteredObject, %XML.Adaptor)
{
Property pqr As %String;
Property stu As %String;
}
And some tests...
set s1="<abc><def>010203</def><ghi>040506</ghi><jkl><mno><pqr>070809</pqr><stu>101112</stu></mno></jkl></abc>"
set s2="<abc><def>010203</def><ghi>040506</ghi><jkl><![CDATA[<mno><pqr>070809</pqr><stu>101112</stu></mno>]]></jkl></abc>"
do ##class(DC.XML.abc).Test(s1)
def................................: 010203
ghi................................: 040506
jkl.mno.pqr........................: 070809
jkl.mno.stu........................: 101112
do ##class(DC.XML.abc).Test(s2)
def................................: 010203
ghi................................: 040506
jkl.mno.pqr........................: 070809
jkl.mno.stu........................: 101112
Note: the above ZZDO command takes an oref as argument and prints it, you can replace it with a simple zw oref.
I have made several callouts but never a callin (with userlogin), like you trying to do.
You wrote, you have several instances (Cache and IRIS) installed, presumably on the same hardware respective OS. Take a look in one of your Cache installation: <InstallDirectory>\dev\Cache\callin\
There are three files worth to study: sampcallin.c, sampcallint.c and shdir.c
The callin mechanism does not needs IPs and ports. To find out if anything has changed as a result of switching from Cache to IRIS, please contact WRC.
You do not need to reference 'localhost', your C++ program and IRIS are located (and running) on the same 'localhost', the source of your problem is something else
Nota Bene: I adopted Robert Cemper's suggestion ISOS, as shorthand for InterSystemsObjectScript
According to my opinion, your ISOS example (and the way, how JSON was implemented by ISC), is a mix of a little bit ISOS and a little bit JSON.
Why? Take this example:
set myObject = { "p1":"abcd", "p2":true, "p3":value, "p4":(sum+2) }
<- ObjScript -><-------------------- JSON------------------------->The example starts with an ISOS syntax and proceeds with JSON syntax.
Unfortunately, the last two properties (p3, p4) are invalid JSON properties.
So we have a perfect mixture!
Remember, ISOS does not have literal constants (like true, false and null) and JSON neither has variables (like value) nor expressions, like (sum+2).
Since the current implementation has been in use for several years, a reimplementation is (probably) impossible. With other words, the bottom line is, unwillingly, but we have to accept the status quo...
Apparently, someone at ISC got a huge discount on parentheses (the easy solution) instead of requiring that these damned parentheses only be used when the assignment is an expression (and the user-friendly version would be: only when the expression contains the [ or ] operators!).
justmy2cents
Put your variables into parentheses, i.e.
return {"value1":(val1), "value2":(val2)}Could you please run the following commands in a terminal session:
write $zv
set exl=##class(%SYS.Python).Import("openpyxl")
set wbk=exl."load_workbook"( "your path_and_filename.xlsx" )
set sht=wbk.active
set cel=sht.cell(row,col) // ROW and COL should point to a date-cell
write cel."data_type"
write cel.value.strftime("%d.%m.%Y")Please post a screenshot here, even if you get some kind of error
Excel store date values as decimal values (or better, as flotaing poin) as dddd.tttt where ddd is the number of days since a base date (usually 1899-12-30) and tttt is: numberOfSecondsSinceMidnight / 86400, hence the value, you get is an date-object, and you have to format it according to your needs
Class DC.PyExcel Extends %RegisteredObject
{
ClassMethod Test(fn = "/home/kav/test/readtest.xlsx")
{
set exl=##class(%SYS.Python).Import("openpyxl")
set wbk=exl."load_workbook"(fn)
set sht=wbk.active
for row=1,2,3 {
for col=1:1:3 {
set cel=sht.cell(row,col)
set typ=cel."data_type"
set val=cel.value
write ?col-1*15,$case(typ, "s":val, "n":$fn(val,",",2), "d":val.strftime("%a, %d.%m.%Y"), :"")
}
write !
}
}
}
I'm just curious, what do you get, if you type write $view(-1,$job) in the output window of Studio?
See my screenshot, red=my input, yellow=Studio output
More info, please. What is $stack(0,...) supposed to represent?
Your lines can be shortened to
if $system.Process.ClientExecutableName($j) = "..." { ... } else { ... }justmy2cents
Port 1972 is the default port, your actual port may be different. That's why I added a comment to the answer above. Check the parameter file of your installation:
for IRIS : see iris.cpf, section [Startup], DefaultPort=...
for Cache: see cache.cpf, section [Startup], DefaultPort=...
At least, there are four different ways to get that info
ClassMethod StudioTest()
{
write "Call from Studio1: ",..InStudio1(),!
write "Call from Studio2: ",..InStudio2(),!
}
/// Is the invocation from the Studio?
ClassMethod InStudio1()
{
for i=$st:-1:1 if $st(i,"PLACE")["%Studio.General." ret 1
ret 0
}
/// Is there a connection to Superserver?
ClassMethod InStudio2()
{
set port=1972 // see iris.cpf, section [Startup], DefaultPort=...
quit $p($v(-1,$j),"^",3)[("|TCP|"_port_"|")
}
Compiling routine DC.Util.1
Compilation finished successfully in 0.024s.
do ##class(DC.Util).StudioTest()
Call from Studio1: 1
Call from Studio2: 1
ICINDY:USER>; from PuTTY -------------------
ICINDY:USER>do ##class(DC.Util).StudioTest()
Call from Studio1: 0
Call from Studio2: 0
The other two methods are: checking for the presence of
a) a dedicated variable or
b) a dedicated object
but both require a usage of undocumented functions
I can't reproduce the problem
Well, I'm neither part of the ObjectScript nor the Objects developer team, hence I can't answer the "why" part of your question but fact is, timing mesuremenst show a significat higher speeds for the literal versions:
ClassMethod DynObject()
{
while $zh#1 {} set t1=$zh for i=1:1:1E6 { if ##class(%DynamicArray).%New() } set t1=$zh-t1
while $zh#1 {} set t2=$zh for i=1:1:1E6 { if ##class(%DynamicObject).%New() } set t2=$zh-t2
while $zh#1 {} set t3=$zh for i=1:1:1E6 { if [] } set t3=$zh-t3
while $zh#1 {} set t4=$zh for i=1:1:1E6 { if {} } set t4=$zh-t4
write "Times for : Class Literal Diff",!
write "DynArray :", $j(t1,9,3), $j(t3,9,3), $j(t1/t3-1*100,9,2),"%",!
write "DynObject :", $j(t2,9,3), $j(t4,9,3), $j(t2/t4-1*100,9,2),"%",!
}
The output will depend on
- IRIS/Cache version in use and
- on the underlying hardware
My values are
USER>d ##class(DC.Times).DynObject()
Times for : Class Literal Diff
DynArray : 0.665 0.401 65.90%
DynObject : 0.649 0.401 61.87%
Maybe someone else or the WRC has an explanation...