/**
  * Constructor
  * 
  * @param Zend_Db_Statement $stmt
  * @return void
  * @access public
  * @since 4/4/08
  */
 public function __construct(Zend_Db_Statement $stmt, $adapter)
 {
     $this->stmt = $stmt;
     $this->adapter = $adapter;
     // It seems that PDO only supports buffered queries on MySQL and it is
     // not recommended to use them even there. buffering therefore must be done
     // here rather than in the adapter layer.
     $this->stmt->setFetchMode(Zend_Db::FETCH_ASSOC);
     $this->rows = $this->stmt->fetchAll();
     $this->stmt->closeCursor();
 }
Example #2
0
 /**
  * @param  string $sql
  * @return void
  * @throws Zend_Db_Statement_Mysqli_Exception
  */
 public function _prepSql($sql)
 {
     parent::_prepSql($sql);
     $mysqli = $this->_adapter->getConnection();
     $this->_stmt = $mysqli->prepare($sql);
     if ($this->_stmt === false || $mysqli->errno) {
         /**
          * @see Zend_Db_Statement_Mysqli_Exception
          */
         require_once 'Zend/Db/Statement/Mysqli/Exception.php';
         throw new Zend_Db_Statement_Mysqli_Exception("Mysqli prepare error: " . $mysqli->error);
     }
 }
Example #3
0
 /**
  * Returns a specific record given it's offset/index
  * @param integer $offset Offset of record to fetch
  */
 public function offsetGet($offset)
 {
     // PDO does not support scrollable cursor for MySQL, so we can't use the cursor
     // and offset parameters of _statement->fetch().
     // Therefore, our only real option is to put a limit on the list temporarily and
     // then reset it.
     $previousLimitCount = $this->_select->getPart(Zend_Db_Select::LIMIT_COUNT);
     $previousLimitOffset = $this->_select->getPart(Zend_Db_Select::LIMIT_OFFSET);
     $this->limit(1, $offset);
     $this->_execute();
     $item = $this->_statement->fetch();
     $this->reset(Zend_Db_Select::LIMIT_COUNT);
     $this->reset(Zend_Db_Select::LIMIT_OFFSET);
     $this->limit($previousLimitCount, $previousLimitOffset);
     if ($item) {
         $class = $this->_class;
         return new $class($item, $this->tableName(), $this->_db);
     }
     return false;
 }
Example #4
0
 /**
  * Busca o próximo registro
  *
  * @param type $style
  * @param type $cursor
  * @param type $offset
  * @return boolean 
  */
 public function fetch($style = null, $cursor = null, $offset = null)
 {
     $this->_row = false;
     if ($this->_record instanceof Zend_Db_Statement) {
         $this->_row = $this->_record->fetch($style, $cursor, $offset);
     } else {
         if ($this->_index > -1 && $this->_index < count($this->_record)) {
             $this->_row = $this->_record[$this->_index];
             $this->_index++;
         }
     }
     if ($this->_row) {
         if (count($this->_replaceAlias)) {
             foreach ($this->_replaceAlias as $oldAlias => $newAlias) {
                 $this->_row[$newAlias] = $this->_row[$oldAlias];
                 unset($this->_row[$oldAlias]);
             }
         }
         if ($this->isRowFormated()) {
             $this->_formatRow($this->_row);
         }
     }
     return is_array($this->_row);
 }
Example #5
0
 /**
  * Returns an array containing all of the result set rows.
  *
  * @param int $style OPTIONAL Fetch mode.
  * @param int $col   OPTIONAL Column number, if fetch mode is by column.
  * @return array Collection of rows, each in a format by the fetch mode.
  *
  * Behaves like parent, but if limit()
  * is used, the final result removes the extra column
  * 'zend_db_rownum'
  */
 public function fetchAll($style = null, $col = null)
 {
     $data = parent::fetchAll($style, $col);
     $results = array();
     $remove = $this->_adapter->foldCase('ZEND_DB_ROWNUM');
     foreach ($data as $row) {
         if (is_array($row) && array_key_exists($remove, $row)) {
             unset($row[$remove]);
         }
         $results[] = $row;
     }
     return $results;
 }
