Skip to content

Commit

Permalink
Fix bound parameters in sub-queries not working.
Browse files Browse the repository at this point in the history
By applying the bound parameters when the valueBinder is different than
the current query's binder we can propagate bound variables from
subqueries to the parent query. The caveat being that this only works
seamlessly for named parameters. Numbered parameters still have a chance
of overlapping.

Refs #8466
  • Loading branch information
markstory committed Mar 18, 2016
1 parent 20c31cb commit 8a5d65c
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 0 deletions.
7 changes: 7 additions & 0 deletions src/Database/QueryCompiler.php
Expand Up @@ -97,6 +97,13 @@ public function compile(Query $query, ValueBinder $generator)
$this->_sqlCompiler($sql, $query, $generator),
$this->{'_' . $type . 'Parts'}
);

// Propagate bound parameters from sub-queries
if ($query->valueBinder() !== $generator) {
foreach ($query->valueBinder()->bindings() as $binding) {
$generator->bind(':' . $binding['placeholder'], $binding['value'], $binding['type']);
}
}
return $sql;
}

Expand Down
42 changes: 42 additions & 0 deletions tests/TestCase/ORM/QueryRegressionTest.php
Expand Up @@ -580,6 +580,48 @@ public function testCountWithContain()
$this->assertEquals(2, $count);
}

/**
* Tests that getting the count of a query with bind is correct
*
* @see https://github.com/cakephp/cakephp/issues/8466
* @return void
*/
public function testCountWithBind()
{
$table = TableRegistry::get('Articles');
$query = $table
->find()
->select(['Articles.title', 'Articles.id'])
->where("Articles.title LIKE :val")
->group('Articles.id')
->bind(':val', '%Second%');
$count = $query->count();
$this->assertEquals(1, $count);
}

/**
* Tests that bind in subqueries works.
*
* @return void
*/
public function testSubqueryBind()
{
$table = TableRegistry::get('Articles');
$sub = $table->find()
->select(['Articles.id'])
->where("Articles.title LIKE :val")
->bind(':val', 'Second %');

$query = $table
->find()
->select(['Articles.title'])
->where(["Articles.id NOT IN" => $sub]);
$result = $query->toArray();
$this->assertCount(2, $result);
$this->assertEquals('First Article', $result[0]->title);
$this->assertEquals('Third Article', $result[1]->title);
}

/**
* Test that deep containments don't generate empty entities for
* intermediary relations.
Expand Down

0 comments on commit 8a5d65c

Please sign in to comment.