+(defun %select-objects (type select-fn query)
+ (mapcar (curry 'make-object-from-plist type)
+ (apply select-fn (intern (format nil "*"))
+ (if (string-equal (first query) :from)
+ query
+ (append `(:from ,type) query)))))
+
+(defun select-objects (type &rest query)
+ (%select-objects type #'select query))
+
+(defun select-only-n-objects (n type &rest query)
+ (let ((fields (if (eq :fields (car query))
+ (loop
+ :for cons :on (cdr query)
+ :if (not (keywordp (car cons)))
+ :collect (car cons) into fields
+ :else :do
+ (setf query cons)
+ (return (nreverse (print fields)))
+ :finally
+ (setf query cons)
+ (return (nreverse (print fields))))
+
+ (list (intern "*")))))
+ (let ((results
+ (%query
+ (print `(:limit (:select
+ ,@fields
+ ,@(if (string-equal (first query) :from)
+ (print query)
+ (append `(:from ,type) query)))
+ ,n)))))
+ (if (eql 1 n)
+ (make-object-from-plist type (first results))
+ (mapcar (curry 'make-object-from-plist type) results)))))
+
+(defun make-object-from-plist (type plist)
+ (let* ((class (find-class type))
+ (object (make-instance class))
+ (slotds (class-slots class)))
+
+ (loop
+ :for (key val) :on plist :by #'cddr
+ :do
+ (dolist (slotd (remove key slotds
+ :key #'slot-definition-column-name
+ :test-not #'string-equal))
+
+ (setf (slot-value-using-class class object slotd) val))
+ :finally (return (reinitialize-instance object)))))
+
+(defun make-object (type &rest plist)
+ (make-object-from-plist type plist))
+
+(defun insert-object (object)
+ (let ((class (class-of object))
+ insert-query
+ delayed)
+ (flet ((ins (slotd &optional (val (slot-value-using-class class object slotd)))
+ (push (lambda () (push (slot-definition-column-name slotd) insert-query)
+ (push val insert-query))
+ delayed)))
+ (loop :for slotd in (class-slots class)
+ :do (cond ((slot-boundp-using-class class object slotd)
+ (cond ((or (slot-definition-foreign-relation slotd)
+ )
+ )
+ ((slot-definition-foreign-type slotd)
+ (set-fkey-from-slotd
+ (slot-value-using-class class object slotd)
+ object slotd
+)
+ )
+ (t
+ (ins slotd)) ))
+ ((slot-definition-primary-key-p slotd)
+ (setf (slot-value-using-class class object slotd) (get-default-value (class-table-name class)
+ (slot-definition-column-name slotd)))
+ (ins slotd ))))
+ (map nil #'funcall delayed)
+ (apply #'insert-into (class-table-name class) (nreverse insert-query))))
+ object)
+
+
+(defun update-object (object)
+ (let ((class (class-of object))
+ update-query
+ delayed)
+ (flet ((ins (slotd &optional (val (slot-value-using-class class object slotd)))
+ (push (lambda () (push (slot-definition-column-name slotd) update-query)
+ (push val update-query))
+ delayed)))
+ (loop :for slotd in (class-slots class)
+ :do (cond ((slot-boundp-using-class class object slotd)
+ (cond ((or (slot-definition-foreign-relation slotd)
+ )
+ )
+ ((slot-definition-foreign-type slotd)
+ (set-fkey-from-slotd
+ (slot-value-using-class class object slotd)
+ object slotd
+)
+ )
+ (t
+ (ins slotd)) ))
+ ((slot-definition-primary-key-p slotd)
+ (setf (slot-value-using-class class object slotd) (get-default-value (class-table-name class)
+ (slot-definition-column-name slotd)))
+ (ins slotd ))))
+ (map nil #'funcall delayed)
+ (apply #'update (class-table-name class) :set (nconc (nreverse update-query)
+ (list :where `(:= ,(dao-id-column-name class)
+ ,(slot-value object (dao-id-column-name class))
+ ))))))
+ object)
+
+(defun select-using-object (object &key (combinator :and))
+ (let ((class (class-of object))
+ select-query)
+ (flet ((sel (slotd &optional (val (slot-value-using-class class object slotd)))
+ (push `(:ilike ,(slot-definition-column-name slotd) ,(if (stringp val)
+ (format nil "~A%" val) val)) select-query)))
+ (loop :for slotd in (class-slots class)
+ :do (cond ((slot-boundp-using-class class object slotd)
+ (unless (or (slot-definition-foreign-relation slotd)
+ (slot-definition-foreign-type slotd))
+ (sel slotd)))))
+ (if select-query
+ (select-objects (class-table-name class)
+ :where (print `(,combinator ,@(nreverse select-query))))
+ nil))))
+