Well initial response to this post has been overwhelmingly low, but
thats fine with me.   After trying to tackle this today, I realized
that I actually didnt want to add a brand new query object and go
through a painful deprecation procedure again and all that...and I
also observed that the notion of a query being against a single entity
is pretty important..things like get(), load() and all that dont make
much sense for multiple entities.  Also, all the things Ive wanted to
do are not actually that hard as we already have code to do most of
it.

So I did not add any new classes or modules, no new methods on
session, I didnt go with my modified "generative" approach (its just
like it always was) and changed absolutely nothing about Query thats
already there (well one little thing i dont think anyone was using).
But I added a whole lot of new methods to Query, essentially
everything SelectResults was able to do.  I was concerned about having
just too much crap on Query but i think it turned out fine.  Plus I
added a little bit of hibernate-like capabilities to query multiple
entities and extra columns too.

So...with that, heres what Query can do now.

First of all, the same stuff that youve always used is just like it
always was:

      query.select_by()
      query.select()
      query.get()
      query.count()
      query.select_by_XXX()....

A couple of methods that Ive never liked because they are klunky, are
still there anyway:

    query.join_to()
    query.join_via()

As it stands, Query has two "generative" methods already (which also i
had to fix a little bit since "generative"-ness would wipe out what
was previously there).  these return for you a new Query with
modifications to its state:

   query.options()
   query.with_lockmode()

So we add a lot of new generative methods taken from SelectResults,
all of which return a brand new Query.  the things you add here will
also take effect on subsequent calls to the regular select(), count(),
select_by(), etc:

   query.filter() - adds criterion
   query.filter_by() - ditto
   query.join() - joins to a property name, or a list
   query.outerjoin()
   query.order_by()
   query.group_by()
   query.distinct() - applies DISTINCT
   query.offset()
   query.limit()
   query[3:5]  -> applies offset 3, limit 2

like SelectResults, we have some "executors" -

  query.list()
  list(query)

or just call query.select(), selectfirst(), selectone(), etc. to
execute whatever has been built up.

the aggregates, which take a Column (not sure how popular these are):

   query.avg()
   query.sum()
   .. and others

So a generative example, including "join" which im really excited
about.  join can act either like "join_to()":

q =
session.query(Person).filter_by(people.c.name.like('%2')).join('status').filter_by(name="active")
print q.list()

or like "join_via" (which is more deterministic), if you send a list:

    l = q.filter(orderitems.c.item_name=='item 4').join(['orders',
'items']).list()

and then, some brand new stuff - better support for "querying more
than one thing at a time".  the instances() method, which was able to
take a list of *mappers, now returns the results the way the docs say
they do, as a list of tuples, each tuple having an entry for each
mapper.  additionally, when that option is used, the "uniquing" of the
result is turned off - this so that the results you get back
correspond to the rows that went in.  and, you can stick arbitrary
columns, not just mappers, in the list too...it will just pull them
from the row.

in addition to the changes on instances(), you can add extra entities/
columns to the compilation as well:

   query.add_entity() - adds columns to the select criterion
   query.add_column() - adds columns to the select criterion

so what can we do with this ?  things like, query an entity and an
aggregate function at the same time:

        q = sess.query(User)
        q = q.group_by([c for c in
users.c]).outerjoin('addresses').add_column(func.count(addresses.c.address_id).label('count'))
        l = q.list()

which will return for you a list of tuples:

     [
        (user1, 3),
        (user2, 5),
        (user3, 0),
        ..etc
     ]

note the "label" is needed right now for a function, it makes it
possible for Query to target the column correctly.

another one from the unit tests.  the "users" table has users 7, 8, 9
in it.  the "addresses" table has addresses 1, 2, 3, 4.  user #7
refereces address #1, user #8 references addresses 2, 3 and 4.

        (user7, user8, user9) = sess.query(User).select()
        (address1, address2, address3, address4) =
sess.query(Address).select()

        q = sess.query(User)
        q = q.add_entity(Address).outerjoin('addresses')
        l = q.list()
        assert l == [
            (user7, address1),
            (user8, address2),
            (user8, address3),
            (user8, address4),
            (user9, None)
        ]

this is how the "non-uniquing" works.

anyway, its all in the trunk, feel free to screw around.



--~--~---------~--~----~------------~-------~--~----~
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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to