N°6182 - Fix crash with UNION OQL queries when classes / aliases are different

This commit is contained in:
Eric Espie
2023-04-26 15:09:12 +02:00
parent 7e08f6131c
commit d8b21e11ed
5 changed files with 114 additions and 15 deletions

View File

@@ -58,12 +58,11 @@ class DBSearchIntersectTest extends ItopTestCase
'alias' => "ApplicationSolution",
'result' => "SELECT `ApplicationSolution` FROM ApplicationSolution AS `ApplicationSolution` WHERE (`ApplicationSolution`.`org_id` = 3) UNION SELECT `BusinessProcess` FROM BusinessProcess AS `BusinessProcess` WHERE (`BusinessProcess`.`org_id` = 3)");
// Bug to fix
// $aTests['Test union #2902'] = array(
// 'left' => "SELECT `L-1` FROM ServiceFamily AS `L-1` WHERE 1",
// 'right' => "SELECT `sf` FROM ServiceFamily AS `sf` JOIN Service AS `s` ON `s`.servicefamily_id = `sf`.id JOIN lnkCustomerContractToService AS `l1` ON `l1`.service_id = `s`.id JOIN CustomerContract AS `cc` ON `l1`.customercontract_id = `cc`.id WHERE (`cc`.`org_id` = 3) UNION SELECT `sf` FROM ServiceFamily AS `sf` JOIN Service AS `s` ON `s`.servicefamily_id = `sf`.id JOIN lnkCustomerContractToService AS `l1` ON `l1`.service_id = `s`.id JOIN CustomerContract AS `cc` ON `l1`.customercontract_id = `cc`.id JOIN Organization AS `child` ON `cc`.org_id = `child`.id JOIN Organization AS `root` ON `child`.parent_id BELOW `root`.id WHERE (`root`.`id` = 3)",
// 'alias' => "L-1",
// 'result' => "SELECT `L-1` FROM ServiceFamily AS `L-1` JOIN Service AS `s` ON `s`.servicefamily_id = `L-1`.id JOIN lnkCustomerContractToService AS `l1` ON `l1`.service_id = `s`.id JOIN CustomerContract AS `cc` ON `l1`.customercontract_id = `cc`.id WHERE (`cc`.`org_id` = 3) UNION SELECT `L-1` FROM ServiceFamily AS `L-1` JOIN Service AS `s` ON `s`.servicefamily_id = `L-1`.id JOIN lnkCustomerContractToService AS `l1` ON `l1`.service_id = `s`.id JOIN CustomerContract AS `cc` ON `l1`.customercontract_id = `cc`.id JOIN Organization AS `child` ON `cc`.org_id = `child`.id JOIN Organization AS `root` ON `child`.parent_id BELOW `root`.id WHERE (`root`.`id` = 3)");
$aTests['Test union #2902'] = array(
'left' => "SELECT `L-1` FROM ServiceFamily AS `L-1` WHERE 1",
'right' => "SELECT `sf` FROM ServiceFamily AS `sf` JOIN Service AS `s` ON `s`.servicefamily_id = `sf`.id JOIN lnkCustomerContractToService AS `l1` ON `l1`.service_id = `s`.id JOIN CustomerContract AS `cc` ON `l1`.customercontract_id = `cc`.id WHERE (`cc`.`org_id` = 3) UNION SELECT `sf` FROM ServiceFamily AS `sf` JOIN Service AS `s` ON `s`.servicefamily_id = `sf`.id JOIN lnkCustomerContractToService AS `l1` ON `l1`.service_id = `s`.id JOIN CustomerContract AS `cc` ON `l1`.customercontract_id = `cc`.id JOIN Organization AS `child` ON `cc`.org_id = `child`.id JOIN Organization AS `root` ON `child`.parent_id BELOW `root`.id WHERE (`root`.`id` = 3)",
'alias' => "L-1",
'result' => "SELECT `L-1` FROM ServiceFamily AS `L-1` JOIN Service AS `s` ON `s`.servicefamily_id = `L-1`.id JOIN lnkCustomerContractToService AS `l1` ON `l1`.service_id = `s`.id JOIN CustomerContract AS `cc` ON `l1`.customercontract_id = `cc`.id WHERE (`cc`.`org_id` = 3) UNION SELECT `L-1` FROM ServiceFamily AS `L-1` JOIN Service AS `s` ON `s`.servicefamily_id = `L-1`.id JOIN lnkCustomerContractToService AS `l1` ON `l1`.service_id = `s`.id JOIN CustomerContract AS `cc` ON `l1`.customercontract_id = `cc`.id JOIN Organization AS `child` ON `cc`.org_id = `child`.id JOIN Organization AS `root` ON `child`.parent_id BELOW `root`.id WHERE (`root`.`id` = 3)");
$aTests['Multiple selected classes inverted'] = array(
'left' => "SELECT `L`, `P` FROM Person AS `P` JOIN Location AS `L` ON `P`.location_id = `L`.id WHERE 1",

View File

@@ -30,6 +30,7 @@ namespace Combodo\iTop\Test\UnitTest\Core;
use CMDBSource;
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
use CoreOqlMultipleResultsForbiddenException;
use DBObjectSet;
use DBSearch;
use Exception;
use Expression;
@@ -745,4 +746,30 @@ class DBSearchTest extends ItopDataTestCase
$oSearch->MakeSelectQuery();
self::assertTrue(true);
}
/**
* @dataProvider QueriesProvider
* @param $sOQL
*
* @return void
*/
public function testQueries($sOQL)
{
$oSearch = DBSearch::FromOQL($sOQL);
$oSet = new DBObjectSet($oSearch);
if ($oSet->Count() > 0) {
$aSelectedAliases = array_keys($oSearch->GetSelectedClasses());
$aFirstRow = $oSet->FetchAssoc();
$aAliases = array_keys($aFirstRow);
$this->assertEquals($aSelectedAliases, $aAliases);
}
}
public function QueriesProvider()
{
return [
['SELECT L,P FROM Person AS P JOIN Location AS L ON P.location_id=L.id'],
['SELECT P,L FROM Person AS P JOIN Location AS L ON P.location_id=L.id'],
];
}
}

