Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Enclosing virtual fields in parentheses to avoid SQL errors

Added new tests to improve  code coverage on virtual fields
  • Loading branch information...
commit 8f29f59c1a61bf44b80b7f2dc44df2d2fccaacd4 1 parent c65e2f3
@lorenzo lorenzo authored
View
8 cake/libs/model/datasources/dbo_source.php
@@ -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);
}
View
121 cake/tests/cases/libs/model/datasources/dbo_source.test.php
@@ -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);
+ }
}
?>
Please sign in to comment.
Something went wrong with that request. Please try again.