#1004068 by Damien Tournoud, dmigtrig01: Complete the implementation of DatabaseSchema::addField() for SQLite... gets us to 100% tests passing in SQLite! :D
parent
925722a804
commit
bb344c82d5
|
@ -276,7 +276,7 @@ class DatabaseSchema_sqlite extends DatabaseSchema {
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addField($table, $field, $spec, $keys_new = array()) {
|
public function addField($table, $field, $specification, $keys_new = array()) {
|
||||||
if (!$this->tableExists($table)) {
|
if (!$this->tableExists($table)) {
|
||||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot add field %table.%field: table doesn't exist.", array('%field' => $field, '%table' => $table)));
|
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot add field %table.%field: table doesn't exist.", array('%field' => $field, '%table' => $table)));
|
||||||
}
|
}
|
||||||
|
@ -284,10 +284,50 @@ class DatabaseSchema_sqlite extends DatabaseSchema {
|
||||||
throw new DatabaseSchemaObjectExistsException(t("Cannot add field %table.%field: field already exists.", array('%field' => $field, '%table' => $table)));
|
throw new DatabaseSchemaObjectExistsException(t("Cannot add field %table.%field: field already exists.", array('%field' => $field, '%table' => $table)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: $keys_new is not supported yet.
|
// SQLite doesn't have a full-featured ALTER TABLE statement. It only
|
||||||
$query = 'ALTER TABLE {' . $table . '} ADD ';
|
// supports adding new fields to a table, in some simple cases. In most
|
||||||
$query .= $this->createFieldSql($field, $this->processField($spec));
|
// cases, we have to create a new table and copy the data over.
|
||||||
|
if (empty($keys_new) && (empty($specification['not null']) || isset($specification['default']))) {
|
||||||
|
// When we don't have to create new keys and we are not creating a
|
||||||
|
// NOT NULL column without a default value, we can use the quicker version.
|
||||||
|
$query = 'ALTER TABLE {' . $table . '} ADD ' . $this->createFieldSql($field, $this->processField($specification));
|
||||||
$this->connection->query($query);
|
$this->connection->query($query);
|
||||||
|
|
||||||
|
// Apply the initial value if set.
|
||||||
|
if (isset($specification['initial'])) {
|
||||||
|
$this->connection->update($table)
|
||||||
|
->fields(array($field => $specification['initial']))
|
||||||
|
->execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// We cannot add the field directly. Use the slower table alteration
|
||||||
|
// method, starting from the old schema.
|
||||||
|
$old_schema = $this->introspectSchema($table);
|
||||||
|
$new_schema = $old_schema;
|
||||||
|
|
||||||
|
// Add the new field.
|
||||||
|
$new_schema['fields'][$field] = $specification;
|
||||||
|
|
||||||
|
// Build the mapping between the old fields and the new fields.
|
||||||
|
$mapping = array();
|
||||||
|
if (isset($specification['initial'])) {
|
||||||
|
// If we have a initial value, copy it over.
|
||||||
|
$mapping[$field] = array(
|
||||||
|
'expression' => ':newfieldinitial',
|
||||||
|
'arguments' => array(':newfieldinitial' => $specification['initial']),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Else use the default of the field.
|
||||||
|
$mapping[$field] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the new indexes.
|
||||||
|
$new_schema += $keys_new;
|
||||||
|
|
||||||
|
$this->alterTable($table, $old_schema, $new_schema, $mapping);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -303,7 +343,13 @@ class DatabaseSchema_sqlite extends DatabaseSchema {
|
||||||
* @param $new_schema
|
* @param $new_schema
|
||||||
* The new schema array for the table.
|
* The new schema array for the table.
|
||||||
* @param $mapping
|
* @param $mapping
|
||||||
* An optional mapping between old fields => new fields.
|
* An optional mapping between the fields of the old specification and the
|
||||||
|
* fields of the new specification. An associative array, whose keys are
|
||||||
|
* the fields of the new table, and values can take two possible forms:
|
||||||
|
* - a simple string, which is interpreted as the name of a field of the
|
||||||
|
* old table,
|
||||||
|
* - an associative array with two keys 'expression' and 'arguments',
|
||||||
|
* that will be used as an expression field.
|
||||||
*/
|
*/
|
||||||
protected function alterTable($table, $old_schema, $new_schema, array $mapping = array()) {
|
protected function alterTable($table, $old_schema, $new_schema, array $mapping = array()) {
|
||||||
$i = 0;
|
$i = 0;
|
||||||
|
@ -313,22 +359,25 @@ class DatabaseSchema_sqlite extends DatabaseSchema {
|
||||||
|
|
||||||
$this->createTable($new_table, $new_schema);
|
$this->createTable($new_table, $new_schema);
|
||||||
|
|
||||||
// Complete the mapping.
|
// Build a SQL query to migrate the data from the old table to the new.
|
||||||
$old_keys = array_keys($old_schema['fields']);
|
|
||||||
$mapping += array_combine($old_keys, $old_keys);
|
|
||||||
|
|
||||||
$select = $this->connection->select($table);
|
$select = $this->connection->select($table);
|
||||||
$fields = &$select->getFields();
|
|
||||||
|
|
||||||
// Map the fields.
|
// Complete the mapping.
|
||||||
foreach ($old_keys as $key) {
|
$possible_keys = array_keys($new_schema['fields']);
|
||||||
if (isset($mapping[$key])) {
|
$mapping += array_combine($possible_keys, $possible_keys);
|
||||||
// Don't use ->addField() here because it messes-up with the aliases.
|
|
||||||
$fields[$mapping[$key]] = array(
|
// Now add the fields.
|
||||||
'field' => $key,
|
foreach ($mapping as $field_alias => $field_source) {
|
||||||
'table' => $table,
|
// Just ignore this field (ie. use it's default value).
|
||||||
'alias' => $mapping[$key],
|
if (!isset($field_source)) {
|
||||||
);
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_array($field_source)) {
|
||||||
|
$select->addExpression($field_source['expression'], $field_alias, $field_source['arguments']);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$select->addField($table, $field_source, $field_alias);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -427,8 +476,6 @@ class DatabaseSchema_sqlite extends DatabaseSchema {
|
||||||
$old_schema = $this->introspectSchema($table);
|
$old_schema = $this->introspectSchema($table);
|
||||||
$new_schema = $old_schema;
|
$new_schema = $old_schema;
|
||||||
|
|
||||||
$mapping = array($field => NULL);
|
|
||||||
|
|
||||||
unset($new_schema['fields'][$field]);
|
unset($new_schema['fields'][$field]);
|
||||||
foreach ($new_schema['indexes'] as $index => $fields) {
|
foreach ($new_schema['indexes'] as $index => $fields) {
|
||||||
foreach ($fields as $key => $field_name) {
|
foreach ($fields as $key => $field_name) {
|
||||||
|
@ -441,7 +488,7 @@ class DatabaseSchema_sqlite extends DatabaseSchema {
|
||||||
unset($new_schema['indexes'][$index]);
|
unset($new_schema['indexes'][$index]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$this->alterTable($table, $old_schema, $new_schema, $mapping);
|
$this->alterTable($table, $old_schema, $new_schema);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -458,7 +505,7 @@ class DatabaseSchema_sqlite extends DatabaseSchema {
|
||||||
|
|
||||||
// Map the old field to the new field.
|
// Map the old field to the new field.
|
||||||
if ($field != $field_new) {
|
if ($field != $field_new) {
|
||||||
$mapping[$field] = $field_new;
|
$mapping[$field_new] = $field;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$mapping = array();
|
$mapping = array();
|
||||||
|
|
Loading…
Reference in New Issue