Skip to content
Permalink
Browse files

Re-implementing UnaryExpression to make it more simple

Allowing isNull and isNotNull to accept ExpressionInterface
  • Loading branch information...
lorenzo committed Jun 30, 2014
1 parent 422d5f0 commit ee0eb638ceff598d4ceedcf9db3ec844fc207360
@@ -99,7 +99,7 @@ protected function _pagingSubquery($original, $limit, $offset) {
$query = clone $original;
$order = $query->clause('order') ?: new OrderByExpression('NULL');
$query->select([
'_cake_page_rownum_' => new UnaryExpression($order, [], 'ROW_NUMBER() OVER')
'_cake_page_rownum_' => new UnaryExpression('ROW_NUMBER() OVER', $order)
])->limit(null)
->offset(null)
->order([], true);
@@ -15,6 +15,7 @@
namespace Cake\Database\Expression;
use Cake\Database\ExpressionInterface;
use Cake\Database\Expression\IdentifierExpression;
use Cake\Database\TypeMapTrait;
use Cake\Database\ValueBinder;
use \Countable;
@@ -201,11 +202,14 @@ public function lte($field, $value, $type = null) {
/**
* Adds a new condition to the expression object in the form "field IS NULL".
*
* @param string $field database field to be tested for null
* @param string|ExpressionInterface $field database field to be tested for null
* @return QueryExpression
*/
public function isNull($field) {
return $this->add($field . ' IS NULL');
if (!($field instanceof ExpressionInterface)) {
$field = new IdentifierExpression($field);
}
return $this->add(new UnaryExpression('IS NULL', $field, UnaryExpression::POSTFIX));
}
/**
@@ -215,7 +219,10 @@ public function isNull($field) {
* @return QueryExpression
*/
public function isNotNull($field) {
return $this->add($field . ' IS NOT NULL');
if (!($field instanceof ExpressionInterface)) {
$field = new IdentifierExpression($field);
}
return $this->add(new UnaryExpression('IS NOT NULL', $field, UnaryExpression::POSTFIX));
}
/**
@@ -437,7 +444,7 @@ protected function _addConditions(array $conditions, array $types) {
}
if (strtolower($k) === 'not') {
$this->_conditions[] = new UnaryExpression(new self($c, $typeMap), [], 'NOT');
$this->_conditions[] = new UnaryExpression('NOT', new self($c, $typeMap));
continue;
}
@@ -22,7 +22,53 @@
*
* @internal
*/
class UnaryExpression extends QueryExpression {
class UnaryExpression implements ExpressionInterface {
/**
* Indicates that the operation is in pre-order
*
*/
const PREFIX = 0;
/**
* Indicates that the operation is in post-order
*
*/
const POSTFIX = 1;
/**
* The operator this unary expression represents
*
* @var string
*/
protected $_operator;
/**
* Holds the value which the unary expression operates
*
* @var mixed
*/
protected $_value;
/**
* Where to place the operator
*
* @var int
*/
protected $_mode;
/**
* Constructor
*
* @param string $operator The operator to used for the expression
* @param mixed $value the value to use as the operand for the expression
* @param int $mode either UnaryExpression::PREFIX or UnaryExpression::POSTFIX
*/
public function __construct($operator, $value, $mode = self::PREFIX) {
$this->_operator = $operator;
$this->_value = $value;
$this->_mode = $mode;
}
/**
* Converts the expression to its string representation
@@ -31,12 +77,25 @@ class UnaryExpression extends QueryExpression {
* @return string
*/
public function sql(ValueBinder $generator) {
foreach ($this->_conditions as $condition) {
if ($condition instanceof ExpressionInterface) {
$condition = $condition->sql($generator);
}
// We only use the first (and only) condition
return $this->_conjunction . ' (' . $condition . ')';
$operand = $this->_value;
if ($operand instanceof ExpressionInterface) {
$operand = $operand->sql($generator);
}
if ($this->_mode === self::POSTFIX) {
return '(' . $operand . ') ' . $this->_operator;
}
return $this->_operator . ' (' . $operand . ')';
}
/**
* {@inheritDoc}
*
*/
public function traverse(callable $callable) {
if ($this->_value instanceof ExpressionInterface) {
$callable($this->_value);
}
}
@@ -2484,6 +2484,37 @@ public function testDebugInfo() {
$result = $query->__debugInfo();
}
/**
* Tests that it is possible to pass ExpressionInterface to isNull and isNotNull
*
* @return void
*/
public function testIsNullWithExpressions() {
$query = new Query($this->connection);
$subquery = (new Query($this->connection))
->select(['id'])
->from('authors')
->where(['id' => 1]);
$result = $query
->select(['name'])
->from(['authors'])
->where(function($exp) use ($subquery) {
return $exp->isNotNull($subquery);
})
->execute();
$this->assertNotEmpty($result->fetchAll('assoc'));
$result = (new Query($this->connection))
->select(['name'])
->from(['authors'])
->where(function($exp) use ($subquery) {
return $exp->isNull($subquery);
})
->execute();
$this->assertEmpty($result->fetchAll('assoc'));
}
/**
* Assertion for comparing a table's contents with what is in it.
*

0 comments on commit ee0eb63

Please sign in to comment.
You can’t perform that action at this time.