r9169: allow :metaclass in def-view-class
[clsql.git] / sql / objects.lisp
index a84bf3be9c44c19d843feb4f7632aafaabdd51d7..d8181d1fb763b6ae6034cd4a3d7c4a6dc631a4bb 100644 (file)
 (defmethod database-pkey-constraint ((class standard-db-class) database)
   (let ((keylist (mapcar #'view-class-slot-column (keyslots-for-class class))))
     (when keylist 
-      (format nil "CONSTRAINT ~APK PRIMARY KEY~A"
-              (database-output-sql (view-table class) database)
-              (database-output-sql keylist database)))))
+      (convert-to-db-default-case
+       (format nil "CONSTRAINT ~APK PRIMARY KEY~A"
+              (database-output-sql (view-table class) database)
+              (database-output-sql keylist database))
+       database))))
 
 
 (defun create-view-from-class (view-class-name
@@ -113,8 +115,6 @@ the view. The argument DATABASE has a default value of
 ;; Drop the tables which store the given view class
 ;;
 
-#.(locally-enable-sql-reader-syntax)
-
 (defun drop-view-from-class (view-class-name &key (database *default-database*))
   "Deletes a view or base table from DATABASE based on VIEW-CLASS-NAME
 which defines that view. The argument DATABASE has a default value of
@@ -126,8 +126,6 @@ which defines that view. The argument DATABASE has a default value of
         (error "Class ~s not found." view-class-name)))
   (values))
 
