+(defmethod sql-name ((cl hyperobject-class))
+ "Return name of SQL table for a class"
+ (let-if (it (slot-value cl 'sql-name))
+ (let* ((name (if (consp it) (car it) it))
+ (lisp-name (if name name (class-name cl))))
+ (lisp-name-to-sql-name lisp-name))))
+
+(defmethod sql-name ((esd hyperobject-esd))
+ (let-if (it (slot-value esd 'sql-name))
+ (let* ((name (if (consp it) (car it) it))
+ (lisp-name (if name name (slot-definition-name esd))))
+ (lisp-name-to-sql-name lisp-name))))
+
+
+(defun lisp-name-to-sql-name (lisp)
+ "Convert a lisp name (atom or list, string or symbol) into a canonical
+SQL name"
+ (unless (stringp lisp)
+ (setq lisp (write-to-string lisp)))
+ (let ((sql (make-string (length lisp))))
+ (dotimes (i (length lisp))
+ (declare (fixnum i))
+ (let ((c (char lisp i)))
+ (case c
+ (#\- #\_)
+ (#\$ #\_)
+ (#\+ #\_)
+ (otherwise c))))
+ (string-upcase sql)))
+
+
+(defun define-inverse (class esd)
+ "Define an inverse function for a slot"
+ (let ((inverse (slot-value esd 'inverse)))