Prev: Configuration file setup and pathname usage
Next: wxcl
From: Roby Sadeli on 13 Mar 2010 23:10 On Mar 14, 4:10 am, Nicolas Neuss <lastn...(a)kit.edu> wrote: > "Alex Mizrahi" <udode...(a)users.sourceforge.net> writes: > > RS> I know that there is oid (object id) for every object but what if I > > RS> want isbn to be unique? Do I have to check on my objects before > > RS> creating a new one? > > > Um, yes, I think you should do that check yourself. What to do in case of > > non-unique keys is application-dependent, and so you need to implement a > > reaction to it yourself anyway. > > Throwing CFFI out of my asdf-registry in favor of UFFI, I succeeded in > making Elephant work, and very soon I also missed that feature > (especially since I am a used to CLSQL where one can enforce this with > ":db-kind :key" in the slot definition). > > As a remedy, I inserted such a test for uniqueness in the > initialize-instance method as follows: > > (defmethod initialize-instance :before > ((ml ele-mailing-list) &key name &allow-other-keys) > ... > (assert (null (find-ele-ml name)) () "This list already exists")) > > Having a ":db-kind :key" slot option would make such kind of tests > superfluous and indicate intent as early as possible, and this I would > like. OTOH, since CLOS itself does not have this feature, I do not > consider it a necessesity for Elephant. > > Nicolas Hi Nicolas, Thanks for giving me a hint about using initialize-instance :before to check whether a key is in the database. That solves my question. I am a newbie, and I learn by looking at simple example codes and I just think cl-elephant example codes out there are a rare. Cheers.
From: Alex Mizrahi on 14 Mar 2010 04:07 RS> So I have to create a function (for example isbn-exists?) to check RS> whether a certain ISBN is already in the database, RS> cl-elephant could not do this automatically. RS> I just find it strange to have to do this manually. Well, Elephant is a CLOS persistence layer, not an object-relational mapping. You're supposed to write application in CLOS-style, Lisp-style instead of mimicking concepts or relational databases. It is not like automatic constraint checks really buy you anything. Let's suppose you have to show an error message when book with given ISBN already exists. Here's how a function which adds book into a database might look with manual checks: (defun add-book (isbn title author) (if (get-instances-by-value 'book 'isbn isbn) (show-error "Book with this ISBN already exists.") (make-instance 'book :isbn isbn :title title :author author))) And how it could look like if make-instance would throw an error on unique constraing violation: (defun add-book (isbn title author) (handler-case (make-instance 'book :isbn isbn :title title :author author) (unique-constraint-violation () (show-error "Book with this ISBN already exists.")))) It didn't get shorter with automatic checking, and first version looks more straightforward IMHO. Automatic checking might prevent database inconsistency in case your code has a bug -- you forgot to check it. But as Common Lisp is dynamically-typed and doesn't usually check stuff automatically, it would be kind of strange that you want automatic check for this specific piece and not all over your code. But if you think you actually need constraints, it's not that hard to implement them. E.g. something like (beware -- proof-of-concept quality code): (defun effective->direct-slot-def (class esd) (find (slot-definition-name esd) (class-direct-slots class) :key #'slot-definition-name)) (defmethod (setf slot-value-using-class) :before (new-value (class persistent-metaclass) (instance persistent-object) (slot-def indexed-slot-definition)) (when (eq (indexed-p (effective->direct-slot-def class slot-def)) :unique) (let ((sc (get-con instance))) (ensure-transaction (:store-controller sc) (let* ((idx (or (get-slot-def-index slot-def sc) (ensure-slot-def-index slot-def sc))) (other-oid (get-value new-value idx))) (when (and other-oid (/= other-oid (oid instance))) (error "unique constraint violation, new value:~a for slot ~a is already present for instance ~a" new-value (slot-definition-name slot-def) (get-value new-value idx)))))))) And now if you define it like this: (defpclass book () ((isbn :initarg :isbn :accessor isbn :index :unique) (title :initarg :title :accessor title :index t) (author :initarg :author :accessor author :index t))) It will do check on that index. ELE> (make-instance 'book :isbn "3" :author "a" :title "t") #<BOOK oid:201> ELE> (make-instance 'book :isbn "3" :author "a" :title "t") unique constraint violation, new value:3 for slot ISBN is already present for instance 201 [Condition of type SIMPLE-ERROR] Restarts: 0: [ABORT] Return to SLIME's top level. ELE> (get-instances-by-value 'book 'isbn "3") (#<BOOK oid:201>) So, it did not add second instance because of unique constrain violation. But it only works so because signaling error have aborted transaction.
From: Alex Mizrahi on 14 Mar 2010 04:11 RS> Thanks for giving me a hint about using initialize-instance :before to RS> check whether a key is in the database. That solves my question. RS> I am a newbie, and I learn by looking at simple example codes and I RS> just think cl-elephant example codes out there are a rare. Well, this code has absolutely nothing to do with Elephant, it is a plain CLOS code. That illustrates a point -- it is a good idea to learn CLOS if you're using Elephant.
From: Alex Mizrahi on 14 Mar 2010 04:21 AM> E.g. something like (beware -- proof-of-concept quality code): To clarify, this code was for illustrative purposes only, it works only in simple situations when there is no class inheritance. If you think that Elephant should implement unique constraints on indices, please write about it into Elephant's mailing list. It is actually pretty easy to add this feature, but I don't know whether other Elephant developers agree on this.
From: Roby Sadeli on 15 Mar 2010 06:09
On Mar 14, 3:21 pm, "Alex Mizrahi" <udode...(a)users.sourceforge.net> wrote: > AM> E.g. something like (beware -- proof-of-concept quality code): > > To clarify, this code was for illustrative purposes only, it works only in > simple situations when there is no class inheritance. > If you think that Elephant should implement unique constraints on indices, > please write about it into Elephant's mailing list. > It is actually pretty easy to add this feature, but I don't know whether > other Elephant developers agree on this. Alex, thanks for helping me out. I still have a lot to learn. Your remark about cl-elephant being a persistent CLOS layer, not ORM, I am seeing the light now. I think I am sticking with manual check, the latter one is more complex, and as you said, it is not desirable to implement unique constraints on indices, but actually it is what I originally asked for :). Thanks. |