(:metaclass standard-db-class)
(:documentation "Superclass for all CLSQL View Classes."))
-(defvar *update-records-on-make-instance* nil
- "When T, UPDATE-RECORDS-FROM-INSTANCE will be automatically called
-when a new instance of a view-class is created.")
+(defvar *db-auto-sync* nil
+ "A non-nil value means that creating View Class instances or
+ setting their slots automatically creates/updates the
+ corresponding records in the underlying database.")
(defvar *db-deserializing* nil)
(defvar *db-initializing* nil)
(setf (slot-value instance slot-name) nil))))))
(call-next-method))
-#+ignore ;; not currently used
(defmethod (setf slot-value-using-class) (new-value (class standard-db-class)
- instance slot)
- (declare (ignore new-value instance slot))
- (call-next-method))
+ instance slot-def)
+ (declare (ignore new-value))
+ (let ((slot-name (%svuc-slot-name slot-def))
+ (slot-kind (view-class-slot-db-kind slot-def)))
+ (call-next-method)
+ (when (and *db-auto-sync*
+ (not *db-initializing*)
+ (not *db-deserializing*)
+ (not (eql slot-kind :virtual)))
+ (update-record-from-slot instance slot-name))))
(defmethod initialize-instance ((object standard-db-object)
&rest all-keys &key &allow-other-keys)
(declare (ignore all-keys))
(let ((*db-initializing* t))
(call-next-method)
- (when (and *update-records-on-make-instance*
+ (when (and *db-auto-sync*
(not *db-deserializing*))
- #+nil (created-object object)
(update-records-from-instance object))))
;;
sels
(error "No slots of type :base in view-class ~A" (class-name vclass)))))
+(defun generate-immediate-joins-list (vclass)
+ "Returns list of pairs of join slots and their class for a class."
+ (let ((sels nil))
+ (dolist (slotdef (ordered-class-slots vclass))
+ (when (and (eq :join (view-class-slot-db-kind slotdef))
+ (eq :immediate (gethash :retrieval (view-class-slot-db-info slotdef))))
+ (push slotdef sels)))
+ (cons vclass (list sels))))
-;;
;; Called by 'get-slot-values-from-view'
;;
-(declaim (inline delistify))
-(defun delistify (list)
- (if (listp list)
- (car list)
- list))
-
(defvar *update-context* nil)
(defmethod update-slot-from-db ((instance standard-db-object) slotdef value)
(let* ((dbi (view-class-slot-db-info slot-def))
(ts (gethash :target-slot dbi))
(jc (gethash :join-class dbi))
+ (ts-view-table (view-table (find-class ts)))
+ (jc-view-table (view-table (find-class jc)))
(tdbi (view-class-slot-db-info
(find ts (class-slots (find-class jc))
:key #'slot-definition-name)))
(:immediate
(let ((res
(find-all (list ts)
- :inner-join (sql-expression :attribute jc)
+ :inner-join (sql-expression :table jc-view-table)
:on (sql-operation
'==
- (sql-expression :attribute (gethash :foreign-key tdbi) :table ts)
- (sql-expression :attribute (gethash :home-key tdbi) :table jc))
+ (sql-expression
+ :attribute (gethash :foreign-key tdbi)
+ :table ts-view-table)
+ (sql-expression
+ :attribute (gethash :home-key tdbi)
+ :table jc-view-table))
:where jq
:result-types :auto)))
(mapcar #'(lambda (i)
(setf (slot-value jcc (gethash :home-key tdbi))
fk)
(list instance jcc)))
- (select (sql-expression :attribute (gethash :foreign-key tdbi) :table jc)
- :from (sql-expression :table jc)
+ (select (sql-expression :attribute (gethash :foreign-key tdbi) :table jc-view-table)
+ :from (sql-expression :table jc-view-table)
:where jq)))))))
(defun update-object-joins (objects &key (slots t) (force-p t)
- class-name (max-len *default-update-objects-max-len))
+ class-name (max-len *default-update-objects-max-len*))
"Updates the remote join slots, that is those slots defined without :retrieval :immediate."
(when objects
(unless class-name
- (class-name (class-of (first object))))
+ (class-name (class-of (first objects))))
)
)
(apply #'sql-and jc)
jc))))))
+;; FIXME: add retrieval immediate for efficiency
+;; For example, for (select 'employee-address) in test suite =>
+;; select addr.*,ea_join.* FROM addr,ea_join WHERE ea_join.aaddressid=addr.addressid\g
+
(defun find-all (view-classes
&rest args
&key all set-operation distinct from where group-by having
(let* ((class-name (class-name vclass))
(db-vals (butlast vals (- (list-length vals)
(list-length selects))))
- (*db-initializing* t)
(obj (make-instance class-name :view-database database)))
;; use refresh keyword here
(setf obj (get-slot-values-from-view obj (mapcar #'car selects)
(car objects)
objects))))
(let* ((*db-deserializing* t)
- (*default-database* (or database
- (error 'clsql-base::clsql-no-database-error :database nil)))
(sclasses (mapcar #'find-class view-classes))
+ (immediate-joins (mapcar #'generate-immediate-joins-list sclasses))
(sels (mapcar #'generate-selection-list sclasses))
(fullsels (apply #'append sels))
(sel-tables (collect-table-refs where))