Skip to content

Commit

Permalink
Fix Hidden fields triggering error when using getSingleScalarResult() (
Browse files Browse the repository at this point in the history
…#8340)

* Fix Hidden fields triggering error when using getSingleScalarResult()

Fixes #4257
HIDDEN fields was causing the "unicity" check to fail (NonUniqueResultException), because we was counting raw data instead of gathered row data.

* Fix Coding Standards (7.4)

* Fix Coding Standards (7.4) #2

* Fix Coding Standards (7.4) - Fix whitespaces

* Fix Coding Standards (7.4) - Fix whitespaces in tests

* Fix Coding Standards (7.4) - Fix more things

* Refactor tests into separate methods

* Fix Coding Standards (7.4) - Equals sign not aligned with surrounding assignments
  • Loading branch information
Mediagone authored and greg0ire committed Dec 1, 2021
1 parent 0d8ed07 commit 498604f
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 48 deletions.
6 changes: 3 additions & 3 deletions lib/Doctrine/ORM/Internal/Hydration/SingleScalarHydrator.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ protected function hydrateAllData()
throw new NonUniqueResultException('The query returned multiple rows. Change the query or use a different result function like getScalarResult().');
}

if (count($data[key($data)]) > 1) {
$result = $this->gatherScalarRowData($data[key($data)]);

if (count($result) > 1) {
throw new NonUniqueResultException('The query returned a row containing multiple columns. Change the query or use a different result function like getScalarResult().');
}

$result = $this->gatherScalarRowData($data[key($data)]);

return array_shift($result);
}
}
4 changes: 2 additions & 2 deletions tests/Doctrine/Tests/ORM/Functional/Ticket/GH7512Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

