On Sunday 19 November 2017 13:14:46 [email protected] wrote:
> Ok, I see not everyone are happy with idea of ORM expression calculated on
> Python side:)

As the main "not happy" (I think), I should say, it's not the calculation-on-
Python-side per se that bugs me; it's the claim that the two ways of 
calculation will always give the same results. As has been pointed out, on all 
sorts of edge cases they won't, and if the (programmer) user is unaware of 
that, this can cause all sorts of issues.

If an API is set up, that makes this point clear enough in the naming, I will 
be satisfied. For this, the SQLAlchemy syntax could be used, with appropriate 
names; e.g. we'd declare

    is_adult = models.DBCalculatedField(
        Case(When(age__gt=18, then=True), default=False
    )
    # (I'm pretty sure we want an Expr there, not a Q object)

and later add

    @is_adult.local_estimate
    def is_adult(self):
        return (self.age > 18)

and allow the local estimate to be used whenever we think the object is not 
fresh from the database. Such names would at least give people pause for 
thought, when they provide the Python almost-equivalent, that it might 
actually not be equivalent.

For this to provide the value I'm after, though, the range of 
"local_estimate"s provided automatically must be extremely limited, if any at 
all.

> But it ruin DRY idea by making author to write same logic twice (for Python
> and SQL), is not it?

I'll give it a slogan: 

        It isn't really DRY if it isn't really R

That is: Telling people "what you're doing here is only *almost* equivalent to 
what you'd be doing there", *in the code* and not just in the docs, is far 
more important than what seems like DRY if you don't take this "almost" in 
account.

The rest of this mail may be a little argumentative, and not essential. Feel 
free to skip.

> 
> I still do not like database approach.
> * If I have list of objects, do you want to have O(n) queries?

Why would you need O(n) queries? If the calculated field is added as if with 
annotate(), you get it all in one query. You may need O(n) queries if you want 
to update n objects -- but then, at least with Django core, you need O(n) 
queries anyway.

> * If calculated field is function of only model fields (no foreign keys
> etc) it should work locally: some projects may have no database at all.
> 

If a project has no database at all, why would it use anything more elaborate 
than simple Python properties?

> >>Even simple comparisons can be difficult to simulate in Python. As an
> 
> example, some databases treat empty strings as null
> But ORM should handle it somehow, should not it?
> I want to belive that "filter(alias__isnull=True)" works identically across
> all databases.
> So, we need to do same on Python side.
> 

You want to believe it, but it isn't true... exactly because, as Anssi said, 
some databases (namely Oracle) store empty strings as null, while others (more 
correctly) think an empty string is a valid string value.

Shai.

Reply via email to