allow data sources to provide smaller integers based on storage requirements

This commit is contained in:
Sebastien Barre 2017-03-03 21:42:58 -05:00 committed by Sebastien Barre
parent 25d746f712
commit d01f3e8aed
3 changed files with 122 additions and 5 deletions

View file

@ -117,6 +117,10 @@ class Mysql extends DboSource {
'text' => array('name' => 'text'),
'biginteger' => array('name' => 'bigint', 'limit' => '20'),
'integer' => array('name' => 'int', 'limit' => '11', 'formatter' => 'intval'),
'integer/4' => array('name' => 'int', 'limit' => '11', 'formatter' => 'intval'),
'integer/3' => array('name' => 'mediumint', 'limit' => '9', 'formatter' => 'intval'),
'integer/2' => array('name' => 'smallint', 'limit' => '6', 'formatter' => 'intval'),
'integer/1' => array('name' => 'tinyint', 'limit' => '4', 'formatter' => 'intval'),
'float' => array('name' => 'float', 'formatter' => 'floatval'),
'decimal' => array('name' => 'decimal', 'formatter' => 'floatval'),
'datetime' => array('name' => 'datetime', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'),
@ -369,6 +373,10 @@ class Mysql extends DboSource {
$fields[$column->Field]['charset'] = $charset;
}
}
$storage = $this->storageRequirement($column->Type);
if (is_numeric($storage)) {
$fields[$column->Field]['storage'] = $storage;
}
}
$this->_cacheDescription($key, $fields);
$cols->closeCursor();
@ -810,6 +818,36 @@ class Mysql extends DboSource {
return 'text';
}
/**
* Gets the storage requirement of a database-native column description, or null if unknown or N/A
*
* @param string $real Real database-layer column type (i.e. "varchar(255)")
* @return mixed An integer representing the storage requirement of the column in bytes, or null if unknown or N/A.
*/
public function storageRequirement($real) {
if (is_array($real)) {
$col = $real['name'];
} else {
$col = $real;
if (strpos($col, '(') !== false) {
list($col, $vals) = explode('(', $col);
}
}
// Base on Storage Requirements for Numeric Types
// https://dev.mysql.com/doc/refman/5.7/en/storage-requirements.html
if ($col === 'tinyint') {
return 1;
}
if ($col === 'smallint') {
return 2;
}
if ($col === 'mediumint') {
return 3;
}
return null;
}
/**
* {@inheritDoc}
*/

View file

@ -3246,6 +3246,16 @@ class DboSource extends DataSource {
return (int)$length;
}
/**
* Gets the storage requirement of a database-native column description, or null if unknown or N/A
*
* @param string $real Real database-layer column type (i.e. "varchar(255)")
* @return mixed An integer representing the storage requirement of the column in bytes, or null if unknown or N/A.
*/
public function storageRequirement($real) {
return null;
}
/**
* Translates between PHP boolean values and Database (faked) boolean values
*
@ -3459,12 +3469,16 @@ class DboSource extends DataSource {
return null;
}
if (!isset($this->columns[$type])) {
trigger_error(__d('cake_dev', 'Column type %s does not exist', $type), E_USER_WARNING);
return null;
// if a storage requirement in bytes was set, try it first (i.e. 'integer/4' before 'integer')
if (isset($storage) && isset($this->columns[$type . '/' . $storage])) {
$real = $this->columns[$type . '/' . $storage];
} else {
if (!isset($this->columns[$type])) {
trigger_error(__d('cake_dev', 'Column type %s does not exist', $type), E_USER_WARNING);
return null;
}
$real = $this->columns[$type];
}
$real = $this->columns[$type];
$out = $this->name($name) . ' ' . $real['name'];
if (isset($column['length'])) {

View file

@ -389,6 +389,36 @@ class MysqlTest extends CakeTestCase {
$expected = '`testName` CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL';
$this->assertEquals($expected, $result);
$this->Dbo->columns = $restore;
$data = array(
'name' => 'testName',
'type' => 'integer',
'storage' => 1
);
$result = $this->Dbo->buildColumn($data);
$expected = '`testName` tinyint(4)';
$this->assertEquals($expected, $result);
$this->Dbo->columns = $restore;
$data = array(
'name' => 'testName',
'type' => 'integer',
'storage' => 2
);
$result = $this->Dbo->buildColumn($data);
$expected = '`testName` smallint(6)';
$this->assertEquals($expected, $result);
$this->Dbo->columns = $restore;
$data = array(
'name' => 'testName',
'type' => 'integer',
'storage' => 3
);
$result = $this->Dbo->buildColumn($data);
$expected = '`testName` mediumint(9)';
$this->assertEquals($expected, $result);
$this->Dbo->columns = $restore;
}
/**
@ -526,6 +556,18 @@ class MysqlTest extends CakeTestCase {
$expected = 'boolean';
$this->assertEquals($expected, $result);
$result = $this->Dbo->column('tinyint(4)');
$expected = 'integer';
$this->assertEquals($expected, $result);
$result = $this->Dbo->column('smallint');
$expected = 'integer';
$this->assertEquals($expected, $result);
$result = $this->Dbo->column('mediumint');
$expected = 'integer';
$this->assertEquals($expected, $result);
$result = $this->Dbo->column('boolean');
$expected = 'boolean';
$this->assertEquals($expected, $result);
@ -3092,6 +3134,29 @@ SQL;
$this->assertSame($expected, $result);
}
/**
* test storageRequirement method
*
* @return void
*/
public function testStorageRequirement () {
$result = $this->Dbo->storageRequirement('varchar(255)');
$expected = null;
$this->assertSame($expected, $result);
$result = $this->Dbo->storageRequirement('mediumint');
$expected = 3;
$this->assertSame($expected, $result);
$result = $this->Dbo->storageRequirement('smallint');
$expected = 2;
$this->assertSame($expected, $result);
$result = $this->Dbo->storageRequirement('tinyint');
$expected = 1;
$this->assertSame($expected, $result);
}
/**
* testBuildIndex method
*