Skip to content
Permalink
Browse files

Adding support fro traversing TupleComparison expressions

  • Loading branch information...
lorenzo committed Jan 11, 2014
1 parent 6733a93 commit 9b92cc8f51220c3e3281df0ae0428a90428945ba
@@ -51,24 +51,29 @@ 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) {
$values[] = $value->sql($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;
}
}
@@ -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]);
}
}

0 comments on commit 9b92cc8

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