class GH7512Test extends OrmFunctionalTestCase
{
protected function setUp() : void
protected function setUp(): void
{
parent::setUp();

Expand All @@ -32,7 +32,7 @@ protected function setUp() : void
$this->_em->clear();
}

public function testFindEntityByAssociationPropertyJoinedChildWithClearMetadata() : void
public function testFindEntityByAssociationPropertyJoinedChildWithClearMetadata(): void
{
// unset metadata for entity B as though it hasn't been touched yet in application lifecycle.
$this->_em->getMetadataFactory()->setMetadataFor(GH7512EntityB::class, null);
Expand Down
162 changes: 119 additions & 43 deletions tests/Doctrine/Tests/ORM/Hydration/SingleScalarHydratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,51 +14,127 @@

class SingleScalarHydratorTest extends HydrationTestCase
{
/** Result set provider for the HYDRATE_SINGLE_SCALAR tests */
public static function singleScalarResultSetProvider(): array
public static function validResultSetProvider()
{
return [
// valid
'valid' => [
'name' => 'result1',
'resultSet' => [
['u__name' => 'romanb'],
// SELECT u.name FROM CmsUser u WHERE u.id = 1
yield [
[
['u__name' => 'romanb'],
],
'romanb',
];

// SELECT u.id FROM CmsUser u WHERE u.id = 1
yield [
[
['u__id' => '1'],
],
1,
];

// SELECT
// u.id,
// COUNT(u.postsCount + u.likesCount) AS HIDDEN score
// FROM CmsUser u
// WHERE u.id = 1
yield [
[
[
'u__id' => '1',
'score' => 10, // Ignored since not part of ResultSetMapping (cf. HIDDEN keyword)
],
],
// valid
1,
];
}

/**
* @dataProvider validResultSetProvider
*/
public function testHydrateSingleScalarFromFieldMappingWithValidResultSet(array $resultSet, $expectedResult): void
{
$rsm = new ResultSetMapping();
$rsm->addEntityResult(CmsUser::class, 'u');
$rsm->addFieldResult('u', 'u__id', 'id');
$rsm->addFieldResult('u', 'u__name', 'name');

$stmt = ArrayResultFactory::createFromArray($resultSet);
$hydrator = new SingleScalarHydrator($this->entityManager);

$result = $hydrator->hydrateAll($stmt, $rsm);
$this->assertEquals($expectedResult, $result);
}

/**
* @dataProvider validResultSetProvider
*/
public function testHydrateSingleScalarFromScalarMappingWithValidResultSet(array $resultSet, $expectedResult): void
{
$rsm = new ResultSetMapping();
$rsm->addScalarResult('u__id', 'id', 'string');
$rsm->addScalarResult('u__name', 'name', 'string');

$stmt = ArrayResultFactory::createFromArray($resultSet);
$hydrator = new SingleScalarHydrator($this->entityManager);

$result = $hydrator->hydrateAll($stmt, $rsm);
$this->assertEquals($expectedResult, $result);
}

public static function invalidResultSetProvider()
{
// Single row (OK), multiple columns (NOT OK)
yield [
[
'name' => 'result2',
'resultSet' => [
['u__id' => '1'],
[
'u__id' => '1',
'u__name' => 'romanb',
],
],
// invalid
];

// Multiple rows (NOT OK), single column (OK)
yield [
[
'name' => 'result3',
'resultSet' => [
[
'u__id' => '1',
'u__name' => 'romanb',
],
['u__id' => '1'],
['u__id' => '2'],
],
];

// Multiple rows (NOT OK), single column with HIDDEN result (OK)
yield [
[
[
'u__id' => '1',
'score' => 10, // Ignored since not part of ResultSetMapping
],
[
'u__id' => '2',
'score' => 10, // Ignored since not part of ResultSetMapping
],
],
// invalid
1,
];

// Multiple row (NOT OK), multiple columns (NOT OK)
yield [
[
'name' => 'result4',
'resultSet' => [
['u__id' => '1'],
['u__id' => '2'],
[
'u__id' => '1',
'u__name' => 'romanb',
],
[
'u__id' => '2',
'u__name' => 'romanb',
],
],
];
}

/**
* select u.name from CmsUser u where u.id = 1
*
* @dataProvider singleScalarResultSetProvider
* @dataProvider invalidResultSetProvider
*/
public function testHydrateSingleScalar($name, $resultSet): void
public function testHydrateSingleScalarFromFieldMappingWithInvalidResultSet(array $resultSet): void
{
$rsm = new ResultSetMapping();
$rsm->addEntityResult(CmsUser::class, 'u');
Expand All @@ -68,23 +144,23 @@ public function testHydrateSingleScalar($name, $resultSet): void
$stmt = ArrayResultFactory::createFromArray($resultSet);
$hydrator = new SingleScalarHydrator($this->entityManager);

if ($name === 'result1') {
$result = $hydrator->hydrateAll($stmt, $rsm);
self::assertEquals('romanb', $result);

return;
}
$this->expectException(NonUniqueResultException::class);
$hydrator->hydrateAll($stmt, $rsm);
}

if ($name === 'result2') {
$result = $hydrator->hydrateAll($stmt, $rsm);
self::assertEquals(1, $result);
/**
* @dataProvider invalidResultSetProvider
*/
public function testHydrateSingleScalarFromScalarMappingWithInvalidResultSet(array $resultSet): void
{
$rsm = new ResultSetMapping();
$rsm->addScalarResult('u__id', 'id', 'string');
$rsm->addScalarResult('u__name', 'name', 'string');

return;
}
$stmt = ArrayResultFactory::createFromArray($resultSet);
$hydrator = new SingleScalarHydrator($this->entityManager);

if (in_array($name, ['result3', 'result4'], true)) {
$this->expectException(NonUniqueResultException::class);
$hydrator->hydrateAll($stmt, $rsm);
}
$this->expectException(NonUniqueResultException::class);
$hydrator->hydrateAll($stmt, $rsm);
}
}

0 comments on commit 498604f

Please sign in to comment.