Skip to content

Commit

Permalink
Added modifiers support for UPDATE statements
Browse files Browse the repository at this point in the history
  • Loading branch information
lorenzo committed Feb 23, 2016
1 parent 4123ba1 commit 747eb2d
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 6 deletions.
38 changes: 33 additions & 5 deletions src/Database/QueryCompiler.php
Expand Up @@ -31,7 +31,6 @@ class QueryCompiler
*/
protected $_templates = [
'delete' => 'DELETE',
'update' => 'UPDATE %s',
'where' => ' WHERE %s',
'group' => ' GROUP BY %s ',
'having' => ' HAVING %s ',
Expand All @@ -56,7 +55,7 @@ class QueryCompiler
*
* @var array
*/
protected $_updateParts = ['update', 'modifier', 'set', 'where', 'epilog'];
protected $_updateParts = ['update', 'set', 'where', 'epilog'];

/**
* The list of query clauses to traverse for generating a DELETE statement
Expand Down Expand Up @@ -309,12 +308,40 @@ protected function _buildValuesPart($parts, $query, $generator)
return implode('', $this->_stringifyExpressions($parts, $generator));
}

/**
* Builds the SQL fragment for UPDATE.
*
* @param array $parts The update parts.
* @param \Cake\Database\Query $query The query that is being compiled
* @param \Cake\Database\ValueBinder $generator the placeholder generator to be used in expressions
* @return string SQL fragment.
*/
protected function _buildUpdatePart($parts, $query, $generator)
{
$table = $this->_stringifyExpressions($parts, $generator);
$modifiers = $this->_buildModifierPart($query->clause('modifier'), $query, $generator);

if ($modifiers !== null) {
$modifiers .= ' ';
}

return sprintf('UPDATE %s%s', $modifiers, implode(',', $table));
}

/**
* Builds the SQL modifier fragment
*
* @param array $parts The query modifier parts
* @param \Cake\Database\Query $query The query that is being compiled
* @param \Cake\Database\ValueBinder $generator the placeholder generator to be used in expressions
* @return string SQL fragment.
*/
protected function _buildModifierPart($parts, $query, $generator)
{
if ($parts === []) {
return null;
}
return implode(' ', $this->_stringifyExpressions($parts, $generator));
return implode(' ', $this->_stringifyExpressions($parts, $generator, false));
}

/**
Expand All @@ -323,15 +350,16 @@ protected function _buildModifierPart($parts, $query, $generator)
*
* @param array $expressions list of strings and ExpressionInterface objects
* @param \Cake\Database\ValueBinder $generator the placeholder generator to be used in expressions
* @param bool $wrap Whether to wrap each expression object with parenthesis
* @return array
*/
protected function _stringifyExpressions($expressions, $generator)
protected function _stringifyExpressions($expressions, $generator, $wrap = true)
{
$result = [];
foreach ($expressions as $k => $expression) {
if ($expression instanceof ExpressionInterface) {
$value = $expression->sql($generator);
$expression = '(' . $value . ')';
$expression = $wrap ? '(' . $value . ')' : $value;
}
$result[$k] = $expression;
}
Expand Down
5 changes: 4 additions & 1 deletion src/Database/SqlserverCompiler.php
Expand Up @@ -35,7 +35,6 @@ class SqlserverCompiler extends QueryCompiler
*/
protected $_templates = [
'delete' => 'DELETE',
'update' => 'UPDATE %s',
'where' => ' WHERE %s',
'group' => ' GROUP BY %s ',
'having' => ' HAVING %s ',
Expand Down Expand Up @@ -70,6 +69,10 @@ protected function _buildInsertPart($parts, $query, $generator)
$columns = $this->_stringifyExpressions($parts[1], $generator);
$modifiers = $this->_buildModifierPart($query->clause('modifier'), $query, $generator);

if ($modifiers !== null) {
$modifiers .= ' ';
}

return sprintf('INSERT %sINTO %s (%s) OUTPUT INSERTED.*',
$modifiers,
$table,
Expand Down
43 changes: 43 additions & 0 deletions tests/TestCase/Database/QueryTest.php
Expand Up @@ -3669,6 +3669,49 @@ public function testInsertModifiers()
);
}

/**
* Test use of modifiers in a UPDATE query
*
* Testing the generated SQL since the modifiers are usually different per driver
*
* @return void
*/
public function testUpdateModifiers()
{
$query = new Query($this->connection);
$result = $query
->update('authors')
->set('name', 'mark')
->modifier('TOP 10 PERCENT');
$this->assertQuotedQuery(
'UPDATE TOP 10 PERCENT <authors> SET <name> = :c0',
$result->sql(),
!$this->autoQuote
);

$query = new Query($this->connection);
$result = $query
->update('authors')
->set('name', 'mark')
->modifier(['TOP 10 PERCENT', 'FOO']);
$this->assertQuotedQuery(
'UPDATE TOP 10 PERCENT FOO <authors> SET <name> = :c0',
$result->sql(),
!$this->autoQuote
);

$query = new Query($this->connection);
$result = $query
->update('authors')
->set('name', 'mark')
->modifier([$query->newExpr('TOP 10 PERCENT')]);
$this->assertQuotedQuery(
'UPDATE TOP 10 PERCENT <authors> SET <name> = :c0',
$result->sql(),
!$this->autoQuote
);
}

/**
* Assertion for comparing a table's contents with what is in it.
*
Expand Down

0 comments on commit 747eb2d

Please sign in to comment.