Skip to content

Commit

Permalink
Add unsigned support to MySQL
Browse files Browse the repository at this point in the history
integer, biginteger, float and decimal types can now be unsigned in
MySQL. Both the schema reflection and generation will handle unsigned
values.
  • Loading branch information
markstory committed Nov 22, 2013
1 parent aabc2af commit 9e4c94b
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 30 deletions.
38 changes: 27 additions & 11 deletions Cake/Database/Schema/MysqlSchema.php
@@ -1,7 +1,5 @@
<?php
/**
* PHP Version 5.4
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
Expand All @@ -21,29 +19,25 @@

/**
* Schema generation/reflection features for MySQL
*
*/
class MysqlSchema extends BaseSchema {

/**
* {@inheritdoc}
*
*/
public function listTablesSql($config) {
return ['SHOW TABLES FROM ' . $this->_driver->quoteIdentifier($config['database']), []];
}

/**
* {@inheritdoc}
*
*/
public function describeTableSql($name, $config) {
return ['SHOW FULL COLUMNS FROM ' . $this->_driver->quoteIdentifier($name), []];
}

/**
* {@inheritdoc}
*
*/
public function describeIndexSql($table, $config) {
return ['SHOW INDEXES FROM ' . $this->_driver->quoteIdentifier($table), []];
Expand All @@ -59,7 +53,7 @@ public function describeIndexSql($table, $config) {
* @throws Cake\Database\Exception When column type cannot be parsed.
*/
protected function _convertColumn($column) {
preg_match('/([a-z]+)(?:\(([0-9,]+)\))?/i', $column, $matches);
preg_match('/([a-z]+)(?:\(([0-9,]+)\))?\s*([a-z]+)?/i', $column, $matches);
if (empty($matches)) {
throw new Exception(__d('cake_dev', 'Unable to parse column type from "%s"', $column));
}
Expand All @@ -81,11 +75,13 @@ protected function _convertColumn($column) {
if (($col === 'tinyint' && $length === 1) || $col === 'boolean') {
return ['type' => 'boolean', 'length' => null];
}

$unsigned = (isset($matches[3]) && strtolower($matches[3]) === 'unsigned');
if (strpos($col, 'bigint') !== false || $col === 'bigint') {
return ['type' => 'biginteger', 'length' => $length];
return ['type' => 'biginteger', 'length' => $length, 'unsigned' => $unsigned];
}
if (strpos($col, 'int') !== false) {
return ['type' => 'integer', 'length' => $length];
return ['type' => 'integer', 'length' => $length, 'unsigned' => $unsigned];
}
if ($col === 'char' && $length === 36) {
return ['type' => 'uuid', 'length' => null];
Expand All @@ -103,10 +99,20 @@ protected function _convertColumn($column) {
return ['type' => 'binary', 'length' => $length];
}
if (strpos($col, 'float') !== false || strpos($col, 'double') !== false) {
return ['type' => 'float', 'length' => $length, 'precision' => $precision];
return [
'type' => 'float',
'length' => $length,
'precision' => $precision,
'unsigned' => $unsigned
];
}
if (strpos($col, 'decimal') !== false) {
return ['type' => 'decimal', 'length' => $length, 'precision' => $precision];
return [
'type' => 'decimal',
'length' => $length,
'precision' => $precision,
'unsigned' => $unsigned
];
}
return ['type' => 'text', 'length' => null];
}
Expand Down Expand Up @@ -280,13 +286,23 @@ public function columnSql(Table $table, $name) {
if (in_array($data['type'], $hasLength, true) && isset($data['length'])) {
$out .= '(' . (int)$data['length'] . ')';
}

$hasPrecision = ['float', 'decimal'];
if (
in_array($data['type'], $hasPrecision, true) &&
(isset($data['length']) || isset($data['precision']))
) {
$out .= '(' . (int)$data['length'] . ',' . (int)$data['precision'] . ')';
}

$hasUnsigned = ['float', 'decimal', 'integer', 'biginteger'];
if (
in_array($data['type'], $hasUnsigned, true) &&
isset($data['unsigned']) && $data['unsigned'] === true
) {
$out .= ' UNSIGNED';
}

if (isset($data['null']) && $data['null'] === false) {
$out .= ' NOT NULL';
}
Expand Down
71 changes: 52 additions & 19 deletions Cake/Test/TestCase/Database/Schema/MysqlSchemaTest.php
@@ -1,7 +1,5 @@
<?php
/**
* PHP Version 5.4
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
Expand Down Expand Up @@ -63,15 +61,23 @@ public static function convertColumnProvider() {
],
[
'TINYINT(2)',
['type' => 'integer', 'length' => 2]
['type' => 'integer', 'length' => 2, 'unsigned' => false]
],
[
'INTEGER(11)',
['type' => 'integer', 'length' => 11]
['type' => 'integer', 'length' => 11, 'unsigned' => false]
],
[
'INTEGER(11) UNSIGNED',
['type' => 'integer', 'length' => 11, 'unsigned' => true]
],
[
'BIGINT',
['type' => 'biginteger', 'length' => null]
['type' => 'biginteger', 'length' => null, 'unsigned' => false]
],
[
'BIGINT UNSIGNED',
['type' => 'biginteger', 'length' => null, 'unsigned' => true]
],
[
'VARCHAR(255)',
Expand Down Expand Up @@ -99,23 +105,39 @@ public static function convertColumnProvider() {
],
[
'FLOAT',
['type' => 'float', 'length' => null, 'precision' => null]
['type' => 'float', 'length' => null, 'precision' => null, 'unsigned' => false]
],
[
'DOUBLE',
['type' => 'float', 'length' => null, 'precision' => null]
['type' => 'float', 'length' => null, 'precision' => null, 'unsigned' => false]
],
[
'DOUBLE UNSIGNED',
['type' => 'float', 'length' => null, 'precision' => null, 'unsigned' => true]
],
[
'DECIMAL(11,2) UNSIGNED',
['type' => 'decimal', 'length' => 11, 'precision' => 2, 'unsigned' => true]
],
[
'DECIMAL(11,2)',
['type' => 'decimal', 'length' => 11, 'precision' => 2]
['type' => 'decimal', 'length' => 11, 'precision' => 2, 'unsigned' => false]
],
[
'FLOAT(11,2)',
['type' => 'float', 'length' => 11, 'precision' => 2]
['type' => 'float', 'length' => 11, 'precision' => 2, 'unsigned' => false]
],
[
'FLOAT(11,2) UNSIGNED',
['type' => 'float', 'length' => 11, 'precision' => 2, 'unsigned' => true]
],
[
'DOUBLE(10,4)',
['type' => 'float', 'length' => 10, 'precision' => 4]
['type' => 'float', 'length' => 10, 'precision' => 4, 'unsigned' => false]
],
[
'DOUBLE(10,4) UNSIGNED',
['type' => 'float', 'length' => 10, 'precision' => 4, 'unsigned' => true]
],
];
}
Expand Down Expand Up @@ -222,10 +244,10 @@ public function testDescribeTable() {
'id' => [
'type' => 'biginteger',
'null' => false,
'unsigned' => false,
'default' => null,
'length' => 20,
'precision' => null,
'fixed' => null,
'comment' => null,
],
'title' => [
Expand All @@ -243,16 +265,15 @@ public function testDescribeTable() {
'default' => null,
'length' => null,
'precision' => null,
'fixed' => null,
'comment' => null,
],
'author_id' => [
'type' => 'integer',
'null' => false,
'unsigned' => false,
'default' => null,
'length' => 11,
'precision' => null,
'fixed' => null,
'comment' => null,
],
'published' => [
Expand All @@ -261,7 +282,6 @@ public function testDescribeTable() {
'default' => 0,
'length' => null,
'precision' => null,
'fixed' => null,
'comment' => null,
],
'allow_comments' => [
Expand All @@ -270,7 +290,6 @@ public function testDescribeTable() {
'default' => 0,
'length' => null,
'precision' => null,
'fixed' => null,
'comment' => null,
],
'created' => [
Expand All @@ -279,7 +298,6 @@ public function testDescribeTable() {
'default' => null,
'length' => null,
'precision' => null,
'fixed' => null,
'comment' => null,
],
];
Expand Down Expand Up @@ -392,11 +410,21 @@ public static function columnSqlProvider() {
['type' => 'integer', 'length' => 11],
'`post_id` INTEGER(11)'
],
[
'post_id',
['type' => 'integer', 'length' => 11, 'unsigned' => true],
'`post_id` INTEGER(11) UNSIGNED'
],
[
'post_id',
['type' => 'biginteger', 'length' => 20],
'`post_id` BIGINT'
],
[
'post_id',
['type' => 'biginteger', 'length' => 20, 'unsigned' => true],
'`post_id` BIGINT UNSIGNED'
],
// Decimal
[
'value',
Expand All @@ -405,8 +433,8 @@ public static function columnSqlProvider() {
],
[
'value',
['type' => 'decimal', 'length' => 11],
'`value` DECIMAL(11,0)'
['type' => 'decimal', 'length' => 11, 'unsigned' => true],
'`value` DECIMAL(11,0) UNSIGNED'
],
[
'value',
Expand All @@ -416,9 +444,14 @@ public static function columnSqlProvider() {
// Float
[
'value',
['type' => 'float'],
['type' => 'float', 'unsigned'],
'`value` FLOAT'
],
[
'value',
['type' => 'float', 'unsigned' => true],
'`value` FLOAT UNSIGNED'
],
[
'value',
['type' => 'float', 'length' => 11, 'precision' => 3],
Expand Down

0 comments on commit 9e4c94b

Please sign in to comment.