BMXSQL5	; IHS/OIT/HMW - BMX REMOTE PROCEDURE CALLS ;
	;;2.1;BMX;;Jul 26, 2009
	;
	;
SELECT	;EP - Get field names into BMXFLD("NAME")="FILE#^FIELD#"
	N BMXA,BMXB,BMXS,BMXSINGL
	N BMXINTNL
	S T=$G(BMXTK("SELECT"))
	I '+T S BMXERR="'SELECT' CLAUSE NOT FOUND" D ERRTACK^BMXSQL(1) Q
	S BMXFLD=0
	N BMXOFF,BMXGS1,BMXLVL
	F  S T=$O(BMXTK(T)) Q:'+T  Q:T=$G(BMXTK("FROM"))  I BMXTK(T)'="," S BMXOFF=1,BMXLVL=0 D S1 Q:$D(BMXERR)
	Q
	;
SALIAS	;
	Q:'+$O(BMXTK(T))
	N V
	S V=T+1
	Q:$G(BMXTK(V))=","
	Q:V=$G(BMXTK("FROM"))
	S:BMXTK(V)["'" BMXTK(V)=$P(BMXTK(V),"'",2)
	S BMXFLDA(BMXFILE,BMXFLDN)=BMXTK(V)
	S $P(BMXFLDO(BMXFLDO-1),U,6)=BMXTK(V)
	S T=T+1
	Q
	;
S1	;
	S BMXTK(T)=$TR(BMXTK(T),"_"," ")
	;Check for INTERNAL[ modifier
	S BMXGS1=0
	S BMXINTNL="E"
	I BMXTK(T)["[" S BMXINTNL="I",BMXTK(T)=$P(BMXTK(T),"[",2),BMXTK(T)=$P(BMXTK(T),"]",1)
	;If explicit file name
	S BMXSINGL=0
	I BMXTK(T)["." D  G:BMXGS1 S1 G:BMXSINGL NOTEXP Q
	. ;Before FILE.FIELD Parsing
	. S BMXA=$P(BMXTK(T),".",1,BMXOFF) ;File Name
	. I '$D(BMXF(BMXA)) D  Q:$D(BMXERR)  Q:BMXSINGL
	. . I $D(^DD(BMXFO(1),"B",BMXTK(T))),BMXOFF=1 S BMXSINGL=1 Q
	. . S BMXERR="FILE NOT FOUND" D ERRTACK^BMXSQL(1) Q
	. S BMXB=$P(BMXTK(T),".",1+BMXOFF,99) ;Field Name TODO: Test here for multiple in extended pointer -- FILE.MULTIPLE.FIELD
	. N BMXLAST S BMXLAST=0
	. I $L(BMXB,".")>1 D  Q:'BMXLAST  ;Multiple
	. . N BMXFNUM,BMXFNAM,BMXFNOD,BMXSUBFN,BMXUPFN,BMXGL,W,BMXFOUND
	. . ;Multiple or Field-name with period?
	. . S BMXFOUND=0
	. . F W=1:1:$L(BMXTK(T),".") D  Q:BMXFOUND
	. . . S BMXOFF=BMXOFF+1
	. . . I $D(^DD(BMXF(BMXA),"B",$P(BMXB,".",1,W))) D
	. . . . S BMXFNAM=$P(BMXB,".",1,W)
	. . . . S BMXFOUND=1
	. . . . S:W=$L(BMXB,".") BMXLAST=1
	. . . . S BMXLVL=BMXLVL+1
	. . ;
	. . Q:BMXLAST
	. . S BMXF=BMXF+1
	. . S BMXFNUM=$O(^DD(BMXF(BMXA),"B",BMXFNAM,0)) ;FieldNumber
	. . S BMXFNOD=^DD(BMXF(BMXA),BMXFNUM,0)
	. . S BMXGL=$P(BMXFNOD,U,4),BMXGL=$P(BMXGL,";")
	. . S BMXSUBFN=+$P(BMXFNOD,U,2) ;Subfile Number
	. . S BMXUPFN=^DD(BMXSUBFN,0,"UP") ;Parent File Number
	. . D SETMFL(BMXUPFN,BMXSUBFN,BMXGL,BMXLVL,0)
	. . S BMXGS1=1
	. S:BMXB["'" BMXB=$P(BMXB,"'",2)
	. I BMXB="BMXIEN" D  Q
	. . S BMXFLD(BMXA_"."_BMXB)=BMXF(BMXA)
	. . S $P(BMXFLD(BMXA_"."_BMXB),"^",2)=".001"
	. . D SELECT1
	. I BMXB="*" D  Q  ;All fields in file BMXA
	. . ;BMXIEN Has to be first because ADO doesn't handle it well if a DATE type column is returned first
	. . S BMXB="BMXIEN"
	. . S BMXFLD(BMXA_"."_BMXB)=BMXF(BMXA)
	. . S $P(BMXFLD(BMXA_"."_BMXB),"^",2)=".001"
	. . D SELECT1
	. . S BMXB=0 F  S BMXB=$O(^DD(BMXF(BMXA),"B",BMXB)) Q:BMXB=""  D
	. . . S BMXFLD(BMXA_"."_BMXB)=BMXF(BMXA)
	. . . S $P(BMXFLD(BMXA_"."_BMXB),"^",2)=$O(^DD(BMXF(BMXA),"B",BMXB,0))
	. . . D SELECT1
	. S BMXFLD(BMXA_"."_BMXB)=BMXF(BMXA)
	. I '$D(^DD(BMXF(BMXA),"B",BMXB)) S BMXERR="FIELD NOT FOUND" D ERRTACK^BMXSQL(1) Q
	. S $P(BMXFLD(BMXA_"."_BMXB),"^",2)=$O(^DD(BMXF(BMXA),"B",BMXB,0))
	. D SELECT1
	. Q
	;
NOTEXP	;File not explicit so Loop through files in BMXF to locate field name
	;
	I BMXTK(T)["'" S BMXTK(T)=$P(BMXTK(T),"'",2)
	S C=0,BMXA=""
	I BMXTK(T)="BMXIEN" D  Q
	. S BMXB=BMXTK(T)
	. S BMXA=BMXFO(1) ;File defaults to first named file in FROM
	. S BMXA=BMXFNX(BMXA)
	. S BMXFLD(BMXA_"."_BMXB)=BMXF(BMXA)
	. S $P(BMXFLD(BMXA_"."_BMXB),"^",2)=".001"
	. D SELECT1
	F  S BMXA=$O(BMXF(BMXA)) Q:BMXA=""  D  Q:$D(BMXERR)
	. S BMXB=BMXTK(T)
	. I BMXB="*" D  Q  ;All fields in file BMXA
	. . S BMXB="BMXIEN"
	. . S BMXA=BMXFO(1) ;File defaults to first named file in FROM
	. . S BMXA=BMXFNX(BMXA)
	. . S BMXFLD(BMXA_"."_BMXB)=BMXF(BMXA)
	. . S $P(BMXFLD(BMXA_"."_BMXB),"^",2)=".001"
	. . D SELECT1
	. . S BMXB=0 F  S BMXB=$O(^DD(BMXF(BMXA),"B",BMXB)) Q:BMXB=""  D
	. . . S BMXS=BMXA_"."_BMXB
	. . . S BMXFLD(BMXS)=BMXF(BMXA)
	. . . S $P(BMXFLD(BMXS),"^",2)=$O(^DD(BMXF(BMXA),"B",BMXB,0))
	. . . D SELECT1
	. . . S C=1
	. I $D(^DD(BMXF(BMXA),"B",BMXTK(T))) D  Q:$D(BMXERR)
	. . S C=C+1
	. . I C>1 S BMXERR="AMBIGUOUS FIELD NAME" D ERRTACK^BMXSQL(1) Q
	. . S BMXB=BMXTK(T) ;Field Name
	. . I BMXB["'" S BMXB=$P(BMXB,"'",2)
	. . S BMXFLD(BMXA_"."_BMXB)=BMXF(BMXA)
	. . S $P(BMXFLD(BMXA_"."_BMXB),"^",2)=$O(^DD(BMXF(BMXA),"B",BMXB,0))
	. . D SELECT1
	. . Q
	. Q
	I C=0 S BMXERR="FIELD NOT FOUND" D ERRTACK^BMXSQL(1) Q
	Q
	;
SELECT1	;
	N BMXGNOD,BMXFILE,BMXGNOD1
	S BMXFLDN=$P(BMXFLD(BMXA_"."_BMXB),"^",2)
	S BMXFILE=$P(BMXFLD(BMXA_"."_BMXB),U)
	S BMXFLDN(BMXFILE,BMXFLDN)=BMXB
	I BMXFLDN=".001" S BMXGNOD="IEN",BMXGNOD1="",$P(BMXGNOD1,U,2)="N"
	E  S BMXGNOD1=^DD(BMXFILE,BMXFLDN,0)
	S BMXGNOD=$P(BMXGNOD1,"^",4)
	S $P(BMXFLD(BMXA_"."_BMXB),"^",3)=$P(BMXGNOD,";")
	S $P(BMXFLD(BMXA_"."_BMXB),"^",4)=$P(BMXGNOD,";",2)
	S $P(BMXFLD(BMXA_"."_BMXB),"^",5)=BMXINTNL
	S BMXFLDO(BMXFLD)=BMXFILE_"^"_BMXFLDN_"^"_BMXINTNL
	I +$P(BMXGNOD1,U,2) D  ;Check for WP
	. S BMXGNOD1=+$P(BMXGNOD1,U,2)
	. Q:'$D(^DD(BMXGNOD1,.01,0))
	. I $P(^DD(BMXGNOD1,.01,0),U,2)["W" S $P(BMXFLDO(BMXFLD),U,4)="W"
	;HMW20030630 Modified next line to make data type of Internal[] for pointer an Integer.
	I $P(BMXGNOD1,U,2)["P" S BMXGNOD1=$$PTYPE(BMXGNOD1) Q:BMXGNOD1=""  S:$G(BMXINTNL)="I" $P(BMXGNOD1,U,2)="N" ;I BMXGNOD1="" then Pointed-to file doesn't exist
	I $P(BMXGNOD1,U,2)["D" S $P(BMXFLDO(BMXFLD),U,5)="D"
	I $P(BMXGNOD1,U,2)["N" D
	. N Z
	. S Z=$P(BMXGNOD1,U,2)
	. I +$P(Z,",",2)=0 S $P(BMXFLDO(BMXFLD),U,5)="I" ;Integer
	S BMXFLDOX(BMXFILE,BMXFLDN,BMXINTNL)=BMXFLD
	S BMXFLD=BMXFLD+1
	S BMXFLDO=BMXFLD
	D SALIAS
	Q
	;
SETMFL(BMXUPFN,BMXSUBFN,BMXGL,BMXOFF,BMXOTM)	      ;EP
	;
	;BMXOTM = One-To-Many
	N BMXUPG
	S BMXMFL("PARENT",BMXSUBFN)=BMXUPFN
	S BMXMFL(BMXUPFN,"SUBFILE",BMXSUBFN)=""
	S BMXMFL("SUBFILE",BMXUPFN,BMXSUBFN)=""
	S BMXUPG=BMXMFL(BMXUPFN,"GLOC") ;Parent File Global Set in FROM clause
	S BMXFNAM=BMXA_"."_BMXFNAM ;TODO: Regression test this line with OTM
	I 'BMXOTM S BMXMFL(BMXSUBFN,"GLOC")=BMXUPG_"IEN"_(BMXOFF-1)_","_$C(34)_BMXGL_$C(34)_","
	E  S BMXMFL(BMXSUBFN,"GLOC")=BMXGL,BMXMFL(BMXSUBFN,"OTM")=""
	S BMXMFL(BMXSUBFN,"MULT")="S IEN"_BMXOFF_"=0 F  S IEN"_BMXOFF_"=$O("_BMXMFL(BMXSUBFN,"GLOC")_"IEN"_BMXOFF_")) Q:'+IEN"_BMXOFF_"  "
	I $D(BMXMFL(BMXUPFN,"MULT")) S BMXMFL(BMXSUBFN,"MULT")=BMXMFL(BMXUPFN,"MULT")_" "_BMXMFL(BMXSUBFN,"MULT")
	I 'BMXOTM S BMXMFL(BMXSUBFN,"IENS")="N J S BMXIENS="""" F J=0:1:"_BMXOFF_" S BMXIENS=@(""IEN""_J)_"",""_BMXIENS"
	E  S BMXMFL(BMXSUBFN,"IENS")="N J S BMXIENS="""" S J=1 S BMXIENS=@(""IEN""_J)_"",""_BMXIENS"
	S BMXMFL(BMXSUBFN,"EXEC")=BMXMFL(BMXSUBFN,"MULT")_"X BMXMFL(BMXFN,""IENS"")"_" D GETS^DIQ(BMXFN,BMXIENS,BMXGF(BMXFN),""E"",BMXA) D SETIEN(IEN"_BMXOFF_",BMXFN)"
	D F1^BMXSQL(BMXF,BMXFNAM,BMXSUBFN)
	;
	Q
	;
PTYPE(BMXGNOD1)	;
	;Traverse pointer chain to retrieve data type of pointed-to field
	N BMXFILE
	I $P(BMXGNOD1,U,2)'["P" Q BMXGNOD1
	S BMXFILE=$P(BMXGNOD1,U,2)
	S BMXFILE=+$P(BMXFILE,"P",2)
	S BMXGNOD1=$G(^DD(BMXFILE,".01",0))
	S BMXGNOD1=$$PTYPE(BMXGNOD1)
	Q BMXGNOD1
