[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
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(
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