From: Ian B. <ia...@co...> - 2003-07-25 02:12:43
|
On Thu, 2003-07-24 at 13:18, Brad Bollenbach wrote: > > > here's another feature I need for my project : I have several tables > > > whose primary key is composed of two or three columns. > > > > Well, if there's going to be composite keys, that might as well be > > generalized to all the columns (i.e., any attribute could be a composite > > of several columns). > > What's the use case for this? Well, there's the possibility of things like a point type or something, where there's more than one column that gets turned into one Python object (immutable, of course). But I waver. Now I think I agree with you. There's lots of things that SQLObject *could* do, but I don't think it should do all those. So long as there are ways to code, manually, what you want to do, this is enough for most of these cases. Only when something is really common or really hairy or just not possible with the current code should we add more features. Like you said, we can do this with properties, and it's not too hard. For the id it's a bit more difficult, and I can deal with improving that. In combination with the non-integer keys, composite keys might not be too bad. (Though I draw the line at mutable primary keys!) And you can't do them with properties. I'd like to do some type coercion stuff, like I've mentioned but not implemented for a long time. Then I have to hold off on more features, because SQLObject could become difficult to understand. I think it's much more readable to do: class Position(SQLObject): x = FloatCol() y = FloatCol() def _get_pos(self): return (self.x, self.y) def _set_pos(self, value): self.set(x=value[0], y=value[1]) Than to do: class Position(SQLObject): pos = CompositeCol(FloatCol('x'), FloatCol('y')) Oh, sure, that's much more elegant looking, much more economical in typing. But it obscures what is made very explicit in the first example. And if you really wanted to you could always do: class TupleComposite(object): def __init__(self, *cols): self.cols = cols def __get__(self, obj, objtype): return tuple([getattr(obj, attr) for attr in self.cols]) def __set__(self, obj, value): obj.set(**dict(zip(self.cols, value))) class Position(SQLObject): x = FloatCol() y = FloatCol() pos = TupleComposite('x', 'y') But then it's up to you to explain what TupleComposite is, and DictComposite, and StructComposite, and whatever else you end up creating -- instead of SQLObject coming to be what is perceived to be a monolithic and complex system that is inaccessible to newcomers (which happens to a lot of projects). Anyway, which is a long way of saying I now agree, just composite ids are called for. They might look like: class Whatever(SQLObject): domain = StringCol() subdomain = StringCol() id = ('domain', 'subdomain') Ian |