Example #6
0
 /**
  * Prepare a statement handle.
  *
  * @param string $sql
  * @return void
  * @throws Zend_Db_Statement_Db2_Exception
  */
 public function _prepSql($sql)
 {
     Zend_Db_Statement::_prepSql($sql);
     $connection = $this->_connection->getConnection();
     $this->_stmt = db2_prepare($connection, $sql);
     if (!$this->_stmt) {
         require_once 'Zend/Db/Statement/Db2/Exception.php';
         throw new Zend_Db_Statement_Db2_Exception(db2_stmt_errormsg($this->_stmt), db2_stmt_error($this->_stmt));
     }
 }
Example #7
0
 /**
  * @param Zend_Db_Statement|PDOStatement $query
  * @param string|bool $fieldQueried
  * @param array $actionsTablesByType
  * @return int
  */
 public static function updateActionsTableWithRowQuery($query, $fieldQueried, &$actionsTablesByType)
 {
     $rowsProcessed = 0;
     while ($row = $query->fetch()) {
         //			var_dump($row);
         if (empty($row['idaction'])) {
             $row['type'] = $fieldQueried == 'idaction_url' ? Piwik_Tracker_Action::TYPE_ACTION_URL : Piwik_Tracker_Action::TYPE_ACTION_NAME;
             // This will be replaced with 'X not defined' later
             $row['name'] = '';
             // Yes, this is kind of a hack, so we don't mix 'page url not defined' with 'page title not defined' etc.
             $row['idaction'] = -$row['type'];
         }
         if ($row['type'] != Piwik_Tracker_Action::TYPE_SITE_SEARCH) {
             unset($row[Piwik_Archive::INDEX_SITE_SEARCH_HAS_NO_RESULT]);
         }
         // This will appear as <url /> in the API, which is actually very important to keep
         // eg. When there's at least one row in a report that does not have a URL, not having this <url/> would break HTML/PDF reports.
         $url = '';
         if ($row['type'] == Piwik_Tracker_Action::TYPE_SITE_SEARCH || $row['type'] == Piwik_Tracker_Action::TYPE_ACTION_NAME) {
             $url = null;
         } elseif (!empty($row['name']) && $row['name'] != Piwik_DataTable::LABEL_SUMMARY_ROW) {
             $url = Piwik_Tracker_Action::reconstructNormalizedUrl((string) $row['name'], $row['url_prefix']);
         }
         if (isset($row['name']) && isset($row['type'])) {
             $actionName = $row['name'];
             $actionType = $row['type'];
             $urlPrefix = $row['url_prefix'];
             $idaction = $row['idaction'];
             // in some unknown case, the type field is NULL, as reported in #1082 - we ignore this page view
             if (empty($actionType)) {
                 if ($idaction != Piwik_DataTable::LABEL_SUMMARY_ROW) {
                     self::setCachedActionRow($idaction, $actionType, false);
                 }
                 continue;
             }
             $actionRow = self::getActionRow($actionName, $actionType, $urlPrefix, $actionsTablesByType);
             self::setCachedActionRow($idaction, $actionType, $actionRow);
         } else {
             $actionRow = self::getCachedActionRow($row['idaction'], $row['type']);
             // Action processed as "to skip" for some reasons
             if ($actionRow === false) {
                 continue;
             }
         }
         if (is_null($actionRow)) {
             continue;
         }
         // Here we do ensure that, the Metadata URL set for a given row, is the one from the Pageview with the most hits.
         // This is to ensure that when, different URLs are loaded with the same page name.
         // For example http://piwik.org and http://id.piwik.org are reported in Piwik > Actions > Pages with /index
         // But, we must make sure http://piwik.org is used to link & for transitions
         // Note: this code is partly duplicated from Piwik_DataTable_Row->sumRowMetadata()
         if (!is_null($url) && !$actionRow->isSummaryRow()) {
             if (($existingUrl = $actionRow->getMetadata('url')) !== false) {
                 if (!empty($row[Piwik_Archive::INDEX_PAGE_NB_HITS]) && $row[Piwik_Archive::INDEX_PAGE_NB_HITS] > $actionRow->maxVisitsSummed) {
                     $actionRow->setMetadata('url', $url);
                     $actionRow->maxVisitsSummed = $row[Piwik_Archive::INDEX_PAGE_NB_HITS];
                 }
             } else {
                 $actionRow->setMetadata('url', $url);
                 $actionRow->maxVisitsSummed = !empty($row[Piwik_Archive::INDEX_PAGE_NB_HITS]) ? $row[Piwik_Archive::INDEX_PAGE_NB_HITS] : 0;
             }
         }
         unset($row['name']);
         unset($row['type']);
         unset($row['idaction']);
         unset($row['url_prefix']);
         foreach ($row as $name => $value) {
             // in some edge cases, we have twice the same action name with 2 different idaction
             // - this happens when 2 visitors visit the same new page at the same time, and 2 actions get recorded for the same name
             // - this could also happen when 2 URLs end up having the same label (eg. 2 subdomains get aggregated to the "/index" page name)
             if (($alreadyValue = $actionRow->getColumn($name)) !== false) {
                 $actionRow->setColumn($name, $alreadyValue + $value);
             } else {
                 $actionRow->addColumn($name, $value);
             }
         }
         // if the exit_action was not recorded properly in the log_link_visit_action
         // there would be an error message when getting the nb_hits column
         // we must fake the record and add the columns
         if ($actionRow->getColumn(Piwik_Archive::INDEX_PAGE_NB_HITS) === false) {
             // to test this code: delete the entries in log_link_action_visit for
             //  a given exit_idaction_url
             foreach (self::getDefaultRow()->getColumns() as $name => $value) {
                 $actionRow->addColumn($name, $value);
             }
         }
         $rowsProcessed++;
     }
     // just to make sure php copies the last $actionRow in the $parentTable array
     $actionRow =& $actionsTablesByType;
     return $rowsProcessed;
 }
 /**
  * Create the new index records for the indexer entity
  *
  * @param Zend_Db_Statement $stmt
  * @return void
  */
 protected function _insertIndexRecords(Zend_Db_Statement $stmt)
 {
     Varien_Profiler::start($this->_getProfilerName() . '::reindexEntity::insert');
     $entityId = null;
     $data = $storesHandled = $entityDefaultGroupsWithoutMode = array();
     while ($row = $stmt->fetch()) {
         $this->_prepareRow($row);
         // A new entity is being handled
         if ($entityId !== $row['entity_id']) {
             // Add missing store id records to the insert data array for the previous entity id
             // That is why we skip this condition on the first iteration.
             // We need to do this last because then $storesHandled is set completely for the $entityId
             if (null !== $entityId) {
                 $this->_addMissingStoreRecords($data, $entityId, $entityDefaultGroupsWithoutMode, $storesHandled);
                 // Insert INSERT_CHUNK_SIZE records at a time.
                 // If INSERT_CHUNK_SIZE records exist in $data then it is reset to an empty array afterwards
                 $this->_insertIndexRecordsIfMinChunkSizeReached($data, self::INSERT_CHUNK_SIZE);
             }
             // Set new entity as default
             $entityId = $row['entity_id'];
             // Set default groups for new entity (store id 0 is the first one for each entity in $result).
             // List of raw attribute value group ids without the store mode settings applied.
             $entityDefaultGroupsWithoutMode = $row['orig_group_ids'];
             // Reset stores handled for new entity to empty list
             $storesHandled = array();
             // We don't need an index entry for store id 0, simply use it as the default
             continue;
         }
         // Don't include stores in the index where the module is disabled anyway
         if ($this->_isModuleDisabledInStore($row['store_id'])) {
             continue;
         }
         // Add index record for each group id
         foreach ($row['group_ids'] as $groupId) {
             $data[] = array('catalog_entity_id' => $row['entity_id'], 'group_id' => $groupId, 'store_id' => $row['store_id']);
             $storesHandled[] = $row['store_id'];
         }
     }
     // Check if at least one entity record was found. If not, $entityId will be null
     if ($entityId) {
         // The last iterations over $result will probably not have hit the >= INSERT_CHUNK_SIZE mark,
         // so we still need to insert these, too.
         // Add missing store id records to the insert data array for the last $entityId
         $this->_addMissingStoreRecords($data, $entityId, $entityDefaultGroupsWithoutMode, $storesHandled);
         // Insert missing index records
         $this->_insertIndexRecordsIfMinChunkSizeReached($data, 1);
     }
     Varien_Profiler::stop($this->_getProfilerName() . '::reindexEntity::insert');
 }
