|
|
@@ -18,6 +18,7 @@ use Cake\Database\Exception;
|
|
|
use Cake\Database\ExpressionInterface;
|
|
|
use Cake\Database\Query;
|
|
|
use Cake\Database\TypeMapTrait;
|
|
|
+use Cake\Database\Type\ExpressionTypeCasterTrait;
|
|
|
use Cake\Database\ValueBinder;
|
|
|
|
|
|
/**
|
|
|
@@ -32,6 +33,7 @@ class ValuesExpression implements ExpressionInterface
|
|
|
{
|
|
|
|
|
|
use TypeMapTrait;
|
|
|
+ use ExpressionTypeCasterTrait;
|
|
|
|
|
|
/**
|
|
|
* Array of values to insert.
|
|
|
@@ -55,6 +57,14 @@ class ValuesExpression implements ExpressionInterface
|
|
|
protected $_query = false;
|
|
|
|
|
|
/**
|
|
|
+ * Whether or not values have been casted to expressions
|
|
|
+ * already.
|
|
|
+ *
|
|
|
+ * @var string
|
|
|
+ */
|
|
|
+ protected $_castedExpressions = false;
|
|
|
+
|
|
|
+ /**
|
|
|
* Constructor
|
|
|
*
|
|
|
* @param array $columns The list of columns that are going to be part of the values.
|
|
|
@@ -88,6 +98,7 @@ class ValuesExpression implements ExpressionInterface
|
|
|
return;
|
|
|
}
|
|
|
$this->_values[] = $data;
|
|
|
+ $this->_castedExpressions = false;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -103,6 +114,7 @@ class ValuesExpression implements ExpressionInterface
|
|
|
return $this->_columns;
|
|
|
}
|
|
|
$this->_columns = $cols;
|
|
|
+ $this->_castedExpressions = false;
|
|
|
return $this;
|
|
|
}
|
|
|
|
|
|
@@ -119,6 +131,7 @@ class ValuesExpression implements ExpressionInterface
|
|
|
return $this->_values;
|
|
|
}
|
|
|
$this->_values = $values;
|
|
|
+ $this->_castedExpressions = false;
|
|
|
return $this;
|
|
|
}
|
|
|
|
|
|
@@ -150,23 +163,37 @@ class ValuesExpression implements ExpressionInterface
|
|
|
return '';
|
|
|
}
|
|
|
|
|
|
+ if (!$this->_castedExpressions) {
|
|
|
+ $this->_processExpressions();
|
|
|
+ }
|
|
|
+
|
|
|
$i = 0;
|
|
|
$defaults = array_fill_keys($this->_columns, null);
|
|
|
$placeholders = [];
|
|
|
|
|
|
+ $types = [];
|
|
|
+ $typeMap = $this->typeMap();
|
|
|
+ foreach ($defaults as $col => $v) {
|
|
|
+ $types[$col] = $typeMap->type($col);
|
|
|
+ }
|
|
|
+
|
|
|
foreach ($this->_values as $row) {
|
|
|
- $row = array_merge($defaults, $row);
|
|
|
+ $row += $defaults;
|
|
|
$rowPlaceholders = [];
|
|
|
- foreach ($row as $column => $value) {
|
|
|
+
|
|
|
+ foreach ($this->_columns as $column) {
|
|
|
+ $value = $row[$column];
|
|
|
+
|
|
|
if ($value instanceof ExpressionInterface) {
|
|
|
$rowPlaceholders[] = '(' . $value->sql($generator) . ')';
|
|
|
continue;
|
|
|
}
|
|
|
- $type = $this->typeMap()->type($column);
|
|
|
+
|
|
|
$placeholder = $generator->placeholder($i);
|
|
|
$rowPlaceholders[] = $placeholder;
|
|
|
- $generator->bind($placeholder, $value, $type);
|
|
|
+ $generator->bind($placeholder, $value, $types[$column]);
|
|
|
}
|
|
|
+
|
|
|
$placeholders[] = implode(', ', $rowPlaceholders);
|
|
|
}
|
|
|
|
|
|
@@ -192,6 +219,10 @@ class ValuesExpression implements ExpressionInterface
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+ if (!$this->_castedExpressions) {
|
|
|
+ $this->_processExpressions();
|
|
|
+ }
|
|
|
+
|
|
|
foreach ($this->_values as $v) {
|
|
|
if ($v instanceof ExpressionInterface) {
|
|
|
$v->traverse($visitor);
|
|
|
@@ -201,9 +232,41 @@ class ValuesExpression implements ExpressionInterface
|
|
|
}
|
|
|
foreach ($v as $column => $field) {
|
|
|
if ($field instanceof ExpressionInterface) {
|
|
|
+ $visitor($field);
|
|
|
$field->traverse($visitor);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Converts values that need to be casted to expressions
|
|
|
+ *
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ protected function _processExpressions()
|
|
|
+ {
|
|
|
+ $types = [];
|
|
|
+ $typeMap = $this->typeMap();
|
|
|
+
|
|
|
+ foreach ($this->_columns as $c) {
|
|
|
+ if (!is_scalar($c)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ $types[$c] = $typeMap->type($c);
|
|
|
+ }
|
|
|
+
|
|
|
+ $types = $this->_requiresToExpressionCasting($types);
|
|
|
+
|
|
|
+ if (empty($types)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ foreach ($this->_values as $row => $values) {
|
|
|
+ foreach ($types as $col => $type) {
|
|
|
+ $this->_values[$row][$col] = $type->toExpression($values[$col]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ $this->_castedExpressions = true;
|
|
|
+ }
|
|
|
}
|