On Thursday, June 19, 2014 12:23:20 AM UTC+3, Carl Meyer wrote:
>
> On 06/18/2014 02:59 PM, Aymeric Augustin wrote: 
> > 2014-06-18 19:18 GMT+02:00 Carl Meyer <ca...@oddbird.net <javascript:> 
> > <mailto:ca...@oddbird.net <javascript:>>>: 
> > 
> >     If you need a Function in your 
> >     project (whether provided by Django or by a third-party library), 
> and 
> >     the Function doesn't natively support the database backend you're 
> using, 
> >     you can simply subclass it, add the appropriate as_vendor method, 
> and 
> >     use your subclass. 
> > 
> > 
> > I was thinking about third-party database backends. How are they 
> expected 
> > to ship customised implementations of Functions included in Django? 
>
> Yes, I wasn't thinking about this case in my first mail, and I agree 
> that this is a serious problem for the pure as_vendor() approach; it's 
> not acceptable IMO to expect third-party database backends to 
> monkeypatch their as_vendor() methods onto the built-in Function classes. 
>
> I think database backends should have a hook to override the SQL 
> implementation of any given Function. I don't think this needs to imply 
> pushing the default implementation of all Functions down into the 
> database backend (that just makes life unnecessarily difficult for 
> third-party Functions). 
>

This is possible to do by supplying a custom SQLCompiler class for the 
backend, and overriding its .compile() method.

Personally I don't see usage of as_vendor() as that problematic. Supplying 
as_vendor in first DatabaseWrapper.__init__() should work. Yes, we are 
dynamically altering the node's class. But we are just using the __dict__ 
of the node to store backend specific implementation instead of using a 
dictionary somewhere in the backend for the implementation. Using the 
__dict__ has the advantage that inheritance works automatically.

As multiple core developers have said they don't like as_vendor() for 3rd 
party backend support it might be better to offer official hook for 
altering the generated SQL. That is, change the SQLCompiler.compile() 
method from

    def compile(self, node):
        vendor_impl = getattr(
            node, 'as_' + self.connection.vendor, None)
        if vendor_impl:
            return vendor_impl(self, self.connection)
        else:
            return node.as_sql(self, self.connection)

to

    def compile(self, node):
        ret = self.connection.compile(node)
        if ret is not None:
            return ret
        vendor_impl = getattr(
            node, 'as_' + self.connection.vendor, None)
        if vendor_impl:
            return vendor_impl(self, self.connection)
        else:
            return node.as_sql(self, self.connection)

The main reason for offering a hook is that overriding SQLCompiler is a bit 
problematic. There exists various subclasses of SQLCompiler, and the 
backend needs to support those, too.

 - 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/ea7cffad-56f3-4ea5-9249-773c19aa2204%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to