View File

@@ -15,6 +15,52 @@ use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
class DBUnionSearchTest extends ItopDataTestCase
{
/**
* @dataProvider UnionSearchProvider
*
* @param $sOQL
*
* @return void
* @throws \CoreException
* @throws \OQLException
*/
public function testUnionSearch($sOQL)
{
$oSearch = DBSearch::FromOQL($sOQL);
$oSet = new DBObjectSet($oSearch);
if ($oSet->Count() > 0) {
$aSelectedAliases = array_keys($oSearch->GetSelectedClasses());
$aFirstRow = $oSet->FetchAssoc();
$aAliases = array_keys($aFirstRow);
$this->assertEquals($aSelectedAliases, $aAliases);
}
$aSelectedClasses = $oSearch->GetSelectedClasses();
foreach ($aSelectedClasses as $sSelectedAlias => $sSelectedClass) {
$oSearchTest = $oSearch->DeepClone();
$oSearchTest->SetSelectedClasses([$sSelectedAlias]);
$oSet = new DBObjectSet($oSearchTest);
if ($oSet->Count() > 0) {
$aSelectedAliases = array_keys($oSearchTest->GetSelectedClasses());
$aFirstRow = $oSet->FetchAssoc();
$aAliases = array_keys($aFirstRow);
$this->assertEquals($aSelectedAliases, $aAliases);
}
}
}
public function UnionSearchProvider()
{
return [
'Same class' => ["SELECT Server UNION SELECT Server"],
'different class same alias' => ['SELECT Server AS fci UNION SELECT VirtualMachine AS fci'],
'different class no alias' => ['SELECT Server UNION SELECT VirtualMachine'],
'multiple classes same alias' => ['SELECT `L`, `P` FROM Location AS `L` JOIN Person AS `P` ON `P`.location_id = `L`.id WHERE (`L`.`org_id` = 3) UNION SELECT `L`, `P` FROM Location AS `L` JOIN Person AS `P` ON `P`.location_id = `L`.id WHERE (`L`.`org_id` = 2)'],
'multiple classes' => ['SELECT `L`, `P` FROM Location AS `L` JOIN Person AS `P` ON `P`.location_id = `L`.id WHERE (`L`.`org_id` = 3) UNION SELECT `L1`, `P1` FROM Person AS `P1` JOIN Location AS `L1` ON `P1`.location_id = `L1`.id WHERE (`P1`.`org_id` = 2)'],
];
}
public function testFilterOnFirstSelectedClass()
{
$sSourceOQL = 'SELECT `Person`, `Location` FROM Person AS `Person` JOIN Location AS `Location` ON `Person`.location_id = `Location`.id WHERE (`Location`.`id` = 1)';