;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*-
;;;; *************************************************************************
;;;;
-;;;; $Id$
-;;;;
;;;; The CLSQL Object Oriented Data Manipulation Language (OODML).
;;;;
;;;; This file is part of CLSQL.
(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)
(setf pk (or pk
(slot-value obj (slot-definition-name pk-slot))))))
(t
- (insert-records :into (sql-expression :table view-class-table)
+ (insert-records :into (sql-expression :table view-class-table)
:av-pairs record-values
:database database)
- (when pk-slot
- (if (or (and (listp (view-class-slot-db-constraints pk-slot))
- (member :auto-increment (view-class-slot-db-constraints pk-slot)))
- (eql (view-class-slot-db-constraints pk-slot) :auto-increment))
- (setf pk (or pk
- (car (query "SELECT LAST_INSERT_ID();"
- :flatp t :field-names nil
- :database database))))
- (setf pk (or pk
- (slot-value obj (slot-definition-name pk-slot))))))
- (when (eql this-class nil)
- (setf (slot-value obj 'view-database) database)))))))
+
+ (when (and pk-slot (not pk))
+ (setf pk (if (or (member :auto-increment (listify (view-class-slot-db-constraints pk-slot)))
+ (not (null (view-class-slot-autoincrement-sequence pk-slot))))
+ (setf (slot-value obj (slot-definition-name pk-slot))
+ (database-last-auto-increment-id database
+ view-class-table
+ pk-slot)))))
+ (when pk-slot
+ (setf pk (or pk
+ (slot-value
+ obj (slot-definition-name pk-slot)))))
+ (when (eql this-class nil)
+ (setf (slot-value obj 'view-database) database)))))))
+ ;; handle slots with defaults
+ (let* ((view-class (or this-class (class-of obj)))
+ (slots (if (normalizedp view-class)
+ (ordered-class-direct-slots view-class)
+ (ordered-class-slots view-class))))
+ (dolist (slot slots)
+ (when (and (slot-exists-p slot 'db-constraints)
+ (listp (view-class-slot-db-constraints slot))
+ (member :default (view-class-slot-db-constraints slot)))
+ (unless (and (slot-boundp obj (slot-definition-name slot))
+ (slot-value obj (slot-definition-name slot)))
+ (update-slot-from-record obj (slot-definition-name slot))))))
+
pk))
(defmethod delete-instance-records ((instance standard-db-object))
(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))
;;;; 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)
(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
: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)
;; 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