1 | TMGFMUT ;TMG/kst/Fileman utility functions ;03/25/06
|
---|
2 | ;;1.0;TMG-LIB;**1**;07/12/05
|
---|
3 |
|
---|
4 | ;"TMG FILEMAN-UTILITY FUNCTIONS
|
---|
5 | ;"Kevin Toppenberg MD
|
---|
6 | ;"GNU General Public License (GPL) applies
|
---|
7 | ;"7-12-2005
|
---|
8 |
|
---|
9 | ;"=======================================================================
|
---|
10 | ;" API -- Public Functions.
|
---|
11 | ;"=======================================================================
|
---|
12 | ;"$$PTRLINKS
|
---|
13 | ;"$$FilePtrs(File,OutVarP)
|
---|
14 | ;"DispArray(ArrayP,DispdList,indentDepth,MaxDepth)
|
---|
15 | ;"ASKPTRIN
|
---|
16 | ;"ASKMVPTR
|
---|
17 | ;"QTMVPTR(Info,PFn) --quietly redirect pointers.
|
---|
18 | ;"QTMMVPTR(Info,ShowProgress) --quietly redirect multiple pointers at once.
|
---|
19 | ;"$$PtrsIn(File,IEN,Array)
|
---|
20 | ;"$$PtrsMIn(IENArray,Array,ShowProgress)
|
---|
21 | ;"$$PossPtrs(File,Array)
|
---|
22 | ;"$$FMDate(DateStr) -- convert string to FM date, with extended syntax handing
|
---|
23 |
|
---|
24 | ;"=======================================================================
|
---|
25 | ;"PRIVATE API FUNCTIONS
|
---|
26 | ;"=======================================================================
|
---|
27 | ;"ScanFile(FInfo,IEN,Array)
|
---|
28 | ;"ScanMFile(FInfoArray,IENArray,Array,ShowProgress)
|
---|
29 | ;"HandleSubFile(SearchValue,FileArray,Array,IENS,Ref)
|
---|
30 | ;"HandleMSubFile(IENArray,FileArray,Array,IENS,Ref)
|
---|
31 |
|
---|
32 | ;"=======================================================================
|
---|
33 | ;"DEPENDENCIES
|
---|
34 | ;"=======================================================================
|
---|
35 | ;"TMGDBAPI
|
---|
36 | ;"=======================================================================
|
---|
37 |
|
---|
38 |
|
---|
39 | PTRLINKS
|
---|
40 | ;"Purpose: To examine the Fileman data dictionary for a specified file
|
---|
41 | ;" Then tell any pointers out to other files. If found, then display
|
---|
42 | ;" this 'dependency'. Then follow trail to that file, and show it's
|
---|
43 | ;" 'dependency'. Trail will be followed up to N levels deep (set=6 here)
|
---|
44 | ;"Results: 1=OKToContinue, 0=failure
|
---|
45 |
|
---|
46 | new File,Info,DispdList
|
---|
47 | new result
|
---|
48 |
|
---|
49 | write "Display pointer dependencies between files.",!!
|
---|
50 | read "Enter file name or number to explore (^ to abort): ",File,!
|
---|
51 | if File="^" goto PTDone
|
---|
52 | set result=$$FilePtrs(File,"Info")
|
---|
53 | if result=0 write "Error. Aborting. Sorry about that...",!! goto PTDone
|
---|
54 |
|
---|
55 | do DispArray("Info",.DispdList,0,6) ;"force max depth=6
|
---|
56 |
|
---|
57 | PTDone
|
---|
58 | quit result
|
---|
59 |
|
---|
60 |
|
---|
61 | FilePtrs(File,OutVarP)
|
---|
62 | ;"For File, create array listing those fields with pointers to other files
|
---|
63 | ;"Input: File -- can be file name or number to explore
|
---|
64 | ;" OutVarP -- the name of array to put results into
|
---|
65 | ;"Output: Values are put into @OutVarP as follows:
|
---|
66 | ;" @OutVarP@(FileNum,"FILE NAME")=File Name
|
---|
67 | ;" @OutVarP@(FileNum,FieldNum)=Field Number
|
---|
68 | ;" @OutVarP@(FileNum,FieldNum,"FIELD NAME")=Field Name
|
---|
69 | ;" @OutVarP@(FileNum,FieldNum,"POINTS TO","GREF")=Open format global reference
|
---|
70 | ;" @OutVarP@(FileNum,FieldNum,"POINTS TO","FILE NAME")=File name pointed to
|
---|
71 | ;" @OutVarP@(FileNum,FieldNum,"POINTS TO","FILE NUMBER")=File number pointed to
|
---|
72 | ;" @OutVarP@(FileNum,FieldNum,"X GET")=Code to xecute to get value
|
---|
73 | ;" e.g. SET TMGVALUE=$PIECE($GET(^VA(200,TMGIEN,.11),"^",5))"
|
---|
74 | ;" note: TMGIEN is IEN to lookup, and result is in TMGVALUE
|
---|
75 | ;" @OutVarP@(FileNum,FieldNum,"X SET")=Code to xecute to set value
|
---|
76 | ;" e.g. SET TMGVALUE=$PIECE(^VA(200,TMGIEN,.11),"^",5)=TMGVALUE"
|
---|
77 | ;" ** For subfiles ** ...
|
---|
78 | ;" @OutVarP@(FileNum,FieldNum,"SUBFILE",FileNum,FieldNum,"FIELD NAME")=Field Name
|
---|
79 | ;" @OutVarP@(FileNum,FieldNum,"SUBFILE",FileNum,FieldNum,"POINTS TO","GREF")=Open format global reference
|
---|
80 | ;" @OutVarP@(FileNum,FieldNum,"SUBFILE",FileNum,FieldNum,"POINTS TO","FILE NAME")=File name pointed to
|
---|
81 | ;" @OutVarP@(FileNum,FieldNum,"SUBFILE",FileNum,FieldNum,"POINTS TO","FILE NUMBER")=File number pointed to
|
---|
82 | ;" @OutVarP@(FileNum,FieldNum,"SUBFILE",FileNum,FieldNum,"X GET")=Code to xecute to get value
|
---|
83 | ;" e.g. SET TMGVALUE=$PIECE($GET(^VA(200,TMGIEN,TMGIEN(1),.11),"^",5))"
|
---|
84 | ;" note: TMGIEN is IEN to lookup, and result is in TMGVALUE
|
---|
85 | ;" @OutVarP@(FileNum,FieldNum,"X SET")=Code to xecute to set value
|
---|
86 | ;" e.g. SET TMGVALUE=$PIECE(^VA(200,TMGIEN,TMGIEN(1),.11),"^",5)=TMGVALUE"
|
---|
87 | ;" ... etc.
|
---|
88 | ;"Results: 1=OKToContinue, 0=failure
|
---|
89 |
|
---|
90 | new TMGptrArray
|
---|
91 | new result
|
---|
92 | new index
|
---|
93 | new FileNum,FileName
|
---|
94 |
|
---|
95 | set result=$$GetFldList^TMGDBAPI(.File,"TMGptrArray")
|
---|
96 | if result=0 goto FPtrDone
|
---|
97 | set result=($get(OutVarP)'="")
|
---|
98 | if result=0 goto FPtrDone
|
---|
99 | if +$get(File)=0 do
|
---|
100 | . set FileNum=$$GetFileNum^TMGDBAPI(.File)
|
---|
101 | . set FileName=$get(File)
|
---|
102 | else do
|
---|
103 | . set FileNum=+File
|
---|
104 | . set FileName=$$GetFName^TMGDBAPI(FileNum)
|
---|
105 | set result=(FileNum'=0)
|
---|
106 | if result=0 goto FPtrDone
|
---|
107 |
|
---|
108 | set index=$order(TMGptrArray(""))
|
---|
109 | for do quit:(result=0)!(index="")
|
---|
110 | . new fieldnum,TMGFldInfo
|
---|
111 | . set fieldnum=index
|
---|
112 | . if +fieldnum=0 set result=0 quit
|
---|
113 | . do FIELD^DID(FileNum,fieldnum,,"POINTER;MULTIPLE-VALUED","TMGFldInfo","TMGMsg")
|
---|
114 | . if $data(TMGMsg) do set result=0 quit
|
---|
115 | . . if $get(TMGDEBUG)>0 do ArrayDump^TMGDEBUG("TMGMsg")
|
---|
116 | . . if $data(TMGMsg("DIERR"))'=0 do quit
|
---|
117 | . . . do ShowDIERR^TMGDEBUG(.TMGMsg,.PriorErrorFound)
|
---|
118 | . if $get(TMGFldInfo("MULTIPLE-VALUED"))=1 do
|
---|
119 | . . ;" handle subfiles via a recursive call
|
---|
120 | . . new subfile,subArrayP
|
---|
121 | . . set subfile=$$GetSubFileNumber^TMGDBAPI(FileNum,fieldnum)
|
---|
122 | . . if subfile=0 quit
|
---|
123 | . . set subArrayP=$name(@OutVarP@(FileNum,fieldnum,"SUBFILE"))
|
---|
124 | . . ;"set subArrayP=OutVarP
|
---|
125 | . . set result=$$FilePtrs(subfile,subArrayP)
|
---|
126 | . if $get(TMGFldInfo("POINTER"))'="" do
|
---|
127 | . . if +TMGFldInfo("POINTER")>0 quit ;"screen out computed nodes.
|
---|
128 | . . if TMGFldInfo("POINTER")[":" quit ;"screen out set type fields
|
---|
129 | . . new gref,node0
|
---|
130 | . . set gref=TMGFldInfo("POINTER")
|
---|
131 | . . set @OutVarP@(FileNum,"FILE NAME")=FileName
|
---|
132 | . . set @OutVarP@(FileNum,fieldnum,"FIELD NAME")=$$GetFldName^TMGDBAPI(FileNum,fieldnum)
|
---|
133 | . . set @OutVarP@(FileNum,fieldnum,"POINTS TO","GREF")=gref
|
---|
134 | . . set gref="^"_gref_"0)"
|
---|
135 | . . ;"write "index=",index," gref=",gref,!
|
---|
136 | . . set node0=$get(@gref)
|
---|
137 | . . set @OutVarP@(FileNum,fieldnum,"POINTS TO","FILE NAME")=$piece(node0,"^",1)
|
---|
138 | . . set @OutVarP@(FileNum,fieldnum,"POINTS TO","FILE NUMBER")=+$piece(node0,"^",2)
|
---|
139 | . . new DD set DD=$get(^DD(FileNum,fieldnum,0)) quit:(DD="")
|
---|
140 | . . new nodepce set nodepce=$piece(DD,"^",4) quit:(nodepce="")
|
---|
141 | . . new node set node=+$piece(nodepce,";",1) quit:(node="")
|
---|
142 | . . new pce set pce=+$piece(nodepce,";",2) quit:(pce'>0)
|
---|
143 | . . new thisGL set thisGL=$get(^DIC(FileNum,0,"GL"))
|
---|
144 | . . new getCode,setCode
|
---|
145 | . . if thisGL="" do quit:(thisGL="")
|
---|
146 | . . . ;"Note: I am only going to support 1 sub level. More--> brain hurts!
|
---|
147 | . . . new upNum set upNum=$get(^DD(FileNum,0,"UP"))
|
---|
148 | . . . if upNum="" quit
|
---|
149 | . . . set thisGL=$get(^DIC(upNum,0,"GL"))
|
---|
150 | . . . if thisGL="" quit ;"happens with sub-sub.. nodes.
|
---|
151 | . . . set getCode="SET TMGVALUE=$PIECE($GET("_thisGL_"TMGIEN,TMGIEN(1),"_node_")),""^"","_pce_")"
|
---|
152 | . . . set setCode="SET $PIECE("_thisGL_"TMGIEN,TMGIEN(1),"_node_"),""^"","_pce_")=TMGVALUE"
|
---|
153 | . . else do
|
---|
154 | . . . set getCode="SET TMGVALUE=$PIECE($GET("_thisGL_"TMGIEN,"_node_")),""^"","_pce_")"
|
---|
155 | . . . set setCode="SET $PIECE("_thisGL_"TMGIEN,"_node_"),""^"","_pce_")=TMGVALUE"
|
---|
156 | . . set @OutVarP@(FileNum,fieldnum,"X GET")=getCode
|
---|
157 | . . set @OutVarP@(FileNum,fieldnum,"X SET")=setCode
|
---|
158 | . set index=$order(TMGptrArray(index))
|
---|
159 |
|
---|
160 | FPtrDone
|
---|
161 | quit result
|
---|
162 |
|
---|
163 | DispArray(ArrayP,DispdList,indentDepth,MaxDepth)
|
---|
164 | ;"Purpose: Display array created by FilePtrs (see format there)
|
---|
165 | ;"Input: ArrayP : name of array containing information
|
---|
166 | ;" DispdList : array (pass by reference) contining list of files already displayed
|
---|
167 | ;" DispdList("TIU DOCUMENT")=""
|
---|
168 | ;" DispdList("PATIENT")="" etc.
|
---|
169 | ;" indentDepth : Number of indents deep this function is. Default=0
|
---|
170 | ;" MaxDepth : maximum number of indents deep allowed.
|
---|
171 |
|
---|
172 | new i,fieldnum,file,FileName
|
---|
173 | set indentDepth=+$get(indentDepth,0)
|
---|
174 | new indentS set indentS=""
|
---|
175 | for i=1:1:(indentDepth) s indentS=indentS_". "
|
---|
176 |
|
---|
177 | set file=$order(@ArrayP@(""))
|
---|
178 | set FileName=$get(@ArrayP@(file,"FILE NAME"))
|
---|
179 | set DispdList(FileName)=""
|
---|
180 | if FileName'="" write indentS,"FILE: ",FileName,!
|
---|
181 | set fieldnum=$order(@ArrayP@(file,""))
|
---|
182 | for do quit:(+fieldnum=0)
|
---|
183 | . if +fieldnum=0 quit
|
---|
184 | . new p2FName
|
---|
185 | . set p2FName=$get(@ArrayP@(file,fieldnum,"POINTS TO","FILE NAME"))
|
---|
186 | . write indentS,"field: ",$get(@ArrayP@(file,fieldnum,"FIELD NAME")),"--> file: ",p2FName
|
---|
187 | . if $data(DispdList(p2FName))=0 do
|
---|
188 | . . set DispdList(p2FName)=""
|
---|
189 | . . if indentDepth<MaxDepth do
|
---|
190 | . . . new p2Array
|
---|
191 | . . . if $$FilePtrs(p2FName,"p2Array")=0 do quit
|
---|
192 | . . . . write " (?)",!
|
---|
193 | . . . write !
|
---|
194 | . . . do DispArray("p2Array",.DispdList,indentDepth+1,.MaxDepth)
|
---|
195 | . . else write " (...)",!
|
---|
196 | . else do
|
---|
197 | . . write " (above)",!
|
---|
198 | . set fieldnum=$order(@ArrayP@(file,fieldnum))
|
---|
199 |
|
---|
200 | quit
|
---|
201 |
|
---|
202 |
|
---|
203 | ASKPTRIN
|
---|
204 | ;"Purpose: An interface shell to PtrsIn.
|
---|
205 | ;" Will ask for name of a file, and then a record in that file.
|
---|
206 | ;" Will then show all pointers to that particular record.
|
---|
207 |
|
---|
208 | new File,IEN,Array,PFn,result
|
---|
209 |
|
---|
210 | write !!,"Pointer Scanner.",!
|
---|
211 | write "Will look for all pointers (references) to specified record.",!!
|
---|
212 | set DIC="^DIC("
|
---|
213 | set DIC(0)="MAQE"
|
---|
214 | d ^DIC
|
---|
215 | set File=+Y
|
---|
216 | if File'>0 goto APTDone
|
---|
217 | set DIC=File
|
---|
218 | do ^DIC
|
---|
219 | set IEN=+Y
|
---|
220 | if IEN'>0 goto APTDone
|
---|
221 | new TMGTIME set TMGTIME=$H
|
---|
222 | ;"set PFn="w TMGCODE,"" "",((TMGCUR/TMGTOTAL)*100)\1,""%"",!"
|
---|
223 | set PFn="do ProgressBar^TMGUSRIF(TMGCUR,""File: ""_$P(TMGCODE,""^"",1),1,TMGTOTAL)"
|
---|
224 | write !!,"Starting File Scan for instances of pointers (references) to this record.",!!
|
---|
225 | set result=$$PtrsIn(File,IEN,.Array,PFn)
|
---|
226 | if result=0 write !,"There was some problem. Sorry.",!! goto APTDone
|
---|
227 |
|
---|
228 | if $data(Array) do
|
---|
229 | . write !,"Done. Here are results:",!
|
---|
230 | . write "Format is: ",!
|
---|
231 | . write " Array(File#,IEN,0)=LastCount",!
|
---|
232 | . write " Array(File#,IEN,count)=FullRef;piece;IENS;TopGlobalRef",!
|
---|
233 | . write " Description of parts:",!
|
---|
234 | . write " ----------------------",!
|
---|
235 | . write " File# -- the file the found entry exists it (may be a subfile number)",!
|
---|
236 | . write " IEN -- the record number in file",!
|
---|
237 | . write " Note: IEN here is different from the IEN passed in as a parameter",!
|
---|
238 | . write " FullRef -- the is the full reference to the found value. e.g.",!
|
---|
239 | . write " set value=$piece(@FullRef,""^"",piece)",!
|
---|
240 | . write " piece -- piece where value is stored in the node that is specified by FullRef",!
|
---|
241 | . write " IENS -- this is provided only for matches in subfiles. ",!
|
---|
242 | . write " It is the IENS that may be used in database calls",!
|
---|
243 | . write " TopGlobalRef -- this is the global reference for file. If the match is in a",!
|
---|
244 | . write " subfile, then this is the global reference of the parent file ",!
|
---|
245 | . write " (or the highest grandparent file if the parent file itself is",!
|
---|
246 | . write " a subfile)",!
|
---|
247 | . zwr Array(*)
|
---|
248 | . write "---------------------------",!
|
---|
249 | . new temp read "Press [ENTER] to continue.",temp:$get(DTIME,3600),!
|
---|
250 | else write !,"No pointers to that record found.",!
|
---|
251 |
|
---|
252 | APTDone
|
---|
253 | quit
|
---|
254 |
|
---|
255 | SCRLPTRIN
|
---|
256 | ;"Purpose: An scrolling interface shell to PtrsIn.
|
---|
257 | ;" Will ask for name of a file, and then a record in that file.
|
---|
258 | ;" Will then show all pointers to that particular record.
|
---|
259 | ;" Will then allow one to trace along pointer path (in or out)
|
---|
260 |
|
---|
261 | new File,IEN,Array,PFn,result
|
---|
262 | new AFile,AIEN,ACount
|
---|
263 | new ShowArray,ShowResults,Header,Count
|
---|
264 | new PickStr,PickInfo,Abort,Menu,UsrSlct
|
---|
265 | new DIC,X,Y
|
---|
266 |
|
---|
267 | write !!,"Pointer Scanner/Browser.",!
|
---|
268 | write "Will look for all pointers (references) to specified record.",!!
|
---|
269 | set DIC="^DIC("
|
---|
270 | set DIC(0)="MAQE"
|
---|
271 | DO ^DIC
|
---|
272 | set File=+Y
|
---|
273 | if File'>0 goto SCPTDone
|
---|
274 | set DIC=File
|
---|
275 | do ^DIC
|
---|
276 | set IEN=+Y
|
---|
277 | if IEN'>0 goto SCPTDone
|
---|
278 | new TMGTIME set TMGTIME=$H
|
---|
279 | set PFn="do ProgressBar^TMGUSRIF(TMGCUR,""File: ""_$P(TMGCODE,""^"",1),1,TMGTOTAL)"
|
---|
280 | SCPT1 ;
|
---|
281 | write !!,"Scanning files for instances of pointers (references) to this record.",!!
|
---|
282 | set result=$$PtrsIn(File,IEN,.Array,PFn)
|
---|
283 | if result=0 do goto APTDone
|
---|
284 | . write !,"There was some problem. Sorry.",!!
|
---|
285 | . do PressToCont^TMGUSRIF
|
---|
286 | ;"Returned format is: ",!
|
---|
287 | ;" Array(File#,IEN,0)=LastCount",!
|
---|
288 | ;" Array(File#,IEN,count)=FullRef;piece;IENS;TopGlobalRef",!
|
---|
289 | ;" Description of parts:",!
|
---|
290 |
|
---|
291 | set File=0,Abort=0
|
---|
292 | for set File=$order(Array(File)) quit:(+File'>0) do
|
---|
293 | . new FName set FName=$piece($get(^DIC(File,0)),"^",1)
|
---|
294 | . new IEN set IEN=0;
|
---|
295 | . for set IEN=$order(Array(File,IEN)) quit:(+IEN'>0) do
|
---|
296 | . . new Value01 set Value01=$$GET1^DIQ(File,IEN,.01)
|
---|
297 | . . set Count=0
|
---|
298 | . . for set Count=$order(Array(File,IEN,Count)) quit:(+Count'>0) do
|
---|
299 | . . . new Str set Str=FName_"; #"_IEN_"; "_Value01
|
---|
300 | . . . if Count>1 set Str=Str_" ("_Count_")"
|
---|
301 | . . . set ShowArray(Str,File_"^"_IEN_"^"_Count)=""
|
---|
302 | . . .
|
---|
303 | set Header="Pick ONE (and only ONE) record to explore. Press ESC ESC when done."
|
---|
304 | SCPT2 kill ShowResults
|
---|
305 | if $get(TMGPTCABORT)=1 goto SCPTDone
|
---|
306 | do Slctor2^TMGUSRIF("ShowArray","ShowResults",Header)
|
---|
307 |
|
---|
308 | set Count=$$ListCt^TMGMISC("ShowResults")
|
---|
309 | if Count>1 do goto SCPT2
|
---|
310 | . write "Please pick ONE (and only ONE) record to explore.",!
|
---|
311 | . write "You selected at least ",Count,!
|
---|
312 | . write "Enter ^ to quit",!
|
---|
313 | . do PressToCont^TMGUSRIF
|
---|
314 |
|
---|
315 | set PickStr=""
|
---|
316 | set PickStr=$order(ShowResults(PickStr))
|
---|
317 | if PickStr="" do goto SCPTDone
|
---|
318 | . write "No selected record. Goodbye.",!
|
---|
319 | . do PressToCont^TMGUSRIF
|
---|
320 |
|
---|
321 | set Count=$$ListCt^TMGMISC("ShowArray("_PickStr_")")
|
---|
322 | if Count>0 do goto SCPTDone
|
---|
323 | . set Abort=1
|
---|
324 | . write "Please pick ONE (and only ONE) record to explore.",!
|
---|
325 | . write "You selected at least ",Count,!
|
---|
326 | . do PressToCont^TMGUSRIF
|
---|
327 |
|
---|
328 | set PickInfo=$order(ShowResults(PickStr,""))
|
---|
329 | set AFile=$piece(PickInfo,"^",1)
|
---|
330 | set AIEN=$piece(PickInfo,"^",2)
|
---|
331 | set ACount=$piece(PickInfo,"^",3)
|
---|
332 |
|
---|
333 | set Menu(0)="Pick Option."
|
---|
334 | set Menu(1)="Show info for this selected record"_$C(9)_"ShowInfo"
|
---|
335 | set Menu(2)="DUMP this record"_$C(9)_"DumpRec"
|
---|
336 | set Menu(3)="Show pointers INTO selected record"_$C(9)_"ShowPtrIN"
|
---|
337 | set Menu(4)="Browse to other records pointed OUT from this record."_$C(9)_"BrowseOUT"
|
---|
338 |
|
---|
339 | MC1 write #
|
---|
340 | set UsrSlct=$$Menu^TMGUSRIF(.Menu,"^")
|
---|
341 | if UsrSlct="^" do goto SCPTDone
|
---|
342 | . write "Goodbye.",!
|
---|
343 | if UsrSlct=0 set UsrSlct=""
|
---|
344 |
|
---|
345 | if UsrSlct="ShowInfo" do goto MC1
|
---|
346 | . if $data(Array(AFile,AIEN,ACount))=0 quit
|
---|
347 | . zwr Array(AFile,AIEN,ACount,*)
|
---|
348 | . do PressToCont^TMGUSRIF
|
---|
349 | if UsrSlct="DumpRec" do goto MC1
|
---|
350 | . do DumpRec2^TMGDEBUG(AFile,AIEN,0)
|
---|
351 | . do PressToCont^TMGUSRIF
|
---|
352 | if UsrSlct="ShowPtrIN" do goto SCPT1
|
---|
353 | . set File=AFile
|
---|
354 | . set IEN=AIEN
|
---|
355 | . set Count=ACount
|
---|
356 | if UsrSlct="BrowseOUT" do goto MC1
|
---|
357 | . do Browse^TMGBROWS(AFile,AIEN,0)
|
---|
358 | . do PressToCont^TMGUSRIF
|
---|
359 | goto MC1
|
---|
360 | SCPTDone
|
---|
361 | quit
|
---|
362 |
|
---|
363 |
|
---|
364 | ASKMVPTR
|
---|
365 | ;"Purpose: An interface shell toRedirect any pointer.
|
---|
366 | ;" Will ask for name of a file, and then a record in that file.
|
---|
367 | ;" Will then pass information to fileman function to move pointers.
|
---|
368 |
|
---|
369 | ;"Note: Example of array passed to P^DITP
|
---|
370 | ;" 23510 is $J
|
---|
371 | ;" 47 is IEN to be deleted in file 50 (stored at ^PSDRUG(*))
|
---|
372 | ;" 1646 is IEN to be substituted for all 47's
|
---|
373 | ;"
|
---|
374 | ;" First part of array is list of all files & fields that point to file
|
---|
375 | ;" ----------------
|
---|
376 | ;" ^UTILITY("DIT",23510,0,1)="727.819^67^P50'"
|
---|
377 | ;" ...
|
---|
378 | ;" ^UTILITY("DIT",23510,0,54)="801.43^.02^RV"
|
---|
379 | ;" ^UTILITY("DIT",23510,0,55)="810.31^.04^V"
|
---|
380 | ;" ^UTILITY("DIT",23510,0,56)="810.32^.01^V"
|
---|
381 | ;" ^UTILITY("DIT",23510,0,57)="811.52^.01^MVX"
|
---|
382 | ;" ^UTILITY("DIT",23510,0,58)="811.902^.01^MVX"
|
---|
383 | ;" ^UTILITY("DIT",23510,0,59)="9009032.4^.05^P50'"
|
---|
384 | ;"
|
---|
385 | ;" Second part of array is list of changes that should be made. Only 1 change shown here.
|
---|
386 | ;" ----------------
|
---|
387 | ;" ^UTILITY("DIT",23510,47)="1646;PSDRUG("
|
---|
388 | ;" ^UTILITY("DIT",23510,"47;PSDRUG(")="1646;PSDRUG("
|
---|
389 |
|
---|
390 | new File,fromIEN,toIEN,Array,PFn,result
|
---|
391 | new PossPtrs
|
---|
392 |
|
---|
393 | write !,"Pointer Redirection Utility",!
|
---|
394 | write "Will change pointers to FROM to TO value",!
|
---|
395 |
|
---|
396 | kill DIC
|
---|
397 | set DIC("A")="Select File holding records being pointed to: "
|
---|
398 | set DIC="^DIC("
|
---|
399 | set DIC(0)="MAQE"
|
---|
400 | d ^DIC ;"Get File to search
|
---|
401 | set File=+Y
|
---|
402 | if File'>0 goto AMPTDone
|
---|
403 |
|
---|
404 | ;"Get list of files/fields with pointers in
|
---|
405 | set result=$$PossPtrs(File,.PossPtrs) if result=0 goto AMPTDone
|
---|
406 | if $data(PossPtrs)'>0 goto AMPTDone
|
---|
407 |
|
---|
408 | set DIC=File
|
---|
409 | set DIC("A")="Select Original (i.e OLD) Record: "
|
---|
410 | do ^DIC ;"get FROM record in File
|
---|
411 | set fromIEN=+Y
|
---|
412 | if fromIEN'>0 goto AMPTDone
|
---|
413 |
|
---|
414 | set DIC("A")="Select New Record: "
|
---|
415 | do ^DIC ;"get FROM record in File
|
---|
416 | set toIEN=+Y
|
---|
417 | if toIEN'>0 goto AMPTDone
|
---|
418 |
|
---|
419 | ;"set PFn="w TMGCODE,"" "",((TMGCUR/TMGTOTAL)*100)\1,""%"",!"
|
---|
420 | ;"new TMGTIME set TMGTIME=$H
|
---|
421 | set PFn="do ProgressBar^TMGUSRIF(TMGCUR,""Scanning File: ""_$P(TMGCODE,""^"",1),1,TMGTOTAL)"
|
---|
422 | write !!,"Starting File Scan for instances of pointers (references) to this record.",!!
|
---|
423 | set result=$$PtrsIn(File,fromIEN,.Array,PFn) if result=0 goto AMPTDone
|
---|
424 |
|
---|
425 | ;" write !,"Here are possible pointers in (file level)",!
|
---|
426 | ;" if $data(PossPtrs) zwr PossPtrs(*)
|
---|
427 |
|
---|
428 | ;" write !,"Here are actual pointers in",!
|
---|
429 | ;" if $data(Array) zwr Array(*)
|
---|
430 |
|
---|
431 | ;"Now convert to FileMan Format.
|
---|
432 | kill ^UTILITY("DIT",$J)
|
---|
433 | do Prep4FM(.Array)
|
---|
434 |
|
---|
435 | if $data(^UTILITY("DIT",$J)) do
|
---|
436 | . merge ^UTILITY("DIT",$J,0)=PossPtrs
|
---|
437 | . ;"write !,"here are results",!
|
---|
438 | . ;" zwr ^UTILITY("DIT",$J,*)
|
---|
439 | . set DIR(0)="Y",DIR("B")="YES"
|
---|
440 | . set DIR("A")="Ask Fileman to redirect pointers?"
|
---|
441 | . set DIR("?")="Enter YES if you want Fileman to change all instances of the FROM record into the TO record."
|
---|
442 | . do ^DIR ;"get user response
|
---|
443 | . if +Y'=1 quit
|
---|
444 | . write "YES",!
|
---|
445 | . do PTS^DITP
|
---|
446 | else do
|
---|
447 | . write "No matches found...",!!
|
---|
448 |
|
---|
449 | AMPTDone
|
---|
450 | quit
|
---|
451 |
|
---|
452 |
|
---|
453 | QTMVPTR(Info,PFn) ;"NOTE: this function hasn't been debugged/tested yet
|
---|
454 | ;"Purpose: An interface to quietly redirect any pointer.
|
---|
455 | ;"Input: Info, an array containing info for redirecting pointers.
|
---|
456 | ;" Format: Note: File can be file name or number.
|
---|
457 | ;" Info(File,OldIEN)=newIEN
|
---|
458 | ;" Info(File,OldIEN)=newIEN1
|
---|
459 | ;" Info(File,OldIEN)=newIEN
|
---|
460 | ;" PFn: OPTIONAL, a progress function (must be a complete M expression)
|
---|
461 | ;"Output: all pointers in linked files to OldIEN will be changed to newIEN
|
---|
462 | ;"Results: none
|
---|
463 |
|
---|
464 | ;"Note: Example of array passed to P^DITP
|
---|
465 | ;" 23510 is $J
|
---|
466 | ;" 47 is IEN to be deleted in file 50 (stored at ^PSDRUG(*))
|
---|
467 | ;" 1646 is IEN to be substituted for all 47's
|
---|
468 | ;"
|
---|
469 | ;" First part of array is list of all files & fields that point to file
|
---|
470 | ;" ----------------
|
---|
471 | ;" ^UTILITY("DIT",23510,0,1)="727.819^67^P50'"
|
---|
472 | ;" ...
|
---|
473 | ;" ^UTILITY("DIT",23510,0,54)="801.43^.02^RV"
|
---|
474 | ;" ^UTILITY("DIT",23510,0,55)="810.31^.04^V"
|
---|
475 | ;" ^UTILITY("DIT",23510,0,56)="810.32^.01^V"
|
---|
476 | ;" ^UTILITY("DIT",23510,0,57)="811.52^.01^MVX"
|
---|
477 | ;" ^UTILITY("DIT",23510,0,58)="811.902^.01^MVX"
|
---|
478 | ;" ^UTILITY("DIT",23510,0,59)="9009032.4^.05^P50'"
|
---|
479 | ;"
|
---|
480 | ;" Second part of array is list of changes that should be made. Only 1 change shown here.
|
---|
481 | ;" ----------------
|
---|
482 | ;" ^UTILITY("DIT",23510,47)="1646;PSDRUG("
|
---|
483 | ;" ^UTILITY("DIT",23510,"47;PSDRUG(")="1646;PSDRUG("
|
---|
484 |
|
---|
485 | new File,Array,result
|
---|
486 | set PFn=$get(PFn)
|
---|
487 | new Itr,File
|
---|
488 |
|
---|
489 | ;"Cycle through all files to be changed.
|
---|
490 | set File=$$ItrAInit^TMGITR("Info",.Itr)
|
---|
491 | if File'="" for do quit:($$ItrANext^TMGITR(.Itr,.File)="")
|
---|
492 | . new PossPtrs
|
---|
493 | . if +File'=File set File=$$GetFileNum^TMGDBAPI(File) ;Convert File Name to File Number
|
---|
494 | . ;"Get list of files/fields with pointers in
|
---|
495 | . set result=$$PossPtrs(File,.PossPtrs) if result=0 quit
|
---|
496 | . if $data(PossPtrs)'>0 quit
|
---|
497 | . kill ^UTILITY("DIT",$J)
|
---|
498 | . new fromIEN,toIEN,fromItr
|
---|
499 | . set fromIEN=+$$ItrAInit^TMGITR($name(Info(File)),.fromItr)
|
---|
500 | . new done2 set done2=0
|
---|
501 | . ;"Cycle through all records to be changed.
|
---|
502 | . if fromIEN'=0 for do quit:(+$$ItrANext^TMGITR(.fromItr,.fromIEN)=0)!(done2=1)
|
---|
503 | . . set toIEN=$get(Info(File,fromIEN))
|
---|
504 | . . set result=$$PtrsIn(File,fromIEN,.Array,PFn) if result=0 set done2=1
|
---|
505 | . . do Prep4FM(.Array)
|
---|
506 | . if $data(^UTILITY("DIT",$J))=0 quit
|
---|
507 | . merge ^UTILITY("DIT",$J,0)=PossPtrs
|
---|
508 | . do PTS^DITP ;"Note: call separately for each file specified.
|
---|
509 |
|
---|
510 | QMPTDone
|
---|
511 | quit
|
---|
512 |
|
---|
513 |
|
---|
514 | QTMMVPTR(Info,ShowProgress) ;"NOTE: this function hasn't been debugged/tested yet
|
---|
515 | ;"Purpose: An interface to quietly redirect multiple pointer.
|
---|
516 | ;"NOTE: This functions differes from QTMVPTR in that it can look for all IEN's
|
---|
517 | ;" for a given file at once, speeding database access.
|
---|
518 | ;"Input: Info, an array containing info for redirecting pointers.
|
---|
519 | ;" Format: Note: File can be file name or number.
|
---|
520 | ;" Info(File,OldIEN)=newIEN
|
---|
521 | ;" Info(File,OldIEN)=newIEN1
|
---|
522 | ;" Info(File,OldIEN)=newIEN
|
---|
523 | ;" ShowProgress: if 1, progress bar shown
|
---|
524 | ;"Output: all pointers in linked files to OldIEN will be changed to newIEN
|
---|
525 | ;"Results: none
|
---|
526 |
|
---|
527 | ;"Note: Example of array passed to P^DITP
|
---|
528 | ;" 23510 is $J
|
---|
529 | ;" 47 is IEN to be deleted in file 50 (stored at ^PSDRUG(*))
|
---|
530 | ;" 1646 is IEN to be substituted for all 47's
|
---|
531 | ;"
|
---|
532 | ;" First part of array is list of all files & fields that point to file
|
---|
533 | ;" ----------------
|
---|
534 | ;" ^UTILITY("DIT",23510,0,1)="727.819^67^P50'"
|
---|
535 | ;" ...
|
---|
536 | ;" ^UTILITY("DIT",23510,0,54)="801.43^.02^RV"
|
---|
537 | ;" ^UTILITY("DIT",23510,0,55)="810.31^.04^V"
|
---|
538 | ;" ^UTILITY("DIT",23510,0,56)="810.32^.01^V"
|
---|
539 | ;" ^UTILITY("DIT",23510,0,57)="811.52^.01^MVX"
|
---|
540 | ;" ^UTILITY("DIT",23510,0,58)="811.902^.01^MVX"
|
---|
541 | ;" ^UTILITY("DIT",23510,0,59)="9009032.4^.05^P50'"
|
---|
542 | ;"
|
---|
543 | ;" Second part of array is list of changes that should be made. Only 1 change shown here.
|
---|
544 | ;" ----------------
|
---|
545 | ;" ^UTILITY("DIT",23510,47)="1646;PSDRUG("
|
---|
546 | ;" ^UTILITY("DIT",23510,"47;PSDRUG(")="1646;PSDRUG("
|
---|
547 |
|
---|
548 | new ToFile,Array,result
|
---|
549 | set PFn=$get(PFn)
|
---|
550 | new Itr
|
---|
551 |
|
---|
552 | ;"Cycle through all files to be changed.
|
---|
553 | set ToFile=$$ItrAInit^TMGITR("Info",.Itr)
|
---|
554 | if ToFile'="" for do quit:($$ItrANext^TMGITR(.Itr,.ToFile)="")
|
---|
555 | . new PossPtrs
|
---|
556 | . if +ToFile'=ToFile set ToFile=$$GetFileNum^TMGDBAPI(ToFile) ;"Convert File Name to File Number
|
---|
557 | . ;"Get list of files/fields with pointers in
|
---|
558 | . set result=$$PossPtrs(ToFile,.PossPtrs) if result=0 quit
|
---|
559 | . if $data(PossPtrs)'>0 quit
|
---|
560 | . kill ^UTILITY("DIT",$J)
|
---|
561 | . ;"new fromIEN,toIEN,fromItr
|
---|
562 | . ;"set fromIEN=+$$ItrAInit^TMGITR($name(Info(ToFile)),.fromItr)
|
---|
563 | . new IENArray set IENArray=ToFile
|
---|
564 | . merge IENArray=Info(ToFile)
|
---|
565 | . set IENArray=ToFile
|
---|
566 | . set result=$$PtrsMIn(.IENArray,.Array,.ShowProgress)
|
---|
567 | . new toFile2,toIEN,fromFile,fromIEN,Array2
|
---|
568 | . set toFile2=""
|
---|
569 | . for set toFile2=$order(Array(toFile2)) quit:(toFile2="") do
|
---|
570 | . . set toIEN=""
|
---|
571 | . . for set toIEN=$order(Array(toFile2,toIEN)) quit:(toIEN="") do
|
---|
572 | . . . set fromFile=""
|
---|
573 | . . . for set fromFile=$order(Array(toFile2,toIEN,fromFile)) quit:(fromFile="") do
|
---|
574 | . . . . set fromIEN=""
|
---|
575 | . . . . for set fromIEN=$order(Array(toFile2,toIEN,fromFile,fromIEN)) quit:(fromIEN="") do
|
---|
576 | . . . . . merge Array2(fromFile,fromIEN)=Array(toFile2,toIEN,fromFile,fromIEN)
|
---|
577 | . set toFile2=""
|
---|
578 | . for set toFile2=$order(Array2(toFile2)) quit:(toFile2="") do
|
---|
579 | . . do MPrep4FM(toFile2,.Array2)
|
---|
580 | . . if $data(^UTILITY("DIT",$J))=0 quit
|
---|
581 | . . merge ^UTILITY("DIT",$J,0)=PossPtrs
|
---|
582 | . . do PTS^DITP ;"Note: call separately for each file specified.
|
---|
583 |
|
---|
584 | QMMPTDone
|
---|
585 | quit
|
---|
586 |
|
---|
587 |
|
---|
588 | Prep4FM(Array)
|
---|
589 | ;"Purpose: to convert Array with redirection info into format for Fileman
|
---|
590 | ;"Input: Array -- PASS BY REFERENCE. An array as created by PtrsIn()
|
---|
591 | ;"Output: Data will be put into ^UTILITY('DIT',$J)
|
---|
592 | ;"Results: none
|
---|
593 |
|
---|
594 | ;"Now convert to FileMan Format.
|
---|
595 | new iFile,iIEN,count,index,toRef
|
---|
596 | set iFile=$order(Array(""))
|
---|
597 | if +iFile'=0 for do quit:(+iFile=0)
|
---|
598 | . set iIEN=$order(Array(iFile,""))
|
---|
599 | . if +iIEN'=0 for do quit:(+iIEN=0)
|
---|
600 | . . set count=+$get(Array(iFile,iIEN,0))
|
---|
601 | . . for index=1:1:count do
|
---|
602 | . . . set toRef=$piece($get(Array(iFile,iIEN,count)),";",4)
|
---|
603 | . . . set toRef=$extract(toRef,2,999)
|
---|
604 | . . . set ^UTILITY("DIT",$J,fromIEN)=toIEN_";"_toRef
|
---|
605 | . . . set ^UTILITY("DIT",$J,""_fromIEN_";"_toRef_"")=""_toIEN_";"_toRef_""
|
---|
606 | . . set iIEN=$order(Array(iFile,iIEN))
|
---|
607 | . set iFile=$order(Array(iFile))
|
---|
608 |
|
---|
609 | quit
|
---|
610 |
|
---|
611 |
|
---|
612 | MPrep4FM(fromFile,Array)
|
---|
613 | ;"Purpose: to convert Array with redirection info into format for Fileman
|
---|
614 | ;"Input: fromFile -- the FromFileNum -- Note: should be called once for
|
---|
615 | ;" each File number
|
---|
616 | ;" Array -- PASS BY REFERENCE. An array as created by PtrsMIn()
|
---|
617 | ;" Array(FromFile#,fromIEN,0)=LastCount
|
---|
618 | ;" Array(FromFile#,fromIEN,count)=FullRef;piece;IENS;TopGlobalRef
|
---|
619 | ;"Output: Data will be put into ^UTILITY('DIT',$J)
|
---|
620 | ;"Results: none
|
---|
621 |
|
---|
622 | ;"Now convert to FileMan Format.
|
---|
623 | new fromIEN set fromIEN=""
|
---|
624 | for set fromIEN=$order(Array(fromFile,fromIEN)) quit:(+fromIEN'>0) do
|
---|
625 | . new count
|
---|
626 | . set count=+$get(Array(fromFile,fromIEN,0))
|
---|
627 | . new index for index=1:1:count do
|
---|
628 | . . new toRef
|
---|
629 | . . set toRef=$piece($get(Array(fromFile,fromIEN,count)),";",4)
|
---|
630 | . . set toRef=$extract(toRef,2,999)
|
---|
631 | . . set ^UTILITY("DIT",$J,fromIEN)=toIEN_";"_toRef
|
---|
632 | . . set ^UTILITY("DIT",$J,""_fromIEN_";"_toRef_"")=""_toIEN_";"_toRef_""
|
---|
633 |
|
---|
634 | quit
|
---|
635 |
|
---|
636 |
|
---|
637 | PtrsIn(File,IEN,Array,PrgsFn)
|
---|
638 | ;"SCOPE: PUBLIC
|
---|
639 | ;"Purpose: Create a list of incoming pointers to a given record in given file
|
---|
640 | ;"Input: File: The file to investigate (Number or Name)
|
---|
641 | ;" IEN: IEN of record to
|
---|
642 | ;" Array -- PASS BY REFERENCE. An array to receive results back.
|
---|
643 | ;" any prexisting data in Array is killed before filling
|
---|
644 | ;" PrgsFn: OPTIONAL -- <Progress Function Code>
|
---|
645 | ;" because this search process can be quite lengthy,
|
---|
646 | ;" an optional line of M code may be given here that will be executed
|
---|
647 | ;" before each file is scanned. The following variables will be defined:
|
---|
648 | ;" TMGCODE -- will hold code of current file being scanned.
|
---|
649 | ;" TMGTOTAL -- will hold total number of records to scan
|
---|
650 | ;" TMGCUR -- will hold count of current record being scanned.
|
---|
651 | ;"Output: Array is filled with format as follows:
|
---|
652 | ;" Array(File#,IEN,0)=LastCount
|
---|
653 | ;" Array(File#,IEN,count)=FullRef;piece;IENS;TopGlobalRef
|
---|
654 | ;" Description of parts:
|
---|
655 | ;" ----------------------
|
---|
656 | ;" File# -- the file the found entry exists it (may be a subfile number)
|
---|
657 | ;" IEN -- the record number in file
|
---|
658 | ;" Note: IEN here is different from the IEN passed in as a parameter
|
---|
659 | ;" FullRef -- the is the full reference to the found value. e.g.
|
---|
660 | ;" set value=$piece(@FullRef,"^",piece)
|
---|
661 | ;" piece -- the piece where value is stored in the node that is specified by FullRef
|
---|
662 | ;" IENS -- this is provided only for matches in subfiles. It is the IENS that may be used in database calls
|
---|
663 | ;" TopGlobalRef -- this is the global reference for file. If the match is in a subfile, then
|
---|
664 | ;" this is the global reference of the parent file (or the highest grandparent file if
|
---|
665 | ;" the parent file itself is a subfile, etc.)
|
---|
666 | ;"
|
---|
667 | ;"Result: 1 if results found, 0 if error occurred.
|
---|
668 | ;"NOTE: This function manually scans through potentially HUGE numbers of records-->BE PATIENT!
|
---|
669 |
|
---|
670 | kill Array
|
---|
671 | new result set result=0
|
---|
672 | new FileNum
|
---|
673 | set IEN=+$get(IEN)
|
---|
674 | if IEN=0 goto FPIDone ;"NOTE: IEN doesn't have to point to a valid record.
|
---|
675 | if $data(File)#10=0 goto FPIDone
|
---|
676 | if +File=0 set FileNum=$$GetFileNum^TMGDBAPI(File) ;"Convert File Name to File Number
|
---|
677 | else set FileNum=File
|
---|
678 | if +FileNum=0 goto FPIDone
|
---|
679 |
|
---|
680 | new PossArray,TMGCODE
|
---|
681 | if $$PossPtrs(File,.PossArray)=0 goto FPIDone
|
---|
682 |
|
---|
683 | ;"Count number of records to scan
|
---|
684 | new TMGCUR set TMGCUR=0
|
---|
685 | new TMGTOTAL set TMGTOTAL=0
|
---|
686 | do
|
---|
687 | . new temp set temp=$order(PossArray(""))
|
---|
688 | . if temp'="" for do quit:(temp="")
|
---|
689 | . . new code set code=PossArray(temp)
|
---|
690 | . . new ref set ref=$get(^DIC(+code,0,"GL"))
|
---|
691 | . . set ref=$$CREF^DILF(ref) ;"convert open to closed format
|
---|
692 | . . new NumRecs
|
---|
693 | . . if ref'="" set NumRecs=+$piece(@ref@(0),"^",4)
|
---|
694 | . . else set NumRecs=10000 ;"some arbitrary guess of #recs in a subfile
|
---|
695 | . . set TMGTOTAL=TMGTOTAL+1
|
---|
696 | . . set TMGTOTAL(TMGTOTAL)=NumRecs
|
---|
697 | . . set temp=$order(PossArray(temp))
|
---|
698 | . set temp=$order(TMGTOTAL(""))
|
---|
699 | . set TMGTOTAL=1
|
---|
700 | . if temp'="" for do quit:(temp="")
|
---|
701 | . . set TMGTOTAL=TMGTOTAL+TMGTOTAL(temp)
|
---|
702 | . . set temp=$order(TMGTOTAL(temp))
|
---|
703 | . if TMGTOTAL=0 set TMGTOTAL=1 ;"avoid div by zero issues.
|
---|
704 |
|
---|
705 | new count set count=1
|
---|
706 | new index set index=$order(PossArray(""))
|
---|
707 | if index'="" for do quit:(index="")
|
---|
708 | . set TMGCUR=TMGCUR+TMGTOTAL(count)
|
---|
709 | . set count=count+1
|
---|
710 | . set TMGCODE=PossArray(index)
|
---|
711 | . if $get(PrgsFn)'="" do
|
---|
712 | . . new $etrap set $etrap="write ""(Invalid M Code!. Error Trapped.)"" set $etrap="""",$ecode="""""
|
---|
713 | . . xecute PrgsFn
|
---|
714 | . do ScanFile(TMGCODE,IEN,.Array)
|
---|
715 | . set index=$order(PossArray(index))
|
---|
716 |
|
---|
717 | set result=1
|
---|
718 | FPIDone
|
---|
719 | quit result
|
---|
720 |
|
---|
721 |
|
---|
722 | PtrsMIn(IENArray,Array,ShowProgress)
|
---|
723 | ;"SCOPE: PUBLIC
|
---|
724 | ;"Purpose: Create a list of incoming pointers to an array of records in given file
|
---|
725 | ;"NOTE: this function differes from PtrsIn because is allows multiple input IEN's
|
---|
726 | ;"Input: IENArray: PASS BY REFERENCE. Array of IENs of record in ToFile. Format:
|
---|
727 | ;" IENArray=SourceFile#
|
---|
728 | ;" IENArray(IEN)=""
|
---|
729 | ;" IENArray(IEN)=""
|
---|
730 | ;" Array -- PASS BY REFERENCE. An array to receive results back. Format below.
|
---|
731 | ;" any prexisting data in Array is killed before filling
|
---|
732 | ;" ShowProgress: if 1, progress bar shown
|
---|
733 | ;"Output: Array is filled with format as follows:
|
---|
734 | ;" Array(ToFile#,ToIEN,FromFile#,fromIEN,0)=LastCount
|
---|
735 | ;" Array(ToFile#,ToIEN,FromFile#,fromIEN,count)=FullRef;piece;IENS;TopGlobalRef
|
---|
736 | ;" Description of parts:
|
---|
737 | ;" ----------------------
|
---|
738 | ;" ToFile# -- the file containing the target IEN record
|
---|
739 | ;" ToIEN --the IEN in ToFile
|
---|
740 | ;" FromFile# -- the file the found entry exists it (may be a subfile number)
|
---|
741 | ;" fromIEN -- the record number in file
|
---|
742 | ;" Note: IEN here is different from the IEN passed in as a parameter
|
---|
743 | ;" FullRef -- the is the full reference to the found value. e.g.
|
---|
744 | ;" set value=$piece(@FullRef,"^",piece)
|
---|
745 | ;" piece -- the piece where value is stored in the node that is specified by FullRef
|
---|
746 | ;" IENS -- this is provided only for matches in subfiles. It is the IENS that may be used in database calls
|
---|
747 | ;" TopGlobalRef -- this is the global reference for file. If the match is in a subfile, then
|
---|
748 | ;" this is the global reference of the parent file (or the highest grandparent file if
|
---|
749 | ;" the parent file itself is a subfile, etc.)
|
---|
750 | ;"
|
---|
751 | ;"Result: 1 if results found, 0 if error occurred.
|
---|
752 | ;"NOTE: This function manually scans through potentially HUGE numbers of records-->BE PATIENT!
|
---|
753 |
|
---|
754 | kill Array
|
---|
755 | new result set result=0
|
---|
756 | new FileNum
|
---|
757 | set ToFile=$get(IENArray) if ToFile="" goto FMPIDone
|
---|
758 | if +ToFile=0 set FileNum=$$GetFileNum^TMGDBAPI(File) ;"Convert File Name to File Number
|
---|
759 | else set FileNum=ToFile
|
---|
760 | if +FileNum=0 goto FMPIDone
|
---|
761 |
|
---|
762 | new PossArray
|
---|
763 | if $$PossPtrs(FileNum,.PossArray)=0 goto FMPIDone
|
---|
764 |
|
---|
765 | new FInfoArray
|
---|
766 | new index set index=""
|
---|
767 | for set index=$order(PossArray(index)) quit:(index="") do
|
---|
768 | . new tempS set tempS=$get(PossArray(index))
|
---|
769 | . new fromFile set fromFile=$piece(tempS,"^",1)
|
---|
770 | . new fromField set fromField=$piece(tempS,"^",2)
|
---|
771 | . new fldCode set fldCode=$piece(tempS,"^",3)
|
---|
772 | . set FInfoArray(fromFile,fromField)=fldCode
|
---|
773 |
|
---|
774 | do ScanMFile(.FInfoArray,.IENArray,.Array,.ShowProgress)
|
---|
775 |
|
---|
776 | set result=1
|
---|
777 | FMPIDone
|
---|
778 | quit result
|
---|
779 |
|
---|
780 |
|
---|
781 | ScanFile(FInfo,IEN,Array)
|
---|
782 | ;"SCOPE: PUBLIC
|
---|
783 | ;"Purpose: To scan one file (from array setup by PossPtrs) for actual pointers to IEN
|
---|
784 | ;"Input: FInfo : OtherFile#^Field#^FieldCode(piece#2 of 0 node of ^DD entry for field)
|
---|
785 | ;"Examples of possible inputs follow:
|
---|
786 | ;"50^62.05^*P50'"
|
---|
787 | ;"695^.01^RP50'"
|
---|
788 | ;"801.43^.02^RV"
|
---|
789 | ;"810.31^.04^V"
|
---|
790 | ;"811.902^.01^MVX"
|
---|
791 |
|
---|
792 | ;"NOTE: Idea for future enhancement: Allow FInfo to hold a list rather than just one value.
|
---|
793 | ;" This would be for instances where multiple fields in given record need to be searched
|
---|
794 | ;" This might speed up database access times.
|
---|
795 |
|
---|
796 | ;" IEN : the IEN that pointers should point to, to be considered a match.
|
---|
797 | ;" Array : PASS BY REFERENCE. An array to receive results.
|
---|
798 | ;"Output: Format of Array output:
|
---|
799 | ;" Array(File#,IEN,0)=LastCount
|
---|
800 | ;" Array(File#,IEN,count)=FullRef;piece;IENS;TopGlobalRef
|
---|
801 | ;" Description of parts:
|
---|
802 | ;" ----------------------
|
---|
803 | ;" File# -- the file the found entry exists it (may be a subfile number)
|
---|
804 | ;" IEN -- the record number in file
|
---|
805 | ;" Note: IEN here is different from the IEN passed in as a parameter
|
---|
806 | ;" FullRef -- the is the full reference to the found value. e.g.
|
---|
807 | ;" set value=$piece(@FullRef,"^",piece)
|
---|
808 | ;" piece -- the piece where value is stored in the node that is specified by FullRef
|
---|
809 | ;" IENS -- this is provided only for matches in subfiles. It is the IENS that may be used in database calls
|
---|
810 | ;" TopGlobalRef -- this is the global reference for file. If the match is in a subfile, then
|
---|
811 | ;" this is the global reference of the parent file (or the highest grandparent file if
|
---|
812 | ;" the parent file itself is a subfile, etc.)
|
---|
813 | ;"
|
---|
814 | ;"result : none
|
---|
815 |
|
---|
816 | new File set File=$piece(FInfo,"^",1) if File="" goto SFDone
|
---|
817 | new Field set Field=$piece(FInfo,"^",2) if Field="" goto SFDone
|
---|
818 | new Code set Code=$piece(FInfo,"^",3) if Code="" goto SFDone
|
---|
819 | new count
|
---|
820 | if '((Code["P")!(Code["V")) goto SFDone
|
---|
821 | new GRef
|
---|
822 | new znode set znode=$get(^DD(File,Field,0))
|
---|
823 | new loc set loc=$piece(znode,"^",4)
|
---|
824 | new node set node=$piece(loc,";",1)
|
---|
825 | new pce set pce=$piece(loc,";",2)
|
---|
826 | if +$$IsSubFile^TMGDBAPI(File) do
|
---|
827 | . new FileArray,i,k,FNum,SubInfo
|
---|
828 | . set i=0
|
---|
829 | . set FileArray(0)=0
|
---|
830 | . set FileArray(i,"PARENT","LOC")=loc
|
---|
831 | . set FNum=File
|
---|
832 | . for do quit:(+FNum=0) ;"setup array describing subfile's inheritence
|
---|
833 | . . set i=i+1
|
---|
834 | . . set FileArray(i)=FNum
|
---|
835 | . . if i=1 set FileArray(0,"FILE")=FNum
|
---|
836 | . . if $$GetSubFInfo^TMGDBAPI(FNum,.SubInfo) do
|
---|
837 | . . . set FileArray(i,"PARENT","LOC")=SubInfo("FIELD IN PARENT","LOC")
|
---|
838 | . . . set GRef=$get(SubInfo("PARENT","GL")) ;"<-- only valid for highest ancestor
|
---|
839 | . . else do
|
---|
840 | . . . set (FileArray(0,"TOP GL"),FileArray(i,"PARENT","GL"))=$get(^DIC(FNum,0,"GL"))
|
---|
841 | . . set FNum=$$IsSubFile^TMGDBAPI(FNum)
|
---|
842 | . do HandleSubFile(IEN,.FileArray,.Array)
|
---|
843 | else do
|
---|
844 | . set GRef=$get(^DIC(File,0,"GL"))
|
---|
845 | . new ORef set ORef=GRef
|
---|
846 | . set GRef=$$CREF^DILF(GRef) ;"convert open to closed format
|
---|
847 | . new index set index=$order(@GRef@(0))
|
---|
848 | . if index'="" for do quit:(index="")
|
---|
849 | . . new value set value=$get(@GRef@(index,node))
|
---|
850 | . . if $piece(value,"^",pce)=IEN do
|
---|
851 | . . . set Array(File,index,0)=1
|
---|
852 | . . . set Array(File,index,1)=$name(@GRef@(index,node))_";"_pce_";"_""_";"_ORef
|
---|
853 | . . set index=$order(@GRef@(index))
|
---|
854 |
|
---|
855 | SFDone
|
---|
856 | quit
|
---|
857 |
|
---|
858 |
|
---|
859 | ScanMFile(FInfoArray,IENArray,Array,ShowProgress)
|
---|
860 | ;"SCOPE: PUBLIC
|
---|
861 | ;"Purpose: To scan multiple file (from array setup by PossPtrs) for actual pointers to IENs
|
---|
862 | ;"Input: FInfoArray : PASS BY REFERENCE. Format:
|
---|
863 | ;" FInfoArray(OtherFile,Field)=FieldCode(piece#2 of 0 node of ^DD entry for field)
|
---|
864 | ;" Examples of possible inputs follow:
|
---|
865 | ;" FInfoArray(50,62.05)="*P50'"
|
---|
866 | ;" FInfoArray(695,.01)="RP50'"
|
---|
867 | ;" FInfoArray(801.43,.02)="RV"
|
---|
868 | ;" FInfoArray(810.31,.04)="V"
|
---|
869 | ;" FInfoArray(811.902,.01)="MVX"
|
---|
870 | ;" IENArray : PASS BY REFERENCE. IEN's that pointers should point TO, to be considered a match.
|
---|
871 | ;" Format: IENArray=SourceFile
|
---|
872 | ;" IENArray(IEN)=""
|
---|
873 | ;" IENArray(IEN)=""
|
---|
874 | ;" Array : PASS BY REFERENCE. AN OUT PARAMETER. Format:
|
---|
875 | ;" Array(ToFile#,ToIEN,fromFile#,fromIEN,0)=LastCount
|
---|
876 | ;" Array(ToFile#,ToIEN,fromFile#,fromIEN,count)=FullRef;piece;IENS;TopGlobalRef
|
---|
877 | ;" Description of parts:
|
---|
878 | ;" ----------------------
|
---|
879 | ;" ToFile# -- the file containing the target IEN record
|
---|
880 | ;" ToIEN --the IEN in ToFile
|
---|
881 | ;" fromFile# -- the file the found entry exists it (may be a subfile number)
|
---|
882 | ;" fromIEN -- the record number in file
|
---|
883 | ;" Note: IEN here is different from the IEN passed in as a parameter
|
---|
884 | ;" FullRef -- the is the full reference to the found value. e.g.
|
---|
885 | ;" set value=$piece(@FullRef,"^",piece)
|
---|
886 | ;" piece -- the piece where value is stored in the node that is specified by FullRef
|
---|
887 | ;" IENS -- this is provided only for matches in subfiles. It is the IENS that may be used in database calls
|
---|
888 | ;" TopGlobalRef -- this is the global reference for file. If the match is in a subfile, then
|
---|
889 | ;" this is the global reference of the parent file (or the highest grandparent file if
|
---|
890 | ;" the parent file itself is a subfile, etc.)
|
---|
891 | ;" ShowProgress: if 1, progress bar shown
|
---|
892 | ;"
|
---|
893 | ;"result : none
|
---|
894 |
|
---|
895 | new ToFile set ToFile=+$get(IENArray)
|
---|
896 | set ShowProgress=$get(ShowProgress,0)
|
---|
897 | new abort set abort=0
|
---|
898 | set fromFile=""
|
---|
899 | for set fromFile=$order(FInfoArray(fromFile)) quit:(fromFile="")!abort do
|
---|
900 | . if $$UserAborted^TMGUSRIF set abort=1 quit
|
---|
901 | . write !,"Processing File#: ",fromFile,!
|
---|
902 | . new Field set Field=""
|
---|
903 | . for set Field=$order(FInfoArray(fromFile,Field)) quit:(Field="") do
|
---|
904 | . . write " Field#: ",Field,!
|
---|
905 | . . new Code set Code=$get(FInfoArray(fromFile,Field)) if Code="" quit
|
---|
906 | . . new count
|
---|
907 | . . if '((Code["P")!(Code["V")) goto SFDone
|
---|
908 | . . new GRef
|
---|
909 | . . new znode set znode=$get(^DD(fromFile,Field,0))
|
---|
910 | . . new loc set loc=$piece(znode,"^",4)
|
---|
911 | . . new node set node=$piece(loc,";",1)
|
---|
912 | . . new pce set pce=$piece(loc,";",2)
|
---|
913 | . . if +$$IsSubFile^TMGDBAPI(fromFile) do
|
---|
914 | . . . new FileArray,i,k,FNum,SubInfo
|
---|
915 | . . . set i=0
|
---|
916 | . . . set FileArray(0)=0
|
---|
917 | . . . set FileArray(i,"PARENT","LOC")=loc
|
---|
918 | . . . set FNum=fromFile
|
---|
919 | . . . for do quit:(+FNum=0) ;"setup array describing subfile's inheritence
|
---|
920 | . . . . set i=i+1
|
---|
921 | . . . . set FileArray(i)=FNum
|
---|
922 | . . . . if i=1 set FileArray(0,"FILE")=FNum
|
---|
923 | . . . . if $$GetSubFInfo^TMGDBAPI(FNum,.SubInfo) do
|
---|
924 | . . . . . set FileArray(i,"PARENT","LOC")=SubInfo("FIELD IN PARENT","LOC")
|
---|
925 | . . . . . set GRef=$get(SubInfo("PARENT","GL")) ;"<-- only valid for highest ancestor
|
---|
926 | . . . . else do
|
---|
927 | . . . . . set (FileArray(0,"TOP GL"),FileArray(i,"PARENT","GL"))=$get(^DIC(FNum,0,"GL"))
|
---|
928 | . . . . set FNum=$$IsSubFile^TMGDBAPI(FNum)
|
---|
929 | . . . do HandleMSubFile(.IENArray,.FileArray,.Array)
|
---|
930 | . . else do
|
---|
931 | . . . set GRef=$get(^DIC(fromFile,0,"GL"))
|
---|
932 | . . . new ORef set ORef=GRef
|
---|
933 | . . . set GRef=$$CREF^DILF(GRef) ;"convert open to closed format
|
---|
934 | . . . new Itr,fromIEN
|
---|
935 | . . . set fromIEN=$$ItrAInit^TMGITR(GRef,.Itr)
|
---|
936 | . . . if ShowProgress=1 do PrepProgress^TMGITR(.Itr,20,1,"fromIEN")
|
---|
937 | . . . if fromIEN'="" for do quit:($$ItrANext^TMGITR(.Itr,.fromIEN)="")!abort
|
---|
938 | . . . . if $$UserAborted^TMGUSRIF set abort=1 quit
|
---|
939 | . . . . ;"for set fromIEN=$order(@GRef@(fromIEN)) quit:(fromIEN="") do
|
---|
940 | . . . . new valueS set valueS=$get(@GRef@(fromIEN,node))
|
---|
941 | . . . . new ToIEN set ToIEN=$piece(valueS,"^",pce)
|
---|
942 | . . . . if $data(IENArray(ToIEN))>0 do
|
---|
943 | . . . . . new lastCount set lastCount=+$get(Array(ToFile,ToIEN,fromFile,fromIEN,0))+1
|
---|
944 | . . . . . set Array(ToFile,ToIEN,fromFile,fromIEN,0)=lastCount
|
---|
945 | . . . . . set Array(ToFile,ToIEN,fromFile,fromIEN,lastCount)=$name(@GRef@(fromIEN,node))_";"_pce_";"_""_";"_ORef
|
---|
946 |
|
---|
947 | SMFDone
|
---|
948 | quit
|
---|
949 |
|
---|
950 |
|
---|
951 | HandleSubFile(SearchValue,FileArray,Array,IENS,Ref)
|
---|
952 | ;"Purpose: To provide a means of recursively handling subfiles, searching for SearchValue.
|
---|
953 | ;"Input: SearchValue -- the value to be searched for, in INTERNAL format.
|
---|
954 | ;" File Array -- PASS BY REFERENCE An array that describes the parent file numbers
|
---|
955 | ;" and storage locations. Example:
|
---|
956 | ;" FileArra(0,"TOP GL")="^XTV(8989.3,"
|
---|
957 | ;" FileArra(0,"FILE")=8989.33211
|
---|
958 | ;" FileArra(0)=0
|
---|
959 | ;" FileArra(0,"PARENT","LOC")="0;1" <-- for FileArray(0) node, stores node;piece
|
---|
960 | ;" FileArra(1)=8989.33211
|
---|
961 | ;" FileArra(1,"PARENT","LOC")="1;0" <--- 1 is storage node
|
---|
962 | ;" FileArra(2)=8989.3321
|
---|
963 | ;" FileArra(2,"PARENT","LOC")="1;0" <--- 1 is storage node
|
---|
964 | ;" FileArra(3)=8989.332
|
---|
965 | ;" FileArra(3,"PARENT","LOC")="ABPKG;0" <--- "ABPKG" is storage node
|
---|
966 | ;" FileArra(4)=8989.3
|
---|
967 | ;" FileArra(4,"PARENT","GL")="^XTV(8989.3,"
|
---|
968 | ;" Array -- PASS BY REFERENCE. An array the receives any search matches.
|
---|
969 | ;" Format is as follows
|
---|
970 | ;" Array(File#,IEN,0)=LastCount
|
---|
971 | ;" Array(File#,IEN,count)=FullRef;piece;IENS;TopGlobalRef
|
---|
972 | ;"
|
---|
973 | ;" IENS -- OPTIONAL -- used by this function internally during recursive calls
|
---|
974 | ;" Ref -- OPTIONAL -- used by this function internally during recursive calls
|
---|
975 |
|
---|
976 | new index,s,IEN,CRef,pce,node
|
---|
977 | set index=$order(FileArray(""),-1)
|
---|
978 | set s=$get(FileArray(index,"PARENT","LOC"))
|
---|
979 | set node=$piece(s,";",1)
|
---|
980 | set pce=+$piece(s,";",2)
|
---|
981 | if s'="" do
|
---|
982 | . if +node'=node set node=""""_node_""""
|
---|
983 | . set s=node_","
|
---|
984 | else do
|
---|
985 | . set s=$get(FileArray(index,"PARENT","GL"))
|
---|
986 | . set node=""
|
---|
987 | set Ref=$get(Ref)_s
|
---|
988 | if Ref="" goto HSFDone
|
---|
989 | set CRef=$$CREF^DILF(Ref)
|
---|
990 | new subFArray
|
---|
991 | merge subFArray=FileArray
|
---|
992 | kill subFArray(index) ;"trim top entry from list/array
|
---|
993 | if index>0 do
|
---|
994 | . set IEN=$order(@CRef@(0))
|
---|
995 | . if +IEN>0 for do quit:(+IEN=0)
|
---|
996 | . . new subRef,subIENS
|
---|
997 | . . set subRef=Ref_IEN_","
|
---|
998 | . . set subIENS=IEN_","_$get(IENS)
|
---|
999 | . . do HandleSubFile(SearchValue,.subFArray,.Array,.subIENS,subRef)
|
---|
1000 | . . set IEN=$order(@CRef@(IEN))
|
---|
1001 | else do
|
---|
1002 | . if (pce>0) do ;"Here is were the actual comparison to SearchValue occurs
|
---|
1003 | . . set subRef=$$CREF^DILF(subRef)
|
---|
1004 | . . new p,t set (p,t)=0
|
---|
1005 | . . for set t=$find(subRef,",",t) set:(t>0) p=t quit:(t=0) ;"find pos of last parameter
|
---|
1006 | . . ;"new ORef set ORef=$extract(subRef,1,p-1)
|
---|
1007 | . . set IEN=$piece($extract(subRef,p,99),")",1)
|
---|
1008 | . . new value set value=$get(@subRef@(node))
|
---|
1009 | . . set value=$piece(value,"^",pce)
|
---|
1010 | . . set value=$piece(value,";",1) ;"I think VARIABLE pointers format is: IEN;file#
|
---|
1011 | . . if value=SearchValue do
|
---|
1012 | . . . new tFile set tFile=$get(FileArray(0,"FILE"),"?")
|
---|
1013 | . . . new count set count=$get(Array(tFile,IEN,0))+1
|
---|
1014 | . . . set Array(tFile,IEN,0)=count
|
---|
1015 | . . . set Array(tFile,IEN,count)=$name(@subRef@(node))_";"_pce_";"_""_$get(IENS)_""_";"_$get(FileArray(0,"TOP GL"))
|
---|
1016 |
|
---|
1017 | HSFDone
|
---|
1018 | quit
|
---|
1019 |
|
---|
1020 |
|
---|
1021 | HandleMSubFile(IENArray,FileArray,Array,IENS,Ref)
|
---|
1022 | ;"Purpose: To provide a means of recursively handling subfiles, searching for SearchValue.
|
---|
1023 | ;"Input: IENArray : PASS BY REFERENCE. IEN's to search for in INTERNAL format.
|
---|
1024 | ;" Format: IENArray=SourceFile
|
---|
1025 | ;" IENArray(IEN)=""
|
---|
1026 | ;" IENArray(IEN)=""
|
---|
1027 | ;" File Array -- PASS BY REFERENCE An array that describes the parent file numbers
|
---|
1028 | ;" and storage locations. Example:
|
---|
1029 | ;" FileArray(0,"TOP GL")="^XTV(8989.3,"
|
---|
1030 | ;" FileArray(0,"FILE")=8989.33211
|
---|
1031 | ;" FileArray(0)=0
|
---|
1032 | ;" FileArray(0,"PARENT","LOC")="0;1" <-- for FileArray(0) node, stores node;piece
|
---|
1033 | ;" FileArray(1)=8989.33211
|
---|
1034 | ;" FileArray(1,"PARENT","LOC")="1;0" <--- 1 is storage node
|
---|
1035 | ;" FileArray(2)=8989.3321
|
---|
1036 | ;" FileArray(2,"PARENT","LOC")="1;0" <--- 1 is storage node
|
---|
1037 | ;" FileArray(3)=8989.332
|
---|
1038 | ;" FileArray(3,"PARENT","LOC")="ABPKG;0" <--- "ABPKG" is storage node
|
---|
1039 | ;" FileArray(4)=8989.3
|
---|
1040 | ;" FileArray(4,"PARENT","GL")="^XTV(8989.3,"
|
---|
1041 | ;" Array : PASS BY REFERENCE. AN OUT PARAMETER. Format:
|
---|
1042 | ;" Array(ToFile#,ToIEN,fromFile#,fromIEN,0)=LastCount
|
---|
1043 | ;" Array(ToFile#,ToIEN,fromFile#,fromIEN,count)=FullRef;piece;IENS;TopGlobalRef
|
---|
1044 | ;" Description of parts:
|
---|
1045 | ;" ----------------------
|
---|
1046 | ;" ToFile# -- the file containing the target IEN record
|
---|
1047 | ;" ToIEN --the IEN in ToFile
|
---|
1048 | ;" fromFile# -- the file the found entry exists it (may be a subfile number)
|
---|
1049 | ;" fromIEN -- the record number in file
|
---|
1050 | ;" Note: IEN here is different from the IEN passed in as a parameter
|
---|
1051 | ;" FullRef -- the is the full reference to the found value. e.g.
|
---|
1052 | ;" set value=$piece(@FullRef,"^",piece)
|
---|
1053 | ;" piece -- the piece where value is stored in the node that is specified by FullRef
|
---|
1054 | ;" IENS -- this is provided only for matches in subfiles. It is the IENS that may be used in database calls
|
---|
1055 | ;" TopGlobalRef -- this is the global reference for file. If the match is in a subfile, then
|
---|
1056 | ;" this is the global reference of the parent file (or the highest grandparent file if
|
---|
1057 | ;" the parent file itself is a subfile, etc.)
|
---|
1058 | ;"
|
---|
1059 | ;" IENS -- OPTIONAL -- used by this function internally during recursive calls
|
---|
1060 | ;" Ref -- OPTIONAL -- used by this function internally during recursive calls
|
---|
1061 |
|
---|
1062 | new ToFile set ToFile=$get(IENArray)
|
---|
1063 | new index,s,IEN,CRef,pce,node
|
---|
1064 | set index=$order(FileArray(""),-1)
|
---|
1065 | set s=$get(FileArray(index,"PARENT","LOC"))
|
---|
1066 | set node=$piece(s,";",1)
|
---|
1067 | set pce=+$piece(s,";",2)
|
---|
1068 | if s'="" do
|
---|
1069 | . if +node'=node set node=""""_node_""""
|
---|
1070 | . set s=node_","
|
---|
1071 | else do
|
---|
1072 | . set s=$get(FileArray(index,"PARENT","GL"))
|
---|
1073 | . set node=""
|
---|
1074 | set Ref=$get(Ref)_s
|
---|
1075 | if Ref="" goto HSFDone
|
---|
1076 | set CRef=$$CREF^DILF(Ref)
|
---|
1077 | new subFArray
|
---|
1078 | merge subFArray=FileArray
|
---|
1079 | kill subFArray(index) ;"trim top entry from list/array
|
---|
1080 | if index>0 do
|
---|
1081 | . set fromIEN=0
|
---|
1082 | . for set fromIEN=$order(@CRef@(fromIEN)) quit:(+fromIEN=0) do
|
---|
1083 | . . new subRef,subIENS
|
---|
1084 | . . set subRef=Ref_fromIEN_","
|
---|
1085 | . . set subIENS=fromIEN_","_$get(IENS)
|
---|
1086 | . . do HandleMSubFile(.IENArray,.subFArray,.Array,.subIENS,subRef)
|
---|
1087 | else do
|
---|
1088 | . if (pce>0) do ;"Here is were the actual comparison to SearchValue occurs
|
---|
1089 | . . set subRef=$$CREF^DILF(subRef)
|
---|
1090 | . . new p,t set (p,t)=0
|
---|
1091 | . . for set t=$find(subRef,",",t) set:(t>0) p=t quit:(t=0) ;"find pos of last parameter
|
---|
1092 | . . ;"new ORef set ORef=$extract(subRef,1,p-1)
|
---|
1093 | . . set fromIEN=$piece($extract(subRef,p,99),")",1)
|
---|
1094 | . . new valueS set valueS=$get(@subRef@(node))
|
---|
1095 | . . set valueS=$piece(valueS,"^",pce)
|
---|
1096 | . . new ToIEN set ToIEN=$piece(valueS,";",1) ;"I think VARIABLE pointers format is: IEN;file#
|
---|
1097 | . . if $data(IENArray(ToIEN))>0 do
|
---|
1098 | . . . new fromFile set fromFile=$get(FileArray(0,"FILE"),"?")
|
---|
1099 | . . . new count set count=$get(Array(ToFile,ToIEN,fromFile,fromIEN,0))+1
|
---|
1100 | . . . set Array(ToFile,ToIEN,fromFile,fromIEN,0)=count
|
---|
1101 | . . . set Array(ToFile,ToIEN,fromFile,fromIEN,count)=$name(@subRef@(node))_";"_pce_";"_""_$get(IENS)_""_";"_$get(FileArray(0,"TOP GL"))
|
---|
1102 |
|
---|
1103 | HMSFDone
|
---|
1104 | quit
|
---|
1105 |
|
---|
1106 |
|
---|
1107 | PossPtrs(File,Array)
|
---|
1108 | ;"SCOPE: PUBLIC
|
---|
1109 | ;"Purpose: to create a list of all possible pointers to a specified file, i.e. all other fields/fields
|
---|
1110 | ;" that point to the specified file.
|
---|
1111 | ;"Input: File: The file to investigate (Number or Name)
|
---|
1112 | ;" Array -- PASS BY REFERENCE. An array to receive results back.
|
---|
1113 | ;" any prexisting data in Array is killed before filling
|
---|
1114 | ;"Output: Array is filled with format as follows:
|
---|
1115 | ;" Array(1)=OtherFile#^Field#^FieldCode(piece#2 of 0 node of ^DD entry for field)
|
---|
1116 | ;" Array(2)=OtherFile#^Field#^FieldCode
|
---|
1117 | ;"Result: 1 if results found, 0 if error occurred.
|
---|
1118 |
|
---|
1119 | kill Array
|
---|
1120 | new result set result=0
|
---|
1121 | new FileNum
|
---|
1122 | if $data(File)#10=0 goto PPtrsDone
|
---|
1123 | if +File=0 set FileNum=$$GetFileNum^TMGDBAPI(File) ;"Convert File Name to File Number
|
---|
1124 | else set FileNum=File
|
---|
1125 | if +FileNum=0 goto PPtrsDone
|
---|
1126 |
|
---|
1127 | new count set count=1
|
---|
1128 | new PtrFile set PtrFile=$order(^DD(FileNum,0,"PT",""))
|
---|
1129 | if PtrFile'="" for do quit:(PtrFile="")
|
---|
1130 | . new PtrField set PtrField=$order(^DD(FileNum,0,"PT",PtrFile,""))
|
---|
1131 | . if PtrField'="" for do quit:(PtrField="")
|
---|
1132 | . . new s set s=PtrFile_"^"_PtrField
|
---|
1133 | . . set s=s_"^"_$piece($get(^DD(PtrFile,PtrField,0)),"^",2)
|
---|
1134 | . . set Array(count)=s
|
---|
1135 | . . set count=count+1
|
---|
1136 | . . set PtrField=$order(^DD(FileNum,0,"PT",PtrFile,PtrField))
|
---|
1137 | . set PtrFile=$order(^DD(FileNum,0,"PT",PtrFile))
|
---|
1138 |
|
---|
1139 | set result=1
|
---|
1140 | PPtrsDone
|
---|
1141 | quit result
|
---|
1142 |
|
---|
1143 |
|
---|
1144 | ;"Note: Not fully debugged yet..."
|
---|
1145 | SAFEKILL(Array,ShowProgress)
|
---|
1146 | ;"Purpose: to safely kill records, including removing any pointers TO them
|
---|
1147 | ;"input: pArray -- PASS BY REFERENCE. Expected input Format:
|
---|
1148 | ;" Array(File,IEN)=0
|
---|
1149 | ;" Array(File,IEN)=0
|
---|
1150 | ;" ShowProgress: if 1, progress bar shown
|
---|
1151 | ;"Output: all pointers in linked files to OldIEN will be changed to newIEN
|
---|
1152 | ;"Results: none
|
---|
1153 |
|
---|
1154 | do QTMMVPTR(.Array,.ShowProgress)
|
---|
1155 | quit
|
---|
1156 |
|
---|
1157 |
|
---|
1158 | ASKKILL
|
---|
1159 | ;"Purpose: to interact with user and safely kill records
|
---|
1160 | ;"Input: none.
|
---|
1161 | ;"Output: Records and pointers may be deleted
|
---|
1162 | ;"Results: none
|
---|
1163 |
|
---|
1164 | new DIC,File,X,Y
|
---|
1165 | new fromIEN,toIEN
|
---|
1166 | new delArray
|
---|
1167 |
|
---|
1168 | kill DIC
|
---|
1169 | set DIC("A")="Select file to delete from: "
|
---|
1170 | set DIC="^DIC("
|
---|
1171 | set DIC(0)="MAQE"
|
---|
1172 | d ^DIC ;"Get File to search
|
---|
1173 | set File=+Y
|
---|
1174 | if File'>0 goto ASKKDone
|
---|
1175 |
|
---|
1176 | new Menu,UsrSlct
|
---|
1177 | set Menu(0)="Pick Option for Selecting Record(s) to Safely Delete"
|
---|
1178 | set Menu(1)="Manually pick Record(s)"_$char(9)_"ManualPick"
|
---|
1179 | set Menu(2)="Select a SET (aka SORT TEMPLATE) Contianing Many Records"_$char(9)_"PickSet"
|
---|
1180 |
|
---|
1181 | M1 write #
|
---|
1182 | set UsrSlct=$$Menu^TMGUSRIF(.Menu,"^")
|
---|
1183 |
|
---|
1184 | if UsrSlct="ManualPick" goto ManualPick
|
---|
1185 | if UsrSlct="PickSet" goto PickSet
|
---|
1186 | if UsrSlct="^" goto ASKKDone
|
---|
1187 | if UsrSlct=0 set UsrSlct=""
|
---|
1188 | goto M1
|
---|
1189 |
|
---|
1190 | ManualPick
|
---|
1191 | set DIC=File
|
---|
1192 | set DIC("A")="Select record to delete: "
|
---|
1193 | do ^DIC ;"get FROM record in File
|
---|
1194 | write !
|
---|
1195 | set fromIEN=+Y
|
---|
1196 | if fromIEN'>0 goto ASKGo
|
---|
1197 | set delArray(File,fromIEN)=0
|
---|
1198 | new % set %=2
|
---|
1199 | write "Pick another record" do YN^DICN write !
|
---|
1200 | if %=1 goto ManualPick
|
---|
1201 | if %=-1 goto ASKKDone
|
---|
1202 | goto ASKGo
|
---|
1203 |
|
---|
1204 | PickSet new IENArray
|
---|
1205 | if $$GetTemplateRecs^TMGXMLUI(File,"IENArray","",1)=0 goto ASKKDone
|
---|
1206 | ;"Output: Data is put into pRecs like this: @pRecs@(IEN)=""
|
---|
1207 |
|
---|
1208 | new IEN set IEN=""
|
---|
1209 | for set IEN=$order(IENArray(IEN)) quit:(IEN="") do
|
---|
1210 | . set delArray(File,IEN)=0
|
---|
1211 |
|
---|
1212 | ASKGo
|
---|
1213 | if $data(delArray)=0 goto ASKKDone
|
---|
1214 |
|
---|
1215 | ;"Get list of files/fields with pointers in
|
---|
1216 | set result=$$PossPtrs(File,.PossPtrs) if result=0 goto ASKKDone
|
---|
1217 | if $data(PossPtrs)'>0 goto DelRecs
|
---|
1218 |
|
---|
1219 | do SAFEKILL(.delArray,1)
|
---|
1220 |
|
---|
1221 | DelRecs ;"Now that pointers to records are deleted, it is safe to remove records themselves
|
---|
1222 |
|
---|
1223 | set IEN=""
|
---|
1224 | new abort set abort=0
|
---|
1225 | for set IEN=$order(IENArray(IEN)) quit:(IEN="")!(abort=1) do
|
---|
1226 | . if $$UserAborted^TMGUSRIF set abort=1 quit
|
---|
1227 | . new TMGFDA,TMGMSG
|
---|
1228 | . set TMGFDA(File,IEN_",",.01)="@"
|
---|
1229 | . do FILE^DIE("EK","TMGFDA","TMGMSG")
|
---|
1230 | . do ShowIfDIERR^TMGDEBUG(.TMGMSG)
|
---|
1231 |
|
---|
1232 | ASKKDone
|
---|
1233 | quit
|
---|
1234 |
|
---|
1235 |
|
---|
1236 |
|
---|
1237 | VerifyPtrs(File,pArray,Verbose,AutoFix)
|
---|
1238 | ;"Purpose: to scan a file for pointers OUT that are bad/invalid
|
---|
1239 | ;"Input: File : file Name or Number to scan
|
---|
1240 | ;" pArray : PASS BY NAME, an OUT PARAMETER. Format:
|
---|
1241 | ;" @pArray@(FileNum,IEN,FieldNum)=ValueOfBadPtr
|
---|
1242 | ;" @pArray@(FileNum,IEN,FieldNum)=ValueOfBadPtr
|
---|
1243 | ;" Verbose: OPTIONAL. If 1, then errors immediately written out.
|
---|
1244 | ;" AutoFix: OPTIONAL. If 1, then bad pointers are deleted.
|
---|
1245 | ;"Results: None
|
---|
1246 |
|
---|
1247 | new PtrsOUT
|
---|
1248 | new pPtrsOUT set pPtrsOUT="PtrsOUT"
|
---|
1249 | new fileNum
|
---|
1250 | if +File=File set fileNum=+File
|
---|
1251 | else set fileNum=$$GetFileNum^TMGDBAPI(File)
|
---|
1252 | set Verbose=+$get(Verbose)
|
---|
1253 | set AutoFix=+$get(AutoFix)
|
---|
1254 |
|
---|
1255 | if $$FilePtrs(fileNum,pPtrsOUT)=0 goto VPtrDone
|
---|
1256 |
|
---|
1257 | new Itr,Itr2,TMGIEN,fieldNum
|
---|
1258 | new TMGVALUE,code
|
---|
1259 | new abort set abort=0
|
---|
1260 | new $etrap set $etrap="set Y=""(Invalid M code!. Error Trapped.)"" set $etrap="""",$ecode="""""
|
---|
1261 |
|
---|
1262 | do DoVerify(File,pArray,Verbose,AutoFix) ;" Split out code to call it to call itself reentrantly
|
---|
1263 |
|
---|
1264 | VPtrDone
|
---|
1265 | quit
|
---|
1266 |
|
---|
1267 |
|
---|
1268 | DoVerify(fileNum,pArray,Verbose,AutoFix,IENS,pTMGIEN)
|
---|
1269 | ;"Purpose: Function allow VerifyPtrs to call reentrantly
|
---|
1270 | ;"Input: File : file Name or Number to scan
|
---|
1271 | ;" pArray : PASS BY NAME, an OUT PARAMETER. Format:
|
---|
1272 | ;" @pArray@(FileNum,IEN,FieldNum)=ValueOfBadPtr
|
---|
1273 | ;" @pArray@(FileNum,IEN,FieldNum)=ValueOfBadPtr
|
---|
1274 | ;" Verbose: OPTIONAL. If 1, then errors immediately written out.
|
---|
1275 | ;" AutoFix: OPTIONAL. If 1, then bad pointers are deleted.
|
---|
1276 | ;" IENS: OPTIONAL. If fileNum is a sub-file, then must supply
|
---|
1277 | ;" to give location of subfile in parent file.
|
---|
1278 | ;" pTMGIEN: "TMGIEN", or "TMGIEN(1)" etc.
|
---|
1279 | ;"Results: None
|
---|
1280 | ;"NOTICE: right now this MUST first be called from VerifyPtrs because
|
---|
1281 | ;" I have not moved some NEW commandes etc from there to here.
|
---|
1282 | ;" So this function depends on it's variables with global scope.
|
---|
1283 |
|
---|
1284 | set IENS=$get(IENS)
|
---|
1285 | set pTMGIEN=$get(pTMGIEN,"TMGIEN")
|
---|
1286 | set @pTMGIEN=$$ItrInit^TMGITR(fileNum,.Itr,.IENS)
|
---|
1287 | if IENS="" do PrepProgress^TMGITR(.Itr,20,0,pTMGIEN) ;" no bar for subfiles
|
---|
1288 | if @pTMGIEN'="" for do quit:(+$$ItrNext^TMGITR(.Itr,.@pTMGIEN)'>0)!abort
|
---|
1289 | . set fieldNum=$$ItrAInit^TMGITR($name(@pPtrsOUT@(fileNum)),.Itr2)
|
---|
1290 | . if fieldNum'="" for do quit:(+$$ItrANext^TMGITR(.Itr2,.fieldNum)'>0)!abort
|
---|
1291 | . . if (@pTMGIEN#10=0),$$UserAborted^TMGUSRIF set abort=1 quit
|
---|
1292 | . . ;"Line below handles subfiles
|
---|
1293 | . . if $data(@pPtrsOUT@(fileNum,fieldNum,"SUBFILE")) do quit
|
---|
1294 | . . . new subFile set subFile=$order(@pPtrsOUT@(fileNum,fieldNum,"SUBFILE",""))
|
---|
1295 | . . . set IENS=IENS_@pTMGIEN_","
|
---|
1296 | . . . do DoVerify(subFile,$name(@pArray@("SUBFILE")),.Verbose,.AutoFix,IENS,$name(@pTMGIEN@(1)))
|
---|
1297 | . . ;"Otherwise, the usual case....
|
---|
1298 | . . set code=$get(PtrsOUT(fileNum,fieldNum,"X GET"))
|
---|
1299 | . . if code="" quit
|
---|
1300 | . . xecute code
|
---|
1301 | . . if TMGVALUE="" quit
|
---|
1302 | . . set TMGVALUE=+TMGVALUE
|
---|
1303 | . . if TMGVALUE'>0 do quit
|
---|
1304 | . . . set @pArray@(fileNum,@pTMGIEN,fieldNum)=TMGVALUE
|
---|
1305 | . . . new setCode set setCode=$get(PtrsOUT(fileNum,fieldNum,"X SET")) quit:(setCode="")
|
---|
1306 | . . . new priorValue set priorValue=TMGVALUE
|
---|
1307 | . . . set TMGVALUE=""
|
---|
1308 | . . . if 'AutoFix quit
|
---|
1309 | . . . xecute setCode
|
---|
1310 | . . . if 'Verbose quit
|
---|
1311 | . . . write !,"File=",fileNum,"; IEN=",@pTMGIEN,"; Field=",fieldNum,"; Bad Pointer value=[",priorValue,"]",!
|
---|
1312 | . . . write " fixed...",!
|
---|
1313 | . . ;"if (fileNum=2)&(TMGVALUE=777) do quit ;"TEMP!!!!
|
---|
1314 | . . ;". set code=$get(PtrsOUT(fileNum,fieldNum,"X SET")) quit:(code="")
|
---|
1315 | . . ;". set TMGVALUE=69
|
---|
1316 | . . ;". xecute code
|
---|
1317 | . . new PtToGref set PtToGref="^"_$get(PtrsOUT(fileNum,fieldNum,"POINTS TO","GREF"))
|
---|
1318 | . . if PtToGref="" do quit
|
---|
1319 | . . . set @pArray@(fileNum,@pTMGIEN,fieldNum)="??No reference for pointed to file??"
|
---|
1320 | . . . if 'Verbose quit
|
---|
1321 | . . . write !,"File=",fileNum,"; IEN=",@pTMGIEN,"; Field=",fieldNum,"; Pointer value=[",TMGVALUE,"] but 'No reference for pointed to file (??)'",!
|
---|
1322 | . . set PtToGref=PtToGref_TMGVALUE_")"
|
---|
1323 | . . if $data(@PtToGref)'>0 do quit
|
---|
1324 | . . . set @pArray@(fileNum,@pTMGIEN,fieldNum)=TMGVALUE
|
---|
1325 | . . . new setCode set setCode=$get(PtrsOUT(fileNum,fieldNum,"X SET")) quit:(setCode="")
|
---|
1326 | . . . new priorValue set priorValue=TMGVALUE
|
---|
1327 | . . . set TMGVALUE=""
|
---|
1328 | . . . if 'AutoFix quit
|
---|
1329 | . . . xecute setCode
|
---|
1330 | . . . if 'Verbose quit
|
---|
1331 | . . . write !,"File=",fileNum,"; IEN=",@pTMGIEN,"; Field=",fieldNum,"; Bad Pointer value=[",priorValue,"]",!
|
---|
1332 | . . . write " fixed...",!
|
---|
1333 | if IENS="" do ProgressDone^TMGITR(.Itr)
|
---|
1334 | quit
|
---|
1335 |
|
---|
1336 |
|
---|
1337 | ASKVFYPT ;"ASK VERIFY POINTERS
|
---|
1338 | ;"Ask user to pick file, then verify pointers for that file.
|
---|
1339 |
|
---|
1340 | write "NOTICE: this function caused corruption of the database from",!
|
---|
1341 | write " deletion of pointers incorrectly. Until this function",!
|
---|
1342 | write " (ASKVFYPT^TMGFMUT) is fixed, it may not be used.",!,!
|
---|
1343 | do PressToCont^TMGUSRIF
|
---|
1344 | goto ASKDone
|
---|
1345 |
|
---|
1346 |
|
---|
1347 | new DIC,X,Y
|
---|
1348 | new FileNum,IEN
|
---|
1349 | new UseDefault set UseDefault=1
|
---|
1350 |
|
---|
1351 | ;"Pick file to dump from
|
---|
1352 | ASK1 set DIC=1
|
---|
1353 | set DIC(0)="AEQM"
|
---|
1354 | set DIC("A")="SELECT FILE TO VERIFY POINTERS IN: "
|
---|
1355 | if UseDefault do ;"leave the redundant do loop, it protects $T, so second do ^DIC isn't called
|
---|
1356 | . do ^DICRW ;" has default value of user's last response
|
---|
1357 | else do ^DIC ;doesn't have default value...
|
---|
1358 | write !
|
---|
1359 | if +Y'>0 write ! goto ASKDone
|
---|
1360 | set FileNum=+Y
|
---|
1361 |
|
---|
1362 | new BadPtrs
|
---|
1363 | new AutoFix,Verbose,%
|
---|
1364 | set %=2
|
---|
1365 | write "View details of scan" do YN^DICN write !
|
---|
1366 | if %=-1 goto ASKDone
|
---|
1367 | set Verbose=(%=1)
|
---|
1368 |
|
---|
1369 | set %=2
|
---|
1370 | write "Auto-delete bad pointers (i.e. 0 value, or pointers to empty records)"
|
---|
1371 | do YN^DICN write !
|
---|
1372 | if %=-1 goto ASKDone
|
---|
1373 | set AutoFix=(%=1)
|
---|
1374 |
|
---|
1375 | do VerifyPtrs(FileNum,"BadPtrs",Verbose,AutoFix)
|
---|
1376 |
|
---|
1377 | if $data(BadPtrs) do
|
---|
1378 | . new % set %=2
|
---|
1379 | . write "View array of bad pointers" do YN^DICN write !
|
---|
1380 | . if %'=1 quit
|
---|
1381 | . do ArrayDump^TMGDEBUG("BadPtrs")
|
---|
1382 | else write "No bad pointers. Great!",!
|
---|
1383 |
|
---|
1384 | do PressToCont^TMGUSRIF
|
---|
1385 |
|
---|
1386 | ASKDone
|
---|
1387 | quit
|
---|
1388 |
|
---|
1389 | GREP(FIELD,S)
|
---|
1390 | ;"The is a stub function, called by a Fileman Function (entry in file .5)
|
---|
1391 | new result
|
---|
1392 | set result="X1="_$get(FIELD)_" X2="_$get(S)_" D0="_$get(D0)_" DCC="_$get(DCC)
|
---|
1393 | merge ^TMG("TMP","KILL","DIQGEY")=DIQGEY
|
---|
1394 | set ^TMG("TMP","KILL","DA")=$get(DA)
|
---|
1395 | set ^TMG("TMP","KILL","DR")=$get(DR)
|
---|
1396 | set ^TMG("TMP","KILL","D0")=$get(D0)
|
---|
1397 | set ^TMG("TMP","KILL","DCC")=$get(DCC)
|
---|
1398 | QUIT result
|
---|
1399 |
|
---|
1400 | GETAPPT(TMGIEN)
|
---|
1401 | QUIT 0
|
---|
1402 |
|
---|
1403 | FMDate(DateStr)
|
---|
1404 | ;"Purpose: convert string to FM date, with extended syntax handling
|
---|
1405 | ;"Results: returns FM date, or -1 if error
|
---|
1406 | new result set result=-1
|
---|
1407 | ;"First try direct conversion
|
---|
1408 | new X,Y
|
---|
1409 | set DateStr=$$TRIM^XLFSTR($get(DateStr))
|
---|
1410 | if DateStr="" goto FMDDone
|
---|
1411 | for quit:(DateStr'[" ") set DateStr=$$Substitute^TMGSTUTL(DateStr," "," ")
|
---|
1412 | if (DateStr'["@")&($length(DateStr," ")>3) do
|
---|
1413 | . set DateStr=$piece(DateStr," ",1,3)_"@"_$piece(DateStr," ",4,99)
|
---|
1414 | for quit:(DateStr'["@ ") set DateStr=$$Substitute^TMGSTUTL(DateStr,"@ ","@")
|
---|
1415 | for quit:(DateStr'[" @") set DateStr=$$Substitute^TMGSTUTL(DateStr," @","@")
|
---|
1416 | set %DT="T",X=DateStr
|
---|
1417 | do ^%DT
|
---|
1418 | set result=Y
|
---|
1419 | FMDDone quit result
|
---|