Navigation Menu

Skip to content

Commit

Permalink
Start adding columnType()
Browse files Browse the repository at this point in the history
SqlDialects will need a way to convert from platform specific types to
the abstract ones used in the rest of the framework.
  • Loading branch information
markstory committed Mar 25, 2013
1 parent dbd2469 commit 001ecae
Show file tree
Hide file tree
Showing 2 changed files with 200 additions and 6 deletions.
53 changes: 51 additions & 2 deletions lib/Cake/Model/Datasource/Database/Dialect/MysqlDialectTrait.php
Expand Up @@ -17,6 +17,8 @@
*/
namespace Cake\Model\Datasource\Database\Dialect;

use Cake\Error;

/**
* Contains functions that encapsulates the SQL dialect used by MySQL,
* including query translators and schema introspection.
Expand All @@ -30,7 +32,7 @@ trait MysqlDialectTrait {
* getting tables from.
* @return array An array of (sql, params) to execute.
*/
public function listTablesSql($config) {
public function listTablesSql(array $config) {
return ["SHOW TABLES FROM " . $this->quoteIdentifier($config['database']), []];
}

Expand All @@ -41,7 +43,54 @@ public function listTablesSql($config) {
* @return array An array of (sql, params) to execute.
*/
public function describeTableSql($table) {
return ["SHOW TABLES FROM " . $this->quoteIdentifier($table), []];
return ["SHOW FULL COLUMNS FROM " . $this->quoteIdentifier($table), []];
}

/**
* Convert a MySQL column type into an abstract type.
*
* @param string $column The column type + length
* @return array List of (type, length)
*/
public function columnType($column) {
preg_match('/([a-z]+)(?:\(([0-9,]+)\))?/i', $column, $matches);
if (empty($matches)) {
throw new Error\Exception(__d('cake_dev', 'Unable to parse column type from "%s"', $column));
}

$col = strtolower($matches[1]);
$length = null;
if (isset($matches[2])) {
$length = (int)$matches[2];
}

if (in_array($col, array('date', 'time', 'datetime', 'timestamp'))) {
return [$col, $length];
}
if (($col === 'tinyint' && $length === 1) || $col === 'boolean') {
return ['boolean', null];
}
if (strpos($col, 'bigint') !== false || $col === 'bigint') {
return ['biginteger', $length];
}
if (strpos($col, 'int') !== false) {
return ['integer', $length];
}
if (strpos($col, 'char') !== false || $col === 'tinytext') {
return ['string', $length];
}
if (strpos($col, 'text') !== false) {
return ['text', $length];
}
if (strpos($col, 'blob') !== false || $col === 'binary') {
return ['binary', $length];
}
if (strpos($col, 'float') !== false || strpos($col, 'double') !== false) {
return ['float', $length];
}
if (strpos($col, 'decimal') !== false) {
return ['decimal', null];
}
return 'text';
}
}
153 changes: 149 additions & 4 deletions lib/Cake/Test/TestCase/Model/Datasource/Database/Driver/MysqlTest.php
Expand Up @@ -27,13 +27,23 @@
*/
class MysqlTest extends \Cake\TestSuite\TestCase {

/**
* setUp
*
* @return void
*/
public function setUp() {
parent::setUp();
$config = Configure::read('Datasource.test');
$this->skipIf(strpos($config['datasource'], 'Mysql') === false, 'Not using Mysql for test config');
}
/**
* Test connecting to Mysql with default configuration
*
* @return void
*/
public function testConnectionConfigDefault() {
$driver = $this->getMock('Cake\Model\Datasource\Database\driver\Mysql', ['_connect']);
$driver = $this->getMock('Cake\Model\Datasource\Database\Driver\Mysql', ['_connect']);
$expected = [
'persistent' => true,
'host' => 'localhost',
Expand Down Expand Up @@ -65,7 +75,7 @@ public function testConnectionConfigDefault() {
* @return void
*/
public function testConnectionConfigCustom() {
$driver = $this->getMock('Cake\Model\Datasource\Database\driver\Mysql', ['_connect']);
$driver = $this->getMock('Cake\Model\Datasource\Database\Driver\Mysql', ['_connect']);
$config = [
'persistent' => false,
'host' => 'foo',
Expand Down Expand Up @@ -93,17 +103,114 @@ public function testConnectionConfigCustom() {
$driver->connect($config);
}

/**
* Helper method for testing methods.
*
* @return void
*/
protected function _createTables($connection) {
$connection->execute('DROP TABLE IF EXISTS articles');
$connection->execute('DROP TABLE IF EXISTS authors');

$table = 'CREATE TABLE authors(id int, name varchar(50))';
$table = <<<SQL
CREATE TABLE authors(
id INT(11) PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50),
bio TEXT,
created DATETIME
)
SQL;
$connection->execute($table);

$table = 'CREATE TABLE articles(id int, title varchar(20), body varchar(50), author_id int)';
$table = <<<SQL
CREATE TABLE articles(
id BIGINT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(20),
body TEXT,
author_id INT(11) NOT NULL,
created DATETIME
)
SQL;
$connection->execute($table);
}

/**
* Dataprovider for column testing
*
* @return array
*/
public static function columnProvider() {
return [
[
'DATETIME',
['datetime', null]
],
[
'DATE',
['date', null]
],
[
'TIME',
['time', null]
],
[
'TINYINT(1)',
['boolean', null]
],
[
'TINYINT(2)',
['integer', 2]
],
[
'BIGINT',
['biginteger', null]
],
[
'VARCHAR(255)',
['string', 255]
],
[
'CHAR(25)',
['string', 25]
],
[
'TINYTEXT',
['string', null]
],
[
'BLOB',
['binary', null]
],
[
'MEDIUMBLOB',
['binary', null]
],
[
'FLOAT',
['float', null]
],
[
'DOUBLE',
['float', null]
],
[
'DECIMAL(11,2)',
['decimal', null]
],
];
}

/**
* Test parsing MySQL column types.
*
* @dataProvider columnProvider
* @return void
*/
public function testColumnType($input, $expected) {
$driver = $this->getMock('Cake\Model\Datasource\Database\Driver\Mysql', ['_connect']);
$this->assertEquals($driver->columnType($input), $expected);
}

/**
* Test listing tables with Mysql
*
Expand All @@ -126,5 +233,43 @@ public function testListTables() {
* @return void
*/
public function testDescribeTable() {
$connection = new Connection(Configure::read('Datasource.test'));
$this->_createTables($connection);

$result = $connection->describe('articles');
$expected = [
'id' => [
'type' => 'biginteger',
'null' => false,
'default' => null,
'length' => 8,
'primary' => true
],
'title' => [
'type' => 'string',
'null' => true,
'default' => null,
'length' => 20,
],
'body' => [
'type' => 'text',
'null' => true,
'default' => null,
'length' => null,
],
'author_id' => [
'type' => 'integer',
'null' => false,
'default' => null,
'length' => 11,
],
'created' => [
'type' => 'datetime',
'null' => true,
'default' => null,
'length' => null,
],
];
$this->assertEquals($expected, $result);
}
}

0 comments on commit 001ecae

Please sign in to comment.