From 79c3b6c8a3ab6fcefcb07c74241ce049d976e874 Mon Sep 17 00:00:00 2001 From: Josh McRae Date: Thu, 30 Oct 2025 14:21:17 +1000 Subject: [PATCH 1/3] Use original column name applying modify to change --- src/Operation/TableOperation.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Operation/TableOperation.php b/src/Operation/TableOperation.php index 71734a0..ba38833 100644 --- a/src/Operation/TableOperation.php +++ b/src/Operation/TableOperation.php @@ -310,7 +310,7 @@ public function apply(ReducibleOperationInterface $operation): ?ReducibleOperati } $columns[] = new ColumnOperation( - $columnOperation->getName(), + $originalName, $originalOperation, $options ); From 81614b1205c4e25c8fdf94b260f217a408222b3e Mon Sep 17 00:00:00 2001 From: Josh McRae Date: Thu, 30 Oct 2025 14:35:09 +1000 Subject: [PATCH 2/3] Added test and fixed change to change --- src/Operation/TableOperation.php | 2 +- tests/Operation/TableOperationTest.php | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/Operation/TableOperation.php b/src/Operation/TableOperation.php index ba38833..6d1ad43 100644 --- a/src/Operation/TableOperation.php +++ b/src/Operation/TableOperation.php @@ -316,7 +316,7 @@ public function apply(ReducibleOperationInterface $operation): ?ReducibleOperati ); break; case ColumnOperation::CHANGE: - $columnName = $columnOperation->getName(); + $columnName = $originalName; if ($originalOperation == ColumnOperation::ADD) { $columnName = $columnOperation->getAfterName(); diff --git a/tests/Operation/TableOperationTest.php b/tests/Operation/TableOperationTest.php index c6c6fca..07b9d1a 100644 --- a/tests/Operation/TableOperationTest.php +++ b/tests/Operation/TableOperationTest.php @@ -119,6 +119,29 @@ public function testApplyAlterToAlterWithColumnChange() $this->assertEquals(['unique' => true], $operation->getIndexOperations()[0]->getOptions()); } + public function testApplyAlterToAlterWithModifyColumnChange() + { + $base = new TableOperation('users', TableOperation::ALTER, [ + new ColumnOperation('id', ColumnOperation::DROP, []), + new ColumnOperation('email', ColumnOperation::CHANGE, ['new_name' => 'username', 'type' => 'string', 'length' => 255, 'first' => true]), + ], []); + + $operation = $base->apply(new TableOperation('users', TableOperation::ALTER, [ + new ColumnOperation('username', ColumnOperation::MODIFY, ['type' => 'char', 'length' => 64]) + ], [])); + + $this->assertEquals('users', $operation->getName()); + $this->assertEquals(TableOperation::ALTER, $operation->getOperation()); + $this->assertCount(2, $operation->getColumnOperations()); + + $this->assertEquals('id', $operation->getColumnOperations()[0]->getName()); + $this->assertEquals(ColumnOperation::DROP, $operation->getColumnOperations()[0]->getOperation()); + + $this->assertEquals('email', $operation->getColumnOperations()[1]->getName()); + $this->assertEquals(ColumnOperation::CHANGE, $operation->getColumnOperations()[1]->getOperation()); + $this->assertEquals(['type' => 'char', 'length' => 64, 'new_name' => 'username'], $operation->getColumnOperations()[1]->getOptions()); + } + public function testApplyDropToAlter() { $base = new TableOperation('users', TableOperation::ALTER, [ From fe3ab715da66dc460f896c31b9ad7a1f24bd8eaf Mon Sep 17 00:00:00 2001 From: Josh McRae Date: Tue, 4 Nov 2025 12:40:26 +1000 Subject: [PATCH 3/3] Added tests and fixed column drop -> add outcome --- src/Operation/TableOperation.php | 12 +- tests/Operation/TableOperationTest.php | 171 +++++++++++++++++++------ 2 files changed, 146 insertions(+), 37 deletions(-) diff --git a/src/Operation/TableOperation.php b/src/Operation/TableOperation.php index 6d1ad43..4dc4391 100644 --- a/src/Operation/TableOperation.php +++ b/src/Operation/TableOperation.php @@ -287,6 +287,14 @@ public function apply(ReducibleOperationInterface $operation): ?ReducibleOperati // Apply new column operation switch ($columnOperation->getOperation()) { case ColumnOperation::ADD: + if ($originalOperation == ColumnOperation::DROP) { + $columnOperation = new ColumnOperation( + $columnOperation->getName(), + ColumnOperation::MODIFY, + $columnOperation->getOptions() + ); + } + $columns[] = $columnOperation; break; case ColumnOperation::DROP: @@ -317,9 +325,11 @@ public function apply(ReducibleOperationInterface $operation): ?ReducibleOperati break; case ColumnOperation::CHANGE: $columnName = $originalName; + $options = $columnOperation->getOptions(); if ($originalOperation == ColumnOperation::ADD) { $columnName = $columnOperation->getAfterName(); + unset($options['new_name']); } if ($originalOperation == ColumnOperation::MODIFY) { @@ -329,7 +339,7 @@ public function apply(ReducibleOperationInterface $operation): ?ReducibleOperati $columns[] = new ColumnOperation( $columnName, $originalOperation, - $columnOperation->getOptions() + $options ); break; } diff --git a/tests/Operation/TableOperationTest.php b/tests/Operation/TableOperationTest.php index 07b9d1a..cf11f0a 100644 --- a/tests/Operation/TableOperationTest.php +++ b/tests/Operation/TableOperationTest.php @@ -86,74 +86,173 @@ public function testApplyAlterToAlter() $this->assertEquals(['unique' => true], $operation->getIndexOperations()[0]->getOptions()); } - public function testApplyAlterToAlterWithColumnChange() + public function testApplyDropToAlter() { $base = new TableOperation('users', TableOperation::ALTER, [ new ColumnOperation('id', ColumnOperation::DROP, []), new ColumnOperation('email', ColumnOperation::ADD, ['type' => 'string', 'length' => 255, 'first' => true]), - new ColumnOperation('username', ColumnOperation::ADD, ['type' => 'string', 'length' => 255]) - ], [ - new IndexOperation('email_username', ColumnOperation::ADD, ['email', 'username'], ['unique' => true]) - ]); + new ColumnOperation('username', ColumnOperation::MODIFY, ['type' => 'string', 'length' => 255]) + ], []); + + $drop = new TableOperation('users', TableOperation::DROP, [], []); + + $operation = $base->apply($drop); + $this->assertEquals($drop, $operation); + } + + public function testApplyColumnDropToColumnAdd() + { + $base = new TableOperation('users', TableOperation::ALTER, [ + new ColumnOperation('email', ColumnOperation::ADD, ['type' => 'string', 'length' => 255, 'first' => true]), + ], []); $operation = $base->apply(new TableOperation('users', TableOperation::ALTER, [ new ColumnOperation('email', ColumnOperation::DROP, []), - new ColumnOperation('username', ColumnOperation::CHANGE, ['type' => 'string', 'length' => 255, 'new_name' => 'email']) ], [])); - $this->assertEquals('users', $operation->getName()); - $this->assertEquals(TableOperation::ALTER, $operation->getOperation()); - $this->assertCount(2, $operation->getColumnOperations()); - $this->assertCount(1, $operation->getIndexOperations()); + $this->assertCount(0, $operation->getColumnOperations()); + } - $this->assertEquals('id', $operation->getColumnOperations()[0]->getName()); + public function testApplyColumnModifyToColumnAdd() + { + $base = new TableOperation('users', TableOperation::ALTER, [ + new ColumnOperation('email', ColumnOperation::ADD, ['type' => 'string', 'length' => 255, 'first' => true]), + ], []); + + $operation = $base->apply(new TableOperation('users', TableOperation::ALTER, [ + new ColumnOperation('email', ColumnOperation::MODIFY, ['type' => 'char', 'length' => 64]), + ], [])); + + $this->assertCount(1, $operation->getColumnOperations()); + $this->assertEquals('email', $operation->getColumnOperations()[0]->getName()); + $this->assertEquals(ColumnOperation::ADD, $operation->getColumnOperations()[0]->getOperation()); + $this->assertEquals(['type' => 'char', 'length' => 64], $operation->getColumnOperations()[0]->getOptions()); + } + + public function testApplyColumnChangeToColumnAdd() + { + $base = new TableOperation('users', TableOperation::ALTER, [ + new ColumnOperation('email', ColumnOperation::ADD, ['type' => 'string', 'length' => 255, 'first' => true]), + ], []); + + $operation = $base->apply(new TableOperation('users', TableOperation::ALTER, [ + new ColumnOperation('email', ColumnOperation::CHANGE, ['type' => 'char', 'length' => 64, 'new_name' => 'username']), + ], [])); + + $this->assertCount(1, $operation->getColumnOperations()); + $this->assertEquals('username', $operation->getColumnOperations()[0]->getName()); + $this->assertEquals(ColumnOperation::ADD, $operation->getColumnOperations()[0]->getOperation()); + $this->assertEquals(['type' => 'char', 'length' => 64], $operation->getColumnOperations()[0]->getOptions()); + } + + public function testApplyColumnAddToColumnDrop() + { + $base = new TableOperation('users', TableOperation::ALTER, [ + new ColumnOperation('email', ColumnOperation::DROP, []), + ], []); + + $operation = $base->apply(new TableOperation('users', TableOperation::ALTER, [ + new ColumnOperation('email', ColumnOperation::ADD, ['type' => 'string']), + ], [])); + + $this->assertCount(1, $operation->getColumnOperations()); + $this->assertEquals('email', $operation->getColumnOperations()[0]->getName()); + $this->assertEquals(ColumnOperation::MODIFY, $operation->getColumnOperations()[0]->getOperation()); + $this->assertEquals(['type' => 'string'], $operation->getColumnOperations()[0]->getOptions()); + } + + public function testApplyColumnDropToColumnModify() + { + $base = new TableOperation('users', TableOperation::ALTER, [ + new ColumnOperation('email', ColumnOperation::MODIFY, ['type' => 'string', 'length' => 255]), + ], []); + + $operation = $base->apply(new TableOperation('users', TableOperation::ALTER, [ + new ColumnOperation('email', ColumnOperation::DROP, []), + ], [])); + + $this->assertCount(1, $operation->getColumnOperations()); + $this->assertEquals('email', $operation->getColumnOperations()[0]->getName()); $this->assertEquals(ColumnOperation::DROP, $operation->getColumnOperations()[0]->getOperation()); + } - $this->assertEquals('email', $operation->getColumnOperations()[1]->getName()); - $this->assertEquals(ColumnOperation::ADD, $operation->getColumnOperations()[1]->getOperation()); - $this->assertEquals(['type' => 'string', 'length' => 255, 'new_name' => 'email'], $operation->getColumnOperations()[1]->getOptions()); + public function testApplyColumnModifyToColumnModify() + { + $base = new TableOperation('users', TableOperation::ALTER, [ + new ColumnOperation('email', ColumnOperation::MODIFY, ['type' => 'string', 'length' => 255]), + ], []); - $this->assertEquals('email_username', $operation->getIndexOperations()[0]->getName()); - $this->assertEquals(IndexOperation::ADD, $operation->getIndexOperations()[0]->getOperation()); - $this->assertEquals(['email'], $operation->getIndexOperations()[0]->getColumns()); - $this->assertEquals(['unique' => true], $operation->getIndexOperations()[0]->getOptions()); + $operation = $base->apply(new TableOperation('users', TableOperation::ALTER, [ + new ColumnOperation('email', ColumnOperation::MODIFY, ['type' => 'char', 'length' => 64]), + ], [])); + + $this->assertCount(1, $operation->getColumnOperations()); + $this->assertEquals('email', $operation->getColumnOperations()[0]->getName()); + $this->assertEquals(ColumnOperation::MODIFY, $operation->getColumnOperations()[0]->getOperation()); + $this->assertEquals(['type' => 'char', 'length' => 64], $operation->getColumnOperations()[0]->getOptions()); } - public function testApplyAlterToAlterWithModifyColumnChange() + public function testApplyColumnChangeToColumnModify() { $base = new TableOperation('users', TableOperation::ALTER, [ - new ColumnOperation('id', ColumnOperation::DROP, []), - new ColumnOperation('email', ColumnOperation::CHANGE, ['new_name' => 'username', 'type' => 'string', 'length' => 255, 'first' => true]), + new ColumnOperation('email', ColumnOperation::MODIFY, ['type' => 'string', 'length' => 255]), ], []); $operation = $base->apply(new TableOperation('users', TableOperation::ALTER, [ - new ColumnOperation('username', ColumnOperation::MODIFY, ['type' => 'char', 'length' => 64]) + new ColumnOperation('email', ColumnOperation::CHANGE, ['type' => 'char', 'length' => 64, 'new_name' => 'username']), ], [])); - $this->assertEquals('users', $operation->getName()); - $this->assertEquals(TableOperation::ALTER, $operation->getOperation()); - $this->assertCount(2, $operation->getColumnOperations()); + $this->assertCount(1, $operation->getColumnOperations()); + $this->assertEquals('email', $operation->getColumnOperations()[0]->getName()); + $this->assertEquals(ColumnOperation::CHANGE, $operation->getColumnOperations()[0]->getOperation()); + $this->assertEquals(['type' => 'char', 'length' => 64, 'new_name' => 'username'], $operation->getColumnOperations()[0]->getOptions()); + } - $this->assertEquals('id', $operation->getColumnOperations()[0]->getName()); + public function testApplyColumnDropToColumnChange() + { + $base = new TableOperation('users', TableOperation::ALTER, [ + new ColumnOperation('email', ColumnOperation::CHANGE, ['type' => 'string', 'length' => 255, 'new_name' => 'username']), + ], []); + + $operation = $base->apply(new TableOperation('users', TableOperation::ALTER, [ + new ColumnOperation('username', ColumnOperation::DROP, []), + ], [])); + + $this->assertCount(1, $operation->getColumnOperations()); + $this->assertEquals('email', $operation->getColumnOperations()[0]->getName()); $this->assertEquals(ColumnOperation::DROP, $operation->getColumnOperations()[0]->getOperation()); + } - $this->assertEquals('email', $operation->getColumnOperations()[1]->getName()); - $this->assertEquals(ColumnOperation::CHANGE, $operation->getColumnOperations()[1]->getOperation()); - $this->assertEquals(['type' => 'char', 'length' => 64, 'new_name' => 'username'], $operation->getColumnOperations()[1]->getOptions()); + public function testApplyColumnModifyToColumnChange() + { + $base = new TableOperation('users', TableOperation::ALTER, [ + new ColumnOperation('email', ColumnOperation::CHANGE, ['type' => 'string', 'length' => 255, 'new_name' => 'username']), + ], []); + + $operation = $base->apply(new TableOperation('users', TableOperation::ALTER, [ + new ColumnOperation('username', ColumnOperation::MODIFY, ['type' => 'char', 'length' => 64]), + ], [])); + + $this->assertCount(1, $operation->getColumnOperations()); + $this->assertEquals('email', $operation->getColumnOperations()[0]->getName()); + $this->assertEquals(ColumnOperation::CHANGE, $operation->getColumnOperations()[0]->getOperation()); + $this->assertEquals(['type' => 'char', 'length' => 64, 'new_name' => 'username'], $operation->getColumnOperations()[0]->getOptions()); } - public function testApplyDropToAlter() + public function testApplyColumnChangeToColumnChange() { $base = new TableOperation('users', TableOperation::ALTER, [ - new ColumnOperation('id', ColumnOperation::DROP, []), - new ColumnOperation('email', ColumnOperation::ADD, ['type' => 'string', 'length' => 255, 'first' => true]), - new ColumnOperation('username', ColumnOperation::MODIFY, ['type' => 'string', 'length' => 255]) + new ColumnOperation('email', ColumnOperation::CHANGE, ['type' => 'string', 'length' => 255, 'new_name' => 'username']), ], []); - $drop = new TableOperation('users', TableOperation::DROP, [], []); + $operation = $base->apply(new TableOperation('users', TableOperation::ALTER, [ + new ColumnOperation('username', ColumnOperation::CHANGE, ['type' => 'char', 'length' => 64, 'new_name' => 'user_id']), + ], [])); - $operation = $base->apply($drop); - $this->assertEquals($drop, $operation); + $this->assertCount(1, $operation->getColumnOperations()); + $this->assertEquals('email', $operation->getColumnOperations()[0]->getName()); + $this->assertEquals(ColumnOperation::CHANGE, $operation->getColumnOperations()[0]->getOperation()); + $this->assertEquals(['type' => 'char', 'length' => 64, 'new_name' => 'user_id'], $operation->getColumnOperations()[0]->getOptions()); } public function testReverseCreate()