Permalink
Browse files

Enclosing virtual fields in parentheses to avoid SQL errors

Added new tests to improve  code coverage on virtual fields
  • Loading branch information...
1 parent c65e2f3 commit 8f29f59c1a61bf44b80b7f2dc44df2d2fccaacd4 @lorenzo lorenzo committed Dec 17, 2009
@@ -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;
}
@@ -2123,7 +2123,9 @@ function __parseKey($model, $key, $value) {
break;
}
}
-
+ if ($virtual) {
+ return "({$key}) {$operator} {$value}";
+ }
return "{$key} {$operator} {$value}";
}
@@ -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);
}
@@ -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')
);
@@ -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.