Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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
José Lorenzo Rodríguez lorenzo authored
52 Cake/Database/Dialect/SqliteDialectTrait.php
View
@@ -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.
*
20 Cake/Database/Expression/TupleComparison.php
View
@@ -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']);;
}
}
4 Cake/Database/SqlDialectTrait.php
View
@@ -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.