r4793: Auto commit for Debian build
[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 ;;;; Author:        Kevin M. Rosenberg
8 ;;;; Date Started:  Apr 2000
9 ;;;;
10 ;;;; $Id: sql-classes.lisp,v 1.67 2003/05/04 01:42:20 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 (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 ;; only WHERE-VALUE and SRL are evaluated
30 (defmacro with-umlisp-query ((table fields srl where-name where-value
31                                     &key (lrl "KCUILRL") distinct single
32                                     order like)
33                              &body body)
34   (let ((value (gensym)))
35     (if single
36         `(let ((,value ,where-value))
37           (when ,value 
38             (let ((tuple (car (umlisp-query ,table ,fields ,srl ,where-name ,value
39                                             :lrl ,lrl :single ,single
40                                             :distinct ,distinct :order ,order
41                                             :like ,like))))
42               (when tuple
43                 (destructuring-bind ,fields tuple
44                   ,@body)))))
45         `(let ((,value ,where-value))
46           (when ,value 
47             (loop for tuple in
48                   (umlisp-query ,table ,fields ,srl ,where-name ,value
49                                 :lrl ,lrl :single ,single :distinct ,distinct
50                                 :order ,order :like ,like)
51                   collect (destructuring-bind ,fields tuple
52                             ,@body)))))))
53
54 (defmacro with-umlisp-query-eval ((table fields srl where-name where-value
55                                          &key (lrl "KCUILRL") distinct single
56                                          order like)
57                                   &body body)
58   (let ((value (gensym))
59         (eval-fields (cadr fields)))
60     (if single
61         `(let ((,value ,where-value))
62           (when ,value 
63             (let ((tuple (car (umlisp-query-eval ,table ,fields ,srl ,where-name ,value
64                                             :lrl ,lrl :single ,single
65                                             :distinct ,distinct :order ,order
66                                             :like ,like))))
67               (when tuple
68                 (destructuring-bind ,eval-fields tuple
69                   ,@body)))))
70         `(let ((,value ,where-value))
71           (when ,value 
72             (loop for tuple in
73                   (umlisp-query-eval ,table ,fields ,srl ,where-name ,value
74                                      :lrl ,lrl :single ,single :distinct ,distinct
75                                      :order ,order :like ,like)
76                   collect (destructuring-bind ,eval-fields tuple
77                             ,@body)))))))
78
79
80 (defmacro umlisp-query (table fields srl where-name where-value
81                      &key (lrl "KCUILRL") single distinct order like)
82   "Query the UMLisp database. Return a list of umlisp objects whose name
83 is OBJNAME from TABLE where WHERE-NAME field = WHERE-VALUE with FIELDS"
84   `(mutex-sql-query
85     (query-string ,table ,fields ,srl ,where-name ,where-value 
86      :lrl ,lrl :single ,single :distinct ,distinct :order ,order :like ,like)))
87
88 (defmacro umlisp-query-eval (table fields srl where-name where-value
89                      &key (lrl "KCUILRL") single distinct order like)
90   "Query the UMLisp database. Return a list of umlisp objects whose name
91 is OBJNAME from TABLE where WHERE-NAME field = WHERE-VALUE with FIELDS"
92   `(mutex-sql-query
93     (query-string-eval ,table ,fields ,srl ,where-name ,where-value 
94      :lrl ,lrl :single ,single :distinct ,distinct :order ,order :like ,like)))
95
96   
97 (defmacro query-string (table fields &optional srl where-name where-value
98                         &key (lrl "KCUILRL") single distinct order like)
99   (let* ((%%fields (format nil "select ~A~{~:@(~A~)~^,~} from ~:@(~A~)"
100                            (if distinct "distinct " "") fields table))
101          (%%order (if order (format nil " order by ~{~:@(~A~) ~(~A~)~^,~}" order) ""))
102          (%%lrl (format nil " and ~:@(~A~)<=" lrl))
103          (%%where (when where-name
104                     (format nil " where ~:@(~A~)~A" where-name
105                           (if like " like " "")))))
106     `(concatenate
107       'string
108       ,%%fields
109       ,@(when %%where (list %%where))
110       ,@(when %%where
111               #+ignore
112               `((if (numberp ,where-value)
113                     (write-to-string ,where-value)
114                     (format nil ,(if like "'%~A%'" "'~A'") ,where-value)))
115               `((typecase ,where-value
116                   (number
117                    (concatenate 'string "=" (write-to-string ,where-value)))
118                   (null
119                    " is null")
120                   (t
121                    (format nil ,(if like "'%~A%'" "'=~A'") ,where-value)))))
122       (if ,srl (concatenate 'string ,%%lrl (write-to-string ,srl)) "")
123       ,@(when %%order (list %%order))
124       ,@(when single (list " limit 1")))))
125
126 (defun query-string-eval (table fields &optional srl where-name where-value
127                           &key (lrl "KCUILRL") single distinct order like)
128   (concatenate
129    'string
130    (format nil "select ~A~{~:@(~A~)~^,~} from ~:@(~A~)" 
131            (if distinct "distinct " "") fields table)
132    (if where-name
133        (format nil
134                (if (stringp where-value)
135                    (if like
136                        " where ~A like '%~A%'"
137                        " where ~A='~A'")
138                    " where ~A=~A")
139                where-name  where-value)
140        "")
141    (if srl (format nil " and ~:@(~A~) <= ~D" lrl srl) "")
142    (if order (format nil " order by ~{~:@(~A~) ~(~A~)~^,~}" order) "")
143    (if single " limit 1" "")))
144
145 (defun find-ucon-cui (cui &key (srl *current-srl*))
146   "Find ucon for a cui"
147   (with-umlisp-query (mrcon (kpfstr kcuilrl) srl cui (parse-cui cui) :single t)
148     (make-instance 'ucon :cui (parse-cui cui)
149                    :pfstr kpfstr
150                    :lrl (ensure-integer kcuilrl))))
151
152 (defun find-ucon-cui-old (cui &key (srl *current-srl*))
153   "Find ucon for a cui"
154   (when (stringp cui) (setq cui (parse-cui cui)))
155   (when cui
156     (let ((ls (format nil "select KPFSTR,KCUILRL from MRCON where CUI=~d" cui)))
157       (when srl
158         (string-append ls (format nil " and KCUILRL <= ~d" srl)))
159       (string-append ls " limit 1")
160       (let ((tuple (car (mutex-sql-query ls))))
161         (destructuring-bind (kpfstr kcuilrl) tuple
162           (make-instance 'ucon :cui cui :pfstr kpfstr
163                          :lrl (ensure-integer kcuilrl)))))))
164
165 (defun find-ucon-cui-sans-pfstr (cui &key (srl *current-srl*))
166   "Find ucon for a cui"
167   (with-umlisp-query (mrcon (kcuilrl) srl cui (parse-cui cui) :single t)
168     (make-instance 'ucon :cui (parse-cui cui)
169                    :lrl (ensure-integer kcuilrl)
170                    :pfstr nil)))
171
172 (defun find-pfstr-cui (cui &key (srl *current-srl*))
173   "Find preferred string for a cui"
174   (with-umlisp-query (mrcon (kpfstr) srl cui (parse-cui cui) :single t)
175     kpfstr))
176
177 (defun find-ucon-lui (lui &key (srl *current-srl*))
178   "Find list of ucon for lui"
179   (with-umlisp-query (mrcon (cui kpfstr kcuilrl) srl lui (parse-lui lui) :distinct t)
180     (make-instance 'ucon :cui (ensure-integer cui)
181                    :pfstr kpfstr
182                    :lrl (ensure-integer kcuilrl))))
183
184 (defun find-ucon-sui (sui &key (srl *current-srl*))
185   "Find list of ucon for sui"
186   (with-umlisp-query (mrcon (cui kpfstr kcuilrl) srl sui (parse-sui sui) :distinct t)
187     (make-instance 'ucon :cui (ensure-integer cui)
188                    :pfstr kpfstr
189                    :lrl (ensure-integer kcuilrl))))
190
191 (defun find-ucon-cuisui (cui sui &key (srl *current-srl*))
192   "Find ucon for cui/sui"
193   (when (and cui sui)
194     (with-umlisp-query (mrcon (cui kpfstr kcuilrl) srl kcuisui 
195                                (make-cuisui (parse-cui cui) (parse-sui sui)))
196       (make-instance 'ucon :cui (ensure-integer cui)
197                      :pfstr kpfstr
198                      :lrl (ensure-integer kcuilrl)))))
199
200 (defun find-ucon-str (str &key (srl *current-srl*))
201   "Find ucon that are exact match for str"
202   (with-umlisp-query (mrcon (cui kpfstr kcuilrl) srl str str :distinct t)
203     (make-instance 'ucon :cui (ensure-integer cui) :pfstr kpfstr
204                    :lrl (ensure-integer kcuilrl))))
205
206 (defun find-ucon-all (&key (srl *current-srl*))
207   "Return list of all ucon's"
208   (with-sql-connection (db)
209     (clsql:map-query 
210      'list
211      #'(lambda (cui pfstr cuilrl)
212          (make-instance 'ucon :cui (ensure-integer cui)
213                         :pfstr pfstr
214                         :lrl (ensure-integer cuilrl)))
215      (query-string mrcon (cui kpfstr kcuilrl) srl nil nil
216                    :order (cui asc) :distinct t)
217      :database db)))
218
219 (defun map-ucon-all (fn &key (srl *current-srl*))
220   "Map a function over all ucon's"
221   (with-sql-connection (db)
222     (clsql:map-query 
223      nil
224      #'(lambda (cui pfstr cuilrl)
225          (funcall fn
226                   (make-instance 'ucon :cui (ensure-integer cui)
227                                  :pfstr pfstr
228                                  :lrl (ensure-integer cuilrl))))
229      (query-string mrcon (cui kpfstr kcuilrl) srl nil nil :order (cui asc) :distinct t)
230      :database db)))
231
232
233 (defun find-udef-cui (cui &key (srl *current-srl*))
234   "Return a list of udefs for cui"
235   (with-umlisp-query (mrdef (sab def) srl cui (parse-cui cui) :lrl "KSRL")
236     (make-instance 'udef :sab sab :def def)))
237
238 (defun find-usty-cui (cui &key (srl *current-srl*))
239   "Return a list of usty for cui"
240   (with-umlisp-query (mrsty (tui sty) srl cui (parse-cui cui) :lrl "KLRL")
241     (make-instance 'usty :tui (ensure-integer tui) :sty sty)))
242
243 (defun find-usty-word (word &key (srl *current-srl*))
244   "Return a list of usty that match word"
245   (with-umlisp-query (mrsty (tui sty) srl sty word :lrl klrl :like t :distinct t)
246     (make-instance 'usty :tui (ensure-integer tui) :sty sty)))
247
248 (defun find-urel-cui (cui &key (srl *current-srl*))
249   "Return a list of urel for cui"
250   (with-umlisp-query (mrrel (rel cui2 rela sab sl mg kpfstr2) srl cui1 (parse-cui cui) :lrl "KSRL")
251     (make-instance 'urel :cui1 (parse-cui cui) :rel rel :cui2 (ensure-integer cui2) :rela rela
252                    :sab sab :sl sl :mg mg :pfstr2 kpfstr2)))
253
254 (defun find-urel-cui2 (cui2 &key (srl *current-srl*))
255   "Return a list of urel for cui2"
256   (with-umlisp-query (mrrel (rel cui1 rela sab sl mg kpfstr2) srl cui2 (parse-cui cui2) :lrl "KSRL")
257     (make-instance 'urel :cui2 (parse-cui cui2) :rel rel :cui1 (ensure-integer cui1) :rela rela
258                    :sab sab :sl sl :mg mg :pfstr2 kpfstr2)))
259
260 (defun find-ucon-rel-cui2 (cui2 &key (srl *current-srl*))
261   (mapcar 
262    #'(lambda (cui) (find-ucon-cui cui :srl srl))
263    (remove-duplicates (mapcar #'cui1 (find-urel-cui2 cui2 :srl srl)))))
264
265 (defun find-ucoc-cui (cui &key (srl *current-srl*))
266   "Return a list of ucoc for cui"
267   (with-umlisp-query (mrcoc (cui2 soc cot cof coa kpfstr2) srl cui1 (parse-cui cui) 
268                              :lrl "KSRL" :order (cof asc))
269     (setq cui2 (ensure-integer cui2))
270     (when (zerop cui2) (setq cui2 nil))
271     (make-instance 'ucoc :cui1 (parse-cui cui) :cui2 (ensure-integer cui2) :soc soc :cot cot
272                    :cof (ensure-integer cof) :coa coa :pfstr2 kpfstr2)))
273
274 (defun find-ucoc-cui2 (cui2 &key (srl *current-srl*))
275   "Return a list of ucoc for cui2"
276   (with-umlisp-query (mrcoc (cui1 soc cot cof coa kpfstr2) srl cui2 (parse-cui cui2) 
277                              :lrl "KSRL" :order (cof asc))
278     (setq cui2 (ensure-integer cui2))
279     (when (zerop cui2) (setq cui2 nil))
280     (make-instance 'ucoc :cui1 (ensure-integer cui1) :cui2 (parse-cui cui2) :soc soc :cot cot
281                    :cof (ensure-integer cof) :coa coa :pfstr2 kpfstr2)))
282
283 (defun find-ucon-coc-cui2 (cui2 &key (srl *current-srl*))
284   "List of ucon with co-occurance cui2"
285   (mapcar 
286    #'(lambda (cui) (find-ucon-cui cui :srl srl))
287    (remove-duplicates (mapcar #'cui1 (find-ucoc-cui2 cui2 :srl srl)))))
288
289 (defun find-ulo-cui (cui &key (srl *current-srl*))
290   "Return a list of ulo for cui"
291   (with-umlisp-query (mrlo (isn fr un sui sna soui) srl cui (parse-cui cui) :lrl "KLRL")
292     (make-instance 'ulo :isn isn :fr (ensure-integer fr) :un un :sui (ensure-integer sui) :sna sna
293                    :soui soui)))
294
295 (defgeneric suistr (lo))
296 (defmethod suistr ((lo ulo))
297   "Return the string for a ulo object"
298   (find-string-sui (sui lo)))
299
300 (defun find-uatx-cui (cui &key (srl *current-srl*))
301   "Return a list of uatx for cui"
302   (with-umlisp-query (mratx (sab rel atx) srl cui (parse-cui cui) :lrl ksrl)
303     (make-instance 'uatx :sab sab :rel rel :atx atx)))
304
305
306 (defun find-uterm-cui (cui &key (srl *current-srl*))
307   "Return a list of uterm for cui"
308   (with-umlisp-query (mrcon (lui lat ts kluilrl) srl cui (parse-cui cui) :lrl kluilrl
309                              :distinct t)
310     (make-instance 'uterm :lui (ensure-integer lui) :cui (parse-cui cui)
311                    :lat lat :ts ts :lrl (ensure-integer kluilrl))))
312
313 (defun find-uterm-lui (lui &key (srl *current-srl*))
314   "Return a list of uterm for lui"
315   (with-umlisp-query (mrcon (cui lat ts kluilrl) srl lui (parse-lui lui) 
316                              :lrl kluilrl :distinct t)
317     (make-instance 'uterm :cui (ensure-integer cui) :lui (parse-lui lui)
318                    :lat lat :ts ts :lrl (ensure-integer kluilrl))))
319
320 (defun find-uterm-cuilui (cui lui &key (srl *current-srl*))
321   "Return single uterm for cui/lui"
322   (with-umlisp-query (mrcon (lat ts kluilrl) srl kcuilui
323                              (make-cuilui (parse-cui cui) (parse-lui lui))
324                              :lrl kluilrl :single t)
325     (make-instance 'uterm :cui cui :lui lui :lat lat :ts ts :lrl (ensure-integer kluilrl))))
326
327 (defun find-ustr-cuilui (cui lui &key (srl *current-srl*))
328   "Return a list of ustr for cui/lui"
329   (with-umlisp-query (mrcon (sui stt str lrl) srl kcuilui (make-cuilui cui lui) :lrl lrl)
330     (make-instance 'ustr :sui (ensure-integer sui) :cui cui :lui lui
331                    :cuisui (make-cuisui cui sui) :stt stt :str str
332                    :lrl (ensure-integer lrl))))
333
334 (defun find-ustr-cuisui (cui sui &key (srl *current-srl*))
335   "Return the single ustr for cuisui"
336   (with-umlisp-query (mrcon (lui stt str lrl) srl kcuisui (make-cuisui cui sui) :lrl lrl :single t)
337     (make-instance 'ustr :sui sui :cui cui :cuisui (make-cuisui cui sui)
338                    :lui (ensure-integer lui) :stt stt :str str :lrl (ensure-integer lrl))))
339
340 (defun find-ustr-sui (sui &key (srl *current-srl*))
341   "Return the list of ustr for sui"
342   (with-umlisp-query (mrcon (cui lui stt str lrl) srl sui (parse-sui sui) :lrl lrl)
343     (make-instance 'ustr :sui sui :cui cui :stt stt :str str
344                    :cuisui (make-cuisui (ensure-integer cui) (parse-sui sui))
345                    :lui (ensure-integer lui)
346                    :lrl (ensure-integer lrl))))
347       
348 (defun find-ustr-sab (sab &key (srl *current-srl*))
349   "Return the list of ustr for sab"
350   (with-umlisp-query (mrso (kcuisui) srl sab sab :lrl srl)
351     (let ((cuisui (ensure-integer kcuisui)))
352       (apply #'find-ustr-cuisui 
353              (append
354               (multiple-value-list (decompose-cuisui cuisui)) (list :srl srl))))))
355
356 (defun find-ustr-all (&key (srl *current-srl*))
357   "Return list of all ustr's"
358     (with-sql-connection (db)
359       (clsql:map-query 
360        'list
361        #'(lambda (cui lui sui stt lrl pfstr)
362            (setq cui (ensure-integer cui))
363            (setq lui (ensure-integer lui))
364            (setq sui (ensure-integer sui))      
365            (setq lrl (ensure-integer lrl))
366            (make-instance 'ustr :cui cui
367                           :lui lui
368                           :sui sui
369                           :cuisui (make-cuisui cui sui)
370                           :stt stt
371                           :lrl lrl
372                           :str pfstr))
373        (query-string mrcon (cui lui sui stt lrl kpfstr) srl nil nil :lrl lrl :distinct t
374                      :order (sui asc))
375        :database db)))
376
377 (defun find-string-sui (sui &key (srl *current-srl*))
378   "Return the string associated with sui"
379   (with-umlisp-query (mrcon (str) srl sui sui :lrl lrl :single t)
380     str))
381
382 (defun find-uso-cuisui (cui sui &key (srl *current-srl*))
383   (with-umlisp-query (mrso (sab code srl tty) srl kcuisui (make-cuisui cui sui) :lrl srl)
384       (make-instance 'uso :sab sab :code code :srl srl :tty tty)))
385
386 (defun find-ucxt-cuisui (cui sui &key (srl *current-srl*))
387   (with-umlisp-query (mrcxt (sab code cxn cxl rnk cxs cui2 hcd rela xc) srl kcuisui
388                              (make-cuisui cui sui) :lrl ksrl)
389     (make-instance 'ucxt :sab sab :code code
390                    :cxn (ensure-integer cxn)
391                    :cxl cxl :cxs cxs :hcd hcd :rela rela :xc xc
392                    :rnk (ensure-integer rnk)
393                    :cui2 (ensure-integer cui2))))
394
395 (defun find-usat-ui (cui &optional (lui nil) (sui nil) &key (srl *current-srl*))
396   (let ((ls (format nil "select CODE,ATN,SAB,ATV from MRSAT where ")))
397     (cond
398       (sui (string-append ls (format nil "KCUISUI=~d" (make-cuisui cui sui))))
399       (lui (string-append ls (format nil "KCUILUI=~d and sui=0" (make-cuilui cui lui))))
400       (t (string-append ls (format nil "cui=~d and lui=0 and sui=0" cui))))
401     (when srl
402       (string-append ls (format nil " and KSRL <= ~d" srl)))
403     (loop for tuple in (mutex-sql-query ls) collect 
404           (destructuring-bind (code atn sab atv) tuple
405             (make-instance 'usat :code code :atn atn :sab sab :atv atv)))))
406
407 (defun find-usty-tui (tui)
408   "Find usty for tui"
409   (with-umlisp-query (mrsty (sty) nil tui (parse-tui tui) :single t)
410     (make-instance 'usty :tui (parse-tui tui) :sty sty)))
411
412 (defun find-usty-sty (sty)
413   "Find usty for a sty"
414   (with-umlisp-query (mrsty (tui) nil sty sty :single t)
415     (make-instance 'usty :tui (ensure-integer tui) :sty sty)))
416
417 (defun find-usty-all ()
418   "Return list of usty's for all semantic types"
419   (with-umlisp-query (mrsty (tui) nil nil nil :distinct t)
420     (find-usty-tui tui)))
421
422 (defun find-usab-all ()
423   "Find usab for a key"
424   (with-umlisp-query (mrsab (vcui rcui vsab rsab son sf sver mstart mend imeta rmeta slc scc srl tfr cfr cxty ttyl atnl lat cenc curver sabin) nil nil nil)
425     (make-instance 'usab :vcui (ensure-integer vcui) 
426                    :rcui (ensure-integer rcui)
427                    :vsab vsab :rsab rsab :son son :sf sf :sver sver :mstart mstart
428                    :mend mend :imeta imeta :rmeta rmeta :slc slc :scc scc
429                    :srl (ensure-integer srl) 
430                    :tfr (ensure-integer tfr) :cfr (ensure-integer cfr)
431                    :cxty cxty :ttyl ttyl :atnl atnl :lat lat :cenc cenc
432                    :curver curver :sabin sabin)))
433
434 (defun find-usab-by-key (key-name key)
435   "Find usab for a key"
436   (with-umlisp-query-eval ('mrsab '(vcui rcui vsab rsab son sf sver mstart mend imeta rmeta slc scc srl tfr cfr cxty ttyl atnl lat cenc curver sabin) nil key-name key :single t)
437     (make-instance 'usab :vcui (ensure-integer vcui) 
438                    :rcui (ensure-integer rcui)
439                    :vsab vsab :rsab rsab :son son :sf sf :sver sver :mstart mstart
440                    :mend mend :imeta imeta :rmeta rmeta :slc slc :scc scc
441                    :srl (ensure-integer srl) 
442                    :tfr (ensure-integer tfr) :cfr (ensure-integer cfr)
443                    :cxty cxty :ttyl ttyl :atnl atnl :lat lat :cenc cenc
444                    :curver curver :sabin sabin)))
445
446 (defun find-usab-rsab (rsab)
447   "Find usab for rsab"
448   (find-usab-by-key 'rsab rsab))
449
450 (defun find-usab-vsab (vsab)
451   "Find usab for vsab"
452   (find-usab-by-key 'vsab vsab))
453
454 (defun find-cui-max ()
455   (ensure-integer (caar (mutex-sql-query "select max(CUI) from MRCON"))))
456
457 ;;;; Cross table find functions
458
459 (defun find-ucon-tui (tui &key (srl *current-srl*))
460   "Find list of ucon for tui"
461   (with-umlisp-query (mrsty (cui) srl tui (parse-tui tui) :lrl klrl
462                              :order (cui asc))
463     (find-ucon-cui (ensure-integer cui) :srl srl)))
464   
465 (defun find-ucon-word (word &key (srl *current-srl*) (like nil))
466   "Return list of ucons that match word. Optionally, use SQL's LIKE syntax"
467   (with-umlisp-query-eval ('mrxw_eng '(cui) srl 'wd word :like like :distinct t
468                                      :lrl 'klrl :order '(cui asc))
469     (find-ucon-cui cui :srl srl)))
470
471 (defun find-ucon-normalized-word (word &key (srl *current-srl*) (like nil))
472   "Return list of ucons that match word, optionally use SQL's LIKE syntax"
473   (with-umlisp-query-eval ('mrxnw_eng '(cui) srl 'nwd word :like like :distinct t
474                                       :lrl 'klrl :order '(cui asc))
475     (find-ucon-cui cui :srl srl)))
476
477 (defun find-ustr-word (word &key (srl *current-srl*))
478   "Return list of ustrs that match word"
479   (with-umlisp-query (mrxw_eng (cui sui) srl wd word
480                                 :lrl klrl
481                                 :order (cui asc sui asc))
482     (find-ustr-cuisui (ensure-integer cui) (ensure-integer sui) :srl srl)))
483
484 (defun find-ustr-normalized-word (word &key (srl *current-srl*))
485   "Return list of ustrs that match word"
486   (with-umlisp-query (mrxnw_eng (cui sui) srl nwd word :lrl klrl
487                                  :order (cui asc sui asc))
488     (find-ustr-cuisui (ensure-integer cui) (ensure-integer sui) :srl srl)))
489
490 ;; Special tables
491
492 (defun find-usrl-all ()
493   (with-umlisp-query (usrl (sab srl) nil nil nil :order (sab asc))
494     (make-instance 'usrl :sab sab :srl (ensure-integer srl))))
495
496 ;;; Multiword lookup and score functions
497
498 (defun find-ucon-multiword (str &key (srl *current-srl*))
499   "Return sorted list of ucon's that match a multiword string"
500   (let* ((words (delimited-string-to-list str #\space))
501          (ucons '()))
502     (dolist (word words)
503       (setq ucons (append ucons (find-ucon-word word :srl srl))))
504     (sort-score-ucon-str str (delete-duplicates ucons :test #'eql :key #'cui))))
505
506 (defun find-ustr-multiword (str &key (srl *current-srl*))
507   "Return sorted list of ustr's that match a multiword string"
508   (let* ((words (delimited-string-to-list str #\space))
509          (ustrs '()))
510     (dolist (word words)
511       (setq ustrs (append ustrs (find-ustr-word word :srl srl))))
512     (sort-score-ustr-str str (delete-duplicates ustrs :test #'eql :key #'cui))))
513         
514 (defun sort-score-ucon-str (str ucons)
515   "Return list of sorted and scored ucons. Score by match of str to ucon-pfstr"
516   (sort-score-umlsclass-str ucons str #'pfstr))
517
518 (defun sort-score-ustr-str (str ustrs)
519   "Return list of sorted and scored ucons. Score by match of str to ucon-pfstr"
520   (sort-score-umlsclass-str ustrs str #'str))
521
522 (defun sort-score-umlsclass-str (objs str lookup-func)
523   "Sort a list of objects based on scoring to a string"
524   (let ((scored '()))
525     (dolist (obj objs)
526       (push 
527        (list obj 
528              (score-multiword-match str (funcall lookup-func obj))) 
529        scored))
530     (mapcar #'car (sort scored #'> :key #'cadr))))
531
532 (defun score-multiword-match (s1 s2)
533   "Score a match between two strings with s1 being reference string"
534   (let* ((word-list-1 (delimited-string-to-list s1 #\space))
535          (word-list-2 (delimited-string-to-list s2 #\space))
536          (n1 (length word-list-1))
537          (n2 (length word-list-2))
538          (unmatched n1)
539          (score 0)
540          (nlong 0)
541          (nshort 0)
542          short-list long-list)
543     (declare (fixnum n1 n2 nshort nlong score unmatched))
544     (if (> n1 n2)
545         (progn
546           (setq nlong n1)
547           (setq nshort n2)
548           (setq long-list word-list-1)
549           (setq short-list word-list-2))
550       (progn
551         (setq nlong n2)
552         (setq nshort n1)
553         (setq long-list word-list-2)
554         (setq short-list word-list-1)))
555     (decf score (- nlong nshort)) ;; reduce score for extra words
556     (dotimes (iword nshort)
557       (declare (fixnum iword))
558       (kmrcl:aif (position (nth iword short-list) long-list :test #'string-equal)
559            (progn
560              (incf score (- 10 (abs (- kmrcl::it iword))))
561              (decf unmatched))))
562     (decf score (* 2 unmatched))
563     score))
564
565
566 ;;; LEX SQL functions
567
568 (defun find-lexterm-eui (eui)
569   (with-umlisp-query (lrwd (wrd) nil eui eui :single t)
570     (make-instance 'lexterm :eui eui :wrd wrd)))
571
572 (defun find-lexterm-word (wrd)
573   (with-umlisp-query (lrwd (eui) nil wrd wrd)
574     (make-instance 'lexterm :eui (ensure-integer eui)
575                    :wrd (copy-seq wrd))))
576
577 ;; LEX SQL Read functions
578
579 (defun find-labr-eui (eui)
580   (with-umlisp-query (lrabr (bas abr eui2 bas2) nil eui eui) 
581     (make-instance 'labr :eui eui :bas bas :abr abr :bas2 bas2
582                    :eui2 (ensure-integer eui2))))
583
584 (defun find-labr-bas (bas)
585   (with-umlisp-query (labr (eui abr eui2 bas2) nil bas bas)
586     (make-instance 'labr :eui (ensure-integer eui) :abr abr :bas2 bas2
587                    :bas (copy-seq bas) :eui2 (ensure-integer eui2))))
588
589 (defun find-lagr-eui (eui)
590   (with-umlisp-query (lragr (str sca agr cit bas) nil eui eui)
591     (make-instance 'lagr :eui eui :str str :sca sca :agr agr
592                    :cit cit :bas bas)))
593
594 (defun find-lcmp-eui (eui)
595   (with-umlisp-query (lrcmp (bas sca com) nil eui eui)
596     (make-instance 'lcmp :eui eui :bas bas :sca sca :com com)))
597
598 (defun find-lmod-eui (eui)
599   (with-umlisp-query (lrmod (bas sca psn_mod fea) nil eui eui)
600     (make-instance 'lmod :eui eui :bas bas :sca sca :psnmod psn_mod :fea fea)))
601
602 (defun find-lnom-eui (eui)
603   (with-umlisp-query (lrnom (bas sca eui2 bas2 sca2) nil eui eui)
604     (make-instance 'lnom :eui eui :bas bas :sca sca :bas2 bas2 :sca2 sca2
605                    :eui2 (ensure-integer eui2))))
606
607 (defun find-lprn-eui (eui)
608   (with-umlisp-query (lrprn (bas num gnd cas pos qnt fea) nil eui eui)
609     (make-instance 'lprn :eui eui :bas bas :num num :gnd gnd
610                    :cas cas :pos pos :qnt qnt :fea fea)))
611
612 (defun find-lprp-eui (eui)
613   (with-umlisp-query (lrprp (bas str sca fea) nil eui eui)
614     (make-instance 'lprp :eui eui :bas bas :str str :sca sca :fea fea)))
615
616 (defun find-lspl-eui (eui)
617   (with-umlisp-query (lrspl (spv bas) nil eui eui)
618     (make-instance 'lspl :eui eui :spv spv :bas bas)))
619
620 (defun find-ltrm-eui (eui)
621   (with-umlisp-query (lrtrm (bas gen) nil eui eui) 
622     (make-instance 'ltrm :eui eui :bas bas :gen gen)))
623
624 (defun find-ltyp-eui (eui)
625   (with-umlisp-query (lrtyp (bas sca typ) nil eui eui)
626     (make-instance 'ltyp :eui eui :bas bas :sca sca :typ typ)))
627
628 (defun find-lwd-wrd (wrd)
629   (make-instance 'lwd :wrd
630                  :euilist (with-umlisp-query (lrwd (eui) nil wrd wrd)
631                             (ensure-integer eui))))
632
633 ;;; Semantic Network SQL access functions
634
635 (defun find-sdef-ui (ui)
636   (with-umlisp-query (srdef (rt sty_rl stn_rtn def ex un rh abr rin)
637                             nil ui ui :single t)
638     (make-instance 'sdef :rt rt :ui ui :styrl sty_rl :stnrtn stn_rtn
639                    :def def :ex ex :un un :rh rh :abr abr :rin rin)))
640
641 (defun find-sstre1-ui (ui)
642   (with-umlisp-query (srstre1 (ui2 ui3) nil ui ui)
643     (make-instance 'sstre1 :ui ui :ui2 (ensure-integer ui2)
644                    :ui3 (ensure-integer ui3))))
645
646 (defun find-sstre1-ui2 (ui2)
647   (with-umlisp-query (srstre1 (ui ui3) nil ui2 ui2)
648     (make-instance 'sstre1 :ui (ensure-integer ui) :ui2 ui2
649                    :ui3 (ensure-integer ui3))))
650
651 (defun find-sstr-rl (rl)
652   (with-umlisp-query (srstre (sty_rl sty_rl2 ls) nil rl rl)
653     (make-instance 'sstr :rl rl :styrl sty_rl :styrl2 sty_rl2 :ls ls)))
654
655 (defun find-sstre2-sty (sty)
656   (with-umlisp-query (srstre2 (rl sty2) nil sty sty)
657     (make-instance 'sstre2 :sty (copy-seq sty) :rl rl :sty2 sty2)))
658
659 (defun find-sstr-styrl (styrl)
660   (with-umlisp-query (srstr (rl sty_rl2 ls) nil styrl styrl)
661     (make-instance 'sstr :styrl styrl :rl rl :styrl2 sty_rl2 :ls ls)))