[sqlalchemy] Re: Extended Query subclass with add_named_column method

2009-03-31 Thread Michael Bayer

wouldn't this be accomplished more simply using contains_eager() ?

On Mar 31, 2009, at 9:12 AM, Bob Farrell wrote:


 Hello, SQLAlchemy people,

 So I spoke to jek on IRC to see if there was a way to use add_column
 without causing the query to return a RowTuple and it doesn't look
 like there is, so I wrote this:

 class AdditiveQuery(Query):

Extended sqlalchemy.orm.Query class with add_named_column method
 to add a
column onto a query but store the values on the main RowProxy
 object
instead of yielding RowTuples as add_column does:

q = AdditiveQuery(FooModel, session=some_session)
q = q.join((BarModel, FooModel.x == BarModel.x))
q = q.add_named_column(BarModel.baz, 'bar_baz')
for row in q:
print q.bar_baz

def __init__(self, *args, **kwargs):
self._named_columns = []
super(AdditiveQuery, self).__init__(*args, **kwargs)

def add_named_column(self, column, alias=None):
if alias is None:
alias = column.key
if alias in self._named_columns:
raise ValueError(Alias %s already in use. % (alias,))
self._named_columns.append(alias)
return self.add_column(column)

def __iter__(self):
def g(it):
checked = False
for rows in it:
row = rows[0]
rest = rows[1:]
for alias, value in zip(self._named_columns, rest):
if not checked and hasattr(row, alias):
raise ValueError(Alias %s already exists on
 
original row object. % (alias,))
setattr(row, alias, value)
yield row
checked = True
it = super(AdditiveQuery, self).__iter__()
return g(it)

 The only immediate issue I can think of with this is that if you do
 AdditiveQuery(FooModel, BarModel)  then this is going to blow up as
 it'll try to call setattr on a RowTuple - I'm not sure whether to a)
 just let this happen, b) take preventative measures and raise a more
 useful exception, c) allow specifying exactly which entity to attach
 the named_column onto.

 Any suggestions welcome and, of course, if any of the SA boys want to
 stick this into SQLAlchemy, you're more than welcome.

 Thanks !

 


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@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
-~--~~~~--~~--~--~---



[sqlalchemy] Re: Extended Query subclass with add_named_column method

2009-03-31 Thread Bob Farrell

Yes, if this has been defined on the mapper. Generally I do a lot of
just using SQLAlchemy to as a way of writing SQL in Python code that
can be passed around for dynamically building up queries so my mappers
tend to be quite bare - or are you suggesting this can be done without
configuring the relation on the mapper ? If there's a way to do this
in SQLAlchemy that doesn't need extra mapper config then I'm all
ears. :-)

On Mar 31, 3:22 pm, Michael Bayer mike...@zzzcomputing.com wrote:
 wouldn't this be accomplished more simply using contains_eager() ?

 On Mar 31, 2009, at 9:12 AM, Bob Farrell wrote:



  Hello, SQLAlchemy people,

  So I spoke to jek on IRC to see if there was a way to use add_column
  without causing the query to return a RowTuple and it doesn't look
  like there is, so I wrote this:

  class AdditiveQuery(Query):
     
     Extended sqlalchemy.orm.Query class with add_named_column method
  to add a
     column onto a query but store the values on the main RowProxy
  object
     instead of yielding RowTuples as add_column does:

     q = AdditiveQuery(FooModel, session=some_session)
     q = q.join((BarModel, FooModel.x == BarModel.x))
     q = q.add_named_column(BarModel.baz, 'bar_baz')
     for row in q:
         print q.bar_baz
     
     def __init__(self, *args, **kwargs):
         self._named_columns = []
         super(AdditiveQuery, self).__init__(*args, **kwargs)

     def add_named_column(self, column, alias=None):
         if alias is None:
             alias = column.key
         if alias in self._named_columns:
             raise ValueError(Alias %s already in use. % (alias,))
         self._named_columns.append(alias)
         return self.add_column(column)

     def __iter__(self):
         def g(it):
             checked = False
             for rows in it:
                 row = rows[0]
                 rest = rows[1:]
                 for alias, value in zip(self._named_columns, rest):
                     if not checked and hasattr(row, alias):
                         raise ValueError(Alias %s already exists on
  
                             original row object. % (alias,))
                     setattr(row, alias, value)
                 yield row
                 checked = True
         it = super(AdditiveQuery, self).__iter__()
         return g(it)

  The only immediate issue I can think of with this is that if you do
  AdditiveQuery(FooModel, BarModel)  then this is going to blow up as
  it'll try to call setattr on a RowTuple - I'm not sure whether to a)
  just let this happen, b) take preventative measures and raise a more
  useful exception, c) allow specifying exactly which entity to attach
  the named_column onto.

  Any suggestions welcome and, of course, if any of the SA boys want to
  stick this into SQLAlchemy, you're more than welcome.

  Thanks !
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@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
-~--~~~~--~~--~--~---



