On 2/26/07, Russell Keith-Magee <[EMAIL PROTECTED]> wrote:
>
> On 2/25/07, Malcolm Tredinnick <[EMAIL PROTECTED]> wrote:
> >
> > What would the new (QuerySet) world order look like
> > ----------------------------------------------------
> > What I propose to do is to split out the SQL construction from the body
> > of QuerySet and make it into a separate class. This class (let's call it
> > Query, for simplicity) would end up being a "query" attribute on
> > QuerySets and it's __str__ function would return the appropriate SQL
> > statement.
>
> Broadly speaking, +1. When I last gave serious thought to aggregates,
> I was starting to have similar ideas on the need for a QuerySet
> refactor. Nice to know I'm not completely out on my own.
>
> Of course, the devil is in the detail, and there are some interesting
> edge cases where WHERE, HAVING and GROUP BY intersect, but if you're
> willing/able to come up with a first draft, I'm happy to throw my
> weight into poking holes in it. :-)

I went for a skiing trip last week, since there was no snow, I gave
the QuerySet a try:

I implemented a very simple approach, using Query as a class
representing the SQL statement ( I didn't actually deal with
querysets, just the SQL)

I use objects

class Model - represents a model/table, can be joined with other model
via a path ( 'some__related__lookup'.split( '__' ) ), has a reference
to query

class Field - has a reference to Model instance so that it can get its
alias (one django model can be used twice in one query), has a
reference to query

operator - a simple dictionary containing functions producing SQL
snippets for expressions, for example:
{
  'lt' : lambda x,y: '%s < %s' % (x, y),
}, more operators can be registered at runtime (custom SQL operators)

class Q - represents generic condition, can be ORed and ANDed, can be
used as WHILE or as HAVING clauses, have the filter( **kwargs )
method, has a reference to query

class Query - contains list of Fields to select, Models to select
from, and mainly encapsulates all lookup operations, so you can call
self.query.lookup_path( some_path )
and it will return a correct Field instance representing the field and
add the necessary joins and where conditions to the query in the
background -- this is the main method where most work will be done, to
demonstrate, this is how a working order_by() method looks:

  def order_by( self, *args ):
        """
          '-field', 'related__field__to__order__by'
        """
        self.order_by = []
        for field in args:
            if field.startswith( '-' ):
                order = 'DESC'
                field = field[1:]
            else:
                order = 'ASC'
            field = self.lookup_path( field.split( '__' ) )
            self.order_by.append( ( field, order, ) )

rendering the order by:
        if self.order_by:
            output.append( 'ORDER BY' )
            output.append( ', '.join( '%s %s' % ( f.alias, order ) for
f, order in self.order_by ) )

the other thing this approach will bring is that by overriding Query's
__str__() method, you can modify everything - nothing is stored in
text form, everything is normalized and only when putting the SQL code
together is it evaluated. so we could even move this (or parts of it)
to the backend and thus work with the special features of the
individual engines. Or just allow users to supply their own Query
class. only the Q object representing the condition is rendered
separately via the operators.

I will try and clean up the code today and post it along with some
examples. Its just a proof of concept, so it can only deal with simple
forward foreign keys, but I think this approach might just work.

start the poking ;)

>
> > Things I think become easier this way
> > -------------------------------------
> >         - aggregates and other computed output columns
> >         - custom fragments in portions of a query (as opposed to writing
> >         a whole query for the database)
> >         - adding new query types (GIS?)
> >         - different database syntax (LIMIT/OFFSET in both MS SQL Server
> >         and Oracle)
> >
> > I don't know of any announced plans/wishes that affect QuerySets that
> > would become more difficult under this change, so please sing out if you
> > know of any.
>
> That's a pretty good list. There might be a few others, but these are
> the big ones I am aware of.
>
> Yours,
> Russ Magee %-)
>
> >
>


-- 
Honza Kr�l
E-Mail: [EMAIL PROTECTED]
ICQ#:   107471613
Phone:  +420 606 678585

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to