On Thu, 6 May 2010 10:39:28 -0400
Michael Bayer <mike...@zzzcomputing.com> wrote:

> 
> On May 5, 2010, at 11:46 PM, Kyle Schaffrick wrote:
> 
> > 1. While you can override existing operators that work on
> > ColumnElements without doing much funny business, if you want to
> > add *new* operations to it, the abstractions leak fairly badly.
> > This seems to be because operator definitions aren't delegated to
> > the class representing the type, which is suboptimal because I
> > would think that the type of a ColumnElement is what logically
> > "defines" what operations are valid on it. The result of this is
> > that I have to create classes like HStoreColumn,
> > HStoreColumnElement, _HStoreDeleteFunction, and so on, so that SQL
> > expressions which are logically of type 'hstore' will have the
> > extended hstore operations available.
> 
> yeah I can see how it could go that the entire "comparator" interface
> moves onto TypeEngine.    There are obviously dozens of major design
> decisions which would have to occur for that to happen and there may
> also be tradeoffs.
> 

Yeah it would be an invasive refactoring, no arguing that. And I'm not
sure it would have to be specifically that the whole thing moves to
TypeEngine, just that the ColumnElement would allow the type to provide
a (possibly empty) set of extended or overridden operations or methods
which are valid on expressions of that type. Maybe with a nested class?
I dunno.

I did noticed that GeoAlchemy ran into this same problem too when
adding support for custom expression methods that apply GIS operators,
since I actually consulted their code to see how they solved it.

On the plus side it feels like things are moving in this direction
anyway, with _adapt_expression() now consulted to compute the effective
type of an operator expression. While this currently appears to be for
the sole purpose of selecting the proper bind_processor or
result_processor, it seems like it would be possible (not to be
confused with "easy") to use this inferred type data to control the
dispatch of expression operations as well.

> > 
> > 2. That expression operations on Foo.some_col and
> > foo_table.c.some_col take completely different paths in the
> > implementation was slightly surprising. I would have expected the
> > former to be implemented in terms of the latter, so that SQL
> > expressions available on some column type are automatically
> > available on the descriptor of a class which maps to that column.
> > But I don't know, there might be good reasons for this. In any case
> > I'm trying to figure out how to write my Comparator for hstore
> > without repeating myself a lot.
> 
> Well consider that Foo.some_col does a lot more than a Column object
> does.   Ultimately its a descriptor object from the attributes
> package, and this object is also used for non-column attributes as
> well.   I.e. it would be less consistent for a mapped object to look
> like:
> 
> class Foo(object):
> 
>     id = < column object>
>     related_stuff = <instrumented attribute>
>     id_synonym = <instrumented attribute>
> 
> we try to make the Column and the InstrumentedAttribute systems
> similar by both subclassing expression.ColumnOperators, which is
> where the column-oriented comparisons occur.   Ultimately when you
> say Foo.some_col == 'foo', it is getting down to the __eq__() method
> on foo_table.c.some_col, so ORM comparators are certainly implemented
> in terms of the SQL constructs, just maybe theres more indirection
> than you would initially think necessary.   In GOF speak the
> InstrumentedAttribute is a "decorator" (not in the Python sense) - an
> object that proxies requests to another, while adding other
> functionality.
> 

Yeah I am definitely not lobbying for an inconsistency here where
InstrumentedAttribute for plain columns goes away, I feel pretty aware
of what it adds to the equation. I guess what I was thinking/expecting
was more like, SQL expressions involving InstrumentedAttributes would do
their thing by proxying the operation to the underlying Column
*instance*, such that in the case that it was some quack-alike object
(an HStoreColumn, or a GeometryColumn), it would Just Work.

If you're saying this is how it works currently then I'll shut up
now :) I tried to trace it but it was a lot to keep in my head and I
almost certainly missed something. I do know that it's not aware of any
custom methods on the underlying Column, since has_key(), dissoc(),
assoc() and so on do not work without a custom comparator. Since I
don't have a good idea how to make that work, don't take it as a "you
should fix this" -- last thing I want to do is criticize the design
without proposing a solution!

Anyway, thanks for the thoughts.

-Kyle

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalch...@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.

Reply via email to