[sqlalchemy] Re: Extended Query subclass with add_named_column method

2009-03-31 Thread Michael Bayer

no, you'd need the mapping to be set up.So yes, if you need to  
compose your result objects together in some way that is specific to  
your use case and has no relationship to your mappings or any standard  
SQLAlchemy feature, you need to either post-process the result of  
Query or create a subclass that does what you want.



On Mar 31, 2009, at 9:41 AM, Bob Farrell wrote:


 Yes, if this has been defined on the mapper. Generally I do a lot of
 just using SQLAlchemy to as a way of writing SQL in Python code that
 can be passed around for dynamically building up queries so my mappers
 tend to be quite bare - or are you suggesting this can be done without
 configuring the relation on the mapper ? If there's a way to do this
 in SQLAlchemy that doesn't need extra mapper config then I'm all
 ears. :-)

 On Mar 31, 3:22 pm, Michael Bayer mike...@zzzcomputing.com wrote:
 wouldn't this be accomplished more simply using contains_eager() ?

 On Mar 31, 2009, at 9:12 AM, Bob Farrell wrote:



 Hello, SQLAlchemy people,

 So I spoke to jek on IRC to see if there was a way to use add_column
 without causing the query to return a RowTuple and it doesn't look
 like there is, so I wrote this:

 class AdditiveQuery(Query):

Extended sqlalchemy.orm.Query class with add_named_column method
 to add a
column onto a query but store the values on the main RowProxy
 object
instead of yielding RowTuples as add_column does:

q = AdditiveQuery(FooModel, session=some_session)
q = q.join((BarModel, FooModel.x == BarModel.x))
q = q.add_named_column(BarModel.baz, 'bar_baz')
for row in q:
print q.bar_baz

def __init__(self, *args, **kwargs):
self._named_columns = []
super(AdditiveQuery, self).__init__(*args, **kwargs)

def add_named_column(self, column, alias=None):
if alias is None:
alias = column.key
if alias in self._named_columns:
raise ValueError(Alias %s already in use. % (alias,))
self._named_columns.append(alias)
return self.add_column(column)

def __iter__(self):
def g(it):
checked = False
for rows in it:
row = rows[0]
rest = rows[1:]
for alias, value in zip(self._named_columns, rest):
if not checked and hasattr(row, alias):
raise ValueError(Alias %s already exists  
 on
 
original row object. % (alias,))
setattr(row, alias, value)
yield row
checked = True
it = super(AdditiveQuery, self).__iter__()
return g(it)

 The only immediate issue I can think of with this is that if you do
 AdditiveQuery(FooModel, BarModel)  then this is going to blow up as
 it'll try to call setattr on a RowTuple - I'm not sure whether to a)
 just let this happen, b) take preventative measures and raise a more
 useful exception, c) allow specifying exactly which entity to attach
 the named_column onto.

 Any suggestions welcome and, of course, if any of the SA boys want  
 to
 stick this into SQLAlchemy, you're more than welcome.

 Thanks !
 


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@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
-~--~~~~--~~--~--~---