Skip to content
Browse files

Implementation of table level and field level parameters support

  • Loading branch information...
1 parent 86d0a04 commit 627eff5f24cff52dce87f438bad93769c4910752 @skie skie committed
View
5 cake/libs/model/cake_schema.php
@@ -237,6 +237,7 @@ function read($options = array()) {
if (empty($tables[$Object->table])) {
$tables[$Object->table] = $this->__columns($Object);
$tables[$Object->table]['indexes'] = $db->index($Object);
+ $tables[$Object->table]['tableParameters'] = $db->readTableParameters($table);
unset($currentTables[$key]);
}
if (!empty($Object->hasAndBelongsToMany)) {
@@ -250,6 +251,7 @@ function read($options = array()) {
$key = array_search($table, $currentTables);
$tables[$Object->$class->table] = $this->__columns($Object->$class);
$tables[$Object->$class->table]['indexes'] = $db->index($Object->$class);
+ $tables[$Object->$class->table]['tableParameters'] = $db->readTableParameters($table);
unset($currentTables[$key]);
}
}
@@ -279,12 +281,15 @@ function read($options = array()) {
if (in_array($table, $systemTables)) {
$tables[$Object->table] = $this->__columns($Object);
$tables[$Object->table]['indexes'] = $db->index($Object);
+ $tables[$Object->table]['tableParameters'] = $db->readTableParameters($table);
} elseif ($models === false) {
$tables[$table] = $this->__columns($Object);
$tables[$table]['indexes'] = $db->index($Object);
+ $tables[$table]['tableParameters'] = $db->readTableParameters($table);
} else {
$tables['missing'][$table] = $this->__columns($Object);
$tables['missing'][$table]['indexes'] = $db->index($Object);
+ $tables['missing'][$table]['tableParameters'] = $db->readTableParameters($table);
}
}
}
View
83 cake/libs/model/datasources/dbo/dbo_mysql.php
@@ -76,6 +76,30 @@ class DboMysqlBase extends DboSource {
);
/**
+ * List of engine specific additional field parameters used on table creating
+ *
+ * @var array
+ * @access public
+ */
+ var $fieldParameters = array(
+ 'charset' => array('value' => 'CHARACTER SET', 'quote' => false, 'join' => ' ', 'column' => false, 'position' => 'beforeDefault'),
+ 'collate' => array('value' => 'COLLATE', 'quote' => false, 'join' => ' ', 'column' => 'Collation', 'position' => 'beforeDefault'),
+ 'comment' => array('value' => 'COMMENT', 'quote' => true, 'join' => ' ', 'column' => 'Comment', 'position' => 'afterDefault')
+ );
+
+/**
+ * List of table engine specific parameters used on table creating
+ *
+ * @var array
+ * @access public
+ */
+ var $tableParameters = array(
+ 'charset' => array('value' => 'DEFAULT CHARSET', 'quote' => false, 'join' => '=', 'column' => 'charset'),
+ 'collate' => array('value' => 'COLLATE', 'quote' => false, 'join' => '=', 'column' => 'Collation'),
+ 'engine' => array('value' => 'ENGINE', 'quote' => false, 'join' => '=', 'column' => 'Engine')
+ );
+
+/**
* MySQL column definition
*
* @var array
@@ -458,6 +482,38 @@ function listSources() {
}
/**
+ * Returns an detailed array of sources (tables) in the database.
+ *
+ * @param string $name Table name to get parameters
+ * @return array Array of tablenames in the database
+ */
+ function listDetailedSources($name = null) {
+ $condition = '';
+ if (is_string($name)) {
+ $condition = ' WHERE Name=' . $this->value($name);
+ }
+ $result = $this->query('SHOW TABLE STATUS FROM ' . $this->name($this->config['database']) . $condition . ';');
+ if (!$result) {
+ return array();
+ } else {
+ $tables = array();
+ foreach ($result as $row) {
+ $tables[$row['TABLES']['Name']] = $row['TABLES'];
+ if (!empty($row['TABLES']['Collation'])) {
+ $charset = $this->getCharsetName($row['TABLES']['Collation']);
+ if ($charset) {
+ $tables[$row['TABLES']['Name']]['charset'] = $charset;
+ }
+ }
+ }
+ if (is_string($name)) {
+ return $tables[$name];
+ }
+ return $tables;
+ }
+ }
+
+/**
* Returns an array of the fields in given table name.
*
* @param string $tableName Name of database table to inspect
@@ -469,7 +525,7 @@ function describe(&$model) {
return $cache;
}
$fields = false;
- $cols = $this->query('DESCRIBE ' . $this->fullTableName($model));
+ $cols = $this->query('SHOW FULL COLUMNS FROM ' . $this->fullTableName($model));
foreach ($cols as $column) {
$colKey = array_keys($column);
@@ -486,6 +542,17 @@ function describe(&$model) {
if (!empty($column[0]['Key']) && isset($this->index[$column[0]['Key']])) {
$fields[$column[0]['Field']]['key'] = $this->index[$column[0]['Key']];
}
+ foreach ($this->fieldParameters as $name => $value) {
+ if (!empty($column[0][$value['column']])) {
+ $fields[$column[0]['Field']][$name] = $column[0][$value['column']];
+ }
+ }
+ if (isset($fields[$column[0]['Field']]['collate'])) {
+ $charset = $this->getCharsetName($fields[$column[0]['Field']]['collate']);
+ if ($charset) {
+ $fields[$column[0]['Field']]['charset'] = $charset;
+ }
+ }
}
}
$this->__cacheDescription($this->fullTableName($model, false), $fields);
@@ -493,6 +560,20 @@ function describe(&$model) {
}
/**
+ * Query charset by collation
+ *
+ * @param string $name Collation name
+ * @return string Character set name
+ */
+ function getCharsetName($name) {
+ $cols = $this->query('SELECT CHARACTER_SET_NAME FROM INFORMATION_SCHEMA.COLLATIONS WHERE COLLATION_NAME= ' . $this->value($name) . ';');
+ if (isset($cols[0]['COLLATIONS']['CHARACTER_SET_NAME'])) {
+ return $cols[0]['COLLATIONS']['CHARACTER_SET_NAME'];
+ }
+ return false;
+ }
+
+/**
* Returns a quoted and escaped string of $data for use in an SQL statement.
*
* @param string $data String to be prepared for use in an SQL statement
View
93 cake/libs/model/datasources/dbo_source.php
@@ -92,6 +92,22 @@ class DboSource extends DataSource {
);
/**
+ * List of table engine specific parameters used on table creating
+ *
+ * @var array
+ * @access protected
+ */
+ var $tableParameters = array();
+
+/**
+ * List of engine specific additional field parameters used on table creating
+ *
+ * @var array
+ * @access protected
+ */
+ var $fieldParameters = array();
+
+/**
* Constructor
*/
function __construct($config = null, $autoConnect = true) {
@@ -1370,15 +1386,17 @@ function renderStatement($type, $data) {
return "DELETE {$alias} FROM {$table} {$aliases}{$conditions}";
break;
case 'schema':
- foreach (array('columns', 'indexes') as $var) {
+ foreach (array('columns', 'indexes', 'tableParameters') as $var) {
if (is_array(${$var})) {
${$var} = "\t" . join(",\n\t", array_filter(${$var}));
+ } else {
+ ${$var} = '';
}
}
if (trim($indexes) != '') {
$columns .= ',';
}
- return "CREATE TABLE {$table} (\n{$columns}{$indexes});";
+ return "CREATE TABLE {$table} (\n{$columns}{$indexes}){$tableParameters};";
break;
case 'alter':
break;
@@ -2334,7 +2352,7 @@ function createSchema($schema, $tableName = null) {
foreach ($schema->tables as $curTable => $columns) {
if (!$tableName || $tableName == $curTable) {
- $cols = $colList = $indexes = array();
+ $cols = $colList = $indexes = $tableParameters = array();
$primary = null;
$table = $this->fullTableName($curTable);
@@ -2345,14 +2363,16 @@ function createSchema($schema, $tableName = null) {
if (isset($col['key']) && $col['key'] == 'primary') {
$primary = $name;
}
- if ($name !== 'indexes') {
+ if ($name !== 'indexes' && $name !== 'tableParameters') {
$col['name'] = $name;
if (!isset($col['type'])) {
$col['type'] = 'string';
}
$cols[] = $this->buildColumn($col);
- } else {
+ } elseif ($name == 'indexes') {
$indexes = array_merge($indexes, $this->buildIndex($col, $table));
+ } elseif ($name == 'tableParameters') {
+ $tableParameters = array_merge($tableParameters, $this->buildTableParameters($col, $table));
}
}
if (empty($indexes) && !empty($primary)) {
@@ -2360,7 +2380,7 @@ function createSchema($schema, $tableName = null) {
$indexes = array_merge($indexes, $this->buildIndex($col, $table));
}
$columns = $cols;
- $out .= $this->renderStatement('schema', compact('table', 'columns', 'indexes')) . "\n\n";
+ $out .= $this->renderStatement('schema', compact('table', 'columns', 'indexes', 'tableParameters')) . "\n\n";
}
}
return $out;
@@ -2440,6 +2460,16 @@ function buildColumn($column) {
$column['default'] = null;
}
+ foreach ($this->fieldParameters as $paramName => $value) {
+ if (isset($column[$paramName]) && $value['position'] == 'beforeDefault') {
+ $val = $column[$paramName];
+ if ($value['quote']) {
+ $val = $this->value($val);
+ }
+ $out .= ' ' . $value['value'] . $value['join'] . $val;
+ }
+ }
+
if (isset($column['key']) && $column['key'] == 'primary' && $type == 'integer') {
$out .= ' ' . $this->columns['primary_key']['name'];
} elseif (isset($column['key']) && $column['key'] == 'primary') {
@@ -2453,6 +2483,17 @@ function buildColumn($column) {
} elseif (isset($column['null']) && $column['null'] == false) {
$out .= ' NOT NULL';
}
+
+ foreach ($this->fieldParameters as $paramName => $value) {
+ if (isset($column[$paramName]) && $value['position'] == 'afterDefault') {
+ $val = $column[$paramName];
+ if ($value['quote']) {
+ $val = $this->value($val);
+ }
+ $out .= ' ' . $value['value'] . $value['join'] . $val;
+ }
+ }
+
return $out;
}
@@ -2487,6 +2528,46 @@ function buildIndex($indexes, $table = null) {
}
/**
+ * Read additional table parameters
+ *
+ * @param array $parameters
+ * @param string $table
+ * @return array
+ */
+ function readTableParameters($name) {
+ $parameters = array();
+ if ($this->isInterfaceSupported('listDetailedSources')) {
+ $currentTableDetails = $this->listDetailedSources($name);
+ foreach ($this->tableParameters as $paramName => $parameter) {
+ if (!empty($parameter['column']) && !empty($currentTableDetails[$parameter['column']])) {
+ $parameters[$paramName] = $currentTableDetails[$parameter['column']];
+ }
+ }
+ }
+ return $parameters;
+ }
+
+/**
+ * Format parameters for create table
+ *
+ * @param array $parameters
+ * @param string $table
+ * @return array
+ */
+ function buildTableParameters($parameters, $table = null) {
+ $result = array();
+ foreach ($parameters as $name => $value) {
+ if (isset($this->tableParameters[$name])) {
+ if ($this->tableParameters[$name]['quote']) {
+ $value = $this->value($value);
+ }
+ $result[] = $this->tableParameters[$name]['value'] . $this->tableParameters[$name]['join'] . $value;
+ }
+ }
+ return $result;
+ }
+
+/**
* Guesses the data type of an array
*
* @param string $value
View
34 cake/tests/cases/libs/model/datasources/dbo/dbo_mysql.test.php
@@ -386,6 +386,40 @@ function testIndexDetection() {
}
/**
+ * testBuildColumn method
+ *
+ * @access public
+ * @return void
+ */
+ function testBuildColumn() {
+ $this->db->columns = array('varchar(255)' => 1);
+ $data = array(
+ 'name' => 'testName',
+ 'type' => 'varchar(255)',
+ 'default',
+ 'null' => true,
+ 'key',
+ 'comment' => 'test'
+ );
+ $result = $this->db->buildColumn($data);
+ $expected = '`testName` DEFAULT NULL COMMENT \'test\'';
+ $this->assertEqual($result, $expected);
+
+ $data = array(
+ 'name' => 'testName',
+ 'type' => 'varchar(255)',
+ 'default',
+ 'null' => true,
+ 'key',
+ 'charset' => 'utf8',
+ 'collate' => 'utf8_unicode_ci'
+ );
+ $result = $this->db->buildColumn($data);
+ $expected = '`testName` CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL';
+ $this->assertEqual($result, $expected);
+ }
+
+/**
* MySQL 4.x returns index data in a different format,
* Using a mock ensure that MySQL 4.x output is properly parsed.
*

0 comments on commit 627eff5

Please sign in to comment.
Something went wrong with that request. Please try again.