Example #9
0
 /**
  * @param Zend_Db_Statement|PDOStatement $query
  * @param string|bool $fieldQueried
  * @return int
  */
 protected function updateActionsTableWithRowQuery($query, $fieldQueried = false)
 {
     $rowsProcessed = 0;
     while ($row = $query->fetch()) {
         if (empty($row['idaction'])) {
             $row['type'] = $fieldQueried == 'idaction_url' ? Piwik_Tracker_Action::TYPE_ACTION_URL : Piwik_Tracker_Action::TYPE_ACTION_NAME;
             // This will be replaced with 'X not defined' later
             $row['name'] = '';
             // Yes, this is kind of a hack, so we don't mix 'page url not defined' with 'page title not defined' etc.
             $row['idaction'] = -$row['type'];
         }
         // Only the first query will contain the name and type of actions, for performance reasons
         if (isset($row['name']) && isset($row['type'])) {
             $actionName = $row['name'];
             $actionType = $row['type'];
             $urlPrefix = $row['url_prefix'];
             // in some unknown case, the type field is NULL, as reported in #1082 - we ignore this page view
             if (empty($actionType)) {
                 self::$cacheParsedAction[$row['idaction']] = false;
                 continue;
             }
             $currentTable = $this->parseActionNameCategoriesInDataTable($actionName, $actionType, $urlPrefix);
             self::$cacheParsedAction[$row['idaction']] = $currentTable;
         } else {
             if (!isset(self::$cacheParsedAction[$row['idaction']])) {
                 // This can happen when
                 // - We select an entry page ID that was only seen yesterday, so wasn't selected in the first query
                 // - We count time spent on a page, when this page was only seen yesterday
                 continue;
             }
             $currentTable = self::$cacheParsedAction[$row['idaction']];
             // Action processed as "to skip" for some reasons
             if ($currentTable === false) {
                 continue;
             }
         }
         unset($row['name']);
         unset($row['type']);
         unset($row['idaction']);
         unset($row['url_prefix']);
         foreach ($row as $name => $value) {
             // in some edge cases, we have twice the same action name with 2 different idaction
             // this happens when 2 visitors visit the same new page at the same time, there is a SELECT and an INSERT for each new page,
             // and in between the two the other visitor comes.
             // here we handle the case where there is already a row for this action name, if this is the case we add the value
             if (($alreadyValue = $currentTable->getColumn($name)) !== false) {
                 $currentTable->setColumn($name, $alreadyValue + $value);
             } else {
                 $currentTable->addColumn($name, $value);
             }
         }
         // if the exit_action was not recorded properly in the log_link_visit_action
         // there would be an error message when getting the nb_hits column
         // we must fake the record and add the columns
         if ($currentTable->getColumn(Piwik_Archive::INDEX_PAGE_NB_HITS) === false) {
             // to test this code: delete the entries in log_link_action_visit for
             //  a given exit_idaction_url
             foreach ($this->defaultRow->getColumns() as $name => $value) {
                 $currentTable->addColumn($name, $value);
             }
         }
         $rowsProcessed++;
     }
     // just to make sure php copies the last $currentTable in the $parentTable array
     $currentTable =& $this->actionsTablesByType;
     return $rowsProcessed;
 }