Browse Source

Automatically casting to array values that are passed using the "in" or
"not in" operators, fixes #2702

Jose Lorenzo Rodriguez 12 years ago
parent
commit
d90ea72b73
2 changed files with 108 additions and 11 deletions
  1. 22 11
      src/Database/Expression/QueryExpression.php
  2. 86 0
      tests/TestCase/Database/QueryTest.php

+ 22 - 11
src/Database/Expression/QueryExpression.php

@@ -109,7 +109,7 @@ class QueryExpression implements ExpressionInterface, Countable {
 			return $this;
 		}
 
-		if ($conditions instanceof self && count($conditions) > 0) {
+		if ($conditions instanceof ExpressionInterface) {
 			$this->_conditions[] = $conditions;
 			return $this;
 		}
@@ -129,7 +129,7 @@ class QueryExpression implements ExpressionInterface, Countable {
  * @return QueryExpression
  */
 	public function eq($field, $value, $type = null) {
-		return $this->add([$field => $value], $type ? [$field => $type] : []);
+		return $this->add(new Comparison($field, $value, $type, '='));
 	}
 
 /**
@@ -143,7 +143,7 @@ class QueryExpression implements ExpressionInterface, Countable {
  * @return QueryExpression
  */
 	public function notEq($field, $value, $type = null) {
-		return $this->add([$field . ' !=' => $value], $type ? [$field => $type] : []);
+		return $this->add(new Comparison($field, $value, $type, '!='));
 	}
 
 /**
@@ -155,7 +155,7 @@ class QueryExpression implements ExpressionInterface, Countable {
  * @return QueryExpression
  */
 	public function gt($field, $value, $type = null) {
-		return $this->add([$field . ' >' => $value], $type ? [$field => $type] : []);
+		return $this->add(new Comparison($field, $value, $type, '>'));
 	}
 
 /**
@@ -167,7 +167,7 @@ class QueryExpression implements ExpressionInterface, Countable {
  * @return QueryExpression
  */
 	public function lt($field, $value, $type = null) {
-		return $this->add([$field . ' <' => $value], $type ? [$field => $type] : []);
+		return $this->add(new Comparison($field, $value, $type, '<'));
 	}
 
 /**
@@ -179,7 +179,7 @@ class QueryExpression implements ExpressionInterface, Countable {
  * @return QueryExpression
  */
 	public function gte($field, $value, $type = null) {
-		return $this->add([$field . ' >=' => $value], $type ? [$field => $type] : []);
+		return $this->add(new Comparison($field, $value, $type, '>='));
 	}
 
 /**
@@ -191,7 +191,7 @@ class QueryExpression implements ExpressionInterface, Countable {
  * @return QueryExpression
  */
 	public function lte($field, $value, $type = null) {
-		return $this->add([$field . ' <=' => $value], $type ? [$field => $type] : []);
+		return $this->add(new Comparison($field, $value, $type, '<='));
 	}
 
 /**
@@ -223,7 +223,7 @@ class QueryExpression implements ExpressionInterface, Countable {
  * @return QueryExpression
  */
 	public function like($field, $value, $type = null) {
-		return $this->add([$field . ' LIKE' => $value], $type ? [$field => $type] : []);
+		return $this->add(new Comparison($field, $value, $type, 'LIKE'));
 	}
 
 /**
@@ -235,7 +235,7 @@ class QueryExpression implements ExpressionInterface, Countable {
  * @return QueryExpression
  */
 	public function notLike($field, $value, $type = null) {
-		return $this->add([$field . ' NOT LIKE' => $value], $type ? [$field => $type] : []);
+		return $this->add(new Comparison($field, $value, $type, 'NOT LIKE'));
 	}
 
 /**
@@ -248,7 +248,10 @@ class QueryExpression implements ExpressionInterface, Countable {
  * @return QueryExpression
  */
 	public function in($field, $values, $type = null) {
-		return $this->add([$field . ' IN' => $values], $type ? [$field => $type] : []);
+		$type = $type ?: 'string';
+		$type .= '[]';
+		$values = $values instanceof ExpressionInterface ? $values : (array)$values;
+		return $this->add(new Comparison($field, $values, $type, 'IN'));
 	}
 
 /**
@@ -261,7 +264,10 @@ class QueryExpression implements ExpressionInterface, Countable {
  * @return QueryExpression
  */
 	public function notIn($field, $values, $type = null) {
-		return $this->add([$field . ' NOT IN' => $values], $type ? [$field => $type] : []);
+		$type = $type ?: 'string';
+		$type .= '[]';
+		$values = $values instanceof ExpressionInterface ? $values : (array)$values;
+		return $this->add(new Comparison($field, $values, $type, 'NOT IN'));
 	}
 
 // @codingStandardsIgnoreStart
@@ -472,6 +478,11 @@ class QueryExpression implements ExpressionInterface, Countable {
 			$type .= $typeMultiple ? null : '[]';
 			$operator = $operator == '=' ? 'IN' : $operator;
 			$operator = $operator == '!=' ? 'NOT IN' : $operator;
+			$typeMultiple = true;
+		}
+
+		if ($typeMultiple) {
+			$value = $value instanceof ExpressionInterface ? $value : (array)$value;
 		}
 
 		return new Comparison($expression, $value, $type, $operator);

+ 86 - 0
tests/TestCase/Database/QueryTest.php

@@ -846,6 +846,92 @@ class QueryTest extends TestCase {
 	}
 
 /**
+ * Tests that calling "in" and "notIn" will cast the passed values to an array
+ *
+ * @return void
+ */
+	public function testInValueCast() {
+		$query = new Query($this->connection);
+		$result = $query
+			->select(['id'])
+			->from('comments')
+			->where(function($exp) {
+				return $exp->in('created', '2007-03-18 10:45:23', 'datetime');
+			})
+			->execute();
+		$this->assertCount(1, $result);
+		$this->assertEquals(['id' => 1], $result->fetch('assoc'));
+
+
+		$query = new Query($this->connection);
+		$result = $query
+			->select(['id'])
+			->from('comments')
+			->where(function($exp) {
+				return $exp->notIn('created', '2007-03-18 10:45:23', 'datetime');
+			})
+			->execute();
+		$this->assertCount(5, $result);
+		$this->assertEquals(['id' => 2], $result->fetch('assoc'));
+		$this->assertEquals(['id' => 3], $result->fetch('assoc'));
+		$this->assertEquals(['id' => 4], $result->fetch('assoc'));
+		$this->assertEquals(['id' => 5], $result->fetch('assoc'));
+
+		$query = new Query($this->connection);
+		$result = $query
+			->select(['id'])
+			->from('comments')
+			->where(function($exp, $q) {
+				return $exp->in(
+					'created',
+					$q->newExpr()->add("'2007-03-18 10:45:23'"),
+					'datetime'
+				);
+			})
+			->execute();
+		$this->assertCount(1, $result);
+		$this->assertEquals(['id' => 1], $result->fetch('assoc'));
+
+		$query = new Query($this->connection);
+		$result = $query
+			->select(['id'])
+			->from('comments')
+			->where(function($exp, $q) {
+				return $exp->notIn(
+					'created',
+					$q->newExpr()->add("'2007-03-18 10:45:23'"),
+					'datetime'
+				);
+			})
+			->execute();
+		$this->assertCount(5, $result);
+	}
+
+/**
+ * Tests that calling "in" and "notIn" will cast the passed values to an array
+ *
+ * @return void
+ */
+	public function testInValueCast2() {
+		$query = new Query($this->connection);
+		$result = $query
+			->select(['id'])
+			->from('comments')
+			->where(['created IN' => '2007-03-18 10:45:23'])
+			->execute();
+		$this->assertCount(1, $result);
+		$this->assertEquals(['id' => 1], $result->fetch('assoc'));
+
+		$query = new Query($this->connection);
+		$result = $query
+			->select(['id'])
+			->from('comments')
+			->where(['created NOT IN' => '2007-03-18 10:45:23'])
+			->execute();
+		$this->assertCount(5, $result);
+	}
+
+/**
  * Tests nesting query expressions both using arrays and closures
  *
  * @return void