public static function QueryToArray($sSql) { $aData = array(); $oKPI = new ExecutionKPI(); try { $oResult = self::$m_oMysqli->query($sSql); } catch (mysqli_sql_exception $e) { $oKPI->ComputeStats('Query exec (mySQL)', $sSql); MySQLException('Failed to issue SQL query', array('query' => $sSql, $e)); } $oKPI->ComputeStats('Query exec (mySQL)', $sSql); if ($oResult === false) { throw new MySQLException('Failed to issue SQL query', array('query' => $sSql)); } while ($aRow = $oResult->fetch_array(MYSQLI_BOTH)) { $aData[] = $aRow; } $oResult->free(); return $aData; }
public function ToArgs($sArgName = 'this') { if (is_null($this->m_aAsArgs)) { $oKPI = new ExecutionKPI(); $aScalarArgs = $this->ToArgsForQuery($sArgName); $aScalarArgs[$sArgName] = $this->GetKey(); $aScalarArgs[$sArgName . '->id'] = $this->GetKey(); $aScalarArgs[$sArgName . '->hyperlink()'] = $this->GetHyperlink('iTopStandardURLMaker', false); $aScalarArgs[$sArgName . '->hyperlink(portal)'] = $this->GetHyperlink('PortalURLMaker', false); $aScalarArgs[$sArgName . '->name()'] = $this->GetName(); $sClass = get_class($this); foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) { if ($oAttDef instanceof AttributeCaseLog) { $oCaseLog = $this->Get($sAttCode); $aScalarArgs[$sArgName . '->' . $sAttCode] = $oCaseLog->GetText(); $sHead = $oCaseLog->GetLatestEntry(); $aScalarArgs[$sArgName . '->head(' . $sAttCode . ')'] = $sHead; $aScalarArgs[$sArgName . '->head_html(' . $sAttCode . ')'] = '<div class="caselog_entry">' . str_replace(array("\r\n", "\n", "\r"), "<br/>", htmlentities($sHead, ENT_QUOTES, 'UTF-8')) . '</div>'; $aScalarArgs[$sArgName . '->html(' . $sAttCode . ')'] = $oCaseLog->GetAsEmailHtml(); } elseif ($oAttDef->IsScalar()) { $aScalarArgs[$sArgName . '->' . $sAttCode] = $this->Get($sAttCode); // #@# Note: This has been proven to be quite slow, this can slow down bulk load $sAsHtml = $this->GetAsHtml($sAttCode); $aScalarArgs[$sArgName . '->html(' . $sAttCode . ')'] = $sAsHtml; $aScalarArgs[$sArgName . '->label(' . $sAttCode . ')'] = $this->GetEditValue($sAttCode); // "Nice" display value, but without HTML tags and entities } elseif ($oAttDef->IsLinkSet()) { $sRemoteName = $oAttDef->IsIndirect() ? $oAttDef->GetExtKeyToRemote() . '_friendlyname' : 'friendlyname'; $oLinkSet = clone $this->Get($sAttCode); // Workaround/Safety net for Trac #887 $iLimit = MetaModel::GetConfig()->Get('max_linkset_output'); if ($iLimit > 0) { $oLinkSet->SetLimit($iLimit); } $aNames = $oLinkSet->GetColumnAsArray($sRemoteName); if ($iLimit > 0) { $iTotal = $oLinkSet->Count(); if ($iTotal > count($aNames)) { $aNames[] = '... ' . Dict::Format('UI:TruncatedResults', count($aNames), $iTotal); } } $sNames = implode("\n", $aNames); $aScalarArgs[$sArgName . '->' . $sAttCode] = $sNames; $aScalarArgs[$sArgName . '->html(' . $sAttCode . ')'] = '<ul><li>' . implode("</li><li>", $aNames) . '</li></ul>'; } } $this->m_aAsArgs = $aScalarArgs; $oKPI->ComputeStats('ToArgs', get_class($this)); } return $this->m_aAsArgs; }
protected function GetSQLQuery($aOrderBy, $aArgs, $aAttToLoad, $aExtendedDataSpec, $iLimitCount, $iLimitStart, $bGetCount, $aGroupByExpr = null) { // Hide objects that are not visible to the current user // $oSearch = $this; if (!$this->IsAllDataAllowed() && !$this->IsDataFiltered()) { $oVisibleObjects = UserRights::GetSelectFilter($this->GetClass(), $this->GetModifierProperties('UserRightsGetSelectFilter')); if ($oVisibleObjects === false) { // Make sure this is a valid search object, saying NO for all $oVisibleObjects = DBObjectSearch::FromEmptySet($this->GetClass()); } if (is_object($oVisibleObjects)) { $oSearch = $this->Intersect($oVisibleObjects); $oSearch->SetDataFiltered(); } else { // should be true at this point, meaning that no additional filtering // is required } } // Compute query modifiers properties (can be set in the search itself, by the context, etc.) // $aModifierProperties = MetaModel::MakeModifierProperties($oSearch); // Create a unique cache id // if (self::$m_bQueryCacheEnabled || self::$m_bTraceQueries) { // Need to identify the query $sOqlQuery = $oSearch->ToOql(); if (count($aModifierProperties)) { array_multisort($aModifierProperties); $sModifierProperties = json_encode($aModifierProperties); } else { $sModifierProperties = ''; } $sRawId = $sOqlQuery . $sModifierProperties; if (!is_null($aAttToLoad)) { $sRawId .= json_encode($aAttToLoad); } if (!is_null($aGroupByExpr)) { foreach ($aGroupByExpr as $sAlias => $oExpr) { $sRawId .= 'g:' . $sAlias . '!' . $oExpr->Render(); } } $sRawId .= $bGetCount; $sOqlId = md5($sRawId); } else { $sOqlQuery = "SELECTING... " . $oSearch->GetClass(); $sOqlId = "query id ? n/a"; } // Query caching // if (self::$m_bQueryCacheEnabled) { // Warning: using directly the query string as the key to the hash array can FAIL if the string // is long and the differences are only near the end... so it's safer (but not bullet proof?) // to use a hash (like md5) of the string as the key ! // // Example of two queries that were found as similar by the hash array: // SELECT SLT JOIN lnkSLTToSLA AS L1 ON L1.slt_id=SLT.id JOIN SLA ON L1.sla_id = SLA.id JOIN lnkContractToSLA AS L2 ON L2.sla_id = SLA.id JOIN CustomerContract ON L2.contract_id = CustomerContract.id WHERE SLT.ticket_priority = 1 AND SLA.service_id = 3 AND SLT.metric = 'TTO' AND CustomerContract.customer_id = 2 // and // SELECT SLT JOIN lnkSLTToSLA AS L1 ON L1.slt_id=SLT.id JOIN SLA ON L1.sla_id = SLA.id JOIN lnkContractToSLA AS L2 ON L2.sla_id = SLA.id JOIN CustomerContract ON L2.contract_id = CustomerContract.id WHERE SLT.ticket_priority = 1 AND SLA.service_id = 3 AND SLT.metric = 'TTR' AND CustomerContract.customer_id = 2 // the only difference is R instead or O at position 285 (TTR instead of TTO)... // if (array_key_exists($sOqlId, self::$m_aQueryStructCache)) { // hit! $oSQLQuery = unserialize(serialize(self::$m_aQueryStructCache[$sOqlId])); // Note: cloning is not enough because the subtree is made of objects } elseif (self::$m_bUseAPCCache) { // Note: For versions of APC older than 3.0.17, fetch() accepts only one parameter // $sOqlAPCCacheId = 'itop-' . MetaModel::GetEnvironmentId() . '-query-cache-' . $sOqlId; $oKPI = new ExecutionKPI(); $result = apc_fetch($sOqlAPCCacheId); $oKPI->ComputeStats('Query APC (fetch)', $sOqlQuery); if (is_object($result)) { $oSQLQuery = $result; self::$m_aQueryStructCache[$sOqlId] = $oSQLQuery; } } } if (!isset($oSQLQuery)) { $oKPI = new ExecutionKPI(); $oSQLQuery = $oSearch->MakeSQLQuery($aAttToLoad, $bGetCount, $aModifierProperties, $aGroupByExpr); $oSQLQuery->SetSourceOQL($sOqlQuery); $oKPI->ComputeStats('MakeSQLQuery', $sOqlQuery); if (self::$m_bQueryCacheEnabled) { if (self::$m_bUseAPCCache) { $oKPI = new ExecutionKPI(); apc_store($sOqlAPCCacheId, $oSQLQuery, self::$m_iQueryCacheTTL); $oKPI->ComputeStats('Query APC (store)', $sOqlQuery); } self::$m_aQueryStructCache[$sOqlId] = $oSQLQuery->DeepClone(); } } // Join to an additional table, if required... // if ($aExtendedDataSpec != null) { $sTableAlias = '_extended_data_'; $aExtendedFields = array(); foreach ($aExtendedDataSpec['fields'] as $sColumn) { $sColRef = $oSearch->GetClassAlias() . '_extdata_' . $sColumn; $aExtendedFields[$sColRef] = new FieldExpressionResolved($sColumn, $sTableAlias); } $oSQLQueryExt = new SQLObjectQuery($aExtendedDataSpec['table'], $sTableAlias, $aExtendedFields); $oSQLQuery->AddInnerJoin($oSQLQueryExt, 'id', $aExtendedDataSpec['join_key']); } return $oSQLQuery; }
public final function CheckToWrite() { if (MetaModel::SkipCheckToWrite()) { return array(true, array()); } if (is_null($this->m_bCheckStatus)) { $this->m_aCheckIssues = array(); $oKPI = new ExecutionKPI(); $this->DoCheckToWrite(); $oKPI->ComputeStats('CheckToWrite', get_class($this)); if (count($this->m_aCheckIssues) == 0) { $this->m_bCheckStatus = true; } else { $this->m_bCheckStatus = false; } } return array($this->m_bCheckStatus, $this->m_aCheckIssues, $this->m_bSecurityIssue); }