Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Adding support fro traversing TupleComparison expressions

  • Loading branch information...
commit 9b92cc8f51220c3e3281df0ae0428a90428945ba 1 parent 6733a93
@lorenzo lorenzo authored
View
67 Cake/Database/Expression/TupleComparison.php
@@ -51,13 +51,20 @@ public function sql(ValueBinder $generator) {
$fields[] = $field instanceof ExpressionInterface ? $field->sql($generator) : $field;
}
- $values = $this->_extractValues($generator);
+ $values = $this->_stringifyValues($generator);
$field = implode(', ', $fields);
return sprintf($template, $field, $this->_conjunction, $values);
}
- protected function _extractValues($generator) {
+/**
+ * Returns a string with the values as placeholders in a string to be used
+ * for the SQL version of this expression
+ *
+ * @param \Cake\Database\ValueBiender $generator
+ * @return string
+ */
+ protected function _stringifyValues($generator) {
$values = [];
foreach ($this->getValue() as $i => $value) {
if ($value instanceof ExpressionInterface) {
@@ -65,10 +72,8 @@ protected function _extractValues($generator) {
continue;
}
- $multi = in_array(strtolower($this->_conjunction), ['in', 'not in']);
$type = isset($this->_type[$i]) ? $this->_type[$i] : null;
-
- if ($multi || strpos($type, '[]') !== false) {
+ if ($this->_isMulti($i, $type)) {
$type = str_replace('[]', '', $type);
$value = $this->_flattenValue($value, $generator, $type);
$values[] = "($value)";
@@ -81,4 +86,56 @@ protected function _extractValues($generator) {
return implode(', ', $values);
}
+/*
+ * Traverses the tree of expressions stored in this object, visiting first
+ * expressions in the left hand side and the the rest.
+ *
+ * Callback function receives as only argument an instance of a ExpresisonInterface
+ *
+ * @param callable $callable
+ * @return void
+ */
+ public function traverse(callable $callable) {
+ foreach ($this->getField() as $field) {
+ $this->_traverseValue($field, $callable);
+ }
+ foreach ($this->getValue() as $i => $value) {
+ $type = isset($this->_type[$i]) ? $this->_type[$i] : null;
+ if ($this->_isMulti($type)) {
+ foreach ($value as $v) {
+ $this->_traverseValue($v, $callable);
+ }
+ } else {
+ $this->_traverseValue($value, $callable);
+ }
+ }
+ }
+
+/**
+ * Conditionally executes the callback for the passed value if
+ * it is an ExpressionInterface
+ *
+ * @param mixed $value
+ * @Param callable $callable
+ * @return void
+ */
+ protected function _traverseValue($value, $callable) {
+ if ($value instanceof ExpressionInterface) {
+ $callable($value);
+ $value->traverse($callable);
+ }
+ }
+
+/**
+ * Determines if each of the values in this expressions is a tuple in
+ * itself
+ *
+ * @param string $type the type to bind for values
+ * @return boolean
+ */
+ protected function _isMulti($type) {
+ $multi = in_array(strtolower($this->_conjunction), ['in', 'not in']);
+ return $multi || strpos($type, '[]') !== false;
+ }
+
}
View
35 Test/TestCase/Database/Expression/TupleComparisonTest.php
@@ -75,7 +75,6 @@ public function testTupleWithExpressionValues() {
* @return void
*/
public function testTupleWithInComparison() {
- $value1 = new QueryExpression(['a' => 1]);
$f = new TupleComparison(
['field1', 'field2'],
[[1, 2], [3, 4]],
@@ -90,4 +89,38 @@ public function testTupleWithInComparison() {
$this->assertSame(4, $binder->bindings()[':c3']['value']);
}
+/**
+ * Tests traversing
+ *
+ * @return void
+ */
+ public function testTraverse() {
+ $value1 = new QueryExpression(['a' => 1]);
+ $field2 = new QueryExpression(['b' => 2]);
+ $f = new TupleComparison(['field1', $field2], [$value1, 2], ['integer', 'integer'], '=');
+ $binder = new ValueBinder;
+ $expressions = [];
+
+ $collector = function($e) use (&$expressions) {
+ $expressions[] = $e;
+ };
+
+ $f->traverse($collector);
+ $this->assertCount(4, $expressions);
+ $this->assertSame($field2, $expressions[0]);
+ $this->assertSame($value1, $expressions[2]);
+
+ $f = new TupleComparison(
+ ['field1', $field2],
+ [[1, 2], [3, $value1]],
+ ['integer', 'integer'],
+ 'IN'
+ );
+ $expressions = [];
+ $f->traverse($collector);
+ $this->assertCount(4, $expressions);
+ $this->assertSame($field2, $expressions[0]);
+ $this->assertSame($value1, $expressions[2]);
+ }
+
}
Please sign in to comment.
Something went wrong with that request. Please try again.