N°3618 - Count on union with different conditions fails (Fix multi-column attributes sql generation)

This commit is contained in:
Eric
2021-02-05 10:15:14 +01:00
parent a5894c1a4c
commit f07f0ba1c7
4 changed files with 101 additions and 22 deletions

View File

@@ -1672,6 +1672,35 @@ class FieldExpression extends UnaryExpression
// Has been resolved into an SQL expression
class FieldExpressionResolved extends FieldExpression
{
protected $m_aAdditionalExpressions;
public function __construct($mExpression, $sParent = '')
{
$this->m_aAdditionalExpressions = array();
if (is_array($mExpression))
{
foreach ($mExpression as $sSuffix => $sExpression)
{
if ($sSuffix == '')
{
$sName = $sExpression;
}
$this->m_aAdditionalExpressions[$sSuffix] = new FieldExpressionResolved($sExpression, $sParent);
}
}
else
{
$sName = $mExpression;
}
parent::__construct($sName, $sParent);
}
public function AdditionalExpressions()
{
return $this->m_aAdditionalExpressions;
}
public function GetUnresolvedFields($sAlias, &$aUnresolved)
{
}

View File

@@ -178,6 +178,14 @@ class QueryBuilderExpressions
foreach ($this->m_aSelectExpr as $sColAlias => $oExpr)
{
$this->m_aSelectExpr[$sColAlias] = $oExpr->Translate($aTranslationData, $bMatchAll, $bMarkFieldsAsResolved);
if ($this->m_aSelectExpr[$sColAlias] instanceof FieldExpressionResolved)
{
// Split the field with the relevant alias
foreach ($this->m_aSelectExpr[$sColAlias]->AdditionalExpressions() as $sSuffix => $oAdditionalExpr)
{
$this->m_aSelectExpr[$sColAlias.$sSuffix] = $oAdditionalExpr->Translate($aTranslationData, $bMatchAll, $bMarkFieldsAsResolved);
}
}
}
if ($this->m_aGroupByExpr)
{

View File

@@ -239,24 +239,16 @@ class SQLObjectQueryBuilder
continue;
}
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
foreach ($oAttDef->GetSQLExpressions() as $sColId => $sSQLExpr)
$oFieldSQLExp = new FieldExpressionResolved($oAttDef->GetSQLExpressions(), $sClassAlias);
/**
* @var string $sPluginClass
* @var iQueryModifier $oQueryModifier
*/
foreach (MetaModel::EnumPlugins('iQueryModifier') as $sPluginClass => $oQueryModifier)
{
if (!empty($sColId))
{
// Multi column attributes
$oBuild->m_oQBExpressions->AddSelect($sSelectedClassAlias.$sAttCode.$sColId, new FieldExpression($sAttCode.$sColId, $sClassAlias));
}
$oFieldSQLExp = new FieldExpressionResolved($sSQLExpr, $sClassAlias);
/**
* @var string $sPluginClass
* @var iQueryModifier $oQueryModifier
*/
foreach (MetaModel::EnumPlugins('iQueryModifier') as $sPluginClass => $oQueryModifier)
{
$oFieldSQLExp = $oQueryModifier->GetFieldExpression($oBuild, $sClass, $sAttCode, $sColId, $oFieldSQLExp, $oBaseSQLQuery);
}
$aTranslation[$sClassAlias][$sAttCode.$sColId] = $oFieldSQLExp;
$oFieldSQLExp = $oQueryModifier->GetFieldExpression($oBuild, $sClass, $sAttCode, '', $oFieldSQLExp, $oBaseSQLQuery);
}
$aTranslation[$sClassAlias][$sAttCode] = $oFieldSQLExp;
}
// Translate the selected columns

View File

@@ -50,6 +50,7 @@ class OQLTest extends ItopDataTestCase
/**
* @dataProvider NestedQueryProvider
* @depends testOQLSetup
*
* @param $sQuery
*
@@ -435,9 +436,7 @@ class OQLTest extends ItopDataTestCase
{
return [
'Bug 3660 1' => [
"SELECT UserRequest AS U
JOIN lnkContactToTicket AS l ON l.ticket_id=U.id
JOIN Team AS T ON l.contact_id=T.id",
"SELECT UserRequest AS U JOIN lnkContactToTicket AS l ON l.ticket_id=U.id JOIN Team AS T ON l.contact_id=T.id",
"SELECT `U` FROM `UserRequest` AS `U`
INNER JOIN `lnkContactToTicket` AS `l`
ON `U`.`id` = `l`.`ticket_id`
@@ -445,13 +444,64 @@ class OQLTest extends ItopDataTestCase
ON `l`.`contact_id` = `T`.`id`",
],
'Bug 3660 2' => [
"SELECT UserRequest AS U
JOIN lnkContactToTicket AS l ON l.ticket_id=U.id
JOIN Contact AS C ON l.contact_id=C.id",
"SELECT UserRequest AS U JOIN lnkContactToTicket AS l ON l.ticket_id=U.id JOIN Contact AS C ON l.contact_id=C.id",
"SELECT `U` FROM `UserRequest` AS `U`
INNER JOIN `lnkContactToTicket` AS `l`
ON `U`.`id` = `l`.`ticket_id`",
],
];
}
/**
* @dataProvider MakeSelectQueryForCountProvider
*
* @param $sOQL
* @param $sExpectedSQL
*
* @throws \CoreException
* @throws \MissingQueryArgument
* @throws \OQLException
*/
public function testMakeSelectQueryForCount($sOQL, $sExpectedSQL)
{
$oFilter = DBSearch::FromOQL($sOQL);
// Avoid adding all the fields for counts or "group by" requests
$aCountAttToLoad = array();
$sMainClass = null;
foreach ($oFilter->GetSelectedClasses() as $sClassAlias => $sClass) {
$aCountAttToLoad[$sClassAlias] = array();
if (empty($sMainClass)) {
$sMainClass = $sClass;
}
}
$sSQL = $oFilter->MakeSelectQuery([], [], $aCountAttToLoad, null, 0, 0, true);
static::assertEquals($sExpectedSQL, $sSQL);
}
public function MakeSelectQueryForCountProvider()
{
return [
'Bug 3618' => [
"SELECT UserRequest WHERE private_log LIKE '%Auteur : %' UNION SELECT Problem",
"SELECT COUNT(*) AS COUNT FROM (SELECT
1
FROM (
SELECT
DISTINCT `UserRequest_Ticket`.`id` AS `UserRequestid`
FROM
`ticket` AS `UserRequest_Ticket`
WHERE ((`UserRequest_Ticket`.`private_log` LIKE '%Auteur : %') AND COALESCE((`UserRequest_Ticket`.`finalclass` IN ('UserRequest')), 1))
UNION
SELECT
DISTINCT `Problem`.`id` AS `Problemid`
FROM
`ticket_problem` AS `Problem`
WHERE 1
) as __selects__
) AS _union_alderaan_",
],
];
}
}