Compare commits

...

5 commits

Author SHA1 Message Date
rxu
db897c7d49
Merge b4b787198a into d3bb7e5bd3 2025-06-11 18:38:02 +00:00
rxu
b4b787198a
[ticket/17524] Try not to hit MSSQL index key length limitations
900 bytes for a clustered index. 1,700 bytes for a nonclustered index.
For SQL Server 2014 (12.x) and earlier, all versions supported 900 bytes
for all index types.

PHPBB-17524
2025-06-12 01:37:40 +07:00
Marc Alexander
d3bb7e5bd3
Merge pull request #6823 from CHItA/ticket/17516
[ticket/17516] Remove dependency on topological sort library
2025-06-11 17:25:52 +02:00
rxu
c7e94d4632
[ticket/17524] Add test assertions
PHPBB-17524
2025-06-11 21:04:56 +07:00
Máté Bartus
b9df5bbbf0 [ticket/17516] Remove dependency on topological sort library
PHPBB-17516
2025-06-01 12:06:58 +01:00
5 changed files with 59 additions and 70 deletions

View file

@ -33,7 +33,6 @@
"ext-sodium": "*", "ext-sodium": "*",
"bantu/ini-get-wrapper": "~1.0", "bantu/ini-get-wrapper": "~1.0",
"carlos-mg89/oauth": "^0.8.15", "carlos-mg89/oauth": "^0.8.15",
"chita/topological_sort": "^3.0",
"composer/composer": "^2.0", "composer/composer": "^2.0",
"composer/installers": "^1.9", "composer/installers": "^1.9",
"composer/package-versions-deprecated": "^1.11", "composer/package-versions-deprecated": "^1.11",

43
phpBB/composer.lock generated
View file

