QuerySet This is the top
layer of query state. From here on out it’s like an onion. Not backend speciﬁc. _db _result_cache _iter query
Query Right now this holds
all state for a query. It’s semi-backend speciﬁc. Right now there’s one, and it’s speciﬁc to SQL backends. Computes most JOINS, aggregates, etc. Translates Q objects into Where objects.
The Query Problem It’s something
of a lossy translation. Translating ﬁlter(), values(), and other calls into internal datastructures is lossless with respect to the database being used, but not with respect to other databases. If you’ve got all SQL databases you’re ﬁne, but if you mix in a non-relational DB you’ve got problems. More on this later.
SQLCompiler Takes a Query and
a connection and turns it into SQL (and executes it). This also does some computation of joins (for select_related). This is the totally backend speciﬁc part (only part that knows about the actual connection and database). The rest of the chain just *assumes* a SQL db.
You call methods on a
QuerySet Which calls methods on a Query Which mutates some datastructures You evaluate a QuerySet Which asks it’s Query for a Compiler Which generates some SQL Which calls some methods on the backend Which gets a cursor and evaluates it
Query thinks in terms of
SQL It chooses between join types it generates table aliases it splits ﬁlters between HAVING and WHERE and probably some other stuff
Why is this an issue
How do I ask a MongoDBCompiler to compile a LEFT OUTER JOIN vs. an INNER JOIN? Or a HAVING vs a WHERE? These concepts don’t map cleanly, so the translation is lossy across backends