Skip to content

Commit

Permalink
Merge pull request #8207 from CakeDC/feature/uuid
Browse files Browse the repository at this point in the history
Add support for Postgres native uuid datatype
  • Loading branch information
markstory committed Feb 17, 2016
2 parents 337b95a + 19fc6ad commit 68082fa
Show file tree
Hide file tree
Showing 13 changed files with 540 additions and 8 deletions.
24 changes: 21 additions & 3 deletions lib/Cake/Model/Datasource/Database/Postgres.php
Expand Up @@ -68,7 +68,8 @@ class Postgres extends DboSource {
'binary' => array('name' => 'bytea'),
'boolean' => array('name' => 'boolean'),
'number' => array('name' => 'numeric'),
'inet' => array('name' => 'inet')
'inet' => array('name' => 'inet'),
'uuid' => array('name' => 'uuid')
);

/**
Expand Down Expand Up @@ -216,6 +217,7 @@ public function describe($model) {
$length = null;
$type = 'text';
} elseif ($c->type === 'uuid') {
$type = 'uuid';
$length = 36;
} else {
$length = (int)$c->oct_length;
Expand All @@ -241,7 +243,10 @@ public function describe($model) {
if ($model instanceof Model) {
if ($c->name === $model->primaryKey) {
$fields[$c->name]['key'] = 'primary';
if ($fields[$c->name]['type'] !== 'string') {
if (
$fields[$c->name]['type'] !== 'string' &&
$fields[$c->name]['type'] !== 'uuid'
) {
$fields[$c->name]['length'] = 11;
}
}
Expand Down Expand Up @@ -698,8 +703,10 @@ public function column($real) {
return 'biginteger';
case (strpos($col, 'int') !== false && $col !== 'interval'):
return 'integer';
case (strpos($col, 'char') !== false || $col === 'uuid'):
case (strpos($col, 'char') !== false):
return 'string';
case (strpos($col, 'uuid') !== false):
return 'uuid';
case (strpos($col, 'text') !== false):
return 'text';
case (strpos($col, 'bytea') !== false):
Expand Down Expand Up @@ -922,6 +929,17 @@ public function buildIndex($indexes, $table = null) {
return $join;
}

/**
* {@inheritDoc}
*/
public function value($data, $column = null, $null = true) {
$value = parent::value($data, $column, $null);
if ($column === 'uuid' && is_scalar($data) && $data === '') {
return 'NULL';
}
return $value;
}

/**
* Overrides DboSource::renderStatement to handle schema generation with Postgres-style indexes
*
Expand Down
2 changes: 1 addition & 1 deletion lib/Cake/Model/Model.php
Expand Up @@ -1982,7 +1982,7 @@ protected function _doSave($data = null, $options = array()) {
*/
protected function _isUUIDField($field) {
$field = $this->schema($field);
return $field['length'] == 36 && in_array($field['type'], array('string', 'binary'));
return $field['length'] == 36 && in_array($field['type'], array('string', 'binary', 'uuid'));
}

