Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

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...
commit befb1e3296c2de97dfd2c89e2a5ec249fc66a9da 1 parent 277422c
@lorenzo lorenzo authored
View
52 Cake/Database/Dialect/SqliteDialectTrait.php
@@ -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;
@@ -55,7 +58,8 @@
protected function _expressionTranslators() {
$namespace = 'Cake\Database\Expression';
return [
- $namespace . '\FunctionExpression' => '_transformFunctionExpression'
+ $namespace . '\FunctionExpression' => '_transformFunctionExpression',
+ $namespace . '\TupleComparison' => '_transformTupleComparison'
];
}
@@ -93,6 +97,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.
*
View
20 Cake/Database/Expression/TupleComparison.php
@@ -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) {
@@ -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);
}
@@ -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']);;
}
}
View
4 Cake/Database/SqlDialectTrait.php
@@ -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);
}
}
});
Please sign in to comment.
Something went wrong with that request. Please try again.