Skip to content

Commit

Permalink
Initial take at reworking "Queries" documentation (#1551)
Browse files Browse the repository at this point in the history
The existing version doesn't cover cases like when `User.firstname`,
`User.friends.firstname`, and `User.friends.lastname` are all
mentioned and the `User.friends` sets need to be dependent on the
elements in `User`.
  • Loading branch information
msullivan committed Jul 29, 2020
1 parent cd5c9ab commit 5eccfeb
Showing 1 changed file with 37 additions and 17 deletions.
54 changes: 37 additions & 17 deletions docs/edgeql/overview.rst
Expand Up @@ -188,47 +188,67 @@ A query is evaluated recursively using the following procedure:
.. code-block:: edgeql
SELECT (
User.firstname,
User.friends.firstname,
User.friends.lastname,
Issue.priority.name,
Issue.number,
Status.name
);
In the above query, the longest common prefixes are: ``User.friends``,
``Issue``, and ``Status.name``.
In the above query, the longest common prefixes are: ``User``,
``User.friends``, ``Issue``, and ``Status.name``.

2. Make a *query input list* of all unique set references which appear
directly in the query (including the common path prefixes identified above).
The set references in this list are called *input set references*,
and the sets they represent are called *input sets*.

3. For every empty input set, check if it appears
exclusively as part of an :ref:`ref_eql_fundamentals_optional` argument,
and if so, exclude it from the query input list.

4. Create a set of *input tuples* as a cartesian product of the input sets.
If the query input list is empty, the input tuple set would contain
a single empty input tuple.

5. Iterate over the set of input tuples, and on every iteration:
The set references and path prefixes in this list are called *input
set references*, and the sets they represent are called *input
sets*. Order this list such that an input references come before
any other input set reference for which it is a prefix (sorting
lexicographically works).

3. Compute a set of *input tuples*.

- Begin with a set containing a single empty tuple.
- For each input set reference, we compute a *dependent* Cartesian
product of the input tuple set (``X``) so far and the input set
``Y`` being considered. In this dependent product, we pair each
tuple ``x`` in the input tuple set ``X`` with each element of the
subset of the input set ``Y`` corresponding to the tuple ``x``. (For
example, in the above example, computing the dependent product
of User and User.friends would pair each user with all of their
friends.)

(Mathematically, ``X' = {(x, y) | x ∈ X, y \in f(x)}``, if ``f(x)``
selects the appropriate subset.)

The set produced becomes the new input tuple set and we continue
down the list.
- As a caveat to the above, if an input set appears exclusively as
an :ref:`ref_eql_fundamentals_optional` argument, produce
pairs with a placeholder value ``Missing`` instead of an empty
Cartesian product in the above
set. (Mathematically, this corresponds to having ``f(x) =
{Missing}`` whenever it would otherwise produce an empty set.)

4. Iterate over the set of input tuples, and on every iteration:

- in the query and its subqueries, replace each input set reference with the
corresponding value from the input tuple or an empty set if the value
is missing;
is ``Missing``;

- evaluate the query expression in the order of precedence using
the following rules:

* subqueries are evaluated recursively from step 1;

* a function or an operator is evaluated in a loop over a cartesian
* a function or an operator is evaluated in a loop over a Cartesian
product of its non-aggregate arguments
(empty ``OPTIONAL`` arguments are excluded from the product);
aggregate arguments are passed as a whole set;
the results of the invocations are collected to form a single set.

6. Collect the results of all iterations to obtain the final result set.
5. Collect the results of all iterations to obtain the final result set.


.. _ref_eql_polymorphic_queries:
Expand Down

0 comments on commit 5eccfeb

Please sign in to comment.