BMXSQL6 ; IHS/OIT/HMW - BMX REMOTE PROCEDURE CALLS ; 7/20/2009 ;;2.1;BMX;;Jul 26, 2009 ; Line EOR+3 used a 2 argument form of $Q which is not ; in the M 95 standard. Replaced this with a call to $$LAST, ; a new Extrinsic in this routine. ; ; WRITE ;EP N BMXFN,C,BMXN,BMXGF,BMXA,BMXFLDF,N,A,IEN0,I N BMXCNT,BMXCNTB,BMXLEN,BMXLTMP,BMXNUM,BMXORD,BMXTYP N BMXCFN,BMXCFNX,F,BMXROOT,BMXCID,BMXZ ;From MAKEC N BMXREC,BMXCHAIN ;TODO: COMMENT AFTER TESTING N BMXIENS ;Set up FIELD value for GETS^DIQ call ; BMXFLD("NAME")="FILE#^FIELD#" ; Need: BMXFLDN(FieldNumber) ; and : BMXFLDO(SelectOrder) ; Get file number -- for now just use first file in array ; TODO: Set up same main file and related files here and in enumerator S C=0,BMXN="" N F S BMXGF=0 S F=0 F S F=$O(BMXF(F)) Q:F="" S BMXFN=BMXF(F) D . S C=0,BMXN=-1 F S BMXN=$O(BMXFLDO(BMXN)) Q:BMXN="" D . . Q:$P(BMXFLDO(BMXN),U)'=BMXFN . . I $P(BMXFLDO(BMXN),U,2)=".001" S BMXGF=BMXGF+1 Q . . S C=C+1 . . S $P(BMXGF(BMXFN),";",C)=$P(BMXFLDO(BMXN),U,2) . . S:'$D(BMXGF(BMXFN,"INTERNAL")) BMXGF(BMXFN,"INTERNAL")="E" . . I $P(BMXFLDO(BMXN),U,3)="I" S BMXGF(BMXFN,"INTERNAL")="IE" . . S BMXGF=BMXGF+1 . . Q . Q ; I BMXGF>1 K BMXTK("DISTINCT") ;Distinct supported for only one field S N=0,BMXFLDF=0,I=1,BMXNUM=0 D FIELDS D MAKEC ; ; I BMXCOL D COLTYPE^BMXSQL,ERRTACK^BMXSQL(I) Q ;Column info only ; S BMXA="A" N G,R ;---> Loop through results global F S N=$O(^BMXTMP($J,N)) Q:'+N D . K A . S R=0 F S R=$O(BMXFO(R)) Q:'+R D ;For each file in ORDER array . . S IEN0=0 . . S BMXFN=BMXFO(R) . . Q:$D(BMXMFL(BMXFN,"MULT")) . . I R=1 S IEN0=^BMXTMP($J,N) ;Primary file . . I R>1,$D(BMXFJ("JOIN",BMXFN)) D ;Joined file . . . S IEN0=0 . . . S G=BMXFJ("JOIN",BMXFN) . . . S V=BMXFF(G,"JOIN","IEN") . . . S @V=^BMXTMP($J,N) . . . X BMXFF(G,"JOIN") . . I +IEN0 D ;Removed $D(BMXGF(BMXFN)) for mult fld on extdnd ptr . . . D SUBFILE(BMXFN) . . I +IEN0,$D(BMXFLDN(BMXFN,.001)) D SETIEN(IEN0,BMXFN) . . ; . . I 0,R>1,$D(BMXMFL(BMXFN,"MULT")) D ;Multiple field . . . Q:'+IEN0 . . . Q:'$D(BMXGF(BMXFN)) ;Intervening multiple . . . ;Call GETS for each subentry in multiple . . . X BMXMFL(BMXFN,"EXEC") . S F=0,BMXCNT=0 . ; . D RECORD . D OUT ; ; ;---> Tack on Error Delimiter and any error. S I=I+1 D ERRTACK^BMXSQL(I) D COLTYPE^BMXSQL Q ; SETIEN(BMXIEN,BMXFN) ; ;B ;SETIEN Q:'$D(BMXFLDN(BMXFN,.001)) Q:'+BMXIEN S A(BMXFN,BMXIEN_",",.001,"E")=BMXIEN Q ; SUBFILE(BMXFN) ; ;Execute GETS for Any fields in BMXGF(SUBFILE) ; ;If the subfile itself has subfiles, call SUBFILE(BMXSUBFN) ; (Loop through BMXMFL(BMXFN,"SUBFILE",BMXSUBFN)) I $D(BMXMFL(BMXFN,"SUBFILE")) D . N BMXSUBFN . S BMXSUBFN=0 . F S BMXSUBFN=$O(BMXMFL(BMXFN,"SUBFILE",BMXSUBFN)) Q:'+BMXSUBFN D SUBFILE(BMXSUBFN) . Q ; I $D(BMXGF(BMXFN)) D . I '$D(BMXMFL(BMXFN,"MULT")) S BMXMSCR=1 D GETS^DIQ(BMXFN,IEN0_",",BMXGF(BMXFN),BMXGF(BMXFN,"INTERNAL"),BMXA) Q . E X BMXMFL(BMXFN,"EXEC") Q ; ; Q ; FIELDS ;---> Write Field Names ;Field name is TAAAAANAME ;Where T is the field type (T=Text; D=Date) ; AAAAA is the field size (see NUMCHAR routine) ; NAME is the field name N BMXNUM,BMXFNUM,BMXFNAM,R K BMXLEN,BMXTYP S BMXFLDF=1 S BMXNUM=0 ;B ;In FIELDS sub D ;:$D(A) . I BMXNUM S ^BMXTEMP($J,I)="IEN^",BMXLEN(I)=10,BMXTYP(I)="T",I=I+1 ;TODO: Change from text to number . S BMXFNUM=0 . S BMXFNAM=0 . F R=0:1:(BMXFLDO-1) S BMXFN=$P(BMXFLDO(R),U),BMXFNUM=$P(BMXFLDO(R),U,2) D . . ;S BMXFNAM=$P(^DD(BMXFN,BMXFNUM,0),"^") ;Get type here . . S BMXFNAM=BMXFLDN(BMXFN,BMXFNUM) . . I $P(BMXFLDO(R),U,3)="I" S BMXFNAM="INTERNAL["_BMXFNAM_"]" . . S BMXFNAM=$TR(BMXFNAM," ","_") . . I BMXF>1 S BMXFNAM=$TR($P(BMXFNX(BMXFN),".")," ","_")_"."_BMXFNAM . . S BMXTYP(I)="T" . . S:$P(BMXFLDO(R),U,5)="D" BMXTYP(I)="D" . . S:$P(BMXFLDO(R),U,5)="I" BMXTYP(I)="I" . . S BMXLEN(I)=0 ;Start with length zero . . ;I $D(BMXFLDA(BMXFN,BMXFNUM)) S BMXFNAM=BMXFLDA(BMXFN,BMXFNUM) . . I $P(BMXFLDO(R),U,6)]"" S BMXFNAM=$P(BMXFLDO(R),U,6) . . S ^BMXTEMP($J,I)=BMXFNAM_"^" . . S I=I+1 . S ^BMXTEMP($J,I-1)=$E(^BMXTEMP($J,I-1),1,$L(^BMXTEMP($J,I-1))-1)_$C(30) Q ; OUT ; ;Output to BMXTEMP($J Q:'$D(BMXREC) N J,K,L,BMXLENT S J=0 F S J=$O(BMXREC(J)) Q:'+J D . S K=0 F S K=$O(BMXREC(J,K)) Q:'+K D . . I +$O(BMXREC(J,K,0)) D Q ;WP . . . S L=0,BMXLENT=0 F S L=$O(BMXREC(J,K,L)) Q:'+L D . . . . S:'$D(^BMXTEMP($J,I)) ^BMXTEMP($J,I)="" . . . . S:$L(^BMXTEMP($J,I))>250 I=I+1,^BMXTEMP($J,I)="" . . . . S ^BMXTEMP($J,I)=^BMXTEMP($J,I)_BMXREC(J,K,L) . . . . S BMXLENT=BMXLENT+$L(BMXREC(J,K,L)) . . . I BMXLEN(K)250 I=I+1,^BMXTEMP($J,I)="" . . I $G(BMXTK("DISTINCT"))="TRUE",BMXREC(J,K)]"" Q:$D(^BMXTEMP($J,"DISTINCT",BMXREC(J,K))) . . S ^BMXTEMP($J,I)=^BMXTEMP($J,I)_BMXREC(J,K) . . S:$L(BMXREC(J,K))>BMXLEN(K) BMXLEN(K)=$L(BMXREC(J,K)) . . I $G(BMXTK("DISTINCT"))="TRUE" S ^BMXTEMP($J,"DISTINCT",BMXREC(J,K))="" Q ; RECORD ; ;For each chain N C,BMXCQ,BMXLCQ,BMXCQN,BMXLCQN,BMXTRACK,BMXNODE,BMXCNAME,BMXWP K BMXREC,BMXCHAIN ;TODO: REMOVE AFTER TESTING D BLDCHN S BMXREC=0 D RECINI S C=0 F S C=$O(BMXCHAIN(C)) Q:'+C D . ;New chain . ;Go to the end of the chain, writing record pieces as you go . ;At the end of the chain, write end-of-record marker,increment record counter, copy previous record . K BMXTRACK . S BMXCNAME="BMXCHAIN("_C_")" . S BMXCQN="" . S BMXCQ=BMXCNAME F S BMXCQ=$Q(@BMXCQ) Q:BMXCQ="" Q:$P(BMXCQ,",")'=("BMXCHAIN("_C) D . . S BMXNODE=@BMXCQ . . I $P(BMXNODE,U,2)="" Q . . S BMXWP=$P(BMXNODE,U,3) . . S BMXLCQ=$L(BMXCQ,",") . . S BMXCQN=$Q(@BMXCQ) . . S BMXLCQN=$L(BMXCQN,",") . . I BMXWP="W" D . . . S BMXREC(BMXREC,$P(BMXNODE,U,2),$P(BMXNODE,U,4))=$P(BMXNODE,U) . . . S BMXTRACK(BMXLCQ-1,$P(BMXNODE,U,2))=BMXNODE . . E D . . . S BMXREC(BMXREC,$P(BMXNODE,U,2))=$P(BMXNODE,U)_U . . . S BMXTRACK(BMXLCQ,$P(BMXNODE,U,2))=BMXNODE . . I BMXCQN="" D EOR Q . . I $P(BMXCQN,",")'=("BMXCHAIN("_C) D EOR Q . . I BMXLCQN>BMXLCQ Q . . I (BMXLCQN>$S(BMXWP="W":7,1:6)) D Q . . . I ($P(BMXCQ,",",1,BMXLCQ-2)=$P(BMXCQN,",",1,BMXLCQN-2)) Q . . . D EOR ;End of chain Q ; RECINI ; N J S BMXREC=BMXREC+1 F J=1:1:BMXFLDO D . I $P(BMXFLDO(J-1),U,4)="W" S BMXREC(BMXREC,J,999999)="^" Q . S BMXREC(BMXREC,J)="^" Q ; EOR ; ;B ;EOR N J,K,L,M,I,N ; S M=$Q(BMXREC(9999999),-1) //SMH - Another Cacheism S M=$$LAST("BMXREC") S @M=$TR(@M,"^",$C(30)) Q:BMXCQN="" I BMXCQN'="" D RECINI ;K BMXTRACK(BMXLCQ) ;Also kill all track levels between current and next level F K BMXTRACK($O(BMXTRACK(999999),-1)) Q:$O(BMXTRACK(9999999),-1)'>BMXLCQN S J=0 F S J=$O(BMXTRACK(J)) Q:'+J D ;Level . S K=0 F S K=$O(BMXTRACK(J,K)) Q:'+K D ;Order . . I $D(BMXTRACK(J,K)) S BMXNODE=BMXTRACK(J,K) S BMXREC(BMXREC,$P(BMXNODE,U,2))=$P(BMXNODE,U)_U . . S L=0 F S L=$O(BMXTRACK(J,K,L)) Q:'+L D ;wp node . . . I $D(BMXTRACK(J,K,L)) S BMXNODE=BMXTRACK(J,K,L) S BMXREC(BMXREC,$P(BMXNODE,U,2),L)=$P(BMXNODE,U) Q ; BLDCHN ; N B D MAKEB ;D MAKEC D BUILD Q ; MAKEC ; ;MAKE Chain ;How many chains are there? S BMXZ=0 S BMXCID=1 K BMXCFN ; ; ;Create BMXCHNP(BMXCID) S F=0 F S F=$O(BMXMFL(F)) Q:'+F I '$D(BMXMFL("SUBFILE",F)),$D(BMXMFL("PARENT",F)) S BMXMFL("BOTTOM",F)="" N BMXCB,BMXCHNP,BMXP S BMXCID=0,BMXCB=0,BMXCHNP=0 I $D(BMXMFL("BOTTOM")) F S BMXCB=$O(BMXMFL("BOTTOM",BMXCB)) Q:'BMXCB D . S BMXCID=BMXCID+1,BMXCHNP=BMXCID . S BMXCHNP(BMXCID)=BMXCB . S BMXP=BMXCB . F Q:'$D(BMXMFL("PARENT",BMXP)) S BMXP=BMXMFL("PARENT",BMXP) S BMXCHNP(BMXCID)=BMXP_U_BMXCHNP(BMXCID) ; N J,K,L,M ;Create BMXMFL("BASE")="FILE1^FILE2^...^FILEN" S F=0,M=0,BMXMFL("BASE")="" F S F=$O(BMXMFL(F)) Q:'+F I (('$D(BMXMFL("PARENT",F)))&('$D(BMXMFL(F,"SUBFILE"))))!(BMXFO(1)=F) S M=M+1,$P(BMXMFL("BASE"),U,M)=F ;Changed to make BMXFO(1) always a member of the base ; ;Create BMXCFN(BMXCID,BMXZ,FILE) I BMXCID=0 S BMXCID=1 S J=0,BMXZ=0 F J=1:1:BMXCID D . I BMXMFL("BASE")]"" F L=1:1:$L(BMXMFL("BASE"),"^") S F=$P(BMXMFL("BASE"),"^",L) D . . S BMXZ=BMXZ+100 . . S BMXCFN(J,BMXZ,F)="" . I +BMXCHNP F K=1:1:$L(BMXCHNP(J),"^") S F=$P(BMXCHNP(J),"^",K) D . . Q:F=BMXFO(1) ;BMXFO(1) Is always a member of the base . . S BMXZ=BMXZ+100 . . S BMXCFN(J,BMXZ,F)="" ; ; ;B ;FIXCFN D FIXCFN Q ; BUILD ;Building BMXCHAIN( N BMXIEN,BMXCID,BMXFLD,BMXCS,BMXINT,BMXCFNC,BMXCFIEN S BMXCID=0,BMXIEN=0 F S BMXCID=$O(BMXCFN(BMXCID)) Q:'+BMXCID D . S BMXCFNC=0 F S BMXCFNC=$O(BMXCFN(BMXCID,BMXCFNC)) Q:'+BMXCFNC S BMXCFN=+BMXCFN(BMXCID,BMXCFNC) D . . S BMXIEN=0 F S BMXIEN=$O(B(BMXCFN,BMXIEN)) Q:BMXIEN="" D . . . S $P(BMXCFN(BMXCID,BMXCFNC),U,2)=BMXIEN . . . S BMXFLD=0 F S BMXFLD=$O(B(BMXCFN,BMXIEN,BMXFLD)) Q:'+BMXFLD D . . . . S BMXINT="D" F S BMXINT=$O(B(BMXCFN,BMXIEN,BMXFLD,BMXINT)) Q:BMXINT="" D . . . . . Q:'$D(BMXFLDOX(BMXCFN,BMXFLD,BMXINT)) . . . . . I $P(BMXFLDO(BMXFLDOX(BMXCFN,BMXFLD,BMXINT)),U,4)="W" D MCWP Q . . . . . D FIXIEN . . . . . S BMXCS="BMXCHAIN("_BMXCID_","_$S($L(BMXIEN,",")=2:1,1:2)_","_BMXCFIEN_","_BMXFLD_","_$C(34)_BMXINT_$C(34)_")" . . . . . S @BMXCS=B(BMXCFN,BMXIEN,BMXFLD,BMXINT)_U_(BMXFLDOX(BMXCFN,BMXFLD,BMXINT)+1) Q ; FIXIEN ; N BMXC,BMXCFN1,BMXOFF S BMXC=BMXCFNC S BMXCFIEN=BMXCFN_","_$P(BMXIEN,",",$L(BMXIEN,",")) S BMXOFF=1 F S BMXC=$O(BMXCFN(BMXCID,BMXC),-1) Q:'+BMXC D . S BMXCFN1=+BMXCFN(BMXCID,BMXC) . I '$D(BMXMFL(BMXCFN,"OTM")) D . . I '$D(BMXMFL(BMXCFN1,"SUBFILE",BMXCFN)) Q . . S BMXCFIEN=BMXCFN1_","_$P(BMXIEN,",",$L(BMXIEN,",")-BMXOFF)_","_BMXCFIEN . I $D(BMXMFL(BMXCFN,"OTM")) D . . I '$D(BMXMFL(BMXCFN1,"SUBFILE",BMXCFN)) Q . . S BMXCFIEN=BMXCFN1_$P(BMXCFN(BMXCID,BMXC),U,2)_","_BMXCFIEN . S BMXOFF=BMXOFF+1 ; ; Q ; FIXCFN ; N J,K,L S J=0 F S J=$O(BMXCFN(J)) Q:'+J D . S K=0 F S K=$O(BMXCFN(J,K)) Q:'+K D . . S L=0 F S L=$O(BMXCFN(J,K,L)) Q:'+L D . . . K BMXCFN(J,K,L) . . . S BMXCFN(J,K)=L ; Q ; MCWP ; ;MAKEC Process WP Field N BMXIENL,BMXWP S BMXIENL=1 S:$L(BMXIEN,",")>2 BMXIENL=2 S BMXWP=0 ; F S BMXWP=$O(B(BMXCFN,BMXIEN,BMXFLD,BMXWP)) Q:'+BMXWP D . S BMXCS="BMXCHAIN("_BMXCID_","_BMXIENL_","_BMXCFN_BMXIEN_","_BMXFLD_","_$C(34)_BMXINT_$C(34)_","_BMXWP_")" . S @BMXCS=B(BMXCFN,BMXIEN,BMXFLD,BMXWP)_U_(BMXFLDOX(BMXCFN,BMXFLD,BMXINT)+1)_U_"W"_U_BMXWP Q ; ; MAKEB ; N BMXFILE,BMXIEN,BMXFLD,BMXINT N BMXSUB,BMXIENR S BMXFILE=0 F S BMXFILE=$O(A(BMXFILE)) Q:'+BMXFILE D . S BMXIEN=0 F S BMXIEN=$O(A(BMXFILE,BMXIEN)) Q:'+BMXIEN D . . S BMXFLD=0 F S BMXFLD=$O(A(BMXFILE,BMXIEN,BMXFLD)) Q:'+BMXFLD D . . . S BMXINT=0 F S BMXINT=$O(A(BMXFILE,BMXIEN,BMXFLD,BMXINT)) Q:BMXINT="" D . . . . S BMXIENR=$$REVERSE(BMXIEN) . . . . S BMXSUB="B("_BMXFILE_","_$C(34)_BMXIENR_$C(34)_","_BMXFLD_","_$C(34)_BMXINT_$C(34)_")" . . . . I $D(BMXFLDOX(BMXFILE,BMXFLD,BMXINT)),$P(BMXFLDO(BMXFLDOX(BMXFILE,BMXFLD,BMXINT)),U,5)="D" D Q . . . . . S @BMXSUB=$TR(A(BMXFILE,BMXIEN,BMXFLD,BMXINT),"@"," ") . . . . S @BMXSUB=A(BMXFILE,BMXIEN,BMXFLD,BMXINT) Q ; REVERSE(BMXIEN) ; N J,T,C S C=1 F J=$L(BMXIEN,","):-1:1 D . S $P(T,",",C)=$P(BMXIEN,",",J) . S C=C+1 Q T LAST(VAR) ; Get last entry in an array //SMH new code N SUB1 S SUB1=$O(@VAR@(""),-1) N SUB2 S SUB2=$O(@VAR@(SUB1,""),-1) N SUB3 S SUB3=$O(@VAR@(SUB1,SUB2,""),-1) I SUB3="" Q $NA(@VAR@(SUB1,SUB2)) E Q $NA(@VAR@(SUB1,SUB2,SUB3))