@ -171,49 +171,6 @@
}, },
"time": "2025-02-08T12:14:07+00:00" "time": "2025-02-08T12:14:07+00:00"
}, },
{
"name": "chita/topological_sort",
"version": "v3.0.1",
"source": {
"type": "git",
"url": "https://github.com/CHItA/TopologicalSort.git",
"reference": "9e0401c712d0c7cf012f264cc105669844d2479e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/CHItA/TopologicalSort/zipball/9e0401c712d0c7cf012f264cc105669844d2479e",
"reference": "9e0401c712d0c7cf012f264cc105669844d2479e",
"shasum": ""
},
"require": {
"php": ">=7.1.0"
},
"require-dev": {
"phpunit/phpunit": "^7.0"
},
"type": "library",
"autoload": {
"psr-4": {
"CHItA\\TopologicalSort\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Máté Bartus",
"email": "mate.bartus@gmail.com"
}
],
"description": "Topological sort function",
"support": {
"issues": "https://github.com/CHItA/TopologicalSort/issues",
"source": "https://github.com/CHItA/TopologicalSort/tree/v3.0.1"
},
"time": "2021-01-04T21:31:59+00:00"
},
{ {
"name": "composer/ca-bundle", "name": "composer/ca-bundle",
"version": "1.5.6", "version": "1.5.6",

View file

@ -14,21 +14,17 @@
namespace phpbb\db\migration; namespace phpbb\db\migration;
use Closure; use Closure;
use LogicException;
use phpbb\config\config; use phpbb\config\config;
use phpbb\db\driver\driver_interface; use phpbb\db\driver\driver_interface;
use phpbb\db\migrator; use phpbb\db\migrator;
use phpbb\db\tools\tools_interface; use phpbb\db\tools\tools_interface;
use UnexpectedValueException; use UnexpectedValueException;
use CHItA\TopologicalSort\TopologicalSort;
/** /**
* The schema generator generates the schema based on the existing migrations * The schema generator generates the schema based on the existing migrations
*/ */
class schema_generator class schema_generator
{ {
use TopologicalSort;
/** @var config */ /** @var config */
protected $config; protected $config;
@ -103,24 +99,56 @@ class schema_generator
return $this->tables; return $this->tables;
} }
$migrations = $this->class_names; $dependency_counts = [];
$filter = function($class_name) { $dependencies = [];
return !migrator::is_migration($class_name); $applicable_migrations = [];
}; $migration_count = 0;
foreach ($this->class_names as $class_name)
$edges = function($class_name) {
return $class_name::depends_on();
};
$apply_for_each = function($class_name) {
$this->apply_migration_to_schema($class_name);
};
try
{ {
$this->topologicalSort($migrations, $edges, true, $apply_for_each, $filter); if (!migrator::is_migration($class_name))
{
continue;
} }
catch (LogicException $e)
$migration_count++;
$migration_dependencies = $class_name::depends_on();
if (empty($migration_dependencies))
{
$applicable_migrations[] = $class_name;
continue;
}
$dependency_counts[$class_name] = count($migration_dependencies);
foreach ($migration_dependencies as $migration_dependency)
{
$dependencies[$migration_dependency][] = $class_name;
}
}
$applied_migrations = 0;
while (!empty($applicable_migrations))
{
$migration = array_pop($applicable_migrations);
$this->apply_migration_to_schema($migration);
++$applied_migrations;
if (!array_key_exists($migration, $dependencies))
{
continue;
}
$dependents = $dependencies[$migration];
foreach ($dependents as $dependent)
{
$dependency_counts[$dependent]--;
if ($dependency_counts[$dependent] === 0)
{
$applicable_migrations[] = $dependent;
}
}
}
if ($migration_count !== $applied_migrations)
{ {
throw new UnexpectedValueException( throw new UnexpectedValueException(
"Migrations either have circular dependencies or unsatisfiable dependencies." "Migrations either have circular dependencies or unsatisfiable dependencies."

View file

@ -26,9 +26,9 @@ class phpbb_dbal_migration_schema extends \phpbb\db\migration\migration
'COLUMNS' => [ 'COLUMNS' => [
'module_id' => ['UINT:3', NULL, 'auto_increment'], 'module_id' => ['UINT:3', NULL, 'auto_increment'],
'user_id' => ['ULINT', 0], 'user_id' => ['ULINT', 0],
'endpoint' => ['TEXT', ''], 'endpoint' => ['VCHAR:220', ''],
'expiration_time' => ['TIMESTAMP', 0], 'expiration_time' => ['TIMESTAMP', 0],
'p256dh' => ['VCHAR', ''], 'p256dh' => ['VCHAR:200', ''],
'auth' => ['VCHAR:100', ''], 'auth' => ['VCHAR:100', ''],
], ],
'PRIMARY_KEY' => 'module_id', 'PRIMARY_KEY' => 'module_id',

View file

@ -409,7 +409,12 @@ class phpbb_dbal_migrator_test extends phpbb_database_test_case
$this->assertTrue($this->db_tools->sql_table_exists('phpbb_foobar')); $this->assertTrue($this->db_tools->sql_table_exists('phpbb_foobar'));
$index_data_row = $this->db_tools->sql_get_table_index_data('phpbb_foobar'); $index_data_row = $this->db_tools->sql_get_table_index_data('phpbb_foobar');
$is_mysql = $this->db->get_sql_layer() === 'mysqli'; // Index length only applies to MySQL indexes $this->assertEquals(4, count($index_data_row));
$this->assertTrue(isset($index_data_row['i_simple']));
$this->assertTrue(isset($index_data_row['i_uniq']));
$this->assertTrue(isset($index_data_row['i_auth']));
$is_mysql = $this->db->get_sql_layer() === 'mysqli'; // Key 'lengths' option only applies to MySQL indexes
$is_mssql = in_array($this->db->get_sql_layer(), ['mssqlnative', 'mssql_odbc']); // MSSQL primary index key has 'clustered' flag $is_mssql = in_array($this->db->get_sql_layer(), ['mssqlnative', 'mssql_odbc']); // MSSQL primary index key has 'clustered' flag
foreach ($index_data_row as $index_name => $index_data) foreach ($index_data_row as $index_name => $index_data)
{ {
@ -417,7 +422,7 @@ class phpbb_dbal_migrator_test extends phpbb_database_test_case
{ {
case 'i_simple': case 'i_simple':
$this->assertEquals(['user_id', 'endpoint'], $index_data['columns']); $this->assertEquals(['user_id', 'endpoint'], $index_data['columns']);
$this->assertEmpty($index_data['flags']); $this->assertEquals($is_mssql ? ['clustered'] : [], $index_data['flags']);
$this->assertFalse($index_data['is_primary']); $this->assertFalse($index_data['is_primary']);
$this->assertFalse($index_data['is_unique']); $this->assertFalse($index_data['is_unique']);
$this->assertTrue($index_data['is_simple']); $this->assertTrue($index_data['is_simple']);
@ -427,7 +432,7 @@ class phpbb_dbal_migrator_test extends phpbb_database_test_case
break; break;
case 'i_uniq': case 'i_uniq':
$this->assertEquals(['expiration_time', 'p256dh'], $index_data['columns']); $this->assertEquals(['expiration_time', 'p256dh'], $index_data['columns']);
$this->assertEmpty($index_data['flags']); $this->assertEquals($is_mssql ? ['clustered'] : [], $index_data['flags']);
$this->assertFalse($index_data['is_primary']); $this->assertFalse($index_data['is_primary']);
$this->assertTrue($index_data['is_unique']); $this->assertTrue($index_data['is_unique']);
$this->assertFalse($index_data['is_simple']); $this->assertFalse($index_data['is_simple']);
@ -437,7 +442,7 @@ class phpbb_dbal_migrator_test extends phpbb_database_test_case
break; break;
case 'i_auth': case 'i_auth':
$this->assertEquals(['auth'], $index_data['columns']); $this->assertEquals(['auth'], $index_data['columns']);
$this->assertEmpty($index_data['flags']); $this->assertEquals($is_mssql ? ['clustered'] : [], $index_data['flags']);
$this->assertFalse($index_data['is_primary']); $this->assertFalse($index_data['is_primary']);
$this->assertFalse($index_data['is_unique']); $this->assertFalse($index_data['is_unique']);
$this->assertTrue($index_data['is_simple']); $this->assertTrue($index_data['is_simple']);