Intersystems cache: <Framestack> and <Command> error in Classes : How to solve AND avoid?

1.2k views Asked by At

I have a single class in Intersystems Cache that

  1. writes records on the globals based on the user calling it
  2. Iterates on the globals and places results on a string
  3. Writes the said result to a notepad file via FILE

However, a part of the code always returns <FRAMESTACK> error.

A search in their documents reveal :
The routine has too many nested calls to Do, For, Xecute, New, or user-written functions.

If you are wondering why I use a single class, which violates SOLID, it is because when I try calling other methods via ##class() in a method I am met with the error <COMMAND>. Hence I took the code inside the methods that I need and mixed them in a single method.

Is there a way to call a class METHOD inside a CLASS properly?

About the FrameStack error, Exactly how many is too many? how do I avoid this?

EDIT : code as requested

ClassMethod GetRRCDelToNP(DateFrom As %String, TimeFrom As %String, DateTo As %String, TimeTo As %String, Startparam As %String, Type As %String, Operator As %String, User As %String) As %String [ SqlProc ]
          {
            k ^IDXCMAWEB("ROADRECEIVAL",User)
            S RRCTR=0
            n conwt
            Q:$G(DateFrom)="" "E:Please enter date time entry."
            Q:$G(TimeFrom)="" "E:Please enter date time entry."
            Q:$G(DateTo)="" "E:Please enter date time entry."
            Q:$G(TimeTo)="" "E:Please enter date entry."
            Q:$G(Type)="" "E:Please enter type entry."
            Q:$G(Operator)="" "E:Please enter operator entry." 
            Q:$G(User)="" "E:Cannot process query. I dont know who you are."
            s (I,J,K,CN,CN1)=""
            s I=$ZDH(DateFrom,9)
            s J=$ZTH(TimeFrom) 
            s TDT3=$ZDH(DateTo,9)
            s TTM3=$ZTH(TimeTo)
            Q:(TDT3<I) "E:Date time to cannot be greater than date time from."
            Q:(TDT3=I)&(TTM3<J) "E:Date time to cannot be greater than date time from."
            s MTY=$s(Type="optall":"",Type="optrec":"R",Type="optdel":"D")
            s OPR=$s(Operator="A":"",Operator="a":"",1:Operator)
            i OPR'="" 
S 
OPR=$tr(OPR,"abcdefghijklmnopqrstuvwxyz,","ABCDEFGHIJKLMNOPQRSTUVWXYZ|")_"|"

s %id=User
i K="" S CN=""

loopi2 ;loopi
 if J="" s I=$O(^IDXLGE(I)) Q:(I="")!(+I>TDT3) 

loopj2 ;loopj
 if K="" s J=$O(^IDXLGE(I,J)) g loopi2:J="" 
if (I'="")&((I=TDT3)&(J>TTM3)) s J="",K="",CN="" g loopi2

loopk2   ;loopk
 if CN="" S K=$O(^IDXLGE(I,J,K)) g loopj2:K=""
 if "RD"'[K g loopk2
 I $G(MTY)'="",MTY'[K g loopk2
 if (I="")!(+I>TDT3) quit ;$G(I)_"/"_$G(J)_"/"_$G(K)_"/"_"0"_"/"_$G(^WK($J))
loopcn2 ;loopcn
 S CN=$O(^IDXLGE(I,J,K,CN)) g loopk2:CN=""
 S D=$G(^IDXLGE(I,J,K,CN))
 S HIS=$P(D,"|"),MOV=$P(D,"|",2),GEN=$P(D,"|",3)
 g loopcn2:HIS=""!(MOV="")!(GEN="")
 S N=$G(^CNREC(CN,HIS,"MOVE",MOV))
 S NB=$G(^CNREC(CN,HIS,"MOVEB",MOV))
 I $P(N,"|",3)="CANCL" g loopcn2
 S Z=$G(^CNREC(CN,HIS,"GEN",GEN))
 I $P($G(^CNREC(CN,HIS,"GENB",GEN)),"|",3)["CSW" g loopcn2
 g loopcn2:$P(Z,"|",9)=""
 I OPR'="",OPR'[($P(Z,"|",9)_"|") g loopcn2
 I "56"[$E($P(Z,"|",2)) g loopcn2

 S Q=$P(Z,"|"),VSC=$P(Z,"|",3)
 s VOY=$P(Z,"|",4)
 I $L($$^CMAUTH(%id,CN,VSC,VOY,$P(Z,"|",9))) s Error="" g loopcn2
 S YEAR=""
 I VSC'="" D
  .S VCN=$P($G(^CDTAB("SEQN",VSC,VOY)),"|")
  .g loopcn2:VCN=""
  .S VN1=$G(^CDTAB("VOY",VSC,VCN,"1"))
  .S VN2=$G(^CDTAB("VOY",VSC,VCN,"2"))
  .S V=$S(Q="E":$P(VN1,"|"),Q="I":$P(VN1,"|",2),1:"UNK")
  .S YEAR=$p($zd($P($P(^CDTAB("VOY",VSC,VCN,1),"|",5),",",1)),"/",3) 
  .S R=$P(VN2,"|",9)
  E  S (VSC,V,R)="" 
  g loopcn2:$E(R,1,3)="ATI"!($E(R,1,3)="BOC")
  S DATE=$zd(I,9)
  S ARR=$G(DATE)_" "_$zt(J,4)
  S Q=$S(Q="E":"Export",Q="I":"Import",Q="S":"Recirculation",1:"Unknown")
  S M=$P(Z,"|",17)
  s conwt=$p(Z,"|",18)
  i conwt'="" s conwt=conwt_" Tons"
  s othersealno=$P(Z,"|",15)
  s bookingseal=$P(Z,"|",5)
  s seal=$P(Z,"|",16)
  s plate=$P(N,"|",11)
  s trucker=""
  i plate'="" D
  .S truckercode=$P($G(^CDTAB("PLATE",plate)),"|",1)
  .i truckercode'="" S 
 trucker=$TR($P($G(^CDTAB("CART",truckercode)),"|",1),"/","")
 S shipper=""
 I YEAR'="" D 
 .S ivn=$G(^IXVH("R",YEAR,R))
 .I ivn="" S ivn=$G(^IXVH("R",YEAR-1,R))
 .I ivn'="" D
 ..S BLN=$O(^IXIFM(ivn,CN,""))
 ..I BLN'="" S shipper=$TR($P(^BSIFM(ivn,BLN),"|",3),"/","")
 s dmg=$P(NB,"|",3)
 S CN1=CN1+1
 S M=$S(M="F":"Full Container Load",M="L":"Less Container Load",M="E":"Empty",M="T":"Transhipment",1:"unknown")
 S K1=CN_"|"_$E($P(N,"|",22),2)_"|"_Q_"|"_M_"|"_$P(Z,"|",2)
 S K1=K1_"|"_$P(Z,"|",10)_"|"_$P(Z,"|",9)_"|"_VSC_"|"_V_"|"_R_"|"_ARR
 S K1=K1_"|"_conwt_"|"_$P(Z,"|",2)_"|"_HIS_"|"_GEN_"|"_CN1_"|"_othersealno_"|"_bookingseal_"|"_dmg_"|"_seal_"|"_plate_"|"_trucker_"|"_shipper
 i $P(K1,"|",2)'="" s $P(K1,"|",2)=$s($P(K1,"|",2)="R":"Received",$P(K1,"|",2)="D":"Delivered",1:$P(K1,"|",2))
 S sz=$P(K1,"|",5)
 i sz'="" s sz=$e(sz,1,1)
 s $P(K1,"|",5)=$s(sz="0":"20'",sz="2":"20'",sz="4":"40'",sz="9":"45'",sz="L":"45'",sz="1":"10'")
 i $P(K1,"|",6)'="" s $P(K1,"|",6)=$p(^CDTAB("COMM",$P(K1,"|",6)),"|")
 i $P(K1,"|",7)'="" s $P(K1,"|",7)=$tr($p(^CDTAB("OPER",$P(K1,"|",7)),"|"),"/","")
 i $P(K1,"|",8)'="" s $P(K1,"|",8)=$tr($p(^CDTAB("VESS",$P(K1,"|",8)),"|"),"/","") 

 S ^IDXCMAWEB("ROADRECEIVAL",User,RRCTR)=K1
 S RRCTR=RRCTR+1 ;now holds the total number of GLOBALS
 s recctr=CN1
 set getrows=""

 s NewI=I
 g loopcn2 ;THIS POINT WORKS AND CREATES THE GLOBALS




;####201694:2017-05-18 = GET THE DATA FROM THE GLOBALS JUST MADE ABOVE WITH THE loopcn2
 S totrec=""
 S totrec=RRCTR-1 ;-1 so that the loop clearly shows all records

 ;totrec will now contain the total number of records. iterate on totrec
 S ctr=0 ;will contain the current record count
 S rsult="" ;will contain the total string result, to be written on the notepad



Do
{   
 S data=""
 I $D(^IDXCMAWEB("ROADRECEIVAL",User,ctr)) D
 .S data=$G(^IDXCMAWEB("ROADRECEIVAL",User,ctr))
 E  D
 .S data=""

 S rsult=rsult_"|"_ctr_$P(data,"|",1) ;modify further. this will be the returned string

 S ctr=ctr+1
} WHILE ctr<=totrec
;Q rsult ;return the results...  

;now, we write the results in a notepad file. 
;writes the text file. OLD: S FILE="\\SOMELOC\PubShare\theFileToJSON.TXT" 
S FILE="\\SOMELOC\PubShare\theFileToJSON.TXT" 
O FILE:"WNS" U FILE
S WriteToFile=rsult 
W rsult ;...we actually write the file?
 C FILE

Q FILE  ;display the file?

}

Here, after the part where the globals are made, I iterated on the total record count RRCTR to get a part of the said globals into a single string.

The Globals are being made succesfully, however no file is created. why is this? when run, it says <COMMAND> as the error

3

There are 3 answers

6
SSH On BEST ANSWER

<FRAMESTACK> usually occurs when you are calling your code recursively. This is not a good programming practice especially if you are hitting stack overflow errors, you can configure a bigger stack but I would recommend do try and rewrite your code not to use recursion.

Looks like your <COMMAND> error happened because you mix "curly brackets" in your do..while loop at the end with "do with a dot" syntax. This is not supported, rewrite that part of your code to use curly brackets everywhere:

Do
{   
 S data=""
 I $D(^IDXCMAWEB("ROADRECEIVAL",User,ctr)) {
    S data=$G(^IDXCMAWEB("ROADRECEIVAL",User,ctr))
 } else {
    S data=""
 }

 S rsult=rsult_"|"_ctr_$P(data,"|",1) ;modify further. this will be the returned string

 S ctr=ctr+1
} WHILE ctr<=totrec
0
Paul On

Try calling the class with "do ##class(class).method" instead of "Write ##class(class).method)" Also that's not really Cache code, its Mumps code and (IMHO) old legacy badly written. Personally you should re-write it (or pay a consultant to)

0
FLipxcode On

I agree with Paul. Using the Go command 'g' to iterate, instead of, for example, the 'argumentless For' is extremely poor programming practice. The entire thing needs to be re-written without any Go ("g") commands.