doctrine / orm

Doctrine Object Relational Mapper (ORM)
https://www.doctrine-project.org/projects/orm.html
MIT License
9.94k stars 2.52k forks source link

QueryBuilder IndexBy not indexing a result set #11137

Open SergeC opened 11 months ago

SergeC commented 11 months ago

Bug Report

Q A
BC Break yes
Version 2.17.2

Summary

QueryBuilder ignores indexBy argument and returns the result set indexed by PHP's array-keys.

Current behavior

QueryBuilder returns the result set indexed by PHP's array-keys.

How to reproduce

/* @var EntityRepository $this */
$this
            ->createQueryBuilder(alias: 'j', indexBy: 'j.id')
            ->select('j.value')
            ->andWhere('j.enabled = true')
            ->setMaxResults(10)
            ->getQuery()
            ->getSingleColumnResult();

Expected behavior

QueryBuilder should return the result set indexed by values in the database, specified in the 2nd argument to createQueryBuilder.

Installed dependencies:

doctrine/cache                        2.2.0   PHP Doctrine Cache library is a popular cache implementation that supports many different drivers such as redis, memcache, apc, mongodb and others.
doctrine/collections                  2.1.4   PHP Doctrine Collections library that adds additional functionality on top of PHP arrays.
doctrine/common                       3.4.3   PHP Doctrine Common project is a library that provides additional functionality that other Doctrine projects depend on such as better reflection support, proxies and much more.
doctrine/dbal                         3.7.2   Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.
doctrine/deprecations                 1.1.2   A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.
doctrine/doctrine-bundle              2.11.1  Symfony DoctrineBundle
doctrine/doctrine-migrations-bundle   3.3.0   Symfony DoctrineMigrationsBundle
doctrine/event-manager                2.0.0   The Doctrine Event Manager is a simple PHP event system that was built to be used with the various Doctrine projects.
doctrine/inflector                    2.0.8   PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.
doctrine/instantiator                 2.0.0   A small, lightweight utility to instantiate objects in PHP without invoking their constructors
doctrine/lexer                        2.1.0   PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.
doctrine/migrations                   3.7.2   PHP Doctrine Migrations project offer additional functionality on top of the database abstraction layer (DBAL) for versioning your database schema and easily deploying changes to it. It is a very easy to us...
doctrine/orm                          2.17.2  Object-Relational-Mapper for PHP
doctrine/persistence                  3.2.0   The Doctrine Persistence project is a set of shared interfaces and functionality that the different Doctrine object mappers share.
doctrine/sql-formatter                1.1.3   a PHP SQL highlighting library

Actual result: image Expected result: image

greg0ire commented 11 months ago

Assuming $this is an entityrepository instance, createQueryBuilder already calls select internally. With your call, you're replacing that select, making sure j.id is no longer selected.

SergeC commented 11 months ago

In this use-case, I fetch only one column. Which means I need to specify it in select. Doctrine should automatically add indexing column to select statement. Even when I add indexing column to select - nothing changes. image image

greg0ire commented 11 months ago

Huh, I did not expect that. Maybe it has to do with getSingleColumnResult() . Can you try other possibilities?

SergeC commented 11 months ago

image image

greg0ire commented 11 months ago

I meant with j.id selected

SergeC commented 11 months ago

image This adds id to the result set along with array keys.

greg0ire commented 11 months ago

Okay. This means this issue really is about index by + getSingleColumnResult.

beberlei commented 11 months ago

I dont understand, where is index by configured here? Maybe i missef it, but this is only a non entity query here, getSingleColumnResult has no index by behavior afair

greg0ire commented 11 months ago

The second argument of EntityRepository::createQueryBuilder() configures it:

https://github.com/doctrine/orm/blob/f80ef66ffb68bfa842071e2d818e87a07a2d014e/lib/Doctrine/ORM/EntityRepository.php#L76-L89

SergeC commented 9 months ago

@greg0ire @beberlei Any update on this? Any other info needed from my side?

jurchiks commented 5 months ago

I just stumbled upon this, good thing I decided to google it. It is stupid that something like this happens; one would think that indexBy is added implicitly regardless of what the user does with select(), because it is REQUIRED by the code. It should NOT be overridable by user.

I was wondering why my "account balance mapped by account ID" query was returning 0-indexed results, made no goddamn sense, and the subsequent code was clearly doing the wrong thing, when it absolutely shouldn't have. Turns out the problem wasn't in my code, but in Doctrine being dumb yet again... Such an overcomplicated mass of code, and yet.

rasstislav commented 2 months ago

@greg0ire Hello. Anything new on this issue?

greg0ire commented 2 months ago

@rasstislav not as far as I can tell. Do you want to work on a fix?