diff --git a/cake/libs/controller/pages_controller.php b/cake/libs/controller/pages_controller.php index ecaf125db..b26f71a74 100644 --- a/cake/libs/controller/pages_controller.php +++ b/cake/libs/controller/pages_controller.php @@ -67,7 +67,7 @@ class PagesController extends AppController { if (!$count) { $this->redirect('/'); } - $page = $subpage = $title = null; + $page = $subpage = $title_for_layout = null; if (!empty($path[0])) { $page = $path[0]; @@ -76,9 +76,9 @@ class PagesController extends AppController { $subpage = $path[1]; } if (!empty($path[$count - 1])) { - $title = Inflector::humanize($path[$count - 1]); + $title_for_layout = Inflector::humanize($path[$count - 1]); } - $this->set(compact('page', 'subpage', 'title')); + $this->set(compact('page', 'subpage', 'title_for_layout')); $this->render(implode('/', $path)); } } diff --git a/cake/libs/model/datasources/dbo/dbo_postgres.php b/cake/libs/model/datasources/dbo/dbo_postgres.php index 25f3cb03a..6a5b5a5b9 100644 --- a/cake/libs/model/datasources/dbo/dbo_postgres.php +++ b/cake/libs/model/datasources/dbo/dbo_postgres.php @@ -440,9 +440,23 @@ class DboPostgres extends DboSource { } $count = count($fields); - if ($count >= 1 && $fields[0] != '*' && strpos($fields[0], 'COUNT(*)') === false) { + if ($count >= 1 && strpos($fields[0], 'COUNT(*)') === false) { + $result = array(); for ($i = 0; $i < $count; $i++) { if (!preg_match('/^.+\\(.*\\)/', $fields[$i]) && !preg_match('/\s+AS\s+/', $fields[$i])) { + if (substr($fields[$i], -1) == '*') { + if (strpos($fields[$i], '.') !== false && $fields[$i] != $alias . '.*') { + $build = explode('.', $fields[$i]); + $AssociatedModel = $model->{$build[0]}; + } else { + $AssociatedModel = $model; + } + + $_fields = $this->fields($AssociatedModel, $AssociatedModel->alias, array_keys($AssociatedModel->schema())); + $result = array_merge($result, $_fields); + continue; + } + $prepend = ''; if (strpos($fields[$i], 'DISTINCT') !== false) { $prepend = 'DISTINCT '; @@ -455,12 +469,40 @@ class DboPostgres extends DboSource { $build = explode('.', $fields[$i]); $fields[$i] = $prepend . $this->name($build[0]) . '.' . $this->name($build[1]) . ' AS ' . $this->name($build[0] . '__' . $build[1]); } + } else { + $fields[$i] = preg_replace_callback('/\(([\s\.\w]+)\)/', array(&$this, '__quoteFunctionField'), $fields[$i]); } + $result[] = $fields[$i]; } + return $result; } return $fields; } +/** + * Auxiliary function to quote matched `(Model.fields)` from a preg_replace_callback call + * + * @param string matched string + * @return string quoted strig + * @access private + */ + function __quoteFunctionField($match) { + $prepend = ''; + if (strpos($match[1], 'DISTINCT') !== false) { + $prepend = 'DISTINCT '; + $match[1] = trim(str_replace('DISTINCT', '', $match[1])); + } + if (strpos($match[1], '.') === false) { + $match[1] = $this->name($alias . '.' . $match[1]); + } else { + $parts = explode('.', $match[1]); + if (!Set::numeric($parts)) { + $match[1] = $this->name($match[1]); + } + } + return '(' . $prepend .$match[1] . ')'; + } + /** * Returns an array of the indexes in given datasource name. * diff --git a/cake/libs/model/datasources/dbo_source.php b/cake/libs/model/datasources/dbo_source.php index 5acc931e1..8c3da9226 100755 --- a/cake/libs/model/datasources/dbo_source.php +++ b/cake/libs/model/datasources/dbo_source.php @@ -2327,7 +2327,7 @@ class DboSource extends DataSource { } /** - * Auxiliary function to qoute matches `Model.fields` from a preg_replace_callback call + * Auxiliary function to quote matches `Model.fields` from a preg_replace_callback call * * @param string matched string * @return string quoted strig diff --git a/cake/tests/cases/libs/model/datasources/dbo/dbo_postgres.test.php b/cake/tests/cases/libs/model/datasources/dbo/dbo_postgres.test.php index 28f9d7338..38f3a28af 100644 --- a/cake/tests/cases/libs/model/datasources/dbo/dbo_postgres.test.php +++ b/cake/tests/cases/libs/model/datasources/dbo/dbo_postgres.test.php @@ -84,6 +84,18 @@ class PostgresTestModel extends Model { */ var $useTable = false; +/** + * belongsTo property + * + * @var array + * @access public + */ + var $belongsTo = array( + 'PostgresClientTestModel' => array( + 'foreignKey' => 'client_id' + ) + ); + /** * find method * @@ -142,6 +154,47 @@ class PostgresTestModel extends Model { } } +/** + * PostgresClientTestModel class + * + * @package cake + * @subpackage cake.tests.cases.libs.model.datasources + */ +class PostgresClientTestModel extends Model { + +/** + * name property + * + * @var string 'PostgresClientTestModel' + * @access public + */ + var $name = 'PostgresClientTestModel'; + +/** + * useTable property + * + * @var bool false + * @access public + */ + var $useTable = false; + +/** + * schema method + * + * @access public + * @return void + */ + function schema() { + return array( + 'id' => array('type' => 'integer', 'null' => '', 'default' => '', 'length' => '8', 'key' => 'primary'), + 'name' => array('type' => 'string', 'null' => '', 'default' => '', 'length' => '255'), + 'email' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '155'), + 'created' => array('type' => 'datetime', 'null' => '1', 'default' => '', 'length' => ''), + 'updated' => array('type' => 'datetime', 'null' => '1', 'default' => '', 'length' => null) + ); + } +} + /** * DboPostgresTest class * @@ -227,13 +280,12 @@ class DboPostgresTest extends CakeTestCase { } /** - * Test field and value quoting method + * Test field quoting method * * @access public */ - function testQuoting() { - $result = $this->db2->fields($this->model); - $expected = array( + function testFieldQuoting() { + $fields = array( '"PostgresTestModel"."id" AS "PostgresTestModel__id"', '"PostgresTestModel"."client_id" AS "PostgresTestModel__client_id"', '"PostgresTestModel"."name" AS "PostgresTestModel__name"', @@ -253,15 +305,29 @@ class DboPostgresTest extends CakeTestCase { '"PostgresTestModel"."created" AS "PostgresTestModel__created"', '"PostgresTestModel"."updated" AS "PostgresTestModel__updated"' ); + + $result = $this->db->fields($this->model); + $expected = $fields; $this->assertEqual($result, $expected); - $expected = "'1.2'"; - $result = $this->db2->value(1.2, 'float'); - $this->assertIdentical($expected, $result); + $result = $this->db->fields($this->model, null, 'PostgresTestModel.*'); + $expected = $fields; + $this->assertEqual($result, $expected); - $expected = "'1,2'"; - $result = $this->db2->value('1,2', 'float'); - $this->assertIdentical($expected, $result); + $result = $this->db->fields($this->model, null, array('*', 'AnotherModel.id', 'AnotherModel.name')); + $expected = array_merge($fields, array( + '"AnotherModel"."id" AS "AnotherModel__id"', + '"AnotherModel"."name" AS "AnotherModel__name"')); + $this->assertEqual($result, $expected); + + $result = $this->db->fields($this->model, null, array('*', 'PostgresClientTestModel.*')); + $expected = array_merge($fields, array( + '"PostgresClientTestModel"."id" AS "PostgresClientTestModel__id"', + '"PostgresClientTestModel"."name" AS "PostgresClientTestModel__name"', + '"PostgresClientTestModel"."email" AS "PostgresClientTestModel__email"', + '"PostgresClientTestModel"."created" AS "PostgresClientTestModel__created"', + '"PostgresClientTestModel"."updated" AS "PostgresClientTestModel__updated"')); + $this->assertEqual($result, $expected); } /** @@ -286,6 +352,9 @@ class DboPostgresTest extends CakeTestCase { * @return void */ function testValueQuoting() { + $this->assertIdentical($this->db2->value(1.2, 'float'), "'1.2'"); + $this->assertEqual($this->db2->value('1,2', 'float'), "'1,2'"); + $this->assertEqual($this->db2->value('0', 'integer'), "'0'"); $this->assertEqual($this->db2->value('', 'integer'), 'NULL'); $this->assertEqual($this->db2->value('', 'float'), 'NULL'); @@ -682,9 +751,12 @@ class DboPostgresTest extends CakeTestCase { $this->db->query($this->db->dropSchema($schema1)); } - /** - * Test it is possible to use virtual field with postgresql - */ +/* + * Test it is possible to use virtual field with postgresql + * + * @access public + * @return void + */ function testVirtualFields() { $this->loadFixtures('Article', 'Comment'); $Article = new Article; @@ -701,13 +773,27 @@ class DboPostgresTest extends CakeTestCase { $this->assertEqual($result['Article']['subquery'], 6); } - /** - * Tests additional order options for postgres - */ +/** + * Tests additional order options for postgres + * + * @access public + * @return void + */ function testOrderAdditionalParams() { $result = $this->db->order(array('title' => 'DESC NULLS FIRST', 'body' => 'DESC')); $expected = ' ORDER BY "title" DESC NULLS FIRST, "body" DESC'; $this->assertEqual($result, $expected); } + +/** +* Test it is possible to do a SELECT COUNT(DISTINCT Model.field) query in postgres and it gets correctly quoted +*/ + function testQuoteDistinctInFunction() { + $this->loadFixtures('Article'); + $Article = new Article; + $result = $this->db->fields($Article, null, array('COUNT(DISTINCT Article.id)')); + $expected = array('COUNT(DISTINCT "Article"."id")'); + $this->assertEqual($result, $expected); + } } ?> \ No newline at end of file