From b11d27b46ee3d89c1abf17f63f2cd0179f94ab8f Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Tue, 14 Apr 2026 12:32:54 -0300 Subject: [PATCH 1/2] test(migration): oracle naming constraints for Version1000 migration Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- .../Version1000Date20260309120000Test.php | 159 ++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 tests/php/Unit/Migration/Version1000Date20260309120000Test.php diff --git a/tests/php/Unit/Migration/Version1000Date20260309120000Test.php b/tests/php/Unit/Migration/Version1000Date20260309120000Test.php new file mode 100644 index 0000000..982a3ca --- /dev/null +++ b/tests/php/Unit/Migration/Version1000Date20260309120000Test.php @@ -0,0 +1,159 @@ +schema = new Schema(); + } + + private function buildSchemaWrapper(Schema $schema, string $prefix): ISchemaWrapper { + return new class($schema, $prefix) implements ISchemaWrapper { + public function __construct( + private Schema $schema, + private string $prefix, + ) { + } + + public function hasTable($tableName): bool { + return $this->schema->hasTable($this->prefix . $tableName); + } + + public function createTable($tableName): Table { + return $this->schema->createTable($this->prefix . $tableName); + } + + public function getTable($tableName): Table { + return $this->schema->getTable($this->prefix . $tableName); + } + + public function dropTable($tableName): Schema { + return $this->schema->dropTable($this->prefix . $tableName); + } + + public function getTables(): array { + return $this->schema->getTables(); + } + + public function getTableNames(): array { + return $this->schema->getTableNames(); + } + + public function getTableNamesWithoutPrefix(): array { + return array_map( + fn (string $n) => substr($n, strlen($this->prefix)), + $this->schema->getTableNames(), + ); + } + + public function getDatabasePlatform(): AbstractPlatform { + throw new \RuntimeException('not implemented in test'); + } + + public function dropAutoincrementColumn(string $table, string $column): void { + throw new \RuntimeException('not implemented in test'); + } + }; + } + + public function testAllNamesPassOracleConstraints(): void { + $wrapper = $this->buildSchemaWrapper($this->schema, self::PREFIX); + $output = $this->createMock(IOutput::class); + $migration = new Version1000Date20260309120000(); + + $migration->changeSchema($output, fn () => $wrapper, ['tablePrefix' => self::PREFIX]); + + $prefixLen = strlen(self::PREFIX); + + foreach ($this->schema->getTables() as $table) { + $tableNameWithoutPrefix = substr($table->getName(), $prefixLen); + + $this->assertLessThanOrEqual( + self::ORACLE_MAX_TABLE, + strlen($tableNameWithoutPrefix), + "Table '{$table->getName()}' name without prefix exceeds Oracle max of " . self::ORACLE_MAX_TABLE . ' chars', + ); + + foreach ($table->getColumns() as $column) { + $this->assertLessThanOrEqual( + self::ORACLE_MAX_NAME, + strlen($column->getName()), + "Column '{$column->getName()}' on '{$table->getName()}' exceeds Oracle max of " . self::ORACLE_MAX_NAME . ' chars', + ); + } + + foreach ($table->getIndexes() as $index) { + $this->assertLessThanOrEqual( + self::ORACLE_MAX_NAME, + strlen($index->getName()), + "Index '{$index->getName()}' on '{$table->getName()}' exceeds Oracle max of " . self::ORACLE_MAX_NAME . ' chars', + ); + } + + foreach ($table->getForeignKeys() as $fk) { + $this->assertLessThanOrEqual( + self::ORACLE_MAX_NAME, + strlen($fk->getName()), + "FK '{$fk->getName()}' on '{$table->getName()}' exceeds Oracle max of " . self::ORACLE_MAX_NAME . ' chars', + ); + } + + $primaryKey = $table->getPrimaryKey(); + if ($primaryKey !== null) { + $pkName = strtolower($primaryKey->getName()); + if ($pkName === 'primary') { + // Default PK name: table name without prefix must be strictly < 23 chars + $this->assertLessThan( + self::ORACLE_MAX_TABLE_FOR_DEFAULT_PK, + strlen($tableNameWithoutPrefix), + "Table '{$tableNameWithoutPrefix}' uses default primary key name but its length " + . strlen($tableNameWithoutPrefix) + . ' >= ' . self::ORACLE_MAX_TABLE_FOR_DEFAULT_PK + . '; set an explicit primary key name <= 30 chars', + ); + } else { + $this->assertLessThanOrEqual( + self::ORACLE_MAX_NAME, + strlen($pkName), + "Primary key name '$pkName' on '{$table->getName()}' exceeds Oracle max of " . self::ORACLE_MAX_NAME . ' chars', + ); + } + } + } + } +} From 71d2eefdbceed188be166a1220ab62f9bf761bff Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Tue, 14 Apr 2026 12:33:03 -0300 Subject: [PATCH 2/2] fix(migration): set explicit primary key and index names for Oracle compatibility - setPrimaryKey with explicit name 'pf_definitions_pk' (16 chars) for profile_fields_definitions table (table name without prefix is 26 chars, requires explicit PK name when >= 23 chars per NC Oracle constraint) - setPrimaryKey with explicit name 'pf_values_pk' for profile_fields_values - rename unique index 'profile_fields_val_field_user_uk' (32 chars) to 'pf_val_def_user_uk' (18 chars); Oracle max identifier length is 30 Fixes #65 Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- lib/Migration/Version1000Date20260309120000.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/Migration/Version1000Date20260309120000.php b/lib/Migration/Version1000Date20260309120000.php index cb32ee9..b0c6b04 100644 --- a/lib/Migration/Version1000Date20260309120000.php +++ b/lib/Migration/Version1000Date20260309120000.php @@ -64,7 +64,7 @@ public function changeSchema(IOutput $output, Closure $schemaClosure, array $opt $table->addColumn('created_at', Types::DATETIME, []); $table->addColumn('updated_at', Types::DATETIME, []); - $table->setPrimaryKey(['id']); + $table->setPrimaryKey(['id'], 'pf_definitions_pk'); $table->addUniqueIndex(['field_key'], 'profile_fields_def_key_uk'); $table->addIndex(['active', 'sort_order'], 'pf_def_active_sort_idx'); } @@ -91,8 +91,8 @@ public function changeSchema(IOutput $output, Closure $schemaClosure, array $opt ]); $table->addColumn('updated_at', Types::DATETIME, []); - $table->setPrimaryKey(['id']); - $table->addUniqueIndex(['field_definition_id', 'user_uid'], 'profile_fields_val_field_user_uk'); + $table->setPrimaryKey(['id'], 'pf_values_pk'); + $table->addUniqueIndex(['field_definition_id', 'user_uid'], 'pf_val_def_user_uk'); $table->addIndex(['user_uid'], 'profile_fields_val_user_idx'); $table->addIndex(['field_definition_id'], 'profile_fields_val_field_idx'); $table->addForeignKeyConstraint(