/**
Expand Down
20 changes: 17 additions & 3 deletions lib/Cake/Test/Case/Model/Datasource/Database/PostgresTest.php
Expand Up @@ -132,7 +132,8 @@ public function schema($field = false) {
'comments' => array('type' => 'text', 'null' => '1', 'default' => '', 'length' => ''),
'last_login' => array('type' => 'datetime', 'null' => '1', 'default' => '', 'length' => ''),
'created' => array('type' => 'date', 'null' => '1', 'default' => '', 'length' => ''),
'updated' => array('type' => 'datetime', 'null' => '1', 'default' => '', 'length' => null)
'updated' => array('type' => 'datetime', 'null' => '1', 'default' => '', 'length' => null),
'some_uuid' => array('type' => 'uuid', 'null' => '1', 'default' => null),
);
}

Expand Down Expand Up @@ -257,7 +258,8 @@ public function testFieldQuoting() {
'"PostgresTestModel"."comments" AS "PostgresTestModel__comments"',
'"PostgresTestModel"."last_login" AS "PostgresTestModel__last_login"',
'"PostgresTestModel"."created" AS "PostgresTestModel__created"',
'"PostgresTestModel"."updated" AS "PostgresTestModel__updated"'
'"PostgresTestModel"."updated" AS "PostgresTestModel__updated"',
'"PostgresTestModel"."some_uuid" AS "PostgresTestModel__some_uuid"'
);

$result = $this->Dbo->fields($this->model);
Expand Down Expand Up @@ -300,6 +302,7 @@ public function testColumnParsing() {
$this->assertEquals('decimal', $this->Dbo2->column('numeric'));
$this->assertEquals('float', $this->Dbo2->column('float'));
$this->assertEquals('float', $this->Dbo2->column('double precision'));
$this->assertEquals('uuid', $this->Dbo2->column('uuid'));

$result = $this->Dbo2->column('bigint');
$expected = 'biginteger';
Expand Down Expand Up @@ -336,6 +339,8 @@ public function testValueQuoting() {
$this->assertEquals("'TRUE'", $this->Dbo->value('1', 'boolean'));
$this->assertEquals("NULL", $this->Dbo->value(null, 'boolean'));
$this->assertEquals("NULL", $this->Dbo->value(array()));
$this->assertEquals("'550e8400-e29b-41d4-a716-446655440000'", $this->Dbo->value('550e8400-e29b-41d4-a716-446655440000', 'uuid'));
$this->assertEquals("NULL", $this->Dbo->value(null, 'uuid'));
}

/**
Expand Down Expand Up @@ -1150,7 +1155,7 @@ public function testDescribeUuid() {
$data = $db->describe('test_uuid_describe');

$expected = array(
'type' => 'string',
'type' => 'uuid',
'null' => false,
'default' => null,
'length' => 36,
Expand Down Expand Up @@ -1204,4 +1209,13 @@ public function testDescribeTimestamp() {
$this->assertEquals($expected, $result);
}

/**
* Test build column working for new uuid types
*/
public function testBuildColumnUuid() {
$column = array('name' => 'col1', 'type' => 'uuid');
$result = $this->Dbo2->buildColumn($column);

$this->assertEquals('"col1" uuid', $result);
}
}
4 changes: 3 additions & 1 deletion lib/Cake/Test/Case/Model/ModelTestBase.php
Expand Up @@ -59,7 +59,7 @@ abstract class BaseModelTest extends CakeTestCase {
'core.feature_set', 'core.exterior_type_category', 'core.document', 'core.device',
'core.document_directory', 'core.primary_model', 'core.secondary_model', 'core.something',
'core.something_else', 'core.join_thing', 'core.join_a', 'core.join_b', 'core.join_c',
'core.join_a_b', 'core.join_a_c', 'core.uuid', 'core.data_test', 'core.posts_tag',
'core.join_a_b', 'core.join_a_c', 'core.uuid', 'core.uuid_native', 'core.data_test', 'core.posts_tag',
'core.the_paper_monkies', 'core.person', 'core.underscore_field', 'core.node',
'core.dependency', 'core.story', 'core.stories_tag', 'core.cd', 'core.book', 'core.basket',
'core.overall_favorite', 'core.account', 'core.content', 'core.content_account',
Expand All @@ -71,6 +71,8 @@ abstract class BaseModelTest extends CakeTestCase {
'core.fruits_uuid_tag', 'core.uuid_tag', 'core.product_update_all', 'core.group_update_all',
'core.player', 'core.guild', 'core.guilds_player', 'core.armor', 'core.armors_player',
'core.bidding', 'core.bidding_message', 'core.site', 'core.domain', 'core.domains_site',
'core.uuidnativeitem', 'core.uuidnativeportfolio', 'core.uuidnativeitems_uuidnativeportfolio',
'core.uuidnativeitems_uuidnativeportfolio_numericid',
);

/**
Expand Down
80 changes: 80 additions & 0 deletions lib/Cake/Test/Case/Model/ModelWriteTest.php
Expand Up @@ -270,6 +270,26 @@ public function testAutoSaveUuid() {
$this->assertEquals(36, strlen($result['Uuid']['id']));
}

/**
* testAutoSaveUuidNative method
*
* @return void
*/
public function testAutoSaveUuidNative() {
$this->skipIf(!($this->db instanceof Postgres), 'This test is compatible with Postgres only.');

$this->loadFixtures('UuidNative');
$TestModel = new UuidNative();

$TestModel->save(array('title' => 'Test record'));
$result = $TestModel->findByTitle('Test record');
$this->assertEquals(
array('id', 'title', 'count', 'created', 'updated'),
array_keys($result['UuidNative'])
);
$this->assertEquals(36, strlen($result['UuidNative']['id']));
}

/**
* Ensure that if the id key is null but present the save doesn't fail (with an
* x sql error: "Column id specified twice")
Expand All @@ -292,6 +312,27 @@ public function testSaveUuidNull() {
$this->assertEquals(36, strlen($result['Uuid']['id']));
}

/**
* Ensure that if the id key is null but present the save doesn't fail (with an
* x sql error: "Column id specified twice")
*
* @return void
*/
public function testSaveUuidNullNative() {
$this->skipIf(!($this->db instanceof Postgres), 'This test is compatible with Postgres only.');

$this->loadFixtures('UuidNative');
$TestModel = new UuidNative();

$TestModel->save(array('title' => 'Test record', 'id' => null));
$result = $TestModel->findByTitle('Test record');
$this->assertEquals(
array('id', 'title', 'count', 'created', 'updated'),
array_keys($result['UuidNative'])
);
$this->assertEquals(36, strlen($result['UuidNative']['id']));
}

/**
* testZeroDefaultFieldValue method
*
Expand Down Expand Up @@ -2938,6 +2979,26 @@ public function testHabtmUuidWithUuidId() {
$this->assertEquals(36, strlen($result['Uuiditem'][0]['UuiditemsUuidportfolio']['id']));
}

/**
* testHabtmUuidWithUuidId method
*
* @return void
*/
public function testHabtmUuidWithUuidIdNative() {
$this->skipIf(!($this->db instanceof Postgres), 'This test is compatible with Postgres only.');
$this->loadFixtures('Uuidnativeportfolio', 'Uuidnativeitem', 'UuidnativeitemsUuidnativeportfolio', 'UuidnativeitemsUuidnativeportfolioNumericid');
$TestModel = new Uuidnativeportfolio();

$data = array('Uuidnativeportfolio' => array('name' => 'Portfolio 3'));
$data['Uuidnativeitem']['Uuidnativeitem'] = array('483798c8-c7cc-430e-8cf9-4fcc40cf8569');
$TestModel->create($data);
$TestModel->save();
$id = $TestModel->id;
$result = $TestModel->read(null, $id);
$this->assertEquals(1, count($result['Uuidnativeitem']));
$this->assertEquals(36, strlen($result['Uuidnativeitem'][0]['UuidnativeitemsUuidnativeportfolio']['id']));
}

/**
* test HABTM saving when join table has no primary key and only 2 columns.
*
Expand Down Expand Up @@ -3007,6 +3068,25 @@ public function testHabtmUuidWithNumericId() {
$this->assertEquals(1, count($result['Uuidportfolio']));
}

/**
* testHabtmUuidWithNumericId method
*
* @return void
*/
public function testHabtmUuidWithNumericIdNative() {
$this->skipIf(!($this->db instanceof Postgres), 'This test is compatible with Postgres only.');
$this->loadFixtures('Uuidnativeportfolio', 'Uuidnativeitem', 'UuidnativeitemsUuidnativeportfolioNumericid');
$TestModel = new Uuidnativeitem();

$data = array('Uuidnativeitem' => array('name' => 'Item 7', 'published' => 0));
$data['Uuidnativeportfolio']['Uuidnativeportfolio'] = array('480af662-eb8c-47d3-886b-230540cf8569');
$TestModel->create($data);
$TestModel->save();
$id = $TestModel->id;
$result = $TestModel->read(null, $id);
$this->assertEquals(1, count($result['Uuidnativeportfolio']));
}

/**
* testSaveMultipleHabtm method
*
Expand Down
93 changes: 93 additions & 0 deletions lib/Cake/Test/Case/Model/models.php
Expand Up @@ -2120,6 +2120,21 @@ class Uuid extends CakeTestModel {
public $name = 'Uuid';
}

/**
* UuidNative class
*
* @package Cake.Test.Case.Model
*/
class UuidNative extends CakeTestModel {

/**
* name property
*
* @var string
*/
public $name = 'UuidNative';
}

/**
* DataTest class
*
Expand Down Expand Up @@ -3055,6 +3070,84 @@ class UuiditemsUuidportfolioNumericid extends CakeTestModel {
public $name = 'UuiditemsUuidportfolioNumericid';
}

/**
* Uuidnativeportfolio class
*
* @package Cake.Test.Case.Model
*/
class Uuidnativeportfolio extends CakeTestModel {

/**
* name property
*
* @var string
*/
public $name = 'Uuidnativeportfolio';

/**
* hasAndBelongsToMany property
*
* @var array
*/
public $hasAndBelongsToMany = array('Uuidnativeitem');
}

/**
* Uuidnativeitem class
*
* @package Cake.Test.Case.Model
*/
class Uuidnativeitem extends CakeTestModel {

/**
* name property
*
* @var string
*/
public $name = 'Uuidnativeitem';

/**
* hasAndBelongsToMany property
*
* @var array
*/
public $hasAndBelongsToMany = array(
'Uuidnativeportfolio' => array(
'with' => 'UuidnativeitemsUuidnativeportfolioNumericid'
));

}

/**
* UuidnativeitemsUuidnativeportfolio class
*
* @package Cake.Test.Case.Model
*/
class UuidnativeitemsUuidnativeportfolio extends CakeTestModel {

/**
* name property
*
* @var string
*/
public $name = 'UuidnativeitemsUuidnativeportfolio';
}

/**
* UuidnativeitemsPortfolioNumericid class
*
* @package Cake.Test.Case.Model
*/
class UuidnativeitemsUuidnativeportfolioNumericid extends CakeTestModel {

/**
* name property
*
* @var string
*/
public $name = 'UuidnativeitemsUuidnativeportfolioNumericid';
}

/**
* TranslateTestModel class.
*
Expand Down

0 comments on commit 68082fa

Please sign in to comment.