r3067: *** 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.5 2002/10/14 15:25:11 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
636 ;;; Multiword lookup and score functions
637
638 (defun find-ucon-multiword (str &key (srl *current-srl*))
639   "Return sorted list of ucon's that match a multiword string"
640   (let* ((words (delimited-string-to-list str #\space))
641          (ucons '()))
642     (dolist (word words)
643       (setq ucons (append ucons (find-ucon-word word :srl srl))))
644     (sort-score-ucon-str str (delete-duplicates ucons :test #'eql :key #'cui))))
645
646 (defun find-ustr-multiword (str &key (srl *current-srl*))
647   "Return sorted list of ustr's that match a multiword string"
648   (let* ((words (delimited-string-to-list str #\space))
649          (ustrs '()))
650     (dolist (word words)
651       (setq ustrs (append ustrs (find-ustr-word word :srl srl))))
652     (sort-score-ustr-str str (delete-duplicates ustrs :test #'eql :key #'cui))))
653         
654 (defun sort-score-ucon-str (str ucons)
655   "Return list of sorted and scored ucons. Score by match of str to ucon-pfstr"
656   (sort-score-umlsclass-str ucons str #'pfstr))
657
658 (defun sort-score-ustr-str (str ustrs)
659   "Return list of sorted and scored ucons. Score by match of str to ucon-pfstr"
660   (sort-score-umlsclass-str ustrs str #'str))
661
662 (defun sort-score-umlsclass-str (objs str lookup-func)
663   "Sort a list of objects based on scoring to a string"
664   (let ((scored '()))
665     (dolist (obj objs)
666       (push 
667        (list obj 
668              (score-multiword-match str (funcall lookup-func obj))) 
669        scored))
670     (mapcar #'car (sort scored #'> :key #'cadr))))
671
672 (defun score-multiword-match (s1 s2)
673   "Score a match between two strings with s1 being reference string"
674   (let* ((word-list-1 (delimited-string-to-list s1 #\space))
675          (word-list-2 (delimited-string-to-list s2 #\space))
676          (n1 (length word-list-1))
677          (n2 (length word-list-2))
678          (unmatched n1)
679          (score 0)
680          (nlong 0)
681          (nshort 0)
682          short-list long-list)
683     (declare (fixnum n1 n2 nshort nlong score unmatched))
684     (if (> n1 n2)
685         (progn
686           (setq nlong n1)
687           (setq nshort n2)
688           (setq long-list word-list-1)
689           (setq short-list word-list-2))
690       (progn
691         (setq nlong n2)
692         (setq nshort n1)
693         (setq long-list word-list-2)
694         (setq short-list word-list-1)))
695     (decf score (- nlong nshort)) ;; reduce score for extra words
696     (dotimes (iword nshort)
697       (declare (fixnum iword))
698       (kmrcl:aif (position (nth iword short-list) long-list :test #'string-equal)
699            (progn
700              (incf score (- 10 (abs (- kmrcl::it iword))))
701              (decf unmatched))))
702     (decf score (* 2 unmatched))
703     score))
704
705
706 ;;; LEX SQL functions
707
708 (defun find-lexterm-eui (eui)
709   (kmrcl:awhen (car (mutex-sql-query
710                   (format nil "select WRD from LRWD where EUI=~d" eui)))
711             (make-instance 'lexterm :eui eui :wrd (nth 0 kmrcl:it))))
712
713 (defun find-lexterm-word (wrd)
714   (kmrcl:awhen (mutex-sql-query
715              (format nil "select EUI from LRWD where WRD='~a'" wrd))
716             (let ((terms '()))
717               (dolist (tuple kmrcl:it)
718                 (let ((eui (ensure-integer (nth 0 tuple))))
719                   (push
720                    (make-instance 'lexterm :eui eui :wrd (copy-seq wrd))
721                    terms)))
722               (nreverse terms))))
723
724 ;; LEXTERM accessors, read on demand
725               
726 (def-lazy-reader lexterm s#abr find-labr-eui eui)
727 (def-lazy-reader lexterm s#agr find-lagr-eui eui)
728 (def-lazy-reader lexterm s#cmp find-lcmp-eui eui)
729 (def-lazy-reader lexterm s#mod find-lmod-eui eui)
730 (def-lazy-reader lexterm s#nom find-lnom-eui eui)
731 (def-lazy-reader lexterm s#prn find-lprn-eui eui)
732 (def-lazy-reader lexterm s#prp find-lprp-eui eui)
733 (def-lazy-reader lexterm s#spl find-lspl-eui eui)
734 (def-lazy-reader lexterm s#trm find-ltrm-eui eui)
735 (def-lazy-reader lexterm s#typ find-ltyp-eui eui)
736
737 ;; LEX SQL Read functions
738
739 (defun find-labr-eui (eui)
740     (kmrcl:awhen (mutex-sql-query 
741                (format nil "select BAS,ABR,EUI2,BAS2 from LRABR where EUI=~d" eui))
742               (let ((results '()))
743                 (dolist (tuple kmrcl::it)
744                   (push
745                    (make-instance 'labr :eui eui 
746                                   :bas (nth 0 tuple) 
747                                   :abr (nth 1 tuple)
748                                   :eui2 (ensure-integer (nth 2 tuple))
749                                   :bas2 (nth 3 tuple))
750                    results))
751                 (nreverse results))))
752
753 (defun find-labr-bas (bas)
754   (kmrcl:awhen (mutex-sql-query 
755                (format nil "select EUI,ABR,EUI2,BAS2 from LRABR where BAS='~a'" bas))
756               (let ((results '()))
757                 (dolist (tuple kmrcl::it)
758                   (push
759                    (make-instance 'labr :eui (ensure-integer (nth 0 tuple))
760                                   :bas (copy-seq bas)
761                                   :abr (nth 1 tuple)
762                                   :eui2 (ensure-integer (nth 2 tuple))
763                                   :bas2 (nth 3 tuple))
764                    results))
765                 (nreverse results))))
766
767 (defun find-lagr-eui (eui)
768   (kmrcl:awhen (mutex-sql-query 
769                (format nil "select STR,SCA,AGR,CIT,BAS from LRAGR where EUI=~d" eui))
770               (let ((results '()))
771                 (dolist (tuple kmrcl::it)
772                   (push
773                    (make-instance 'lagr 
774                                   :eui eui
775                                   :str (nth 0 tuple)
776                                   :sca (nth 1 tuple)
777                                   :agr (nth 2 tuple)
778                                   :cit (nth 3 tuple)
779                                   :bas (nth 4 tuple))
780                    results))
781                 (nreverse results))))
782
783 (defun find-lcmp-eui (eui)
784   (kmrcl:awhen (mutex-sql-query 
785                (format nil "select BAS,SCA,COM from LRCMP where EUI=~d" eui))
786               (let ((results '()))
787                 (dolist (tuple kmrcl::it)
788                   (push
789                    (make-instance 'lcmp
790                                   :eui eui
791                                   :bas (nth 0 tuple)
792                                   :sca (nth 1 tuple)
793                                   :com (nth 2 tuple))
794                    results))
795                 (nreverse results))))
796
797 (defun find-lmod-eui (eui)
798   (kmrcl:awhen (mutex-sql-query 
799                (format nil "select BAS,SCA,PSN_MOD,FEA from LRMOD where EUI=~d" eui))
800               (let ((results '()))
801                 (dolist (tuple kmrcl::it)
802                   (push
803                    (make-instance 'lmod
804                                   :eui eui
805                                   :bas (nth 0 tuple)
806                                   :sca (nth 1 tuple)
807                                   :psnmod (nth 2 tuple)
808                                   :fea (nth 3 tuple))
809                    results))
810                 (nreverse results))))
811
812 (defun find-lnom-eui (eui)
813   (kmrcl:awhen (mutex-sql-query 
814                (format nil "select BAS,SCA,EUI2,BAS2,SCA2 from LRNOM where EUI=~d" eui))
815               (let ((results '()))
816                 (dolist (tuple kmrcl::it)
817                   (push
818                    (make-instance 'lnom
819                                   :eui eui
820                                   :bas (nth 0 tuple)
821                                   :sca (nth 1 tuple)
822                                   :eui2 (ensure-integer (nth 2 tuple))
823                                   :bas2 (nth 3 tuple)
824                                   :sca2 (nth 4 tuple))
825                    results))
826                 (nreverse results))))
827
828 (defun find-lprn-eui (eui)
829   (kmrcl:awhen (mutex-sql-query 
830                (format nil "select BAS,NUM,GND,CAS,POS,QNT,FEA from LRPRN where EUI=~d" eui))
831               (let ((results '()))
832                 (dolist (tuple kmrcl::it)
833                   (push
834                    (make-instance 'lprn
835                                   :eui eui
836                                   :bas (nth 0 tuple)
837                                   :num (nth 1 tuple)
838                                   :gnd (nth 2 tuple)
839                                   :cas (nth 3 tuple)
840                                   :pos (nth 4 tuple)
841                                   :qnt (nth 5 tuple)
842                                   :fea (nth 6 tuple))
843                    results))
844                 (nreverse results))))
845
846 (defun find-lprp-eui (eui)
847   (kmrcl:awhen (mutex-sql-query 
848                (format nil "select BAS,STR,SCA,FEA from LRPRP where EUI=~d" eui))
849               (let ((results '()))
850                 (dolist (tuple kmrcl::it)
851                   (push
852                    (make-instance 'lprp
853                                   :eui eui
854                                   :bas (nth 0 tuple)
855                                   :str (nth 1 tuple)
856                                   :sca (nth 2 tuple)
857                                   :fea (nth 3 tuple))
858                    results))
859                 (nreverse results))))
860
861 (defun find-lspl-eui (eui)
862   (kmrcl:awhen (mutex-sql-query 
863                (format nil "select SPV,BAS from LRSPL where EUI=~d" eui))
864               (let ((results '()))
865                 (dolist (tuple kmrcl::it)
866                   (push
867                    (make-instance 'lspl
868                                   :eui eui
869                                   :spv (nth 0 tuple)
870                                   :bas (nth 1 tuple))
871                    results))
872                 (nreverse results))))
873
874
875 (defun find-ltrm-eui (eui)
876   (kmrcl:awhen (mutex-sql-query 
877                (format nil "select BAS,GEN from LRTRM where EUI=~d" eui))
878               (let ((results '()))
879                 (dolist (tuple kmrcl::it)
880                   (push
881                    (make-instance 'ltrm
882                                   :eui eui
883                                   :bas (nth 0 tuple)
884                                   :gen (nth 1 tuple))
885                    results))
886                 (nreverse results))))
887
888 (defun find-ltyp-eui (eui)
889   (kmrcl:awhen (mutex-sql-query 
890                (format nil "select BAS,SCA,TYP from LRTYP where EUI=~d" eui))
891               (let ((results '()))
892                 (dolist (tuple kmrcl::it)
893                   (push
894                    (make-instance 'ltyp
895                                   :eui eui
896                                   :bas (nth 0 tuple)
897                                   :sca (nth 1 tuple)
898                                   :typ (nth 2 tuple))
899                    results))
900                 (nreverse results))))
901
902 (defun find-lwd-wrd (wrd)
903   (kmrcl:awhen (mutex-sql-query 
904              (format nil "select EUI from LRWD where WRD='~a'" wrd))
905               (let ((results '()))
906                 (dolist (tuple kmrcl::it)
907                   (push (ensure-integer (nth 0 tuple)) results))
908                 (make-instance 'lwd :wrd wrd
909                                :euilist (nreverse results)))))
910
911 ;;; Semantic Network SQL access functions
912  
913 (defun find-sdef-ui (ui)
914   (kmrcl:awhen (car (mutex-sql-query 
915                   (format nil "select RT,STY_RL,STN_RTN,DEF,EX,UN,RH,ABR,RIN from SRDEF where UI=~d" ui)))
916             (make-instance 'sdef :rt (nth 0 kmrcl::it)
917                            :ui ui
918                            :styrl (nth 1 kmrcl::it)
919                            :stnrtn (nth 2 kmrcl::it)
920                            :def (nth 3 kmrcl::it)
921                            :ex (nth 4 kmrcl::it)
922                            :un (nth 5 kmrcl::it)
923                            :rh (nth 6 kmrcl::it)
924                            :abr (nth 7 kmrcl::it)
925                            :rin (nth 8 kmrcl::it))))
926
927 (defun find-sstre1-ui (ui)
928   (kmrcl:awhen (mutex-sql-query 
929                (format nil "select UI2,UI3 from SRSTRE1 where UI=~d" ui))
930               (let ((results '()))
931                 (dolist (tuple kmrcl::it)
932                   (push
933                    (make-instance 'sstre1 :ui ui
934                                   :ui2 (ensure-integer (nth 0 tuple))
935                                   :ui3 (ensure-integer (nth 1 tuple)))
936                    results))
937                 (nreverse results))))
938
939 (defun find-sstre1-ui2 (ui2)
940   (kmrcl:awhen (mutex-sql-query 
941                (format nil "select UI,UI3 from SRSTRE1 where UI2=~d" ui2))
942               (let ((results '()))
943                 (dolist (tuple kmrcl::it)
944                   (push
945                    (make-instance 'sstre1 :ui (ensure-integer (nth 0 tuple))
946                                   :ui2 ui2
947                                   :ui3 (ensure-integer (nth 1 tuple)))
948                    results))
949                 (nreverse results))))
950
951 (defun find-sstr-rl (rl)
952   (kmrcl:awhen (mutex-sql-query 
953                (format nil "select STY_RL,STY_RL2,LS from SRSTRE where RL='~a'" rl))
954               (let ((results '()))
955                 (dolist (tuple kmrcl::it)
956                   (push
957                    (make-instance 'sstr 
958                                   :rl rl
959                                   :styrl (nth 0 tuple)
960                                   :styrl2 (nth 1 tuple)
961                                   :ls (nth 2 tuple))
962                    results))
963                 (nreverse results))))
964
965
966 (defun find-sstre2-sty (sty)
967   (kmrcl:awhen (mutex-sql-query 
968              (format nil "select RL,STY2 from SRSTRE2 where STY='~a'" sty))
969             (let ((results '()))
970               (dolist (tuple kmrcl::it)
971                 (push
972                  (make-instance 'sstre2
973                                 :sty (copy-seq sty)
974                                 :rl (nth 0 tuple)
975                                 :sty2 (nth 1 tuple))
976                                 results))
977                 (nreverse results))))
978
979 (defun find-sstr-styrl (styrl)
980   (kmrcl:awhen (mutex-sql-query 
981                (format nil "select RL,STY_RL2,LS from SRSTR where RL='~a'" styrl))
982               (let ((results '()))
983                 (dolist (tuple kmrcl::it)
984                   (push
985                    (make-instance 'sstr :styrl styrl
986                                   :rl (nth 0 tuple)
987                                   :styrl2 (nth 1 tuple)
988                                   :ls (nth 2 tuple))
989                    results))
990                 (nreverse results))))
991
992