redefine doctrine DBAL classes
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Espo\Core\Utils\Database\DBAL\Driver\Mysqli;
|
||||
|
||||
class Driver extends \Doctrine\DBAL\Driver\Mysqli\Driver
|
||||
{
|
||||
|
||||
public function getDatabasePlatform()
|
||||
{
|
||||
return new \Espo\Core\Utils\Database\DBAL\Platforms\MySqlPlatform();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Espo\Core\Utils\Database\DBAL\Driver\PDOMySql;
|
||||
|
||||
class Driver extends \Doctrine\DBAL\Driver\PDOMySql\Driver
|
||||
{
|
||||
|
||||
public function getDatabasePlatform()
|
||||
{
|
||||
return new \Espo\Core\Utils\Database\DBAL\Platforms\MySqlPlatform();
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Espo\Core\Utils\Database\FieldTypes;
|
||||
namespace Espo\Core\Utils\Database\DBAL\FieldTypes;
|
||||
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Espo\Core\Utils\Database\FieldTypes;
|
||||
namespace Espo\Core\Utils\Database\DBAL\FieldTypes;
|
||||
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Espo\Core\Utils\Database\FieldTypes;
|
||||
namespace Espo\Core\Utils\Database\DBAL\FieldTypes;
|
||||
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Espo\Core\Utils\Database\FieldTypes;
|
||||
namespace Espo\Core\Utils\Database\DBAL\FieldTypes;
|
||||
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||
@@ -0,0 +1,252 @@
|
||||
<?php
|
||||
|
||||
namespace Espo\Core\Utils\Database\DBAL\Platforms;
|
||||
|
||||
use Doctrine\DBAL\Schema\TableDiff;
|
||||
use Doctrine\DBAL\Schema\Index;
|
||||
use Doctrine\DBAL\Schema\Table;
|
||||
|
||||
|
||||
class MySqlPlatform extends \Doctrine\DBAL\Platforms\MySqlPlatform
|
||||
{
|
||||
|
||||
public function getAlterTableSQL(TableDiff $diff)
|
||||
{
|
||||
$columnSql = array();
|
||||
$queryParts = array();
|
||||
if ($diff->newName !== false) {
|
||||
$queryParts[] = 'RENAME TO ' . $diff->newName;
|
||||
}
|
||||
|
||||
foreach ($diff->addedColumns as $column) {
|
||||
if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$columnArray = $column->toArray();
|
||||
$columnArray['comment'] = $this->getColumnComment($column);
|
||||
$queryParts[] = 'ADD ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray);
|
||||
}
|
||||
|
||||
foreach ($diff->removedColumns as $column) {
|
||||
if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//$queryParts[] = 'DROP ' . $column->getQuotedName($this); //espo: no needs to remove columns
|
||||
}
|
||||
|
||||
foreach ($diff->changedColumns as $columnDiff) {
|
||||
if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* @var $columnDiff \Doctrine\DBAL\Schema\ColumnDiff */
|
||||
$column = $columnDiff->column;
|
||||
$columnArray = $column->toArray();
|
||||
$columnArray['comment'] = $this->getColumnComment($column);
|
||||
|
||||
$queryParts[] = 'CHANGE ' . ($columnDiff->oldColumnName) . ' '
|
||||
. $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray);
|
||||
}
|
||||
|
||||
//espo: It works not correctly. It can rename some existing fields
|
||||
foreach ($diff->renamedColumns as $oldColumnName => $column) {
|
||||
if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$columnArray = $column->toArray();
|
||||
$columnArray['comment'] = $this->getColumnComment($column);
|
||||
/*$queryParts[] = 'CHANGE ' . $oldColumnName . ' '
|
||||
. $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray); */
|
||||
$queryParts[] = 'ADD ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray); //espo: fixed the problem
|
||||
} //espo: END
|
||||
|
||||
|
||||
$sql = array();
|
||||
$tableSql = array();
|
||||
|
||||
if ( ! $this->onSchemaAlterTable($diff, $tableSql)) {
|
||||
if (count($queryParts) > 0) {
|
||||
$sql[] = 'ALTER TABLE ' . $this->espoQuote($diff->name) . ' ' . implode(", ", $queryParts);
|
||||
}
|
||||
$sql = array_merge(
|
||||
$this->getPreAlterTableIndexForeignKeySQL($diff),
|
||||
$sql,
|
||||
$this->getPostAlterTableIndexForeignKeySQL($diff)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
return array_merge($sql, $tableSql, $columnSql);
|
||||
}
|
||||
|
||||
|
||||
protected function getPreAlterTableIndexForeignKeySQL(TableDiff $diff)
|
||||
{
|
||||
$sql = array();
|
||||
$table = $diff->name;
|
||||
|
||||
foreach ($diff->removedIndexes as $remKey => $remIndex) {
|
||||
|
||||
foreach ($diff->addedIndexes as $addKey => $addIndex) {
|
||||
if ($remIndex->getColumns() == $addIndex->getColumns()) {
|
||||
|
||||
$type = '';
|
||||
if ($addIndex->isUnique()) {
|
||||
$type = 'UNIQUE ';
|
||||
}
|
||||
|
||||
$query = 'ALTER TABLE ' . $this->espoQuote($table) . ' DROP INDEX ' . $remIndex->getName() . ', ';
|
||||
$query .= 'ADD ' . $type . 'INDEX ' . $addIndex->getName();
|
||||
$query .= ' (' . $this->getIndexFieldDeclarationListSQL($addIndex->getQuotedColumns($this)) . ')';
|
||||
|
||||
$sql[] = $query;
|
||||
|
||||
unset($diff->removedIndexes[$remKey]);
|
||||
unset($diff->addedIndexes[$addKey]);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$sql = array_merge($sql, parent::getPreAlterTableIndexForeignKeySQL($diff));
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
|
||||
public function getDropIndexSQL($index, $table=null)
|
||||
{
|
||||
if ($index instanceof Index) {
|
||||
$indexName = $index->getQuotedName($this);
|
||||
} else if(is_string($index)) {
|
||||
$indexName = $index;
|
||||
} else {
|
||||
throw new \InvalidArgumentException('MysqlPlatform::getDropIndexSQL() expects $index parameter to be string or \Doctrine\DBAL\Schema\Index.');
|
||||
}
|
||||
|
||||
if ($table instanceof Table) {
|
||||
$table = $table->getQuotedName($this);
|
||||
} else if(!is_string($table)) {
|
||||
throw new \InvalidArgumentException('MysqlPlatform::getDropIndexSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.');
|
||||
}
|
||||
|
||||
if ($index instanceof Index && $index->isPrimary()) {
|
||||
// mysql primary keys are always named "PRIMARY",
|
||||
// so we cannot use them in statements because of them being keyword.
|
||||
return $this->getDropPrimaryKeySQL($table);
|
||||
}
|
||||
|
||||
return 'DROP INDEX ' . $indexName . ' ON ' . $this->espoQuote($table);
|
||||
}
|
||||
|
||||
protected function getDropPrimaryKeySQL($table)
|
||||
{
|
||||
return 'ALTER TABLE ' . $this->espoQuote($table) . ' DROP PRIMARY KEY';
|
||||
}
|
||||
|
||||
public function getDropTemporaryTableSQL($table)
|
||||
{
|
||||
if ($table instanceof Table) {
|
||||
$table = $table->getQuotedName($this);
|
||||
} else if(!is_string($table)) {
|
||||
throw new \InvalidArgumentException('getDropTableSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.');
|
||||
}
|
||||
|
||||
return 'DROP TEMPORARY TABLE ' . $this->espoQuote($table);
|
||||
}
|
||||
|
||||
//ESPO: fix problem with quoting table name
|
||||
public function espoQuote($name)
|
||||
{
|
||||
if ($name instanceof Table) {
|
||||
$name = $name->getQuotedName($this);
|
||||
}
|
||||
|
||||
if (isset($name[0]) && $name[0] != '`') {
|
||||
$name = $this->quoteIdentifier($name);
|
||||
}
|
||||
return $name;
|
||||
}
|
||||
|
||||
public function getCreateForeignKeySQL(\Doctrine\DBAL\Schema\ForeignKeyConstraint $foreignKey, $table)
|
||||
{
|
||||
$query = 'ALTER TABLE ' . $this->espoQuote($table) . ' ADD ' . $this->getForeignKeyDeclarationSQL($foreignKey);
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
public function getIndexDeclarationSQL($name, Index $index)
|
||||
{
|
||||
$columns = $index->getQuotedColumns($this);
|
||||
|
||||
if (count($columns) === 0) {
|
||||
throw new \InvalidArgumentException("Incomplete definition. 'columns' required.");
|
||||
}
|
||||
|
||||
return $this->getCreateIndexSQLFlags($index) . 'INDEX ' . $this->espoQuote($name) . ' ('
|
||||
. $this->getIndexFieldDeclarationListSQL($columns)
|
||||
. ')';
|
||||
}
|
||||
|
||||
public function getCreateIndexSQL(Index $index, $table)
|
||||
{
|
||||
if ($table instanceof Table) {
|
||||
$table = $table->getQuotedName($this);
|
||||
}
|
||||
$name = $index->getQuotedName($this);
|
||||
$columns = $index->getQuotedColumns($this);
|
||||
|
||||
if (count($columns) == 0) {
|
||||
throw new \InvalidArgumentException("Incomplete definition. 'columns' required.");
|
||||
}
|
||||
|
||||
if ($index->isPrimary()) {
|
||||
return $this->getCreatePrimaryKeySQL($index, $table);
|
||||
}
|
||||
|
||||
$query = 'CREATE ' . $this->getCreateIndexSQLFlags($index) . 'INDEX ' . $name . ' ON ' . $this->espoQuote($table);
|
||||
$query .= ' (' . $this->getIndexFieldDeclarationListSQL($columns) . ')';
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
public function getDropConstraintSQL($constraint, $table)
|
||||
{
|
||||
if ($constraint instanceof Constraint) {
|
||||
$constraint = $constraint->getQuotedName($this);
|
||||
}
|
||||
|
||||
if ($table instanceof Table) {
|
||||
$table = $table->getQuotedName($this);
|
||||
}
|
||||
|
||||
return 'ALTER TABLE ' . $this->espoQuote($table) . ' DROP CONSTRAINT ' . $constraint;
|
||||
}
|
||||
|
||||
public function getDropForeignKeySQL($foreignKey, $table)
|
||||
{
|
||||
if ($foreignKey instanceof ForeignKeyConstraint) {
|
||||
$foreignKey = $foreignKey->getQuotedName($this);
|
||||
}
|
||||
|
||||
if ($table instanceof Table) {
|
||||
$table = $table->getQuotedName($this);
|
||||
}
|
||||
|
||||
return 'ALTER TABLE ' . $this->espoQuote($table) . ' DROP FOREIGN KEY ' . $foreignKey;
|
||||
}
|
||||
|
||||
public function getCreatePrimaryKeySQL(Index $index, $table)
|
||||
{
|
||||
if ($table instanceof Table) {
|
||||
$table = $table->getQuotedName($this);
|
||||
}
|
||||
|
||||
return 'ALTER TABLE ' . $this->espoQuote($table) . ' ADD PRIMARY KEY (' . $this->getIndexFieldDeclarationListSQL($index->getQuotedColumns($this)) . ')';
|
||||
}
|
||||
//end: ESPO
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
namespace Espo\Core\Utils\Database\DBAL\Schema;
|
||||
|
||||
use Doctrine\DBAL\Schema\Column;
|
||||
|
||||
|
||||
class Comparator extends \Doctrine\DBAL\Schema\Comparator
|
||||
{
|
||||
|
||||
public function diffColumn(Column $column1, Column $column2)
|
||||
{
|
||||
$changedProperties = array();
|
||||
if ( $column1->getType() != $column2->getType() ) {
|
||||
|
||||
//espo: fix problem with executing query for custom types
|
||||
$column1DbTypeName = method_exists($column1->getType(), 'getDbTypeName') ? $column1->getType()->getDbTypeName() : $column1->getType()->getName();
|
||||
$column2DbTypeName = method_exists($column2->getType(), 'getDbTypeName') ? $column2->getType()->getDbTypeName() : $column2->getType()->getName();
|
||||
|
||||
if (strtolower($column1DbTypeName) != strtolower($column2DbTypeName)) {
|
||||
$changedProperties[] = 'type';
|
||||
}
|
||||
//END: espo
|
||||
}
|
||||
|
||||
if ($column1->getNotnull() != $column2->getNotnull()) {
|
||||
$changedProperties[] = 'notnull';
|
||||
}
|
||||
|
||||
if ($column1->getDefault() != $column2->getDefault()) {
|
||||
$changedProperties[] = 'default';
|
||||
}
|
||||
|
||||
if ($column1->getUnsigned() != $column2->getUnsigned()) {
|
||||
$changedProperties[] = 'unsigned';
|
||||
}
|
||||
|
||||
if ($column1->getType() instanceof \Doctrine\DBAL\Types\StringType) {
|
||||
// check if value of length is set at all, default value assumed otherwise.
|
||||
$length1 = $column1->getLength() ?: 255;
|
||||
$length2 = $column2->getLength() ?: 255;
|
||||
if ($length1 != $length2) {
|
||||
$changedProperties[] = 'length';
|
||||
}
|
||||
|
||||
if ($column1->getFixed() != $column2->getFixed()) {
|
||||
$changedProperties[] = 'fixed';
|
||||
}
|
||||
}
|
||||
|
||||
if ($column1->getType() instanceof \Doctrine\DBAL\Types\DecimalType) {
|
||||
if (($column1->getPrecision()?:10) != ($column2->getPrecision()?:10)) {
|
||||
$changedProperties[] = 'precision';
|
||||
}
|
||||
if ($column1->getScale() != $column2->getScale()) {
|
||||
$changedProperties[] = 'scale';
|
||||
}
|
||||
}
|
||||
|
||||
if ($column1->getAutoincrement() != $column2->getAutoincrement()) {
|
||||
$changedProperties[] = 'autoincrement';
|
||||
}
|
||||
|
||||
// only allow to delete comment if its set to '' not to null.
|
||||
if ($column1->getComment() !== null && $column1->getComment() != $column2->getComment()) {
|
||||
$changedProperties[] = 'comment';
|
||||
}
|
||||
|
||||
$options1 = $column1->getCustomSchemaOptions();
|
||||
$options2 = $column2->getCustomSchemaOptions();
|
||||
|
||||
$commonKeys = array_keys(array_intersect_key($options1, $options2));
|
||||
|
||||
foreach ($commonKeys as $key) {
|
||||
if ($options1[$key] !== $options2[$key]) {
|
||||
$changedProperties[] = $key;
|
||||
}
|
||||
}
|
||||
|
||||
$diffKeys = array_keys(array_diff_key($options1, $options2) + array_diff_key($options2, $options1));
|
||||
|
||||
$changedProperties = array_merge($changedProperties, $diffKeys);
|
||||
|
||||
return $changedProperties;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -11,7 +11,7 @@ class Converter
|
||||
private $dbalSchema;
|
||||
private $fileManager;
|
||||
|
||||
private $customTablePath = 'application/Espo/Core/Utils/Database/Schema/customTables';
|
||||
private $customTablePath = 'application/Espo/Core/Utils/Database/Schema/CustomTables';
|
||||
|
||||
protected $typeList;
|
||||
|
||||
@@ -148,18 +148,7 @@ class Converter
|
||||
if (!isset($tables[$tableName])) { //no needs to create the table if it already exists
|
||||
$tables[$tableName] = $this->prepareManyMany($entityName, $relationParams, $tables);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'hasMany':
|
||||
if (isset($relationParams['relationName'])) {
|
||||
$tableName = $relationParams['relationName'];
|
||||
|
||||
//check for duplication tables
|
||||
if (!isset($tables[$tableName])) { //no needs to create the table if it already exists
|
||||
$tables[$tableName] = $this->prepareManyMany($entityName, $relationParams, $tables);
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'belongsTo':
|
||||
$foreignEntity = $relationParams['entity'];
|
||||
|
||||
@@ -18,6 +18,16 @@ class Schema
|
||||
|
||||
private $connection;
|
||||
|
||||
protected $drivers = array(
|
||||
'mysqli' => '\Espo\Core\Utils\Database\DBAL\Driver\Mysqli\Driver',
|
||||
'pdo_mysql' => '\Espo\Core\Utils\Database\DBAL\Driver\PDOMySql\Driver',
|
||||
);
|
||||
|
||||
protected $fieldTypePaths = array(
|
||||
'Espo/Core/Utils/Database/DBAL/FieldTypes',
|
||||
'Espo/Custom/Core/Utils/Database/DBAL/FieldTypes',
|
||||
);
|
||||
|
||||
|
||||
public function __construct(\Espo\Core\Utils\Config $config, \Espo\Core\Utils\Metadata $metadata, \Espo\Core\Utils\File\Manager $fileManager)
|
||||
{
|
||||
@@ -25,7 +35,7 @@ class Schema
|
||||
$this->metadata = $metadata;
|
||||
$this->fileManager = $fileManager;
|
||||
|
||||
$this->comparator = new \Doctrine\DBAL\Schema\Comparator();
|
||||
$this->comparator = new \Espo\Core\Utils\Database\DBAL\Schema\Comparator();
|
||||
$this->initFieldTypes();
|
||||
|
||||
$this->converter = new \Espo\Core\Utils\Database\Converter($this->metadata, $this->fileManager);
|
||||
@@ -72,6 +82,9 @@ class Schema
|
||||
$dbalConfig = new \Doctrine\DBAL\Configuration();
|
||||
|
||||
$connectionParams = (array) $this->getConfig()->get('database');
|
||||
|
||||
$connectionParams['driverClass'] = $this->drivers[ $connectionParams['driver'] ];
|
||||
unset($connectionParams['driver']);
|
||||
|
||||
$this->connection = \Doctrine\DBAL\DriverManager::getConnection($connectionParams, $dbalConfig);
|
||||
|
||||
@@ -81,12 +94,7 @@ class Schema
|
||||
|
||||
protected function initFieldTypes()
|
||||
{
|
||||
$typePaths = array(
|
||||
'Espo/Core/Utils/Database/FieldTypes',
|
||||
'Espo/Custom/Core/Utils/Database/FieldTypes',
|
||||
);
|
||||
|
||||
foreach($typePaths as $path) {
|
||||
foreach($this->fieldTypePaths as $path) {
|
||||
|
||||
$typeList = $this->getFileManager()->getFileList('application/'.$path, false, '\.php$');
|
||||
if ($typeList !== false) {
|
||||
|
||||
Reference in New Issue
Block a user