/**
  *  Check that it merges all subtables into one blob entry
  *
  * @depends      testApi
  */
 public function test_checkArchiveRecords_shouldMergeSubtablesIntoOneRow()
 {
     $chunk = new Chunk();
     $tests = array('archive_blob_2010_01' => array($chunk->getRecordNameForTableId('CustomVariables_valueByName', 0) => 6, $chunk->getRecordNameForTableId('Referrers_keywordBySearchEngine', 0) => 1, $chunk->getRecordNameForTableId('Referrers_searchEngineByKeyword', 0) => 1), 'archive_blob_2009_12' => array($chunk->getRecordNameForTableId('CustomVariables_valueByName', 0) => 6, $chunk->getRecordNameForTableId('Referrers_keywordBySearchEngine', 0) => 1, $chunk->getRecordNameForTableId('Referrers_searchEngineByKeyword', 0) => 1));
     $numTests = 0;
     foreach ($tests as $table => $expectedSubtables) {
         foreach ($expectedSubtables as $name => $expectedNumSubtables) {
             $sql = "SELECT `value` FROM " . Common::prefixTable($table) . " WHERE `name` ='{$name}'";
             $blobs = Db::get()->fetchAll($sql);
             foreach ($blobs as $blob) {
                 $numTests++;
                 $blob = $blob['value'];
                 $blob = gzuncompress($blob);
                 $blob = unserialize($blob);
                 $countSubtables = count($blob);
                 $this->assertEquals($expectedNumSubtables, $countSubtables, "{$name} in {$table} expected to contain {$expectedNumSubtables} subtables, got {$countSubtables}");
             }
         }
     }
     // 6 _subtables entries + 6 _subtables entries for the segment
     $this->assertEquals(12, $numTests, "{$numTests} were executed but expected 12");
 }
 /**
  *  Check that requesting period "Range" means only processing
  *  the requested Plugin blob (Actions in this case), not all Plugins blobs
  *
  * @depends      testApi
  */
 public function test_checkArchiveRecords_shouldMergeSubtablesIntoOneRow()
 {
     $tests = array('archive_blob_2010_12' => 3, 'archive_blob_2011_01' => 3);
     $chunk = new Chunk();
     $chunkName = $chunk->getRecordNameForTableId('Actions_actions_url', 0);
     foreach ($tests as $table => $expectedNumSubtables) {
         $sql = "SELECT value FROM " . Common::prefixTable($table) . " WHERE period = " . Piwik::$idPeriods['range'] . " and `name` ='{$chunkName}'";
         $blob = Db::get()->fetchOne($sql);
         $blob = gzuncompress($blob);
         $blob = unserialize($blob);
         $countSubtables = count($blob);
         $this->assertEquals($expectedNumSubtables, $countSubtables, "Actions_actions_url_chunk_0_99 in {$table} expected to contain {$expectedNumSubtables} subtables, got {$countSubtables}");
     }
 }
Beispiel #3
0
 /**
  * @dataProvider getRecordNameForTableIdDataProvider
  */
 public function test_getRecordNameForTableId_shouldSplitChunksIntoBitsOf100($expectedChunk, $tableId)
 {
     $this->assertEquals($this->recordName . '_chunk_' . $expectedChunk, $this->chunk->getRecordNameForTableId($this->recordName, $tableId));
 }
 private function createManyDifferentArchiveBlobs()
 {
     $recordName1 = 'Actions_Actions';
     $recordName2 = 'Actions_Actionsurl';
     $chunk = new Chunk();
     $chunk0_1 = $chunk->getRecordNameForTableId($recordName1, 0);
     $chunk0_2 = $chunk->getRecordNameForTableId($recordName2, 0);
     $this->createArchiveBlobEntry('2013-01-01', array($recordName2 => 'test01'));
     $this->createArchiveBlobEntry('2013-01-02', array($recordName2 => 'test02', $recordName2 . '_1' => 'test1', $recordName2 . '_2' => 'test2', $recordName1 => 'actions_02', $chunk0_1 => serialize(array(1 => 'actionsSubtable1', 2 => 'actionsSubtable2', 5 => 'actionsSubtable5'))));
     $this->createArchiveBlobEntry('2013-01-03', array($recordName2 => 'test03', $chunk0_2 => serialize(array(1 => 'subtable1', 2 => 'subtable2', 5 => 'subtable5')), $recordName1 => 'actions_03', $recordName1 . '_1' => 'actionsTest1', $recordName1 . '_2' => 'actionsTest2'));
     $this->createArchiveBlobEntry('2013-01-04', array($recordName2 => 'test04', $recordName2 . '_5' => 'subtable45', $recordName2 . '_6' => 'subtable6'));
     $this->createArchiveBlobEntry('2013-01-06', array($recordName2 => 'test06', $chunk0_2 => serialize(array())));
 }
