From 34b6624410e8505acd085de75b4c216b46e4e48b Mon Sep 17 00:00:00 2001 From: Carsten Brandt Date: Wed, 24 Apr 2013 00:20:27 +0200 Subject: [PATCH] implemented redis AR ActiveQuery and find() --- framework/db/redis/ActiveQuery.php | 160 ++++++++++-------------------------- framework/db/redis/ActiveRecord.php | 22 ++--- 2 files changed, 54 insertions(+), 128 deletions(-) diff --git a/framework/db/redis/ActiveQuery.php b/framework/db/redis/ActiveQuery.php index abc3f87..b387421 100644 --- a/framework/db/redis/ActiveQuery.php +++ b/framework/db/redis/ActiveQuery.php @@ -70,15 +70,20 @@ class ActiveQuery extends \yii\base\Component */ public $limit; /** - * @var integer zero-based offset from where the records are to be returned. If not set or - * less than 0, it means starting from the beginning. + * @var integer zero-based offset from where the records are to be returned. + * If not set, it means starting from the beginning. + * If less than zero it means starting n elements from the end. */ public $offset; /** - * @var string|array how to sort the query results. This refers to the ORDER BY clause in a SQL statement. - * It can be either a string (e.g. `'id ASC, name DESC'`) or an array (e.g. `array('id ASC', 'name DESC')`). + * @var array array of primary keys of the records to find. */ - public $orderBy; + public $primaryKeys; + + public function primaryKeys($primaryKeys) { + $this->primaryKeys = $primaryKeys; + return $this; + } /** * Executes query and returns all results as an array. @@ -86,9 +91,20 @@ class ActiveQuery extends \yii\base\Component */ public function all() { - // TODO implement - $command = $this->createCommand(); - $rows = $command->queryAll(); + $modelClass = $this->modelClass; + /** @var Connection $db */ + $db = $modelClass::getDb(); + if (($primaryKeys = $this->primaryKeys) === null) { + $start = $this->offset === null ? 0 : $this->offset; + $end = $this->limit === null ? -1 : $start + $this->limit; + $primaryKeys = $db->executeCommand('LRANGE', array($modelClass::tableName(), $start, $end)); + } + $rows = array(); + foreach($primaryKeys as $pk) { + $key = $modelClass::tableName() . ':a:' . (is_array($pk) ? implode('-', $pk) : $pk); // TODO escape PK glue + // get attributes + $rows[] = $db->executeCommand('HGETALL', array($key)); + } if ($rows !== array()) { $models = $this->createModels($rows); if (!empty($this->with)) { @@ -108,9 +124,18 @@ class ActiveQuery extends \yii\base\Component */ public function one() { - // TODO implement - $command = $this->createCommand(); - $row = $command->queryRow(); + $modelClass = $this->modelClass; + /** @var Connection $db */ + $db = $modelClass::getDb(); + if (($primaryKeys = $this->primaryKeys) === null) { + $start = $this->offset === null ? 0 : $this->offset; + $primaryKeys = $db->executeCommand('LRANGE', array($modelClass::tableName(), $start, $start + 1)); + } + $pk = reset($primaryKeys); + $key = $modelClass::tableName() . ':a:' . (is_array($pk) ? implode('-', $pk) : $pk); // TODO escape PK glue + // get attributes + $row = $db->executeCommand('HGETALL', array($key)); +// TODO check for empty list if key does not exist if ($row !== false && !$this->asArray) { /** @var $class ActiveRecord */ $class = $this->modelClass; @@ -132,63 +157,12 @@ class ActiveQuery extends \yii\base\Component * Make sure you properly quote column names. * @return integer number of records */ - public function count($q = '*') - { - // TODO implement - $this->select = array("COUNT($q)"); - return $this->createCommand()->queryScalar(); - } - - /** - * Returns the sum of the specified column values. - * @param string $q the column name or expression. - * Make sure you properly quote column names. - * @return integer the sum of the specified column values - */ - public function sum($q) - { - // TODO implement - $this->select = array("SUM($q)"); - return $this->createCommand()->queryScalar(); - } - - /** - * Returns the average of the specified column values. - * @param string $q the column name or expression. - * Make sure you properly quote column names. - * @return integer the average of the specified column values. - */ - public function average($q) - { - // TODO implement - $this->select = array("AVG($q)"); - return $this->createCommand()->queryScalar(); - } - - /** - * Returns the minimum of the specified column values. - * @param string $q the column name or expression. - * Make sure you properly quote column names. - * @return integer the minimum of the specified column values. - */ - public function min($q) - { - // TODO implement - $this->select = array("MIN($q)"); - return $this->createCommand()->queryScalar(); - } - - /** - * Returns the maximum of the specified column values. - * @param string $q the column name or expression. - * Make sure you properly quote column names. - * @return integer the maximum of the specified column values. - */ - public function max($q) + public function count() { - // TODO implement - $this->select = array("MAX($q)"); - return $this->createCommand()->queryScalar(); + $modelClass = $this->modelClass; + /** @var Connection $db */ + $db = $modelClass::getDb(); + return $db->executeCommand('LLEN', array($modelClass::tableName())); } /** @@ -197,10 +171,10 @@ class ActiveQuery extends \yii\base\Component * @return string|boolean the value of the first column in the first row of the query result. * False is returned if the query result is empty. */ - public function scalar() + public function scalar($column) { - // TODO implement - return $this->createCommand()->queryScalar(); + $record = $this->one(); + return $record->$column; } /** @@ -209,9 +183,7 @@ class ActiveQuery extends \yii\base\Component */ public function exists() { - // TODO implement - $this->select = array(new Expression('1')); - return $this->scalar() !== false; + return $this->one() !== null; } @@ -228,48 +200,6 @@ class ActiveQuery extends \yii\base\Component } /** - * Sets the ORDER BY part of the query. - * TODO: refactor, it is duplicated from yii/db/Query - * @param string|array $columns the columns (and the directions) to be ordered by. - * Columns can be specified in either a string (e.g. "id ASC, name DESC") or an array (e.g. array('id ASC', 'name DESC')). - * The method will automatically quote the column names unless a column contains some parenthesis - * (which means the column contains a DB expression). - * @return Query the query object itself - * @see addOrder() - */ - public function orderBy($columns) - { - $this->orderBy = $columns; - return $this; - } - - /** - * Adds additional ORDER BY columns to the query. - * TODO: refactor, it is duplicated from yii/db/Query - * @param string|array $columns the columns (and the directions) to be ordered by. - * Columns can be specified in either a string (e.g. "id ASC, name DESC") or an array (e.g. array('id ASC', 'name DESC')). - * The method will automatically quote the column names unless a column contains some parenthesis - * (which means the column contains a DB expression). - * @return Query the query object itself - * @see order() - */ - public function addOrderBy($columns) - { - if (empty($this->orderBy)) { - $this->orderBy = $columns; - } else { - if (!is_array($this->orderBy)) { - $this->orderBy = preg_split('/\s*,\s*/', trim($this->orderBy), -1, PREG_SPLIT_NO_EMPTY); - } - if (!is_array($columns)) { - $columns = preg_split('/\s*,\s*/', trim($columns), -1, PREG_SPLIT_NO_EMPTY); - } - $this->orderBy = array_merge($this->orderBy, $columns); - } - return $this; - } - - /** * Sets the LIMIT part of the query. * TODO: refactor, it is duplicated from yii/db/Query * @param integer $limit the limit diff --git a/framework/db/redis/ActiveRecord.php b/framework/db/redis/ActiveRecord.php index 95d771d..af78331 100644 --- a/framework/db/redis/ActiveRecord.php +++ b/framework/db/redis/ActiveRecord.php @@ -60,16 +60,15 @@ abstract class ActiveRecord extends \yii\db\ActiveRecord * returned (null will be returned if there is no matching). * @see createQuery() */ - public static function find($q = null) + public static function find($q = null) // TODO optimize API { - // TODO $query = static::createQuery(); if (is_array($q)) { - return $query->where($q)->one(); + return $query->primaryKeys($q)->one(); } elseif ($q !== null) { // query by primary key $primaryKey = static::primaryKey(); - return $query->where(array($primaryKey[0] => $q))->one(); + return $query->primaryKeys(array($primaryKey[0] => $q))->one(); } return $query; } @@ -178,7 +177,7 @@ abstract class ActiveRecord extends \yii\db\ActiveRecord } } // save pk in a findall pool - $db->executeCommand('SADD', array(static::tableName(), $pk)); + $db->executeCommand('RPUSH', array(static::tableName(), $pk)); $key = static::tableName() . ':a:' . implode('-', $pk); // TODO escape PK glue // save attributes @@ -214,7 +213,7 @@ abstract class ActiveRecord extends \yii\db\ActiveRecord { $db = static::getDb(); if ($condition==='') { - $condition = $db->executeCommand('SMEMBERS', array(static::tableName())); + $condition = $db->executeCommand('LRANGE', array(static::tableName(), 0, -1)); } if (empty($attributes)) { return 0; @@ -255,7 +254,7 @@ abstract class ActiveRecord extends \yii\db\ActiveRecord { $db = static::getDb(); if ($condition==='') { - $condition = $db->executeCommand('SMEMBERS', array(static::tableName())); + $condition = $db->executeCommand('LRANGE', array(static::tableName(), 0, -1)); } $n=0; foreach($condition as $pk) { @@ -287,23 +286,20 @@ abstract class ActiveRecord extends \yii\db\ActiveRecord { $db = static::getDb(); if ($condition==='') { - $condition = $db->executeCommand('SMEMBERS', array(static::tableName())); + $condition = $db->executeCommand('LRANGE', array(static::tableName(), 0, -1)); } if (empty($condition)) { return 0; } - $smembers = array(); $attributeKeys = array(); foreach($condition as $pk) { if (is_array($pk)) { $pk = implode('-', $pk); } - $smembers[] = $pk; // TODO escape PK glue + $db->executeCommand('LREM', array(static::tableName(), 0, $pk)); // TODO escape PK glue $attributeKeys[] = static::tableName() . ':' . $pk . ':a'; // TODO escape PK glue } - array_unshift($smembers, static::tableName()); - $db->executeCommand('DEL', $attributeKeys); - return $db->executeCommand('SREM', $smembers); + return $db->executeCommand('DEL', $attributeKeys); } /**