-#.(restore-sql-reader-syntax-state)
-
 (defun %uninstall-class (self &key (database *default-database*))
   (drop-table (sql-expression :table (view-table self))
               :if-does-not-exist :ignore
@@ -141,19 +139,27 @@ which defines that view. The argument DATABASE has a default value of
 ;;
 
 (defun list-classes (&key (test #'identity)
-                          (root-class 'standard-db-object)
-                          (database *default-database*))
-  "Returns a list of View Classes connected to a given DATABASE which
-defaults to *DEFAULT-DATABASE*."
-  (declare (ignore root-class))
-  (remove-if #'(lambda (c) (not (funcall test c)))
-             (database-view-classes database)))
+                    (root-class (find-class 'standard-db-object))
+                    (database *default-database*))
+  "The LIST-CLASSES function collects all the classes below
+ROOT-CLASS, which defaults to standard-db-object, that are connected
+to the supplied DATABASE and which satisfy the TEST function. The
+default for the TEST argument is identity. By default, LIST-CLASSES
+returns a list of all the classes connected to the default database,
+*DEFAULT-DATABASE*."
+  (flet ((find-superclass (class) 
+          (member root-class (class-precedence-list class))))
+    (let ((view-classes (and database (database-view-classes database))))
+      (when view-classes
+       (remove-if #'(lambda (c) (or (not (funcall test c))
+                                    (not (find-superclass c))))
+                  view-classes)))))
 
 ;;
 ;; Define a new view class
 ;;
 
-(defmacro def-view-class (class supers slots &rest options)
+(defmacro def-view-class (class supers slots &rest cl-options)
   "Extends the syntax of defclass to allow special slots to be mapped
 onto the attributes of database views. The macro DEF-VIEW-CLASS
 creates a class called CLASS which maps onto a database view. Such a
@@ -166,9 +172,11 @@ instances are filled with attribute values from the database. If
 SUPERS is nil then STANDARD-DB-OBJECT automatically becomes the
 superclass of the newly-defined View Class."
   `(progn
-     (defclass ,class ,supers ,slots ,@options
-              (:metaclass standard-db-class))
-     (finalize-inheritance (find-class ',class))))
+    (defclass ,class ,supers ,slots 
+      ,@(if (find :metaclass `,cl-options :key #'car)
+           `,cl-options
+           (cons '(:metaclass clsql-sys::standard-db-class) `,cl-options)))
+    (finalize-inheritance (find-class ',class))))
 
 (defun keyslots-for-class (class)
   (slot-value class 'key-slots))
@@ -230,6 +238,7 @@ superclass of the newly-defined View Class."
     (let ((cdef
            (list (sql-expression :attribute (view-class-slot-column slotdef))
                  (slot-type slotdef))))
+      (setf cdef (append cdef (list (view-class-slot-db-type slotdef))))
       (let ((const (view-class-slot-db-constraints slotdef)))
         (when const 
           (setq cdef (append cdef (list const)))))
@@ -539,7 +548,8 @@ DATABASE-NULL-VALUE on the type of the slot."))
 
 (defmethod database-get-type-specifier (type args database)
   (declare (ignore type args))
-  (if (member (database-type database) '(:postgresql :postgresql-socket))
+  (if (clsql-base-sys::in (database-underlying-type database)
+                         :postgresql :postgresql-socket)
           "VARCHAR"
           "VARCHAR(255)"))
 
@@ -554,31 +564,32 @@ DATABASE-NULL-VALUE on the type of the slot."))
                                         database)
   (if args
       (format nil "VARCHAR(~A)" (car args))
-      (if (member (database-type database) '(:postgresql :postgresql-socket))
-          "VARCHAR"
-          "VARCHAR(255)")))
+    (if (clsql-base-sys::in (database-underlying-type database) 
+                           :postgresql :postgresql-socket)
+       "VARCHAR"
+      "VARCHAR(255)")))
 
 (defmethod database-get-type-specifier ((type (eql 'simple-string)) args
                                         database)
   (if args
       (format nil "VARCHAR(~A)" (car args))
-      (if (member (database-type database) '(:postgresql :postgresql-socket))
-          "VARCHAR"
-          "VARCHAR(255)")))
+    (if (clsql-base-sys::in (database-underlying-type database) 
+                           :postgresql :postgresql-socket)
+       "VARCHAR"
+      "VARCHAR(255)")))
 
 (defmethod database-get-type-specifier ((type (eql 'string)) args database)
   (if args
       (format nil "VARCHAR(~A)" (car args))
-      (if (member (database-type database) '(:postgresql :postgresql-socket))
-          "VARCHAR"
-          "VARCHAR(255)")))
+    (if (clsql-base-sys::in (database-underlying-type database) 
+                           :postgresql :postgresql-socket)
+       "VARCHAR"
+      "VARCHAR(255)")))
 
 (defmethod database-get-type-specifier ((type (eql 'wall-time)) args database)
   (declare (ignore args))
-  (case (database-type database)
-    (:postgresql
-     "TIMESTAMP WITHOUT TIME ZONE")
-    (:postgresql-socket
+  (case (database-underlying-type database)
+    ((:postgresql :postgresql-socket)
      "TIMESTAMP WITHOUT TIME ZONE")
     (:mysql
      "DATETIME")
@@ -697,13 +708,14 @@ DATABASE-NULL-VALUE on the type of the slot."))
 (defmethod read-sql-value (val (type (eql 'keyword)) database)
   (declare (ignore database))
   (when (< 0 (length val))
-    (intern (string-upcase val) "KEYWORD")))
+    (intern (symbol-name-default-case val) 
+           (find-package '#:keyword))))
 
 (defmethod read-sql-value (val (type (eql 'symbol)) database)
   (declare (ignore database))
   (when (< 0 (length val))
-    (unless (string= val "NIL")
-      (intern (string-upcase val)
+    (unless (string= val (clsql-base-sys:symbol-name-default-case "NIL"))
+      (intern (clsql-base-sys:symbol-name-default-case val)
               (symbol-package *update-context*)))))
 
 (defmethod read-sql-value (val (type (eql 'integer)) database)
@@ -727,6 +739,11 @@ DATABASE-NULL-VALUE on the type of the slot."))
   (unless (eq 'NULL val)
     (parse-timestring val)))
 
+(defmethod read-sql-value (val (type (eql 'duration)) database)
+  (declare (ignore database))
+  (unless (or (eq 'NULL val)
+              (equal "NIL" val))
+    (parse-timestring val)))
 
 ;; ------------------------------------------------------------
 ;; Logic for 'faulting in' :join slots