EasyCorp / EasyCorp/EasyAdminBundle
4.27.0 queries all rows in a table causing a crash
Nobody has claimed this yet.
- Dominant language
- PHP
- Stars
- 4.3k
- Forks
- 1.1k
- Avg merge
- 8d 2h
- Merged PRs (30d)
- 11
Description
Something in 4.27.0 generates following SQL:
SELECT v0_.foo1 AS foo1_0,
v0_.foo2 AS foo2_1,
v0_.foo3 AS foo3_2,
v0_.foo4 AS foo4_3,
v0_.foo5 AS foo5_4,
v0_.foo6 AS foo6_5,
v0_.foo7 AS foo7_6,
v0_.foo8 AS foo8_7,
v0_.foo9 AS foo9_8,
v0_.foo10 AS foo10_9,
v0_.foo11 AS foo11_10,
v0_.foo12 AS foo12_11,
v0_.foo13 AS foo13_12,
v0_.foo14 AS foo14_13,
v0_.foo15 AS foo15_14,
v0_.foo16 AS foo16_15,
v0_.foo17 AS foo17_16,
v0_.foo18 AS foo18_17
FROM foos v0_
The table has millions of rows so the app runs out of memory and crashes.
Here's a stack trace where this SQL is executed:
#0 /Users/simo/Projects/Foo/Bar/vendor/doctrine/orm/src/Query/Exec/FinalizedSelectExecutor.php(27): Doctrine\DBAL\Connection->executeQuery('SELECT v0_.foo1...', Array, Array, NULL)
#1 /Users/simo/Projects/Foo/Bar/vendor/doctrine/orm/src/Query.php(296): Doctrine\ORM\Query\Exec\FinalizedSelectExecutor->execute(Object(Doctrine\DBAL\Connection), Array, Array)
#2 /Users/simo/Projects/Foo/Bar/vendor/doctrine/orm/src/AbstractQuery.php(930): Doctrine\ORM\Query->_doExecute()
#3 /Users/simo/Projects/Foo/Bar/vendor/doctrine/orm/src/AbstractQuery.php(886): Doctrine\ORM\AbstractQuery->executeIgnoreQueryCache(NULL, NULL)
#4 /Users/simo/Projects/Foo/Bar/vendor/symfony/doctrine-bridge/Form/ChoiceList/ORMQueryBuilderLoader.php(35): Doctrine\ORM\AbstractQuery->execute()
#5 /Users/simo/Projects/Foo/Bar/vendor/symfony/doctrine-bridge/Form/ChoiceList/DoctrineChoiceLoader.php(53): Symfony\Bridge\Doctrine\Form\ChoiceList\ORMQueryBuilderLoader->getEntities()
#6 /Users/simo/Projects/Foo/Bar/vendor/symfony/form/ChoiceList/Loader/AbstractChoiceLoader.php(29): Symfony\Bridge\Doctrine\Form\ChoiceList\DoctrineChoiceLoader->loadChoices()
#7 /Users/simo/Projects/Foo/Bar/vendor/symfony/form/ChoiceList/LazyChoiceList.php(56): Symfony\Component\Form\ChoiceList\Loader\AbstractChoiceLoader->loadChoiceList(Object(Closure))
#8 /Users/simo/Projects/Foo/Bar/vendor/symfony/form/ChoiceList/Factory/DefaultChoiceListFactory.php(60): Symfony\Component\Form\ChoiceList\LazyChoiceList->getChoices()
#9 /Users/simo/Projects/Foo/Bar/vendor/symfony/form/ChoiceList/Factory/PropertyAccessDecorator.php(178): Symfony\Component\Form\ChoiceList\Factory\DefaultChoiceListFactory->createView(Object(Symfony\Component\Form\ChoiceList\LazyChoiceList), Array, Object(Closure), Object(Closure), NULL, NULL, Array, true)
#10 /Users/simo/Projects/Foo/Bar/vendor/symfony/form/ChoiceList/Factory/CachingFactoryDecorator.php(202): Symfony\Component\Form\ChoiceList\Factory\PropertyAccessDecorator->createView(Object(Symfony\Component\Form\ChoiceList\LazyChoiceList), Array, Object(Closure), Object(Closure), NULL, NULL, Array, true)
#11 /Users/simo/Projects/Foo/Bar/vendor/symfony/form/Extension/Core/Type/ChoiceType.php(479): Symfony\Component\Form\ChoiceList\Factory\CachingFactoryDecorator->createView(Object(Symfony\Component\Form\ChoiceList\LazyChoiceList), Array, Object(Closure), Object(Closure), NULL, NULL, Array, true)
#12 /Users/simo/Projects/Foo/Bar/vendor/symfony/form/Extension/Core/Type/ChoiceType.php(234): Symfony\Component\Form\Extension\Core\Type\ChoiceType->createChoiceListView(Object(Symfony\Component\Form\ChoiceList\LazyChoiceList), Array)
#13 /Users/simo/Projects/Foo/Bar/vendor/symfony/form/ResolvedFormType.php(107): Symfony\Component\Form\Extension\Core\Type\ChoiceType->buildView(Object(Symfony\Component\Form\FormView), Object(Symfony\Component\Form\Form), Array)
#14 /Users/simo/Projects/Foo/Bar/vendor/symfony/form/Extension/DataCollector/Proxy/ResolvedTypeDataCollectorProxy.php(78): Symfony\Component\Form\ResolvedFormType->buildView(Object(Symfony\Component\Form\FormView), Object(Symfony\Component\Form\Form), Array)
#15 /Users/simo/Projects/Foo/Bar/vendor/symfony/form/ResolvedFormType.php(105): Symfony\Component\Form\Extension\DataCollector\Proxy\ResolvedTypeDataCollectorProxy->buildView(Object(Symfony\Component\Form\FormView), Object(Symfony\Component\Form\Form), Array)
#16 /Users/simo/Projects/Foo/Bar/vendor/symfony/form/Extension/DataCollector/Proxy/ResolvedTypeDataCollectorProxy.php(78): Symfony\Component\Form\ResolvedFormType->buildView(Object(Symfony\Component\Form\FormView), Object(Symfony\Component\Form\Form), Array)
#17 /Users/simo/Projects/Foo/Bar/vendor/symfony/form/Form.php(888): Symfony\Component\Form\Extension\DataCollector\Proxy\ResolvedTypeDataCollectorProxy->buildView(Object(Symfony\Component\Form\FormView), Object(Symfony\Component\Form\Form), Array)
#18 /Users/simo/Projects/Foo/Bar/vendor/symfony/form/Form.php(891): Symfony\Component\Form\Form->createView(Object(Symfony\Component\Form\FormView))
#19 /Users/simo/Projects/Foo/Bar/vendor/symfony/form/Extension/Core/Type/CollectionType.php(64): Symfony\Component\Form\Form->createView(Object(Symfony\Component\Form\FormView))
#20 /Users/simo/Projects/Foo/Bar/vendor/symfony/form/ResolvedFormType.php(107): Symfony\Component\Form\Extension\Core\Type\CollectionType->buildView(Object(Symfony\Component\Form\FormView), Object(Symfony\Component\Form\Form), Array)
#21 /Users/simo/Projects/Foo/Bar/vendor/symfony/form/Extension/DataCollector/Proxy/ResolvedTypeDataCollectorProxy.php(78): Symfony\Component\Form\ResolvedFormType->buildView(Object(Symfony\Component\Form\FormView), Object(Symfony\Component\Form\Form), Array)
#22 /Users/simo/Projects/Foo/Bar/vendor/symfony/form/Form.php(888): Symfony\Component\Form\Extension\DataCollector\Proxy\ResolvedTypeDataCollectorProxy->buildView(Object(Symfony\Component\Form\FormView), Object(Symfony\Component\Form\Form), Array)
#23 /Users/simo/Projects/Foo/Bar/vendor/symfony/form/Form.php(891): Symfony\Component\Form\Form->createView(Object(Symfony\Component\Form\FormView))
#24 /Users/simo/Projects/Foo/Bar/vendor/easycorp/easyadmin-bundle/src/EventListener/CrudResponseListener.php(44): Symfony\Component\Form\Form->createView()
#25 /Users/simo/Projects/Foo/Bar/vendor/symfony/event-dispatcher/Debug/WrappedListener.php(115): EasyCorp\Bundle\EasyAdminBundle\EventListener\CrudResponseListener->onKernelView(Object(Symfony\Component\HttpKernel\Event\ViewEvent), 'kernel.view', Object(Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher))
#26 /Users/simo/Projects/Foo/Bar/vendor/symfony/event-dispatcher/EventDispatcher.php(206): Symfony\Component\EventDispatcher\Debug\WrappedListener->__invoke(Object(Symfony\Component\HttpKernel\Event\ViewEvent), 'kernel.view', Object(Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher))
#27 /Users/simo/Projects/Foo/Bar/vendor/symfony/event-dispatcher/EventDispatcher.php(56): Symfony\Component\EventDispatcher\EventDispatcher->callListeners(Array, 'kernel.view', Object(Symfony\Component\HttpKernel\Event\ViewEvent))
#28 /Users/simo/Projects/Foo/Bar/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php(126): Symfony\Component\EventDispatcher\EventDispatcher->dispatch(Object(Symfony\Component\HttpKernel\Event\ViewEvent), 'kernel.view')
#29 /Users/simo/Projects/Foo/Bar/vendor/symfony/http-kernel/HttpKernel.php(188): Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher->dispatch(Object(Symfony\Component\HttpKernel\Event\ViewEvent), 'kernel.view')
#30 /Users/simo/Projects/Foo/Bar/vendor/symfony/http-kernel/HttpKernel.php(76): Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object(Symfony\Component\HttpFoundation\Request), 1)
#31 /Users/simo/Projects/Foo/Bar/vendor/symfony/http-kernel/Kernel.php(182): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#32 /Users/simo/Projects/Foo/Bar/vendor/symfony/runtime/Runner/Symfony/HttpKernelRunner.php(35): Symfony\Component\HttpKernel\Kernel->handle(Object(Symfony\Component\HttpFoundation\Request))
#33 /Users/simo/Projects/Foo/Bar/vendor/autoload_runtime.php(29): Symfony\Component\Runtime\Runner\Symfony\HttpKernelRunner->run()
#34 /Users/simo/Projects/Foo/Bar/public/index.php(9): require_once('/Users/simo/Pro...')
#35 {main}
It's the CollectionField field somehow, but doesn't happen with every CollectionField I have.
Will try to create a minimal reproducer later
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Use the CollectionField path and the ORMQueryBuilderLoader stack frame as entry points. First reproduce the 4.27.0 behavior with a CollectionField and a large table, then trace why the choice loader executes an unrestricted query. Done means the affected field no longer loads every row into memory and the crash is prevented.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- php, symfony
- Domain
- backend, database
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100