Skip to content

Commit

Permalink
Add Range Query Support
Browse files Browse the repository at this point in the history
  • Loading branch information
beberlei committed Apr 2, 2012
1 parent e788122 commit 1ff66d2
Show file tree
Hide file tree
Showing 6 changed files with 374 additions and 9 deletions.
19 changes: 16 additions & 3 deletions lib/Doctrine/KeyValueStore/EntityManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

use Doctrine\KeyValueStore\Storage\Storage;
use Doctrine\KeyValueStore\Mapping\ClassMetadataFactory;
use Doctrine\KeyValueStore\Query\RangeQuery;
use Doctrine\Common\Persistence\Mapping\Driver\MappingDriver;
use Doctrine\Common\Cache\Cache;

Expand Down Expand Up @@ -64,11 +65,11 @@ public function find($className, $key, array $fields = null)
*
* @param string $className
* @param string $partitionKey
* @return Iterator
* @return \Doctrine\KeyValueStore\Query\RangeQuery
*/
public function findRange($className, $partitionKey, array $conditions = array(), array $fields = array(), $limit = null, $offset = null)
public function createRangeQuery($className, $partitionKey)
{

return new RangeQuery($this, $className, $partitionKey);
}

public function persist($object)
Expand All @@ -94,6 +95,18 @@ public function unwrap()
return $this->storageDriver;
}

/**
* @return \Doctrine\KeyValueStore\UnitOfWork
*/
public function getUnitOfWork()
{
return $this->unitOfWork;
}

/**
* @param string $className
* @return \Doctrine\KeyValueStore\Mapping\ClassMetadata
*/
public function getClassMetadata($className)
{
return $this->unitOfwork->getClassMetadata($className);
Expand Down
216 changes: 216 additions & 0 deletions lib/Doctrine/KeyValueStore/Query/RangeQuery.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/

namespace Doctrine\KeyValueStore\Query;

use Doctrine\KeyValueStore\EntityManager;

/**
* Range Query Object. It always requires a partition/hash key and
* optionally conditions on the range key.
*
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class RangeQuery
{
const CONDITION_EQ = 'eq';
const CONDITION_LE = 'le';
const CONDITION_LT = 'lt';
const CONDITION_GT = 'gt';
const CONDITION_GE = 'ge';
const CONDITION_NEQ = 'neq';
const CONDITION_BETWEEN = 'between';
const CONDITION_STARTSWITH = 'startswith';

/**
* @param string
*/
protected $className;

/**
* @param string
*/
protected $partitionKey;

/**
* @var array
*/
protected $rangeConditions = array();

/**
* Limit result to only a set of entities.
*
* @var int|null
*/
protected $limit;

/**
* Vendor specific query hints
*
* @var array
*/
protected $hints = array();

/**
* @var EntityManager
*/
protected $em;

public function __construct(EntityManager $em, $className, $partitionKey)
{
$this->em = $em;
$this->className = $className;
$this->partitionKey = $partitionKey;
}

public function setLimit($limit)
{
$this->limit = $limit;
return $this;
}

public function getLimit()
{
return $this->limit;
}

/**
* Get className.
*
* @return className.
*/
public function getClassName()
{
return $this->className;
}

/**
* Get partitionKey.
*
* @return partitionKey.
*/
public function getPartitionKey()
{
return $this->partitionKey;
}

/**
* Add range equals condition to range key.
*
* @param mixed $value
* @return RangeQuery
*/
public function rangeEquals($value)
{
$this->conditions[] = array(self::CONDITION_EQ, $value);
return $this;
}

/**
* Add range not equals condition to range key.
*
* @param mixed $value
* @return RangeQuery
*/
public function rangeNotEquals($value)
{
$this->conditions[] = array(self::CONDITION_NEQ, $value);
return $this;
}

/**
* Add range less than condition to range key.
*
* @param mixed $value
* @return RangeQuery
*/
public function rangeLessThan($value)
{
$this->conditions[] = array(self::CONDITION_LT, $value);
return $this;
}

/**
* Add range less than equals condition to range key.
*
* @param mixed $value
* @return RangeQuery
*/
public function rangeLessThanEquals($value)
{
$this->conditions[] = array(self::CONDITION_LE, $value);
return $this;
}

/**
* Add range greater than condition to range key.
*
* @param mixed $value
* @return RangeQuery
*/
public function rangeGreaterThan($value)
{
$this->conditions[] = array(self::CONDITION_GT, $value);
return $this;
}

/**
* Add range greater than equals condition to range key.
*
* @param mixed $value
* @return RangeQuery
*/
public function rangeGreaterThanEquals($value)
{
$this->conditions[] = array(self::CONDITION_GE, $value);
return $this;
}

/**
* Get all conditions
*
* @return array
*/
public function getConditions()
{
return $this->conditions;
}

/**
* Execute query and return a result iterator.
*
* @return ResultIterator
*/
public function execute()
{
$storage = $this->em->unwrap();

if ( ! ($storage instanceof RangeQueryStorage)) {
throw new \RuntimeException("The storage backend " . $this->storage->getName() . " does not support range queries.");
}

$uow = $em->getUnitOfWork();
$class = $this->em->getClassMetadata($this->className);

return $storage>executeRangeQuery($this, $class->storageName, $class->identifiers, function ($row) use($uow, $class) {
return $uow->createEntity($class, $data);
});
}
}

41 changes: 41 additions & 0 deletions lib/Doctrine/KeyValueStore/Query/RangeQueryStorage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/

namespace Doctrine\KeyValueStore\Query;

/**
* Interface used by storages that support range queries on composite primary
* keys with one partition key and a range key.
*
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
interface RangeQueryStorage
{
/**
* Execute the range query and return a ResultIterator
*
* @param RangeQuery $query
* @param string $storageName
* @param array $key
* @param Closure $hydrateRow
* @return ResultIterator
*/
function executeRangeQuery(RangeQuery $query, $storageName, $key, \Closure $hydrateRow = null);
}

Loading

0 comments on commit 1ff66d2

Please sign in to comment.