mirror of
https://github.com/phpbb/phpbb.git
synced 2025-07-16 15:08:54 +00:00
Merge 868b5350f7
into 30ee379576
This commit is contained in:
commit
3f056bb795
3 changed files with 147 additions and 20 deletions
|
@ -435,6 +435,42 @@ class doctrine implements tools_interface
|
|||
return $prefix && str_starts_with($name, $prefix) ? substr($name, strlen($prefix)) : $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of the table index names and relevant data in format
|
||||
* [
|
||||
* [$index_name] = [
|
||||
* 'columns' => (array) $index_columns,
|
||||
* 'flags' => (array) $index_flags,
|
||||
* 'options' => (array) $index_options,
|
||||
* 'is_primary'=> (bool) $isPrimary,
|
||||
* 'is_unique' => (bool) $isUnique,
|
||||
* 'is_simple' => (bool) $isSimple,
|
||||
* ]
|
||||
*
|
||||
* @param string $table_name
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function sql_get_table_index_data(string $table_name): array
|
||||
{
|
||||
$schema = $this->get_schema();
|
||||
$table = $schema->getTable($table_name);
|
||||
$indexes = [];
|
||||
foreach ($table->getIndexes() as $index)
|
||||
{
|
||||
$indexes[$index->getName()] = [
|
||||
'columns' => array_map('strtolower', $index->getUnquotedColumns()),
|
||||
'flags' => $index->getFlags(),
|
||||
'options' => $index->getOptions(),
|
||||
'is_primary'=> $index->isPrimary(),
|
||||
'is_unique' => $index->isUnique(),
|
||||
'is_simple' => $index->isSimpleIndex(),
|
||||
];
|
||||
}
|
||||
|
||||
return $indexes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of indices for either unique and primary keys, or simple indices.
|
||||
*
|
||||
|
@ -686,24 +722,16 @@ class doctrine implements tools_interface
|
|||
$columns = (is_array($key_data[1])) ? $key_data[1] : [$key_data[1]];
|
||||
$key_name = !str_starts_with($key_name, $short_table_name) ? self::add_prefix($key_name, $short_table_name) : $key_name;
|
||||
|
||||
// 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);
|
||||
$options = [];
|
||||
$this->schema_get_index_key_data($columns, $options);
|
||||
|
||||
if ($key_data[0] === 'UNIQUE')
|
||||
{
|
||||
$table->addUniqueIndex($columns, $key_name);
|
||||
$table->addUniqueIndex($columns, $key_name, $options);
|
||||
}
|
||||
else
|
||||
{
|
||||
$table->addIndex($columns, $key_name);
|
||||
$table->addIndex($columns, $key_name, [], $options);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -900,7 +928,10 @@ class doctrine implements tools_interface
|
|||
return;
|
||||
}
|
||||
|
||||
$table->addIndex($columns, $index_name);
|
||||
$options = [];
|
||||
$this->schema_get_index_key_data($columns, $options);
|
||||
|
||||
$table->addIndex($columns, $index_name, [], $options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -956,7 +987,10 @@ class doctrine implements tools_interface
|
|||
return;
|
||||
}
|
||||
|
||||
$table->addUniqueIndex($columns, $index_name);
|
||||
$options = [];
|
||||
$this->schema_get_index_key_data($columns, $options);
|
||||
|
||||
$table->addUniqueIndex($columns, $index_name, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1005,6 +1039,30 @@ class doctrine implements tools_interface
|
|||
$table->setPrimaryKey($columns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if index data contains key length
|
||||
* and put it into $options['lengths'] array.
|
||||
* Handles key length in formats of 'keyname:123' or 'keyname(123)'
|
||||
*
|
||||
* @param array $columns
|
||||
* @param array $options
|
||||
*/
|
||||
protected function schema_get_index_key_data(array &$columns, array &$options): void
|
||||
{
|
||||
if (!empty($columns))
|
||||
{
|
||||
$columns = array_map(function (string $column) use (&$options)
|
||||
{
|
||||
if (preg_match('/^([a-zA-Z0-9_]+)(?:(?:\:|\()([0-9]{1,3})\)?)?$/', $column, $parts))
|
||||
{
|
||||
$options['lengths'][] = $parts[2] ?? null;
|
||||
return $parts[1];
|
||||
}
|
||||
return $column;
|
||||
}, $columns);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recreate an index of a table
|
||||
*
|
||||
|
|
|
@ -22,12 +22,22 @@ class phpbb_dbal_migration_schema extends \phpbb\db\migration\migration
|
|||
),
|
||||
),
|
||||
'add_tables' => array(
|
||||
$this->table_prefix . 'foobar' => array(
|
||||
'COLUMNS' => array(
|
||||
'module_id' => array('UINT:3', NULL, 'auto_increment'),
|
||||
),
|
||||
$this->table_prefix . 'foobar' => [
|
||||
'COLUMNS' => [
|
||||
'module_id' => ['UINT:3', NULL, 'auto_increment'],
|
||||
'user_id' => ['ULINT', 0],
|
||||
'endpoint' => ['VCHAR:220', ''],
|
||||
'expiration_time' => ['TIMESTAMP', 0],
|
||||
'p256dh' => ['VCHAR:200', ''],
|
||||
'auth' => ['VCHAR:100', ''],
|
||||
],
|
||||
'PRIMARY_KEY' => 'module_id',
|
||||
),
|
||||
'KEYS' => [
|
||||
'i_simple' => ['INDEX', ['user_id', 'endpoint:191']],
|
||||
'i_uniq' => ['UNIQUE', ['expiration_time', 'p256dh(100)']],
|
||||
'i_auth' => ['INDEX', 'auth'],
|
||||
],
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -57,11 +57,12 @@ class phpbb_dbal_migrator_test extends phpbb_database_test_case
|
|||
|
||||
parent::setUp();
|
||||
|
||||
$this->table_prefix = $table_prefix;
|
||||
$this->db = $this->new_dbal();
|
||||
$this->doctrine_db = $this->new_doctrine_dbal();
|
||||
$factory = new \phpbb\db\tools\factory();
|
||||
$this->db_tools = $factory->get($this->doctrine_db);
|
||||
$this->db_tools->set_table_prefix($table_prefix);
|
||||
$this->db_tools->set_table_prefix($this->table_prefix);
|
||||
|
||||
$this->config = new \phpbb\config\db($this->db, new phpbb_mock_cache, 'phpbb_config');
|
||||
|
||||
|
@ -412,6 +413,64 @@ class phpbb_dbal_migrator_test extends phpbb_database_test_case
|
|||
$this->assertTrue($this->db_tools->sql_column_exists('phpbb_config', 'test_column1'));
|
||||
$this->assertTrue($this->db_tools->sql_table_exists('phpbb_foobar'));
|
||||
|
||||
$short_table_name = \phpbb\db\doctrine\table_helper::generate_shortname('foobar');
|
||||
$index_data_row = $this->db_tools->sql_get_table_index_data('phpbb_foobar');
|
||||
$this->assertEquals(4, count($index_data_row));
|
||||
$this->assertTrue(isset($index_data_row[$short_table_name . '_i_simple']));
|
||||
$this->assertTrue(isset($index_data_row[$short_table_name . '_i_uniq']));
|
||||
$this->assertTrue(isset($index_data_row[$short_table_name . '_i_auth']));
|
||||
|
||||
$is_mysql = $this->db->get_sql_layer() === 'mysqli'; // Key 'lengths' option only applies to MySQL indexes
|
||||
|
||||
// MSSQL primary index key has 'clustered' flag, 'nonclustered' otherwise
|
||||
// See https://learn.microsoft.com/en-us/sql/relational-databases/indexes/clustered-and-nonclustered-indexes-described?view=sql-server-ver17#indexes-and-constraints
|
||||
$is_mssql = in_array($this->db->get_sql_layer(), ['mssqlnative', 'mssql_odbc']);
|
||||
|
||||
foreach ($index_data_row as $index_name => $index_data)
|
||||
{
|
||||
switch ($index_name)
|
||||
{
|
||||
case $short_table_name . '_i_simple':
|
||||
$this->assertEquals(['user_id', 'endpoint'], $index_data['columns']);
|
||||
$this->assertEquals($is_mssql ? ['nonclustered'] : [], $index_data['flags']);
|
||||
$this->assertFalse($index_data['is_primary']);
|
||||
$this->assertFalse($index_data['is_unique']);
|
||||
$this->assertTrue($index_data['is_simple']);
|
||||
$this->assertEquals(2, count($index_data['options']['lengths']));
|
||||
$this->assertEmpty($index_data['options']['lengths'][0]);
|
||||
$this->assertEquals($is_mysql ? 191 : null, $index_data['options']['lengths'][1]);
|
||||
break;
|
||||
case $short_table_name . '_i_uniq':
|
||||
$this->assertEquals(['expiration_time', 'p256dh'], $index_data['columns']);
|
||||
$this->assertEquals($is_mssql ? ['nonclustered'] : [], $index_data['flags']);
|
||||
$this->assertFalse($index_data['is_primary']);
|
||||
$this->assertTrue($index_data['is_unique']);
|
||||
$this->assertFalse($index_data['is_simple']);
|
||||
$this->assertEquals(2, count($index_data['options']['lengths']));
|
||||
$this->assertEmpty($index_data['options']['lengths'][0]);
|
||||
$this->assertEquals($is_mysql ? 100 : null, $index_data['options']['lengths'][1]);
|
||||
break;
|
||||
case $short_table_name . '_i_auth':
|
||||
$this->assertEquals(['auth'], $index_data['columns']);
|
||||
$this->assertEquals($is_mssql ? ['nonclustered'] : [], $index_data['flags']);
|
||||
$this->assertFalse($index_data['is_primary']);
|
||||
$this->assertFalse($index_data['is_unique']);
|
||||
$this->assertTrue($index_data['is_simple']);
|
||||
$this->assertEquals(1, count($index_data['options']['lengths']));
|
||||
$this->assertEmpty($index_data['options']['lengths'][0]);
|
||||
break;
|
||||
default: // Primary key
|
||||
$this->assertEquals(['module_id'], $index_data['columns']);
|
||||
$this->assertEquals($is_mssql ? ['clustered'] : [], $index_data['flags']);
|
||||
$this->assertTrue($index_data['is_primary']);
|
||||
$this->assertTrue($index_data['is_unique']);
|
||||
$this->assertFalse($index_data['is_simple']);
|
||||
$this->assertEquals(1, count($index_data['options']['lengths']));
|
||||
$this->assertEmpty($index_data['options']['lengths'][0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while ($this->migrator->migration_state('phpbb_dbal_migration_schema'))
|
||||
{
|
||||
$this->migrator->revert('phpbb_dbal_migration_schema');
|
||||
|
|
Loading…
Add table
Reference in a new issue