Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Adding support for eager laoding and composite keys in Sqlite
While it has several deficiencies if one wants to use TupleComparison in
a more general sense, this covers an 80% of the cases
  • Loading branch information
lorenzo committed Jan 14, 2014
1 parent 277422c commit befb1e3
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 10 deletions.
52 changes: 51 additions & 1 deletion Cake/Database/Dialect/SqliteDialectTrait.php
Expand Up @@ -18,6 +18,9 @@

use Cake\Database\ExpressionInterface;
use Cake\Database\Expression\FunctionExpression;
use Cake\Database\Expression\IdentifierExpression;
use Cake\Database\Expression\QueryExpression;
use Cake\Database\Expression\TupleComparison;
use Cake\Database\Query;
use Cake\Database\SqlDialectTrait;

Expand Down Expand Up @@ -55,7 +58,8 @@ trait SqliteDialectTrait {
protected function _expressionTranslators() {
$namespace = 'Cake\Database\Expression';
return [
$namespace . '\FunctionExpression' => '_transformFunctionExpression'
$namespace . '\FunctionExpression' => '_transformFunctionExpression',
$namespace . '\TupleComparison' => '_transformTupleComparison'
];
}

Expand Down Expand Up @@ -92,6 +96,52 @@ protected function _transformFunctionExpression(FunctionExpression $expression)
}
}

/**
* Receives a TupleExpression and changes it so that it conforms to this
* SQL dialect.
*
* @param Cake\Database\Expression\TupleComparison
* @return void
*/
protected function _transformTupleComparison(TupleComparison $expression, $query) {
$fields = $expression->getField();

if (!is_array($fields)) {
return;
}

$value = $expression->getValue();
$op = $expression->type();

if ($value instanceof Query) {
$selected = array_values($value->clause('select'));
foreach ($fields as $i => $field) {
$value->andWhere([$field . " $op" => new IdentifierExpression($selected[$i])]);
}
$value->select(new IdentifierExpression(1), true);
$expression->field(new IdentifierExpression('1'));
$expression->type('=');
return;
}

$surrogate = $query->connection()
->newQuery()
->select(new IdentifierExpression('1'));

foreach ($value as $tuple) {
$surrogate->orWhere(function($exp) use ($fields, $tuple) {
foreach ($tuple as $i => $value) {
$exp->add([$fields[$i] => $value]);
}
return $exp;
});
}

$expression->field(new IdentifierExpression('1'));
$expression->value($surrogate);
$expression->type('=');
}

/**
* Transforms an insert query that is meant to insert multiple rows at a time,
* otherwise it leaves the query untouched.
Expand Down
20 changes: 13 additions & 7 deletions Cake/Database/Expression/TupleComparison.php
Expand Up @@ -82,7 +82,7 @@ protected function _stringifyValues($generator) {

$type = $this->_type;
$multiType = is_array($type);
$isMulti = $this->_isMulti($i, $type);
$isMulti = $this->isMulti($i, $type);
$type = $isMulti ? str_replace('[]', '', $type) : $type;

if ($isMulti) {
Expand Down Expand Up @@ -116,9 +116,17 @@ public function traverse(callable $callable) {
foreach ($this->getField() as $field) {
$this->_traverseValue($field, $callable);
}
foreach ($this->getValue() as $i => $value) {

$value = $this->getValue();
if ($value instanceof ExpressionInterface) {
$callable($value);
$value->traverse($callable);
return;
}

foreach ($value as $i => $value) {
$type = isset($this->_type[$i]) ? $this->_type[$i] : null;
if ($this->_isMulti($type)) {
if ($this->isMulti()) {
foreach ($value as $v) {
$this->_traverseValue($v, $callable);
}
Expand Down Expand Up @@ -147,12 +155,10 @@ protected function _traverseValue($value, $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;
protected function isMulti() {
return in_array(strtolower($this->_conjunction), ['in', 'not in']);;
}

}
4 changes: 2 additions & 2 deletions Cake/Database/SqlDialectTrait.php
Expand Up @@ -82,10 +82,10 @@ public function queryTranslator($type) {
return $query;
}

$query->traverseExpressions(function($expression) use ($translators) {
$query->traverseExpressions(function($expression) use ($translators, $query) {
foreach ($translators as $class => $method) {
if ($expression instanceof $class) {
$this->{$method}($expression);
$this->{$method}($expression, $query);
}
}
});
Expand Down

0 comments on commit befb1e3

Please sign in to comment.