/** * * * @param * * @return */ protected static function findNoIndex($parameters) { $dbConnection = Main\HttpApplication::getConnection(); $dbHelper = $dbConnection->getSqlHelper(); // tables $locationTable = Location\LocationTable::getTableName(); $locationNameTable = Location\Name\LocationTable::getTableName(); $locationGroupTable = Location\GroupLocationTable::getTableName(); $locationSiteTable = Location\SiteLocationTable::getTableName(); $locationTypeTable = Location\TypeTable::getTableName(); ////////////////////////////////// // sql parameters prepare ////////////////////////////////// $filter = static::parseFilter($parameters['filter']); if (strlen($filter['SITE_ID']['VALUE'])) { $filterSite = $dbHelper->forSql(substr($filter['SITE_ID']['VALUE'], 0, 2)); $hasLocLinks = Location\SiteLocationTable::checkLinkUsage($filterSite, Location\SiteLocationTable::DB_LOCATION_FLAG); $hasGrpLinks = Location\SiteLocationTable::checkLinkUsage($filterSite, Location\SiteLocationTable::DB_GROUP_FLAG); $doFilterBySite = true; } if (strlen($filter['PHRASE']['VALUE'])) { $doFilterByName = true; $filterName = ToUpper($dbHelper->forSql($filter['PHRASE']['VALUE'])); } if (intval($filter['ID']['VALUE'])) { $doFilterById = true; $filterId = intval($filter['ID']['VALUE']); } if (intval($filter['CODE']['VALUE'])) { $doFilterByCode = true; $filterCode = $dbHelper->forSql($filter['CODE']['VALUE']); } $doFilterByLang = true; if (strlen($filter['NAME.LANGUAGE_ID']['VALUE'])) { $filterLang = $dbHelper->forSql(substr($filter['NAME.LANGUAGE_ID']['VALUE'], 0, 2)); } else { $filterLang = LANGUAGE_ID; } if (isset($filter['PARENT_ID']) && intval($filter['PARENT_ID']['VALUE']) >= 0) { $doFilterByParent = true; $filterParentId = intval($filter['PARENT_ID']['VALUE']); } if (intval($filter['TYPE_ID']['VALUE'])) { $doFilterByType = true; $filterTypeId = intval($filter['TYPE_ID']['VALUE']); } // filter select fields if (!is_array($parameters['select'])) { $parameters['select'] = array(); } $map = Location\LocationTable::getMap(); $nameAlias = false; foreach ($parameters['select'] as $alias => $field) { if ($field == 'CHILD_CNT') { $doCountChildren = true; } if ($field == 'NAME.NAME') { $nameAlias = $alias; } if (!isset($map[$field]) || !in_array($map[$field]['data_type'], array('integer', 'string', 'float', 'boolean')) || isset($map[$field]['expression'])) { unset($parameters['select'][$alias]); } } ////////////////////////////////// // sql query build ////////////////////////////////// // mandatory fields to be selected anyway // alias => field $fields = array('L.ID' => 'L.ID', 'L.CODE' => 'L.CODE', 'L.SORT' => 'L.SORT', 'LT_SORT' => 'LT.DISPLAY_SORT'); if ($nameAlias === false || !preg_match('#^[a-zA-Z0-9]+$#', $nameAlias)) { $fields['NAME'] = 'LN.NAME'; } else { $fields[$nameAlias] = 'LN.NAME'; } $fields = array_merge($fields, array('L.LEFT_MARGIN' => 'L.LEFT_MARGIN', 'L.RIGHT_MARGIN' => 'L.RIGHT_MARGIN')); $groupFields = $fields; // additional fields to select foreach ($parameters['select'] as $alias => $fld) { $lFld = 'L.' . $fld; // check if field is already selected if ((string) $alias === (string) intval($alias)) { // already selected if (in_array($lFld, $fields)) { continue; } $fields[$lFld] = $lFld; //$groupFields[$lFld] = $lFld; } else { if (isset($fields[$alias])) { continue; } $fields[$alias] = $lFld; //$groupFields[$alias] = $lFld; } $groupFields[$lFld] = $lFld; } if ($doCountChildren) { $fields['CHILD_CNT'] = 'COUNT(LC.ID)'; } // make select sql $selectSql = array(); foreach ($fields as $alias => $fld) { if ($fld == $alias) { $selectSql[] = $fld; } else { $selectSql[] = $fld . ' as ' . $alias; } } $selectSql = implode(', ', $selectSql); //$groupSql = implode(', ', array_keys($groupFields)); $groupSql = implode(', ', $groupFields); $mainSql = "select {$selectSql}\n\t\t\t\t\t\tfrom {$locationTable} L \n\t\t\t\t\t\t\tinner join {$locationNameTable} LN on L.ID = LN.LOCATION_ID\n\t\t\t\t\t\t\tinner join {$locationTypeTable} LT on L.TYPE_ID = LT.ID " . ($doCountChildren ? "\n\t\t\t\t\t\t\t\tleft join {$locationTable} LC on L.ID = LC.PARENT_ID\n\t\t\t\t\t\t\t" : "") . " \n\n\t\t\t\t\t\t%SITE_FILTER_CONDITION%\n\n\t\t\t\t\t\twhere \n\n\t\t\t\t\t\t\t%MAIN_FILTER_CONDITION%\n\n\t\t\t\t\t\t\t%GROUP_BY%\n\t\t\t\t\t\t\t"; $where = array(); if ($doFilterByLang) { $where[] = "LN.LANGUAGE_ID = '" . $filterLang . "'"; } if ($doFilterByParent) { $where[] = "L.PARENT_ID = '" . $filterParentId . "'"; } if ($doFilterById) { $where[] = "L.ID = '" . $filterId . "'"; } if ($doFilterByCode) { $where[] = "L.CODE = '" . $filterCode . "'"; } if ($doFilterByType) { $where[] = "L.TYPE_ID = '" . $filterTypeId . "'"; } if ($doFilterByName) { $where[] = "LN.NAME_UPPER like '" . $filterName . "%'"; } $mainSql = str_replace('%MAIN_FILTER_CONDITION%', implode(' and ', $where), $mainSql); $needDistinct = false; $unionized = false; $artificialNav = false; if (!$doFilterBySite) { $sql = str_replace('%SITE_FILTER_CONDITION%', '', $mainSql); } else { $sql = array(); if ($hasLocLinks) { $sql[] = str_replace('%SITE_FILTER_CONDITION%', "\n\n\t\t\t\t\tinner join {$locationTable} L2 on L2.LEFT_MARGIN <= L.LEFT_MARGIN and L2.RIGHT_MARGIN >= L.RIGHT_MARGIN\n\t\t\t\t\tinner join {$locationSiteTable} LS2 on L2.ID = LS2.LOCATION_ID and LS2.LOCATION_TYPE = 'L' and LS2.SITE_ID = '{$filterSite}'\n\n\t\t\t\t", $mainSql); } if ($hasGrpLinks) { $sql[] = str_replace('%SITE_FILTER_CONDITION%', "\n\n\t\t\t\t\tinner join {$locationTable} L2 on L2.LEFT_MARGIN <= L.LEFT_MARGIN and L2.RIGHT_MARGIN >= L.RIGHT_MARGIN\n\t\t\t\t\tinner join {$locationGroupTable} LG on LG.LOCATION_ID = L2.ID\n\t\t\t\t\tinner join {$locationSiteTable} LS2 on LG.LOCATION_GROUP_ID = LS2.LOCATION_ID and LS2.LOCATION_TYPE = 'G' and LS2.SITE_ID = '{$filterSite}'\n\n\t\t\t\t", $mainSql); $useDistinct = true; } $cnt = count($sql); if ($cnt == 1) { $needDistinct = true; } else { // UNION removes duplicates, so distinct is required only when no union here $unionized = true; } $sql = ($cnt > 1 ? '(' : '') . implode(') union (', $sql) . ($cnt > 1 ? ')' : ''); } // set groupping if needed $sql = str_replace('%GROUP_BY%', $needDistinct || $doCountChildren ? "group by {$groupSql}" : '', $sql); if (!is_array($parameters['order'])) { $sql .= " order by 3, 4 asc, 5"; } else { // currenly spike if (isset($parameters['order']['NAME.NAME'])) { $sql .= " order by 5 " . ($parameters['order']['NAME.NAME'] == 'asc' ? 'asc' : 'desc'); } } $offset = intval($parameters['offset']); $limit = intval($parameters['limit']); if ($limit) { if ($dbConnection->getType() == 'mssql') { // due to huge amount of limitations of windowed functions in transact, using artificial nav here // (does not support UNION and integer indices in ORDER BY) $artificialNav = true; } else { $sql = $dbHelper->getTopSql($sql, $limit, $offset); } } $res = $dbConnection->query($sql); if ($artificialNav) { $result = array(); $i = -1; while ($item = $res->fetch()) { $i++; if ($i < $offset) { continue; } if ($i >= $offset + $limit) { break; } $result[] = $item; } return new DB\ArrayResult($result); } else { return $res; } }