Julius Kavay · Oct 2, 2020 go to post

The above should work, so the question is, what is the content of pData. Do you can share a sample with us?

Also, you can write the above somewhat shorter too and you can access all the properties either via propertyname or via the %Get() method.

I assume, you have a string like this:

set pData="{""Name"":""Joe"", ""Age"":50}"

the you can do this

set object={}.%FromJSON(pData)
write object.Name // Joe
write object.%Get("Name") // Joe
write pData // {"Name":"Joe", "Age":50}
Julius Kavay · Sep 27, 2020 go to post

Now we have the year 2020 (but I will discard this year from my life because of Covid-19) but our loved COS wasn't in this year nor in  the very past years invented.

COS (better, the predecessor, M ) has more then 50 years under his belt, it was created in the late sixties - in a time, where RAM was rare, expensive and therefore it was measured in units of kilobyte!

If I recall correctly, at end of the seventies, we had some customers on a PDP-11/34 with less then 64KB of memory, one or two 2kb partitions and some "big" partitions with 4KB or 6KB, the rest was for disk buffers (512 byte each) and DEC's V4b (which acted as OS, database and language interpreter).

Hence the ability of COS for excessive abbreviations and if you get an old routine, written by an old school programmer (like me) then you will see there (mostly) abbreviated commands,  postconditions and (local-/globalvariable, label and routine) names, consisting just a few letters (one to three, maybe four).

Unfortunately, this (abbreviated commands, short names) happens to me in this days too - you know, old habits never die.

There is a wonderful (and at the same time a horrific) example of such a routine: one letter names, everything abbreviated:
https://stackoverflow.com/questions/4151554/need-mumps-sample-code/4430…

clock ;; a digital clock from
;; https://stackoverflow.com/questions/4151554/need-mumps-sample-code/4430996
;;
Q N R,Q,C,D,E,W,B,G,H,S,T,U,V,F,L,P,N,J,A S N=$G(N),Q='N,F=Q+Q,P=F+F,W=$L($T(Q))
 S W=$E(W,Q),S='N_+N,W=W-F*S,L=$G(L),R=$C(Q_F_P),R(F)=$C(F+Q_F),R(P)=$C(W-F) W #
 S T=$E($T(Q+F),F,W\S)_$C(W+S+F) X T S B=$P(T,$C(P_P),F),C=B\(W*W),D=B-(C*W*W)\W
 F G=S-Q:F:S+F+Q S E=B-(C*W*W+(D*W)),H=$E($T(Q),G),@H=$S(@H<S:'Q,Q:N)_@H,T=C_D_E
 F A=Q:Q:W\S S J=$E(T,A),C(F)=$S(J>(F+Q)&(J<(S-F)):Q,Q:+N),C(P)=$S(J#F:Q,Q:+N) D
 .S C(Q)=$S(J<(S-F):+N,Q:Q),C(F+Q)=$S(J>Q&(J<(S-F))&(J'=(P+'L))&(J'=(P)):Q,Q:+N)
 .S H('L)=L F  S H(N?.E)=$O(C(H('$G(N)))) Q:H('+L)=L  S F(A,H('L))=C(H(W[(W\S)))
 F U=Q:Q:P W !,R F V=Q:Q:P+F W $S(F(V,U):'Q,Q:$C(P_(W\S))) W:'(V#F) $C('N_F_F+F)
 W !!,R(F)_C_R(P)_D_R(P)_E_R(F) X $RE($E($T(Q),Q+F,P+Q))_R(P)_'N W # G:N=L Q+F Q

It's not only tricky to read but has an attractive form too

Julius Kavay · Sep 13, 2020 go to post

For such cases use the macro: #def1arg

See this example:

Test ;my Macro test
#def1arg ADD(%a) $$add(%a)
 write $$$ADD(1),!
 write $$$ADD(1,2),!
 write $$$ADD(1,2,3),!
 write $$$ADD(1,2,3,4),!
 quit

add(a,b=0,c=0,d=0) { quit a+b+c+d }
do ^Test

gives you the output

1

3

6

10
Julius Kavay · Aug 31, 2020 go to post

First, I think, you should check the above method...
You use the date variable two times

set date = $piece(...)
return date_" "...


I'm pretty shure, if the time in Vienna (Europe) is 00:30:00 then the coresponding UTC time is 23:30:00 previous day (standard time). But you never change the date variable!
As a timestamp:
2020-08-31T00:30:00+01:00 (Vienna, 31. August)
2020-08-30Z23:30:00 (UTC,  30.August)

Second (but this is just my very privete view), checking time(stamp) format should be done BEFORE calling the ConvertW3CToTimestampUTC() method and not in the method itself.

The holy trinity of programming is:
1) accept data (data input)
2) check the data
3) if the data is OK use it, else back to input (or return an error)

