public static function getCachedQueryResults(Criteria $criteria, $queryType, $peerClassName, &$cacheKey, &$queryDB) { if (!kConf::get("query_cache_enabled")) { return null; } // if the criteria has an empty IN, no need to go to the DB or memcache - return an empty array foreach ($criteria->getMap() as $criterion) { if (in_array(Criterion::ODER, $criterion->getConjunctions())) { continue; } if ($criterion->getComparison() == Criteria::IN && !$criterion->getValue()) { KalturaLog::debug("kQueryCache: criteria has empty IN, returning empty result set, peer={$peerClassName}"); return array(); } } // initialize $invalidationKeyRules = call_user_func(array($peerClassName, 'getCacheInvalidationKeys')); $invalidationKeys = self::getInvalidationKeysForQuery($invalidationKeyRules, $criteria); if (!$invalidationKeys) { return null; } self::initGlobalMemcache(); if (self::$s_memcacheQueries === null) { return null; } // build memcache query foreach ($invalidationKeys as $index => $invalidationKey) { $invalidationKeys[$index] = self::CACHE_PREFIX_INVALIDATION_KEY . $invalidationKey; } $keysToGet = $invalidationKeys; $keysToGet[] = self::DONT_CACHE_KEY; $keysToGet[] = self::MAX_SLAVE_LAG_KEY; $queryStart = microtime(true); $cacheResult = self::$s_memcacheKeys->multiGet($keysToGet); KalturaLog::debug("kQueryCache: keys query took " . (microtime(true) - $queryStart) . " seconds"); if ($cacheResult === false) { KalturaLog::log("kQueryCache: failed to query keys memcache, not using query cache"); return null; } // get max slave lag $queryMasterThreshold = self::MAX_QUERY_MASTER_TIME_MARGIN_SEC; $maxSlaveLag = null; if (array_key_exists(self::MAX_SLAVE_LAG_KEY, $cacheResult) && strlen($cacheResult[self::MAX_SLAVE_LAG_KEY]) && is_numeric($cacheResult[self::MAX_SLAVE_LAG_KEY])) { $maxSlaveLag = $cacheResult[self::MAX_SLAVE_LAG_KEY]; $maxSlaveLag += self::SLAVE_LAG_TIME_MARGIN_SEC; $queryMasterThreshold = min($maxSlaveLag, $queryMasterThreshold); } unset($cacheResult[self::MAX_SLAVE_LAG_KEY]); // don't cache the result if the 'dont cache' flag is enabled $cacheQuery = true; if (array_key_exists(self::DONT_CACHE_KEY, $cacheResult) && $cacheResult[self::DONT_CACHE_KEY]) { KalturaLog::log("kQueryCache: dontCache key is set -> not caching the result"); $cacheQuery = false; } unset($cacheResult[self::DONT_CACHE_KEY]); // get max invalidation time $maxInvalidationTime = null; $maxInvalidationKey = null; if (count($cacheResult)) { $maxInvalidationTime = max($cacheResult); $maxInvalidationKey = array_search($maxInvalidationTime, $cacheResult); } // check whether we should query the master $queryDB = self::QUERY_DB_SLAVE; $currentTime = time(); if (!is_null($maxInvalidationTime) && $currentTime < $maxInvalidationTime + $queryMasterThreshold) { KalturaLog::debug("kQueryCache: changed recently -> query master, peer={$peerClassName}, invkey={$maxInvalidationKey} querytime={$currentTime} invtime={$maxInvalidationTime} threshold={$queryMasterThreshold}"); $queryDB = self::QUERY_DB_MASTER; if ($currentTime < $maxInvalidationTime + self::CLOCK_SYNC_TIME_MARGIN_SEC) { return null; // The query won't be cached since cacheKey is null, it's ok cause it won't be used anyway } } if ($queryDB == self::QUERY_DB_SLAVE && !is_null($maxInvalidationTime) && $currentTime < $maxInvalidationTime + $maxSlaveLag) { KalturaLog::debug("kQueryCache: using an out of date slave -> not caching the result, peer={$peerClassName}, invkey={$maxInvalidationKey} querytime={$currentTime} invtime={$maxInvalidationTime} slavelag={$maxSlaveLag}"); $cacheQuery = false; } // get the cache key and update the api cache $origCacheKey = self::CACHE_PREFIX_QUERY . $queryType . md5(serialize($criteria) . self::CACHE_VERSION); if ($cacheQuery) { kApiCache::addInvalidationKeys($invalidationKeys, $maxInvalidationTime); $cacheKey = new kQueryCacheKey($origCacheKey); } else { kApiCache::disableConditionalCache(); } // check whether we have a valid cached query $queryStart = microtime(true); $queryResult = self::$s_memcacheQueries->get($origCacheKey); KalturaLog::debug("kQueryCache: query took " . (microtime(true) - $queryStart) . " seconds"); if (!$queryResult) { KalturaLog::debug("kQueryCache: cache miss, peer={$peerClassName}, key={$origCacheKey}"); return null; } list($queryResult, $queryTime, $debugInfo) = $queryResult; if (!is_null($maxInvalidationTime) && $queryTime < $maxInvalidationTime + self::CLOCK_SYNC_TIME_MARGIN_SEC) { KalturaLog::debug("kQueryCache: cached query invalid, peer={$peerClassName}, key={$origCacheKey}, invkey={$maxInvalidationKey} querytime={$queryTime} debugInfo={$debugInfo} invtime={$maxInvalidationTime}"); return null; } // return from memcache $existingInvKeys = array(); foreach ($cacheResult as $invalidationKey => $invalidationTime) { $existingInvKeys[] = "{$invalidationKey}:{$invalidationTime}"; } $existingInvKeys = implode(',', $existingInvKeys); KalturaLog::debug("kQueryCache: returning from memcache, peer={$peerClassName}, key={$origCacheKey} queryTime={$queryTime} debugInfo={$debugInfo} invkeys=[{$existingInvKeys}]"); return $queryResult; }
/** * Add the content of a Criteria to the current Criteria * In case of conflict, the current Criteria keeps its properties * * @param Criteria $criteria The criteria to read properties from * @param string $operator The logical operator used to combine conditions * Defaults to Criteria::LOGICAL_AND, also accapts Criteria::LOGICAL_OR * This parameter is deprecated, use _or() instead * * @return Criteria The current criteria object */ public function mergeWith(Criteria $criteria, $operator = null) { // merge limit $limit = $criteria->getLimit(); if ($limit != 0 && $this->getLimit() == 0) { $this->limit = $limit; } // merge offset $offset = $criteria->getOffset(); if ($offset != 0 && $this->getOffset() == 0) { $this->offset = $offset; } // merge select modifiers $selectModifiers = $criteria->getSelectModifiers(); if ($selectModifiers && !$this->selectModifiers) { $this->selectModifiers = $selectModifiers; } // merge select columns $this->selectColumns = array_merge($this->getSelectColumns(), $criteria->getSelectColumns()); // merge as columns $commonAsColumns = array_intersect_key($this->getAsColumns(), $criteria->getAsColumns()); if (!empty($commonAsColumns)) { throw new PropelException('The given criteria contains an AsColumn with an alias already existing in the current object'); } $this->asColumns = array_merge($this->getAsColumns(), $criteria->getAsColumns()); // merge orderByColumns $orderByColumns = array_merge($this->getOrderByColumns(), $criteria->getOrderByColumns()); $this->orderByColumns = array_unique($orderByColumns); // merge groupByColumns $groupByColumns = array_merge($this->getGroupByColumns(), $criteria->getGroupByColumns()); $this->groupByColumns = array_unique($groupByColumns); // merge where conditions if ($operator == Criteria::LOGICAL_OR) { $this->_or(); } $isFirstCondition = true; foreach ($criteria->getMap() as $key => $criterion) { if ($isFirstCondition && $this->defaultCombineOperator == Criteria::LOGICAL_OR) { $this->addOr($criterion, null, null, false); $this->defaultCombineOperator == Criteria::LOGICAL_AND; } elseif ($this->containsKey($key)) { $this->addAnd($criterion); } else { $this->add($criterion); } $isFirstCondition = false; } // merge having if ($having = $criteria->getHaving()) { if ($this->getHaving()) { $this->addHaving($this->getHaving()->addAnd($having)); } else { $this->addHaving($having); } } // merge alias $commonAliases = array_intersect_key($this->getAliases(), $criteria->getAliases()); if (!empty($commonAliases)) { throw new PropelException('The given criteria contains an alias already existing in the current object'); } $this->aliases = array_merge($this->getAliases(), $criteria->getAliases()); // merge join $this->joins = array_merge($this->getJoins(), $criteria->getJoins()); return $this; }
private function _parseSql() { $where = ''; $maps = $this->_criteria->getMap(); foreach ($maps as $aCriterion) { $partWhere = $this->_createSqlFromCriterion($aCriterion); if ($where) { //$andOr = $this->_allIsOr?'or':'and'; //$this->_allIsOr 已经在 _criteria 生成的时候就完成了 //$where = '('. $where. " $andOr ".trim($table.$map->getColumn(),'.').$map->getComparison().$value .')'; $where = '(' . $where . " ) and " . $partWhere; } else { $where = $partWhere; } } //var_dump( $where ); $isHaveWhere = false; /* if( strpos( $this->_sql, 'where' ) && preg_match( "/where .* \)\$/i", $this->_sql ) ){ $isHaveWhere = true; }*/ if ($where) { if (strpos($this->_sql, self::SQL_WHERE_STANDER)) { $this->_parsed_sql = str_replace(self::SQL_WHERE_STANDER, ' and (' . $where . ')', $this->_sql); } else { if (strpos($this->_sql, 'where ') === false) { $this->_parsed_sql = $this->_sql . ' where (' . $where . ')'; } else { $this->_parsed_sql = $this->_sql . ' and (' . $where . ')'; } } } else { $this->_parsed_sql = str_replace(self::SQL_WHERE_STANDER, '', $this->_sql); //$this->_parsed_sql = $this->_sql; } /* $orderBy = $criteria->getOrderByColumns(); $groupBy = $criteria->getGroupByColumns(); $ignoreCase = $criteria->isIgnoreCase(); $select = $criteria->getSelectColumns(); $aliases = $criteria->getAsColumns(); var_dump( $orderBy ); var_dump( $groupBy ); var_dump( $ignoreCase ); var_dump( $select ); var_dump( $aliases ); */ }