Skip to content

Commit

Permalink
Enclosing virtual fields in parentheses to avoid SQL errors
Browse files Browse the repository at this point in the history
Added new tests to improve  code coverage on virtual fields
  • Loading branch information
lorenzo committed Dec 17, 2009
1 parent c65e2f3 commit 8f29f59
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 5 deletions.
8 changes: 5 additions & 3 deletions cake/libs/model/datasources/dbo_source.php
Original file line number Diff line number Diff line change
Expand Up @@ -1788,7 +1788,7 @@ function _constructVirtualFields(&$model,$alias,$fields) {
foreach ($fields as $field) {
$virtualField = $this->name("{$alias}__{$field}");
$expression = $this->__quoteFields($model->getVirtualField($field));
$virtual[] = $expression . " {$this->alias} {$virtualField}";
$virtual[] = '(' .$expression . ") {$this->alias} {$virtualField}";
}
return $virtual;
}
Expand Down Expand Up @@ -2123,7 +2123,9 @@ function __parseKey($model, $key, $value) {
break;
}
}

if ($virtual) {
return "({$key}) {$operator} {$value}";
}
return "{$key} {$operator} {$value}";
}

Expand Down Expand Up @@ -2241,7 +2243,7 @@ function order($keys, $direction = 'ASC', &$model = null) {
$key = trim($key);
if (!preg_match('/\s/', $key) && !strpos($key,'.')) {
if (is_object($model) && $model->isVirtualField($key)) {
$key = $this->__quoteFields($model->getVirtualField($key));
$key = '('.$this->__quoteFields($model->getVirtualField($key)).')';
} else {
$key = $this->name($key);
}
Expand Down
121 changes: 119 additions & 2 deletions cake/tests/cases/libs/model/datasources/dbo_source.test.php
Original file line number Diff line number Diff line change
Expand Up @@ -3609,8 +3609,8 @@ function testBuildColumn() {
$this->testDb->fieldParameters['param'] = array(
'value' => 'COLLATE',
'quote' => false,
'join' => ' ',
'column' => 'Collate',
'join' => ' ',
'column' => 'Collate',
'position' => 'beforeDefault',
'options' => array('GOOD', 'OK')
);
Expand Down Expand Up @@ -4081,5 +4081,122 @@ function testShowQuery() {
$this->assertNoPattern('/Num:/s', $contents);
$this->assertNoPattern('/Took:/s', $contents);
}

function testVirtualFields() {
$this->loadFixtures('Article');

$Article =& ClassRegistry::init('Article');
$Article->virtualFields = array(
'this_moment' => 'NOW()',
'two' => '1 + 1',
'comment_count' => 'SELECT COUNT(*) FROM ' . $this->db->fullTableName('comments') .
' WHERE Article.id = ' . $this->db->fullTableName('comments'). '.article_id'
);
$result = $this->db->fields($Article);
$expected = array(
'`Article`.`id`',
'`Article`.`user_id`',
'`Article`.`title`',
'`Article`.`body`',
'`Article`.`published`',
'`Article`.`created`',
'`Article`.`updated`',
'(NOW()) AS `Article__this_moment`',
'(1 + 1) AS `Article__two`',
'(SELECT COUNT(*) FROM comments WHERE `Article`.`id` = `comments`.`article_id`) AS `Article__comment_count`'
);
$this->assertEqual($expected,$result);

$result = $this->db->fields($Article,null,array('this_moment','title'));
$expected = array(
'`Article`.`title`',
'(NOW()) AS `Article__this_moment`',
);
$this->assertEqual($expected,$result);
}

function testVirtualFieldsInConditions() {
$this->loadFixtures('Article');

$Article =& ClassRegistry::init('Article');
$Article->virtualFields = array(
'this_moment' => 'NOW()',
'two' => '1 + 1',
'comment_count' => 'SELECT COUNT(*) FROM ' . $this->db->fullTableName('comments') .
' WHERE Article.id = ' . $this->db->fullTableName('comments'). '.article_id'
);
$conditions = array('two' => 2);
$result = $this->db->conditions($conditions,true,false,$Article);
$expected = '(1 + 1) = 2';
$this->assertEqual($expected,$result);

$conditions = array('this_moment BETWEEN ? AND ?' => array(1,2));
$expected = 'NOW() BETWEEN 1 AND 2';
$result = $this->db->conditions($conditions,true,false,$Article);
$this->assertEqual($expected,$result);

$conditions = array('comment_count >' => 5);
$expected = '(SELECT COUNT(*) FROM comments WHERE `Article`.`id` = `comments`.`article_id`) > 5';
$result = $this->db->conditions($conditions,true,false,$Article);
$this->assertEqual($expected,$result);

$conditions = array('NOT' => array('two' => 2));
$result = $this->db->conditions($conditions,true,false,$Article);
$expected = 'NOT ((1 + 1) = 2)';
$this->assertEqual($expected,$result);
}

function testVirtualFieldsInOrder() {
$this->loadFixtures('Article');

$Article =& ClassRegistry::init('Article');
$Article->virtualFields = array(
'this_moment' => 'NOW()',
'two' => '1 + 1',
);
$order = array('two','this_moment');
$result = $this->db->order($order,'ASC',$Article);
$expected = ' ORDER BY (1 + 1) ASC, (NOW()) ASC';
$this->assertEqual($expected,$result);
}

function testVirtualFieldsInCalculate() {
$this->loadFixtures('Article');

$Article =& ClassRegistry::init('Article');
$Article->virtualFields = array(
'this_moment' => 'NOW()',
'two' => '1 + 1',
'comment_count' => 'SELECT COUNT(*) FROM ' . $this->db->fullTableName('comments') .
' WHERE Article.id = ' . $this->db->fullTableName('comments'). '.article_id'
);

$result = $this->db->calculate($Article,'count',array('this_moment'));
$expected = 'COUNT(NOW()) AS `count`';
$this->assertEqual($expected,$result);

$result = $this->db->calculate($Article,'max',array('comment_count'));
$expected = 'MAX(SELECT COUNT(*) FROM comments WHERE `Article`.`id` = `comments`.`article_id`) AS `comment_count`';
$this->assertEqual($expected,$result);
}

function testVirtualFieldsFetch() {
$this->loadFixtures('Article','Comment');

$Article =& ClassRegistry::init('Article');
$Article->virtualFields = array(
'comment_count' => 'SELECT COUNT(*) FROM ' . $this->db->fullTableName('comments') .
' WHERE Article.id = ' . $this->db->fullTableName('comments'). '.article_id'
);

$conditions = array('comment_count >' => 2);
$query = 'SELECT ' . join(',',$this->db->fields($Article,null,array('id','comment_count'))) .
' FROM ' . $this->db->fullTableName($Article) . ' Article ' . $this->db->conditions($conditions,true,true,$Article);
$result = $this->db->fetchAll($query);
$expected = array(array(
'Article' => array('id' => 1, 'comment_count' => 4)
));
$this->assertEqual($expected,$result);
}
}
?>

0 comments on commit 8f29f59

Please sign in to comment.