Skip to content
Permalink
Browse files

Translating multi row insert in SQLite, all tests passing in all

drivers!
  • Loading branch information...
lorenzo committed Mar 17, 2013
1 parent f00bb63 commit 91b3c6c73a7196b9143b6f13cf5152d8b4772437
@@ -17,6 +17,7 @@
*/
namespace Cake\Model\Datasource\Database\Dialect;
use Cake\Model\Datasource\Database\Expression;
use Cake\Model\Datasource\Database\Expression\FunctionExpression;
use Cake\Model\Datasource\Database\Query;
@@ -68,4 +69,43 @@ protected function _transformFunctionExpression(FunctionExpression $expression)
}
}
/**
* Transforms an insert query that is meant to insert multiple tows at a time,
* otherwise it leaves the query untouched.
*
* The way SQLite works with multi insert is by having multiple select statements
* joined with UNION.
*
* @return Query
*/
protected function _insertQueryTranslator($query) {
$v = $query->clause('values');
if (count($v->values()) === 1) {
return $query;
}
$cols = $v->columns();
$newQuery = $query->connection()->newQuery();
$values = [];
foreach ($v->values() as $k => $val) {
$values[] = $val;
$val = array_merge($val, array_fill(0, count($cols) - count($val), null));
$val = array_map(function($val) {
return $val instanceof Expression ? $val : '?';
}, $val);
if ($k === 0) {
array_unshift($values, $newQuery->select(array_combine($cols, $val)));
continue;
}
$q = $newQuery->connection()->newQuery();
$newQuery->union($q->select(array_combine($cols, $val)), true);
}
$v = clone $v;
$v->values($values);
return $query->values($v);
}
}
@@ -93,6 +93,36 @@ public function add($data) {
$this->_values[] = $data;
}
/**
* Sets the columns to be inserted. If no params are passed, then it returns
* the currently stored columns
*
* @param array $cols arrays with columns to be inserted
* @return array|ValuesExpression
*/
public function columns($cols = null) {
if ($cols === null) {
return $this->_columns;
}
$this->_columns = $cols;
return $this;
}
/**
* Sets the values to be inserted. If no params are passed, then it returns
* the currently stored values
*
* @param array $cols arrays with values to be inserted
* @return array|ValuesExpression
*/
public function values($values = null) {
if ($values === null) {
return $this->_values;
}
$this->_values = $values;
return $this;
}
/**
* Convert the rows of data into a format that works with Query::_bindParams()
*
@@ -128,7 +158,7 @@ public function sql() {
if (empty($this->_values)) {
return '';
}
if ($this->_hasQuery) {
if ($this->_values[0] instanceof Query) {
return ' ' . $this->_values[0]->sql();
}
$placeholders = [];
@@ -174,9 +174,6 @@ public function connection($connection = null) {
* @return Cake\Model\Datasource\Database\Statement
*/
public function execute() {
$this->_transformedQuery = null;
$this->_dirty = false;
$query = $this->_transformQuery();
$statement = $this->_connection->prepare($query->sql(false));
$query->_bindStatement($statement);
@@ -1197,7 +1194,13 @@ public function values($data) {
__d('cake_dev', 'You cannot add values before defining columns to use.')
);
}
$this->_dirty = true;
if ($data instanceof ValuesExpression) {
$this->_parts['values'] = $data;
return $this;
}
$this->_parts['values']->add($data);
return $this;
}
@@ -1449,7 +1452,7 @@ protected function _bindStatement($statement) {
$statement->bind($params, $types);
};
$this->_transformQuery()->traverseExpressions($binder);
$this->traverseExpressions($binder);
}
/**

0 comments on commit 91b3c6c

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