anchor.diff:  (defclass kanji-text ()
     ((id :reader id :col-type serial)
      (seq :reader seq :col-type integer :initarg :seq)
  -   (text :reader text :col-type string :initarg :text))
  -  (:metaclass dao-class)
  -  (:keys id))
  +   (text :reader text :col-type string :initarg :text)
  +   (ord :reader ord :col-type integer :initarg :ord)
  +   )
  +  (:metaclass dao-class)
  +  (:keys id))
  +
  +(defmethod print-object ((obj kanji-text) stream)
  +  (print-unreadable-object (obj stream :type t :identity nil)
  +    (princ (text obj) stream)))
   
   (deftable kanji-text
     (!dao-def)
     (!index 'seq)
  +  (!index 'ord)
     (!index 'text)
     (!foreign 'entry 'seq))
   
  -(defclass reading-text ()
  +(defclass kana-text ()
     ((id :reader id :col-type serial)
      (seq :reader seq :col-type integer :initarg :seq)
  -   (text :reader text :col-type string :initarg :text))
  -  (:metaclass dao-class)
  -  (:keys id))
  -
  -(deftable reading-text
  +   (text :reader text :col-type string :initarg :text)
  +   (ord :reader ord :col-type integer :initarg :ord)
  +   )
  +  (:metaclass dao-class)
  +  (:keys id))
  +
  +(defmethod print-object ((obj kana-text) stream)
  +  (print-unreadable-object (obj stream :type t :identity nil)
  +    (princ (text obj) stream)))
  +
  +(deftable kana-text
     (!dao-def)
     (!index 'seq)
  +  (!index 'ord)
     (!index 'text)
     (!foreign 'entry 'seq))
   
  +(defclass sense ()
  +  ((id :reader id :col-type serial)
  +   (seq :reader seq :col-type integer :initarg :seq)
  +   (ord :reader ord :col-type integer :initarg :ord))
  +  (:metaclass dao-class)
  +  (:keys id))
  +
  +(deftable sense
  +  (!dao-def)
  +  (!index 'seq)
  +  (!index 'ord)
  +  (!foreign 'entry 'seq))
  +
  +(defclass gloss ()
  +  ((id :reader id :col-type serial)
  +   (sense-id :reader sense-id :col-type integer :initarg :sense-id)
  +   (text :reader text :col-type string :initarg :text)
  +   (ord :reader ord :col-type integer :initarg :ord))
  +  (:documentation "English meaning")
  +  (:metaclass dao-class)
  +  (:keys id))
  +
  +(defmethod print-object ((obj gloss) stream)
  +  (print-unreadable-object (obj stream :type t :identity nil)
  +    (format stream "(~a) ~a" (ord obj) (text obj))))
  +
  +(deftable gloss
  +  (!dao-def)
  +  (!index 'sense-id)
  +  (!index 'ord)
  +  (!foreign 'sense 'sense-id 'id))
  +
  +(defclass pos ()
  +  ((id :reader id :col-type serial)
  +   (sense-id :reader sense-id :col-type integer :initarg :sense-id)
  +   (text :reader text :col-type string :initarg :text)
  +   (ord :reader ord :col-type integer :initarg :ord))
  +  (:documentation "Part of speech tags")
  +  (:metaclass dao-class)
  +  (:keys id))
  +
  +(defmethod print-object ((obj pos) stream)
  +  (print-unreadable-object (obj stream :type t :identity nil)
  +    (princ (text obj) stream)))
  +
  +(deftable pos
  +  (!dao-def)
  +  (!index 'sense-id)
  +  (!index 'ord)
  +  (!index 'text)
  +  (!foreign 'sense 'sense-id 'id))
  +
   (defun init-tables ()
     (with-connection *connection*
  -    (let ((tables '(entry kanji-text reading-text)))
  +    (let ((tables '(entry kanji-text kana-text sense gloss pos)))
         (loop for table in (reverse tables)
            do (query (:drop-table :if-exists table)))
         (loop for table in tables
            do (create-table table)))))
   
  +(defmacro do-node-list-ord ((ord-var node-var node-list) &body body)
  +  `(let ((,ord-var 0))
  +     (dom:do-node-list (,node-var ,node-list)
  +       ,@body
  +       (incf ,ord-var))))
  +
   (defun insert-readings (node-list tag table seq)
  -  (dom:do-node-list (node node-list)
  +  (do-node-list-ord (ord node node-list)
       (let* ((reading-node (dom:item (dom:get-elements-by-tag-name node tag) 0))
              (reading-text (node-text reading-node)))
  -      (make-dao table :seq seq :text reading-text))))
  +      (make-dao table :seq seq :text reading-text :ord ord))
  +    (incf ord)))
  +
  +(defun insert-sense-traits (node-list table sense-id)
  +  (do-node-list-ord (ord node node-list)
  +    (make-dao table :sense-id sense-id :text (node-text node) :ord ord)))
  +
  +(defun insert-senses (node-list seq)
  +  (do-node-list-ord (ord node node-list)
  +    (let ((sense-id (id (make-dao 'sense :seq seq :ord ord))))
  +      (insert-sense-traits (dom:get-elements-by-tag-name node "pos") 'pos sense-id)
  +      (insert-sense-traits (dom:get-elements-by-tag-name node "gloss") 'gloss sense-id))))
   
   (defun load-entry (content)
     (let* ((parsed (cxml:parse content (cxml-dom:make-dom-builder)))
            (entseq-node (dom:item (dom:get-elements-by-tag-name parsed "ent_seq") 0))
  -         (seq (parse-integer (node-text entseq-node))))
  -    (make-dao 'entry :seq seq :content content)
  -    (let ((kana-nodes (dom:get-elements-by-tag-name parsed "r_ele"))
  -          (kanji-nodes (dom:get-elements-by-tag-name parsed "k_ele")))
  -      (insert-readings kana-nodes "reb" 'reading-text seq)
  -      (insert-readings kanji-nodes "keb" 'kanji-text seq))))
  +         (seq (parse-integer (node-text entseq-node)))
  +         (entry-obj (make-dao 'entry :seq seq :content content)))
  +    (let* ((kanji-nodes (dom:get-elements-by-tag-name parsed "k_ele"))
  +           (kana-nodes (dom:get-elements-by-tag-name parsed "r_ele"))
  +           (n-kanji (dom:length kanji-nodes))
  +           (n-kana (dom:length kana-nodes))
  +           (sense-nodes (dom:get-elements-by-tag-name parsed "sense")))
  +      (insert-readings kanji-nodes "keb" 'kanji-text seq)
  +      (insert-readings kana-nodes "reb" 'kana-text seq)
  +      (insert-senses sense-nodes seq)
  +      (setf (n-kanji entry-obj) n-kanji
  +            (n-kana entry-obj) n-kana)
  +      (update-dao entry-obj))))
  +
  +(defun fix-entities (source)
  +  "replaces entity definitions with abbreviations"
  +  (let ((entity-hash (cxml::dtd-gentities (cxml::dtd (slot-value source 'cxml::context)))))
  +    (maphash 
  +     (lambda (name entdef)
  +       (unless (member name '("lt" "gt" "amp" "apos" "quot") :test #'equal)
  +         (setf (cxml::entdef-value (cdr entdef)) name)))
  +     entity-hash)))
       
   (defun load-jmdict (&optional (path *jmdict-path*))
  +  (init-tables)
     (with-connection *connection*
       (klacks:with-open-source (source (cxml:make-source path))
  -      (loop for cnt from 1
  +      (klacks:find-element source "JMdict")
  +      (fix-entities source)
  +      (loop for cnt from 1 to 1000
            while (klacks:find-element source "entry")
            do
              (let ((content (klacks:serialize-element source (cxml:make-string-sink))))
  
positive.code: 
  (defclass entry ()
    ((seq :reader seq :col-type integer :initarg :seq)
     (content :reader content :col-type string :initarg :content))
    (:metaclass dao-class)
    (:keys seq))
  
  (deftable entry
    (!dao-def))
  
negative.code: (in-package #:ichiran/dict)
  
  (defparameter *jmdict-path* #p"foobar")
  
  (defparameter *jmdict-data* #p"foobar")
  
  (defparameter *connection* '("jmdict" "postgres" "" "localhost"))
  
  