Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Undefined index: isIdentifier in Hydrator #9483

Open
fink3l opened this issue Feb 7, 2022 · 8 comments
Open

Undefined index: isIdentifier in Hydrator #9483

fink3l opened this issue Feb 7, 2022 · 8 comments

Comments

@fink3l
Copy link

fink3l commented Feb 7, 2022

Summary

After merge #7905 (doctrine/orm > 2.6.4) i'm having problems with LimitSubqueryWalker and AbstractHydrator. When i add hint LimitSubqueryWalker to Query and try to hydrate my Query i will get Notice Undefined index: isIdentifier in lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php:459

How to reproduce

For reproduce i wrote test:

<?php

declare(strict_types=1);

namespace Doctrine\Tests\ORM\Functional\Ticket;

use Doctrine\ORM\AbstractQuery;
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\GeneratedValue;
use Doctrine\ORM\Mapping\Id;
use Doctrine\Tests\OrmFunctionalTestCase;

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

        $this->setUpEntitySchema(
            [
                SomeEntity::class,
            ]
        );
    }

    public function testLimitSubqueryWalkerIsIdentifierUndefined(): void
    {
        $this->_em->persist(new SomeEntity());
        $this->_em->flush();

        $dql   = 'SELECT e FROM Doctrine\Tests\ORM\Functional\Ticket\SomeEntity e';
        $query = $this->_em->createQuery($dql);
        $query->setHint(\Doctrine\ORM\Query::HINT_CUSTOM_TREE_WALKERS, [\Doctrine\ORM\Tools\Pagination\LimitSubqueryWalker::class]);

        $query->getResult(AbstractQuery::HYDRATE_ARRAY);
    }
}

/** @Entity */
final class SomeEntity
{
    /**
     * @var int
     * @Id
     * @Column(type="integer")
     * @GeneratedValue
     */
    public $id;
}
@realkasparov

This comment was marked as spam.

@greg0ire
Copy link
Member

You seem to still be using an outdated version because now the line with the issue is 460 (not 459). But when I try your test on 2.11.x, I get the issue, which means recent versions are still affected.

@greg0ire
Copy link
Member

@lcobucci @ostrolucky maybe you will have some idea of what to do?

@lcobucci
Copy link
Member

I'm on mobile now and won't be able to do this but essentially we need to debug what's generated by

protected function hydrateColumnInfo($key)
to understand why that index is missing.

@greg0ire
Copy link
Member

From what I see when executing the failing test case, it ends up here:

case isset($this->_rsm->scalarMappings[$key], $this->_hints[LimitSubqueryWalker::FORCE_DBAL_TYPE_CONVERSION]):
return $this->_cache[$key] = [
'fieldName' => $this->_rsm->scalarMappings[$key],
'type' => Type::getType($this->_rsm->typeMappings[$key]),
'dqlAlias' => '',
];

I'm not sure what to add there, but when I add 'isIdentifier' => true or 'isIdentifier' => false (I don't have any idea what I'm doing), I get another error message Exception: [PHPUnit\Framework\Error\Warning] Undefined array key "" emanating from

$entityKey = $this->resultSetMapping()->entityMappings[$dqlAlias] ?: 0;
(which is consistent with 'dqlAlias' => '' in the listing above.

@lcobucci
Copy link
Member

I have some time today for checking it 👍

@lcobucci
Copy link
Member

@fink3l @realkasparov does the snippet represent a real-life use case or is this only there to reproduce the issue? In other words, why are you having to use that SQL walker?

@lcobucci
Copy link
Member

Just to give more information here, this SQL walker was designed for the pagination tool (ergo my previous question). Using it outside of its designed use case will create unintended results - SQL AST is manipulated to generate a SELECT DISTINCT table.id AS _dctrn_id FROM table.

The unintended result highlighted here is that ArrayHydrator (and ObjectHydrator) doesn't work when that SQL walker is added to the query. That's because, since the linked issue, we're doing a workaround to avoid BC-breaks and always force DBAL type conversion for pagination queries.

Using scalar hydrators work just fine:

<?php
declare(strict_types=1);

namespace Doctrine\Tests\ORM\Functional\Ticket;

use Doctrine\ORM\AbstractQuery;
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\GeneratedValue;
use Doctrine\ORM\Mapping\Id;
use Doctrine\Tests\OrmFunctionalTestCase;

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

        $this->setUpEntitySchema(
            [
                GH9483SomeEntity::class,
            ]
        );
    }

    public function testLimitSubqueryWalkerIsIdentifierUndefined(): void
    {
        $this->_em->persist(new GH9483SomeEntity());
        $this->_em->flush();

        $dql   = 'SELECT e FROM Doctrine\Tests\ORM\Functional\Ticket\GH9483SomeEntity e';
        $query = $this->_em->createQuery($dql);
        $query->setHint(\Doctrine\ORM\Query::HINT_CUSTOM_TREE_WALKERS, [\Doctrine\ORM\Tools\Pagination\LimitSubqueryWalker::class]);

        self::assertSame([['__dctrn_id' => 1]], $query->getResult(AbstractQuery::HYDRATE_SCALAR));
        self::assertSame(1, $query->getResult(AbstractQuery::HYDRATE_SINGLE_SCALAR));
    }
}

/** @Entity */
final class GH9483SomeEntity
{
    /**
     * @var int
     * @Id
     * @Column(type="integer")
     * @GeneratedValue
     */
    public $id;
}

The ideal solution would be always performing the DBAL type conversion but that's a BC-break. Then, the workaround that was previously introduced could be removed.

With that said, we must ask: why do you need to rely on a pagination SQL walker for a query that doesn't use the paginator component? Or, wouldn't it be easier for you to make your code explicit and use a DQL like SELECT DISTINCT e.id FROM Doctrine\Tests\ORM\Functional\Ticket\GH9483SomeEntity e?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants