From 80573038ed44da6eeb13e85d4f380d8b08b97292 Mon Sep 17 00:00:00 2001 From: Greg Bell Date: Sat, 22 Jul 2017 17:28:48 +1000 Subject: [PATCH 1/3] Add additional detail and clarifications on SELECT - Also the effect of WHERE on result array. --- .../reference/dql-doctrine-query-language.rst | 59 +++++++++++++++---- 1 file changed, 48 insertions(+), 11 deletions(-) diff --git a/docs/en/reference/dql-doctrine-query-language.rst b/docs/en/reference/dql-doctrine-query-language.rst index b0d19e8e0..44ef29483 100644 --- a/docs/en/reference/dql-doctrine-query-language.rst +++ b/docs/en/reference/dql-doctrine-query-language.rst @@ -49,9 +49,12 @@ SELECT queries DQL SELECT clause ~~~~~~~~~~~~~~~~~ -The select clause of a DQL query specifies what appears in the -query result. The composition of all the expressions in the select -clause also influences the nature of the query result. +The SELECT clause of a DQL query specifies what gets hydrated in +the query result. You are always returned usable objects, but any +associated objects not included in the SELECT clause will be +proxies (ie. unhydrated). They get hydrated by Doctrine when +they're read by your code, but that means at least one additional +database access. Here is an example that selects all users with an age > 20: @@ -83,14 +86,48 @@ Lets examine the query: The result of this query would be a list of User objects where all users are older than 20. -The SELECT clause allows to specify both class identification -variables that signal the hydration of a complete entity class or -just fields of the entity using the syntax ``u.name``. Combinations -of both are also allowed and it is possible to wrap both fields and -identification values into aggregation and DQL functions. Numerical -fields can be part of computations using mathematical operations. -See the sub-section on `Functions, Operators, Aggregates`_ for -more information. +The composition of the expressions in the SELECT clause also +influences the nature of the query result. There are three +cases: + +- All objects. For example: + ``SELECT u, p, n FROM Users u...`` + In this case, the result array will be made up of objects of + the type in the FROM clause. In the example above, the query + will return an array of User objects, with associated classes + identify else where in the query as 'p' and 'n' hydrated. + +- All scalars. For example: + ``SELECT u.name, u.address FROM Users u...`` + In this case, the result will be an array of arrays. In the + example above, each element of the result array would be an + array of the scalar name and address values. + + You can select scalars from any entity in the query. + +- Mixed. For example: + ``SELECT u, p.quantity FROM Users u...`` + Here, the result will again be an array of arrays, with each + element being an array made up of a User object and the scalar + value p.quantity. + +Multiple FROM clauses are allowed, which would cause the result +array elements to cycle through the classes included in the +multiple FROM clauses. + +.. note:: + + You cannot select other entities unless you also select the + root of the selection (the first entity in FROM). + + Doctrine tells you you have violated this constraint with the + exception "Cannot select entity through identification + variables without choosing at least one root entity alias." + +It is possible to wrap both fields and identification values into +aggregation and DQL functions. Numerical fields can be part of +computations using mathematical operations. See the sub-section +on `Functions, Operators, Aggregates`_ for more information. Joins ~~~~~ From 624af3df220a409731b31495a9e2c6bdd7cf3ca3 Mon Sep 17 00:00:00 2001 From: Greg Bell Date: Sat, 22 Jul 2017 17:40:56 +1000 Subject: [PATCH 2/3] Add note clarifying WHERE, WITH and HAVING - A per Ocramius' explanation in #6563 --- docs/en/reference/dql-doctrine-query-language.rst | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/docs/en/reference/dql-doctrine-query-language.rst b/docs/en/reference/dql-doctrine-query-language.rst index 44ef29483..035ef611c 100644 --- a/docs/en/reference/dql-doctrine-query-language.rst +++ b/docs/en/reference/dql-doctrine-query-language.rst @@ -356,7 +356,8 @@ article-ids: $query = $em->createQuery('SELECT u.id, a.id as article_id FROM CmsUser u LEFT JOIN u.articles a'); $results = $query->getResult(); // array of user ids and every article_id for each user -Restricting a JOIN clause by additional conditions: +Restricting a JOIN clause by additional conditions specified by +WITH: .. code-block:: php @@ -489,6 +490,17 @@ Joins between entities without associations were not possible until version createQuery('SELECT u FROM User u JOIN Blacklist b WITH u.email = b.email'); +.. note:: + The differences between WHERE, WITH and HAVING clauses may be + confusing. + + - WHERE is applied to the results of an entire query + - WITH is applied to a join as an additional condition. For + arbitrary joins (SELECT f, b FROM Foo f, Bar b WITH f.id = b.id) + the WITH is required, even if it is 1 = 1 + - HAVING is applied to the results of a query after + aggregation (GROUP BY) + Partial Object Syntax ^^^^^^^^^^^^^^^^^^^^^ From 74c83f3cecfba5a8ee537e10d55a095e3e8f5011 Mon Sep 17 00:00:00 2001 From: Greg Bell Date: Fri, 18 Aug 2017 15:20:17 +1000 Subject: [PATCH 3/3] Fix format and content as-per discussion in PR --- .../reference/dql-doctrine-query-language.rst | 81 ++++++++++--------- 1 file changed, 44 insertions(+), 37 deletions(-) diff --git a/docs/en/reference/dql-doctrine-query-language.rst b/docs/en/reference/dql-doctrine-query-language.rst index 035ef611c..1b0d3b013 100644 --- a/docs/en/reference/dql-doctrine-query-language.rst +++ b/docs/en/reference/dql-doctrine-query-language.rst @@ -49,13 +49,6 @@ SELECT queries DQL SELECT clause ~~~~~~~~~~~~~~~~~ -The SELECT clause of a DQL query specifies what gets hydrated in -the query result. You are always returned usable objects, but any -associated objects not included in the SELECT clause will be -proxies (ie. unhydrated). They get hydrated by Doctrine when -they're read by your code, but that means at least one additional -database access. - Here is an example that selects all users with an age > 20: .. code-block:: php @@ -86,30 +79,43 @@ Lets examine the query: The result of this query would be a list of User objects where all users are older than 20. +Result format +~~~~~~~~~~~~~ The composition of the expressions in the SELECT clause also influences the nature of the query result. There are three cases: -- All objects. For example: - ``SELECT u, p, n FROM Users u...`` - In this case, the result array will be made up of objects of - the type in the FROM clause. In the example above, the query - will return an array of User objects, with associated classes - identify else where in the query as 'p' and 'n' hydrated. +**All objects** -- All scalars. For example: - ``SELECT u.name, u.address FROM Users u...`` - In this case, the result will be an array of arrays. In the - example above, each element of the result array would be an - array of the scalar name and address values. +.. code-block:: sql - You can select scalars from any entity in the query. + SELECT u, p, n FROM Users u... + +In this case, the result will be an array of User objects because of +the FROM clause, with children ``p`` and ``n`` hydrated because of +their inclusion in the SELECT clause. + +**All scalars** + +.. code-block:: sql + + SELECT u.name, u.address FROM Users u... + +In this case, the result will be an array of arrays. In the example +above, each element of the result array would be an array of the +scalar name and address values. + +You can select scalars from any entity in the query. + +**Mixed** + +.. code-block:: sql -- Mixed. For example: ``SELECT u, p.quantity FROM Users u...`` - Here, the result will again be an array of arrays, with each - element being an array made up of a User object and the scalar - value p.quantity. + +Here, the result will again be an array of arrays, with each element +being an array made up of a User object and the scalar value +``p.quantity``. Multiple FROM clauses are allowed, which would cause the result array elements to cycle through the classes included in the @@ -118,16 +124,13 @@ multiple FROM clauses. .. note:: You cannot select other entities unless you also select the - root of the selection (the first entity in FROM). + root of the selection (which is the first entity in FROM). - Doctrine tells you you have violated this constraint with the - exception "Cannot select entity through identification - variables without choosing at least one root entity alias." + For example, ``SELECT p,n FROM Users u...`` would be wrong because + ``u`` is not part of the SELECT + + Doctrine throws an exception if you violate this constraint. -It is possible to wrap both fields and identification values into -aggregation and DQL functions. Numerical fields can be part of -computations using mathematical operations. See the sub-section -on `Functions, Operators, Aggregates`_ for more information. Joins ~~~~~ @@ -496,10 +499,11 @@ Joins between entities without associations were not possible until version - WHERE is applied to the results of an entire query - WITH is applied to a join as an additional condition. For - arbitrary joins (SELECT f, b FROM Foo f, Bar b WITH f.id = b.id) - the WITH is required, even if it is 1 = 1 + arbitrary joins (SELECT f, b FROM Foo f, Bar b WITH f.id = b.id) + the WITH is required, even if it is 1 = 1 - HAVING is applied to the results of a query after - aggregation (GROUP BY) + aggregation (GROUP BY) + Partial Object Syntax ^^^^^^^^^^^^^^^^^^^^^ @@ -656,6 +660,9 @@ The same restrictions apply for the reference of related entities. Functions, Operators, Aggregates -------------------------------- +It is possible to wrap both fields and identification values into +aggregation and DQL functions. Numerical fields can be part of +computations using mathematical operations. DQL Functions ~~~~~~~~~~~~~ @@ -1430,11 +1437,11 @@ Given that there are 10 users and corresponding addresses in the database the ex .. note:: Changing the fetch mode during a query mostly makes sense for one-to-one and many-to-one relations. In that case, -   all the necessary IDs are available after the root entity (``user`` in the above example) has been loaded. So, one -   query per association can be executed to fetch all the referred-to entities (``address``). + all the necessary IDs are available after the root entity (``user`` in the above example) has been loaded. So, one + query per association can be executed to fetch all the referred-to entities (``address``). For one-to-many relations, changing the fetch mode to eager will cause to execute one query **for every root entity -   loaded**. This gives no improvement over the ``lazy`` fetch mode which will also initialize the associations on + loaded**. This gives no improvement over the ``lazy`` fetch mode which will also initialize the associations on a one-by-one basis once they are accessed.