Merge branch 'connection-pool-fix'
[clsql.git] / sql / oodml.lisp
index 9910ab484948088a569268f49b87fea8e9374a0d..710e5e8e090c45548e4a41d6948ccd35c7c7536c 100644 (file)
@@ -1,8 +1,6 @@
 ;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*-
 ;;;; *************************************************************************
 ;;;;
-;;;; $Id$
-;;;;
 ;;;; The CLSQL Object Oriented Data Manipulation Language (OODML).
 ;;;;
 ;;;; This file is part of CLSQL.
@@ -55,7 +53,7 @@
 (defun generate-selection-list (vclass)
   (let* ((sels nil)
          (this-class vclass)
-         (slots (if (normalisedp vclass)
+         (slots (if (normalizedp vclass)
                     (labels ((getdslots ()
                                (let ((sl (ordered-class-direct-slots this-class)))
                                  (cond (sl)
                                     (database *default-database*))
   (let* ((database (or (view-database obj) database))
          (view-class (class-of obj)))
-    (when (normalisedp view-class)
-      ;; If it's normalised, find the class that actually contains
+    (when (normalizedp view-class)
+      ;; If it's normalized, find the class that actually contains
       ;; the slot that's tied to the db
       (setf view-class
             (do ((this-class view-class
 
 (defmethod update-record-from-slots ((obj standard-db-object) slots &key
                                      (database *default-database*))
+  (when (normalizedp (class-of obj))
+    ;; FIXME: Rewrite to bundle slots for same table to be written
+    ;; as avpairs (like how is done for non-normalized view-classes below)
+    (dolist (slot slots)
+      (update-record-from-slot obj slot :database database))
+    (return-from update-record-from-slots (values)))
+
   (let* ((database (or (view-database obj) database))
          (vct (view-table (class-of obj)))
          (sds (slotdefs-for-slots-with-class slots (class-of obj)))
              (pk-slot (car (keyslots-for-class view-class)))
              (view-class-table (view-table view-class))
              (pclass (car (class-direct-superclasses view-class))))
-        (when (normalisedp view-class)
+        (when (normalizedp view-class)
           (setf pk (update-records-from-instance obj :database database
                                                  :this-class pclass))
           (when pk-slot
             (setf (slot-value obj (slot-definition-name pk-slot)) pk)))
         (let* ((slots (remove-if-not #'slot-storedp
-                                     (if (normalisedp view-class)
+                                     (if (normalizedp view-class)
                                          (ordered-class-direct-slots view-class)
                                          (ordered-class-slots view-class))))
                (record-values (mapcar #'slot-value-list slots)))
-          (cond ((and (not (normalisedp view-class))
+          (cond ((and (not (normalizedp view-class))
                       (not record-values))
                  (error "No settable slots."))
-                ((and (normalisedp view-class)
+                ((and (normalizedp view-class)
                       (not record-values))
                  nil)
                 ((view-database obj)
   (let* ((view-class (or this-class (class-of instance)))
          (pclass (car (class-direct-superclasses view-class)))
          (pres nil))
-    (when (normalisedp view-class)
+    (when (normalizedp view-class)
       (setf pres (update-instance-from-records instance :database database
                                                :this-class pclass)))
     (let* ((view-table (sql-expression :table (view-table view-class)))
                                                      :result-types nil
                                                      :database vd))))
              (when res
+              (setf (slot-value instance 'view-database) vd)
                (get-slot-values-from-view instance (mapcar #'car sels) (car res))))
             (pres)
             (t nil)))))
                                     slot &key (database *default-database*))
   (let* ((view-class (find-class (class-name (class-of instance))))
          (slot-def (slotdef-for-slot-with-class slot view-class)))
-    (when (normalisedp view-class)
-      ;; If it's normalised, find the class that actually contains
+    (when (normalizedp view-class)
+      ;; If it's normalized, find the class that actually contains
       ;; the slot that's tied to the db
       (setf view-class
             (do ((this-class view-class
            (res (select att-ref :from  view-table :where view-qual
                                                   :result-types nil)))
       (when res
+       (setf (slot-value instance 'view-database) vd)
         (get-slot-values-from-view instance (list slot-def) (car res))))))
 
 (defmethod update-slot-with-null ((object standard-db-object)
        (format nil "~F" val))))
 
 (defmethod read-sql-value (val type database db-type)
-  (declare (ignore type database db-type))
-  (read-from-string val))
+  (declare (ignore database db-type))
+  (cond
+    ((null type) val) ;;we have no desired type, just give the value
+    ((typep val type) val) ;;check that it hasn't already been converted.
+    ((typep val 'string) (read-from-string val)) ;;maybe read will just take care of it?
+    (T (error "Unable to read-sql-value ~a as type ~a" val type))))
 
 (defmethod read-sql-value (val (type (eql 'string)) database db-type)
   (declare (ignore database db-type))
   (declare (ignore database db-type))
   ;; writing 1.0 writes 1, so we we *really* want a float, must do (float ...)
   (etypecase val
-    (string
-     (float (read-from-string val)))
-    (float
-     val)))
+    (string (float (read-from-string val)))
+    (float val)))
+
+(defmethod read-sql-value (val (type (eql 'double-float)) database db-type)
+  (declare (ignore database db-type))
+  ;; writing 1.0 writes 1, so if we *really* want a float, must do (float ...)
+  (etypecase val
+    (string (float
+            (let ((*read-default-float-format* 'double-float))
+              (read-from-string val))
+            1.0d0))
+    (double-float val)
+    (float (coerce val 'double-float))))
 
 (defmethod read-sql-value (val (type (eql 'boolean)) database db-type)
   (declare (ignore database db-type))
@@ -875,7 +895,7 @@ maximum of MAX-LEN instances updated in each query."
 ;;;; Should we not return the whole result, instead of only
 ;;;; the one slot-value? We get all the values from the db
 ;;;; anyway, so?
-(defun fault-join-normalised-slot (class object slot-def)
+(defun fault-join-normalized-slot (class object slot-def)
   (labels ((getsc (this-class)
              (let ((sc (car (class-direct-superclasses this-class))))
                (if (key-slots sc)
@@ -898,7 +918,7 @@ maximum of MAX-LEN instances updated in each query."
                                   (slot-value object hk))
                                  (t hk)))))
 
-        ;; Caching nil in next select, because in normalised mode
+        ;; Caching nil in next select, because in normalized mode
         ;; records can be changed through other instances (children,
         ;; parents) so changes possibly won't be noticed
         (let ((res (car (select (class-name sc) :where jq
@@ -907,14 +927,14 @@ maximum of MAX-LEN instances updated in each query."
                                                 :database (view-database object))))
               (slot-name (slot-definition-name slot-def)))
 
-          ;; If current class is normalised and wanted slot is not
+          ;; If current class is normalized and wanted slot is not
           ;; a direct member, recurse up
-          (if (and (normalisedp class)
+          (if (and (normalizedp class)
                    (not (member slot-name
                                 (mapcar #'(lambda (esd) (slot-definition-name esd))
                                         (ordered-class-direct-slots class))))
                    (not (slot-boundp res slot-name)))
-              (fault-join-normalised-slot sc res slot-def)
+              (fault-join-normalized-slot sc res slot-def)
               (slot-value res slot-name)))))) )
 
 (defun join-qualifier (class object slot-def)
@@ -979,7 +999,7 @@ maximum of MAX-LEN instances updated in each query."
                          ;; find all immediate-select slots and join-vals for this object
                          (let* ((jo-class (class-of jo))
                                 (slots
-                                 (if (normalisedp jo-class)
+                                 (if (normalizedp jo-class)
                                      (class-direct-slots jo-class)
                                      (class-slots jo-class)))
                                 (pos-list (remove-if #'null