r11140: do not export internal functions
[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 ;;;; Created:  Apr 2000
9 ;;;;
10 ;;;; $Id$
11 ;;;;
12 ;;;; This file, part of UMLisp, is
13 ;;;;    Copyright (c) 2000-2006 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
21
22 (defvar *current-srl* nil)
23 (defun current-srl ()
24   *current-srl*)
25 (defun current-srl! (srl)
26   (setq *current-srl* srl))
27
28 (defmacro query-string (table fields &optional srl where-name where-value
29                         &key (lrl "KCUILRL") single distinct order like)
30   (let* ((%%fields (format nil "select ~A~{~:@(~A~)~^,~} from ~:@(~A~)"
31                            (if distinct "distinct " "") fields table))
32          (%%order (if order (format nil " order by ~{~:@(~A~) ~(~A~)~^,~}"
33                                     order)
34                       ""))
35          (%%lrl (format nil " and ~:@(~A~)<=" lrl))
36          (%%where (when where-name
37                     (format nil " where ~:@(~A~)~A" where-name
38                           (if like " like " "")))))
39     `(concatenate
40       'string
41       ,%%fields
42       ,@(when %%where (list %%where))
43       ,@(when %%where
44           `((typecase ,where-value
45               #+ignore
46               (fixnum
47                (concatenate 'string "='" (prefixed-fixnum-string ,where-value #\0 10) "'"))
48               (number
49                (concatenate 'string "='" (write-to-string ,where-value) "'"))
50               (null
51                " is null")
52               (t
53                (format nil ,(if like "'%~A%'" "='~A'") ,where-value)))))
54       (if ,srl (concatenate 'string ,%%lrl (write-to-string ,srl)) "")
55       ,@(when %%order (list %%order))
56       ,@(when single (list " limit 1")))))
57
58 (defun query-string-eval (table fields &optional srl where-name where-value
59                           &key (lrl "KCUILRL") single distinct order like)
60   (concatenate
61    'string
62    (format nil "select ~A~{~:@(~A~)~^,~} from ~:@(~A~)"
63            (if distinct "distinct " "") fields table)
64    (if where-name (format nil " where ~:@(~A~)" where-name) "")
65    (if where-name
66        (format nil
67                (typecase where-value
68                  (number "='~D'")
69                  (null " is null")
70                  (t
71                   (if like " like '%~A%""='~A'")))
72                where-value)
73        "")
74    (if srl (format nil " and ~:@(~A~)<=~D" lrl srl) "")
75    (if order (format nil " order by ~{~:@(~A~) ~(~A~)~^,~}" order) "")
76    (if single " limit 1" "")))
77
78
79 (defmacro umlisp-query (table fields srl where-name where-value
80                      &key (lrl "KCUILRL") single distinct order like
81                         (query-cmd 'mutex-sql-query))
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   `(,query-cmd
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 ;; only WHERE-VALUE and SRL are evaluated
97 (defmacro collect-umlisp-query ((table fields srl where-name where-value
98                                     &key (lrl "KCUILRL") distinct single
99                                     order like (query-cmd 'mutex-sql-query))
100                                 &body body)
101   (let ((value (gensym))
102         (r (gensym)))
103     (if single
104         `(let* ((,value ,where-value)
105                 (tuple (car (umlisp-query ,table ,fields ,srl ,where-name ,value
106                                           :lrl ,lrl :single ,single
107                                           :distinct ,distinct :order ,order
108                                           :like ,like
109                                           :query-cmd ,query-cmd))))
110           ,@(unless where-name `((declare (ignore ,value))))
111           (when tuple
112                 (destructuring-bind ,fields tuple
113                   ,@body)))
114         `(let ((,value ,where-value))
115            ,@(unless where-name `((declare (ignore ,value))))
116            (let ((,r '()))
117              (dolist (tuple (umlisp-query ,table ,fields ,srl ,where-name ,value
118                                           :lrl ,lrl :single ,single :distinct ,distinct
119                                           :order ,order :like ,like))
120                (push (destructuring-bind ,fields tuple ,@body) ,r))
121              (nreverse ,r))
122            #+ignore
123            (loop for tuple in
124                  (umlisp-query ,table ,fields ,srl ,where-name ,value
125                                :lrl ,lrl :single ,single :distinct ,distinct
126                                :order ,order :like ,like)
127                collect (destructuring-bind ,fields tuple ,@body))))))
128
129 (defmacro collect-umlisp-query-eval ((table fields srl where-name where-value
130                                          &key (lrl "KCUILRL") distinct single
131                                          order like)
132                                   &body body)
133   (let ((value (gensym))
134         (r (gensym))
135         (eval-fields (cadr fields)))
136     (if single
137         `(let* ((,value ,where-value)
138                 (tuple (car (umlisp-query-eval ,table ,fields ,srl ,where-name ,value
139                                                :lrl ,lrl :single ,single
140                                                :distinct ,distinct :order ,order
141                                                :like ,like))))
142           (when tuple
143             (destructuring-bind ,eval-fields tuple
144               ,@body)))
145         `(let ((,value ,where-value)
146                (,r '()))
147            (dolist (tuple (umlisp-query-eval ,table ,fields ,srl ,where-name ,value
148                                              :lrl ,lrl :single ,single :distinct ,distinct
149                                              :order ,order :like ,like))
150              (push (destructuring-bind ,eval-fields tuple ,@body) ,r))
151            (nreverse ,r)
152            #+ignore
153            (loop for tuple in
154                  (umlisp-query-eval ,table ,fields ,srl ,where-name ,value
155                                     :lrl ,lrl :single ,single :distinct ,distinct
156                                     :order ,order :like ,like)
157                collect (destructuring-bind ,eval-fields tuple ,@body))))))
158
159 ;;;
160 ;;; Read from SQL database
161
162 (defmacro ensure-cui-integer (cui)
163   `(if (stringp ,cui)
164     (setq ,cui (parse-cui ,cui))
165     ,cui))
166
167 (defmacro ensure-lui-integer (lui)
168   `(if (stringp ,lui)
169     (setq ,lui (parse-lui ,lui))
170     ,lui))
171
172 (defmacro ensure-sui-integer (sui)
173   `(if (stringp ,sui)
174     (setq ,sui (parse-sui ,sui))
175     ,sui))
176
177 (defmacro ensure-tui-integer (tui)
178   `(if (stringp ,tui)
179     (setq ,tui (parse-tui ,tui))
180     ,tui))
181
182 (defmacro ensure-eui-integer (eui)
183   `(if (stringp ,eui)
184     (setq ,eui (parse-eui ,eui))
185     ,eui))
186
187 (defun find-ucon-cui (cui &key (srl *current-srl*))
188   "Find ucon for a cui"
189   (ensure-cui-integer cui)
190   (unless cui (return-from find-ucon-cui nil))
191
192   (let ((tuple (car (mutex-sql-query 
193                      (format nil
194                              "SELECT kcuilrl,str FROM MRCONSO WHERE CUI=~D AND KPFENG=1~A"
195                              cui (if srl (format nil " AND SRL<=~D" srl) ""))))))
196     (unless tuple
197       (setq tuple (car (mutex-sql-query
198                         (format nil
199                                 "SELECT kcuilrl,str FROM MRCONSO WHERE CUI=~D"
200                                 cui (if srl (format nil " AND SRL<=~D" srl) nil))))))
201     (unless tuple
202       (return-from find-ucon-cui nil))
203     (make-instance 'ucon :cui cui :pfstr (second tuple)
204                    :lrl (ensure-integer (first tuple)))))
205
206 (defun find-ucon-cui-sans-pfstr (cui &key (srl *current-srl*))
207   "Find ucon for a cui"
208   (ensure-cui-integer cui)
209   (collect-umlisp-query (mrconso (kcuilrl) srl cui cui :single t)
210     (make-instance 'ucon :cui cui :lrl (ensure-integer kcuilrl)
211                    :pfstr nil)))
212
213 (defun find-pfstr-cui (cui &key (srl *current-srl*))
214   "Find preferred string for a cui"
215   (ensure-cui-integer cui)
216   (or
217     (caar (mutex-sql-query
218            (format nil "SELECT DISTINCT str FROM MRCONSO WHERE CUI=~D AND KPFENG=1~A LIMIT 1"
219                    cui (if srl (format nil " AND SRL<=~D" srl) ""))))
220     (caar (mutex-sql-query
221            (format nil "SELECT DISTINCT str FROM MRCONSO WHERE CUI=~D~A LIMIT 1"
222                    cui (if srl (format nil " AND SRL<=~D" srl) ""))))))
223
224 (defun find-ucon-lui (lui &key (srl *current-srl*))
225   "Find list of ucon for lui"
226   (ensure-lui-integer lui)
227   (collect-umlisp-query (mrconso (cui kcuilrl) srl lui lui
228                             :distinct t)
229      (make-instance 'ucon :cui (ensure-integer cui) :pfstr (find-pfstr-cui cui)
230                    :lrl (ensure-integer kcuilrl)))
231   (unless lui (return-from find-ucon-lui nil))
232
233   (let ((tuple (car (mutex-sql-query "SELECT cui,kcuilrl,str FROM MRCONSO WHERE LUI=~D AND KPFENG=1~A ORDER BY kcuilrl ASC LIMIT 1"
234                                      lui (if srl (format nil " AND SRL<=~D" srl) "")))))
235     (unless tuple
236       (setq tuple (car (mutex-sql-query "SELECT cui,kcuilrl,str FROM MRCONSO WHERE LUI=~D~A ORDER BY kcuilrl ASC LIMIT 1"
237                                         lui (if srl (format nil " AND SRL<=~D" srl) "")))))
238     (unless tuple
239       (return-from find-ucon-lui nil))
240     (make-instance 'ucon :cui (first tuple) :pfstr (third tuple)
241                    :lrl (ensure-integer (third tuple)))))
242
243 (defun find-ucon-sui (sui &key (srl *current-srl*))
244   "Find list of ucon for sui"
245   (ensure-sui-integer sui)
246   (collect-umlisp-query (mrconso (cui kcuilrl) srl sui sui :distinct t)
247     (make-instance 'ucon :cui (ensure-integer cui) :pfstr (find-pfstr-cui cui)
248                    :lrl (ensure-integer kcuilrl))))
249
250 (defun find-ucon-aui (aui &key (srl *current-srl*))
251   "Find list of ucon for aui"
252   (ensure-sui-integer aui)
253   (collect-umlisp-query (mrconso (cui kcuilrl) srl aui aui :distinct t)
254     (make-instance 'ucon :cui (ensure-integer cui) :pfstr (find-pfstr-cui cui)
255                    :lrl (ensure-integer kcuilrl))))
256
257 (defun find-ucon-cuisui (cui sui &key (srl *current-srl*))
258   "Find ucon for cui/sui"
259   (ensure-cui-integer cui)
260   (ensure-sui-integer sui)
261   (when (and cui sui)
262     (collect-umlisp-query (mrconso (kcuilrl) srl kcuisui
263                               (make-cuisui cui sui))
264       (make-instance 'ucon :cui cui
265                      :pfstr (find-pfstr-cui cui)
266                      :lrl (ensure-integer kcuilrl)))))
267
268 (defun find-ucon-str (str &key (srl *current-srl*))
269   "Find ucon that are exact match for str"
270   (collect-umlisp-query (mrconso (cui kcuilrl) srl str str :distinct t)
271     (make-instance 'ucon :cui (ensure-integer cui) :pfstr (find-pfstr-cui cui)
272                    :lrl (ensure-integer kcuilrl))))
273
274 (defun find-ucon-all (&key (srl *current-srl*))
275   "Return list of all ucon's"
276   (with-sql-connection (db)
277     (clsql:map-query
278      'list
279      #'(lambda (tuple)
280          (destructuring-bind (cui cuilrl) tuple
281              (make-instance 'ucon :cui (ensure-integer cui)
282                             :pfstr (find-pfstr-cui cui)
283                             :lrl (ensure-integer cuilrl))))
284      (query-string mrconso (cui kcuilrl) srl nil nil
285                    :order (cui asc) :distinct t)
286      :database db)))
287
288 (defun find-ucon-all2 (&key (srl *current-srl*))
289   "Return list of all ucon's"
290   (collect-umlisp-query (mrconso (cui kcuilrl) srl nil nil :order (cui asc)
291                             :distinct t)
292     (make-instance 'ucon :cui (ensure-integer cui)
293                    :pfstr (find-pfstr-cui cui)
294                    :lrl (ensure-integer kcuilrl))))
295
296 (defun find-cui-ucon-all (&key (srl *current-srl*))
297   "Return list of CUIs for all ucons"
298   (collect-umlisp-query (mrconso (cui) srl nil nil :order (cui asc)
299                                :distinct t)
300                         cui))
301
302 (defun map-ucon-all (fn &key (srl *current-srl*))
303   "Map a function over all ucon's"
304   (with-sql-connection (db)
305     (clsql:map-query
306      nil
307      #'(lambda (tuple)
308          (destructuring-bind (cui cuilrl) tuple
309            (funcall fn (make-instance 'ucon :cui (ensure-integer cui)
310                                       :pfstr (find-pfstr-cui cui)
311                                       :lrl (ensure-integer cuilrl)))))
312      (query-string mrconso (cui kcuilrl) srl nil nil :order (cui asc)
313                    :distinct t)
314      :database db)))
315
316
317 (defun find-udef-cui (cui &key (srl *current-srl*))
318   "Return a list of udefs for cui"
319   (ensure-cui-integer cui)
320   (collect-umlisp-query (mrdef (sab def suppress) srl cui cui :lrl "KSRL")
321     (make-instance 'udef :sab sab :def def :suppress suppress)))
322
323 (defun find-udoc-key (key)
324   "Return list of abbreviation documentation for a key"
325   (collect-umlisp-query (mrdoc (value type expl) nil dockey key)
326     (make-instance 'udoc :key key :value value :type type :expl expl)))
327
328 (defun find-udoc-value (value)
329   "Return abbreviation documentation"
330   (collect-umlisp-query (mrdoc (dockey type expl) nil value value)
331     (make-instance 'udoc :key dockey :value value :type type :expl expl)))
332
333 (defun find-udoc-key-value (key value)
334   (let ((tuple (car (mutex-sql-query
335                      (format nil "SELECT TYPE,EXPL FROM MRDOC WHERE DOCKEY='~A' AND VALUE='~A'"
336                              key value)))))
337     (when tuple
338       (make-instance 'udoc :key key :value value :type (first tuple) :expl (second tuple)))))
339
340 (defun find-udoc-all ()
341   "Return all abbreviation documentation"
342   (collect-umlisp-query (mrdoc (dockey value type expl) nil nil nil)
343     (make-instance 'udoc :key dockey :value value :type type :expl expl)))
344
345 (defun find-usty-cui (cui &key (srl *current-srl*))
346   "Return a list of usty for cui"
347   (ensure-cui-integer cui)
348   (collect-umlisp-query (mrsty (tui sty) srl cui cui :lrl "KLRL")
349     (make-instance 'usty :tui (ensure-integer tui) :sty sty)))
350
351 (defun find-usty-word (word &key (srl *current-srl*))
352   "Return a list of usty that match word"
353   (collect-umlisp-query (mrsty (tui sty) srl sty word :lrl klrl :like t
354                             :distinct t)
355     (make-instance 'usty :tui (ensure-integer tui) :sty sty)))
356
357 (defun find-urel-cui (cui &key (srl *current-srl*))
358   "Return a list of urel for cui"
359   (ensure-cui-integer cui)
360   (collect-umlisp-query (mrrel (aui1 rel stype1 cui2 aui2 stype2 rela rui srui sab sl rg dir suppress cvf)
361                                srl cui1 cui :lrl "KSRL")
362     (make-instance 'urel :cui1 cui :aui1 (ensure-integer aui1) :stype1 stype1 :rel rel
363                    :cui2 (ensure-integer cui2) :aui2 (ensure-integer aui2) :stype2 stype2
364                    :rui rui :srui srui :rela rela :sab sab :sl sl :rg rg :dir dir
365                    :suppress suppress :cvf cvf :pfstr2 (find-pfstr-cui cui2))))
366
367 (defun find-cui2-urel-cui (cui &key (srl *current-srl*))
368   "Return a list of urel for cui"
369   (ensure-cui-integer cui)
370   (collect-umlisp-query (mrrel (cui2) srl cui1
371                                cui :lrl "KSRL")
372                         cui2))
373
374 (defun find-urel-cui2 (cui2 &key (srl *current-srl*))
375   "Return a list of urel for cui2"
376   (ensure-cui-integer cui2)
377   (collect-umlisp-query (mrrel (rel cui1 aui1 stype1 aui2 stype2 rela rui srui sab sl rg dir suppress cvf)
378                                srl cui2 cui2 :lrl "KSRL")
379     (make-instance 'urel :cui2 cui2 :rel rel :aui2 (ensure-integer aui2) :stype2 stype2 :rui rui :srui srui
380                    :stype1 stype1 :cui1 (ensure-integer cui1) :aui1 (ensure-integer aui1)
381                    :rela rela :sab sab :sl sl :rg rg :dir dir :suppress suppress :cvf cvf
382                    :pfstr2 (find-pfstr-cui cui2))))
383
384 (defun find-ucon-rel-cui2 (cui2 &key (srl *current-srl*))
385   (ensure-cui-integer cui2)
386   (loop for cui in (remove-duplicates
387                     (mapcar #'cui1 (find-urel-cui2 cui2 :srl srl)))
388         collect (find-ucon-cui cui :srl srl)))
389
390 (defun find-ucoc-cui (cui &key (srl *current-srl*))
391   "Return a list of ucoc for cui"
392   (ensure-cui-integer cui)
393   (collect-umlisp-query (mrcoc (aui1 cui2 aui2 sab cot cof coa) srl cui1
394                             cui :lrl klrl :order (cof asc))
395     (setq cui2 (ensure-integer cui2))
396     (when (eql 0 cui2) (setq cui2 nil))
397     (make-instance 'ucoc :cui1 cui :aui1 (ensure-integer aui1)
398                    :cui2 (ensure-integer cui2) :aui2 (ensure-integer aui2)
399                    :cot cot :cof (ensure-integer cof) :coa coa :sab sab
400                    :pfstr2 (find-pfstr-cui cui2))))
401
402 (defun find-ucoc-cui2 (cui2 &key (srl *current-srl*))
403   "Return a list of ucoc for cui2"
404   (ensure-cui-integer cui2)
405   (collect-umlisp-query (mrcoc (cui1 aui1 aui2 sab cot cof coa) srl cui2
406                             cui2 :lrl klrl :order (cof asc))
407     (when (zerop cui2) (setq cui2 nil))
408     (make-instance 'ucoc :cui1 (ensure-integer cui1) :cui2 cui2
409                    :aui1 (ensure-integer aui1) :aui2 (ensure-integer aui2)
410                    :sab sab :cot cot :cof (ensure-integer cof) :coa coa
411                    :pfstr2 (find-pfstr-cui cui2))))
412
413 (defun find-ucon-coc-cui2 (cui2 &key (srl *current-srl*))
414   "List of ucon with co-occurance cui2"
415   (ensure-cui-integer cui2)
416   (mapcar
417    #'(lambda (cui) (find-ucon-cui cui :srl srl))
418    (remove-duplicates (mapcar #'cui1 (find-ucoc-cui2 cui2 :srl srl)))))
419
420
421 (defun find-uterm-cui (cui &key (srl *current-srl*))
422   "Return a list of uterm for cui"
423   (ensure-cui-integer cui)
424   (collect-umlisp-query (mrconso (lui lat ts kluilrl) srl cui cui
425                             :lrl kluilrl :distinct t)
426     (make-instance 'uterm :lui (ensure-integer lui) :cui cui
427                    :lat lat :ts ts :lrl (ensure-integer kluilrl))))
428
429 (defun find-uterm-lui (lui &key (srl *current-srl*))
430   "Return a list of uterm for lui"
431   (ensure-lui-integer lui)
432   (collect-umlisp-query (mrconso (cui lat ts kluilrl) srl lui lui
433                              :lrl kluilrl :distinct t)
434     (make-instance 'uterm :cui (ensure-integer cui) :lui lui
435                    :lat lat :ts ts :lrl (ensure-integer kluilrl))))
436
437 (defun find-uterm-cuilui (cui lui &key (srl *current-srl*))
438   "Return single uterm for cui/lui"
439   (ensure-cui-integer cui)
440   (ensure-lui-integer lui)
441   (collect-umlisp-query (mrconso (lat ts kluilrl) srl kcuilui
442                              (make-cuilui cui lui)
443                              :lrl kluilrl :single t)
444     (make-instance 'uterm :cui cui :lui lui :lat lat :ts ts
445                    :lrl (ensure-integer kluilrl))))
446
447 (defun find-ustr-cuilui (cui lui &key (srl *current-srl*))
448   "Return a list of ustr for cui/lui"
449   (ensure-cui-integer cui)
450   (ensure-lui-integer lui)
451   (collect-umlisp-query (mrconso (sui stt str suppress ksuilrl) srl kcuilui
452                                  (make-cuilui cui lui) :lrl ksuilrl)
453                 (make-instance 'ustr :sui (ensure-integer sui) :cui cui :lui lui
454                    :cuisui (make-cuisui cui sui) :stt stt :str str :suppress suppress
455                    :lrl (ensure-integer ksuilrl))))
456
457 (defun find-ustr-cuisui (cui sui &key (srl *current-srl*))
458   "Return the single ustr for cuisui"
459   (ensure-cui-integer cui)
460   (ensure-sui-integer sui)
461   (collect-umlisp-query (mrconso (lui stt str suppress ksuilrl) srl kcuisui
462                             (make-cuisui cui sui) :lrl lsuilrl :single t)
463     (make-instance 'ustr :sui sui :cui cui :cuisui (make-cuisui cui sui)
464                    :lui (ensure-integer lui) :stt stt :str str :suppress suppress
465                    :lrl (ensure-integer ksuilrl))))
466
467 (defun find-ustr-sui (sui &key (srl *current-srl*))
468   "Return the list of ustr for sui"
469   (ensure-sui-integer sui)
470   (collect-umlisp-query (mrconso (cui lui stt str suppress ksuilrl) srl sui sui
471                             :lrl ksuilrl)
472     (make-instance 'ustr :sui sui :cui cui :stt stt :str str
473                    :cuisui (make-cuisui (ensure-integer cui) sui)
474                    :suppress suppress
475                    :lui (ensure-integer lui) :lrl (ensure-integer ksuilrl))))
476
477 (defun find-ustr-sab (sab &key (srl *current-srl*))
478   "Return the list of ustr for sab"
479   (collect-umlisp-query (mrconso (kcuisui) srl sab sab :lrl srl)
480     (let ((cuisui (ensure-integer kcuisui)))
481       (apply #'find-ustr-cuisui
482              (append
483               (multiple-value-list (decompose-cuisui cuisui))
484               (list :srl srl))))))
485
486 (defun find-ustr-all (&key (srl *current-srl*))
487   "Return list of all ustr's"
488     (with-sql-connection (db)
489       (clsql:map-query
490        'list
491        #'(lambda (tuple)
492            (destructuring-bind (cui lui sui stt ksuilrl suppress) tuple
493              (make-instance 'ustr :cui (ensure-integer cui)
494                             :lui (ensure-integer lui) :sui (ensure-integer sui)
495                             :stt stt :str (find-pfstr-cui cui)
496                             :cuisui (make-cuisui (ensure-integer cui)
497                                                  (ensure-integer sui))
498                             :suppress suppress
499                             :lrl (ensure-integer ksuilrl))))
500        (query-string mrconso (cui lui sui stt ksuilrl) srl nil nil :lrl ksuilrl
501                      :distinct t
502                      :order (sui asc))
503        :database db)))
504
505 (defun find-string-sui (sui &key (srl *current-srl*))
506   "Return the string associated with sui"
507   (ensure-sui-integer sui)
508   (collect-umlisp-query (mrconso (str) srl sui sui :lrl ksuilrl :single t)
509     str))
510
511 (defun find-uso-cuisui (cui sui &key (srl *current-srl*))
512   (ensure-sui-integer sui)
513   (ensure-cui-integer cui)
514   (collect-umlisp-query (mrconso (aui sab code srl tty saui sdui scui) srl kcuisui
515                            (make-cuisui cui sui) :lrl srl)
516     (make-instance 'uso :aui aui :sab sab :code code :srl srl :tty tty
517                    :cui cui :sui sui :saui saui :sdui sdui :scui scui)))
518
519 (defun find-uso-aui (aui &key (srl *current-srl*))
520   (ensure-sui-integer aui)
521   (collect-umlisp-query (mrconso (sab cui sui code srl tty saui sdui scui) srl aui
522                                  aui :lrl srl :single t)
523     (make-instance 'uso :aui aui :cui cui :sab sab :code code :srl srl :tty tty
524                    :sui sui :saui saui :sdui sdui :scui scui)))
525
526 (defun find-ucxt-cuisui (cui sui &key (srl *current-srl*))
527   (ensure-cui-integer cui)
528   (ensure-sui-integer sui)
529   (collect-umlisp-query (mrcxt (sab rank code cxn cxl cxs cui2 hcd rela xc)
530                             srl kcuisui (make-cuisui cui sui) :lrl ksrl)
531                         (make-instance 'ucxt :sab sab :code code
532                 :rank rank
533                    :cxn (ensure-integer cxn) :cxl cxl :cxs cxs :hcd hcd
534                    :rela rela :xc xc
535                    :cui2 (ensure-integer cui2))))
536
537 (defun find-uhier-cui (cui &key (srl *current-srl*))
538   (ensure-cui-integer cui)
539   (collect-umlisp-query (mrhier (aui cxn paui sab rela ptr hcd cvf)
540                             srl cui cui :lrl ksrl)
541     (make-instance 'uhier :cui cui :aui (ensure-integer aui)
542                    :cxn (ensure-integer cxn)
543                    :paui (ensure-integer paui)
544                    :sab sab :rela rela :ptr ptr :hcd hcd :cvf cvf)))
545
546 (defun find-uhier-all (&key (srl *current-srl*))
547   (collect-umlisp-query (mrhier (cui aui cxn paui sab rela ptr hcd cvf)
548                             srl nil nil :lrl ksrl)
549     (make-instance 'uhier :cui cui :aui (ensure-integer aui)
550                    :cxn (ensure-integer cxn)
551                    :paui (ensure-integer paui)
552                    :sab sab :rela rela :ptr ptr :hcd hcd :cvf cvf)))
553
554 (defun find-usat-ui (cui &optional (lui nil) (sui nil) &key (srl *current-srl*))
555   (ensure-cui-integer cui)
556   (ensure-lui-integer lui)
557   (ensure-sui-integer sui)
558   (let ((ls "select CODE,ATN,SAB,ATV from MRSAT where "))
559     (cond
560       (sui (string-append ls "KCUISUI='"
561                           (integer-string (make-cuisui cui sui) 14)
562                           "'"))
563       (lui (string-append ls "KCUILUI='"
564                           (integer-string (make-cuilui cui lui) 14)
565                           "' and sui='0'"))
566       (t (string-append ls "cui='" (prefixed-fixnum-string cui nil 7)
567                         "' and lui='0' and sui='0'")))
568     (when srl
569       (string-append ls " and KSRL<=" (prefixed-fixnum-string srl nil 3)))
570     (loop for tuple in (mutex-sql-query ls) collect
571           (destructuring-bind (code atn sab atv) tuple
572             (make-instance 'usat :code code :atn atn :sab sab :atv atv)))))
573
574 (defun find-usty-tui (tui)
575   "Find usty for tui"
576   (ensure-tui-integer tui)
577   (collect-umlisp-query (mrsty (sty) nil tui tui :single t)
578     (make-instance 'usty :tui tui :sty sty)))
579
580 (defun find-usty-sty (sty)
581   "Find usty for a sty"
582   (collect-umlisp-query (mrsty (tui) nil sty sty :single t)
583     (make-instance 'usty :tui (ensure-integer tui) :sty sty)))
584
585 (defun find-usty-all ()
586   "Return list of usty's for all semantic types"
587   (collect-umlisp-query (mrsty (tui) nil nil nil :distinct t)
588     (find-usty-tui tui)))
589
590 (defun find-usab-all ()
591   "Find usab for a key"
592   (collect-umlisp-query (mrsab (vcui rcui vsab rsab son sf sver vstart vend imeta
593                                   rmeta slc scc srl tfr cfr cxty ttyl atnl lat
594                                   cenc curver sabin ssn scit) nil nil nil)
595     (make-instance 'usab :vcui (ensure-integer vcui)
596                    :rcui (ensure-integer rcui) :vsab vsab :rsab rsab :son son
597                    :sf sf :sver sver :vstart vstart :vend vend :imeta imeta
598                    :rmeta rmeta :slc slc :scc scc  :srl (ensure-integer srl)
599                    :tfr (ensure-integer tfr) :cfr (ensure-integer cfr)
600                    :cxty cxty :ttyl ttyl :atnl atnl :lat lat :cenc cenc
601                    :curver curver :sabin sabin :ssn ssn :scit scit)))
602
603 (defun find-usab-by-key (key-name key)
604   "Find usab for a key"
605   (collect-umlisp-query-eval ('mrsab '(vcui rcui vsab rsab son sf sver vstart
606                                        vend imeta rmeta slc scc srl tfr cfr cxty
607                                        ttyl atnl lat cenc curver sabin
608                                        ssn scit)
609                                      nil key-name key :single t)
610      (make-instance 'usab :vcui (ensure-integer vcui)
611                     :rcui (ensure-integer rcui) :vsab vsab :rsab rsab :son son
612                     :sf sf :sver sver :vstart vstart :vend vend :imeta imeta
613                     :rmeta rmeta :slc slc :scc scc :srl (ensure-integer srl)
614                     :tfr (ensure-integer tfr) :cfr (ensure-integer cfr)
615                     :cxty cxty :ttyl ttyl :atnl atnl :lat lat :cenc cenc
616                     :curver curver :sabin sabin
617                     :ssn ssn :scit scit)))
618
619 (defun find-usab-rsab (rsab)
620   "Find usab for rsab"
621   (find-usab-by-key 'rsab rsab))
622
623 (defun find-usab-vsab (vsab)
624   "Find usab for vsab"
625   (find-usab-by-key 'vsab vsab))
626
627 (defun find-cui-max ()
628   (ensure-integer (caar (mutex-sql-query "select max(CUI) from MRCON"))))
629
630 (defun find-umap-cui (cui)
631   (ensure-cui-integer cui)
632   (collect-umlisp-query (mrmap (mapsetsab mapsubsetid maprank fromid fromsid fromexpr
633                                           fromtype fromrule fromres rel rela toid tosid
634                                           toexpr totype torule tores maprule maptype
635                                           mapatn mapatv cvf)
636                                nil mapsetcui cui)
637     (make-instance 'umap :mapsetcui cui :mapsetsab mapsetsab :mapsubsetid mapsubsetid
638                    :maprank (ensure-integer maprank) :fromid fromid :fromsid fromsid
639                    :fromexpr fromexpr :fromtype fromtype :fromrule fromrule :fromres fromres
640                    :rel rel :rela rela :toid toid :tosid tosid :toexpr toexpr :totype totype
641                    :torule torule :tores tores :maprule maprule :maptype maptype :mapatn mapatn
642                    :mapatv mapatv :cvf cvf)))
643
644 ;;;; Cross table find functions
645
646 (defun find-ucon-tui (tui &key (srl *current-srl*))
647   "Find list of ucon for tui"
648   (ensure-tui-integer tui)
649   (collect-umlisp-query (mrsty (cui) srl tui tui :lrl klrl :order (cui asc))
650     (find-ucon-cui (ensure-integer cui) :srl srl)))
651
652 (defun find-ucon-word (word &key (srl *current-srl*) (like nil))
653   "Return list of ucons that match word. Optionally, use SQL's LIKE syntax"
654   (collect-umlisp-query-eval ('mrxw_eng '(cui) srl 'wd word :like like :distinct t
655                                      :lrl 'klrl :order '(cui asc))
656     (find-ucon-cui cui :srl srl)))
657
658 (defun find-ucon-normalized-word (word &key (srl *current-srl*) (like nil))
659   "Return list of ucons that match word, optionally use SQL's LIKE syntax"
660   (collect-umlisp-query-eval ('mrxnw_eng '(cui) srl 'nwd word :like like :distinct t
661                                       :lrl 'klrl :order '(cui asc))
662     (find-ucon-cui cui :srl srl)))
663
664 (defun find-cui-normalized-word (word &key (srl *current-srl*) (like nil))
665   "Return list of cui that match word, optionally use SQL's LIKE syntax"
666   (collect-umlisp-query-eval ('mrxnw_eng '(cui) srl 'nwd word :like like :distinct t
667                                          :lrl 'klrl :order '(cui asc))
668                              cui))
669
670 (defun find-lui-normalized-word (word &key (srl *current-srl*) (like nil))
671   "Return list of cui that match word, optionally use SQL's LIKE syntax"
672   (collect-umlisp-query-eval ('mrxnw_eng '(lui) srl 'nwd word :like like :distinct t
673                                          :lrl 'klrl :order '(cui asc))
674                              lui))
675
676 (defun find-sui-normalized-word (word &key (srl *current-srl*) (like nil))
677   "Return list of cui that match word, optionally use SQL's LIKE syntax"
678   (collect-umlisp-query-eval ('mrxnw_eng '(sui) srl 'nwd word :like like :distinct t
679                                          :lrl 'klrl :order '(cui asc))
680                              sui))
681
682 (defun find-ustr-word (word &key (srl *current-srl*))
683   "Return list of ustrs that match word"
684   (collect-umlisp-query (mrxw_eng (cui sui) srl wd word :lrl klrl
685                                :order (cui asc sui asc))
686     (find-ustr-cuisui (ensure-integer cui) (ensure-integer sui) :srl srl)))
687
688 (defun find-ustr-normalized-word (word &key (srl *current-srl*))
689   "Return list of ustrs that match word"
690   (collect-umlisp-query (mrxnw_eng (cui sui) srl nwd word :lrl klrl
691                                  :order (cui asc sui asc))
692     (find-ustr-cuisui (ensure-integer cui) (ensure-integer sui) :srl srl)))
693
694 (defun find-uterm-word (word &key (srl *current-srl*))
695   "Return list of uterms that match word"
696   (collect-umlisp-query (mrxw_eng (cui lui) srl wd word :lrl klrl
697                                :order (cui asc lui asc))
698     (find-uterm-cuilui (ensure-integer cui) (ensure-integer lui) :srl srl)))
699
700 (defun find-uterm-normalized-word (word &key (srl *current-srl*))
701   "Return list of uterms that match word"
702   (collect-umlisp-query (mrxnw_eng (cui lui) srl nwd word :lrl klrl
703                                  :order (cui asc lui asc))
704     (find-uterm-cuilui (ensure-integer cui) (ensure-integer lui) :srl srl)))
705
706 (defun find-ucon-noneng-word (word &key (srl *current-srl*) (like nil))
707   "Return list of ucons that match non-english word"
708   (collect-umlisp-query-eval ('mrxw_noneng '(cui) srl 'wd word :like like
709                                         :distinct t :lrl 'klrl :order '(cui asc))
710     (find-ucon-cui cui :srl srl)))
711
712 (defun find-ustr-noneng-word (word &key (srl *current-srl*))
713   "Return list of ustrs that match non-english word"
714   (collect-umlisp-query (mrxw_noneng (cui sui) srl wd word :lrl klrl
715                                   :order (cui asc sui asc))
716     (find-ustr-cuisui (ensure-integer cui) (ensure-integer sui) :srl srl)))
717
718 ;; Special tables
719
720 (defun find-usrl-all ()
721   (collect-umlisp-query (usrl (sab srl) nil nil nil :order (sab asc))
722     (make-instance 'usrl :sab sab :srl (ensure-integer srl))))
723
724 ;;; Multiword lookup and score functions
725
726 (defun find-uobj-multiword (str obj-lookup-fun sort-fun key srl
727                             only-exact-if-match limit)
728   (let ((uobjs '()))
729     (dolist (word (delimited-string-to-list str #\space))
730       (setq uobjs (append uobjs (funcall obj-lookup-fun word :srl srl))))
731     (let ((sorted
732            (funcall sort-fun str
733                     (delete-duplicates uobjs :test #'= :key key))))
734       (let ((len (length sorted)))
735         (cond
736          ((zerop len)
737           (return-from find-uobj-multiword nil))
738          ((and only-exact-if-match (multiword-match str (pfstr (first sorted))))
739           (first sorted))
740          (limit
741           (if (and (plusp limit) (> len limit))
742               (subseq sorted 0 limit)
743             limit))
744          (t
745           sorted))))))
746
747 (defun find-ucon-multiword (str &key (srl *current-srl*)
748                                      (only-exact-if-match t)
749                                      limit)
750   (find-uobj-multiword str #'find-ucon-word #'sort-score-pfstr-str
751                        #'cui srl only-exact-if-match limit))
752
753 (defun find-uterm-multiword (str &key (srl *current-srl*)
754                                       (only-exact-if-match t)
755                                       limit)
756   (find-uobj-multiword str #'find-uterm-word #'sort-score-pfstr-str
757                        #'lui srl only-exact-if-match limit))
758
759 (defun find-ustr-multiword (str &key (srl *current-srl*)
760                                      (only-exact-if-match t)
761                                      limit)
762   (find-uobj-multiword str #'find-ustr-word #'sort-score-ustr-str
763                        #'sui srl only-exact-if-match limit))
764
765 (defun sort-score-pfstr-str (str uobjs)
766   "Return list of sorted and scored ucons. Score by match of str to ucon-pfstr"
767   (sort-score-umlsclass-str uobjs str #'pfstr))
768
769 (defun sort-score-ustr-str (str ustrs)
770   "Return list of sorted and scored ucons. Score by match of str to ucon-pfstr"
771   (sort-score-umlsclass-str ustrs str #'str))
772
773 (defun sort-score-umlsclass-str (objs str lookup-func)
774   "Sort a list of objects based on scoring to a string"
775   (let ((scored '()))
776     (dolist (obj objs)
777       (push (list obj (score-multiword-match str (funcall lookup-func obj)))
778        scored))
779     (mapcar #'car (sort scored #'> :key #'cadr))))
780
781
782 ;;; LEX SQL functions
783
784 (defun find-lexterm-eui (eui)
785   (ensure-eui-integer eui)
786   (collect-umlisp-query (lrwd (wrd) nil eui eui :single t)
787     (make-instance 'lexterm :eui eui :wrd wrd)))
788
789 (defun find-lexterm-word (wrd)
790   (collect-umlisp-query (lrwd (eui) nil wrd wrd)
791     (make-instance 'lexterm :eui (ensure-integer eui)
792                    :wrd (copy-seq wrd))))
793
794 ;; LEX SQL Read functions
795
796 (defun find-labr-eui (eui)
797   (ensure-eui-integer eui)
798   (collect-umlisp-query (lrabr (bas abr eui2 bas2) nil eui eui)
799     (make-instance 'labr :eui eui :bas bas :abr abr :bas2 bas2
800                    :eui2 (ensure-integer eui2))))
801
802 (defun find-labr-bas (bas)
803   (collect-umlisp-query (labr (eui abr eui2 bas2) nil bas bas)
804     (make-instance 'labr :eui (ensure-integer eui) :abr abr :bas2 bas2
805                    :bas (copy-seq bas) :eui2 (ensure-integer eui2))))
806
807 (defun find-lagr-eui (eui)
808   (ensure-eui-integer eui)
809   (collect-umlisp-query (lragr (str sca agr cit bas) nil eui eui)
810     (make-instance 'lagr :eui eui :str str :sca sca :agr agr
811                    :cit cit :bas bas)))
812
813 (defun find-lcmp-eui (eui)
814   (ensure-eui-integer eui)
815   (collect-umlisp-query (lrcmp (bas sca com) nil eui eui)
816     (make-instance 'lcmp :eui eui :bas bas :sca sca :com com)))
817
818 (defun find-lmod-eui (eui)
819   (ensure-eui-integer eui)
820   (collect-umlisp-query (lrmod (bas sca psn_mod fea) nil eui eui)
821     (make-instance 'lmod :eui eui :bas bas :sca sca :psnmod psn_mod :fea fea)))
822
823 (defun find-lnom-eui (eui)
824   (ensure-eui-integer eui)
825   (collect-umlisp-query (lrnom (bas sca eui2 bas2 sca2) nil eui eui)
826     (make-instance 'lnom :eui eui :bas bas :sca sca :bas2 bas2 :sca2 sca2
827                    :eui2 (ensure-integer eui2))))
828
829 (defun find-lprn-eui (eui)
830   (ensure-eui-integer eui)
831   (collect-umlisp-query (lrprn (bas num gnd cas pos qnt fea) nil eui eui)
832     (make-instance 'lprn :eui eui :bas bas :num num :gnd gnd
833                    :cas cas :pos pos :qnt qnt :fea fea)))
834
835 (defun find-lprp-eui (eui)
836   (ensure-eui-integer eui)
837   (collect-umlisp-query (lrprp (bas str sca fea) nil eui eui)
838     (make-instance 'lprp :eui eui :bas bas :str str :sca sca :fea fea)))
839
840 (defun find-lspl-eui (eui)
841   (ensure-eui-integer eui)
842   (collect-umlisp-query (lrspl (spv bas) nil eui eui)
843     (make-instance 'lspl :eui eui :spv spv :bas bas)))
844
845 (defun find-ltrm-eui (eui)
846   (ensure-eui-integer eui)
847   (collect-umlisp-query (lrtrm (bas gen) nil eui eui)
848     (make-instance 'ltrm :eui eui :bas bas :gen gen)))
849
850 (defun find-ltyp-eui (eui)
851   (ensure-eui-integer eui)
852   (collect-umlisp-query (lrtyp (bas sca typ) nil eui eui)
853     (make-instance 'ltyp :eui eui :bas bas :sca sca :typ typ)))
854
855 (defun find-lwd-wrd (wrd)
856   (make-instance 'lwd :wrd wrd
857                  :euilist (collect-umlisp-query (lrwd (eui) nil wrd wrd)
858                                                 (ensure-integer eui))))
859
860 ;;; Semantic Network SQL access functions
861
862 (defun find-sdef-ui (ui)
863   (collect-umlisp-query (srdef (rt sty_rl stn_rtn def ex un rh abr rin)
864                             nil ui ui :single t)
865     (make-instance 'sdef :rt rt :ui ui :styrl sty_rl :stnrtn stn_rtn
866                    :def def :ex ex :un un :rh rh :abr abr :rin rin)))
867
868 (defun find-sstre1-ui (ui)
869   (collect-umlisp-query (srstre1 (ui2 ui3) nil ui ui)
870     (make-instance 'sstre1 :ui ui :ui2 (ensure-integer ui2)
871                    :ui3 (ensure-integer ui3))))
872
873 (defun find-sstre1-ui2 (ui2)
874   (collect-umlisp-query (srstre1 (ui ui3) nil ui2 ui2)
875     (make-instance 'sstre1 :ui (ensure-integer ui) :ui2 ui2
876                    :ui3 (ensure-integer ui3))))
877
878 (defun find-sstr-rl (rl)
879   (collect-umlisp-query (srstre (sty_rl sty_rl2 ls) nil rl rl)
880     (make-instance 'sstr :rl rl :styrl sty_rl :styrl2 sty_rl2 :ls ls)))
881
882 (defun find-sstre2-sty (sty)
883   (collect-umlisp-query (srstre2 (rl sty2) nil sty sty)
884     (make-instance 'sstre2 :sty (copy-seq sty) :rl rl :sty2 sty2)))
885
886 (defun find-sstr-styrl (styrl)
887   (collect-umlisp-query (srstr (rl sty_rl2 ls) nil styrl styrl)
888     (make-instance 'sstr :styrl styrl :rl rl :styrl2 sty_rl2 :ls ls)))
889
890
891 ;;; **************************
892 ;;; Local Classes
893 ;;; **************************
894
895
896 (defun make-ustats ()
897   (with-sql-connection (conn)
898     (ignore-errors (sql-execute "drop table USTATS" conn))
899     (sql-execute "create table USTATS (NAME varchar(160), COUNT bigint, SRL integer)" conn)
900
901     (dotimes (srl 5)
902       (insert-ustats-count conn "Concept Count" "MRCONSO" "distinct CUI" "KCUILRL" srl)
903       (insert-ustats-count conn "Term Count" "MRCONSO" "distinct KCUILUI" "KCUILRL" srl)
904       (insert-ustats-count conn "Distinct Term Count" "MRCONSO" "distinct LUI" "KLUILRL" srl)
905       (insert-ustats-count conn "String Count" "MRCONSO" "*" "KSUILRL" srl)
906       (insert-ustats-count conn "Distinct String Count" "MRCONSO" "distinct SUI" "KSUILRL" srl)
907       (insert-ustats-count conn "Hierarchcy" "MRHIER" "*" "KSRL" srl)
908       (insert-ustats-count conn "Mappings" "MRMAP" "*" "KSRL" srl)
909       (insert-ustats-count conn "Simple Mappings" "MRSMAP" "*" "KSRL" srl)
910       (insert-ustats-count conn "Co-occuring Concept Count" "MRCOC" "*" "KLRL" srl)
911       (insert-ustats-count conn "Definition Count" "MRDEF" "*" "KSRL" srl)
912       (insert-ustats-count conn "Rank Count" "MRRANK" "*" "KSRL" srl)
913       (insert-ustats-count conn "Relationship Count" "MRREL" "*" "KSRL" srl)
914       (insert-ustats-count conn "Semantic Type Count" "MRSTY" "*" "KLRL" srl)
915       (insert-ustats-count conn "Simple Attribute Count" "MRSAT" "*" "KSRL" srl)
916       (insert-ustats-count conn "Source Abbreviation Count" "MRSAB" "*" "SRL" srl)
917       (insert-ustats-count conn "Word Index Count" "MRXW_ENG" "*" "KLRL" srl)
918       (insert-ustats-count conn "Normalized Word Index Count" "MRXNW_ENG" "*" "KLRL" srl)
919       (insert-ustats-count conn "Normalized String Index Count" "MRXNS_ENG" "*" "KLRL" srl))
920     (sql-execute "create index USTATS_SRL on USTATS (SRL)" conn))
921   (find-ustats-all))
922
923 (defun insert-ustats-count (conn name table count-variable srl-control srl)
924   (insert-ustats conn name (find-count-table conn table srl count-variable srl-control) srl))
925
926 (defun find-count-table (conn table srl count-variable srl-control)
927   (cond
928    ((stringp srl-control)
929     (ensure-integer
930      (caar (sql-query (format nil "select count(~a) from ~a where ~a <= ~d"
931                               count-variable table srl-control srl)
932                       conn))))
933    ((null srl-control)
934     (ensure-integer
935      (caar (sql-query (format nil "select count(~a) from ~a"
936                               count-variable table )
937                       conn))))
938    (t
939     (error "Unknown srl-control")
940     0)))
941
942 (defun insert-ustats (conn name count srl)
943   (sql-execute (format nil "insert into USTATS (name,count,srl) values ('~a',~d,~d)"
944                        name count (if srl srl 3))
945                conn))
946
947 (defun find-ustats-all (&key (srl *current-srl*))
948   (if srl
949       (collect-umlisp-query (ustats (name count srl) nil srl srl
950                                     :order (name asc))
951                             (make-instance 'ustats :name name
952                                            :hits (ensure-integer count)
953                                            :srl (ensure-integer srl)))
954     (collect-umlisp-query (ustats (name count srl) nil nil nil
955                                   :order (name asc))
956                           (make-instance 'ustats :name name
957                                          :hits (ensure-integer count)
958                                          :srl (ensure-integer srl)))))
959
960 (defun find-ustats-srl (srl)
961   (collect-umlisp-query (ustats (name count) nil srl srl :order (name asc))
962                            (make-instance 'ustats :name name :hits (ensure-integer count))))
963
964
965
966 (defun find-bsab-sab (sab)
967  (collect-umlisp-query (bonus_sab (name count) nil sab sab :single t)
968      (make-instance 'bsab :sab sab :name name :hits (ensure-integer count))))
969
970 (defun find-bsab-all ()
971  (collect-umlisp-query (bonus_sab (sab name count) nil nil nil :order (sab asc))
972      (make-instance 'bsab :sab sab :name name :hits (ensure-integer count))))
973
974 (defun find-btty-tty (tty)
975  (collect-umlisp-query (bonus_tty (name count) nil tty tty :single t)
976      (make-instance 'btty :tty tty :name name :hits (ensure-integer count))))
977
978 (defun find-btty-all ()
979  (collect-umlisp-query (bonus_tty (tty name count) nil nil nil :order (tty asc))
980   (make-instance 'btty :tty tty :name name :hits (ensure-integer count))))
981
982 (defun find-brel-rel (rel)
983   (collect-umlisp-query (bonus_rel (sab sl rel rela count) nil rel rel)
984     (make-instance 'brel :sab sab :sl sl :rel rel :rela rela
985                     :hits (ensure-integer count))))