Beispiel #5
0
 /**
  * Queries and returns archive data using a set of archive IDs.
  *
  * @param array $archiveIds The IDs of the archives to get data from.
  * @param array $recordNames The names of the data to retrieve (ie, nb_visits, nb_actions, etc.)
  * @param string $archiveDataType The archive data type (either, 'blob' or 'numeric').
  * @param int|null|string $idSubtable  null if the root blob should be loaded, an integer if a subtable should be
  *                                     loaded and 'all' if all subtables should be loaded.
  * @throws Exception
  * @return array
  */
 public function getArchiveData($archiveIds, $recordNames, $archiveDataType, $idSubtable)
 {
     $chunk = new Chunk();
     // create the SQL to select archive data
     $loadAllSubtables = $idSubtable == CoreArchive::ID_SUBTABLE_LOAD_ALL_SUBTABLES;
     if ($loadAllSubtables) {
         $name = reset($recordNames);
         // select blobs w/ name like "$name_[0-9]+" w/o using RLIKE
         $nameEnd = strlen($name) + 1;
         $nameEndAppendix = $nameEnd + 1;
         $appendix = $chunk->getAppendix();
         $lenAppendix = strlen($appendix);
         $checkForChunkBlob = "SUBSTRING(name, {$nameEnd}, {$lenAppendix}) = '{$appendix}'";
         $checkForSubtableId = "(SUBSTRING(name, {$nameEndAppendix}, 1) >= '0'\n                                    AND SUBSTRING(name, {$nameEndAppendix}, 1) <= '9')";
         $whereNameIs = "(name = ? OR (name LIKE ? AND ( {$checkForChunkBlob} OR {$checkForSubtableId} ) ))";
         $bind = array($name, $name . '%');
     } else {
         if ($idSubtable === null) {
             // select root table or specific record names
             $bind = array_values($recordNames);
         } else {
             // select a subtable id
             $bind = array();
             foreach ($recordNames as $recordName) {
                 // to be backwards compatibe we need to look for the exact idSubtable blob and for the chunk
                 // that stores the subtables (a chunk stores many blobs in one blob)
                 $bind[] = $chunk->getRecordNameForTableId($recordName, $idSubtable);
                 $bind[] = ArchiveSelector::appendIdSubtable($recordName, $idSubtable);
             }
         }
         $inNames = Common::getSqlStringFieldsArray($bind);
         $whereNameIs = "name IN ({$inNames})";
     }
     $getValuesSql = "SELECT value, name, idsite, date1, date2, ts_archived\n                                FROM %s\n                                WHERE idarchive IN (%s)\n                                  AND " . $whereNameIs;
     // get data from every table we're querying
     $rows = array();
     foreach ($archiveIds as $period => $ids) {
         if (empty($ids)) {
             throw new Exception("Unexpected: id archive not found for period '{$period}' '");
         }
         // $period = "2009-01-04,2009-01-04",
         $date = Date::factory(substr($period, 0, 10));
         $isNumeric = $archiveDataType == 'numeric';
         if ($isNumeric) {
             $table = ArchiveTableCreator::getNumericTable($date);
         } else {
             $table = ArchiveTableCreator::getBlobTable($date);
         }
         $sql = sprintf($getValuesSql, $table, implode(',', $ids));
         $dataRows = $this->db->fetchAll($sql, $bind);
         foreach ($dataRows as $row) {
             if ($isNumeric) {
                 $rows[] = $row;
             } else {
                 $row['value'] = $this->uncompress($row['value']);
                 if ($chunk->isRecordNameAChunk($row['name'])) {
                     $this->moveChunkRowToRows($rows, $row, $chunk, $loadAllSubtables, $idSubtable);
                 } else {
                     $rows[] = $row;
                 }
             }
         }
     }
     return $rows;
 }