Full restore: tables the restore creates get this installation's charset and collation (utf8mb4 on MySQL/MariaDB); test with an emoji
This commit is contained in:
+26
-3
@@ -159,7 +159,7 @@ final class DbDumper {
|
||||
// everywhere); tables it does not know are left out, as asked.
|
||||
foreach ($missing as $table) {
|
||||
if (isset($manifest['tables'][$table]['schema'])) {
|
||||
$this->db->createSchemaManager()->createTable(self::tableFromStructure($table, $manifest['tables'][$table]['schema']));
|
||||
$this->db->createSchemaManager()->createTable(self::tableFromStructure($table, $manifest['tables'][$table]['schema'], $this->tableOptions()));
|
||||
$report['created'][] = $table;
|
||||
} else {
|
||||
$report['missing'][] = $table;
|
||||
@@ -319,8 +319,31 @@ final class DbDumper {
|
||||
'foreignKeys' => $foreignKeys];
|
||||
}
|
||||
|
||||
private static function tableFromStructure(string $name, array $structure): \Doctrine\DBAL\Schema\Table {
|
||||
$table = new \Doctrine\DBAL\Schema\Table($name);
|
||||
/**
|
||||
* Table options for a table the restore creates: those of this installation's own tables.
|
||||
* On MySQL/MariaDB that is the character set and collation, as Nextcloud's tables have them
|
||||
* (utf8mb4, so emoji and other 4-byte characters fit); DBAL alone would use 3-byte utf8.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
* @psalm-suppress UndefinedClass the DBAL classes come with Nextcloud, not with this app
|
||||
*/
|
||||
private function tableOptions(): array {
|
||||
$options = $this->db->createSchemaManager()->createSchemaConfig()->getDefaultTableOptions();
|
||||
if ($this->db->getDatabasePlatform() instanceof \Doctrine\DBAL\Platforms\AbstractMySQLPlatform) {
|
||||
$collation = $this->db->fetchOne('SELECT TABLE_COLLATION FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ?',
|
||||
[$this->prefix . 'appconfig']);
|
||||
if (is_string($collation) && $collation !== '') {
|
||||
$options['collation'] = $collation;
|
||||
$options['charset'] = explode('_', $collation, 2)[0];
|
||||
unset($options['collate']);
|
||||
}
|
||||
}
|
||||
return $options;
|
||||
}
|
||||
|
||||
/** @param array<string, mixed> $options table options (see tableOptions()) */
|
||||
private static function tableFromStructure(string $name, array $structure, array $options = []): \Doctrine\DBAL\Schema\Table {
|
||||
$table = new \Doctrine\DBAL\Schema\Table($name, [], [], [], [], $options);
|
||||
foreach ($structure['columns'] as $c) {
|
||||
$table->addColumn($c['name'], $c['type'], array_filter([
|
||||
'length' => $c['length'], 'precision' => $c['precision'], 'scale' => $c['scale'],
|
||||
|
||||
@@ -119,6 +119,8 @@ if [ "$DB" != sqlite ]; then
|
||||
|| fail "the mail account does not point at its mailboxes"
|
||||
# Deck installed and then switched off: its tables stay in the database and in the backup
|
||||
run_on ngb-frt-origin app:install deck >/dev/null || fail "install deck on the origin"
|
||||
# a 4-byte character (emoji) in a table the restore has to create: utf8mb4 on MySQL/MariaDB
|
||||
sql origin "insert into oc_deck_boards (title, owner, color, archived, deleted_at, last_modified) values ('Plan 📌', 'frtest', '0087C5', 0, 0, 0)" >/dev/null
|
||||
run_on ngb-frt-origin app:disable deck >/dev/null
|
||||
ok "origin has a synced Mail account and the tables of a disabled app"
|
||||
fi
|
||||
@@ -202,6 +204,7 @@ if [ "$ORIGIN_DBTYPE" != sqlite ] && [ "$DB" != sqlite ] && [ "$LEGACY" = legacy
|
||||
ok "older backup: tables of the disabled app left out, Mail restored"
|
||||
elif [ "$ORIGIN_DBTYPE" != sqlite ] && [ "$DB" != sqlite ]; then
|
||||
[ "$(sql restore "select count(*) from information_schema.tables where table_name = 'oc_deck_boards'")" = 1 ] || fail "the tables of the disabled app were not created"
|
||||
[ "$(sql restore "select title from oc_deck_boards")" = "Plan 📌" ] || fail "a 4-byte character did not survive in a created table"
|
||||
[ "$(sql restore "select count(*) from oc_mail_accounts where drafts_mailbox_id is not null")" = 1 ] || fail "the mail account was not restored"
|
||||
[ "$(sql restore "select count(*) from information_schema.table_constraints where constraint_type = 'FOREIGN KEY' and table_name like 'oc_mail_%'")" -gt 0 ] \
|
||||
|| fail "the foreign keys of Mail are missing after the restore"
|
||||
|
||||
Reference in New Issue
Block a user