From 770f5de313e7e79b6f3c02322c9dda33e3f7092c Mon Sep 17 00:00:00 2001 From: Matthias Schmidt Date: Sat, 10 Aug 2019 16:05:34 +0200 Subject: [PATCH] Improve speed of MySQLDatabaseEditor::getForeignKeys() The JOIN made the previous very slow. --- .../editor/MySQLDatabaseEditor.class.php | 63 ++++++++++--------- 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/wcfsetup/install/files/lib/system/database/editor/MySQLDatabaseEditor.class.php b/wcfsetup/install/files/lib/system/database/editor/MySQLDatabaseEditor.class.php index 0f22908e5e..ecd82689f5 100644 --- a/wcfsetup/install/files/lib/system/database/editor/MySQLDatabaseEditor.class.php +++ b/wcfsetup/install/files/lib/system/database/editor/MySQLDatabaseEditor.class.php @@ -1,5 +1,6 @@ dbObj->prepareStatement($sql); $statement->execute([ $this->dbObj->getDatabaseName(), $tableName ]); - $keyInformation = $statement->fetchAll(\PDO::FETCH_ASSOC); + $referentialConstraints = $statement->fetchAll(\PDO::FETCH_ASSOC); $validActions = ['CASCADE', 'SET NULL', 'NO ACTION']; $foreignKeys = []; - foreach ($keyInformation as $information) { - if (!isset($foreignKeys[$information['CONSTRAINT_NAME']])) { - $foreignKeys[$information['CONSTRAINT_NAME']] = [ - 'columns' => [$information['COLUMN_NAME']], - 'referencedColumns' => [$information['REFERENCED_COLUMN_NAME']], - 'referencedTable' => $information['REFERENCED_TABLE_NAME'], - 'ON DELETE' => in_array($information['DELETE_RULE'], $validActions) ? $information['DELETE_RULE'] : null, - 'ON UPDATE' => in_array($information['UPDATE_RULE'], $validActions) ? $information['UPDATE_RULE'] : null - ]; - } - else { - $foreignKeys[$information['CONSTRAINT_NAME']]['columns'][] = $information['COLUMN_NAME']; - $foreignKeys[$information['CONSTRAINT_NAME']]['referencedColumns'][] = $information['REFERENCED_COLUMN_NAME']; - } + foreach ($referentialConstraints as $information) { + $foreignKeys[$information['CONSTRAINT_NAME']] = [ + 'columns' => [], + 'referencedColumns' => [], + 'ON DELETE' => in_array($information['DELETE_RULE'], $validActions) ? $information['DELETE_RULE'] : null, + 'ON UPDATE' => in_array($information['UPDATE_RULE'], $validActions) ? $information['UPDATE_RULE'] : null + ]; + } + + if (empty($foreignKeys)) { + return []; + } + + $conditionBuilder = new PreparedStatementConditionBuilder(); + $conditionBuilder->add('CONSTRAINT_NAME IN (?)', [array_keys($foreignKeys)]); + $conditionBuilder->add('TABLE_SCHEMA = ?', [$this->dbObj->getDatabaseName()]); + $conditionBuilder->add('TABLE_NAME = ?', [$tableName]); + + $sql = "SELECT CONSTRAINT_NAME, COLUMN_NAME, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME + FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE + " . $conditionBuilder; + $statement = $this->dbObj->prepareStatement($sql); + $statement->execute($conditionBuilder->getParameters()); + $keyColumnUsage = $statement->fetchAll(\PDO::FETCH_ASSOC); + + foreach ($keyColumnUsage as $information) { + $foreignKeys[$information['CONSTRAINT_NAME']]['columns'][] = $information['COLUMN_NAME']; + $foreignKeys[$information['CONSTRAINT_NAME']]['referencedColumns'][] = $information['REFERENCED_COLUMN_NAME']; + $foreignKeys[$information['CONSTRAINT_NAME']]['referencedTable'] = $information['REFERENCED_TABLE_NAME']; } foreach ($foreignKeys as $keyName => $keyData) { -- 2.20.1