Re: RFC/patch: normalised object oriented clsql?
Thijs Oppermann <[email protected]>
| Newsgroups | gmane.lisp.clsql.general |
|---|---|
| Message-ID | <[email protected]> |
Picking up a very old thread for this, as it includes a lot of background.. I went ahead and pushed my 'fork' of CLSQL to github with the changes described in the old thread. The repository is at: http://github.com/thijs/clsql-fork/ I rebased my changes on top of the latest git clone from b9, which seemed to apply cleanly.. I need to do some testing on that though. Anyway, if you're interested you could clone it ( git clone git://github.com/thijs/clsql-fork.git ) and play around. Run the test suite and you should see if the normalised inheritance code works. I only have mysql here, though, so if you use something else you might run into trouble... I'd like to know. Gr, Thijs On Tue, Sep 16, 2008 at 9:51 PM, Vsevolod <[email protected]> wrote: > Yes, now I see your point. > I think, overall, it's a good idea. > > Good luck > Vsevolod > > On 9/16/08, Thijs Oppermann <[email protected]> wrote: >> Replying to the list, because I guess my answer covers some stuff I >> forgot to cover in my first post. But thanks for your input, Vsevoiod. >> >> First, my changes do *nothing* unless you explicitly *use* it (at >> least, that was my intention, so barring bugs, that is how it should >> work). So old code works as it always has. No need to change a thing. >> And if you run into anything that shows otherwise I very much want to >> know, because that's a bug and I'd like to squash those... >> >> And yes, I see exactly what you mean with your example, and in that >> case I would use it as it is now, too. But my case is a little bit >> different, as the different view-classes have a very clear hierarchy >> themselves. And having this mirrored in the database cleans it up. An >> example may help: >> >> Basically, in the framework everything is a node (wonder how many of >> you know now what framework I'm working off of... ;) >> So you have a view class 'node', defined as (this is actually taken >> verbatim from the tests I added): >> >> (def-view-class node () >> ((node-id :accessor node-id :initarg :node-id >> :type integer :db-kind :key >> :db-constraints (:not-null :auto-increment)) >> (title :accessor title :initarg :title :type (varchar 240)) >> (createtime :accessor createtime :initarg :createtime :type wall-time >> :db-constraints (:not-null) :initform (get-time)) >> (modifiedtime :accessor modifiedtime :initarg :modifiedtime :type >> wall-time >> :initform (make-time :year 1900 :month 1 :day 1)))) >> >> As you see: nothing out of the ordinary here. But now we have a >> 'setting', which is also a node, but with more functionality: >> >> (def-view-class setting (node) >> ((setting-id :accessor setting-id :initarg :setting-id >> :type integer :db-kind :key :db-constraints (:not-null)) >> (vars :accessor vars :initarg :vars :type (varchar 240))) >> (:normalisedp t)) >> >> Two things here: >> 1) 'setting' is a subclass of 'node', also not that shocking >> 2) but, the last line in that def shows: it's a normalised view-class, >> which is what my additions are all about. >> >> Now, you get the following table structure from those two definitions: >> >> NODE_ID int(11) [auto_increment] >> TITLE varchar(240) >> CREATETIME datetime >> MODIFIEDTIME datetime >> >> and >> >> SETTING_ID int(11) >> VARS varchar(240) >> >> where a setting is linked to the parent node through the two _id >> fields, in a one-to-one relationship. >> >> Especially in the case I'm working with, this cleans up the database >> tremendously, as there are a lot of different types of subclasses of >> 'node', and sometimes even nested. And they all have a title, a >> createtime, etc. etc. >> >> So, I hope this clears up my use-case a bit. And once again: no need >> to do anything if you don't want this, as the defaults stay exactly as >> they were. You need to explicitly *use* this. >> >> Cheers, >> Thijs >> >> On Tue, Sep 16, 2008 at 8:35 AM, Vsevolod <[email protected]> wrote: >>> Hi Thijs, >>> >>> I don't think, that your idea is obvious. :) >>> My view is that, view-classes are tied to database tables, which can >>> be completely independent from one another, but if you introduce >>> re-use, you force them be dependent. But subclassing of view-classes >>> is useful in other (obvious) way: you reuse the functionality, >>> associated with them: getters, db-readers etc. And, moreover, you can >>> use those classes in the same places in your code, because they share >>> the same accessors. >>> >>> Think of such an example: >>> I have 2 view-classes: transaction and pending-transaction. Pending-tr >>> is very much like simple tr, but has a couple more slots, so I >>> subclass it to tr. But if it reused the same table, that would have >>> meant, that each time I make a pending-tr, I make a corresponding tr, >>> which in my case contradicts business rules. >>> >>> Cheers, >>> Vsevolod >>> >>> On 9/16/08, Thijs Oppermann <[email protected]> wrote: >>>> As a for-play hobby project I started porting/rewriting a perl web >>>> framework I like to common lisp. Mostly to learn the language. Fairly >>>> quickly I needed a place to put my data, and I ended up choosing >>>> clsql, and started off using the object oriented parts of it. >>>> Immediately I ran into something I thought a bit weird: subclassed >>>> views did not re-use the database fields from the superclass, but >>>> flatly included them within. At first I thought I must be doing >>>> something wrong, so I started digging into the docs, but soon I found >>>> that nowhere this issue was mentioned. Now, maybe I want something >>>> stupid, or maybe I'm using or doing it wrong, but I thought it was >>>> obvious that a subclassed view would be linked to it's parent view >>>> through primary/foreign key pairs. A 'normalised' view, if I may abuse >>>> that term here. Finding that clsql did nothing of the sort I thought I >>>> would quickly add that functionality to it and move on. Famous last >>>> words and all that... >>>> >>>> Anyway, I've been working away at this for a while now, on and off. >>>> Finding out that it entailed entirely a lot more changes than I had >>>> anticipated, of course. Maybe this is why it wasn't there in the first >>>> place... It's not really as trivial as I thought. Although, now, I'm >>>> getting somewhere. I've actually added a bunch of tests that I now >>>> also manage to pass. So it seems as I'm getting close to a working >>>> system. An ideal time to throw it out there, and be pointed at an >>>> existing implementatoin, or a better way to do it or whatever... ;) >>>> >>>> I would very much like to hear thoughts, rants, pointers, anything >>>> about this. I'm gonna go on with my original project now, and use this >>>> stuff there. But maybe someone else likes this and wants to use it. >>>> Maybe it's something that was planned all along and I've saved someone >>>> some work (or done the work twice). Maybe this is something no-one >>>> ever thought about, even, but likes anyway. I'd also encourage any >>>> comments on my coding, I'm very much still learning. Maybe I've made >>>> some big mistakes that I've missed with the tests I've added (I know >>>> already that I've not done the tests and changes to delete rows, >>>> that's something I'll have to look into now, I guess). >>>> >>>> So, see attached patch. If people want it in a different form, give me >>>> a yell, I'll see what I can do. >>>> >>>> Greeting, >>>> Thijs Oppermann >>>> >>> >>> >>> -- >>> vsevolod >>> >> _______________________________________________ >> CLSQL mailing list >> [email protected] >> http://lists.b9.com/cgi-bin/mailman/listinfo/clsql >> > _______________________________________________ CLSQL mailing list [email protected] http://lists.b9.com/cgi-bin/mailman/listinfo/clsql