r3091: *** empty log message ***
[umlisp.git] / sql-classes.lisp
1 ;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10; Package: umlisp -*-
2 ;;;; *************************************************************************
3 ;;;; FILE IDENTIFICATION
4 ;;;;
5 ;;;; Name:          sql-classes.lisp
6 ;;;; Purpose:       Routines for reading UMLS objects from SQL database
7 ;;;; Programmer:    Kevin M. Rosenberg
8 ;;;; Date Started:  Apr 2000
9 ;;;;
10 ;;;; $Id: sql-classes.lisp,v 1.6 2002/10/18 03:57:39 kevin Exp $
11 ;;;;
12 ;;;; This file, part of UMLisp, is
13 ;;;;    Copyright (c) 2000-2002 by Kevin M. Rosenberg, M.D.
14 ;;;;
15 ;;;; UMLisp users are granted the rights to distribute and use this software
16 ;;;; as governed by the terms of the GNU General Public License.
17 ;;;; *************************************************************************
18
19 (in-package :umlisp)
20 (declaim (optimize (speed 3) (safety 1) (compilation-speed 0) (debug 3)))
21
22
23 (defvar *current-srl* nil)
24 (defun current-srl ()
25   *current-srl*)
26 (defun current-srl! (srl)
27   (setq *current-srl* srl))
28
29
30 ;;; Accessors (read on demand)
31
32 ;; defines a slot-unbound method for class and slot-name, fills
33 ;; the slot by calling reader function with the slot values of
34 ;; the instance's reader-keys
35 (defmacro def-lazy-reader (class slot-name reader &rest reader-keys)
36   (let* ((the-slot-name (gensym))
37          (the-class (gensym))
38          (the-instance (gensym))
39          (keys '()))
40     (dolist (key reader-keys)
41       (push (list 'slot-value the-instance (list 'quote key)) keys))
42     (setq keys (nreverse keys))
43     `(defmethod slot-unbound (,the-class (,the-instance ,class)
44                                          (,the-slot-name (eql ',slot-name)))
45        (declare (ignore ,the-class))
46        (setf (slot-value ,the-instance ,the-slot-name)
47            (,reader ,@keys)))))
48
49 (def-lazy-reader ucon s#term find-uterm-cui cui)
50 (def-lazy-reader ucon s#def find-udef-cui cui)
51 (def-lazy-reader ucon s#sty find-usty-cui cui)
52 (def-lazy-reader ucon s#rel find-urel-cui cui)
53 (def-lazy-reader ucon s#coc find-ucoc-cui cui)
54 (def-lazy-reader ucon s#lo find-ulo-cui cui)
55 (def-lazy-reader ucon s#atx find-uatx-cui cui)
56 (def-lazy-reader ucon s#sat find-usat-ui cui)
57
58 ;; For uterms
59 (def-lazy-reader uterm s#str find-ustr-cuilui cui lui)
60 (def-lazy-reader uterm s#sat find-usat-ui cui lui)
61
62 ;; For ustrs
63 (def-lazy-reader ustr s#sat find-usat-ui cui lui sui)
64 (def-lazy-reader ustr s#cxt find-ucxt-cuisui cui sui)
65 (def-lazy-reader ustr s#so find-uso-cuisui cui sui)
66
67 ;;; Object lookups
68
69 ;;; Lookup functions for uterms,ustr in ucons
70
71 (defun find-uterm-in-ucon (ucon lui)
72   (find lui (s#term ucon) :key #'lui :test 'equal))
73
74 (defun find-ustr-in-uterm (uterm sui)
75   (find sui (s#str uterm) :key #'sui :test 'equal))
76
77 (defun find-ustr-in-ucon (ucon sui)
78   (let ((found-ustr nil))
79     (dolist (uterm (s#term ucon))
80       (unless found-ustr
81         (dolist (ustr (s#str uterm))
82           (unless found-ustr
83             (when (string-equal sui (sui ustr))
84               (setq found-ustr ustr))))))
85     found-ustr))
86
87
88 (defun find-ucon-cui (cui &key (srl *current-srl*))
89   "Find ucon for a cui"
90   (if (stringp cui)
91       (setq cui (parse-cui cui)))
92   (if cui
93       (let ((ls (format nil "select KPFSTR,KCUILRL from MRCON where CUI=~d"
94                         cui)))
95         (if srl
96             (string-append ls (format nil " and KCUILRL <= ~d limit 1" srl))
97           (string-append ls " limit 1"))
98         (kmrcl:awhen (car (mutex-sql-query ls))
99                   (make-instance 'ucon :cui cui :pfstr (car kmrcl::it) 
100                                  :lrl (ensure-integer (cadr kmrcl::it)))))
101     nil))
102
103 (defun find-ucon-lui (lui &key (srl *current-srl*))
104   "Find list of ucon for lui"
105   (if (stringp lui)
106       (setq lui (parse-lui lui)))
107   (if lui
108       (let ((ucons '())
109             (ls (format nil "select distinct CUI,KPFSTR,KCUILRL from MRCON where LUI=~d" lui)))
110         (if srl
111             (string-append ls (format nil " and KCUILRL <= ~d" srl)))
112         (dolist (tuple (mutex-sql-query ls))
113           (push (make-instance 'ucon :cui (ensure-integer (nth 0 tuple))
114                                :pfstr (nth 1 tuple)
115                                :lrl (ensure-integer (nth 2 tuple)))
116                 ucons))
117         (nreverse ucons))
118     nil))
119
120 (defun find-ucon-sui (sui &key (srl *current-srl*))
121   "Find list of ucon for sui"
122   (if (stringp sui)
123       (setq sui (parse-sui sui)))
124   (if sui
125       (let ((ucons '())
126             (ls (format nil "select distinct CUI,KPFSTR,KCUILRL from MRCON where SUI=~d" sui)))
127         (when srl
128             (string-append ls (format nil " and KCUILRL <= ~d" srl)))
129         (let ((tuples (mutex-sql-query ls)))
130           (dolist (tuple tuples)
131             (push (make-instance 'ucon :cui (ensure-integer (nth 0 tuple)) 
132                                  :pfstr (nth 1 tuple)
133                                  :lrl (ensure-integer (nth 2 tuple)))
134                   ucons)))
135     (nreverse ucons))
136   nil))
137
138 (defun find-ucon-cuisui (cui sui &key (srl *current-srl*))
139   "Find ucon for cui/sui"
140   (if (stringp cui)
141       (setq cui (parse-cui cui)))
142   (if (stringp sui)
143       (setq sui (parse-sui sui)))
144   (if (and cui sui)
145       (let ((ls (format nil "select distinct CUI,KPFSTR,KCUILRL from MRCON where KCUISUI=~d"
146                         (make-cuisui cui sui))))
147         (when srl
148             (string-append ls (format nil " and KCUILRL <= ~d" srl)))
149         (kmrcl:aif (car (mutex-sql-query ls))
150              (make-instance 'ucon :cui (ensure-integer (nth 0 kmrcl::it)) 
151                             :pfstr (nth 1 kmrcl::it)
152                             :lrl (ensure-integer (nth 2 kmrcl::it)))
153              nil))
154     nil))
155
156 (defun find-ucon-str (str &key (srl *current-srl*))
157   "Find ucon that are exact match for str"
158   (if str
159       (let ((ucons '())
160             (ls (format nil "select distinct CUI,KPFSTR,KCUILRL from MRCON where STR='~a'" str)))
161         (when srl
162             (string-append ls " and KCUILRL <= ~d" srl))
163         (dolist (tuple (mutex-sql-query ls))
164           (push (make-instance 'ucon :cui (ensure-integer (nth 0 tuple)) 
165                                :pfstr (nth 1 tuple)
166                                :lrl (ensure-integer (nth 2 tuple))) ucons))
167         (nreverse ucons))
168     nil))
169
170 (defun find-ucon-all (&key (srl *current-srl*))
171   "Return list of all ucon's"
172   (let ((ls "select distinct CUI,KPFSTR,KCUILRL from MRCON"))
173     (when srl
174       (string-append ls (format nil " where KCUILRL <= ~d" srl)))
175     (string-append ls " order by CUI asc")
176     (with-sql-connection (db)
177       (clsql:map-query 
178        'list
179        #'(lambda (cui pfstr cuilrl)
180            (make-instance 'ucon :cui (ensure-integer cui)
181                           :pfstr pfstr
182                           :lrl (ensure-integer cuilrl)))
183        ls
184        :database db))))
185
186
187
188 (defun find-udef-cui (cui &key (srl *current-srl*))
189   "Return a list of udefs for cui"
190   (let ((udefs '())
191         (ls (format nil "select SAB,DEF from MRDEF where CUI=~d" cui)))
192     (when srl
193         (string-append ls (format nil " and KSRL <= ~d" srl)))
194     (dolist (tuple (mutex-sql-query ls))
195       (push (make-instance 'udef :sab (car tuple) :def (cadr tuple)) udefs))
196     (nreverse udefs)))
197
198 (defun find-usty-cui (cui &key (srl *current-srl*))
199   "Return a list of usty for cui"
200   (let ((ustys '())
201         (ls (format nil "select TUI,STY from MRSTY where CUI=~d" cui)))
202     (when srl
203         (string-append ls (format nil " and KLRL <= ~d" srl)))
204     (dolist (tuple (mutex-sql-query ls))
205       (push (make-instance 'usty :tui (ensure-integer (car tuple)) :sty (cadr tuple)) ustys))
206     ustys))
207
208 (defun find-usty-word (word &key (srl *current-srl*))
209   "Return a list of usty that match word"
210   (let ((ustys '())
211         (ls (format nil "select distinct TUI,STY from MRSTY where STY like '%~a%'" word)))
212     (when srl
213         (string-append ls (format nil " and KLRL <= ~d" srl)))
214     (dolist (tuple (mutex-sql-query ls))
215       (push (make-instance 'usty :tui (ensure-integer (car tuple)) :sty (cadr tuple)) ustys))
216     ustys))
217
218 (defun find-urel-cui (cui &key (srl *current-srl*))
219   "Return a list of urel for cui"
220   (let ((urels '())
221         (ls (format nil "select REL,CUI2,RELA,SAB,SL,MG,KPFSTR2 from MRREL where CUI1=~d" cui)))
222     (when srl
223         (string-append ls (format nil " and KSRL <= ~d" srl)))
224     (dolist (tuple (mutex-sql-query ls))
225       (push (make-instance 'urel 
226               :cui1 cui
227               :rel (nth 0 tuple) 
228               :cui2 (ensure-integer (nth 1 tuple))
229               :rela (nth 2 tuple)
230               :sab (nth 3 tuple)
231               :sl (nth 4 tuple)
232               :mg (nth 5 tuple)
233               :pfstr2 (nth 6 tuple))
234             urels))
235     (nreverse urels)))
236
237 (defun find-urel-cui2 (cui2 &key (srl *current-srl*))
238   "Return a list of urel for cui2"
239   (let ((urels '())
240         (ls (format nil "select REL,CUI1,RELA,SAB,SL,MG,KPFSTR2 from MRREL where CUI2=~d" cui2)))
241     (when srl
242         (string-append ls (format nil " and SRL <= ~d" srl)))
243     (dolist (tuple (mutex-sql-query ls))
244       (push (make-instance 'urel 
245               :cui2 cui2
246               :rel (nth 0 tuple) 
247               :cui1 (ensure-integer (nth 1 tuple))
248               :rela (nth 2 tuple)
249               :sab (nth 3 tuple)
250               :sl (nth 4 tuple)
251               :mg (nth 5 tuple)
252               :pfstr2 (nth 6 tuple))
253             urels))
254     (nreverse urels)))
255
256 (defun find-ucon-rel-cui2 (cui2 &key (srl *current-srl*))
257   (mapcar 
258    #'(lambda (cui) (find-ucon-cui cui :srl srl))
259    (remove-duplicates (mapcar #'cui1 (find-urel-cui2 cui2 :srl srl)))))
260
261 (defun find-ucoc-cui (cui &key (srl *current-srl*))
262   "Return a list of ucoc for cui"
263   (let ((ucocs '())
264         (ls (format nil "select CUI2,SOC,COT,COF,COA,KPFSTR2 from MRCOC where CUI1=~d" cui)))
265     (when srl
266         (string-append ls (format nil " and KLRL <= ~d" srl)))
267     (string-append ls " order by COF asc")
268     (dolist (tuple (mutex-sql-query ls))
269       (let ((cui2 (ensure-integer (nth 0 tuple))))
270         (when (zerop cui2)
271           (setq cui2 nil))
272         (push (make-instance 'ucoc :cui1 cui
273                              :cui2 cui2
274                              :soc (nth 1 tuple)
275                              :cot (nth 2 tuple)
276                              :cof (ensure-integer (nth 3 tuple))
277                              :coa (nth 4 tuple)
278                              :pfstr2 (nth 5 tuple))
279               ucocs)))
280     ucocs)) ;; akready ordered by SQL select
281
282 (defun find-ucoc-cui2 (cui2 &key (srl *current-srl*))
283   "Return a list of ucoc for cui2"
284   (let ((ucocs '())
285         (ls (format nil "select CUI1,SOC,COT,COF,COA,KPFSTR2 from MRCOC where CUI2=~d" cui2)))
286     (when srl
287         (string-append ls (format nil " and KSRL <= ~d" srl)))
288     (string-append ls " order by COF asc")
289     (dolist (tuple (mutex-sql-query ls))
290       (push (make-instance 'ucoc :cui1 (ensure-integer (nth 0 tuple))
291                            :cui2 cui2
292                            :soc (nth 1 tuple)
293                            :cot (nth 2 tuple)
294                            :cof (ensure-integer (nth 3 tuple))
295                            :coa (nth 4 tuple)
296                            :pfstr2 (nth 5 tuple))
297             ucocs))
298     ucocs)) ;; already ordered by SQL select
299
300 (defun find-ucon-coc-cui2 (cui2 &key (srl *current-srl*))
301   "List of ucon with co-occurance cui2"
302   (mapcar 
303    #'(lambda (cui) (find-ucon-cui cui :srl srl))
304    (remove-duplicates (mapcar #'cui1 (find-ucoc-cui2 cui2 :srl srl)))))
305
306 (defun find-ulo-cui (cui &key (srl *current-srl*))
307   "Return a list of ulo for cui"
308   (let ((ulos '())
309         (ls (format nil "select ISN,FR,UN,SUI,SNA,SOUI from MRLO where CUI=~d" cui)))
310     (when srl
311         (string-append ls (format nil " and KLRL <= ~d" srl)))
312     (dolist (tuple (mutex-sql-query ls))
313       (push (make-instance 'ulo :isn (nth 0 tuple) 
314                            :fr (ensure-integer (nth 1 tuple))
315                            :un (nth 2 tuple)
316                            :sui (ensure-integer (nth 3 tuple))
317                            :sna (nth 4 tuple)
318                            :soui (nth 5 tuple))
319             ulos))
320     (nreverse ulos)))
321
322 (defgeneric suistr (lo))
323 (defmethod suistr ((lo ulo))
324   "Return the string for a ulo object"
325   (find-string-sui (sui lo)))
326
327 (defun find-uatx-cui (cui &key (srl *current-srl*))
328   "Return a list of uatx for cui"
329   (let ((uatxs '())
330         (ls (format nil "select SAB,REL,ATX from MRATX where CUI=~d" cui)))
331     (when srl
332         (string-append ls (format nil " and KSRL <= ~d" srl)))
333     (dolist (tuple (mutex-sql-query ls))
334       (push (make-instance 'uatx :sab (nth 0 tuple) 
335                            :rel (nth 1 tuple)
336                            :atx (nth 2 tuple))
337             uatxs))
338     (nreverse uatxs)))
339
340
341 (defun find-uterm-cui (cui &key (srl *current-srl*))
342   "Return a list of uterm for cui"
343   (let ((uterms '())
344         (ls (format nil "select distinct LUI,LAT,TS,KLUILRL from MRCON where CUI=~d" cui)))
345     (when srl
346         (string-append ls (format nil " and KLUILRL <= ~d" srl)))
347     (dolist (tuple (mutex-sql-query ls))
348       (push (make-instance 'uterm :lui (ensure-integer (nth 0 tuple))
349                            :cui cui
350                            :lat (nth 1 tuple)
351                            :ts (nth 2 tuple)
352                            :lrl (ensure-integer (nth 3 tuple)))
353         uterms))
354     (nreverse uterms)))
355
356 (defun find-uterm-lui (lui &key (srl *current-srl*))
357   "Return a list of uterm for lui"
358   (if (stringp lui)
359       (setq lui (parse-lui lui)))
360   (let ((uterms '())
361         (ls (format nil "select distinct CUI,LAT,TS,KLUILRL from MRCON where LUI=~d" lui)))
362     (when srl
363         (string-append ls (format nil " and KLUILRL <= ~d" srl)))
364     (dolist (tuple (mutex-sql-query ls))
365       (push (make-instance 'uterm :cui (ensure-integer (nth 0 tuple))
366                            :lui lui
367                            :lat (nth 1 tuple)
368                            :ts (nth 2 tuple)
369                            :lrl (ensure-integer (nth 3 tuple)))
370             uterms))
371     (nreverse uterms)))
372
373 (defun find-uterm-cuilui (cui lui &key (srl *current-srl*))
374   "Return single uterm for cui/lui"
375   (let ((ls (format nil "select LAT,TS,KLUILRL from MRCON where KCUILUI=~d limit 1" (make-cuilui cui lui))))
376     (when srl
377         (string-append ls (format nil " and KLUILRL <= ~d" srl)))
378     (kmrcl:aif (car (mutex-sql-query ls))
379          (make-instance 'uterm :cui cui
380                         :lui lui
381                         :lat (nth 0 kmrcl::it)
382                        :ts (nth 1 kmrcl::it)
383                        :lrl (ensure-integer (nth 2 kmrcl::it)))
384          nil)))
385
386 (defun find-ustr-cuilui (cui lui &key (srl *current-srl*))
387   "Return a list of ustr for cui/lui"
388   (declare (fixnum cui lui))
389   (let ((ustrs '())
390         (ls (format nil "select SUI,STT,STR,LRL from MRCON where KCUILUI=~d" (make-cuilui cui lui))))
391     (when srl
392         (string-append ls (format nil " and LRL <= ~d" srl)))
393     (dolist (tuple (mutex-sql-query ls))
394       (let* ((sui (ensure-integer (car tuple)))
395              (ustr (make-instance 'ustr :sui sui
396                                   :cui cui
397                                   :cuisui (make-cuisui cui sui)
398                                   :lui lui
399                                   :stt (nth 1 tuple)
400                                   :str (nth 2 tuple)
401                                   :lrl (ensure-integer (nth 3 tuple)))))
402         (push ustr ustrs)))
403     (nreverse ustrs)))
404
405 (defun find-ustr-cuisui (cui sui &key (srl *current-srl*))
406   "Return the single ustr for cuisui"
407   (let ((ls (format nil "select LUI,STT,STR,LRL from MRCON where KCUISUI=~d"
408                     (make-cuisui cui sui))))
409     (when srl
410         (string-append ls (format nil " and LRL <= ~d" srl)))
411     (kmrcl:aif (car (mutex-sql-query ls))
412          (make-instance 'ustr :sui sui 
413                         :cui cui
414                         :cuisui (make-cuisui cui sui)
415                         :lui (ensure-integer (nth 0 kmrcl::it))
416                         :stt (nth 1 kmrcl::it)
417                         :str (nth 2 kmrcl::it)
418                         :lrl (ensure-integer (nth 3 kmrcl::it)))
419          nil)))
420
421 (defun find-ustr-sui (sui &key (srl *current-srl*))
422   "Return the list of ustr for sui"
423   (if (stringp sui)
424       (setq sui (parse-sui sui)))
425   (let ((ustrs '())
426         (ls (format nil "select CUI,LUI,STT,STR,LRL from MRCON where SUI=~d" sui)))
427     (when srl
428         (string-append ls (format nil " and LRL <= ~d" srl)))
429     (dolist (tuple (mutex-sql-query ls))
430       (let ((cui (ensure-integer (car tuple))))
431         (push (make-instance 'ustr :sui sui 
432                              :cui cui
433                              :cuisui (make-cuisui cui sui)
434                              :lui (ensure-integer (nth 1 tuple))
435                              :stt (nth 2 tuple)
436                              :str (nth 3 tuple)
437                              :lrl (ensure-integer (nth 4 tuple)))
438         ustrs)))
439     (nreverse ustrs)))
440       
441 (defun find-ustr-sab (sab &key (srl *current-srl*))
442   "Return the list of ustr for sab"
443   (let ((ustrs '())
444         (ls (format nil "select KCUISUI from MRSO where SAB='~a'" sab)))
445     (when srl
446         (string-append ls (format nil " and SRL <= ~d" srl)))
447     (dolist (tuple (mutex-sql-query ls))
448       (let ((cuisui (ensure-integer (car tuple))))
449         (push (apply #'find-ustr-cuisui 
450                      (append
451                       (multiple-value-list (decompose-cuisui cuisui))
452                       (list :srl srl)))
453               ustrs)))
454     (nreverse ustrs)))
455
456 (defun find-ustr-all (&key (srl *current-srl*))
457   "Return list of all ustr's"
458   (let ((ls "select distinct CUI,LUI,SUI,STT,LRL,KPFSTR from MRCON"))
459     (when srl
460       (string-append ls (format nil " where LRL <= ~d" srl)))
461     (string-append ls " order by SUI asc")
462     (with-sql-connection (db)
463       (clsql:map-query 
464        'list
465        #'(lambda (cui lui sui stt lrl pfstr)
466            (setq cui (ensure-integer cui))
467            (setq lui (ensure-integer lui))
468            (setq sui (ensure-integer sui))      
469            (setq lrl (ensure-integer lrl))
470            (make-instance 'ustr :cui cui
471                           :lui lui
472                           :sui sui
473                           :cuisui (make-cuisui cui sui)
474                           :stt stt
475                           :lrl lrl
476                           :str pfstr))
477        ls
478        :database db))))
479
480 (defun find-string-sui (sui &key (srl *current-srl*))
481   "Return the string associated with sui"
482   (let ((ls (format nil "select STR from MRCON where SUI=~d" sui)))
483     (when srl
484       (string-append ls (format nil " and LRL <= ~d" srl)))
485     (string-append ls " limit 1")
486     (caar (mutex-sql-query ls))))
487
488 (defun find-uso-cuisui (cui sui &key (srl *current-srl*))
489   (declare (fixnum cui sui))
490   (let ((usos '())
491         (ls (format nil "select SAB,CODE,SRL,TTY from MRSO where KCUISUI=~d"
492                     (make-cuisui cui sui))))
493     (when srl
494         (string-append ls (format nil " and SRL <= ~d" srl)))
495     (dolist (tuple (mutex-sql-query ls))
496       (push (make-instance 'uso :sab (nth 0 tuple) :code (nth 1 tuple) 
497                            :srl (nth 2 tuple) :tty (nth 3 tuple))
498             usos))
499     (nreverse usos)))
500
501 (defun find-ucxt-cuisui (cui sui &key (srl *current-srl*))
502   (declare (fixnum cui sui))
503   (let ((ucxts '())
504         (ls (format nil "select SAB,CODE,CXN,CXL,RNK,CXS,CUI2,HCD,RELA,XC from MRCXT where KCUISUI=~d" 
505                     (make-cuisui cui sui))))
506     (when srl
507         (string-append ls (format nil " and KSRL <= ~d" srl)))
508     (dolist (tuple (mutex-sql-query ls))
509       (push (make-instance 'ucxt :sab (nth 0 tuple) 
510                            :code (nth 1 tuple) 
511                            :cxn (ensure-integer (nth 2 tuple))
512                            :cxl (nth 3 tuple)
513                            :rnk (ensure-integer (nth 4 tuple))
514                            :cxs (nth 5 tuple)
515                            :cui2 (ensure-integer (nth 6 tuple))
516                            :hcd (nth 7 tuple)
517                            :rela (nth 8 tuple)
518                            :xc (nth 9 tuple))
519             ucxts))
520     (nreverse ucxts)))
521
522 (defun find-usat-ui (cui &optional (lui nil) (sui nil) &key (srl *current-srl*))
523   (let ((ls (format nil "select CODE,ATN,SAB,ATV from MRSAT where ")))
524     (cond
525      (sui (string-append ls (format nil "KCUISUI=~d" (make-cuisui cui sui))))
526      (lui (string-append ls (format nil "KCUILUI=~d and sui=0" (make-cuilui cui lui))))
527      (t (string-append ls (format nil "cui=~d and lui=0 and sui=0" cui))))
528     (when srl
529         (string-append ls (format nil " and KSRL <= ~d" srl)))
530     (let ((usats '()))
531       (dolist (tuple (mutex-sql-query ls))
532         (push (make-instance 'usat :code (nth 0 tuple)
533                              :atn (nth 1 tuple)
534                              :sab (nth 2 tuple)
535                              :atv (nth 3 tuple))
536               usats))
537       (nreverse usats))))
538
539
540 (defun find-pfstr-cui (cui)
541   (caar (mutex-sql-query (format nil "select KPFSTR from MRCON where CUI=~d limit 1" cui))))
542
543 (defun find-usty-tui (tui)
544   "Find usty for tui"
545   (setq tui (parse-tui tui)) 
546     (kmrcl:aif (car (mutex-sql-query 
547                (format nil "select STY from MRSTY where TUI=~d limit 1" tui)))
548          (make-instance 'usty :tui tui :sty (nth 0 kmrcl::it))
549          nil))
550
551 (defun find-usty-sty (sty)
552   "Find usty for a sty"
553   (kmrcl:aif (car (mutex-sql-query 
554                 (format nil "select TUI from MRSTY where STY='~a' limit 1" sty)))
555           (make-instance 'usty :tui (ensure-integer (nth 0 kmrcl::it)) :sty sty)
556           nil))
557
558 (defun find-usty-all ()
559   "Return list of usty's for all semantic types"
560   (let ((ustys '()))
561     (dolist (tuple (mutex-sql-query "select distinct TUI from MRSTY"))
562       (push (find-usty-tui (nth 0 tuple)) ustys))
563     (nreverse ustys)))
564
565
566 (defun find-cui-max ()
567   (let ((cui (caar (mutex-sql-query "select max(CUI) from MRCON"))))
568     (ensure-integer cui)))
569
570 ;;;; Cross table find functions
571
572 (defun find-ucon-tui (tui &key (srl *current-srl*))
573   "Find list of ucon for tui"
574   (when (stringp tui)
575       (setq tui (parse-tui tui)))
576   (let ((ucons '())
577         (ls (format nil "select CUI from MRSTY where TUI=~d" tui)))
578     (when srl
579         (string-append ls (format nil " and KLRL <= ~d" srl)))
580     (string-append ls " order by cui desc")
581     (dolist (tuple (mutex-sql-query ls))
582       (push (find-ucon-cui (ensure-integer (car tuple)) :srl srl) ucons))
583     ucons))
584   
585 (defun find-ucon-word (word &key (srl *current-srl*) (like nil))
586   "Return list of ucons that match word. Optionally, use SQL's LIKE syntax"
587   (let ((ucons '())
588         (ls (format nil "select distinct cui from MRXW_ENG where wd~A'~A'" 
589                     (if like " LIKE " "=") 
590                     word)))
591     (when srl
592       (string-append ls (format nil " and KLRL <= ~d" srl)))
593     (string-append ls " order by cui desc")
594     (dolist (tuple (mutex-sql-query ls))
595       (push (find-ucon-cui (car tuple) :srl srl) ucons))
596     ucons))
597
598 (defun find-ucon-normalized-word (word &key (srl *current-srl*) (like nil))
599   "Return list of ucons that match word, optionally use SQL's LIKE syntax"
600   (let ((ucons '())
601         (ls (format nil "select distinct cui from MRXNW_ENG where nwd~A'~A'" 
602                     (if like " LIKE " "=")
603                     word)))
604     (when srl
605       (string-append ls (format nil " and KLRL <= ~d" srl)))
606     (string-append ls " order by cui desc")
607     (dolist (tuple (mutex-sql-query ls))
608       (push (find-ucon-cui (car tuple) :srl srl) ucons))
609     ucons))
610
611 (defun find-ustr-word (word &key (srl *current-srl*))
612   "Return list of ustrs that match word"
613   (let ((ustrs '())
614         (ls (format nil "select cui,sui from MRXW_ENG where wd='~a'" word)))
615     (when srl
616         (string-append ls (format nil " and KLRL <= ~d" srl)))
617     (string-append ls " order by cui desc,sui desc")
618     (dolist (tuple (mutex-sql-query ls))
619       (push (find-ustr-cuisui (ensure-integer (car tuple)) (ensure-integer (cadr tuple)) :srl srl)
620             ustrs))
621     ustrs))
622
623 (defun find-ustr-normalized-word (word &key (srl *current-srl*))
624   "Return list of ustrs that match word"
625   (let ((ustrs '())
626         (ls (format nil "select cui,sui from MRXNW_ENG where nwd='~a'" word)))
627     (when srl
628         (string-append ls (format nil " and KLRL <= ~d" srl)))
629     (string-append ls " order by cui desc,sui desc")
630     (dolist (tuple (mutex-sql-query ls))
631       (push (find-ustr-cuisui (ensure-integer (car tuple)) (ensure-integer (cadr tuple)) :srl srl)
632             ustrs))
633     ustrs))
634
635 ;; Special tables
636
637 (defun find-usrl-all ()
638   (let ((usrls '())
639         (tuples (mutex-sql-query "select SAB,SRL from USRL order by SAB desc")))
640     (dolist (tuple tuples)
641       (push (make-instance 'usrl :sab (nth 0 tuple)
642                            :srl (ensure-integer (nth 1 tuple))) usrls))
643     usrls))
644
645 ;;; Multiword lookup and score functions
646
647 (defun find-ucon-multiword (str &key (srl *current-srl*))
648   "Return sorted list of ucon's that match a multiword string"
649   (let* ((words (delimited-string-to-list str #\space))
650          (ucons '()))
651     (dolist (word words)
652       (setq ucons (append ucons (find-ucon-word word :srl srl))))
653     (sort-score-ucon-str str (delete-duplicates ucons :test #'eql :key #'cui))))
654
655 (defun find-ustr-multiword (str &key (srl *current-srl*))
656   "Return sorted list of ustr's that match a multiword string"
657   (let* ((words (delimited-string-to-list str #\space))
658          (ustrs '()))
659     (dolist (word words)
660       (setq ustrs (append ustrs (find-ustr-word word :srl srl))))
661     (sort-score-ustr-str str (delete-duplicates ustrs :test #'eql :key #'cui))))
662         
663 (defun sort-score-ucon-str (str ucons)
664   "Return list of sorted and scored ucons. Score by match of str to ucon-pfstr"
665   (sort-score-umlsclass-str ucons str #'pfstr))
666
667 (defun sort-score-ustr-str (str ustrs)
668   "Return list of sorted and scored ucons. Score by match of str to ucon-pfstr"
669   (sort-score-umlsclass-str ustrs str #'str))
670
671 (defun sort-score-umlsclass-str (objs str lookup-func)
672   "Sort a list of objects based on scoring to a string"
673   (let ((scored '()))
674     (dolist (obj objs)
675       (push 
676        (list obj 
677              (score-multiword-match str (funcall lookup-func obj))) 
678        scored))
679     (mapcar #'car (sort scored #'> :key #'cadr))))
680
681 (defun score-multiword-match (s1 s2)
682   "Score a match between two strings with s1 being reference string"
683   (let* ((word-list-1 (delimited-string-to-list s1 #\space))
684          (word-list-2 (delimited-string-to-list s2 #\space))
685          (n1 (length word-list-1))
686          (n2 (length word-list-2))
687          (unmatched n1)
688          (score 0)
689          (nlong 0)
690          (nshort 0)
691          short-list long-list)
692     (declare (fixnum n1 n2 nshort nlong score unmatched))
693     (if (> n1 n2)
694         (progn
695           (setq nlong n1)
696           (setq nshort n2)
697           (setq long-list word-list-1)
698           (setq short-list word-list-2))
699       (progn
700         (setq nlong n2)
701         (setq nshort n1)
702         (setq long-list word-list-2)
703         (setq short-list word-list-1)))
704     (decf score (- nlong nshort)) ;; reduce score for extra words
705     (dotimes (iword nshort)
706       (declare (fixnum iword))
707       (kmrcl:aif (position (nth iword short-list) long-list :test #'string-equal)
708            (progn
709              (incf score (- 10 (abs (- kmrcl::it iword))))
710              (decf unmatched))))
711     (decf score (* 2 unmatched))
712     score))
713
714
715 ;;; LEX SQL functions
716
717 (defun find-lexterm-eui (eui)
718   (kmrcl:awhen (car (mutex-sql-query
719                   (format nil "select WRD from LRWD where EUI=~d" eui)))
720             (make-instance 'lexterm :eui eui :wrd (nth 0 kmrcl:it))))
721
722 (defun find-lexterm-word (wrd)
723   (kmrcl:awhen (mutex-sql-query
724              (format nil "select EUI from LRWD where WRD='~a'" wrd))
725             (let ((terms '()))
726               (dolist (tuple kmrcl:it)
727                 (let ((eui (ensure-integer (nth 0 tuple))))
728                   (push
729                    (make-instance 'lexterm :eui eui :wrd (copy-seq wrd))
730                    terms)))
731               (nreverse terms))))
732
733 ;; LEXTERM accessors, read on demand
734               
735 (def-lazy-reader lexterm s#abr find-labr-eui eui)
736 (def-lazy-reader lexterm s#agr find-lagr-eui eui)
737 (def-lazy-reader lexterm s#cmp find-lcmp-eui eui)
738 (def-lazy-reader lexterm s#mod find-lmod-eui eui)
739 (def-lazy-reader lexterm s#nom find-lnom-eui eui)
740 (def-lazy-reader lexterm s#prn find-lprn-eui eui)
741 (def-lazy-reader lexterm s#prp find-lprp-eui eui)
742 (def-lazy-reader lexterm s#spl find-lspl-eui eui)
743 (def-lazy-reader lexterm s#trm find-ltrm-eui eui)
744 (def-lazy-reader lexterm s#typ find-ltyp-eui eui)
745
746 ;; LEX SQL Read functions
747
748 (defun find-labr-eui (eui)
749     (kmrcl:awhen (mutex-sql-query 
750                (format nil "select BAS,ABR,EUI2,BAS2 from LRABR where EUI=~d" eui))
751               (let ((results '()))
752                 (dolist (tuple kmrcl::it)
753                   (push
754                    (make-instance 'labr :eui eui 
755                                   :bas (nth 0 tuple) 
756                                   :abr (nth 1 tuple)
757                                   :eui2 (ensure-integer (nth 2 tuple))
758                                   :bas2 (nth 3 tuple))
759                    results))
760                 (nreverse results))))
761
762 (defun find-labr-bas (bas)
763   (kmrcl:awhen (mutex-sql-query 
764                (format nil "select EUI,ABR,EUI2,BAS2 from LRABR where BAS='~a'" bas))
765               (let ((results '()))
766                 (dolist (tuple kmrcl::it)
767                   (push
768                    (make-instance 'labr :eui (ensure-integer (nth 0 tuple))
769                                   :bas (copy-seq bas)
770                                   :abr (nth 1 tuple)
771                                   :eui2 (ensure-integer (nth 2 tuple))
772                                   :bas2 (nth 3 tuple))
773                    results))
774                 (nreverse results))))
775
776 (defun find-lagr-eui (eui)
777   (kmrcl:awhen (mutex-sql-query 
778                (format nil "select STR,SCA,AGR,CIT,BAS from LRAGR where EUI=~d" eui))
779               (let ((results '()))
780                 (dolist (tuple kmrcl::it)
781                   (push
782                    (make-instance 'lagr 
783                                   :eui eui
784                                   :str (nth 0 tuple)
785                                   :sca (nth 1 tuple)
786                                   :agr (nth 2 tuple)
787                                   :cit (nth 3 tuple)
788                                   :bas (nth 4 tuple))
789                    results))
790                 (nreverse results))))
791
792 (defun find-lcmp-eui (eui)
793   (kmrcl:awhen (mutex-sql-query 
794                (format nil "select BAS,SCA,COM from LRCMP where EUI=~d" eui))
795               (let ((results '()))
796                 (dolist (tuple kmrcl::it)
797                   (push
798                    (make-instance 'lcmp
799                                   :eui eui
800                                   :bas (nth 0 tuple)
801                                   :sca (nth 1 tuple)
802                                   :com (nth 2 tuple))
803                    results))
804                 (nreverse results))))
805
806 (defun find-lmod-eui (eui)
807   (kmrcl:awhen (mutex-sql-query 
808                (format nil "select BAS,SCA,PSN_MOD,FEA from LRMOD where EUI=~d" eui))
809               (let ((results '()))
810                 (dolist (tuple kmrcl::it)
811                   (push
812                    (make-instance 'lmod
813                                   :eui eui
814                                   :bas (nth 0 tuple)
815                                   :sca (nth 1 tuple)
816                                   :psnmod (nth 2 tuple)
817                                   :fea (nth 3 tuple))
818                    results))
819                 (nreverse results))))
820
821 (defun find-lnom-eui (eui)
822   (kmrcl:awhen (mutex-sql-query 
823                (format nil "select BAS,SCA,EUI2,BAS2,SCA2 from LRNOM where EUI=~d" eui))
824               (let ((results '()))
825                 (dolist (tuple kmrcl::it)
826                   (push
827                    (make-instance 'lnom
828                                   :eui eui
829                                   :bas (nth 0 tuple)
830                                   :sca (nth 1 tuple)
831                                   :eui2 (ensure-integer (nth 2 tuple))
832                                   :bas2 (nth 3 tuple)
833                                   :sca2 (nth 4 tuple))
834                    results))
835                 (nreverse results))))
836
837 (defun find-lprn-eui (eui)
838   (kmrcl:awhen (mutex-sql-query 
839                (format nil "select BAS,NUM,GND,CAS,POS,QNT,FEA from LRPRN where EUI=~d" eui))
840               (let ((results '()))
841                 (dolist (tuple kmrcl::it)
842                   (push
843                    (make-instance 'lprn
844                                   :eui eui
845                                   :bas (nth 0 tuple)
846                                   :num (nth 1 tuple)
847                                   :gnd (nth 2 tuple)
848                                   :cas (nth 3 tuple)
849                                   :pos (nth 4 tuple)
850                                   :qnt (nth 5 tuple)
851                                   :fea (nth 6 tuple))
852                    results))
853                 (nreverse results))))
854
855 (defun find-lprp-eui (eui)
856   (kmrcl:awhen (mutex-sql-query 
857                (format nil "select BAS,STR,SCA,FEA from LRPRP where EUI=~d" eui))
858               (let ((results '()))
859                 (dolist (tuple kmrcl::it)
860                   (push
861                    (make-instance 'lprp
862                                   :eui eui
863                                   :bas (nth 0 tuple)
864                                   :str (nth 1 tuple)
865                                   :sca (nth 2 tuple)
866                                   :fea (nth 3 tuple))
867                    results))
868                 (nreverse results))))
869
870 (defun find-lspl-eui (eui)
871   (kmrcl:awhen (mutex-sql-query 
872                (format nil "select SPV,BAS from LRSPL where EUI=~d" eui))
873               (let ((results '()))
874                 (dolist (tuple kmrcl::it)
875                   (push
876                    (make-instance 'lspl
877                                   :eui eui
878                                   :spv (nth 0 tuple)
879                                   :bas (nth 1 tuple))
880                    results))
881                 (nreverse results))))
882
883
884 (defun find-ltrm-eui (eui)
885   (kmrcl:awhen (mutex-sql-query 
886                (format nil "select BAS,GEN from LRTRM where EUI=~d" eui))
887               (let ((results '()))
888                 (dolist (tuple kmrcl::it)
889                   (push
890                    (make-instance 'ltrm
891                                   :eui eui
892                                   :bas (nth 0 tuple)
893                                   :gen (nth 1 tuple))
894                    results))
895                 (nreverse results))))
896
897 (defun find-ltyp-eui (eui)
898   (kmrcl:awhen (mutex-sql-query 
899                (format nil "select BAS,SCA,TYP from LRTYP where EUI=~d" eui))
900               (let ((results '()))
901                 (dolist (tuple kmrcl::it)
902                   (push
903                    (make-instance 'ltyp
904                                   :eui eui
905                                   :bas (nth 0 tuple)
906                                   :sca (nth 1 tuple)
907                                   :typ (nth 2 tuple))
908                    results))
909                 (nreverse results))))
910
911 (defun find-lwd-wrd (wrd)
912   (kmrcl:awhen (mutex-sql-query 
913              (format nil "select EUI from LRWD where WRD='~a'" wrd))
914               (let ((results '()))
915                 (dolist (tuple kmrcl::it)
916                   (push (ensure-integer (nth 0 tuple)) results))
917                 (make-instance 'lwd :wrd wrd
918                                :euilist (nreverse results)))))
919
920 ;;; Semantic Network SQL access functions
921  
922 (defun find-sdef-ui (ui)
923   (kmrcl:awhen (car (mutex-sql-query 
924                   (format nil "select RT,STY_RL,STN_RTN,DEF,EX,UN,RH,ABR,RIN from SRDEF where UI=~d" ui)))
925             (make-instance 'sdef :rt (nth 0 kmrcl::it)
926                            :ui ui
927                            :styrl (nth 1 kmrcl::it)
928                            :stnrtn (nth 2 kmrcl::it)
929                            :def (nth 3 kmrcl::it)
930                            :ex (nth 4 kmrcl::it)
931                            :un (nth 5 kmrcl::it)
932                            :rh (nth 6 kmrcl::it)
933                            :abr (nth 7 kmrcl::it)
934                            :rin (nth 8 kmrcl::it))))
935
936 (defun find-sstre1-ui (ui)
937   (kmrcl:awhen (mutex-sql-query 
938                (format nil "select UI2,UI3 from SRSTRE1 where UI=~d" ui))
939               (let ((results '()))
940                 (dolist (tuple kmrcl::it)
941                   (push
942                    (make-instance 'sstre1 :ui ui
943                                   :ui2 (ensure-integer (nth 0 tuple))
944                                   :ui3 (ensure-integer (nth 1 tuple)))
945                    results))
946                 (nreverse results))))
947
948 (defun find-sstre1-ui2 (ui2)
949   (kmrcl:awhen (mutex-sql-query 
950                (format nil "select UI,UI3 from SRSTRE1 where UI2=~d" ui2))
951               (let ((results '()))
952                 (dolist (tuple kmrcl::it)
953                   (push
954                    (make-instance 'sstre1 :ui (ensure-integer (nth 0 tuple))
955                                   :ui2 ui2
956                                   :ui3 (ensure-integer (nth 1 tuple)))
957                    results))
958                 (nreverse results))))
959
960 (defun find-sstr-rl (rl)
961   (kmrcl:awhen (mutex-sql-query 
962                (format nil "select STY_RL,STY_RL2,LS from SRSTRE where RL='~a'" rl))
963               (let ((results '()))
964                 (dolist (tuple kmrcl::it)
965                   (push
966                    (make-instance 'sstr 
967                                   :rl rl
968                                   :styrl (nth 0 tuple)
969                                   :styrl2 (nth 1 tuple)
970                                   :ls (nth 2 tuple))
971                    results))
972                 (nreverse results))))
973
974
975 (defun find-sstre2-sty (sty)
976   (kmrcl:awhen (mutex-sql-query 
977              (format nil "select RL,STY2 from SRSTRE2 where STY='~a'" sty))
978             (let ((results '()))
979               (dolist (tuple kmrcl::it)
980                 (push
981                  (make-instance 'sstre2
982                                 :sty (copy-seq sty)
983                                 :rl (nth 0 tuple)
984                                 :sty2 (nth 1 tuple))
985                                 results))
986                 (nreverse results))))
987
988 (defun find-sstr-styrl (styrl)
989   (kmrcl:awhen (mutex-sql-query 
990                (format nil "select RL,STY_RL2,LS from SRSTR where RL='~a'" styrl))
991               (let ((results '()))
992                 (dolist (tuple kmrcl::it)
993                   (push
994                    (make-instance 'sstr :styrl styrl
995                                   :rl (nth 0 tuple)
996                                   :styrl2 (nth 1 tuple)
997                                   :ls (nth 2 tuple))
998                    results))
999                 (nreverse results))))
1000
1001