-
-;;; Accessors (read on demand)
-
-;; defines a slot-unbound method for class and slot-name, fills
-;; the slot by calling reader function with the slot values of
-;; the instance's reader-keys
-(defmacro def-lazy-reader (class slot-name reader &rest reader-keys)
- (let* ((the-slot-name (gensym))
- (the-class (gensym))
- (the-instance (gensym))
- (keys '()))
- (dolist (key reader-keys)
- (push (list 'slot-value the-instance (list 'quote key)) keys))
- (setq keys (nreverse keys))
- `(defmethod slot-unbound (,the-class (,the-instance ,class)
- (,the-slot-name (eql ',slot-name)))
- (declare (ignore ,the-class))
- (setf (slot-value ,the-instance ,the-slot-name)
- (,reader ,@keys)))))
-
-(def-lazy-reader ucon s#term find-uterm-cui cui)
-(def-lazy-reader ucon s#def find-udef-cui cui)
-(def-lazy-reader ucon s#sty find-usty-cui cui)
-(def-lazy-reader ucon s#rel find-urel-cui cui)
-(def-lazy-reader ucon s#coc find-ucoc-cui cui)
-(def-lazy-reader ucon s#lo find-ulo-cui cui)
-(def-lazy-reader ucon s#atx find-uatx-cui cui)
-(def-lazy-reader ucon s#sat find-usat-ui cui)
-
-;; For uterms
-(def-lazy-reader uterm s#str find-ustr-cuilui cui lui)
-(def-lazy-reader uterm s#sat find-usat-ui cui lui)
-
-;; For ustrs
-(def-lazy-reader ustr s#sat find-usat-ui cui lui sui)
-(def-lazy-reader ustr s#cxt find-ucxt-cuisui cui sui)
-(def-lazy-reader ustr s#so find-uso-cuisui cui sui)
-
-;;; Object lookups
-
-;;; Lookup functions for uterms,ustr in ucons
-
-(defun find-uterm-in-ucon (ucon lui)
- (find lui (s#term ucon) :key #'lui :test 'equal))
-
-(defun find-ustr-in-uterm (uterm sui)
- (find sui (s#str uterm) :key #'sui :test 'equal))
-
-(defun find-ustr-in-ucon (ucon sui)
- (let ((found-ustr nil))
- (dolist (uterm (s#term ucon))
- (unless found-ustr
- (dolist (ustr (s#str uterm))
- (unless found-ustr
- (when (string-equal sui (sui ustr))
- (setq found-ustr ustr))))))
- found-ustr))
-
-
-(defun find-ucon-cui (cui &key (srl *current-srl*))
- "Find ucon for a cui"
- (if (stringp cui)
- (setq cui (parse-cui cui)))
- (if cui
- (let ((ls (format nil "select KPFSTR,KCUILRL from MRCON where CUI=~d"
- cui)))
- (if srl
- (string-append ls (format nil " and KCUILRL <= ~d limit 1" srl))
- (string-append ls " limit 1"))
- (kmrcl:awhen (car (mutex-sql-query ls))
- (make-instance 'ucon :cui cui :pfstr (car kmrcl::it)
- :lrl (ensure-integer (cadr kmrcl::it)))))
- nil))
+(defmacro query-string (table fields srl where-name where-value
+ &key (lrl "KCUILRL") single distinct order like limit
+ filter)
+ (let* ((%%fields (format nil "SELECT ~A~{~:@(~A~)~^,~} FROM ~:@(~A~)"
+ (if distinct "DISTINCT " "") fields table))
+ (%%order (if order (format nil " ORDER BY ~{~:@(~A~) ~(~A~)~^,~}"
+ order)
+ ""))
+ (%%lrl (format nil " AND ~:@(~A~)<=" lrl))
+ (%%where (when where-name
+ (format nil " WHERE ~:@(~A~)~A" where-name
+ (if like " like " ""))))
+ (%filter (gensym "FILTER-"))
+ (%single (gensym "SINGLE-"))
+ (%limit (gensym "LIMIT-")))
+ `(let ((,%limit ,limit)
+ (,%single ,single)
+ (,%filter ,filter))
+ (concatenate
+ 'string
+ ,%%fields
+ ,@(when %%where (list %%where))
+ ,@(when %%where
+ `((typecase ,where-value
+ #+ignore
+ (fixnum
+ (concatenate 'string "='" (prefixed-fixnum-string ,where-value #\0 10) "'"))
+ (number
+ (concatenate 'string "='" (write-to-string ,where-value) "'"))
+ (null
+ " IS NULL")
+ (t
+ (format nil ,(if like "'%~A%'" "='~A'") ,where-value)))))
+ (if ,%filter (concatenate 'string
+ ,(if %%where " AND " " WHERE ")
+ ,%filter) "")
+ (if ,srl (concatenate 'string ,%%lrl (write-to-string ,srl)) "")
+ ,@(when %%order (list %%order))
+ (cond
+ ((and ,%single ,%limit)
+ (error "Can't set single (~S) and limit (~S)" ,%single ,%limit))
+ (,%single
+ " LIMIT 1")
+ (,%limit
+ (format nil " LIMIT ~D" ,%limit))
+ (t
+ ""))))))
+
+(defun query-string-eval (table fields srl where-name where-value
+ &key (lrl "KCUILRL") single distinct order like limit filter)
+ (when single (setq limit 1))
+ (concatenate
+ 'string
+ (format nil "SELECT ~A~{~:@(~A~)~^,~} FROM ~:@(~A~)"
+ (if distinct "DISTINCT " "") fields table)
+ (if where-name (format nil " WHERE ~:@(~A~)" where-name) "")
+ (if where-name
+ (format nil
+ (typecase where-value
+ (number "='~D'")
+ (null " IS NULL")
+ (t
+ (if like " LINK '%~A%""='~A'")))
+ where-value)
+ "")
+ (if filter (concatenate 'string " AND " filter) nil)
+ (if srl (format nil " AND ~:@(~A~)<=~D" lrl srl) "")
+ (if order (format nil " ORDER BY ~{~:@(~A~) ~(~A~)~^,~}" order) "")
+ (if limit (format nil " LIMIT ~D" limit) "")))
+
+
+(defmacro umlisp-query (table fields srl where-name where-value
+ &key (lrl "KCUILRL") single distinct order like
+ limit filter (query-cmd 'mutex-sql-query))
+ "Query the UMLisp database. Return a list of umlisp objects whose name
+is OBJNAME from TABLE where WHERE-NAME field = WHERE-VALUE with FIELDS"
+ `(,query-cmd
+ (query-string ,table ,fields ,srl ,where-name ,where-value
+ :lrl ,lrl :single ,single :distinct ,distinct :order ,order :like ,like
+ :filter ,filter :limit ,limit)))
+
+(defmacro umlisp-query-eval (table fields srl where-name where-value
+ &key (lrl "KCUILRL") single distinct order like
+ filter limit)
+ "Query the UMLisp database. Return a list of umlisp objects whose name
+is OBJNAME from TABLE where WHERE-NAME field = WHERE-VALUE with FIELDS"
+ `(mutex-sql-query
+ (query-string-eval ,table ,fields ,srl ,where-name ,where-value
+ :lrl ,lrl :single ,single :distinct ,distinct :order ,order :like ,like
+ :filter ,filter :limit ,limit)))
+
+;; only WHERE-VALUE and SRL are evaluated
+(defmacro collect-umlisp-query ((table fields srl where-name where-value
+ &key (lrl "KCUILRL") distinct single
+ order like (query-cmd 'mutex-sql-query)
+ filter limit)
+ &body body)
+ (let ((value (gensym))
+ (r (gensym)))
+ (if single
+ (if (and limit (> limit 1))
+ (error "Can't set limit along with single.")
+ `(let* ((,value ,where-value)
+ (tuple (car (umlisp-query ,table ,fields ,srl ,where-name ,value
+ :lrl ,lrl :single ,single
+ :distinct ,distinct :order ,order
+ :like ,like :filter ,filter
+ :query-cmd ,query-cmd))))
+ ,@(unless where-name `((declare (ignore ,value))))
+ (when tuple
+ (destructuring-bind ,fields tuple
+ ,@body))))
+ `(let ((,value ,where-value))
+ ,@(unless where-name `((declare (ignore ,value))))
+ (let ((,r '()))
+ (dolist (tuple (umlisp-query ,table ,fields ,srl ,where-name ,value
+ :lrl ,lrl :single ,single :distinct ,distinct
+ :order ,order :filter ,filter :like ,like
+ :limit ,limit))
+ (push (destructuring-bind ,fields tuple ,@body) ,r))
+ (nreverse ,r))
+ #+ignore
+ (loop for tuple in
+ (umlisp-query ,table ,fields ,srl ,where-name ,value
+ :lrl ,lrl :single ,single :distinct ,distinct
+ :order ,order :like ,like :filter ,filter :limit ,limit)
+ collect (destructuring-bind ,fields tuple ,@body))))))
+
+(defmacro collect-umlisp-query-eval ((table fields srl where-name where-value
+ &key (lrl "KCUILRL") distinct single
+ order like filter limit)
+ &body body)
+ (let ((value (gensym))
+ (r (gensym))
+ (eval-fields (cadr fields)))
+ (if single
+ `(let* ((,value ,where-value)
+ (tuple (car (umlisp-query-eval ,table ,fields ,srl ,where-name ,value
+ :lrl ,lrl :single ,single
+ :distinct ,distinct :order ,order
+ :like ,like :filter ,filter
+ :limit ,limit))))
+ (when tuple
+ (destructuring-bind ,eval-fields tuple
+ ,@body)))
+ `(let ((,value ,where-value)
+ (,r '()))
+ (dolist (tuple (umlisp-query-eval ,table ,fields ,srl ,where-name ,value
+ :lrl ,lrl :single ,single :distinct ,distinct
+ :order ,order :like ,like
+ :filter ,filter :limit ,limit))
+ (push (destructuring-bind ,eval-fields tuple ,@body) ,r))
+ (nreverse ,r)
+ #+ignore
+ (loop for tuple in
+ (umlisp-query-eval ,table ,fields ,srl ,where-name ,value
+ :lrl ,lrl :single ,single :distinct ,distinct
+ :order ,order :like ,like :filter ,filter
+ :limit ,limit)
+ collect (destructuring-bind ,eval-fields tuple ,@body))))))
+
+;;;
+;;; Read from SQL database
+
+(defmacro ensure-cui-integer (cui)
+ `(if (stringp ,cui)
+ (setq ,cui (parse-cui ,cui))
+ ,cui))
+
+(defmacro ensure-lui-integer (lui)
+ `(if (stringp ,lui)
+ (setq ,lui (parse-lui ,lui))
+ ,lui))
+
+(defmacro ensure-sui-integer (sui)
+ `(if (stringp ,sui)
+ (setq ,sui (parse-sui ,sui))
+ ,sui))
+
+(defmacro ensure-aui-integer (aui)
+ `(if (stringp ,aui)
+ (setq ,aui (parse-aui ,aui))
+ ,aui))
+
+(defmacro ensure-rui-integer (rui)
+ `(if (stringp ,rui)
+ (setq ,rui (parse-rui ,rui))
+ ,rui))
+
+(defmacro ensure-tui-integer (tui)
+ `(if (stringp ,tui)
+ (setq ,tui (parse-tui ,tui))
+ ,tui))
+
+(defmacro ensure-eui-integer (eui)
+ `(if (stringp ,eui)
+ (setq ,eui (parse-eui ,eui))
+ ,eui))
+
+(defun make-ucon-cui (cui)
+ (ensure-cui-integer cui)
+ (when cui
+ (make-instance 'ucon :cui cui)))
+
+(defun find-ucon-cui (cui &key (srl *current-srl*) without-pfstr)
+ "Find ucon for a cui. If set SAB, the without-pfstr is on by default"
+ (ensure-cui-integer cui)
+ (unless cui (return-from find-ucon-cui nil))
+
+ (if without-pfstr
+ (collect-umlisp-query (mrconso (kcuilrl) srl cui cui :single t)
+ (make-instance 'ucon :cui cui :lrl (ensure-integer kcuilrl)
+ :pfstr nil)))
+ (or
+ (collect-umlisp-query (mrconso (kcuilrl str) srl cui cui :single t :filter "KPFENG=1")
+ (make-instance 'ucon :cui cui :pfstr str
+ :lrl kcuilrl))
+ (collect-umlisp-query (mrconso (kcuilrl str) srl cui cui :single t)
+ (make-instance 'ucon :cui cui :pfstr str
+ :lrl kcuilrl))))
+
+(defun find-uconso-cui (cui &key sab (srl *current-srl*))
+ "Find uconso for a cui."
+ (ensure-cui-integer cui)
+ (unless cui (return-from find-uconso-cui nil))
+
+ (collect-umlisp-query (mrconso (lat ts lui stt sui ispref aui saui scui sdui sab tty code str
+ srl suppress cvf kpfeng kcuisui kcuilui kcuilrl
+ kluilrl ksuilrl) srl cui cui
+ :filter (if sab (concatenate 'string "SAB='" sab "'") nil))
+ (make-instance 'uconso :cui cui :lat lat :ts ts :lui lui :stt stt :sui sui :ispref ispref
+ :aui aui :saui saui :scui scui :sdui sdui :sab sab :tty tty :code code
+ :str str :srl srl :suppress suppress :cvf cvf :kpfeng kpfeng
+ :kcuisui kcuisui :kcuilui kcuilui :kcuilrl kcuilrl :kluilrl kluilrl
+ :ksuilrl ksuilrl)))
+
+(defun find-uconso-sui (sui &key sab (srl *current-srl*))
+ "Find uconso for a sui. If set SAB, the without-pfstr is on by default"
+ (ensure-sui-integer sui)
+ (unless (and sui (stringp sab))
+ (return-from find-uconso-sui nil))
+
+ (collect-umlisp-query (mrconso (cui lat ts lui stt sui ispref aui saui scui sdui sab tty code str
+ srl suppress cvf kpfeng kcuisui kcuilui kcuilrl
+ kluilrl ksuilrl) srl sui sui
+ :filter (if sab (concatenate 'string "SAB='" sab "'") nil))
+ (make-instance 'uconso :cui cui :lat lat :ts ts :lui lui :stt stt :sui sui :ispref ispref
+ :aui aui :saui saui :scui scui :sdui sdui :sab sab :tty tty :code code
+ :str str :srl srl :suppress suppress :cvf cvf :kpfeng kpfeng
+ :kcuisui kcuisui :kcuilui kcuilui :kcuilrl kcuilrl :kluilrl kluilrl
+ :ksuilrl ksuilrl)))
+
+(defun find-pfstr-cui (cui &key (srl *current-srl*))
+ "Find preferred string for a cui"
+ (ensure-cui-integer cui)
+ (or
+ (collect-umlisp-query (mrconso (str) srl cui cui :distinct t
+ :filter " KPFENG=1" :single t)
+ str)
+ (collect-umlisp-query (mrconso (str) srl cui cui :distinct t
+ :single t)
+ str)))
+
+(defun find-lrl-cui (cui &key (srl *current-srl*))
+ "Find LRL for a cui"
+ (ensure-cui-integer cui)
+ (collect-umlisp-query (mrconso (kcuilrl) srl cui cui :distinct t :single t)
+ (ensure-integer kcuilrl)))