mirror of
https://github.com/kamilwylegala/cakephp2-php8.git
synced 2025-01-18 02:26:17 +00:00
Refactoring schema handling for SQLite and Postgres drivers. Non-primary key indexes are now created properly. Fixed testing bugs in db drivers.
git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@6922 3807eeeb-6ff5-0310-8944-8be069107fe0
This commit is contained in:
parent
e1fc6ad5fd
commit
6bed503b56
5 changed files with 166 additions and 35 deletions
|
@ -597,28 +597,62 @@ class DboPostgres extends DboSource {
|
||||||
* Format indexes for create table
|
* Format indexes for create table
|
||||||
*
|
*
|
||||||
* @param array $indexes
|
* @param array $indexes
|
||||||
|
* @param string $table
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
function buildIndex($indexes) {
|
function buildIndex($indexes, $table = null) {
|
||||||
$join = array();
|
$join = array();
|
||||||
foreach ($indexes as $name => $value) {
|
foreach ($indexes as $name => $value) {
|
||||||
$out = '';
|
|
||||||
if ($name == 'PRIMARY') {
|
if ($name == 'PRIMARY') {
|
||||||
$out .= 'PRIMARY ';
|
$out = 'PRIMARY KEY (' . $this->name($value['column']) . ')';
|
||||||
$name = null;
|
|
||||||
} else {
|
} else {
|
||||||
|
$out = 'CREATE ';
|
||||||
if (!empty($value['unique'])) {
|
if (!empty($value['unique'])) {
|
||||||
$name .= ' UNIQUE ';
|
$out .= 'UNIQUE ';
|
||||||
}
|
}
|
||||||
}
|
if (is_array($value['column'])) {
|
||||||
if (is_array($value['column'])) {
|
$value['column'] = join(', ', array_map(array(&$this, 'name'), $value['column']));
|
||||||
$out .= 'CONSTRAINT '. $name .' (' . join(', ', array_map(array(&$this, 'name'), $value['column'])) . ')';
|
} else {
|
||||||
} else {
|
$value['column'] = $this->name($value['column']);
|
||||||
$out .= 'KEY '. $name .' (' . $this->name($value['column']) . ')';
|
}
|
||||||
|
$out .= "INDEX {$name} ON {$table}({$value['column']});";
|
||||||
}
|
}
|
||||||
$join[] = $out;
|
$join[] = $out;
|
||||||
}
|
}
|
||||||
return join(",\n\t", $join);
|
return $join;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Overrides DboSource::renderStatement to handle schema generation with Postgres-style indexes
|
||||||
|
*
|
||||||
|
* @param string $type
|
||||||
|
* @param array $data
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function renderStatement($type, $data) {
|
||||||
|
switch (strtolower($type)) {
|
||||||
|
case 'schema':
|
||||||
|
extract($data);
|
||||||
|
|
||||||
|
foreach ($indexes as $i => $index) {
|
||||||
|
if (preg_match('/PRIMARY KEY/', $index)) {
|
||||||
|
unset($indexes[$i]);
|
||||||
|
$columns[] = $index;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (array('columns', 'indexes') as $var) {
|
||||||
|
if (is_array(${$var})) {
|
||||||
|
${$var} = "\t" . join(",\n\t", array_filter(${$var}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "CREATE TABLE {$table} (\n{$columns});\n{$indexes}";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return parent::renderStatement($type, $data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -93,6 +93,10 @@ class DboSqlite extends DboSource {
|
||||||
$config = $this->config;
|
$config = $this->config;
|
||||||
$this->connection = $config['connect']($config['database']);
|
$this->connection = $config['connect']($config['database']);
|
||||||
$this->connected = is_resource($this->connection);
|
$this->connected = is_resource($this->connection);
|
||||||
|
|
||||||
|
if ($this->connected) {
|
||||||
|
$this->_execute('PRAGMA count_changes = 1');
|
||||||
|
}
|
||||||
return $this->connected;
|
return $this->connected;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -186,7 +190,7 @@ class DboSqlite extends DboSource {
|
||||||
* @param string $data String to be prepared for use in an SQL statement
|
* @param string $data String to be prepared for use in an SQL statement
|
||||||
* @return string Quoted and escaped
|
* @return string Quoted and escaped
|
||||||
*/
|
*/
|
||||||
function value ($data, $column = null, $safe = false) {
|
function value($data, $column = null, $safe = false) {
|
||||||
$parent = parent::value($data, $column, $safe);
|
$parent = parent::value($data, $column, $safe);
|
||||||
|
|
||||||
if ($parent != null) {
|
if ($parent != null) {
|
||||||
|
@ -237,7 +241,7 @@ class DboSqlite extends DboSource {
|
||||||
* @return boolean True on success, false on fail
|
* @return boolean True on success, false on fail
|
||||||
* (i.e. if the database/model does not support transactions).
|
* (i.e. if the database/model does not support transactions).
|
||||||
*/
|
*/
|
||||||
function begin (&$model) {
|
function begin(&$model) {
|
||||||
if (parent::begin($model)) {
|
if (parent::begin($model)) {
|
||||||
if ($this->execute('BEGIN')) {
|
if ($this->execute('BEGIN')) {
|
||||||
$this->_transactionStarted = true;
|
$this->_transactionStarted = true;
|
||||||
|
@ -254,7 +258,7 @@ class DboSqlite extends DboSource {
|
||||||
* (i.e. if the database/model does not support transactions,
|
* (i.e. if the database/model does not support transactions,
|
||||||
* or a transaction has not started).
|
* or a transaction has not started).
|
||||||
*/
|
*/
|
||||||
function commit (&$model) {
|
function commit(&$model) {
|
||||||
if (parent::commit($model)) {
|
if (parent::commit($model)) {
|
||||||
$this->_transactionStarted = false;
|
$this->_transactionStarted = false;
|
||||||
return $this->execute('COMMIT');
|
return $this->execute('COMMIT');
|
||||||
|
@ -269,7 +273,7 @@ class DboSqlite extends DboSource {
|
||||||
* (i.e. if the database/model does not support transactions,
|
* (i.e. if the database/model does not support transactions,
|
||||||
* or a transaction has not started).
|
* or a transaction has not started).
|
||||||
*/
|
*/
|
||||||
function rollback (&$model) {
|
function rollback(&$model) {
|
||||||
if (parent::rollback($model)) {
|
if (parent::rollback($model)) {
|
||||||
return $this->execute('ROLLBACK');
|
return $this->execute('ROLLBACK');
|
||||||
}
|
}
|
||||||
|
@ -485,6 +489,79 @@ class DboSqlite extends DboSource {
|
||||||
}
|
}
|
||||||
return $out;
|
return $out;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Sets the database encoding
|
||||||
|
*
|
||||||
|
* @param string $enc Database encoding
|
||||||
|
*/
|
||||||
|
function setEncoding($enc) {
|
||||||
|
if (!in_array($enc, array("UTF-8", "UTF-16", "UTF-16le", "UTF-16be"))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return $this->_execute("PRAGMA encoding = \"{$enc}\"") !== false;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Gets the database encoding
|
||||||
|
*
|
||||||
|
* @return string The database encoding
|
||||||
|
*/
|
||||||
|
function getEncoding() {
|
||||||
|
return $this->fetchRow('PRAGMA encoding');
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Removes redundant primary key indexes, as they are handled in the column def of the key.
|
||||||
|
*
|
||||||
|
* @param array $indexes
|
||||||
|
* @param string $table
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function buildIndex($indexes, $table = null) {
|
||||||
|
$join = array();
|
||||||
|
|
||||||
|
foreach ($indexes as $name => $value) {
|
||||||
|
|
||||||
|
if ($name == 'PRIMARY') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$out = 'CREATE ';
|
||||||
|
|
||||||
|
if (!empty($value['unique'])) {
|
||||||
|
$out .= 'UNIQUE ';
|
||||||
|
}
|
||||||
|
if (is_array($value['column'])) {
|
||||||
|
$value['column'] = join(', ', array_map(array(&$this, 'name'), $value['column']));
|
||||||
|
} else {
|
||||||
|
$value['column'] = $this->name($value['column']);
|
||||||
|
}
|
||||||
|
$out .= "INDEX {$name} ON {$table}({$value['column']});";
|
||||||
|
$join[] = $out;
|
||||||
|
}
|
||||||
|
return $join;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Overrides DboSource::renderStatement to handle schema generation with SQLite-style indexes
|
||||||
|
*
|
||||||
|
* @param string $type
|
||||||
|
* @param array $data
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function renderStatement($type, $data) {
|
||||||
|
switch (strtolower($type)) {
|
||||||
|
case 'schema':
|
||||||
|
extract($data);
|
||||||
|
|
||||||
|
foreach (array('columns', 'indexes') as $var) {
|
||||||
|
if (is_array(${$var})) {
|
||||||
|
${$var} = "\t" . join(",\n\t", array_filter(${$var}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "CREATE TABLE {$table} (\n{$columns});\n{$indexes}";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return parent::renderStatement($type, $data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
|
@ -1232,6 +1232,19 @@ class DboSource extends DataSource {
|
||||||
}
|
}
|
||||||
return "DELETE {$alias} FROM {$table} {$aliases}{$conditions}";
|
return "DELETE {$alias} FROM {$table} {$aliases}{$conditions}";
|
||||||
break;
|
break;
|
||||||
|
case 'schema':
|
||||||
|
foreach (array('columns', 'indexes') as $var) {
|
||||||
|
if (is_array(${$var})) {
|
||||||
|
${$var} = "\t" . join(",\n\t", array_filter(${$var}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (trim($indexes) != '') {
|
||||||
|
$columns .= ',';
|
||||||
|
}
|
||||||
|
return "CREATE TABLE {$table} (\n{$columns}{$indexes});";
|
||||||
|
break;
|
||||||
|
case 'alter':
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -2007,11 +2020,11 @@ class DboSource extends DataSource {
|
||||||
* Generate a database-native schema for the given Schema object
|
* Generate a database-native schema for the given Schema object
|
||||||
*
|
*
|
||||||
* @param object $schema An instance of a subclass of CakeSchema
|
* @param object $schema An instance of a subclass of CakeSchema
|
||||||
* @param string $table Optional. If specified only the table name given will be generated.
|
* @param string $tableName Optional. If specified only the table name given will be generated.
|
||||||
* Otherwise, all tables defined in the schema are generated.
|
* Otherwise, all tables defined in the schema are generated.
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
function createSchema($schema, $table = null) {
|
function createSchema($schema, $tableName = null) {
|
||||||
if (!is_a($schema, 'CakeSchema')) {
|
if (!is_a($schema, 'CakeSchema')) {
|
||||||
trigger_error(__('Invalid schema object', true), E_USER_WARNING);
|
trigger_error(__('Invalid schema object', true), E_USER_WARNING);
|
||||||
return null;
|
return null;
|
||||||
|
@ -2019,10 +2032,11 @@ class DboSource extends DataSource {
|
||||||
$out = '';
|
$out = '';
|
||||||
|
|
||||||
foreach ($schema->tables as $curTable => $columns) {
|
foreach ($schema->tables as $curTable => $columns) {
|
||||||
if (!$table || $table == $curTable) {
|
if (!$tableName || $tableName == $curTable) {
|
||||||
$out .= 'CREATE TABLE ' . $this->fullTableName($curTable) . " (\n";
|
$cols = $colList = $indexes = array();
|
||||||
$cols = $colList = $index = array();
|
|
||||||
$primary = null;
|
$primary = null;
|
||||||
|
$table = $this->fullTableName($curTable);
|
||||||
|
|
||||||
foreach ($columns as $name => $col) {
|
foreach ($columns as $name => $col) {
|
||||||
if (is_string($col)) {
|
if (is_string($col)) {
|
||||||
$col = array('type' => $col);
|
$col = array('type' => $col);
|
||||||
|
@ -2037,14 +2051,15 @@ class DboSource extends DataSource {
|
||||||
}
|
}
|
||||||
$cols[] = $this->buildColumn($col);
|
$cols[] = $this->buildColumn($col);
|
||||||
} else {
|
} else {
|
||||||
$index[] = $this->buildIndex($col);
|
$indexes = array_merge($indexes, $this->buildIndex($col, $table));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (empty($index) && !empty($primary)) {
|
if (empty($indexes) && !empty($primary)) {
|
||||||
$col = array('PRIMARY' => array('column'=> $primary, 'unique' => 1));
|
$col = array('PRIMARY' => array('column' => $primary, 'unique' => 1));
|
||||||
$index[] = $this->buildIndex($col);
|
$indexes = array_merge($indexes, $this->buildIndex($col, $table));
|
||||||
}
|
}
|
||||||
$out .= "\t" . join(",\n\t", array_filter(array_merge($cols, $index))) . "\n);\n\n";
|
$columns = $cols;
|
||||||
|
$out .= $this->renderStatement('schema', compact('table', 'columns', 'indexes')) . "\n\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $out;
|
return $out;
|
||||||
|
@ -2135,9 +2150,10 @@ class DboSource extends DataSource {
|
||||||
* Format indexes for create table
|
* Format indexes for create table
|
||||||
*
|
*
|
||||||
* @param array $indexes
|
* @param array $indexes
|
||||||
* @return string
|
* @param string $table
|
||||||
|
* @return array
|
||||||
*/
|
*/
|
||||||
function buildIndex($indexes) {
|
function buildIndex($indexes, $table = null) {
|
||||||
$join = array();
|
$join = array();
|
||||||
foreach ($indexes as $name => $value) {
|
foreach ($indexes as $name => $value) {
|
||||||
$out = '';
|
$out = '';
|
||||||
|
@ -2156,7 +2172,8 @@ class DboSource extends DataSource {
|
||||||
}
|
}
|
||||||
$join[] = $out;
|
$join[] = $out;
|
||||||
}
|
}
|
||||||
return join(",\n\t", $join);
|
return $join;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
|
@ -194,7 +194,9 @@ class DboMysqlTest extends CakeTestCase {
|
||||||
$this->db->cacheSources = $this->db->testing = false;
|
$this->db->cacheSources = $this->db->testing = false;
|
||||||
$this->db->query('CREATE TABLE ' . $this->db->fullTableName('tinyint') . ' (id int(11) AUTO_INCREMENT, bool tinyint(1), small_int tinyint(2), primary key(id));');
|
$this->db->query('CREATE TABLE ' . $this->db->fullTableName('tinyint') . ' (id int(11) AUTO_INCREMENT, bool tinyint(1), small_int tinyint(2), primary key(id));');
|
||||||
|
|
||||||
$this->model = new Model(array('name' => 'Tinyint', 'table' => $this->db->fullTableName('tinyint', false)));
|
$this->model = new CakeTestModel(array(
|
||||||
|
'name' => 'Tinyint', 'table' => $this->db->fullTableName('tinyint', false)
|
||||||
|
));
|
||||||
$result = $this->model->schema();
|
$result = $this->model->schema();
|
||||||
$this->assertEqual($result['bool']['type'], 'boolean');
|
$this->assertEqual($result['bool']['type'], 'boolean');
|
||||||
$this->assertEqual($result['small_int']['type'], 'integer');
|
$this->assertEqual($result['small_int']['type'], 'integer');
|
||||||
|
|
|
@ -2484,12 +2484,13 @@ class ModelTest extends CakeTestCase {
|
||||||
|
|
||||||
$this->assertIdentical($model->Comment->find('count'), 0);
|
$this->assertIdentical($model->Comment->find('count'), 0);
|
||||||
|
|
||||||
$result = $model->saveAll(array(
|
$result = $model->saveAll(
|
||||||
'Article' => array('title' => 'Post with Author', 'body' => 'This post will be saved without an author'),
|
array(
|
||||||
'Comment' => array(
|
'Article' => array('title' => 'Post with Author', 'body' => 'This post will be saved with an author', 'user_id' => 2),
|
||||||
array('comment' => 'Only new comment'),
|
'Comment' => array(array('comment' => 'Only new comment', 'user_id' => 2))
|
||||||
)
|
),
|
||||||
), array('validate' => 'first'));
|
array('validate' => 'first')
|
||||||
|
);
|
||||||
$this->assertIdentical($result, true);
|
$this->assertIdentical($result, true);
|
||||||
|
|
||||||
$result = $model->Comment->find('all');
|
$result = $model->Comment->find('all');
|
||||||
|
|
Loading…
Add table
Reference in a new issue