From c494848d03b5dc76e698b28aeb3c3f7301bdb2f5 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Roland=20H=C3=A4der?= Date: Fri, 22 Feb 2013 07:36:43 +0000 Subject: [PATCH] Fixed handling of cache keys as empty results caused cache keys to exist. :( --- .../interfaces/cache/class_Cacheable.php | 8 ++-- inc/classes/main/cache/class_MemoryCache.php | 26 +++++++++++-- .../main/criteria/class_BaseCriteria.php | 2 +- .../criteria/search/class_SearchCriteria.php | 26 ++++++------- .../database/class_BaseDatabaseWrapper.php | 4 +- .../databases/class_LocalFileDatabase.php | 38 ++++++++++++++++--- .../main/result/class_DatabaseResult.php | 10 +++++ 7 files changed, 86 insertions(+), 28 deletions(-) diff --git a/inc/classes/interfaces/cache/class_Cacheable.php b/inc/classes/interfaces/cache/class_Cacheable.php index de4c30ae..d02c35a0 100644 --- a/inc/classes/interfaces/cache/class_Cacheable.php +++ b/inc/classes/interfaces/cache/class_Cacheable.php @@ -25,10 +25,12 @@ interface Cacheable extends FrameworkInterface { /** * Does the specified offset exist in cache? * - * @param $offset The offset we are looking for - * @return $exists Whether the offset exists + * @param $offset The offset we are looking for + * @param $arrayElement If type is array, then this element must be found + * @param $minimumCount If array element is found then this count must at least match + * @return $exists Whether the offset exists */ - function offsetExists($offset); + function offsetExists($offset, $arrayElement = NULL, $minimumCount = 0); /** * Setter for cache offset diff --git a/inc/classes/main/cache/class_MemoryCache.php b/inc/classes/main/cache/class_MemoryCache.php index 55bf24db..7f254d33 100644 --- a/inc/classes/main/cache/class_MemoryCache.php +++ b/inc/classes/main/cache/class_MemoryCache.php @@ -66,11 +66,31 @@ class MemoryCache extends BaseFrameworkSystem implements Cacheable { /** * Does the specified offset exist in cache? * - * @param $offset The offset we are looking for - * @return $exists Whether the offset exists + * @param $offset The offset we are looking for + * @param $arrayElement If type is array, then this element must be found + * @param $minimumCount If array element is found then this count must at least match + * @return $exists Whether the offset exists */ - public function offsetExists ($offset) { + public function offsetExists ($offset, $arrayElement = NULL, $minimumCount = 0) { + // Is it there? $exists = $this->dataCache->offsetExists($offset); + + // So look for array element? + if (($exists === TRUE) && (!is_null($arrayElement))) { + // Get it + $array = $this->offetget($offset); + + // Is it an array and element is found? + if ((is_array($array)) && (isset($array[$arrayElement]))) { + // Is an array and element is found, so check count + $exists = (count($array[$arrayElement]) >= $minimumCount); + } else { + // Not found + $exists = FALSE; + } + } // END - if + + // Return status return $exists; } diff --git a/inc/classes/main/criteria/class_BaseCriteria.php b/inc/classes/main/criteria/class_BaseCriteria.php index b0edb27d..d02c32fc 100644 --- a/inc/classes/main/criteria/class_BaseCriteria.php +++ b/inc/classes/main/criteria/class_BaseCriteria.php @@ -154,7 +154,7 @@ class BaseCriteria extends BaseFrameworkSystem implements Criteria { $criteriaKey = $this->convertDashesToUnderscores($criteriaKey); // Debug message - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(strtoupper($criteriaType) . '(' . $this->__toString() . ')-CRITERIA[' . __LINE__ . ']: criteriaKey=' . $criteriaKey . ',criteriaValue=' . $criteriaValue); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(strtoupper($criteriaType) . '(' . $this->__toString() . ')-CRITERIA[' . __LINE__ . ']: criteriaKey=' . $criteriaKey . ',criteriaValue=' . $criteriaValue); // Is it already there? if ($this->isKeySet($criteriaType, $criteriaKey)) { diff --git a/inc/classes/main/criteria/search/class_SearchCriteria.php b/inc/classes/main/criteria/search/class_SearchCriteria.php index 02f3083d..df1f60ef 100644 --- a/inc/classes/main/criteria/search/class_SearchCriteria.php +++ b/inc/classes/main/criteria/search/class_SearchCriteria.php @@ -131,19 +131,19 @@ class SearchCriteria extends BaseCriteria implements LocalSearchCriteria { $valueArray = explode($separator, $value); // Debug message - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('SEARCH-CRITERIA[' . __LINE__ . ']: key=' . $key . ',value[' . gettype($value) . ']=' . $value . ' - ENTERED!'); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('SEARCH-CRITERIA[' . __LINE__ . ']: key=' . $key . ',value[' . gettype($value) . ']=' . $value . ' - ENTERED!'); // Get 'default' search value $searchDefault = $this->getCriteriaElemnent($key); // Debug message - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('SEARCH-CRITERIA[' . __LINE__ . ']: getCriteriaElement(' . $key . ')[' . gettype($searchDefault) . ']=' . $searchDefault); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('SEARCH-CRITERIA[' . __LINE__ . ']: getCriteriaElement(' . $key . ')[' . gettype($searchDefault) . ']=' . $searchDefault); // 'default' check $isMatching = (((($searchDefault !== FALSE) && ($searchDefault == $value)) || ((is_null($searchDefault)) && (is_null($value)))) || ($searchDefault === FALSE)); // Debug message - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('SEARCH-CRITERIA[' . __LINE__ . ']: getCriteriaElement(' . $key . ')[' . gettype($searchDefault) . ']=' . $searchDefault . ',isMatching=' . intval($isMatching)); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('SEARCH-CRITERIA[' . __LINE__ . ']: getCriteriaElement(' . $key . ')[' . gettype($searchDefault) . ']=' . $searchDefault . ',isMatching=' . intval($isMatching)); // Get 'choice' search value (can be NULL or $separator-separated string) $searchChoice = $this->getCriteriaChoiceElemnent($key); @@ -152,7 +152,7 @@ class SearchCriteria extends BaseCriteria implements LocalSearchCriteria { assert(($searchChoice === FALSE) || (is_array($searchChoice))); // Debug message - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('SEARCH-CRITERIA[' . __LINE__ . ']: getCriteriaChoiceElement(' . $key . ')[' . gettype($searchChoice) . ']=' . print_r($searchChoice, TRUE)); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('SEARCH-CRITERIA[' . __LINE__ . ']: getCriteriaChoiceElement(' . $key . ')[' . gettype($searchChoice) . ']=' . print_r($searchChoice, TRUE)); // 'choice' check if ((is_array($searchChoice)) && (count($valueArray) == 1)) { @@ -160,41 +160,41 @@ class SearchCriteria extends BaseCriteria implements LocalSearchCriteria { $isMatching = ((($isMatching === TRUE) || (($searchDefault === FALSE) && (!is_null($value)))) && (in_array($value, $searchChoice))); // Debug message - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('SEARCH-CRITERIA[' . __LINE__ . ']: getCriteriaChoiceElement(' . $key . ')[]=' . gettype($searchChoice) . ',value[' . gettype($value) . ']=' . $value . ',isMatching=' . intval($isMatching) . ' - SINGLE-MATCH'); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('SEARCH-CRITERIA[' . __LINE__ . ']: getCriteriaChoiceElement(' . $key . ')[]=' . gettype($searchChoice) . ',value[' . gettype($value) . ']=' . $value . ',isMatching=' . intval($isMatching) . ' - SINGLE-MATCH'); } elseif ((is_array($searchChoice)) && (count($valueArray) > 1)) { // Debug message - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('SEARCH-CRITERIA[' . __LINE__ . ']: getCriteriaChoiceElement(' . $key . ')[]=' . gettype($searchChoice) . ',valueArray()=' . count($valueArray) . ',isMatching=' . intval($isMatching)); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('SEARCH-CRITERIA[' . __LINE__ . ']: getCriteriaChoiceElement(' . $key . ')[]=' . gettype($searchChoice) . ',valueArray()=' . count($valueArray) . ',isMatching=' . intval($isMatching)); // $value is choice-search value, so check all entries $isMatching = (($isMatching === TRUE) || (($searchDefault === FALSE) && (!is_null($value)))); $idx = 0; foreach ($valueArray as $idx => $match) { // Debug message - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('SEARCH-CRITERIA[' . __LINE__ . ']: match=' . $match . ',count(searchChoice)=' . count($searchChoice)); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('SEARCH-CRITERIA[' . __LINE__ . ']: match=' . $match . ',count(searchChoice)=' . count($searchChoice)); // Is it found? (one is okay) $isMatching = (($isMatching === TRUE) && (in_array($match, $searchChoice))); // Debug message - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('SEARCH-CRITERIA[' . __LINE__ . ']: match=' . $match . ',isMatching=' . intval($isMatching)); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('SEARCH-CRITERIA[' . __LINE__ . ']: match=' . $match . ',isMatching=' . intval($isMatching)); } // END - foreach // Debug message - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('SEARCH-CRITERIA[' . __LINE__ . ']: getCriteriaChoiceElement(' . $key . ')[]=' . gettype($searchChoice) . ',valueArray()=' . count($valueArray) . ',idx=' . $idx . ',isMatching=' . intval($isMatching) . ' - CHOICE-MATCH'); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('SEARCH-CRITERIA[' . __LINE__ . ']: getCriteriaChoiceElement(' . $key . ')[]=' . gettype($searchChoice) . ',valueArray()=' . count($valueArray) . ',idx=' . $idx . ',isMatching=' . intval($isMatching) . ' - CHOICE-MATCH'); } else { // Choice-match is FALSE // Debug message - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('SEARCH-CRITERIA[' . __LINE__ . ']: getCriteriaChoiceElement(' . $key . ')[]=' . gettype($searchChoice) . ',value[' . gettype($value) . ']=' . $value . ',isMatching=' . intval($isMatching) . ' - FALSE-MATCH'); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('SEARCH-CRITERIA[' . __LINE__ . ']: getCriteriaChoiceElement(' . $key . ')[]=' . gettype($searchChoice) . ',value[' . gettype($value) . ']=' . $value . ',isMatching=' . intval($isMatching) . ' - FALSE-MATCH'); } // Debug message - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('SEARCH-CRITERIA[' . __LINE__ . ']: getCriteriaChoiceElement(' . $key . ')[]=' . gettype($searchChoice) . ',isMatching=' . intval($isMatching)); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('SEARCH-CRITERIA[' . __LINE__ . ']: getCriteriaChoiceElement(' . $key . ')[]=' . gettype($searchChoice) . ',isMatching=' . intval($isMatching)); // Get 'exclude' search value $searchExclude = $this->getCriteriaExcludeElemnent($key); // Debug message - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('SEARCH-CRITERIA[' . __LINE__ . ']: getCriteriaExcludeElement(' . $key . ')[' . gettype($searchExclude) . ']=' . $searchExclude); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('SEARCH-CRITERIA[' . __LINE__ . ']: getCriteriaExcludeElement(' . $key . ')[' . gettype($searchExclude) . ']=' . $searchExclude); // 'exclude' check $isMatching = ( @@ -218,7 +218,7 @@ class SearchCriteria extends BaseCriteria implements LocalSearchCriteria { ); // Return result - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('SEARCH-CRITERIA[' . __LINE__ . ']: key=' . $key . ',value[' . gettype($value) . ']=' . $value . ',isMatching=' . intval($isMatching) . ' - EXIT!'); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('SEARCH-CRITERIA[' . __LINE__ . ']: key=' . $key . ',value[' . gettype($value) . ']=' . $value . ',isMatching=' . intval($isMatching) . ' - EXIT!'); return $isMatching; } } diff --git a/inc/classes/main/database/class_BaseDatabaseWrapper.php b/inc/classes/main/database/class_BaseDatabaseWrapper.php index 63d121c9..271849d8 100644 --- a/inc/classes/main/database/class_BaseDatabaseWrapper.php +++ b/inc/classes/main/database/class_BaseDatabaseWrapper.php @@ -149,9 +149,9 @@ class BaseDatabaseWrapper extends BaseFrameworkSystem { $cacheKey = $this->getCacheKeyByCriteria($criteriaInstance, $onlyKeys); // Does this key exists in cache? - if ($this->cacheInstance->offsetExists($cacheKey)) { + if ($this->cacheInstance->offsetExists($cacheKey, BaseDatabaseBackend::RESULT_INDEX_ROWS, 1)) { // Debug message - //* DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('BASE-WRAPPER: Cache used for cacheKey=' . $cacheKey); + //* DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('BASE-WRAPPER: Cache used for cacheKey=' . $cacheKey . ':' . print_r($this->cacheInstance->offsetGet($cacheKey), TRUE)); // Then use this result $result = $this->cacheInstance->offsetGet($cacheKey); diff --git a/inc/classes/main/database/databases/class_LocalFileDatabase.php b/inc/classes/main/database/databases/class_LocalFileDatabase.php index 7aa3fb35..c4c67ee5 100644 --- a/inc/classes/main/database/databases/class_LocalFileDatabase.php +++ b/inc/classes/main/database/databases/class_LocalFileDatabase.php @@ -272,6 +272,27 @@ class LocalFileDatabase extends BaseDatabaseBackend implements DatabaseBackendIn $this->writeDataArrayToFqfn($fqfn, $this->tableInfo[$dataSetInstance->getTableName()]); } + /** + * Updates the table info file from given dataset instance + * + * @param $dataSetInstance An instance of a database set class + * @return void + */ + private function updateTableInfoFile (StoreableCriteria $dataSetInstance) { + // "Cache" table name + $tableName = $dataSetInstance->getTableName(); + + // Create FQFN for creating the table information file + $fqfn = $this->generateFqfnFromDataSet($dataSetInstance, 'info'); + + // Get the data out from dataset in a local array + $this->tableInfo[$tableName]['primary'] = $dataSetInstance->getPrimaryKey(); + $this->tableInfo[$tableName]['last_updated'] = time(); + + // Write the data to the file + $this->writeDataArrayToFqfn($fqfn, $this->tableInfo[$tableName]); + } + /** * Updates the primary key information or creates the table info file if not found * @@ -279,16 +300,20 @@ class LocalFileDatabase extends BaseDatabaseBackend implements DatabaseBackendIn * @return void */ private function updatePrimaryKey (StoreableCriteria $dataSetInstance) { + // "Cache" table name + $tableName = $dataSetInstance->getTableName(); + // Get the information array from lower method $infoArray = $this->getContentsFromTableInfoFile($dataSetInstance); // Is the primary key there? - if (!isset($this->tableInfo['primary'])) { + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('DATABASE: tableInfo=' . print_r($this->tableInfo, TRUE)); + if (!isset($this->tableInfo[$tableName]['primary'])) { // Then create the info file $this->createTableInfoFile($dataSetInstance); - } elseif (($this->getConfigInstance()->getConfigEntry('db_update_primary_forced') == 'Y') && ($dataSetInstance->getPrimaryKey() != $this->tableInfo['primary'])) { + } elseif (($this->getConfigInstance()->getConfigEntry('db_update_primary_forced') == 'Y') && ($dataSetInstance->getPrimaryKey() != $this->tableInfo[$tableName]['primary'])) { // Set the array element - $this->tableInfo[$dataSetInstance->getTableName()]['primary'] = $dataSetInstance->getPrimaryKey(); + $this->tableInfo[$tableName]['primary'] = $dataSetInstance->getPrimaryKey(); // Update the entry $this->updateTableInfoFile($dataSetInstance); @@ -348,7 +373,7 @@ class LocalFileDatabase extends BaseDatabaseBackend implements DatabaseBackendIn // Read the file $dataArray = $this->getDataArrayFromFile($pathName . $dataFile); - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('DATABASE: dataFile=' . $dataFile . ',dataArray='.print_r($dataArray, TRUE)); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('DATABASE: dataFile=' . $dataFile . ',dataArray='.print_r($dataArray, TRUE)); // Is this an array? if (is_array($dataArray)) { @@ -362,11 +387,11 @@ class LocalFileDatabase extends BaseDatabaseBackend implements DatabaseBackendIn // Found one entry? $isFound = (($isFound === TRUE) && ($searchInstance->isCriteriaMatching($key, $value))); - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('DATABASE: key=' . $key . ',value=' . $value . ',isFound=' . intval($isFound)); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('DATABASE: key=' . $key . ',value=' . $value . ',isFound=' . intval($isFound)); } // END - foreach // Is all found? - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('DATABASE: isFound=' . intval($isFound) . ',limitFound=' . $limitFound . ',limit=' . $searchInstance->getLimit()); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('DATABASE: isFound=' . intval($isFound) . ',limitFound=' . $limitFound . ',limit=' . $searchInstance->getLimit()); if ($isFound === TRUE) { // Shall we skip this entry? if ($searchInstance->getSkip() > 0) { @@ -518,6 +543,7 @@ class LocalFileDatabase extends BaseDatabaseBackend implements DatabaseBackendIn foreach ($searchArray as $searchKey => $searchValue) { // Make sure the value is not bool again assert(!is_bool($searchValue)); + assert($searchKey != $this->indexKey); // Debug message + add/update it //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('DATABASE: criteriaKey=' . $searchKey . ',criteriaValue=' . $searchValue); diff --git a/inc/classes/main/result/class_DatabaseResult.php b/inc/classes/main/result/class_DatabaseResult.php index f143a540..11143105 100644 --- a/inc/classes/main/result/class_DatabaseResult.php +++ b/inc/classes/main/result/class_DatabaseResult.php @@ -193,6 +193,16 @@ class DatabaseResult extends BaseFrameworkSystem implements SearchableResult, Up return $isValid; } + /** + * Returns count of entries + * + * @return $isValid Whether the next/rewind entry is valid + */ + public function count () { + // Return it + return count($this->resultArray[BaseDatabaseBackend::RESULT_INDEX_ROWS]); + } + /** * Determines whether the status of the query was fine (BaseDatabaseBackend::RESULT_OKAY) * -- 2.30.2