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

Fix parameter name comparison in AbstractQuery regarding different types (fixes #6699) #6705

Merged
merged 3 commits into from
Nov 24, 2017

Conversation

Majkl578
Copy link
Contributor

@Majkl578 Majkl578 commented Sep 16, 2017

AbstractQuery::setParameter() uses weak comparison to compare parameter names and decide whether to update existing or add new parameter. AbstractQuery::getParameter() does so as well.
This is problematic for parameter named 0 since strings are downcasted to 0 as well, making it incorrectly assume that i.e. the 0 and "foo" are the same parameter.
In most cases, cast is not needed and we would ideally want to prevent it, thus added identity check first and only if it fails, string cast comparison is attempted.

Fixes #6699.

@Majkl578 Majkl578 added the WIP label Sep 16, 2017
@Majkl578 Majkl578 force-pushed the ticket/6699 branch 3 times, most recently from ab436ea to 708f8c0 Compare September 16, 2017 20:23
@Majkl578 Majkl578 changed the title Failing test for #6699 Fix parameter name comparison in AbstractQuery regarding different types (fixes #6699) Sep 16, 2017
@Majkl578
Copy link
Contributor Author

Reworded & fix + more tests added.

@Seb33300
Copy link
Contributor

You have only updated the AbstractQuery::setParameter() function but I can find the exact same function in QueryBuilder: https://github.com/doctrine/doctrine2/blob/80f7824b3d8a2b5e3810c597582ee3524750b682/lib/Doctrine/ORM/QueryBuilder.php#L533
Not sure if it should be modified too.

Copy link
Member

@lcobucci lcobucci left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some nitpicking, as usual 😂
We should also use self::assert*() everywhere.

I got some time now so I can apply the changes and investigate any performance impact, if you don't mind.

@@ -323,8 +323,8 @@ public function getParameter($key)
$filteredParameters = $this->parameters->filter(
function ($parameter) use ($key)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

: bool

@@ -369,17 +369,10 @@ public function setParameters($parameters)
*/
public function setParameter($key, $value, $type = null)
{
$filteredParameters = $this->parameters->filter(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice simplification here, do we have any impact on performance (due to the additional method call)?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just tested, the answer is: we have no performance impact

use Doctrine\Tests\OrmFunctionalTestCase;

/**
* @group #6699
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're using the ticket id without the # everywhere else, we should keep it consistent here too

@@ -303,4 +304,65 @@ public function testSelectFromSubquery()
$this->expectExceptionMessage('Subquery');
$query->getSQL();
}

/**
* @group #6699
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're using the ticket id without the # everywhere else, we should keep it consistent here too

}

/**
* @group #6699
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're using the ticket id without the # everywhere else, we should keep it consistent here too


public function testMixedParametersWithZeroNumber()
{
$qb = $this->_em->createQueryBuilder()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can simplify this bit, since the query builder reference is not really needed, like:

$query = $this->_em->createQueryBuilder()
                   ->select('u')
                   ->from(CmsUser::class, 'u')
                   ->andWhere('u.username = :username')
                   ->andWhere('u.id = ?0')
                   ->getQuery();

parent::setUp();
}

public function testMixedParametersWithZeroNumber()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

: void

*/
class GH6699Test extends OrmFunctionalTestCase
{
protected function setUp()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

: void

/**
* @group #6699
*/
public function testSetParameterWithTypeJugglingWorks()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

: void

*/
public function testSetParameterWithTypeJugglingWorks()
{
$query = $this->_em->createQuery("select u from Doctrine\Tests\Models\CMS\CmsUser u where u.id != ?0 and u.username = :name");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could use ' . CmsUser::class . ' to keep consistency

@lcobucci lcobucci added this to the 2.5.12 milestone Nov 24, 2017
@lcobucci lcobucci self-assigned this Nov 24, 2017
@lcobucci lcobucci modified the milestones: 2.5.12, 2.5.13 Nov 24, 2017
@lcobucci lcobucci merged commit b7cace8 into doctrine:master Nov 24, 2017
lcobucci added a commit to lcobucci/doctrine2 that referenced this pull request Nov 24, 2017
@lcobucci
Copy link
Member

@Majkl578 🚢 and backported to v2.5.x

Thanks!

@Majkl578
Copy link
Contributor Author

Majkl578 commented Dec 6, 2017

We should probably copy this behavior to AbstractQuery::setParameter() as well (thanks for spotting @Seb33300).
For 3.0 we should consider different approach - I was already thinking about having ParameterCollection or ParameterBag (Symfony-style naming).

@Majkl578 Majkl578 deleted the ticket/6699 branch December 6, 2017 03:33
@lcobucci
Copy link
Member

lcobucci commented Dec 6, 2017

We should probably copy this behavior to AbstractQuery::setParameter() as well (thanks for spotting @Seb33300).

I've applied it there as well

@Majkl578
Copy link
Contributor Author

Majkl578 commented Dec 6, 2017

@lcobucci Cool, thanks!

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

Successfully merging this pull request may close these issues.

5 participants