If you accpet data without checking, it means, every time, you intend to use those data, you have to check them again and again (as above), wich is not very efficient.

Julius Kavay · Aug 27, 2020 go to post

All ISC products (Ensemble, Cache, IRIS...) have an callin and callout interface via dll/so.  As a starting point, read this

https://docs.intersystems.com/healthconnectlatest/csp/docbook/DocBook.U…

and this

https://cedocs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?…

You will also need some experience in C/C++ or Delphi or in other language, where you can compile *.dll (Win) or *.so (Linux) files.

See the functions $zf(-3), $zf(-4), $zf(-5) and $zf(-6)

Julius Kavay · Aug 25, 2020 go to post

Create a FindLab() method in your ListLabCenter class, something like:

Method FindLab(start = 0, LabId = "", Center = "", Code = "")

{    set nc1=LabId="", nc2=Center="", nc3=Code=""

     for i=start+1:1:..Labs.Count() {

         set tmp=..Labs.GetAt(i)

         if tmp.LabId=LabId!nc1, tmp.Center=Center!nc2, tmp.Code=Code!nc3 return i

}

   quit 0

}

Then use it as follows:

write obj.FindLab(0,"A08829848","A088298480003","") to find a specific Lab

or 

set  center=0
for  { set center = obj.FindLab(center,,"A088298480003")
       quit:'center
       /* do something with center *./
}

to find all LabCenter objects where Center = "A088298480003"

Julius Kavay · Aug 24, 2020 go to post

ISO 8601 time format is either yyyy-mm-ddZhh:mm:ss (UTC time) or yyyy-mm-ddThh:mm:ss+TZ (local time)
where TZ is the time zone.

If both times are UTC time, then just compare.
If the times are local times and both times are in the same TZ then just compare
in elsecase either convert both times to UTC or one of the times to the TZ of the another time.
Then just compare.

The compare function is just a $select(), nothing more:

t1, t2 are the times, then

if $select(t1]t2:"t1 later", t1=t2:"equal", 1:"t1 is earlier")

or more general:

set result=$select(t1]t2:1, t1=t2:0, 1:-1)
if result>0 write "t1 is later then t2"
if result>=0 write "t1 is later or equal to t2"
...
Julius Kavay · Aug 20, 2020 go to post

If the class is in use (i.e. instantiated) then it will use the "old version".
So you have to take whatever  step(s) needed (stop production, stop Cache/IRIS) to unload the old version.

Julius Kavay · Aug 4, 2020 go to post

After more than 42 years of M-programming and in total of 48 years of programming experience I would say, if you need a class with about 1000 or more properties than something is wrong with your (database) design. There is nothing more to say. Period.

Julius Kavay · Jul 29, 2020 go to post

I assume,  your JSON is generated by converting a dynamic object to string, i.e.: 

do obj.%ToJSON()

In elsecase, it's created manually an there you could put as many quotes as you like around the numbers.

For the first case, just make a function which converts the numbers into string, see below:

test ;test for stringify
   set a={},a.Name="John",a.Age=47,a.xx="ab:1234",a.City="Boston",a.Year=2020
   set a."Arr"=[11,22,"aa","bb"]
   set a."Obj"={"aa":"bb"}

   write a.%ToJSON(),!
   write $$stringify(a).%ToJSON(),!
   quit

stringify(x)
{
   set y=x.%GetIterator()
   while y.%GetNext(.i,.v) {
     set t=x.%GetTypeOf(i)
     if t="number" { d x.%Set(i,v,"string") } elseif t="array"!(t="object") { do stringify(v) }
   }
   quit x
}

The output  is then:

do ^test
{"Name":"John","Age":47,"xx":"ab:1234","City":"Boston","Year":2020,"Arr":[11,22,"aa","bb"],"Obj":{"aa":"bb"}}
{"Name":"John","Age":"47","xx":"ab:1234","City":"Boston","Year":"2020","Arr":["11","22","aa","bb"],"Obj":{"aa":"bb"}}
Julius Kavay · Jul 15, 2020 go to post

Did you read the documentation?

TO_DATE(datestring [,format])

Your datestring is 5/8/2020 but your format is 'YYYY-MM-DD' which does not match '5/8/2020'!!

Julius Kavay · Jul 15, 2020 go to post

Maybe you want to use TO_DATE(...)  but if you want to use TO_CHAR() then you have to supply a correct argument, which is in this case a $HOROLOG value

SELECT TO_CHAR(0,'mm/dd/yyyy') ---01/12/1840

SELECT TO_CHAR(65575,'mm/dd/yyyy') ---15/07/2020

TO_CHAR(): A string function that converts a date, timestamp, or number to a formatted character string.

TO_DATE(): A date function that converts a formatted string to a date.

Julius Kavay · Jul 6, 2020 go to post

As always, it depends on ...
In this case on the definition of the date column.

a) if the date column is defined as %Date (i.e.: Property DateOfBirth As %Date) then the STORED value is just a number like 65567, because dates are stored in $Horolog format). 

b) if the date column is defined (for whatever reason) as %String (i.e.: Property DateOfBirth As %String) then the stored value is (as the type says) a string, and you can use the pattern operator to check the format.So the first question is, how is your date column defined?

Julius Kavay · Jul 5, 2020 go to post

You are a lucky man, you own a 300bd device!
I have one, but it's a newer type with 2400bd BUT with a fallback mode for 300bd too (if I recall it right).

Julius Kavay · Jul 5, 2020 go to post

This should be something like:

do httpRequest.EntityBody.Clear()

do httpRequest.EntityBody.Write("Your Data")

set status=do httpRequest.Post(...)
Julius Kavay · Jul 3, 2020 go to post

If I understand you correctly,  you want something like

select * from yourTablename where yourColumname %PATTERN '1.N'

i.e. where a column contains an integer greater or equal 0 (1.N means: one or more digits)

Julius Kavay · Jun 18, 2020 go to post

Thanks for the (finger board) link.

Until now, I didn't realise, that the tags are clickable. Sorry.
But in general, it's a good idea, before using an acronym, to spell it out first, to avoid misunderstandings

Julius Kavay · Jun 18, 2020 go to post

It would be very helpful to know, what CCR means.
https://acronyms.thefreedictionary.com/CCR knows  241 acronymes for CCR (not including such as Code Certification Rule, Code Certification Report, Customer Care Report and many more) .
If you filter for Science and Medicine (in the above site), you end up with 62 acronymes.

So what does your CCR mean?

Think about, not everybody works in the same field as you. Some people, like me, wrote countless applications for marketing, business management, trading, banking, scientific solutions and others, but never for healthcare.


justmy2cents

Julius Kavay · May 21, 2020 go to post

radix 10: mantisse *  10**exponent  (the  ISC  floating format)

radix 2 : mantisse * 2 ** exponent ($double/ IEEE 754 format )

Julius Kavay · May 21, 2020 go to post

The first part is easy... string, integer,... that's not the problem.

The second part, is it a date or not depends on the date format(s) you expect (or allow).

But for the first part, you can use this approach:

/// Return values
/// 0=empty, 1=string, 2=integer, 3=float/radix-10, 4=float/radix-2, 5=object
ClassMethod ValType(var) 
{
  if var="" quit 0
  if $isobject(var) quit 5
  quit $select($length(var)>254:1, 1:$translate($ascii($listbuild(var),2),1245678,1122334))
}

Of course, hardcore people would use just one line

ClassMethod ValType(var) { q $s(var="":0, $isobject(var):5, $l(var)>254:1, 1:$tr($a($lb(var),2),1245678,1122334)) }
Julius Kavay · May 21, 2020 go to post

Just to bring things in the right light

I'm a retired person but one needs some level of activity, that's the reason, why I'm here, do give answers and comments (and if the old customers need "a kind of prolonged help", I'm there too).
In early and mid seventies I programmed some so called "desktop computer", learned Cobol, IBM/360 assembler, Algol60 and Pascal as the preferred language on the university. Then, end of 1977 I met M (DEC's V4B).
Until the nineties thre were no IDEs, the first one I used was Serenji (from GeorgeJames) for MSM and Cache's Studio (with a lovely meat-chopper as the compiler icon). And there were no GitHub.
Anyway, we had great projects and great programms and fun.

The above means, I for myself do not need anything, neither Atelier nor VS-Code not even Studio but in case, I want to edit a class or routine, I prefer Studio.
During my active times, Studio was a great editor (and still it is!), sometimes I had more then one Studio open (at the same time, of course) to different Servers or different namespaces that's the reason why I requested the feature (server defined colors) some decades ago. The light red was the connection into, say a productio system, the green was into  a test namespace and blue, for example was the developmet system. A short glimpse at the display, if I saw red, my brain said, "keep fingers from keyboard", if I saw blue then my brain was ready for switch off... 

But I know several people working since decades with Studio only (and with the line editor before - I hope you know ^% and remember it?). Those people are (roughly) between 50 and 60 years old, worked (and still work) with whatever brand of M-Language (DTM, MSM, ISM, GT-M, Cache etc.) and never had contact to "modern" languages like java, C++, javascript, etc.
That's in my opinion the reason, why Atelier not so widespread as it deserved to be.

De facto, we have a two class society of M-programers

a) the young ones,
- they know everything about the current IDEs (Visual Studio, VS-Code, Eclipse, etc.
- they try to master (more or less) the M-World but
- their heart beats for languages as Java, Javascript, C++, Angular, Scala, etc.
- can't live without Git, GitHub, Bitbucket etc.
- they do not understand the essence/character of M-language (especially Cache/Iris)
- and think, MongoDB is the only NoSql-DB
- work few months (or one or two years) for a company, then change
- in the new company start over with another environment (Java, Angular, whatever)
- many are, I use to say, single-threaded: one project at time only
- etc.

b) and the old ones
- they grew up with the M-language
- they understand the power of M as a unity (language and database)
- most of them never used Git (and similar sites) for version control
- some of them never used a version control at all!
- most of them work with Windows (but this has historical reason)
- a few years before retirement there's no incentive to change to new IDEs

The real problem is not which IDE is in use, the real problem is to get people for M-programming, who then use an IDE. There are, I think, more old(er) then young M-Programer. I know for companies, they search for M-Programers but have dufficulties to find one.
That said, at the end of the day, you have to raise interesse for M-Language and M-Database. So you will need another means and not just a new IDE.
Maybe I'm wrong, but it's like comparing the M-Language and M-Database with a dinner by a start chef.
Nobody asks for the IDE they was in use, nobody asks for the pots and stoves they was in use.
After you leave the restaurant, the only thing that remains is, was the dinner good, were you satisfied.
Same goes the M-Language, does it can all things I need, will I be happy with it.
And yes, my answer is a big yes, definitive.

Julius Kavay · May 20, 2020 go to post

In my opinion the very first question is the support. a) Studio

  • it's installed (and updated) with Cache/IRIS
  • if I have a question, there is WRC b) VS-Code
  • it's not installed with Cache/IRIS
  • so I have to care about the installation
  • where to get the suitable files (and updates)
  • and I have to care about the "how to" install it
  • in a case of a problem, who am I contacting?
    1. the WRC? They will say, it's not our product
    2. the community? Are they always (24/7) there?

The current situation with VS-Code and the COS-plugin (my very private opinion) is

  1. it is assumed, that one is an experienced user of VS-Code
  2. there are no installinstuctions and user manuals

ad 1): assume, one day ISC says "VS-Code with COS plugin exists, so we can drop Studio". What should happen to all those COS-programers, how should they master VS-Code? Most of them have never ever heard about VS-Code? Keep in mind, not everybody grew up with mother's breast in one hand and an App in another !

ad 2): yes, there are some YouTube videos. On all videos I saw, VC-Code was already installed

Do not get me wrong, I'm not again VS-Code (the truth is, I would like to use it on my Linux) and I'm not for keeping Studio until eternity (because there is no Studio for Linux). But currently, Studio has some advantage (again, for me):

  • it's installed
  • I can have (and yes, I have) several connections
  • I can give each connection a different (background) color
  • I have the WRC (but I never had a Studio issue)
Julius Kavay · May 2, 2020 go to post

In case, you want some speed, use

set outArray = []

instead of 

set outArray = ##class(%DynamicArray).%New()

Your speed gain: ca. 50%

Julius Kavay · Apr 30, 2020 go to post

The %OpenId() method checks, if the object to be opened ALREADY open (in the current session/job). If it's open then it just returns with an success.  In other case, it loads it from the disk. 

If on your development system, for whatever reason,  there is an open instance  then you save 6.1 million times the "load" operation.

Julius Kavay · Apr 30, 2020 go to post

You are wondering about a SLOW production server and a FAST development machine?

I show you, how to turn your machines (production or development or both) into  a SLOW and FAST systems  by using your own measurement method.

ClassMethod Unclean()
{
   s p=##class(digi.packet).%OpenId("packet||5237")
   d ..runme4()
} 

ClassMethod Clean()
{
   d ..runme4()
}

Login to either of your systems and try the abowe methods in a terminal session. On my local system (of course, with an own persistent class)  the one method is 12 times faster then the other.

Maybe you have an "Unclean" situation on your development system...

Also, sometime it is worth to put a line like

do $system.OBJ.ShowObjects()

as a first line into the runme4() method

Julius Kavay · Apr 16, 2020 go to post

Why do you do make things such complicated?  You neither need  %ListOfDataTypes nor  %ZEN.proxyObject. If I see correctly, at the end of the query you have a characterstream, filled with JSON. Right? So just create this stream on-the-fly!

set json = ##class(%Stream.TmpCharacter).%New(), del=""

  &sql(declare ... )
  &sql(open queryONLWK01)
        
  do json.Write("[")
     for  {
        &sql(fetch queryONLWK01)
        quit:SQLCODE
        do json.Write(del_"{")
        do json.Write("""articlenumber"":" _ articlenumber _ ",") // (*)
        do json.Write("""amount"":" _ amount)
        do json.Write("}")
        set del=","
     }
     do json.WriteLine("]")

(*) if articlenumber is an alphanumeric value then you should do something like this

    do json.Write("""Aarticlenumber"":"_$$json(article)_",")

 where $$json(x) could be something like this ($zconvert() has  no JSON-mode in Cache-2013)
    

json(val) {
   for c="\","/","""",$c(8),$c(9),$c(10),$c(12),$c(13) set val=$replace(val,c,"\"_$tr(c,$c(8,9,10,12,13),"btnfr"))
   for  quit:'$locate(val,"[:cntrl:]",0,j,v)  set $e(val,j-1)="\u"_$e($zh($a(v)+65536),2,5)
   quit """"_$zcvt(val,"O","UTF8")_""""
}