From 3a555440e1f9e4399c060cf924e5dbaad42b3ed3 Mon Sep 17 00:00:00 2001 From: Jon Stovell Date: Thu, 4 Jul 2024 14:48:33 -0600 Subject: [PATCH] Use InnoDB and dynamic rows for MySQL Signed-off-by: Jon Stovell --- Sources/Db/APIs/MySQL.php | 40 ++++++++++++++--------- Sources/Db/APIs/PostgreSQL.php | 8 +++++ Sources/Db/DatabaseApiInterface.php | 9 ++++++ other/upgrade.php | 50 +++++++++++++++++++++++++++-- 4 files changed, 90 insertions(+), 17 deletions(-) diff --git a/Sources/Db/APIs/MySQL.php b/Sources/Db/APIs/MySQL.php index d7f1533b09..02e28a73d6 100644 --- a/Sources/Db/APIs/MySQL.php +++ b/Sources/Db/APIs/MySQL.php @@ -662,6 +662,26 @@ public function select(string $database, ?object $connection = null): bool return mysqli_select_db($connection ?? $this->connection, $database); } + /** + * {@inheritDoc} + */ + public function get_engines(): array + { + if (empty($this->engines)) { + $request = $this->query('', 'SHOW ENGINES', []); + + while ($row = $this->fetch_assoc($request)) { + if ($row['Support'] == 'YES' || $row['Support'] == 'DEFAULT') { + $this->engines[] = $row['Engine']; + } + } + + $this->free_result($request); + } + + return $this->engines; + } + /** * {@inheritDoc} */ @@ -870,7 +890,7 @@ public function backup_table(string $table, string $backup_table): object|bool $auto_inc = ''; // Default engine type. - $engine = 'MyISAM'; + $engine = 'InnoDB'; $charset = ''; $collate = ''; @@ -1090,7 +1110,7 @@ public function table_sql(string $tableName): string $schema_create .= ',' . $crlf . ' ' . $keyname . ' (' . implode(', ', $columns) . ')'; } - // Now just get the comment and engine... (MyISAM, etc.) + // Now just get the comment and engine... (InnoDB, etc.) $result = $this->query( '', 'SHOW TABLE STATUS @@ -1102,7 +1122,7 @@ public function table_sql(string $tableName): string $row = $this->fetch_assoc($result); $this->free_result($result); - // Probably MyISAM.... and it might have a comment. + // Probably InnoDB.... and it might have a comment. $schema_create .= $crlf . ') ENGINE=' . $row['Engine'] . ($row['Comment'] != '' ? ' COMMENT="' . $row['Comment'] . '"' : ''); return $schema_create; @@ -1661,18 +1681,7 @@ public function create_table(string $table_name, array $columns, array $indexes } // Which engine do we want here? - if (empty($this->engines)) { - // Figure out which engines we have - $get_engines = $this->query('', 'SHOW ENGINES', []); - - while ($row = $this->fetch_assoc($get_engines)) { - if ($row['Support'] == 'YES' || $row['Support'] == 'DEFAULT') { - $this->engines[] = $row['Engine']; - } - } - - $this->free_result($get_engines); - } + $this->get_engines(); // If we don't have this engine, or didn't specify one, default to InnoDB or MyISAM // depending on which one is available @@ -1804,6 +1813,7 @@ public function table_structure(string $table_name): array 'columns' => $this->list_columns($table_name, true), 'indexes' => $this->list_indexes($table_name, true), 'engine' => $row['Engine'], + 'row_format' => $row['Row_format'], ]; } diff --git a/Sources/Db/APIs/PostgreSQL.php b/Sources/Db/APIs/PostgreSQL.php index c9420bc34d..f0871e28df 100644 --- a/Sources/Db/APIs/PostgreSQL.php +++ b/Sources/Db/APIs/PostgreSQL.php @@ -705,6 +705,14 @@ public function select(string $database, ?object $connection = null): bool return true; } + /** + * {@inheritDoc} + */ + public function get_engines(): array + { + return []; + } + /** * {@inheritDoc} */ diff --git a/Sources/Db/DatabaseApiInterface.php b/Sources/Db/DatabaseApiInterface.php index 821e25c801..7063cc0847 100644 --- a/Sources/Db/DatabaseApiInterface.php +++ b/Sources/Db/DatabaseApiInterface.php @@ -207,6 +207,15 @@ public function error(object $connection): string; */ public function select(string $database, ?object $connection = null): bool; + /** + * Gets a list of engines that MySQL supports. + * + * Returns an empty array for PostgreSQL. + * + * @return array Supported engines. + */ + public function get_engines(): array; + /** * Escape the LIKE wildcards so that they match the character and not the wildcard. * diff --git a/other/upgrade.php b/other/upgrade.php index 7a520998fe..1c50faf435 100644 --- a/other/upgrade.php +++ b/other/upgrade.php @@ -1946,6 +1946,10 @@ function DatabaseChanges() ); } + if (Config::$db_type == 'mysql') { + convertToInnoDb(); + } + // So the template knows we're done. if (!$support_js) { $upcontext['changes_complete'] = true; @@ -1970,8 +1974,50 @@ function setSqlMode($strict = true) } mysqli_query(Db::$db_connection, 'SET SESSION sql_mode = \'' . $mode . '\''); +} +/** + * Converts all MySQL tables to the InnoDB engine and dynamic rows. + */ +function convertToInnoDb() +{ + if (Config::$db_type != 'mysql') { + return; + } + $tables = Db::$db->list_tables(false, Db::$db->prefix . '%'); + + foreach ($tables as $table) { + $structure = Db::$db->table_structure($table); + + if ($structure['engine'] !== 'InnoDB') { + Db::$db->query( + '', + 'ALTER TABLE {identifier:table} + ENGINE {literal:InnoDB} + ROW_FORMAT=DYNAMIC', + [ + 'table' => $table, + ], + ); + } elseif ($structure['row_format'] !== 'Dynamic') { + Db::$db->query( + '', + 'ALTER TABLE {identifier:table} + ROW_FORMAT=DYNAMIC', + [ + 'table' => $table, + ], + ); + } + } + + // Ensure all future tables use dynamic row format. + Db::$db->query( + '', + 'SET GLOBAL innodb_default_row_format=DYNAMIC', + [], + ); } // Delete the damn thing! @@ -2347,7 +2393,7 @@ function ($errno, $errstr, $errfile, $errline) use ($support_js) { ); // If we're on MySQL, set {db_collation}; this approach is used throughout upgrade_2-0_mysql.php to set new tables to utf8 - // Note it is expected to be in the format: ENGINE=MyISAM{$db_collation}; + // Note it is expected to be in the format: ENGINE=InnoDB{$db_collation}; if (Config::$db_type == 'mysql') { $db_collation = ' DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci'; } else { @@ -2364,7 +2410,7 @@ function ($errno, $errstr, $errfile, $errline) use ($support_js) { $last_step = ''; // Make sure all newly created tables will have the proper characters set; this approach is used throughout upgrade_2-1_mysql.php - $lines = str_replace(') ENGINE=MyISAM;', ') ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;', $lines); + $lines = preg_replace('/\) ENGINE=(InnoDB|MyISAM);/', ') ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;', $lines); // Count the total number of steps within this file - for progress. $file_steps = substr_count(implode('', $lines), '---#');