From abc48ca76f7a9bed70e63ee9f4bb1b91d7c5a2e8 Mon Sep 17 00:00:00 2001 From: Taras Machyshyn Date: Fri, 13 Jul 2018 16:52:02 +0300 Subject: [PATCH] Fulltext bug fixes --- .../Database/DBAL/Driver/PDOMySql/Driver.php | 11 +- .../Core/Utils/Database/DBAL/Schema/Index.php | 82 ++++++++++ .../DBAL/Schema/MySqlSchemaManager.php | 144 ++++++++++++++++++ .../Utils/Database/DBAL/Schema/Schema.php | 2 +- .../Core/Utils/Database/DBAL/Schema/Table.php | 34 ++++- 5 files changed, 267 insertions(+), 6 deletions(-) create mode 100644 application/Espo/Core/Utils/Database/DBAL/Schema/Index.php create mode 100644 application/Espo/Core/Utils/Database/DBAL/Schema/MySqlSchemaManager.php diff --git a/application/Espo/Core/Utils/Database/DBAL/Driver/PDOMySql/Driver.php b/application/Espo/Core/Utils/Database/DBAL/Driver/PDOMySql/Driver.php index 64c03f8776..fa4d3e6455 100644 --- a/application/Espo/Core/Utils/Database/DBAL/Driver/PDOMySql/Driver.php +++ b/application/Espo/Core/Utils/Database/DBAL/Driver/PDOMySql/Driver.php @@ -25,16 +25,19 @@ * * In accordance with Section 7(b) of the GNU General Public License version 3, * these Appropriate Legal Notices must retain the display of the "EspoCRM" word. - ************************************************************************/ + ************************************************************************/ namespace Espo\Core\Utils\Database\DBAL\Driver\PDOMySql; -class Driver extends \Doctrine\DBAL\Driver\PDOMySql\Driver +class Driver extends \Doctrine\DBAL\Driver\PDOMySql\Driver { - public function getDatabasePlatform() { return new \Espo\Core\Utils\Database\DBAL\Platforms\MySqlPlatform(); } - + + public function getSchemaManager(\Doctrine\DBAL\Connection $conn) + { + return new \Espo\Core\Utils\Database\DBAL\Schema\MySqlSchemaManager($conn); + } } \ No newline at end of file diff --git a/application/Espo/Core/Utils/Database/DBAL/Schema/Index.php b/application/Espo/Core/Utils/Database/DBAL/Schema/Index.php new file mode 100644 index 0000000000..6c14080585 --- /dev/null +++ b/application/Espo/Core/Utils/Database/DBAL/Schema/Index.php @@ -0,0 +1,82 @@ +_flags[strtolower($flag)] = true; + + return $this; + } + + public function hasFlag($flag) + { + return isset($this->_flags[strtolower($flag)]); + } + + public function removeFlag($flag) + { + unset($this->_flags[strtolower($flag)]); + } + + public function isFullfilledBy(DBALIndex $other) + { + if (count($other->getColumns()) != count($this->getColumns())) { + return false; + } + + $sameColumns = $this->spansColumns($other->getColumns()); + + if ($sameColumns) { + $flags = $this->getFlags(); + $otherFlags = $other->getFlags(); + + if ( ! $this->isUnique() && !$this->isPrimary() && $flags === $otherFlags) { + return true; + } else if ($other->isPrimary() != $this->isPrimary()) { + return false; + } else if ($other->isUnique() != $this->isUnique()) { + return false; + } + + if (count($flags) != count($otherFlags) || array_diff($flags, $otherFlags) !== array_diff($otherFlags, $flags)) { + return false; + } + + return true; + } + + return false; + } +} \ No newline at end of file diff --git a/application/Espo/Core/Utils/Database/DBAL/Schema/MySqlSchemaManager.php b/application/Espo/Core/Utils/Database/DBAL/Schema/MySqlSchemaManager.php new file mode 100644 index 0000000000..29161e8fc7 --- /dev/null +++ b/application/Espo/Core/Utils/Database/DBAL/Schema/MySqlSchemaManager.php @@ -0,0 +1,144 @@ +_platform->supportsSequences()) { + $sequences = $this->listSequences(); + } + $tables = $this->listTables(); + + return new Schema($tables, $sequences, $this->createSchemaConfig()); + } + + public function listTables() + { + $tableNames = $this->listTableNames(); + + $tables = array(); + foreach ($tableNames as $tableName) { + $tables[] = $this->listTableDetails($tableName); + } + + return $tables; + } + + public function listTableDetails($tableName) + { + $columns = $this->listTableColumns($tableName); + $foreignKeys = array(); + if ($this->_platform->supportsForeignKeyConstraints()) { + $foreignKeys = $this->listTableForeignKeys($tableName); + } + $indexes = $this->listTableIndexes($tableName); + + return new Table($tableName, $columns, $indexes, $foreignKeys, false, array()); + } + + public function listTableIndexes($table) + { + $sql = $this->_platform->getListTableIndexesSQL($table, $this->_conn->getDatabase()); + + $tableIndexes = $this->_conn->fetchAll($sql); + + return $this->_getPortableTableIndexesList($tableIndexes, $table); + } + + protected function _getPortableTableIndexesList($tableIndexes, $tableName=null) + { + foreach($tableIndexes as $k => $v) { + $v = array_change_key_case($v, CASE_LOWER); + if($v['key_name'] == 'PRIMARY') { + $v['primary'] = true; + } else { + $v['primary'] = false; + } + if (strpos($v['index_type'], 'FULLTEXT') !== false) { + $v['flags'] = array('FULLTEXT'); + } + $tableIndexes[$k] = $v; + } + + $result = array(); + foreach($tableIndexes as $tableIndex) { + + $indexName = $keyName = $tableIndex['key_name']; + if ($tableIndex['primary']) { + $keyName = 'primary'; + } + $keyName = strtolower($keyName); + + if (!isset($result[$keyName])) { + $result[$keyName] = array( + 'name' => $indexName, + 'columns' => array($tableIndex['column_name']), + 'unique' => $tableIndex['non_unique'] ? false : true, + 'primary' => $tableIndex['primary'], + 'flags' => isset($tableIndex['flags']) ? $tableIndex['flags'] : array(), + ); + } else { + $result[$keyName]['columns'][] = $tableIndex['column_name']; + } + } + + $eventManager = $this->_platform->getEventManager(); + + $indexes = array(); + foreach($result as $indexKey => $data) { + $index = null; + $defaultPrevented = false; + + if (null !== $eventManager && $eventManager->hasListeners(Events::onSchemaIndexDefinition)) { + $eventArgs = new SchemaIndexDefinitionEventArgs($data, $tableName, $this->_conn); + $eventManager->dispatchEvent(Events::onSchemaIndexDefinition, $eventArgs); + + $defaultPrevented = $eventArgs->isDefaultPrevented(); + $index = $eventArgs->getIndex(); + } + + if ( ! $defaultPrevented) { + $index = new Index($data['name'], $data['columns'], $data['unique'], $data['primary'], $data['flags']); + } + + if ($index) { + $indexes[$indexKey] = $index; + } + } + + return $indexes; + } +} \ No newline at end of file diff --git a/application/Espo/Core/Utils/Database/DBAL/Schema/Schema.php b/application/Espo/Core/Utils/Database/DBAL/Schema/Schema.php index eff3bd0ed1..24c6e52747 100644 --- a/application/Espo/Core/Utils/Database/DBAL/Schema/Schema.php +++ b/application/Espo/Core/Utils/Database/DBAL/Schema/Schema.php @@ -28,9 +28,9 @@ ************************************************************************/ namespace Espo\Core\Utils\Database\DBAL\Schema; + class Schema extends \Doctrine\DBAL\Schema\Schema { - /** * Creates a new table. * diff --git a/application/Espo/Core/Utils/Database/DBAL/Schema/Table.php b/application/Espo/Core/Utils/Database/DBAL/Schema/Table.php index 07040edc79..1985781609 100644 --- a/application/Espo/Core/Utils/Database/DBAL/Schema/Table.php +++ b/application/Espo/Core/Utils/Database/DBAL/Schema/Table.php @@ -28,11 +28,12 @@ ************************************************************************/ namespace Espo\Core\Utils\Database\DBAL\Schema; + use Doctrine\DBAL\Types\Type; +use Doctrine\DBAL\Schema\SchemaException; class Table extends \Doctrine\DBAL\Schema\Table { - /** * @param string $columnName * @param string $typeName @@ -49,4 +50,35 @@ class Table extends \Doctrine\DBAL\Schema\Table return $column; } + public function addIndex(array $columnNames, $indexName = null, array $flags = array()) + { + if($indexName == null) { + $indexName = $this->_generateIdentifierName( + array_merge(array($this->getName()), $columnNames), "idx", $this->_getMaxIdentifierLength() + ); + } + + return $this->_createIndex($columnNames, $indexName, false, false, $flags); + } + + private function _createIndex(array $columnNames, $indexName, $isUnique, $isPrimary, array $flags = array()) + { + if (preg_match('(([^a-zA-Z0-9_]+))', $indexName)) { + throw SchemaException::indexNameInvalid($indexName); + } + + foreach ($columnNames as $columnName => $indexColOptions) { + if (is_numeric($columnName) && is_string($indexColOptions)) { + $columnName = $indexColOptions; + } + + if ( ! $this->hasColumn($columnName)) { + throw SchemaException::columnDoesNotExist($columnName, $this->_name); + } + } + + $this->_addIndex(new Index($indexName, $columnNames, $isUnique, $isPrimary, $flags)); + + return $this; + } } \ No newline at end of file