Thread: Re: [SQLObject] Join tables (Page 2)
SQLObject is a Python ORM.
Brought to you by:
ianbicking,
phd
From: Luke O. <lu...@me...> - 2003-11-11 17:30:14
|
> It can do both! > > But you (the people who own the project) need to decide which side of the > wall > to sit on. If you're going to go the superset way, then it needs to be > thought of now rather than later. Just to clarify my email, yes, I agree! Do both, I think it has always been the intent of SQLObject to go both ways (although in my mind, not arbitrary object storage, and never at the expense of python style or relational modelling :). And yes, I've started looking at the objectmatter site to see what might be missing. But as in all opensource projects, who's going to code these things? Someone with the itch. To bring it back to the specific superset issue, I see the following points: a. SQLObject currently stores no information about class relationships (inheritance trees) except for explicit joins/fkeys. b. We currently only directly support what the objectmatter docs describe as a horizontal mapping (as I said, "one complete table per concrete class"). So in order to add the functionality you requested for supersets, two separate pieces: 1. A syntactic method for describing inheritance. Using python class inheritance is the obvious choice. However, that may be overloaded from what we're willing to implement (multiple inheritance?). Alternatively, an extends/derives method, although it feels less obviously pythonic. Along with this comes the syntax and logic necessary to have joins of the Person--*Area type alternatively return subset objects (Homes/Offices), and reverse. (actually, reverse might already work... if you define Area to have a fkey to Person, both Home and Office will as well. yes.) In my mind, this is the OO side of the development (ie, SQLObject would now have conceptual support) 2. Independently, support for vertical mapping. That is, #1 would work with our current method of supporting 'inheritance', this support would allow that syntax and logic to work across specially designated foreignkeys (the Home-->Area key). This is the DB/implementation side of the development (extending the conceptual support to a new db structure). Comments? - Luke |
From: John B. <jb...@te...> - 2003-11-11 17:49:46
|
On Tuesday 11 November 2003 17:30, Luke Opperman wrote: > But as in all opensource projects, who's going to code these things? > Someone with the itch. I might have a shot, one day. It depends if I need to use Python on a much bigger project that means I have to try to model serious relationships ;-) > To bring it back to the specific superset issue, I see the following > points: > > a. SQLObject currently stores no information about class relationships > (inheritance trees) except for explicit joins/fkeys. Well it doesn't really have to. If we know B and C extend A, we can SELECT across tables B and C to find matching rows. Not efficient, but that's accepted with the type of mapping. You (the developer) can also decide to store information. For example, in the Java systems I write, I have a ClassType table mapping a fully qualified classname to a primary key. I can then have a foreign key from a top level object to the ClassType table, for example: class Thing (SQLObject): areas = MultipleJoin("Area") classType = ForeignKey("ClassType") Therefore I can do: areas.get(classType.get()) (or whatever syntax you'd prefer) to get the areas inside the Collection. Assuming they are all of the same type. > 1. A syntactic method for describing inheritance. Using python class > inheritance is the obvious choice. However, that may be overloaded from > what we're willing to implement (multiple inheritance?). Alternatively, an > extends/derives method, although it feels less obviously pythonic. I'd suggest multiple inheritence is a step to far, as that really does get very complex. I've never been sold on multiple inheritence, however people will want to use it (I'm sure), so adding support would be nice. Take: class A (SQLObject): class B (SQLObject): class C (A, B): We'd need to foreign keys in C (fk_a and fk_b) to support this. But this can be done automatically, I guess. > Along with this comes the syntax and logic necessary to have joins of the > Person--*Area type alternatively return subset objects (Homes/Offices), and > reverse. (actually, reverse might already work... if you define Area to > have a fkey to Person, both Home and Office will as well. yes.) Something to keep in mind is we'd want to use table aliasing. Objectmatter 'forgot' this, and as a result they've well and truely shot themselves in the foot as you can't do complex joins. (Deadline to meet, /me goes back to work) John -- John Baker, Senior Developer, TEAM. http://www.teamenergy.com Views expressed in this mail are my own. |
From: John B. <jb...@dr...> - 2003-11-11 17:20:05
|
Ok :-) So please provide me with some code that will do my Ward/Constituency/Area and 'something has many Areas' example... :) J On Tue, Nov 11, 2003 at 11:14:40AM -0600, Ian Bicking wrote: > On Nov 11, 2003, at 4:20 AM, John Baker wrote: > > If SQLObject is to be aimed at a very limited set of solutions, that > > don't > > lend themselves towards proper OO programming, then perhaps clearly > > stating this on the website would be a step forward. But at this point > > in > > time, without superset mapping, you cannot model anything more than > > trivial relationships. This makes it rather unhelpful, which is a shame > > because it's actually quite easy to use. > > You have to understand, it's easy to use because the mapping is simple > and clear. I am trying to avoid frameworkification in SQLObject, which > is a difficult task. To me, exposed object hierarchies are one of the > creepers which can overwhelm a project if left unchecked. > > Now, I'm not sure if that's the case with this example, since the > object hierarchies we're talking about are in user code, not the > library code. Still, I'm wary of all things inheritance-related. Call > it the Zope syndrome. > > My intention with SQLObject is not that it be all things to all people, > but rather that you can build all things on it. The more complex > SQLObject is, the more disconnect there will be when the complexity of > your problem doesn't match the complexity of SQLObject. As it is > SQLObject is clearly an easier foundation for building superset objects > than the DBAPI. To do so it may be a little ad hoc right now, but you > have to build ad hoc designs before generalizing anyway, and a little > ad hoc design never killed anyone. > > Maybe having done that you'll desperately want to generalize this > particular recipe. I can only say that I would be much happier seeing > it phrased in an explicit manner using composition of objects, rather > than inheritance, perhaps because I don't treasure inheritance the way > a "real OO programmer" might (which is true), or perhaps because I > dislike false cognates and subtle disconnects. > > > To the developer, how the data is stored is totally irrelevant. But > > when > > your developer can't actually model relationships because the system of > > persistence is restrictive, then we have a problem. I've already > > provided > > two or three examples that clearly demonstrates that SQLObject can't do > > what I want it to do, and I'm hardly trying :-) > > FWIW, you don't have to code those examples as inheritance, and I > naturally wouldn't do so. Composition is quite powerful, even if > mundane, and is pleasantly explicit. > > > And as we all, as good OO developers know, if you build on poor > > foundations, you regret it later in life. > > As all good agile developers know, you make it up as you go along ;) > > -- > Ian Bicking | ia...@co... | http://blog.ianbicking.org > |
From: Ian B. <ia...@co...> - 2003-11-11 17:41:59
|
On Nov 11, 2003, at 11:20 AM, John Baker wrote: > Ok :-) > > So please provide me with some code that will do my > Ward/Constituency/Area > and 'something has many Areas' example... :) def oneOrNone(val): try: return val[0] except IndexError: return None class Area(SQLObject): # Really should be a one-to-one join for these... def _get_ward(self): return oneOrNone(Ward.selectBy(area=self)) def _get_consituency(self): return oneOrNone(Constiuency.selectBy(area=self)) ... class Ward(SQLObject): area = ForeignKey('Area') ... Ta-da! More work if you want to fold the attributes of the connected tables into the original Area object. I'm sure you won't be satisfied by this, but it's only bad if you come into the problem with inheritance fixed in your mind. I tend to come at the problem thinking in terms of related objects, which works fine right now, and with which you can handle the same problems, even if in a different way. -- Ian Bicking | ia...@co... | http://blog.ianbicking.org |
From: John B. <jb...@te...> - 2003-11-11 17:51:03
|
On Tuesday 11 November 2003 17:41, Ian Bicking wrote: > On Nov 11, 2003, at 11:20 AM, John Baker wrote: > > Ok :-) > > > > So please provide me with some code that will do my > > Ward/Constituency/Area > > and 'something has many Areas' example... :) > > def oneOrNone(val): > try: > return val[0] > except IndexError: > return None > > class Area(SQLObject): > # Really should be a one-to-one join for these... > def _get_ward(self): > return oneOrNone(Ward.selectBy(area=self)) > def _get_consituency(self): > return oneOrNone(Constiuency.selectBy(area=self)) > ... > > class Ward(SQLObject): > area = ForeignKey('Area') > > ... > > > Ta-da! More work if you want to fold the attributes of the connected > tables into the original Area object. I'm sure you won't be satisfied > by this, but it's only bad if you come into the problem with > inheritance fixed in your mind. I tend to come at the problem thinking > in terms of related objects, which works fine right now, and with which > you can handle the same problems, even if in a different way. Well attributes in area would be nice, but it'll do for now :) -- John Baker, Senior Developer, TEAM. http://www.teamenergy.com Views expressed in this mail are my own. |