mirror of
https://github.com/phpbb/phpbb.git
synced 2025-05-31 19:49:20 +02:00
966 lines
22 KiB
PHP
966 lines
22 KiB
PHP
<?php
|
|
/**
|
|
*
|
|
* This file is part of the phpBB Forum Software package.
|
|
*
|
|
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
|
* @license GNU General Public License, version 2 (GPL-2.0)
|
|
*
|
|
* For full copyright and license information, please see
|
|
* the docs/CREDITS.txt file.
|
|
*
|
|
*/
|
|
|
|
namespace phpbb\db\tools;
|
|
|
|
use Doctrine\DBAL\Connection;
|
|
use Doctrine\DBAL\Exception;
|
|
use Doctrine\DBAL\Schema\AbstractAsset;
|
|
use Doctrine\DBAL\Schema\AbstractSchemaManager;
|
|
use Doctrine\DBAL\Schema\Index;
|
|
use Doctrine\DBAL\Schema\Schema;
|
|
use Doctrine\DBAL\Schema\SchemaException;
|
|
use Doctrine\DBAL\Schema\Sequence;
|
|
use Doctrine\DBAL\Schema\Table;
|
|
use Doctrine\DBAL\Types\Type;
|
|
use phpbb\db\doctrine\comparator;
|
|
use phpbb\db\doctrine\table_helper;
|
|
|
|
/**
|
|
* BC layer for database tools.
|
|
*
|
|
* In general, it is recommended to use Doctrine directly instead of this class as this
|
|
* implementation is only a BC layer.
|
|
*/
|
|
class doctrine implements tools_interface
|
|
{
|
|
/**
|
|
* @var AbstractSchemaManager
|
|
*/
|
|
private $schema_manager;
|
|
|
|
/**
|
|
* @var Connection
|
|
*/
|
|
private $connection;
|
|
|
|
/**
|
|
* @var bool
|
|
*/
|
|
private $return_statements;
|
|
|
|
/**
|
|
* Database tools constructors.
|
|
*
|
|
* @param Connection $connection
|
|
* @param bool $return_statements
|
|
*/
|
|
public function __construct(Connection $connection, bool $return_statements = false)
|
|
{
|
|
$this->return_statements = $return_statements;
|
|
$this->connection = $connection;
|
|
}
|
|
|
|
/**
|
|
* @return AbstractSchemaManager
|
|
*
|
|
* @throws Exception
|
|
*/
|
|
protected function get_schema_manager(): AbstractSchemaManager
|
|
{
|
|
if ($this->schema_manager == null)
|
|
{
|
|
$this->schema_manager = $this->connection->createSchemaManager();
|
|
}
|
|
|
|
return $this->schema_manager;
|
|
}
|
|
|
|
/**
|
|
* @return Schema
|
|
*
|
|
* @throws Exception
|
|
*/
|
|
protected function get_schema(): Schema
|
|
{
|
|
return $this->get_schema_manager()->createSchema();
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
public function sql_list_tables(): array
|
|
{
|
|
try
|
|
{
|
|
$tables = array_map('strtolower', $this->get_schema_manager()->listTableNames());
|
|
return array_combine($tables, $tables);
|
|
}
|
|
catch (Exception $e)
|
|
{
|
|
return [];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
public function sql_table_exists(string $table_name): bool
|
|
{
|
|
try
|
|
{
|
|
return $this->get_schema_manager()->tablesExist([$table_name]);
|
|
}
|
|
catch (Exception $e)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
public function sql_list_columns(string $table_name): array
|
|
{
|
|
try
|
|
{
|
|
return $this->get_asset_names($this->get_schema_manager()->listTableColumns($table_name));
|
|
}
|
|
catch (Exception $e)
|
|
{
|
|
return [];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
public function sql_column_exists(string $table_name, string $column_name): bool
|
|
{
|
|
try
|
|
{
|
|
return $this->asset_exists($column_name, $this->get_schema_manager()->listTableColumns($table_name));
|
|
}
|
|
catch (Exception $e)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
public function sql_list_index(string $table_name): array
|
|
{
|
|
return $this->get_asset_names($this->get_filtered_index_list($table_name, true));
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
public function sql_index_exists(string $table_name, string $index_name): bool
|
|
{
|
|
return $this->asset_exists($index_name, $this->get_filtered_index_list($table_name, true));
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
public function sql_unique_index_exists(string $table_name, string $index_name): bool
|
|
{
|
|
return $this->asset_exists($index_name, $this->get_filtered_index_list($table_name, false));
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
public function perform_schema_changes(array $schema_changes)
|
|
{
|
|
if (empty($schema_changes))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return $this->alter_schema(
|
|
function (Schema $schema) use ($schema_changes): void
|
|
{
|
|
$this->schema_perform_changes($schema, $schema_changes);
|
|
}
|
|
);
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
public function sql_create_table(string $table_name, array $table_data)
|
|
{
|
|
return $this->alter_schema(
|
|
function (Schema $schema) use ($table_name, $table_data): void
|
|
{
|
|
$this->schema_create_table($schema, $table_name, $table_data, true);
|
|
}
|
|
);
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
public function sql_table_drop(string $table_name)
|
|
{
|
|
return $this->alter_schema(
|
|
function (Schema $schema) use ($table_name): void
|
|
{
|
|
$this->schema_drop_table($schema, $table_name, true);
|
|
}
|
|
);
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
public function sql_column_add(string $table_name, string $column_name, array $column_data)
|
|
{
|
|
return $this->alter_schema(
|
|
function (Schema $schema) use ($table_name, $column_name, $column_data): void
|
|
{
|
|
$this->schema_column_add($schema, $table_name, $column_name, $column_data);
|
|
}
|
|
);
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
public function sql_column_change(string $table_name, string $column_name, array $column_data)
|
|
{
|
|
$column_indexes = $this->get_filtered_index_list($table_name, true);
|
|
|
|
$column_indexes = array_filter($column_indexes, function($index) use ($column_name) {
|
|
$index_columns = array_map('strtolower', $index->getUnquotedColumns());
|
|
return in_array($column_name, $index_columns, true);
|
|
});
|
|
|
|
if (count($column_indexes))
|
|
{
|
|
$ret = $this->alter_schema(
|
|
function (Schema $schema) use ($table_name, $column_name, $column_data, $column_indexes): void
|
|
{
|
|
foreach ($column_indexes as $index)
|
|
{
|
|
$this->schema_index_drop($schema, $table_name, $index->getName());
|
|
}
|
|
}
|
|
);
|
|
|
|
if ($ret !== true)
|
|
{
|
|
return $ret;
|
|
}
|
|
}
|
|
|
|
return $this->alter_schema(
|
|
function (Schema $schema) use ($table_name, $column_name, $column_data, $column_indexes): void
|
|
{
|
|
$this->schema_column_change($schema, $table_name, $column_name, $column_data);
|
|
|
|
if (count($column_indexes))
|
|
{
|
|
foreach ($column_indexes as $index)
|
|
{
|
|
$this->schema_create_index($index->getColumns(), $schema, $table_name, $index->getName());
|
|
}
|
|
}
|
|
}
|
|
);
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
public function sql_column_remove(string $table_name, string $column_name)
|
|
{
|
|
// Check if this column is part of a primary key. If yes, remove the primary key.
|
|
$primary_key_indexes = $this->get_filtered_index_list($table_name, false);
|
|
|
|
$primary_key_indexes = array_filter($primary_key_indexes, function($index) use ($column_name) {
|
|
$index_columns = array_map('strtolower', $index->getUnquotedColumns());
|
|
return in_array($column_name, $index_columns, true) && $index->isPrimary();
|
|
});
|
|
|
|
if (count($primary_key_indexes))
|
|
{
|
|
$ret = $this->alter_schema(
|
|
function (Schema $schema) use ($table_name, $column_name): void
|
|
{
|
|
$table = $schema->getTable($table_name);
|
|
$table->dropPrimaryKey();
|
|
}
|
|
);
|
|
|
|
if ($ret !== true)
|
|
{
|
|
return $ret;
|
|
}
|
|
}
|
|
|
|
return $this->alter_schema(
|
|
function (Schema $schema) use ($table_name, $column_name): void
|
|
{
|
|
$this->schema_column_remove($schema, $table_name, $column_name);
|
|
}
|
|
);
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
public function sql_create_index(string $table_name, string $index_name, $column)
|
|
{
|
|
return $this->alter_schema(
|
|
function (Schema $schema) use ($table_name, $index_name, $column): void
|
|
{
|
|
$this->schema_create_index($column, $schema, $table_name, $index_name);
|
|
}
|
|
);
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
public function sql_index_drop(string $table_name, string $index_name)
|
|
{
|
|
return $this->alter_schema(
|
|
function (Schema $schema) use ($table_name, $index_name): void
|
|
{
|
|
$this->schema_index_drop($schema, $table_name, $index_name);
|
|
}
|
|
);
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
public function sql_create_unique_index(string $table_name, string $index_name, $column)
|
|
{
|
|
return $this->alter_schema(
|
|
function (Schema $schema) use ($table_name, $index_name, $column): void
|
|
{
|
|
$this->schema_create_unique_index($column, $schema, $table_name, $index_name);
|
|
}
|
|
);
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
public function sql_create_primary_key(string $table_name, $column)
|
|
{
|
|
return $this->alter_schema(
|
|
function (Schema $schema) use ($table_name, $column): void
|
|
{
|
|
$this->schema_create_primary_key($schema, $column, $table_name);
|
|
}
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Returns an array of indices for either unique and primary keys, or simple indices.
|
|
*
|
|
* @param string $table_name The name of the table.
|
|
* @param bool $is_non_unique Whether to return simple indices or primary and unique ones.
|
|
*
|
|
* @return Index[] The filtered index array.
|
|
*/
|
|
protected function get_filtered_index_list(string $table_name, bool $is_non_unique): array
|
|
{
|
|
try
|
|
{
|
|
$indices = $this->get_schema_manager()->listTableIndexes($table_name);
|
|
}
|
|
catch (Exception $e)
|
|
{
|
|
return [];
|
|
}
|
|
|
|
if ($is_non_unique)
|
|
{
|
|
return array_filter($indices, function (Index $index)
|
|
{
|
|
return $index->isSimpleIndex();
|
|
});
|
|
}
|
|
|
|
return array_filter($indices, function (Index $index)
|
|
{
|
|
return !$index->isSimpleIndex();
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Returns an array of lowercase asset names.
|
|
*
|
|
* @param array $assets Array of assets.
|
|
*
|
|
* @return array An array of lowercase asset names.
|
|
*/
|
|
protected function get_asset_names(array $assets): array
|
|
{
|
|
return array_map(
|
|
function (AbstractAsset $asset)
|
|
{
|
|
return strtolower($asset->getName());
|
|
},
|
|
$assets
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Returns whether an asset name exists in a list of assets (case insensitive).
|
|
*
|
|
* @param string $needle The asset name to search for.
|
|
* @param array $assets The array of assets.
|
|
*
|
|
* @return bool Whether the asset name exists in a list of assets.
|
|
*/
|
|
protected function asset_exists(string $needle, array $assets): bool
|
|
{
|
|
return in_array(strtolower($needle), $this->get_asset_names($assets), true);
|
|
}
|
|
|
|
/**
|
|
* Alter the current database representation using a callback and execute the changes.
|
|
* Returns false in case of error.
|
|
*
|
|
* @param callable $callback Callback taking the schema as parameters and returning it altered (or null in case of error)
|
|
*
|
|
* @return bool|string[]
|
|
*/
|
|
protected function alter_schema(callable $callback)
|
|
{
|
|
try
|
|
{
|
|
$current_schema = $this->get_schema();
|
|
$new_schema = clone $current_schema;
|
|
call_user_func($callback, $new_schema);
|
|
|
|
$comparator = new comparator();
|
|
$schemaDiff = $comparator->compareSchemas($current_schema, $new_schema);
|
|
$queries = $schemaDiff->toSql($this->get_schema_manager()->getDatabasePlatform());
|
|
|
|
if ($this->return_statements)
|
|
{
|
|
return $queries;
|
|
}
|
|
|
|
foreach ($queries as $query)
|
|
{
|
|
// executeQuery() must be used here because $query might return a result set, for instance REPAIR does
|
|
$this->connection->executeQuery($query);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
catch (Exception $e)
|
|
{
|
|
return $e->getMessage();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Alter table.
|
|
*
|
|
* @param string $table_name Table name.
|
|
* @param callable $callback Callback function to modify the table.
|
|
*
|
|
* @throws SchemaException
|
|
*/
|
|
protected function alter_table(Schema $schema, string $table_name, callable $callback): void
|
|
{
|
|
$table = $schema->getTable($table_name);
|
|
call_user_func($callback, $table);
|
|
}
|
|
|
|
/**
|
|
* Perform schema changes
|
|
*
|
|
* @param Schema $schema
|
|
* @param array $schema_changes
|
|
*/
|
|
protected function schema_perform_changes(Schema $schema, array $schema_changes): void
|
|
{
|
|
$mapping = [
|
|
'drop_tables' => [
|
|
'method' => 'schema_drop_table',
|
|
'use_key' => false,
|
|
],
|
|
'add_tables' => [
|
|
'method' => 'schema_create_table',
|
|
'use_key' => true,
|
|
],
|
|
'change_columns' => [
|
|
'method' => 'schema_column_change_add',
|
|
'use_key' => true,
|
|
'per_table' => true,
|
|
],
|
|
'add_columns' => [
|
|
'method' => 'schema_column_add',
|
|
'use_key' => true,
|
|
'per_table' => true,
|
|
],
|
|
'drop_columns' => [
|
|
'method' => 'schema_column_remove',
|
|
'use_key' => false,
|
|
'per_table' => true,
|
|
],
|
|
'drop_keys' => [
|
|
'method' => 'schema_index_drop',
|
|
'use_key' => false,
|
|
'per_table' => true,
|
|
],
|
|
'add_primary_keys' => [
|
|
'method' => 'schema_create_primary_key',
|
|
'use_key' => true,
|
|
],
|
|
'add_unique_index' => [
|
|
'method' => 'schema_create_unique_index',
|
|
'use_key' => true,
|
|
'per_table' => true,
|
|
],
|
|
'add_index' => [
|
|
'method' => 'schema_create_index',
|
|
'use_key' => true,
|
|
'per_table' => true,
|
|
],
|
|
];
|
|
|
|
foreach ($mapping as $action => $params)
|
|
{
|
|
if (array_key_exists($action, $schema_changes))
|
|
{
|
|
foreach ($schema_changes[$action] as $table_name => $table_data)
|
|
{
|
|
if (array_key_exists('per_table', $params) && $params['per_table'])
|
|
{
|
|
foreach ($table_data as $key => $data)
|
|
{
|
|
if ($params['use_key'] == false)
|
|
{
|
|
$this->{$params['method']}($schema, $table_name, $data, true);
|
|
}
|
|
else
|
|
{
|
|
$this->{$params['method']}($schema, $table_name, $key, $data, true);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ($params['use_key'] == false)
|
|
{
|
|
$this->{$params['method']}($schema, $table_data, true);
|
|
}
|
|
else
|
|
{
|
|
$this->{$params['method']}($schema, $table_name, $table_data, true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update the schema representation with a new table.
|
|
* Returns null in case of errors
|
|
*
|
|
* @param Schema $schema
|
|
* @param string $table_name
|
|
* @param array $table_data
|
|
* @param bool $safe_check
|
|
*
|
|
* @throws SchemaException
|
|
*/
|
|
protected function schema_create_table(Schema $schema, string $table_name, array $table_data, bool $safe_check = false): void
|
|
{
|
|
if ($safe_check && $this->sql_table_exists($table_name))
|
|
{
|
|
return;
|
|
}
|
|
|
|
$table = $schema->createTable($table_name);
|
|
$dbms_name = $this->get_schema_manager()->getDatabasePlatform()->getName();
|
|
|
|
foreach ($table_data['COLUMNS'] as $column_name => $column_data)
|
|
{
|
|
list($type, $options) = table_helper::convert_column_data(
|
|
$column_data,
|
|
$dbms_name
|
|
);
|
|
$table->addColumn($column_name, $type, $options);
|
|
}
|
|
|
|
if (array_key_exists('PRIMARY_KEY', $table_data))
|
|
{
|
|
$table_data['PRIMARY_KEY'] = (!is_array($table_data['PRIMARY_KEY']))
|
|
? [$table_data['PRIMARY_KEY']]
|
|
: $table_data['PRIMARY_KEY'];
|
|
|
|
$table->setPrimaryKey($table_data['PRIMARY_KEY']);
|
|
}
|
|
|
|
if (array_key_exists('KEYS', $table_data))
|
|
{
|
|
foreach ($table_data['KEYS'] as $key_name => $key_data)
|
|
{
|
|
$columns = (is_array($key_data[1])) ? $key_data[1] : [$key_data[1]];
|
|
|
|
// Supports key columns defined with there length
|
|
$columns = array_map(function (string $column)
|
|
{
|
|
if (strpos($column, ':') !== false)
|
|
{
|
|
$parts = explode(':', $column, 2);
|
|
return $parts[0];
|
|
}
|
|
return $column;
|
|
}, $columns);
|
|
|
|
if ($key_data[0] === 'UNIQUE')
|
|
{
|
|
$table->addUniqueIndex($columns, $key_name);
|
|
}
|
|
else
|
|
{
|
|
$table->addIndex($columns, $key_name);
|
|
}
|
|
}
|
|
}
|
|
|
|
switch ($dbms_name)
|
|
{
|
|
case 'mysql':
|
|
$table->addOption('collate', 'utf8_bin');
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param Schema $schema
|
|
* @param string $table_name
|
|
* @param bool $safe_check
|
|
*
|
|
* @throws SchemaException
|
|
*/
|
|
protected function schema_drop_table(Schema $schema, string $table_name, bool $safe_check = false): void
|
|
{
|
|
if ($safe_check && !$schema->hasTable($table_name))
|
|
{
|
|
return;
|
|
}
|
|
|
|
$schema->dropTable($table_name);
|
|
}
|
|
|
|
/**
|
|
* @param Schema $schema
|
|
* @param string $table_name
|
|
* @param string $column_name
|
|
* @param array $column_data
|
|
* @param bool $safe_check
|
|
*
|
|
* @throws SchemaException
|
|
*/
|
|
protected function schema_column_add(Schema $schema, string $table_name, string $column_name, array $column_data, bool $safe_check = false): void
|
|
{
|
|
$this->alter_table(
|
|
$schema,
|
|
$table_name,
|
|
function (Table $table) use ($column_name, $column_data, $safe_check)
|
|
{
|
|
if ($safe_check && $table->hasColumn($column_name))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
$dbms_name = $this->get_schema_manager()->getDatabasePlatform()->getName();
|
|
|
|
list($type, $options) = table_helper::convert_column_data($column_data, $dbms_name);
|
|
$table->addColumn($column_name, $type, $options);
|
|
return $table;
|
|
}
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param Schema $schema
|
|
* @param string $table_name
|
|
* @param string $column_name
|
|
* @param array $column_data
|
|
* @param bool $safe_check
|
|
*
|
|
* @throws SchemaException
|
|
*/
|
|
protected function schema_column_change(Schema $schema, string $table_name, string $column_name, array $column_data, bool $safe_check = false): void
|
|
{
|
|
$this->alter_table(
|
|
$schema,
|
|
$table_name,
|
|
function (Table $table) use ($column_name, $column_data, $safe_check): void
|
|
{
|
|
if ($safe_check && !$table->hasColumn($column_name))
|
|
{
|
|
return;
|
|
}
|
|
|
|
$dbms_name = $this->get_schema_manager()->getDatabasePlatform()->getName();
|
|
|
|
list($type, $options) = table_helper::convert_column_data($column_data, $dbms_name);
|
|
$options['type'] = Type::getType($type);
|
|
$table->changeColumn($column_name, $options);
|
|
}
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param Schema $schema
|
|
* @param string $table_name
|
|
* @param string $column_name
|
|
* @param array $column_data
|
|
* @param bool $safe_check
|
|
*
|
|
* @throws SchemaException
|
|
*/
|
|
protected function schema_column_change_add(Schema $schema, string $table_name, string $column_name, array $column_data, bool $safe_check = false): void
|
|
{
|
|
$table = $schema->getTable($table_name);
|
|
if ($table->hasColumn($column_name))
|
|
{
|
|
$this->schema_column_change($schema, $table_name, $column_name, $column_data, $safe_check);
|
|
}
|
|
else
|
|
{
|
|
$this->schema_column_add($schema, $table_name, $column_name, $column_data, $safe_check);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param Schema $schema
|
|
* @param string $table_name
|
|
* @param string $column_name
|
|
* @param bool $safe_check
|
|
*
|
|
* @throws SchemaException
|
|
*/
|
|
protected function schema_column_remove(Schema $schema, string $table_name, string $column_name, bool $safe_check = false): void
|
|
{
|
|
$this->alter_table(
|
|
$schema,
|
|
$table_name,
|
|
function (Table $table) use ($schema, $table_name, $column_name, $safe_check): void
|
|
{
|
|
if ($safe_check && !$table->hasColumn($column_name))
|
|
{
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* As our sequences does not have the same name as these generated
|
|
* by default by doctrine or the DBMS, we have to manage them ourselves.
|
|
*/
|
|
if ($table->getColumn($column_name)->getAutoincrement())
|
|
{
|
|
foreach ($schema->getSequences() as $sequence)
|
|
{
|
|
if ($this->isSequenceAutoIncrementsFor($sequence, $table))
|
|
{
|
|
$schema->dropSequence($sequence->getName());
|
|
}
|
|
}
|
|
}
|
|
|
|
// Re-create / delete the indices using this column
|
|
foreach ($table->getIndexes() as $index)
|
|
{
|
|
$index_columns = array_map('strtolower', $index->getUnquotedColumns());
|
|
$key = array_search($column_name, $index_columns, true);
|
|
if ($key !== false)
|
|
{
|
|
unset($index_columns[$key]);
|
|
$this->recreate_index($table, $index, $index_columns);
|
|
}
|
|
}
|
|
|
|
$table->dropColumn($column_name);
|
|
}
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param $column
|
|
* @param Schema $schema
|
|
* @param string $table_name
|
|
* @param string $index_name
|
|
* @param bool $safe_check
|
|
*
|
|
* @throws SchemaException
|
|
*/
|
|
protected function schema_create_index($column, Schema $schema, string $table_name, string $index_name, bool $safe_check = false): void
|
|
{
|
|
$columns = (is_array($column)) ? $column : [$column];
|
|
$table = $schema->getTable($table_name);
|
|
|
|
if ($safe_check && $table->hasIndex($index_name))
|
|
{
|
|
return;
|
|
}
|
|
|
|
$table->addIndex($columns, $index_name);
|
|
}
|
|
|
|
/**
|
|
* @param $column
|
|
* @param Schema $schema
|
|
* @param string $table_name
|
|
* @param string $index_name
|
|
* @param bool $safe_check
|
|
*
|
|
* @throws SchemaException
|
|
*/
|
|
protected function schema_create_unique_index($column, Schema $schema, string $table_name, string $index_name, bool $safe_check = false): void
|
|
{
|
|
$columns = (is_array($column)) ? $column : [$column];
|
|
$table = $schema->getTable($table_name);
|
|
|
|
if ($safe_check && $table->hasIndex($index_name))
|
|
{
|
|
return;
|
|
}
|
|
|
|
$table->addUniqueIndex($columns, $index_name);
|
|
}
|
|
|
|
/**
|
|
* @param Schema $schema
|
|
* @param string $table_name
|
|
* @param string $index_name
|
|
* @param bool $safe_check
|
|
*
|
|
* @throws SchemaException
|
|
*/
|
|
protected function schema_index_drop(Schema $schema, string $table_name, string $index_name, bool $safe_check = false): void
|
|
{
|
|
$table = $schema->getTable($table_name);
|
|
|
|
if ($safe_check && !$table->hasIndex($index_name))
|
|
{
|
|
return;
|
|
}
|
|
|
|
$table->dropIndex($index_name);
|
|
}
|
|
|
|
/**
|
|
* @param $column
|
|
* @param Schema $schema
|
|
* @param string $table_name
|
|
* @param bool $safe_check
|
|
*
|
|
* @throws SchemaException
|
|
*/
|
|
protected function schema_create_primary_key(Schema $schema, $column, string $table_name, bool $safe_check = false): void
|
|
{
|
|
$columns = (is_array($column)) ? $column : [$column];
|
|
$table = $schema->getTable($table_name);
|
|
$table->dropPrimaryKey();
|
|
$table->setPrimaryKey($columns);
|
|
}
|
|
|
|
/**
|
|
* Recreate an index of a table
|
|
*
|
|
* @param Table $table
|
|
* @param Index $index
|
|
* @param array Columns to use in the new (recreated) index
|
|
*
|
|
* @throws SchemaException
|
|
*/
|
|
protected function recreate_index(Table $table, Index $index, array $new_columns): void
|
|
{
|
|
if ($index->isPrimary())
|
|
{
|
|
$table->dropPrimaryKey();
|
|
}
|
|
else
|
|
{
|
|
$table->dropIndex($index->getName());
|
|
}
|
|
|
|
if (count($new_columns) > 0)
|
|
{
|
|
if ($index->isPrimary())
|
|
{
|
|
$table->setPrimaryKey(
|
|
$new_columns,
|
|
$index->getName(),
|
|
);
|
|
}
|
|
else if ($index->isUnique())
|
|
{
|
|
$table->addUniqueIndex(
|
|
$new_columns,
|
|
$index->getName(),
|
|
$index->getOptions(),
|
|
);
|
|
}
|
|
else
|
|
{
|
|
$table->addIndex(
|
|
$new_columns,
|
|
$index->getName(),
|
|
$index->getFlags(),
|
|
$index->getOptions(),
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param Sequence $sequence
|
|
* @param Table $table
|
|
*
|
|
* @return bool
|
|
* @throws SchemaException
|
|
*
|
|
* @see Sequence
|
|
*/
|
|
private function isSequenceAutoIncrementsFor(Sequence $sequence, Table $table): bool
|
|
{
|
|
$primaryKey = $table->getPrimaryKey();
|
|
|
|
if ($primaryKey === null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
$pkColumns = $primaryKey->getColumns();
|
|
|
|
if (count($pkColumns) !== 1)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
$column = $table->getColumn($pkColumns[0]);
|
|
|
|
if (! $column->getAutoincrement())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
$sequenceName = $sequence->getShortestName($table->getNamespaceName());
|
|
$tableName = $table->getShortestName($table->getNamespaceName());
|
|
$tableSequenceName = sprintf('%s_seq', $tableName);
|
|
|
|
return $tableSequenceName === $sequenceName;
|
|
}
|
|
}
|