namespace Drupal\Core\Database\Driver\sqlite;
-use Drupal\Component\Utility\Unicode;
use Drupal\Core\Database\SchemaObjectExistsException;
use Drupal\Core\Database\SchemaObjectDoesNotExistException;
use Drupal\Core\Database\Schema as DatabaseSchema;
* An array of SQL statements to create the table.
*/
public function createTableSql($name, $table) {
+ if (!empty($table['primary key']) && is_array($table['primary key'])) {
+ $this->ensureNotNullPrimaryKey($table['primary key'], $table['fields']);
+ }
+
$sql = [];
$sql[] = "CREATE TABLE {" . $name . "} (\n" . $this->createColumnsSql($name, $table) . "\n)\n";
return array_merge($sql, $this->createIndexSql($name, $table));
// Set the correct database-engine specific datatype.
// In case one is already provided, force it to uppercase.
if (isset($field['sqlite_type'])) {
- $field['sqlite_type'] = Unicode::strtoupper($field['sqlite_type']);
+ $field['sqlite_type'] = mb_strtoupper($field['sqlite_type']);
}
else {
$map = $this->getFieldTypeMap();
if ($this->fieldExists($table, $field)) {
throw new SchemaObjectExistsException(t("Cannot add field @table.@field: field already exists.", ['@field' => $field, '@table' => $table]));
}
+ if (isset($keys_new['primary key']) && in_array($field, $keys_new['primary key'], TRUE)) {
+ $this->ensureNotNullPrimaryKey($keys_new['primary key'], [$field => $specification]);
+ }
// SQLite doesn't have a full-featured ALTER TABLE statement. It only
// supports adding new fields to a table, in some simple cases. In most
$this->connection->query($query);
// Apply the initial value if set.
- if (isset($specification['initial'])) {
+ if (isset($specification['initial_from_field'])) {
+ if (isset($specification['initial'])) {
+ $expression = 'COALESCE(' . $specification['initial_from_field'] . ', :default_initial_value)';
+ $arguments = [':default_initial_value' => $specification['initial']];
+ }
+ else {
+ $expression = $specification['initial_from_field'];
+ $arguments = [];
+ }
$this->connection->update($table)
- ->fields([$field => $specification['initial']])
+ ->expression($field, $expression, $arguments)
->execute();
}
- if (isset($specification['initial_from_field'])) {
+ elseif (isset($specification['initial'])) {
$this->connection->update($table)
- ->expression($field, $specification['initial_from_field'])
+ ->fields([$field => $specification['initial']])
->execute();
}
}
// Build the mapping between the old fields and the new fields.
$mapping = [];
- if (isset($specification['initial'])) {
+ if (isset($specification['initial_from_field'])) {
// If we have a initial value, copy it over.
+ if (isset($specification['initial'])) {
+ $expression = 'COALESCE(' . $specification['initial_from_field'] . ', :default_initial_value)';
+ $arguments = [':default_initial_value' => $specification['initial']];
+ }
+ else {
+ $expression = $specification['initial_from_field'];
+ $arguments = [];
+ }
$mapping[$field] = [
- 'expression' => ':newfieldinitial',
- 'arguments' => [':newfieldinitial' => $specification['initial']],
+ 'expression' => $expression,
+ 'arguments' => $arguments,
];
}
- elseif (isset($specification['initial_from_field'])) {
+ elseif (isset($specification['initial'])) {
// If we have a initial value, copy it over.
$mapping[$field] = [
- 'expression' => $specification['initial_from_field'],
- 'arguments' => [],
+ 'expression' => ':newfieldinitial',
+ 'arguments' => [':newfieldinitial' => $specification['initial']],
];
}
else {
$schema['fields'][$row->name] = [
'type' => $type,
'size' => $size,
- 'not null' => !empty($row->notnull),
+ 'not null' => !empty($row->notnull) || $row->pk !== "0",
'default' => trim($row->dflt_value, "'"),
];
if ($length) {
$schema['fields'][$row->name]['length'] = $length;
}
+ // $row->pk contains a number that reflects the primary key order. We
+ // use that as the key and sort (by key) below to return the primary key
+ // in the same order that it is stored in.
if ($row->pk) {
- $schema['primary key'][] = $row->name;
+ $schema['primary key'][$row->pk] = $row->name;
}
}
else {
throw new \Exception("Unable to parse the column type " . $row->type);
}
}
+ ksort($schema['primary key']);
+ // Re-key the array because $row->pk starts counting at 1.
+ $schema['primary key'] = array_values($schema['primary key']);
+
$indexes = [];
$result = $this->connection->query('PRAGMA ' . $info['schema'] . '.index_list(' . $info['table'] . ')');
foreach ($result as $row) {
unset($new_schema['fields'][$field]);
- // Handle possible primary key changes.
- if (isset($new_schema['primary key']) && ($key = array_search($field, $new_schema['primary key'])) !== FALSE) {
- unset($new_schema['primary key'][$key]);
+ // Drop the primary key if the field to drop is part of it. This is
+ // consistent with the behavior on PostgreSQL.
+ // @see \Drupal\Core\Database\Driver\mysql\Schema::dropField()
+ if (isset($new_schema['primary key']) && in_array($field, $new_schema['primary key'], TRUE)) {
+ unset($new_schema['primary key']);
}
// Handle possible index changes.
if (($field != $field_new) && $this->fieldExists($table, $field_new)) {
throw new SchemaObjectExistsException(t("Cannot rename field @table.@name to @name_new: target field already exists.", ['@table' => $table, '@name' => $field, '@name_new' => $field_new]));
}
+ if (isset($keys_new['primary key']) && in_array($field_new, $keys_new['primary key'], TRUE)) {
+ $this->ensureNotNullPrimaryKey($keys_new['primary key'], [$field_new => $spec]);
+ }
$old_schema = $this->introspectSchema($table);
$new_schema = $old_schema;
if (is_array($field)) {
$field = &$field[0];
}
- if (isset($mapping[$field])) {
- $field = $mapping[$field];
+
+ $mapped_field = array_search($field, $mapping, TRUE);
+ if ($mapped_field !== FALSE) {
+ $field = $mapped_field;
}
}
return $key_definition;
}
$new_schema['primary key'] = $fields;
+ $this->ensureNotNullPrimaryKey($new_schema['primary key'], $new_schema['fields']);
$this->alterTable($table, $old_schema, $new_schema);
}
return TRUE;
}
+ /**
+ * {@inheritdoc}
+ */
+ protected function findPrimaryKeyColumns($table) {
+ if (!$this->tableExists($table)) {
+ return FALSE;
+ }
+ $schema = $this->introspectSchema($table);
+ return $schema['primary key'];
+ }
+
/**
* {@inheritdoc}
*/