diff --git a/.travis.yml b/.travis.yml index e88053559..57b2cb1f6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,6 +20,7 @@ before_script: - if [ "$DEPENDENCIES" != "low" ]; then composer update; fi; - if [ "$DEPENDENCIES" == "low" ]; then composer update --prefer-lowest; fi; - if [[ $PHPSTAN = 1 ]]; then composer require --dev --prefer-stable phpstan/phpstan:^0.7 symfony/console:^3.0; fi + - if [ "$MYSQL_VERSION" == "5.7" ]; then bash ./tests/travis/install-mysql-5.7.sh; fi; - if [[ $DB == "mysql" || $DB == "mariadb" ]]; then mysql -e "CREATE SCHEMA doctrine_tests; GRANT ALL PRIVILEGES ON doctrine_tests.* to travis@'%'"; fi; script: @@ -47,6 +48,13 @@ matrix: - DB=pgsql - PHPSTAN=1 + - php: 7.1 + env: DB=mysql MYSQL_VERSION=5.7 + sudo: required + - php: nightly + env: DB=mysql MYSQL_VERSION=5.7 + sudo: required + allow_failures: - php: nightly diff --git a/composer.json b/composer.json index a4b43de3b..d320b0b4d 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ "ext-pdo": "*", "doctrine/collections": "^1.4", "doctrine/dbal": ">=2.5-dev,<2.7-dev", - "doctrine/instantiator": "~1.0.1", + "doctrine/instantiator": "~1.1", "doctrine/common": "^2.7.1", "doctrine/cache": "~1.6", "doctrine/annotations": "~1.4", diff --git a/lib/Doctrine/ORM/Tools/Pagination/LimitSubqueryOutputWalker.php b/lib/Doctrine/ORM/Tools/Pagination/LimitSubqueryOutputWalker.php index 5d59722ed..034b33b2c 100644 --- a/lib/Doctrine/ORM/Tools/Pagination/LimitSubqueryOutputWalker.php +++ b/lib/Doctrine/ORM/Tools/Pagination/LimitSubqueryOutputWalker.php @@ -43,6 +43,8 @@ use Doctrine\ORM\Query\AST\SelectStatement; */ class LimitSubqueryOutputWalker extends SqlWalker { + private const ORDER_BY_PATH_EXPRESSION = '/(?rebuildOrderByClauseForOuterScope($orderByClause); - - // Build the select distinct statement - $sql = sprintf( - 'SELECT DISTINCT %s FROM (%s) dctrn_result ORDER BY %s', - implode(', ', $sqlIdentifier), - $innerSql, - implode(', ', $orderBy) + // now only select distinct identifier + return \sprintf( + 'SELECT DISTINCT %s FROM (%s) dctrn_result', + \implode(', ', $sqlIdentifier), + $this->recreateInnerSql($orderByClause, $sqlIdentifier, $innerSql) ); - - return $sql; } /** - * Generates a new order by clause that works in the scope of a select query wrapping the original + * Generates a new SQL statement for the inner query to keep the correct sorting * * @param OrderByClause $orderByClause - * @return array + * @param array $identifiers + * @param string $innerSql + * + * @return string */ - private function rebuildOrderByClauseForOuterScope(OrderByClause $orderByClause) - { - $dqlAliasToSqlTableAliasMap - = $searchPatterns - = $replacements - = $dqlAliasToClassMap - = $selectListAdditions - = $orderByItems - = []; + private function recreateInnerSql( + OrderByClause $orderByClause, + array $identifiers, + string $innerSql + ) : string { + [$searchPatterns, $replacements] = $this->generateSqlAliasReplacements(); - // Generate DQL alias -> SQL table alias mapping - foreach(array_keys($this->rsm->aliasMap) as $dqlAlias) { - $dqlAliasToClassMap[$dqlAlias] = $class = $this->queryComponents[$dqlAlias]['metadata']; - $dqlAliasToSqlTableAliasMap[$dqlAlias] = $this->getSQLTableAlias($class->getTableName(), $dqlAlias); + $orderByItems = []; + + foreach ($orderByClause->orderByItems as $orderByItem) { + // Walk order by item to get string representation of it and + // replace path expressions in the order by clause with their column alias + $orderByItemString = \preg_replace( + $searchPatterns, + $replacements, + $this->walkOrderByItem($orderByItem) + ); + + $orderByItems[] = $orderByItemString; + $identifier = \substr($orderByItemString, 0, \strrpos($orderByItemString, ' ')); + + if (! \in_array($identifier, $identifiers, true)) { + $identifiers[] = $identifier; + } } - // Pattern to find table path expressions in the order by clause - $fieldSearchPattern = '/(? SQL table alias mapping + foreach (\array_keys($this->rsm->aliasMap) as $dqlAlias) { + $metadataList[$dqlAlias] = $class = $this->queryComponents[$dqlAlias]['metadata']; + $aliasMap[$dqlAlias] = $this->getSQLTableAlias($class->getTableName(), $dqlAlias); + } // Generate search patterns for each field's path expression in the order by clause - foreach($this->rsm->fieldMappings as $fieldAlias => $fieldName) { + foreach ($this->rsm->fieldMappings as $fieldAlias => $fieldName) { $dqlAliasForFieldAlias = $this->rsm->columnOwnerMap[$fieldAlias]; - $class = $dqlAliasToClassMap[$dqlAliasForFieldAlias]; + $class = $metadataList[$dqlAliasForFieldAlias]; - // If the field is from a joined child table, we won't be ordering - // on it. - if (!isset($class->fieldMappings[$fieldName])) { + // If the field is from a joined child table, we won't be ordering on it. + if (! isset($class->fieldMappings[$fieldName])) { continue; } @@ -425,37 +453,29 @@ class LimitSubqueryOutputWalker extends SqlWalker // Get the proper column name as will appear in the select list $columnName = $this->quoteStrategy->getColumnName( $fieldName, - $dqlAliasToClassMap[$dqlAliasForFieldAlias], + $metadataList[$dqlAliasForFieldAlias], $this->em->getConnection()->getDatabasePlatform() ); // Get the SQL table alias for the entity and field - $sqlTableAliasForFieldAlias = $dqlAliasToSqlTableAliasMap[$dqlAliasForFieldAlias]; + $sqlTableAliasForFieldAlias = $aliasMap[$dqlAliasForFieldAlias]; + if (isset($fieldMapping['declared']) && $fieldMapping['declared'] !== $class->name) { // Field was declared in a parent class, so we need to get the proper SQL table alias // for the joined parent table. $otherClassMetadata = $this->em->getClassMetadata($fieldMapping['declared']); - if (!$otherClassMetadata->isMappedSuperclass) { + + if (! $otherClassMetadata->isMappedSuperclass) { $sqlTableAliasForFieldAlias = $this->getSQLTableAlias($otherClassMetadata->getTableName(), $dqlAliasForFieldAlias); } } - // Compose search/replace patterns - $searchPatterns[] = sprintf($fieldSearchPattern, $sqlTableAliasForFieldAlias, $columnName); - $replacements[] = $fieldAlias; + // Compose search and replace patterns + $searchPatterns[] = \sprintf(self::ORDER_BY_PATH_EXPRESSION, $sqlTableAliasForFieldAlias, $columnName); + $replacements[] = $fieldAlias; } - foreach($orderByClause->orderByItems as $orderByItem) { - // Walk order by item to get string representation of it - $orderByItemString = $this->walkOrderByItem($orderByItem); - - // Replace path expressions in the order by clause with their column alias - $orderByItemString = preg_replace($searchPatterns, $replacements, $orderByItemString); - - $orderByItems[] = $orderByItemString; - } - - return $orderByItems; + return [$searchPatterns, $replacements]; } /** diff --git a/tests/Doctrine/Tests/ORM/Tools/Pagination/LimitSubqueryOutputWalkerTest.php b/tests/Doctrine/Tests/ORM/Tools/Pagination/LimitSubqueryOutputWalkerTest.php index 7e65ab7bc..39ee1360d 100644 --- a/tests/Doctrine/Tests/ORM/Tools/Pagination/LimitSubqueryOutputWalkerTest.php +++ b/tests/Doctrine/Tests/ORM/Tools/Pagination/LimitSubqueryOutputWalkerTest.php @@ -8,9 +8,9 @@ use Doctrine\DBAL\Platforms\PostgreSqlPlatform; use Doctrine\ORM\Query; use Doctrine\ORM\Tools\Pagination\LimitSubqueryOutputWalker; -class LimitSubqueryOutputWalkerTest extends PaginationTestCase +final class LimitSubqueryOutputWalkerTest extends PaginationTestCase { - public function testLimitSubquery() + public function testLimitSubquery() : void { $query = $this->entityManager->createQuery( 'SELECT p, c, a FROM Doctrine\Tests\ORM\Tools\Pagination\MyBlogPost p JOIN p.category c JOIN p.author a'); @@ -18,12 +18,12 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase $limitQuery = clone $query; $limitQuery->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, LimitSubqueryOutputWalker::class); - $this->assertEquals( + self::assertSame( "SELECT DISTINCT id_0 FROM (SELECT m0_.id AS id_0, m0_.title AS title_1, c1_.id AS id_2, a2_.id AS id_3, a2_.name AS name_4, m0_.author_id AS author_id_5, m0_.category_id AS category_id_6 FROM MyBlogPost m0_ INNER JOIN Category c1_ ON m0_.category_id = c1_.id INNER JOIN Author a2_ ON m0_.author_id = a2_.id) dctrn_result", $limitQuery->getSQL() ); } - public function testLimitSubqueryWithSortPg() + public function testLimitSubqueryWithSortPg() : void { $odp = $this->entityManager->getConnection()->getDatabasePlatform(); $this->entityManager->getConnection()->setDatabasePlatform(new PostgreSqlPlatform); @@ -33,14 +33,14 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase $limitQuery = clone $query; $limitQuery->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, LimitSubqueryOutputWalker::class); - $this->assertEquals( + self::assertSame( "SELECT DISTINCT id_0, MIN(sclr_5) AS dctrn_minrownum FROM (SELECT m0_.id AS id_0, m0_.title AS title_1, c1_.id AS id_2, a2_.id AS id_3, a2_.name AS name_4, ROW_NUMBER() OVER(ORDER BY m0_.title ASC) AS sclr_5, m0_.author_id AS author_id_6, m0_.category_id AS category_id_7 FROM MyBlogPost m0_ INNER JOIN Category c1_ ON m0_.category_id = c1_.id INNER JOIN Author a2_ ON m0_.author_id = a2_.id) dctrn_result GROUP BY id_0 ORDER BY dctrn_minrownum ASC", $limitQuery->getSQL() ); $this->entityManager->getConnection()->setDatabasePlatform($odp); } - public function testLimitSubqueryWithScalarSortPg() + public function testLimitSubqueryWithScalarSortPg() : void { $odp = $this->entityManager->getConnection()->getDatabasePlatform(); $this->entityManager->getConnection()->setDatabasePlatform(new PostgreSqlPlatform); @@ -51,7 +51,7 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase $limitQuery = clone $query; $limitQuery->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, LimitSubqueryOutputWalker::class); - $this->assertEquals( + self::assertSame( "SELECT DISTINCT id_1, MIN(sclr_3) AS dctrn_minrownum FROM (SELECT COUNT(g0_.id) AS sclr_0, u1_.id AS id_1, g0_.id AS id_2, ROW_NUMBER() OVER(ORDER BY COUNT(g0_.id) ASC) AS sclr_3 FROM User u1_ INNER JOIN user_group u2_ ON u1_.id = u2_.user_id INNER JOIN groups g0_ ON g0_.id = u2_.group_id) dctrn_result GROUP BY id_1 ORDER BY dctrn_minrownum ASC", $limitQuery->getSQL() ); @@ -59,7 +59,7 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase $this->entityManager->getConnection()->setDatabasePlatform($odp); } - public function testLimitSubqueryWithMixedSortPg() + public function testLimitSubqueryWithMixedSortPg() : void { $odp = $this->entityManager->getConnection()->getDatabasePlatform(); $this->entityManager->getConnection()->setDatabasePlatform(new PostgreSqlPlatform); @@ -70,7 +70,7 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase $limitQuery = clone $query; $limitQuery->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, LimitSubqueryOutputWalker::class); - $this->assertEquals( + self::assertSame( "SELECT DISTINCT id_1, MIN(sclr_3) AS dctrn_minrownum FROM (SELECT COUNT(g0_.id) AS sclr_0, u1_.id AS id_1, g0_.id AS id_2, ROW_NUMBER() OVER(ORDER BY COUNT(g0_.id) ASC, u1_.id DESC) AS sclr_3 FROM User u1_ INNER JOIN user_group u2_ ON u1_.id = u2_.user_id INNER JOIN groups g0_ ON g0_.id = u2_.group_id) dctrn_result GROUP BY id_1 ORDER BY dctrn_minrownum ASC", $limitQuery->getSQL() ); @@ -78,7 +78,7 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase $this->entityManager->getConnection()->setDatabasePlatform($odp); } - public function testLimitSubqueryWithHiddenScalarSortPg() + public function testLimitSubqueryWithHiddenScalarSortPg() : void { $odp = $this->entityManager->getConnection()->getDatabasePlatform(); $this->entityManager->getConnection()->setDatabasePlatform(new PostgreSqlPlatform); @@ -89,7 +89,7 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase $limitQuery = clone $query; $limitQuery->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, LimitSubqueryOutputWalker::class); - $this->assertEquals( + self::assertSame( "SELECT DISTINCT id_1, MIN(sclr_3) AS dctrn_minrownum FROM (SELECT COUNT(g0_.id) AS sclr_0, u1_.id AS id_1, g0_.id AS id_2, ROW_NUMBER() OVER(ORDER BY COUNT(g0_.id) ASC, u1_.id DESC) AS sclr_3 FROM User u1_ INNER JOIN user_group u2_ ON u1_.id = u2_.user_id INNER JOIN groups g0_ ON g0_.id = u2_.group_id) dctrn_result GROUP BY id_1 ORDER BY dctrn_minrownum ASC", $limitQuery->getSQL() ); @@ -97,7 +97,7 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase $this->entityManager->getConnection()->setDatabasePlatform($odp); } - public function testLimitSubqueryPg() + public function testLimitSubqueryPg() : void { $odp = $this->entityManager->getConnection()->getDatabasePlatform(); $this->entityManager->getConnection()->setDatabasePlatform(new PostgreSqlPlatform); @@ -107,7 +107,7 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase $this->entityManager->getConnection()->setDatabasePlatform($odp); } - public function testLimitSubqueryWithSortOracle() + public function testLimitSubqueryWithSortOracle() : void { $odp = $this->entityManager->getConnection()->getDatabasePlatform(); $this->entityManager->getConnection()->setDatabasePlatform(new OraclePlatform); @@ -118,14 +118,14 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase $limitQuery = clone $query; $limitQuery->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, LimitSubqueryOutputWalker::class); - $this->assertEquals( + self::assertSame( "SELECT DISTINCT ID_0, MIN(SCLR_5) AS dctrn_minrownum FROM (SELECT m0_.id AS ID_0, m0_.title AS TITLE_1, c1_.id AS ID_2, a2_.id AS ID_3, a2_.name AS NAME_4, ROW_NUMBER() OVER(ORDER BY m0_.title ASC) AS SCLR_5, m0_.author_id AS AUTHOR_ID_6, m0_.category_id AS CATEGORY_ID_7 FROM MyBlogPost m0_ INNER JOIN Category c1_ ON m0_.category_id = c1_.id INNER JOIN Author a2_ ON m0_.author_id = a2_.id) dctrn_result GROUP BY ID_0 ORDER BY dctrn_minrownum ASC", $limitQuery->getSQL() ); $this->entityManager->getConnection()->setDatabasePlatform($odp); } - public function testLimitSubqueryWithScalarSortOracle() + public function testLimitSubqueryWithScalarSortOracle() : void { $odp = $this->entityManager->getConnection()->getDatabasePlatform(); $this->entityManager->getConnection()->setDatabasePlatform(new OraclePlatform); @@ -137,7 +137,7 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase $limitQuery = clone $query; $limitQuery->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, LimitSubqueryOutputWalker::class); - $this->assertEquals( + self::assertSame( "SELECT DISTINCT ID_1, MIN(SCLR_3) AS dctrn_minrownum FROM (SELECT COUNT(g0_.id) AS SCLR_0, u1_.id AS ID_1, g0_.id AS ID_2, ROW_NUMBER() OVER(ORDER BY COUNT(g0_.id) ASC) AS SCLR_3 FROM User u1_ INNER JOIN user_group u2_ ON u1_.id = u2_.user_id INNER JOIN groups g0_ ON g0_.id = u2_.group_id) dctrn_result GROUP BY ID_1 ORDER BY dctrn_minrownum ASC", $limitQuery->getSQL() ); @@ -145,7 +145,7 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase $this->entityManager->getConnection()->setDatabasePlatform($odp); } - public function testLimitSubqueryWithMixedSortOracle() + public function testLimitSubqueryWithMixedSortOracle() : void { $odp = $this->entityManager->getConnection()->getDatabasePlatform(); $this->entityManager->getConnection()->setDatabasePlatform(new OraclePlatform); @@ -157,7 +157,7 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase $limitQuery = clone $query; $limitQuery->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, LimitSubqueryOutputWalker::class); - $this->assertEquals( + self::assertSame( "SELECT DISTINCT ID_1, MIN(SCLR_3) AS dctrn_minrownum FROM (SELECT COUNT(g0_.id) AS SCLR_0, u1_.id AS ID_1, g0_.id AS ID_2, ROW_NUMBER() OVER(ORDER BY COUNT(g0_.id) ASC, u1_.id DESC) AS SCLR_3 FROM User u1_ INNER JOIN user_group u2_ ON u1_.id = u2_.user_id INNER JOIN groups g0_ ON g0_.id = u2_.group_id) dctrn_result GROUP BY ID_1 ORDER BY dctrn_minrownum ASC", $limitQuery->getSQL() ); @@ -165,7 +165,7 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase $this->entityManager->getConnection()->setDatabasePlatform($odp); } - public function testLimitSubqueryOracle() + public function testLimitSubqueryOracle() : void { $odp = $this->entityManager->getConnection()->getDatabasePlatform(); $this->entityManager->getConnection()->setDatabasePlatform(new OraclePlatform); @@ -176,21 +176,21 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase $limitQuery = clone $query; $limitQuery->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, LimitSubqueryOutputWalker::class); - $this->assertEquals( + self::assertSame( "SELECT DISTINCT ID_0 FROM (SELECT m0_.id AS ID_0, m0_.title AS TITLE_1, c1_.id AS ID_2, a2_.id AS ID_3, a2_.name AS NAME_4, m0_.author_id AS AUTHOR_ID_5, m0_.category_id AS CATEGORY_ID_6 FROM MyBlogPost m0_ INNER JOIN Category c1_ ON m0_.category_id = c1_.id INNER JOIN Author a2_ ON m0_.author_id = a2_.id) dctrn_result", $limitQuery->getSQL() ); $this->entityManager->getConnection()->setDatabasePlatform($odp); } - public function testCountQueryMixedResultsWithName() + public function testCountQueryMixedResultsWithName() : void { $query = $this->entityManager->createQuery( 'SELECT a, sum(a.name) as foo FROM Doctrine\Tests\ORM\Tools\Pagination\Author a'); $limitQuery = clone $query; $limitQuery->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, LimitSubqueryOutputWalker::class); - $this->assertEquals( + self::assertSame( "SELECT DISTINCT id_0 FROM (SELECT a0_.id AS id_0, a0_.name AS name_1, sum(a0_.name) AS sclr_2 FROM Author a0_) dctrn_result", $limitQuery->getSQL() ); } @@ -198,7 +198,7 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase /** * @group DDC-3336 */ - public function testCountQueryWithArithmeticOrderByCondition() + public function testCountQueryWithArithmeticOrderByCondition() : void { $query = $this->entityManager->createQuery( 'SELECT a FROM Doctrine\Tests\ORM\Tools\Pagination\Author a ORDER BY (1 - 1000) * 1 DESC' @@ -208,12 +208,12 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase $query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, LimitSubqueryOutputWalker::class); $this->assertSame( - 'SELECT DISTINCT id_0 FROM (SELECT a0_.id AS id_0, a0_.name AS name_1 FROM Author a0_) dctrn_result ORDER BY (1 - 1000) * 1 DESC', + 'SELECT DISTINCT id_0 FROM (SELECT DISTINCT id_0, (1 - 1000) * 1 FROM (SELECT a0_.id AS id_0, a0_.name AS name_1 FROM Author a0_) dctrn_result_inner ORDER BY (1 - 1000) * 1 DESC) dctrn_result', $query->getSQL() ); } - public function testCountQueryWithComplexScalarOrderByItem() + public function testCountQueryWithComplexScalarOrderByItem() : void { $query = $this->entityManager->createQuery( 'SELECT a FROM Doctrine\Tests\ORM\Tools\Pagination\Avatar a ORDER BY a.image_height * a.image_width DESC' @@ -223,12 +223,12 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase $query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, LimitSubqueryOutputWalker::class); $this->assertSame( - 'SELECT DISTINCT id_0 FROM (SELECT a0_.id AS id_0, a0_.image AS image_1, a0_.image_height AS image_height_2, a0_.image_width AS image_width_3, a0_.image_alt_desc AS image_alt_desc_4, a0_.user_id AS user_id_5 FROM Avatar a0_) dctrn_result ORDER BY image_height_2 * image_width_3 DESC', + 'SELECT DISTINCT id_0 FROM (SELECT DISTINCT id_0, image_height_2 * image_width_3 FROM (SELECT a0_.id AS id_0, a0_.image AS image_1, a0_.image_height AS image_height_2, a0_.image_width AS image_width_3, a0_.image_alt_desc AS image_alt_desc_4, a0_.user_id AS user_id_5 FROM Avatar a0_) dctrn_result_inner ORDER BY image_height_2 * image_width_3 DESC) dctrn_result', $query->getSQL() ); } - public function testCountQueryWithComplexScalarOrderByItemJoined() + public function testCountQueryWithComplexScalarOrderByItemJoined() : void { $query = $this->entityManager->createQuery( 'SELECT u FROM Doctrine\Tests\ORM\Tools\Pagination\User u JOIN u.avatar a ORDER BY a.image_height * a.image_width DESC' @@ -238,12 +238,12 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase $query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, LimitSubqueryOutputWalker::class); $this->assertSame( - 'SELECT DISTINCT id_0 FROM (SELECT u0_.id AS id_0, a1_.image_height AS image_height_1, a1_.image_width AS image_width_2, a1_.user_id AS user_id_3 FROM User u0_ INNER JOIN Avatar a1_ ON u0_.id = a1_.user_id) dctrn_result ORDER BY image_height_1 * image_width_2 DESC', + 'SELECT DISTINCT id_0 FROM (SELECT DISTINCT id_0, image_height_1 * image_width_2 FROM (SELECT u0_.id AS id_0, a1_.image_height AS image_height_1, a1_.image_width AS image_width_2, a1_.user_id AS user_id_3 FROM User u0_ INNER JOIN Avatar a1_ ON u0_.id = a1_.user_id) dctrn_result_inner ORDER BY image_height_1 * image_width_2 DESC) dctrn_result', $query->getSQL() ); } - public function testCountQueryWithComplexScalarOrderByItemJoinedWithPartial() + public function testCountQueryWithComplexScalarOrderByItemJoinedWithPartial() : void { $query = $this->entityManager->createQuery( 'SELECT u, partial a.{id, image_alt_desc} FROM Doctrine\Tests\ORM\Tools\Pagination\User u JOIN u.avatar a ORDER BY a.image_height * a.image_width DESC' @@ -253,12 +253,12 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase $query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, LimitSubqueryOutputWalker::class); $this->assertSame( - 'SELECT DISTINCT id_0 FROM (SELECT u0_.id AS id_0, a1_.id AS id_1, a1_.image_alt_desc AS image_alt_desc_2, a1_.image_height AS image_height_3, a1_.image_width AS image_width_4, a1_.user_id AS user_id_5 FROM User u0_ INNER JOIN Avatar a1_ ON u0_.id = a1_.user_id) dctrn_result ORDER BY image_height_3 * image_width_4 DESC', + 'SELECT DISTINCT id_0 FROM (SELECT DISTINCT id_0, image_height_3 * image_width_4 FROM (SELECT u0_.id AS id_0, a1_.id AS id_1, a1_.image_alt_desc AS image_alt_desc_2, a1_.image_height AS image_height_3, a1_.image_width AS image_width_4, a1_.user_id AS user_id_5 FROM User u0_ INNER JOIN Avatar a1_ ON u0_.id = a1_.user_id) dctrn_result_inner ORDER BY image_height_3 * image_width_4 DESC) dctrn_result', $query->getSQL() ); } - public function testCountQueryWithComplexScalarOrderByItemOracle() + public function testCountQueryWithComplexScalarOrderByItemOracle() : void { $query = $this->entityManager->createQuery( 'SELECT a FROM Doctrine\Tests\ORM\Tools\Pagination\Avatar a ORDER BY a.image_height * a.image_width DESC' @@ -276,7 +276,7 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase /** * @group DDC-3434 */ - public function testLimitSubqueryWithHiddenSelectionInOrderBy() + public function testLimitSubqueryWithHiddenSelectionInOrderBy() : void { $query = $this->entityManager->createQuery( 'SELECT a, a.name AS HIDDEN ord FROM Doctrine\Tests\ORM\Tools\Pagination\Author a ORDER BY ord DESC' @@ -284,13 +284,13 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase $query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, LimitSubqueryOutputWalker::class); - $this->assertEquals( - 'SELECT DISTINCT id_0 FROM (SELECT a0_.id AS id_0, a0_.name AS name_1, a0_.name AS name_2 FROM Author a0_) dctrn_result ORDER BY name_2 DESC', + self::assertSame( + 'SELECT DISTINCT id_0 FROM (SELECT DISTINCT id_0, name_2 FROM (SELECT a0_.id AS id_0, a0_.name AS name_1, a0_.name AS name_2 FROM Author a0_) dctrn_result_inner ORDER BY name_2 DESC) dctrn_result', $query->getSQL() ); } - public function testLimitSubqueryWithColumnWithSortDirectionInName() + public function testLimitSubqueryWithColumnWithSortDirectionInName() : void { $query = $this->entityManager->createQuery( 'SELECT a FROM Doctrine\Tests\ORM\Tools\Pagination\Avatar a ORDER BY a.image_alt_desc DESC' @@ -300,12 +300,12 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase $query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, LimitSubqueryOutputWalker::class); $this->assertSame( - 'SELECT DISTINCT id_0 FROM (SELECT a0_.id AS id_0, a0_.image AS image_1, a0_.image_height AS image_height_2, a0_.image_width AS image_width_3, a0_.image_alt_desc AS image_alt_desc_4, a0_.user_id AS user_id_5 FROM Avatar a0_) dctrn_result ORDER BY image_alt_desc_4 DESC', + 'SELECT DISTINCT id_0 FROM (SELECT DISTINCT id_0, image_alt_desc_4 FROM (SELECT a0_.id AS id_0, a0_.image AS image_1, a0_.image_height AS image_height_2, a0_.image_width AS image_width_3, a0_.image_alt_desc AS image_alt_desc_4, a0_.user_id AS user_id_5 FROM Avatar a0_) dctrn_result_inner ORDER BY image_alt_desc_4 DESC) dctrn_result', $query->getSQL() ); } - public function testLimitSubqueryWithOrderByInnerJoined() + public function testLimitSubqueryWithOrderByInnerJoined() : void { $query = $this->entityManager->createQuery( 'SELECT b FROM Doctrine\Tests\ORM\Tools\Pagination\BlogPost b JOIN b.author a ORDER BY a.name ASC' @@ -313,13 +313,13 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase $query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, LimitSubqueryOutputWalker::class); - $this->assertEquals( - 'SELECT DISTINCT id_0 FROM (SELECT b0_.id AS id_0, a1_.name AS name_1, b0_.author_id AS author_id_2, b0_.category_id AS category_id_3 FROM BlogPost b0_ INNER JOIN Author a1_ ON b0_.author_id = a1_.id) dctrn_result ORDER BY name_1 ASC', + self::assertSame( + 'SELECT DISTINCT id_0 FROM (SELECT DISTINCT id_0, name_1 FROM (SELECT b0_.id AS id_0, a1_.name AS name_1, b0_.author_id AS author_id_2, b0_.category_id AS category_id_3 FROM BlogPost b0_ INNER JOIN Author a1_ ON b0_.author_id = a1_.id) dctrn_result_inner ORDER BY name_1 ASC) dctrn_result', $query->getSQL() ); } - public function testLimitSubqueryWithOrderByAndSubSelectInWhereClauseMySql() + public function testLimitSubqueryWithOrderByAndSubSelectInWhereClauseMySql() : void { $this->entityManager->getConnection()->setDatabasePlatform(new MySqlPlatform()); $query = $this->entityManager->createQuery( @@ -329,13 +329,13 @@ ORDER BY b.id DESC' ); $query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, LimitSubqueryOutputWalker::class); - $this->assertEquals( - 'SELECT DISTINCT id_0 FROM (SELECT b0_.id AS id_0, b0_.author_id AS author_id_1, b0_.category_id AS category_id_2 FROM BlogPost b0_ WHERE ((SELECT COUNT(b1_.id) AS sclr_3 FROM BlogPost b1_) = 1)) dctrn_result ORDER BY id_0 DESC', + self::assertSame( + 'SELECT DISTINCT id_0 FROM (SELECT DISTINCT id_0 FROM (SELECT b0_.id AS id_0, b0_.author_id AS author_id_1, b0_.category_id AS category_id_2 FROM BlogPost b0_ WHERE ((SELECT COUNT(b1_.id) AS sclr_3 FROM BlogPost b1_) = 1)) dctrn_result_inner ORDER BY id_0 DESC) dctrn_result', $query->getSQL() ); } - public function testLimitSubqueryWithOrderByAndSubSelectInWhereClausePgSql() + public function testLimitSubqueryWithOrderByAndSubSelectInWhereClausePgSql() : void { $this->entityManager->getConnection()->setDatabasePlatform(new PostgreSqlPlatform()); $query = $this->entityManager->createQuery( @@ -345,7 +345,7 @@ ORDER BY b.id DESC' ); $query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, LimitSubqueryOutputWalker::class); - $this->assertEquals( + self::assertSame( 'SELECT DISTINCT id_0, MIN(sclr_1) AS dctrn_minrownum FROM (SELECT b0_.id AS id_0, ROW_NUMBER() OVER(ORDER BY b0_.id DESC) AS sclr_1, b0_.author_id AS author_id_2, b0_.category_id AS category_id_3 FROM BlogPost b0_ WHERE ((SELECT COUNT(b1_.id) AS sclr_4 FROM BlogPost b1_) = 1)) dctrn_result GROUP BY id_0 ORDER BY dctrn_minrownum ASC', $query->getSQL() ); @@ -354,7 +354,7 @@ ORDER BY b.id DESC' /** * This tests ordering by property that has the 'declared' field. */ - public function testLimitSubqueryOrderByFieldFromMappedSuperclass() + public function testLimitSubqueryOrderByFieldFromMappedSuperclass() : void { $this->entityManager->getConnection()->setDatabasePlatform(new MySqlPlatform()); @@ -364,8 +364,8 @@ ORDER BY b.id DESC' ); $query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, LimitSubqueryOutputWalker::class); - $this->assertEquals( - 'SELECT DISTINCT id_0 FROM (SELECT b0_.id AS id_0, b0_.name AS name_1 FROM Banner b0_) dctrn_result ORDER BY id_0 DESC', + self::assertSame( + 'SELECT DISTINCT id_0 FROM (SELECT DISTINCT id_0 FROM (SELECT b0_.id AS id_0, b0_.name AS name_1 FROM Banner b0_) dctrn_result_inner ORDER BY id_0 DESC) dctrn_result', $query->getSQL() ); } @@ -373,7 +373,7 @@ ORDER BY b.id DESC' /** * Tests order by on a subselect expression (mysql). */ - public function testLimitSubqueryOrderBySubSelectOrderByExpression() + public function testLimitSubqueryOrderBySubSelectOrderByExpression() : void { $this->entityManager->getConnection()->setDatabasePlatform(new MySqlPlatform()); @@ -389,8 +389,8 @@ ORDER BY b.id DESC' ); $query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, LimitSubqueryOutputWalker::class); - $this->assertEquals( - 'SELECT DISTINCT id_0 FROM (SELECT a0_.id AS id_0, a0_.name AS name_1, (SELECT MIN(m1_.title) AS sclr_3 FROM MyBlogPost m1_ WHERE m1_.author_id = a0_.id) AS sclr_2 FROM Author a0_) dctrn_result ORDER BY sclr_2 DESC', + self::assertSame( + 'SELECT DISTINCT id_0 FROM (SELECT DISTINCT id_0, sclr_2 FROM (SELECT a0_.id AS id_0, a0_.name AS name_1, (SELECT MIN(m1_.title) AS sclr_3 FROM MyBlogPost m1_ WHERE m1_.author_id = a0_.id) AS sclr_2 FROM Author a0_) dctrn_result_inner ORDER BY sclr_2 DESC) dctrn_result', $query->getSQL() ); } @@ -398,7 +398,7 @@ ORDER BY b.id DESC' /** * Tests order by on a subselect expression invoking RowNumberOverFunction (postgres). */ - public function testLimitSubqueryOrderBySubSelectOrderByExpressionPg() + public function testLimitSubqueryOrderBySubSelectOrderByExpressionPg() : void { $this->entityManager->getConnection()->setDatabasePlatform(new PostgreSqlPlatform()); @@ -414,7 +414,7 @@ ORDER BY b.id DESC' ); $query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, LimitSubqueryOutputWalker::class); - $this->assertEquals( + self::assertSame( 'SELECT DISTINCT id_0, MIN(sclr_4) AS dctrn_minrownum FROM (SELECT a0_.id AS id_0, a0_.name AS name_1, (SELECT MIN(m1_.title) AS sclr_3 FROM MyBlogPost m1_ WHERE m1_.author_id = a0_.id) AS sclr_2, ROW_NUMBER() OVER(ORDER BY (SELECT MIN(m1_.title) AS sclr_5 FROM MyBlogPost m1_ WHERE m1_.author_id = a0_.id) DESC) AS sclr_4 FROM Author a0_) dctrn_result GROUP BY id_0 ORDER BY dctrn_minrownum ASC', $query->getSQL() ); @@ -423,7 +423,7 @@ ORDER BY b.id DESC' /** * Tests order by on a subselect expression invoking RowNumberOverFunction (oracle). */ - public function testLimitSubqueryOrderBySubSelectOrderByExpressionOracle() + public function testLimitSubqueryOrderBySubSelectOrderByExpressionOracle() : void { $this->entityManager->getConnection()->setDatabasePlatform(new OraclePlatform()); @@ -439,7 +439,7 @@ ORDER BY b.id DESC' ); $query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, LimitSubqueryOutputWalker::class); - $this->assertEquals( + self::assertSame( 'SELECT DISTINCT ID_0, MIN(SCLR_4) AS dctrn_minrownum FROM (SELECT a0_.id AS ID_0, a0_.name AS NAME_1, (SELECT MIN(m1_.title) AS SCLR_3 FROM MyBlogPost m1_ WHERE m1_.author_id = a0_.id) AS SCLR_2, ROW_NUMBER() OVER(ORDER BY (SELECT MIN(m1_.title) AS SCLR_5 FROM MyBlogPost m1_ WHERE m1_.author_id = a0_.id) DESC) AS SCLR_4 FROM Author a0_) dctrn_result GROUP BY ID_0 ORDER BY dctrn_minrownum ASC', $query->getSQL() ); diff --git a/tests/travis/install-mysql-5.7.sh b/tests/travis/install-mysql-5.7.sh new file mode 100644 index 000000000..66b0d1ecf --- /dev/null +++ b/tests/travis/install-mysql-5.7.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +set -ex + +echo "Installing MySQL 5.7..." + +sudo service mysql stop +sudo apt-get remove "^mysql.*" +sudo apt-get autoremove +sudo apt-get autoclean +echo mysql-apt-config mysql-apt-config/select-server select mysql-5.7 | sudo debconf-set-selections +wget http://dev.mysql.com/get/mysql-apt-config_0.8.6-1_all.deb +sudo DEBIAN_FRONTEND=noninteractive dpkg -i mysql-apt-config_0.8.6-1_all.deb +sudo rm -rf /var/lib/apt/lists/* +sudo apt-get clean +sudo apt-get update -q +sudo apt-get install -q -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" mysql-server libmysqlclient-dev +sudo mysql_upgrade + +echo "Restart mysql..." +sudo mysql -e "use mysql; update user set authentication_string=PASSWORD('') where User='root'; update user set plugin='mysql_native_password';FLUSH PRIVILEGES;" +