source: cprs/branches/tmg-cprs/m_files/TMGSRCH.m~@ 796

Last change on this file since 796 was 796, checked in by Kevin Toppenberg, 14 years ago

Initial upload

File size: 18.4 KB
Line 
1TMGSRCH ;TMG/kst/Search API ; 5/24/10
2 ;;1.0;TMG-LIB;**1**;05/19/10
3 ;
4 ;"TMG FILEMAN SEARCH API
5 ;
6 ;"Copyright Kevin Toppenberg MD 5/19/10
7 ;"Released under GNU General Public License (GPL)
8 ;"
9 ;"NOTE: this function depends on new version of LIST^DIC, from G. Timpson Patch
10 ;"=======================================================================
11 ;" RPC -- Public Functions.
12 ;"=======================================================================
13 ;"SRCH(OUT,FILENUM,STR) --A search function, to support calls by RPC from CPRS
14 ;"BKSRCH(FILENUM,STR) -- designed to be called via JOB --> separate job thread
15 ;"FMSRCH(OUT,FILENUM,COMPEXPR) --A wrapper for Fileman search call
16 ;"=======================================================================
17 ;"PRIVATE API FUNCTIONS
18 ;"=======================================================================
19 ;"PARSESTR(FILENUM,STR,ARRAY,FNUMPTR) -- Parse user input into formatted array
20 ;"PARSE1(FILENUM,STR,FNUMPTR,ARRAY) --Parse a simple search term
21 ;"BKPGFN(MSG,PCT) -- Callable progress function code for background thread.
22 ;"DOSRCH(PTMGOUT,FILENUM,STR,PGFN) --Common search codes
23 ;"=======================================================================
24 ;"=======================================================================
25 ;"Dependencies:
26 ;" DIC, TMGDEBUG,TMGUSRIF, TMGDBAPI, DIE, XLFSTR, TMGSRCH*
27 ;"=======================================================================
28 ;"=======================================================================
29 ;
30 ;
31 ;"=======================================================================
32 ;" SEARCH STRING DOCUMENTATION
33 ;"=======================================================================
34 ;"Search string examples:
35 ;" 8925:.02(.01="SMITH,JOHN")
36 ;" 1234:.01(.03in"32..55") <-- this is a range test
37 ;" 1234:.99((.01="SMITH,JOHN") OR (.01="SMITH,BILL")) AND 4567:.01(.02'="4/2/10") NOT (1["HAPPY")
38 ;" 8925:(REPORT TEXT[DM-2)!(REPORT TEXT[HTN) AND 120.5:((VITAL TYPE=PULSE)&(RATE>70)) Targetfile=2
39 ;"
40 ;"SYNTAX:
41 ;" -- File specifier. To specify searching in a file OTHER THAN target filenumber, an optional
42 ;" FILENUM:FLD[:FLD[:FLD...]] may be specified. However, ultimately, this must point back
43 ;" to the target filenumber. E.g. Search in file 8925, but for each entry found, use the IEN
44 ;" specified by FLD (or FLDA:FLDB or FLDA:FLDB:FLDC:...). NOTE: If just FILENUM is provided
45 ;" without specifying FLD(s) to point to target filenumber, then the code will find a path
46 ;" (if possible), using first one found.
47 ;" FILENUM:(...)
48 ;" The logic is read from left to right, honoring parentheses. If a filenumber
49 ;" is not specified, then the last specified filenumber is used.
50 ;" E.g. 1234:.01( LogicA ) OR 234:.99( LogicB ) AND ( LogicC )
51 ;" LogicA fields refer to file 1234:.01.
52 ;" LogicB fields refer to file 234:.99
53 ;" LogicA fields refer to file 234:.99 (last specified file number)
54 ;" E.g. 5678:.01( (LogicA1) OR 5432:.88(LogicA2) NOT (LogicA3) ) or (LogicB)
55 ;" LogicA1 fields refer to file 5678:.01
56 ;" LogicA2 fields refer to file 5432:.88
57 ;" LogicA3 fields refer to file 5432:.88 (last specified file number inside parentheses)
58 ;" LogicB fields refer to file 5678 (last specified file number at same parentheses level)
59 ;" -- Each individual search term must be enclosed in parentheses, and may contain sub-terms
60 ;" enclosed in nested parentheses
61 ;" -- Each individual search term is comprised of:
62 ;" FIELD then COMPARATOR then VALUE
63 ;" 1. FIELDS -- can be name or number. This is for currently active file (see below)
64 ;" may also be FIELDA:FIELDB:... when FIELDA is a pointer, then FIELDB
65 ;" is taken from the pointed-to file. If FIELDB is not provided, and FIELDA
66 ;" is a pointer, then the .01 field of pointed-to-file. Individual field
67 ;" names may be inclosed in quotes
68 ;" 2. COMPARATOR -- can be:
69 ;" "=" -- means exact match
70 ;" "'=", "<>", -- any of these means Does-not-equal
71 ;" ">=", "'<" -- means greater-than-or-equal-to (same as not-less-than)
72 ;" "<=", "'>" -- means less-than-or-equal-to (same sa not-greater-than)
73 ;" "in","IN","In","{" -- means field is in specified rage (see Value below)
74 ;" When using IN, if field name is provided by NAME (not number),
75 ;" then field name should be inclosed in quotes to separate the
76 ;" letters of the field name from the letters of 'IN'.
77 ;" "[" -- means 'contains'. Interpreted as follows:
78 ;" -- For Word processor (WP) fields, this means that any line in the entire field
79 ;" can contain search term, to be matched positive.
80 ;" -- For free text field, then just text of field is searched.
81 ;" 3. VALUE -- The search term to search for. Should be in quotes.
82 ;" Note: if comparator is "IN", then syntax is "Value1..Value2"
83 ;" There should be a ".." between the two values.
84 ;" -- Logical combiners of separate search terms allowed are:
85 ;" "OR" or "|" or "||" or "!"
86 ;" "AND" or "&" or "&&"
87 ;" "NOT" or "'" or "ANDNOT"
88 ;"=======================================================================
89 ;"=======================================================================
90 ;
91 ;
92TEST ;
93 NEW STR,OUT
94 ;"SET STR="8925:(STATUS=COMPLETED)&((PATIENT[CUTSHALL)!(PATIENT[CUTSHAW))"
95 SET STR="8925:(REPORT TEXT[DM-2)!(REPORT TEXT[HTN) AND 120.5:((VITAL TYPE=PULSE)&(RATE>70))"
96 ;"SET STR="8925:(REPORT TEXT[DM-2) AND 120.5:((VITAL TYPE=PULSE)&(RATE>70))"
97 ;"SET STR="8925:(REPORT TEXT[HTN) AND 120.5:((VITAL TYPE=PULSE)&(RATE{70..75))"
98 ;"SET STR="8925:(REPORT TEXT[DM-2)!(REPORT TEXT[HTN)"
99 ;"WRITE STR,!
100 ;"DO SRCH(.OUT,2,STR)
101 ;"NEW CT SET CT=+$GET(OUT("COUNT"))
102 ;"WRITE "Found ",CT," total matches.",!
103 ;"DO PressToCont^TMGUSRIF
104
105 DO BKSRCH(2,STR)
106 NEW STATUS,PCT
107 NEW REF SET REF=$NAME(^TMP("TMG","TMGSRCH",$J))
108 FOR DO QUIT:(STATUS["#DONE#")
109 . HANG 1
110 . SET STATUS=$GET(@REF@("MSG"))
111 . WRITE "STATUS: ",STATUS,!
112 ;"IF $DATA(@REF) ZWR @REF
113 QUIT
114 ;
115SRCH(OUT,FILENUM,STR) ;
116 ;"Purpose: A search function, to support calls by RPC from CPRS
117 ;"Input: OUT-- Pass by reference. AN OUT PARAMETER.
118 ;" FILENUM -- The target file number that resulting IENs will be in
119 ;" STR -- This is a logic string for searching. See details above.
120 ;"Results: OUT is filled in. Format:
121 ;" OUT(0)=1 for success, or -1^Error Message
122 ;" OUT(IEN)=""
123 ;" OUT(IEN)=""
124 ;" OUT("COUNT")=Count of number of found records.
125 ;"Results: None
126 ;"
127 DO DOSRCH("OUT",.FILENUM,.STR) ;
128SRCHDN QUIT
129 ;
130 ;
131BKSRCH(FILENUM,STR) ;
132 ;"Purpose: this function is designed to be called via JOB, to setup separate job thread
133 ;" E.g. JOB BKSRCH^TMGTMGSRCH(FILENUM,STR) NEW MSGJOB SET MSGJOB=$ZJOB
134 ;" NOTE: When job, output MSG will be "#DONE#" (see below)
135 ;"Input: Filenum: This this is the target file of the search.
136 ;" STR -- This is the logic string for searching. Format as per SRCH() docs
137 ;"Output: Output will go into ^TMP("TMG","TMGSRCH",$J,"OUT")
138 ;" Messages will go into ^TMP("TMG","TMGSRCH",$J,"MSG")
139 ;" % Done will go into ^TMP("TMG","TMGSRCH",$J,"PCT")
140 ;"Results: none
141 NEW PGFN SET PGFN="DO BKPGFN^TMGSRCH(.TMGSTAT,.TMGPCT)"
142 NEW POUT SET POUT=$NAME(^TMP("TMG","TMGSRCH",$J,"OUT"))
143 KILL @POUT
144 DO DOSRCH(POUT,.FILENUM,.STR,PGFN) ;
145 DO BKPGFN("#DONE#",100)
146 QUIT ;"This should terminate thread (if called by JOB as above)
147 ;
148BKPGFN(MSG,PCT) ;
149 ;"Callable progress function code for background thread.
150 SET ^TMP("TMG","TMGSRCH",$J,"MSG")=$GET(MSG)
151 SET ^TMP("TMG","TMGSRCH",$J,"PCT")=$GET(PCT)
152 QUIT
153 ;
154 ;
155DOSRCH(PTMGOUT,FILENUM,STR,PGFN) ;
156 ;"Common entry endpoint for search entry tags. See docs in SRCH()
157 ;"Input: PTMGOUT -- Pass by NAME. The name of the output array
158 ;" FILENUM -- See SRCH()
159 ;" STR -- See SRCH()
160 ;" TMGPGFN -- OPTIONAL. Mumps code that will be called periodically
161 ;" to allow display of progress of slow searches.
162 ;" Code may depend on the following variables:
163 ;" TMGSTAT -- The most recent status text
164 ;" TMGPCT -- a very gross estimate of % done (0-100%)
165 ;"Results -- None.
166 NEW TMGARRAY,RESULT,CT
167 SET RESULT=$$PARSESTR(.FILENUM,STR,.TMGARRAY)
168 ;
169 ;"MERGE ^TMG("TMP","RPC","TMGRPCSR","TMGARRAY")=TMGARRAY ;"TEMP!!!
170 ;
171 IF +RESULT=-1 SET @PTMGOUT@(0)=RESULT GOTO DSRCHDN
172 SET CT=$$ARRYSRCH^TMGSRCH0(FILENUM,PTMGOUT,.TMGARRAY,.PGFN)
173 SET @PTMGOUT@("COUNT")=CT
174 SET @PTMGOUT@("FILENUM")=FILENUM
175 IF $GET(@PTMGOUT@(0))="" SET @PTMGOUT@(0)=1 ;"Success
176DSRCHDN QUIT
177 ;
178 ;
179PARSESTR(FILENUM,STR,ARRAY,FNUMPTR) ;
180 ;"Purpose: To take user input, validate it, and parse into an formatted array
181 ;"Input: FILENUM -- The file number that is the target of the search.
182 ;" STR: This is the user input string. Format as documented in SRCH() above.
183 ;" ARRAY -- PASS BY REFERENCE. An OUT PARAMETER. Format as follows.
184 ;" ARRAY(1,"FNUMPTR")= FNUM:FLDA[:FLDB[:FLDC...]] FNUM is filenumber that
185 ;" contain search field, and then fields used to point
186 ;" back to *TARGET* FILENUM for entire search
187 ;" ARRAY(1,"FLD")=Fieldnumber to search
188 ;" ARRAY(1,"COMP")=Comparator, will be "=", "'=", "'<", or "'>", "[", "{", "IN"
189 ;" ARRAY(1,"SRCH")=The value of to be used in search.
190 ;" ARRAY(1,"WP")=1 if field is a WP field
191 ;" ARRAY(2,...) The second search term.
192 ;" ARRAY(2,"LOGIC")=#^Combiner
193 ;" # means the set so far.
194 ;" Combiner will be "AND", "OR", or "NOT"
195 ;" ARRAY(3,...) The third search term (which is comprised of sub terms)
196 ;" ARRAY(3,1,... The first subterm (same format as higher level)
197 ;" ARRAY(3,2,... The second subterm (same format as higher level)
198 ;" ARRAY(n,...) The N'th search term.
199 ;" removed-> ARRAY("SETCOMP",i)= NumA^Combiner^NumB
200 ;" NumA and NumB refer to seach term number (e.g. 1, 2, ... n above)
201 ;" If NumA="#", then it means 'the resulting set of results so far'
202 ;" Combiner will be "AND", "OR", or "NOT"
203 ;" i is the index variable, and logic should be evaluated in numerical order
204 ;" FNUMPTR: Will be used when calling self reiteratively. Leave blank in first call.
205 ;" DON'T pass by reference. This is 'FileNum:FLD[:FLD[:FLD...]] specifier
206 ;"Results: 1 if OK, or -1^Message if error during processing.
207 ;
208 NEW SUBSTRA,SUBSTRB,POS
209 NEW RESULT SET RESULT=1 ;"default to success
210 NEW TERMNUM SET TERMNUM=0
211 SET FILENUM=+$GET(FILENUM)
212 IF FILENUM'>0 DO GOTO PSDN
213 . SET RESULT="-1^Target file number not provided."
214 SET FNUMPTR=$GET(FNUMPTR,FILENUM)
215 SET ARRAY("FILE")=FILENUM
216 NEW LOGICNUM SET LOGICNUM=0
217 NEW DONE SET DONE=0
218 FOR DO QUIT:(DONE=1)!(+RESULT=-1)
219 . NEW TEMPARRAY
220 . SET TERMNUM=TERMNUM+1
221 . ;"--- Get file number, if any
222 . SET STR=$$TRIM^XLFSTR(STR)
223 . IF +$PIECE(STR,"(",1)>0 DO QUIT:(+RESULT=-1)
224 . . SET FNUMPTR=$PIECE(STR,"(",1) ;"Convert 1234:.01:.02:(...) --> 1234:.01:.02:
225 . . IF $EXTRACT(FNUMPTR,$LENGTH(FNUMPTR))=":" SET FNUMPTR=$EXTRACT(FNUMPTR,1,$LENGTH(FNUMPTR)-1)
226 . . IF ($PIECE(FNUMPTR,":",2)="")&(+FNUMPTR'=FILENUM) DO QUIT:(+RESULT=-1)
227 . . . NEW SAVPTR SET SAVPTR=FNUMPTR
228 . . . SET FNUMPTR=$PIECE($$PATHTO^TMGSRCH1(+FNUMPTR,FILENUM),"^",1)
229 . . . IF FNUMPTR="" SET RESULT="-1^Unable to find path to file #"_FILENUM_" from "_SAVPTR
230 . . ELSE IF $$FNPTR^TMGSRCH1(FNUMPTR)'=FILENUM DO QUIT
231 . . . SET RESULT="-1^'"_FNUMPTR_"' points to file #"_$$FNPTR^TMGSRCH1(FNUMPTR)_", not file #"_FILENUM_" as expected"
232 . ;"Split STR --> SUBSTRA + SUBSTRB
233 . SET SUBSTRA=$$MATCHXTR^TMGSTUTL(STR,"(",,,"(")
234 . IF SUBSTRA="" SET DONE=1 QUIT
235 . SET POS=$FIND(STR,SUBSTRA) ;"Return pos of following character
236 . SET SUBSTRB=$EXTRACT(STR,POS+1,9999) ;"Should be " [LOGICTERM] [SearchTerm]..."
237 . ;"Process SUBSTRA, either directly if single term, or recursively if compound term.
238 . IF $$HNQTSUB^TMGSTUTL(SUBSTRA,"(") DO
239 . . SET RESULT=$$PARSESTR(FILENUM,SUBSTRA,.TEMPARRAY,FNUMPTR)
240 . . SET ARRAY(TERMNUM,"SUBTERMS")=1
241 . ELSE DO
242 . . SET RESULT=$$PARSE1(FILENUM,SUBSTRA,FNUMPTR,.TEMPARRAY)
243 . IF +RESULT=-1 QUIT
244 . SET SUBSTRA=""
245 . MERGE ARRAY(TERMNUM)=TEMPARRAY
246 . ;"Now get Logic term connecting this to next term (if any)
247 . SET SUBSTRB=$$TRIM^XLFSTR(SUBSTRB) ;"Remove opening (and closing) spaces
248 . NEW LOGICTERM SET LOGICTERM=""
249 . NEW P,CH
250 . NEW DNCOMB SET DNCOMB=0
251 . FOR P=1:1:$LENGTH(SUBSTRB) DO QUIT:DNCOMB!(+RESULT=-1)
252 . . SET CH=$$UP^XLFSTR($EXTRACT(SUBSTRB,P))
253 . . IF ("&|'!ANDORNOT"'[CH) SET DNCOMB=1 QUIT
254 . . SET LOGICTERM=LOGICTERM_CH
255 . SET STR=$EXTRACT(SUBSTRB,$LENGTH(LOGICTERM)+1,9999),SUBSTRB=""
256 . IF LOGICTERM="" QUIT
257 . SET LOGICTERM=$$FIXCOMB^TMGSRCH1(LOGICTERM,.RESULT) QUIT:(+RESULT=-1)
258 . NEW CURSET SET CURSET=$SELECT(TERMNUM=1:"1",1:"#")
259 . SET LOGICNUM=LOGICNUM+1
260 . ;"SET ARRAY("SETCOMP",LOGICNUM)=CURSET_"^"_LOGICTERM_"^"_(TERMNUM+1) ;"will check later that TERMNUM+1 is supplied
261 . SET ARRAY(TERMNUM+1,"LOGIC")="#^"_LOGICTERM
262PSDN QUIT RESULT
263 ;
264 ;
265PARSE1(FILENUM,STR,FNUMPTR,ARRAY) ;
266 ;"Purpose: Parse a simple search term (e.g. .01="SMITH,JOHN"). Also validate that field exists in file.
267 ;"Input: FILENUM -- The TARGET filenumber that the entire search is referencing.
268 ;" STR: This is part of the user input string to parse
269 ;" FNUMPTR: FNUM:FLDA[:FLDB[:FLDC...]] FNUM is filenumber that contain search field, and then
270 ;" fields used to point back to *TARGET* FILENUM for entire search
271 ;" ARRAY -- PASS BY REFERENCE. An OUT PARAMETER. Format as follows.
272 ;" ARRAY("FNUMPTR")=Filenumber that contains field)
273 ;" ARRAY("FLD")=Fieldnumber to search
274 ;" ARRAY("COMP")=Comparator, will be "=", "'=", "'<", or "'>", "[","IN", "{"
275 ;" ARRAY("SRCH")=The value of to be used in search.
276 ;" ARRAY("WP")=1 if field is a WP field
277 ;"NOTE: If field specifies a DATE, then the search value will be converted to FileMan format
278 ;"Results: 1 if OK, or -1^Message if error during processing.
279 ;"
280 NEW RESULT SET RESULT=1 ;"default to success
281 NEW SAV SET SAV=STR
282 SET STR=$$TRIM^XLFSTR($GET(STR))
283 SET ARRAY("FNUMPTR")=FNUMPTR
284 NEW FLD,FLDS SET FLDS=""
285 NEW TMGTFILE SET TMGTFILE=+FNUMPTR
286 FOR QUIT:("'<>=[:({"[$EXTRACT(STR,1))!(STR="") DO
287 . SET FLD=$$GETFLD^TMGSRCH1(.STR) ;
288 . NEW SAVFIL SET SAVFIL=TMGTFILE
289 . NEW ONEFLD SET ONEFLD=$$FLDNUM^TMGSRCH1(.TMGTFILE,.FLD)
290 . IF ONEFLD'>0 DO QUIT
291 . . SET RESULT="-1^Field ["_FLD_"] was not found in file ["_SAVFIL_"]"
292 . IF FLDS'="" SET FLDS=FLDS_":"
293 . SET FLDS=FLDS_ONEFLD
294 IF +RESULT=-1 GOTO PS1DN
295 SET ARRAY("FLD")=FLDS
296 IF $$ISWPFLD^TMGDBAPI(+FNUMPTR,+FLDS) SET ARRAY("WP")=1
297 NEW FLDTYPE SET FLDTYPE=$PIECE($GET(^DD(+FNUMPTR,+FLDS,0)),"^",2)
298 IF FLDTYPE["M" DO GOTO PS1DN
299 . SET RESULT="-1^Searches in fields that are MULTIPLES not supported"
300 SET STR=$$TRIM^XLFSTR(STR)
301 NEW COMP
302 IF $$UP^XLFSTR($EXTRACT(STR,1,3))="'IN" SET COMP="'IN"
303 ELSE IF $$UP^XLFSTR($EXTRACT(STR,1,2))="IN" SET COMP="IN"
304 ELSE DO
305 . SET COMP="" NEW P,CH
306 . FOR P=1:1:$LENGTH(STR) SET CH=$EXTRACT(STR,P) QUIT:("'!<>=[{"'[CH) SET COMP=COMP_CH
307 SET STR=$EXTRACT(STR,$LENGTH(COMP)+1,9999)
308 SET COMP=$$FIXCOMP^TMGSRCH1(COMP,.RESULT)
309 IF +RESULT=-1 GOTO PS1DN
310 SET ARRAY("COMP")=COMP
311 SET STR=$$TRIM^XLFSTR(STR) ;"Remove any spaces after comparator
312 NEW SRCH SET SRCH=$$TRIM^XLFSTR(STR,,"""") ;"Trim quotes, if any.
313 IF FLDTYPE["D" DO GOTO:(+RESULT=-1) PS1DN ;"standardized dates
314 . NEW ADATE SET ADATE=SRCH
315 . NEW TEMPRSLT SET TEMPRSLT=""
316 . FOR QUIT:(ADATE="")!(+RESULT=-1) DO
317 . . IF TEMPRSLT'="" SET TEMPRSLT=TEMPRSLT_".."
318 . . SET TEMPRSLT=TEMPRSLT_$$STDDATE^TMGSRCH1($PIECE(ADATE,"..",1),.RESULT)
319 . . IF +RESULT=-1 QUIT
320 . . SET ADATE=$PIECE(SRCH,"..",2)
321 . SET SRCH=TEMPRSLT
322 ELSE IF FLDTYPE["S" DO ;"Convert FM SET type into internal format
323 . NEW OUT,TMGMSG
324 . DO VAL^DIE(+FNUMPTR,"+1,",FLD,"E",SRCH,.OUT,,"TMGMSG")
325 . SET SRCH=$GET(OUT)
326 IF SRCH'="" SET ARRAY("SRCH")=SRCH
327 ELSE DO GOTO PS1DN
328 . SET RESULT="-1^Search value is invalid"
329 ;
330PS1DN IF +RESULT=-1 SET RESULT=RESULT_", found in ["_SAV_"]"
331 QUIT RESULT
332 ;
333 ;
334FMSRCH(TMGFILE,TMGCOMPEXPR,TMGOUT,TMGOPTION) ;
335 QUIT $$FMSRCH^TMGSRCH0(.TMGFILE,.TMGCOMPEXPR,.TMGOUT,.TMGOPTION)
336
Note: See TracBrowser for help on using the repository browser.