Skip to content

Commit

Permalink
Automatic identifier quoting for insert queries
Browse files Browse the repository at this point in the history
  • Loading branch information
lorenzo committed Nov 6, 2013
1 parent e4e6a4a commit d2f7819
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 17 deletions.
6 changes: 5 additions & 1 deletion Cake/Database/Query.php
Expand Up @@ -1228,7 +1228,11 @@ public function insert($table, $columns, $types = []) {
$this->_dirty();
$this->_type = 'insert';
$this->_parts['insert'] = [$table, $columns];
$this->_parts['values'] = new ValuesExpression($columns, $types + $this->defaultTypes());

if (!$this->_parts['values']) {
$this->_parts['values'] = new ValuesExpression($columns, $types + $this->defaultTypes());
}

return $this;
}

Expand Down
36 changes: 29 additions & 7 deletions Cake/Database/SqlDialectTrait.php
Expand Up @@ -77,7 +77,10 @@ public function quoteIdentifier($identifier) {
public function queryTranslator($type) {
return function($query) use ($type) {
if ($this->autoQuoting()) {
$binder = $query->valueBinder();
$query->valueBinder(false);
$query = $this->_quoteQueryIdentifiers($type, $query);
$query->valueBinder($binder);
}

$query = $this->{'_' . $type . 'QueryTranslator'}($query);
Expand Down Expand Up @@ -189,20 +192,20 @@ protected function _transformDistinct($query) {
* @return Query
*/
protected function _quoteQueryIdentifiers($type, $query) {
if ($type !== 'select') {
return $query;
if ($type === 'insert') {
return $this->_quoteInsertIdentifiers($query);
}

$binder = $query->valueBinder();
$query->valueBinder(false);
$quoter = function($part) use ($query) {
$result = [];
foreach ((array)$query->clause($part) as $alias => $value) {
$value = !is_string($value) ? $value : $this->quoteIdentifier($value);
$alias = is_numeric($alias) ? $alias : $this->quoteIdentifier($alias);
$result[$alias] = $value;
}
$query->{$part}($result, true);
if ($result) {
$query->{$part}($result, true);
}
};

if (is_array($query->clause('distinct'))) {
Expand All @@ -224,8 +227,27 @@ protected function _quoteQueryIdentifiers($type, $query) {

$result[$alias] = $value;
}
$query->join($result, [], true);
$query->valueBinder($binder);

if ($result) {
$query->join($result, [], true);
}

return $query;
}

/**
* Quotes the table name and columns for an insert query
*
* @param Query $query
* @return Query
*/
protected function _quoteInsertIdentifiers($query) {
list($table, $columns) = $query->clause('insert');
$table = $this->quoteIdentifier($table);
foreach ($columns as &$column) {
$column = $this->quoteIdentifier($column);
}
$query->insert($table, $columns);
return $query;
}

Expand Down
21 changes: 12 additions & 9 deletions Cake/Test/TestCase/Database/QueryTest.php
Expand Up @@ -1515,7 +1515,7 @@ public function testDeleteWithFrom() {
->where('1 = 1');

$result = $query->sql();
$this->assertContains('DELETE FROM authors', $result);
$this->assertRegExp('/^DELETE FROM [`"]?authors[`"]?/', $result);

$result = $query->execute();
$this->assertInstanceOf('Cake\Database\StatementInterface', $result);
Expand All @@ -1534,7 +1534,7 @@ public function testDeleteNoFrom() {
->where('1 = 1');

$result = $query->sql();
$this->assertContains('DELETE FROM authors ', $result);
$this->assertRegExp('/^DELETE FROM [`"]?authors[`"]? /', $result);

$result = $query->execute();
$this->assertInstanceOf('Cake\Database\StatementInterface', $result);
Expand All @@ -1553,8 +1553,8 @@ public function testSelectAndDeleteOnSameQuery() {
->where('1 = 1');
$result = $query->sql();

$this->assertContains('DELETE FROM authors', $result);
$this->assertContains('authors WHERE 1 = 1', $result);
$this->assertRegExp('/^DELETE FROM [`"]?authors[`"]? /', $result);
$this->assertContains(' WHERE 1 = 1', $result);
}

/**
Expand Down Expand Up @@ -1676,8 +1676,8 @@ public function testInsertSimple() {
'body' => 'test insert'
]);
$result = $query->sql();
$this->assertContains(
'INSERT INTO articles (title, body) VALUES (?, ?)',
$this->assertRegExp(
'/INSERT INTO [`"]articles[`"] \([`"]title[`"], [`"]body[`"]\) VALUES \(\?, \?\)/',
$result
);

Expand Down Expand Up @@ -1709,8 +1709,8 @@ public function testInsertSparseRow() {
'title' => 'mark',
]);
$result = $query->sql();
$this->assertContains(
'INSERT INTO articles (title, body) VALUES (?, ?)',
$this->assertRegExp(
'/INSERT INTO [`"]articles[`"] \([`"]title[`"], [`"]body[`"]\) VALUES \(\?, \?\)/',
$result
);

Expand Down Expand Up @@ -1785,7 +1785,10 @@ public function testInsertFromSelect() {
->values($select);

$result = $query->sql();
$this->assertContains('INSERT INTO articles (title, body, author_id) SELECT', $result);
$this->assertRegExp(
'/INSERT INTO [`"]articles[`"] \([`"]title[`"], [`"]body[`"], [`"]author_id[`"]\) SELECT/',
$result
);
$this->assertRegExp(
'/SELECT ["`]?name["`]?, \'some text\', 99 FROM ["`]?authors["`]?/',
$result);
Expand Down

0 comments on commit d2f7819

Please sign in to comment.