Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions src/Compat/FilterProcessor.php
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<?php

namespace ipl\Orm\Compat;
Expand All @@ -9,6 +9,7 @@
use ipl\Orm\Query;
use ipl\Orm\Relation;
use ipl\Orm\UnionQuery;
use ipl\Sql\Adapter\Pgsql;
use ipl\Sql\Filter\Exists;
use ipl\Sql\Filter\In;
use ipl\Sql\Filter\NotExists;
Expand Down Expand Up @@ -323,15 +324,17 @@
$subQuerySelect = $subQuery->assembleSelect()->resetOrderBy();

if ($count !== null && ($negate || $filter instanceof Filter\All)) {
$targetKeys = join(
',',
array_values(
$subQuery->getResolver()->qualifyColumns(
(array) $subQuery->getModel()->getKeyName(),
$subQuery->getModel()
)
$targetKeys = array_values(
$subQuery->getResolver()->qualifyColumns(
(array) $subQuery->getModel()->getKeyName(),
$subQuery->getModel()
)
);
if (count($targetKeys) > 1 && $query->getDb()->getAdapter() instanceof Pgsql) {
$targetKeys = '(' . join(', ', $targetKeys) . ')';
} else {
$targetKeys = join(', ', $targetKeys);
}

$subQuerySelect->having(["COUNT(DISTINCT $targetKeys) >= ?" => $count]);
$subQuerySelect->groupBy(array_values($subQuerySelect->getColumns()));
Expand Down
20 changes: 20 additions & 0 deletions tests/FilterProcessorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use ipl\Sql\Connection;
use ipl\Sql\Test\Databases;
use ipl\Stdlib\Filter;
use ipl\Tests\Orm\Lib\Model\Employee;
use ipl\Tests\Orm\Lib\Model\Office;

class FilterProcessorTest extends \PHPUnit\Framework\TestCase
Expand Down Expand Up @@ -116,6 +117,23 @@ public function testUnequalTargetingAnOptionalToManyRelationIgnoresFalsePositive
$this->assertSame('London', $results[0]['city'] ?? 'not found');
}

/** @dataProvider databases */
public function testNegationOfAToManyRelationWorksAcrossDatabaseAdapters(Connection $db): void
{
$db->insert('employee', ['id' => 1, 'department_id' => 1, 'name' => 'Minnie', 'role' => 'CEO']);
$db->insert('employee', ['id' => 2, 'department_id' => 2, 'name' => 'Goofy', 'role' => 'Developer']);
$db->insert('chair', ['department_id' => 1, 'employee_id' => 1, 'vendor' => 'Acme Chairs']);
$db->insert('chair', ['department_id' => 2, 'employee_id' => 1, 'vendor' => 'Bcme Chairs']);
$db->insert('chair', ['department_id' => 3, 'employee_id' => 2, 'vendor' => 'Bcme Chairs']);

$employeesWithoutAcmeChairs = Employee::on($db)
->filter(Filter::unequal('chair.vendor', 'Acme Chairs'));
$results = iterator_to_array($employeesWithoutAcmeChairs);

$this->assertCount(1, $results);
$this->assertSame('Goofy', $results[0]->name);
}

protected function createSchema(Connection $db, string $driver): void
{
$db->exec('CREATE TABLE office (id INT PRIMARY KEY, city VARCHAR(255))');
Expand All @@ -124,10 +142,12 @@ protected function createSchema(Connection $db, string $driver): void
'CREATE TABLE employee (id INT PRIMARY KEY, department_id INT,'
. ' office_id INT, name VARCHAR(255), role VARCHAR(255))'
);
$db->exec('CREATE TABLE chair (department_id INT, employee_id INT, vendor VARCHAR(255))');
}

protected function dropSchema(Connection $db, string $driver): void
{
$db->exec('DROP TABLE IF EXISTS chair');
$db->exec('DROP TABLE IF EXISTS employee');
$db->exec('DROP TABLE IF EXISTS department');
$db->exec('DROP TABLE IF EXISTS office');
Expand Down
33 changes: 33 additions & 0 deletions tests/Lib/Model/Chair.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace ipl\Tests\Orm\Lib\Model;

use ipl\Orm\Model;
use ipl\Orm\Relations;

class Chair extends Model
{
public function getTableName()
{
return 'chair';
}

public function getKeyName()
{
return ['department_id', 'employee_id'];
}

public function getColumns()
{
return [
'department_id',
'employee_id',
'vendor'
];
}

public function createRelations(Relations $relations)
{
$relations->belongsTo('employee', Employee::class);
}
}
1 change: 1 addition & 0 deletions tests/Lib/Model/Employee.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,6 @@ public function createRelations(Relations $relations)
$relations->belongsTo('department', Department::class);
$relations->belongsTo('office', Office::class)
->setJoinType('LEFT');
$relations->hasMany('chair', Chair::class);
}
}
Loading