[TransWarp] TableDM proof of concept, request for comments

Phillip J. Eby pje at telecommunity.com
Thu Oct 9 16:14:13 EDT 2003


At 12:36 PM 10/9/03 -0700, John Landahl wrote:

>See the attached tabledm.py for the code, and feel free to offer any
>criticism or suggestions.

A few issues I see:

* ID generation isn't multi-user safe; if two processes generate an ID at 
the same time, one will fail.

* Multi-column primary keys aren't supported

* A PropertyName of 'db' is likely to collide; you should probably either 
use 'TableDM.db', or better yet, simply Obtain(storage.ISQLConnection).

* Using 'None' as a return flag from 'writable()' is a bad idea if you want 
to support using NULL in the underlying database.  Usually, you'd map NULLs 
to/from None.  Perhaps NOT_FOUND or NOT_GIVEN would be a better choice

* EntityMap doesn't retrieve single entities; it should have a 'mapFrom' 
that simply returns self.dm[row[self.field]].  (Right now it seems to 
always return a collection, rather than a single item.)

* FieldMap.mapFrom() seems broken: why does it return the non-existent 
'self._field' instead of returning 'row[self.field]'?

* The code assumes '%s'-style placeholders are used by the underlying RDBMS.

If I were going to make something like this part of PEAK, I'd probably want 
to define a formal interface for field mappers, and I'd probably want to 
have a mechanism I could use to generate SQL templates ahead of time.  For 
example, your code generates SELECT, INSERT, and UPDATE query templates 
that are the *same* every time they're used.  Why not create bindings for 
say, 'selectTemplate', 'updateTemplate', and 'insertTemplate'?  You could 
then simply call 'self.db(self.whateverTemplate, values)' to perform the 
operations.

But that's not all...  suppose that for some reason you want to map 
something more complex than a single table, and you don't have or can't use 
a view...  Then the user simply writes custom 'whateverTemplate' SQL 
definitions in their subclass, as long as they declare their field mappings 
in the right order.

The other thing I'd probably do is make the mappings also implement 
binding.IRecipe, so that you could say, e.g.:

     fieldMap = binding.Make(
         [
             FieldMap('loginId'),
             FieldMap('fullName'),
             FieldMap('password')
         ]
     )

Of course, for this to work, these things would actually be factories 
rather than the "real" field-mapping objects.  For example, the ones that 
use DM's would need to accept a component key, instead of the actual 
DM.  Then, when they were invoked by binding.Make they'd look up the DM 
they were supposed to connect to.

I'd want mappers to allow easy renaming of fields between the DB and the 
DM, and easy specification of type conversion or adaptation in each 
direction.  And last, but very far from least, I'd want a way to allow 
object-level queries to be mapped down to SQL queries.  But that's probably 
a much bigger project in itself.  :)




More information about the PEAK mailing list