X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=classes%2FMemcached_DataObject.php;h=0eae9fb42a835e79087a0845f2449f85afd52e28;hb=e274ec4900172b5a53f38e5d9f44d899bf490dc3;hp=27bb5d3c9d6e32f58063f9e1320b5daa711d123f;hpb=7765ddae81e9b29af06009d961b3d56b293f527c;p=quix0rs-gnu-social.git diff --git a/classes/Memcached_DataObject.php b/classes/Memcached_DataObject.php index 27bb5d3c9d..0eae9fb42a 100644 --- a/classes/Memcached_DataObject.php +++ b/classes/Memcached_DataObject.php @@ -34,7 +34,7 @@ class Memcached_DataObject extends Safe_DataObject { if (is_null($v)) { $v = $k; - # XXX: HACK! + // XXX: HACK! $i = new $cls; $keys = $i->keys(); $k = $keys[0]; @@ -63,7 +63,91 @@ class Memcached_DataObject extends Safe_DataObject } return $i; } + + /** + * Get multiple items from the database by key + * + * @param string $cls Class to fetch + * @param string $keyCol name of column for key + * @param array $keyVals key values to fetch + * @param boolean $skipNulls return only non-null results? + * + * @return array Array of objects, in order + */ + function multiGet($cls, $keyCol, $keyVals, $skipNulls=true) + { + $result = array_fill_keys($keyVals, null); + + $toFetch = array(); + + foreach ($keyVals as $keyVal) { + $i = self::getcached($cls, $keyCol, $keyVal); + if ($i !== false) { + $result[$keyVal] = $i; + } else if (!empty($keyVal)) { + $toFetch[] = $keyVal; + } + } + + if (count($toFetch) > 0) { + $i = DB_DataObject::factory($cls); + if (empty($i)) { + throw new Exception(_('Cannot instantiate class ' . $cls)); + } + $i->whereAddIn($keyCol, $toFetch, $i->columnType($keyCol)); + if ($i->find()) { + while ($i->fetch()) { + $copy = clone($i); + $copy->encache(); + $result[$i->$keyCol] = $copy; + } + } + + // Save state of DB misses + + foreach ($toFetch as $keyVal) { + if (empty($result[$keyVal])) { + // save the fact that no such row exists + $c = self::memcache(); + if (!empty($c)) { + $ck = self::cachekey($cls, $keyCol, $keyVal); + $c->set($ck, null); + } + } + } + } + + $values = array_values($result); + + if ($skipNulls) { + $tmp = array(); + foreach ($values as $value) { + if (!empty($value)) { + $tmp[] = $value; + } + } + $values = $tmp; + } + + return new ArrayWrapper($values); + } + function columnType($columnName) + { + $keys = $this->table(); + if (!array_key_exists($columnName, $keys)) { + throw new Exception('Unknown key column ' . $columnName . ' in ' . join(',', array_keys($keys))); + } + + $def = $keys[$columnName]; + + if ($def & DB_DATAOBJECT_INT) { + return 'integer'; + } else { + return 'string'; + } + } + /** * @fixme Should this return false on lookup fail to match staticGet? */ @@ -74,11 +158,17 @@ class Memcached_DataObject extends Safe_DataObject return $i; } else { $i = DB_DataObject::factory($cls); - if (empty($i)) { + if (empty($i) || PEAR::isError($i)) { return false; } foreach ($kv as $k => $v) { - $i->$k = $v; + if (is_null($v)) { + // XXX: possible SQL injection...? Don't + // pass keys from the browser, eh. + $i->whereAdd("$k is null"); + } else { + $i->$k = $v; + } } if ($i->find(true)) { $i->encache(); @@ -273,24 +363,23 @@ class Memcached_DataObject extends Safe_DataObject function getSearchEngine($table) { require_once INSTALLDIR.'/lib/search_engines.php'; - static $search_engine; - if (!isset($search_engine)) { - if (Event::handle('GetSearchEngine', array($this, $table, &$search_engine))) { - if ('mysql' === common_config('db', 'type')) { - $type = common_config('search', 'type'); - if ($type == 'like') { - $search_engine = new MySQLLikeSearch($this, $table); - } else if ($type == 'fulltext') { - $search_engine = new MySQLSearch($this, $table); - } else { - // Low level exception. No need for i18n as discussed with Brion. - throw new ServerException('Unknown search type: ' . $type); - } + + if (Event::handle('GetSearchEngine', array($this, $table, &$search_engine))) { + if ('mysql' === common_config('db', 'type')) { + $type = common_config('search', 'type'); + if ($type == 'like') { + $search_engine = new MySQLLikeSearch($this, $table); + } else if ($type == 'fulltext') { + $search_engine = new MySQLSearch($this, $table); } else { - $search_engine = new PGSearch($this, $table); + // Low level exception. No need for i18n as discussed with Brion. + throw new ServerException('Unknown search type: ' . $type); } + } else { + $search_engine = new PGSearch($this, $table); } } + return $search_engine; } @@ -339,10 +428,15 @@ class Memcached_DataObject extends Safe_DataObject $start = microtime(true); $fail = false; - try { - $result = parent::_query($string); - } catch (Exception $e) { - $fail = $e; + $result = null; + if (Event::handle('StartDBQuery', array($this, $string, &$result))) { + common_perf_counter('query', $string); + try { + $result = parent::_query($string); + } catch (Exception $e) { + $fail = $e; + } + Event::handle('EndDBQuery', array($this, $string, &$result)); } $delta = microtime(true) - $start; @@ -490,6 +584,10 @@ class Memcached_DataObject extends Safe_DataObject } } } + // Needed to make timestamp values usefully comparable. + if (common_config('db', 'type') == 'mysql') { + parent::_query("set time_zone='+0:00'"); + } } return $result;