Closed Birmania closed 9 years ago
Can you give me the full query and the stack trace ?
Sure, there is it.
Full Query :
SELECT DISTINCT s0.idsymbol AS idsymbol0 FROM symbols s0 ORDER BY s0_.namesymbol ASC LIMIT 25 OFFSET 0
First stack trace :
[2/2] Twig_ErrorRuntime: An exception has been thrown during the rendering of a template ("SQLSTATE[42P10]: Invalid column reference: 7 ERROR: for SELECT DISTINCT, ORDER BY expressions must appear in select list
LINE 1: ....idsymbol AS idsymbol0 FROM symbols s0 ORDER BY s0.namesy...
^") in "SonataAdminBundle:CRUD:base_list.html.twig" at line 28. -
in /tmp/Symfony/app/cache/dev/twig/37/a0/f7529f7d22400ddbc9948cce03b7.php at line 39 -+
in /tmp/Symfony/app/cache/dev/classes.php at line 7399 -+
in /tmp/Symfony/app/cache/dev/twig/61/46/0679a1df2b78e79550c29673e015.php at line 21 -+
in /tmp/Symfony/app/cache/dev/classes.php at line 7399 -+
in /tmp/Symfony/app/cache/dev/classes.php at line 7418 -+
in /home/abrultet/interface-admin/Symfony/vendor/symfony/src/Symfony/Bundle/TwigBundle/TwigEngine.php at line 60 -+
in /home/abrultet/interface-admin/Symfony/vendor/symfony/src/Symfony/Bundle/TwigBundle/TwigEngine.php at line 114 -+
in /home/abrultet/interface-admin/Symfony/vendor/symfony/src/Symfony/Bundle/FrameworkBundle/Controller/Controller.php at line 98 -+
in /home/abrultet/interface-admin/Symfony/vendor/bundles/Sonata/AdminBundle/Controller/CRUDController.php at line 128 -+
in /home/abrultet/interface-admin/Symfony/vendor/bundles/Sonata/AdminBundle/Controller/CRUDController.php at line 144 -+
141.
in at line -+
in /tmp/Symfony/app/cache/dev/classes.php at line 3880 -+
3877.
in /tmp/Symfony/app/cache/dev/classes.php at line 3850 -+
in /tmp/Symfony/app/cache/dev/classes.php at line 4785 -+
in kernel.root_dir/bootstrap.php.cache at line 547 -+
in /home/abrultet/interface-admin/Symfony/web/app_dev.php at line 24 -
Second stack trace :
[1/2] PDOException: SQLSTATE[42P10]: Invalid column reference: 7 ERROR: for SELECT DISTINCT, ORDER BY expressions must appear in select list
LINE 1: ....idsymbol AS idsymbol0 FROM symbols s0 ORDER BY s0_.namesy...
^ -+
s0_.namesymbol
.. looks like that should be s0.namesymbol
Yeah and s0.namesymbol must be in the SELECT part I think. Like that : SELECT DISTINCT s0.idsymbol AS idsymbol0,s0.namesymbol FROM symbols s0 ORDER BY s0.namesymbol ASC LIMIT 25 OFFSET 0
In this code (Sonata\AdminBundle\Datagrid\ORM\ProxyQuery.php) :
public function execute(array $params = array(), $hydrationMode = null)
{
// always clone the original queryBuilder
$queryBuilder = clone $this->queryBuilder;
// todo : check how doctrine behave, potential SQL injection here ...
if ($this->getSortBy()) {
$sortBy = $this->getSortBy();
if (strpos($sortBy, '.') === false) { // add the current alias
$sortBy = $queryBuilder->getRootAlias().'.'.$sortBy;
}
$queryBuilder->orderBy($sortBy, $this->getSortOrder());
$queryBuilder->addSelect($sortBy); //Line added
}
return $this->getFixedQueryBuilder($queryBuilder)->getQuery()->execute($params, $hydrationMode);
}
I try to add the line : $queryBuilder->addSelect($sortBy);
But it cause this error : ErrorException: Warning: spl_object_hash() expects parameter 1 to be object, array given in /home/abrultet/interface-admin/Symfony/vendor/doctrine/lib/Doctrine/ORM/UnitOfWork.php line 1180
I understand the error (the select part became an array) but I think it's the good thing to do. How can I do to solve the PostgreSQL usage problem so ?
Hi, Birmania.
I modified 2 lines and added 3 lines. It works for me.
public function execute(array $params = array(), $hydrationMode = null)
{
// always clone the original queryBuilder
$queryBuilder = clone $this->queryBuilder;
// todo : check how doctrine behave, potential SQL injection here ...
if ($this->getSortBy()) {
$sortBy = $this->getSortBy();
if (strpos($sortBy, '.') === false) { // add the current alias
$sortBy = $queryBuilder->getRootAlias().'.'.$sortBy;
}
$queryBuilder->orderBy($sortBy, $this->getSortOrder());
}
return $this->getFixedQueryBuilder($queryBuilder, $sortBy)->getQuery()->execute($params, $hydrationMode); // modified
}
private function getFixedQueryBuilder(QueryBuilder $queryBuilder, $sortBy = null) // modified
{
$queryBuilderId = clone $queryBuilder;
// step 1 : retrieve the targeted class
$from = $queryBuilderId->getDQLPart('from');
$class = $from[0]->getFrom();
// step 2 : retrieve the column id
$idName = current($queryBuilderId->getEntityManager()->getMetadataFactory()->getMetadataFor($class)->getIdentifierFieldNames());
// step 3 : retrieve the different subjects id
$select = sprintf('%s.%s', $queryBuilderId->getRootAlias(), $idName);
$queryBuilderId->resetDQLPart('select');
$queryBuilderId->add('select', 'DISTINCT '.$select);
if ($sortBy) { // added
$queryBuilderId->addSelect($sortBy); // added
} // added
$results = $queryBuilderId->getQuery()->execute(array(), Query::HYDRATE_ARRAY);
$idx = array();
$connection = $queryBuilder->getEntityManager()->getConnection();
foreach($results as $id) {
$idx[] = $connection->quote($id[$idName]);
}
// step 4 : alter the query to match the targeted ids
if (count($idx) > 0) {
$queryBuilder->andWhere(sprintf('%s IN (%s)', $select, implode(',', $idx)));
$queryBuilder->setMaxResults(null);
$queryBuilder->setFirstResult(null);
}
return $queryBuilder;
}
I haven't seen the issue before, so I made an individual PR which was just merged so this should now work by default for anyone using master. @Birmania can you confirm, that the master also works for you and close the ticket afterwards if it does.
Hmm, if you have a DISTINCT
query plus an ORDER BY
clause, you would also need to add a `GROUP BY
, in which case the result set will be different (unless you use some random throw-away aggregator to group the ordered elements).
But other than that, all of this seems kind of fishy and is just a workaround, perhaps someone can offer a clean solution? I can look into it tomorrow, but perhaps we can get some input from Doctrine fellows meanwhile?
EDIT: And why is the query always modified with a DISTINCT Id
, shouldn't this kind of logic reside in the endpoints, not in the direct wrapper?
EDIT2: Postgre support for NewsBundle
is poor as well, there are some direct LIKE
expressions against date fields, which are not supported by PG since 8.3 and a helper function parsing dates into strings seem to be lacking from ORM at this point as well :(
EDIT3: Issued a PR in NewsBundle
to fix EDIT2 comment.
Seems to be fixed by @helmer in #14.
BTW, this old issue seems to be not relevant anymore.
Going to close it.
@rande Please reopen it if i'm wrong.
Hello,
I install Sonata AdminBundle on Symfony 2 with a PostgreSQL database and when I try to sort a list on a column, I obtain this error :
An exception has been thrown during the rendering of a template ("SQLSTATE[42P10]: Invalid column reference: 7 ERROR: for SELECT DISTINCT, ORDER BY expressions must appear in select list LINE 1: ....idsystem AS idsystem0 FROM systems s0 ORDER BY s0_.codesy... ^") in "SonataAdminBundle:CRUD:base_list.html.twig" at line 28.
It look like PostgreSQL need to have the "order by" columns in the SELECT statement to work contrary to MySQL.
Have you got a solution to solve this problem please ?