On Friday, January 3, 2014 6:34:13 PM UTC+2, Josh Smeaton wrote:
>
> I now have all tests passing on Postgres and SQLite (See 
> here)<https://github.com/jarshwah/django/compare/akaariai:lookups_3...aggregates-14030?expand=1>.
>  
> I still haven't touched GIS, but I believe it should be as simple as 
> changing the query to directly call prepare on the expression, and removing 
> references to SQLEvaluator.
>
> The big problem is that if we drop the SQLEvaluator and similarly the 
>> models/aggregates.py <-> models/sql/aggregates.py ways of writing 
>> Expressions and Aggregates, then there will be a lot of broken 3rd party 
>> aggregates and expressions. Even if the APIs are private I am not willing 
>> to just drop the old way. So, some backwards compatibility is required.
>>
>
> What level of backwards compatibility would be required? I like the idea 
> of using the @add_implementation decorator to extend Expressions and 
> Aggregates, but would that be enough? I've not used django-nonrel or any 
> other non-official backend, so I'm really not sure what would be required 
> or where a line should be drawn. The SQLEvaluator API (mostly) has moved 
> down to ExpressionNode, so the callers only change by calling .prepare on 
> the value rather than wrapping it in an Evaluator.
>

The biggest problem are 3rd party Aggregates. To write a custom aggregate 
one needed two classes, one for user facing API, one for implementing that 
API for SQL queries.

Taking first example I found from Google, from 
http://voices.canonical.com/michael.hudson/2012/09/02/using-postgres-array_agg-from-django/:

class SQLArrayAgg(SQLAggregate):
    sql_function = 'array_agg'

class ArrayAgg(Aggregate):
    name = 'ArrayAgg'
    def add_to_query(self, query, alias, col, source, is_summary):
        klass = SQLArrayAgg
        aggregate = klass(
            col, source=source, is_summary=is_summary, **self.extra)
        aggregate.field = DecimalField() # vomit
        query.aggregates[alias] = aggregate

Then doing:
    qs = SomeModel.objects.annotate(ArrayAgg('id'))
should produce results using the ArrayAgg class. This is using private API, but 
there is a lot of code relying on this. We should support this if at all 
possible.

Another case you should check is how GIS works *without* rewriting anything in 
django.contrib.gis. If that works, then that shows fairly good backwards 
compatibility.


Lets try to find the common use cases and try to make sure that they work 
without any modification during deprecation period, and they are as easy as 
possible to rewrite to use the new way.

If this turns out to be too painful to support backwards compatibility we 
have to consider either dropping compatibility or maybe supporting both 
NewAggregate and old style Aggregate simultaneously.

I am not sure how much custom ExpressionNodes there are, at least such 
nodes that rely on having SQLEvaluator available. If anybody reading this 
knows of any please mention them here.

I'll try to check your work in detail as soon as possible. Unfortunately I 
am very busy at the moment, so I can't guarantee anything.

 - Anssi

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/f115b7b9-80d5-435d-9d14-cd38e66e3a28%40googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to