From 1955245047ec39418a2ee6e4e8f41819141978e1 Mon Sep 17 00:00:00 2001 From: Simon Mundy Date: Mon, 23 Feb 2026 23:24:05 +1100 Subject: [PATCH 1/4] Added IF/IF NOT EXISTS to table alterations, SQL column types Signed-off-by: Simon Mundy --- src/Sql/Ddl/CreateTable.php | 16 +++++++- src/Sql/Ddl/DropTable.php | 20 ++++++++- src/Sql/Ddl/Index/Index.php | 23 ++++++++++- test/unit/Sql/Ddl/CreateTableTest.php | 34 +++++++++++++++ test/unit/Sql/Ddl/DropTableTest.php | 36 ++++++++++++++++ test/unit/Sql/Ddl/Index/IndexTest.php | 59 +++++++++++++++++++++++++++ 6 files changed, 184 insertions(+), 4 deletions(-) diff --git a/src/Sql/Ddl/CreateTable.php b/src/Sql/Ddl/CreateTable.php index 1ccfa494..e068c388 100644 --- a/src/Sql/Ddl/CreateTable.php +++ b/src/Sql/Ddl/CreateTable.php @@ -22,13 +22,15 @@ class CreateTable extends AbstractSql protected array $constraints = []; + protected bool $ifNotExists = false; + protected bool $isTemporary = false; /** * {@inheritDoc} */ protected array $specifications = [ - self::TABLE => 'CREATE %1$sTABLE %2$s (', + self::TABLE => 'CREATE %1$sTABLE %2$s%3$s (', self::COLUMNS => [ "\n %1\$s" => [ [1 => '%1$s', 'combinedby' => ",\n "], @@ -51,6 +53,17 @@ public function __construct(string|TableIdentifier $table = '', bool $isTemporar $this->setTemporary($isTemporary); } + public function ifNotExists(bool $ifNotExists = true): static + { + $this->ifNotExists = $ifNotExists; + return $this; + } + + public function getIfNotExists(): bool + { + return $this->ifNotExists; + } + public function setTemporary(string|int|bool $temporary): static { $this->isTemporary = (bool) $temporary; @@ -102,6 +115,7 @@ protected function processTable(?PlatformInterface $adapterPlatform = null): arr { return [ $this->isTemporary ? 'TEMPORARY ' : '', + $this->ifNotExists ? 'IF NOT EXISTS ' : '', $this->resolveTable($this->table, $adapterPlatform), ]; } diff --git a/src/Sql/Ddl/DropTable.php b/src/Sql/Ddl/DropTable.php index 6193f939..dd0d85a5 100644 --- a/src/Sql/Ddl/DropTable.php +++ b/src/Sql/Ddl/DropTable.php @@ -12,8 +12,10 @@ class DropTable extends AbstractSql { final public const TABLE = 'table'; + protected bool $ifExists = false; + protected array $specifications = [ - self::TABLE => 'DROP TABLE %1$s', + self::TABLE => 'DROP TABLE %1$s%2$s', ]; protected string|TableIdentifier $table = ''; @@ -23,9 +25,23 @@ public function __construct(string|TableIdentifier $table = '') $this->table = $table; } + public function ifExists(bool $ifExists = true): static + { + $this->ifExists = $ifExists; + return $this; + } + + public function getIfExists(): bool + { + return $this->ifExists; + } + /** @return string[] */ protected function processTable(?PlatformInterface $adapterPlatform = null): array { - return [$this->resolveTable($this->table, $adapterPlatform)]; + return [ + $this->ifExists ? 'IF EXISTS ' : '', + $this->resolveTable($this->table, $adapterPlatform), + ]; } } diff --git a/src/Sql/Ddl/Index/Index.php b/src/Sql/Ddl/Index/Index.php index 60d76514..a3802782 100644 --- a/src/Sql/Ddl/Index/Index.php +++ b/src/Sql/Ddl/Index/Index.php @@ -6,6 +6,7 @@ use Override; use PhpDb\Sql\Argument\Identifier; +use PhpDb\Sql\Argument\Literal; use function count; use function implode; @@ -17,6 +18,8 @@ class Index extends AbstractIndex protected array $lengths; + protected ?string $type = null; + public function __construct(null|array|string $columns, ?string $name = null, array $lengths = []) { parent::__construct($columns, $name); @@ -24,6 +27,17 @@ public function __construct(null|array|string $columns, ?string $name = null, ar $this->lengths = $lengths; } + public function setType(string $type): static + { + $this->type = $type; + return $this; + } + + public function getType(): ?string + { + return $this->type; + } + /** @inheritDoc */ #[Override] public function getExpressionData(): array @@ -43,8 +57,15 @@ public function getExpressionData(): array $specParts[] = $specPart; } + $spec = str_replace('...', implode(', ', $specParts), $this->specification); + + if ($this->type !== null) { + $spec .= ' USING %s'; + $values[] = new Literal($this->type); + } + return [ - 'spec' => str_replace('...', implode(', ', $specParts), $this->specification), + 'spec' => $spec, 'values' => $values, ]; } diff --git a/test/unit/Sql/Ddl/CreateTableTest.php b/test/unit/Sql/Ddl/CreateTableTest.php index 8b8715cc..a31547d9 100644 --- a/test/unit/Sql/Ddl/CreateTableTest.php +++ b/test/unit/Sql/Ddl/CreateTableTest.php @@ -14,6 +14,8 @@ use PHPUnit\Framework\TestCase; #[CoversMethod(CreateTable::class, '__construct')] +#[CoversMethod(CreateTable::class, 'ifNotExists')] +#[CoversMethod(CreateTable::class, 'getIfNotExists')] #[CoversMethod(CreateTable::class, 'setTemporary')] #[CoversMethod(CreateTable::class, 'isTemporary')] #[CoversMethod(CreateTable::class, 'setTable')] @@ -308,4 +310,36 @@ public function testSetTableAfterConstruction(): void self::assertSame($ct, $result); self::assertEquals('another_table', $ct->getRawState(CreateTable::TABLE)); } + + public function testIfNotExists(): void + { + $ct = new CreateTable('foo'); + self::assertFalse($ct->getIfNotExists()); + + $result = $ct->ifNotExists(); + self::assertSame($ct, $result); + self::assertTrue($ct->getIfNotExists()); + + self::assertEquals("CREATE TABLE IF NOT EXISTS \"foo\" ( \n)", $ct->getSqlString()); + } + + public function testIfNotExistsDisable(): void + { + $ct = new CreateTable('foo'); + $ct->ifNotExists(); + self::assertTrue($ct->getIfNotExists()); + + $ct->ifNotExists(false); + self::assertFalse($ct->getIfNotExists()); + + self::assertEquals("CREATE TABLE \"foo\" ( \n)", $ct->getSqlString()); + } + + public function testIfNotExistsCombinedWithTemporary(): void + { + $ct = new CreateTable('foo', true); + $ct->ifNotExists(); + + self::assertEquals("CREATE TEMPORARY TABLE IF NOT EXISTS \"foo\" ( \n)", $ct->getSqlString()); + } } diff --git a/test/unit/Sql/Ddl/DropTableTest.php b/test/unit/Sql/Ddl/DropTableTest.php index 711d7805..12198591 100644 --- a/test/unit/Sql/Ddl/DropTableTest.php +++ b/test/unit/Sql/Ddl/DropTableTest.php @@ -9,7 +9,11 @@ use PHPUnit\Framework\Attributes\CoversMethod; use PHPUnit\Framework\TestCase; +#[CoversMethod(DropTable::class, '__construct')] +#[CoversMethod(DropTable::class, 'ifExists')] +#[CoversMethod(DropTable::class, 'getIfExists')] #[CoversMethod(DropTable::class, 'getSqlString')] +#[CoversMethod(DropTable::class, 'processTable')] class DropTableTest extends TestCase { public function testGetSqlString(): void @@ -23,4 +27,36 @@ public function testGetSqlString(): void $dt = new DropTable(new TableIdentifier('bar', 'foo')); self::assertEquals('DROP TABLE "foo"."bar"', $dt->getSqlString()); } + + public function testIfExists(): void + { + $dt = new DropTable('foo'); + self::assertFalse($dt->getIfExists()); + + $result = $dt->ifExists(); + self::assertSame($dt, $result); + self::assertTrue($dt->getIfExists()); + + self::assertEquals('DROP TABLE IF EXISTS "foo"', $dt->getSqlString()); + } + + public function testIfExistsDisable(): void + { + $dt = new DropTable('foo'); + $dt->ifExists(); + self::assertTrue($dt->getIfExists()); + + $dt->ifExists(false); + self::assertFalse($dt->getIfExists()); + + self::assertEquals('DROP TABLE "foo"', $dt->getSqlString()); + } + + public function testIfExistsWithTableIdentifier(): void + { + $dt = new DropTable(new TableIdentifier('bar', 'foo')); + $dt->ifExists(); + + self::assertEquals('DROP TABLE IF EXISTS "foo"."bar"', $dt->getSqlString()); + } } diff --git a/test/unit/Sql/Ddl/Index/IndexTest.php b/test/unit/Sql/Ddl/Index/IndexTest.php index fc3daaff..9bf9b784 100644 --- a/test/unit/Sql/Ddl/Index/IndexTest.php +++ b/test/unit/Sql/Ddl/Index/IndexTest.php @@ -5,11 +5,14 @@ namespace PhpDbTest\Sql\Ddl\Index; use PhpDb\Sql\Argument\Identifier; +use PhpDb\Sql\Argument\Literal; use PhpDb\Sql\Ddl\Index\Index; use PHPUnit\Framework\Attributes\CoversMethod; use PHPUnit\Framework\TestCase; #[CoversMethod(Index::class, '__construct')] +#[CoversMethod(Index::class, 'setType')] +#[CoversMethod(Index::class, 'getType')] #[CoversMethod(Index::class, 'getExpressionData')] final class IndexTest extends TestCase { @@ -53,4 +56,60 @@ public function testGetExpressionDataWithLengthUnmatched(): void new Identifier('bar'), ], $expressionData['values']); } + + public function testSetTypeAndGetType(): void + { + $index = new Index('foo', 'my_idx'); + self::assertNull($index->getType()); + + $result = $index->setType('BTREE'); + self::assertSame($index, $result); + self::assertEquals('BTREE', $index->getType()); + } + + public function testGetExpressionDataWithBtreeType(): void + { + $index = new Index('foo', 'my_idx'); + $index->setType('BTREE'); + + $expressionData = $index->getExpressionData(); + + self::assertEquals('INDEX %s(%s) USING %s', $expressionData['spec']); + self::assertEquals([ + new Identifier('my_idx'), + new Identifier('foo'), + new Literal('BTREE'), + ], $expressionData['values']); + } + + public function testGetExpressionDataWithHashType(): void + { + $index = new Index('foo', 'my_idx'); + $index->setType('HASH'); + + $expressionData = $index->getExpressionData(); + + self::assertEquals('INDEX %s(%s) USING %s', $expressionData['spec']); + self::assertEquals([ + new Identifier('my_idx'), + new Identifier('foo'), + new Literal('HASH'), + ], $expressionData['values']); + } + + public function testGetExpressionDataWithTypeAndLengths(): void + { + $index = new Index(['foo', 'bar'], 'my_idx', [10, 5]); + $index->setType('BTREE'); + + $expressionData = $index->getExpressionData(); + + self::assertEquals('INDEX %s(%s(10), %s(5)) USING %s', $expressionData['spec']); + self::assertEquals([ + new Identifier('my_idx'), + new Identifier('foo'), + new Identifier('bar'), + new Literal('BTREE'), + ], $expressionData['values']); + } } From 372c12aad061e777914b40693ac0de537f256b56 Mon Sep 17 00:00:00 2001 From: Simon Mundy Date: Mon, 23 Feb 2026 23:26:31 +1100 Subject: [PATCH 2/4] Add Double, Json, and SmallInteger DDL column types with tests --- src/Sql/Ddl/Column/Double.php | 10 +++++ src/Sql/Ddl/Column/Json.php | 10 +++++ src/Sql/Ddl/Column/SmallInteger.php | 10 +++++ test/unit/Sql/Ddl/Column/DoubleTest.php | 28 +++++++++++++ test/unit/Sql/Ddl/Column/JsonTest.php | 27 ++++++++++++ test/unit/Sql/Ddl/Column/SmallIntegerTest.php | 41 +++++++++++++++++++ 6 files changed, 126 insertions(+) create mode 100644 src/Sql/Ddl/Column/Double.php create mode 100644 src/Sql/Ddl/Column/Json.php create mode 100644 src/Sql/Ddl/Column/SmallInteger.php create mode 100644 test/unit/Sql/Ddl/Column/DoubleTest.php create mode 100644 test/unit/Sql/Ddl/Column/JsonTest.php create mode 100644 test/unit/Sql/Ddl/Column/SmallIntegerTest.php diff --git a/src/Sql/Ddl/Column/Double.php b/src/Sql/Ddl/Column/Double.php new file mode 100644 index 00000000..ad9a6085 --- /dev/null +++ b/src/Sql/Ddl/Column/Double.php @@ -0,0 +1,10 @@ +getExpressionData(); + + self::assertEquals('%s %s(%s) NOT NULL', $expressionData['spec']); + self::assertEquals([ + Argument::identifier('foo'), + Argument::literal('DOUBLE'), + Argument::literal('10,5'), + ], $expressionData['values']); + } +} diff --git a/test/unit/Sql/Ddl/Column/JsonTest.php b/test/unit/Sql/Ddl/Column/JsonTest.php new file mode 100644 index 00000000..afd4e1f6 --- /dev/null +++ b/test/unit/Sql/Ddl/Column/JsonTest.php @@ -0,0 +1,27 @@ +getExpressionData(); + + self::assertEquals('%s %s NOT NULL', $expressionData['spec']); + self::assertEquals([ + Argument::identifier('foo'), + Argument::literal('JSON'), + ], $expressionData['values']); + } +} diff --git a/test/unit/Sql/Ddl/Column/SmallIntegerTest.php b/test/unit/Sql/Ddl/Column/SmallIntegerTest.php new file mode 100644 index 00000000..384aea53 --- /dev/null +++ b/test/unit/Sql/Ddl/Column/SmallIntegerTest.php @@ -0,0 +1,41 @@ +getName()); + } + + public function testGetExpressionData(): void + { + $column = new SmallInteger('foo'); + $expressionData = $column->getExpressionData(); + + self::assertEquals( + '%s %s NOT NULL', + $expressionData['spec'] + ); + + self::assertEquals( + [ + Argument::Identifier('foo'), + Argument::Literal('SMALLINT'), + ], + $expressionData['values'] + ); + } +} From 7509fb10cf9ab763d7a21b77421d73ca7aeccbae Mon Sep 17 00:00:00 2001 From: Simon Mundy Date: Tue, 24 Feb 2026 00:14:26 +1100 Subject: [PATCH 3/4] Allow Literal as column default for unquoted SQL expressions Column::setDefault() now accepts Literal instances so that SQL expressions like CURRENT_TIMESTAMP are emitted unquoted rather than being wrapped in a Value. --- src/Sql/Ddl/Column/Column.php | 10 ++++--- src/Sql/Ddl/Column/ColumnInterface.php | 3 +- test/unit/Sql/Ddl/Column/ColumnTest.php | 29 ++++++++++++++++++++ test/unit/Sql/Ddl/Column/TimestampTest.php | 32 ++++++++++++++++++++++ 4 files changed, 69 insertions(+), 5 deletions(-) diff --git a/src/Sql/Ddl/Column/Column.php b/src/Sql/Ddl/Column/Column.php index b82c5eb7..550c6f8d 100644 --- a/src/Sql/Ddl/Column/Column.php +++ b/src/Sql/Ddl/Column/Column.php @@ -14,7 +14,7 @@ class Column implements ColumnInterface { - protected string|int|null $default; + protected string|int|Literal|null $default; protected bool $isNullable = false; @@ -65,14 +65,14 @@ public function isNullable(): bool return $this->isNullable; } - public function setDefault(string|int|null $default): static + public function setDefault(string|int|Literal|null $default): static { $this->default = $default; return $this; } #[Override] - public function getDefault(): string|int|null + public function getDefault(): string|int|Literal|null { return $this->default; } @@ -118,7 +118,9 @@ public function getExpressionData(): array if ($this->default !== null) { $specParts[] = 'DEFAULT %s'; - $values[] = new Value($this->default); + $values[] = $this->default instanceof Literal + ? $this->default + : new Value($this->default); } foreach ($this->constraints as $constraint) { diff --git a/src/Sql/Ddl/Column/ColumnInterface.php b/src/Sql/Ddl/Column/ColumnInterface.php index f26bc943..1f7bc5a1 100644 --- a/src/Sql/Ddl/Column/ColumnInterface.php +++ b/src/Sql/Ddl/Column/ColumnInterface.php @@ -4,6 +4,7 @@ namespace PhpDb\Sql\Ddl\Column; +use PhpDb\Sql\Argument\Literal; use PhpDb\Sql\ExpressionInterface; /** @@ -15,7 +16,7 @@ public function getName(): string; public function isNullable(): bool; - public function getDefault(): string|int|null; + public function getDefault(): string|int|Literal|null; public function getOptions(): array; } diff --git a/test/unit/Sql/Ddl/Column/ColumnTest.php b/test/unit/Sql/Ddl/Column/ColumnTest.php index 1a1e4b38..33dbd75a 100644 --- a/test/unit/Sql/Ddl/Column/ColumnTest.php +++ b/test/unit/Sql/Ddl/Column/ColumnTest.php @@ -5,6 +5,7 @@ namespace PhpDbTest\Sql\Ddl\Column; use PhpDb\Sql\Argument; +use PhpDb\Sql\Argument\Literal; use PhpDb\Sql\Ddl\Column\Column; use PHPUnit\Framework\Attributes\CoversMethod; use PHPUnit\Framework\TestCase; @@ -166,4 +167,32 @@ public function testGetExpressionData(): void Argument::value('bar'), ], $expressionData['values']); } + + public function testSetDefaultWithLiteral(): void + { + $column = new Column(); + $column->setName('created_at'); + + $literal = new Literal('CURRENT_TIMESTAMP'); + $result = $column->setDefault($literal); + + self::assertSame($column, $result); + self::assertSame($literal, $column->getDefault()); + } + + public function testGetExpressionDataWithLiteralDefault(): void + { + $column = new Column(); + $column->setName('created_at'); + $column->setDefault(new Literal('CURRENT_TIMESTAMP')); + + $expressionData = $column->getExpressionData(); + + self::assertEquals('%s %s NOT NULL DEFAULT %s', $expressionData['spec']); + self::assertEquals([ + Argument::identifier('created_at'), + Argument::literal('INTEGER'), + Argument::literal('CURRENT_TIMESTAMP'), + ], $expressionData['values']); + } } diff --git a/test/unit/Sql/Ddl/Column/TimestampTest.php b/test/unit/Sql/Ddl/Column/TimestampTest.php index 1133c4e9..7712588f 100644 --- a/test/unit/Sql/Ddl/Column/TimestampTest.php +++ b/test/unit/Sql/Ddl/Column/TimestampTest.php @@ -67,6 +67,38 @@ public function testGetExpressionDataWithoutOnUpdateOption(): void self::assertEquals(Argument::literal('TIMESTAMP'), $values[1]); } + public function testGetExpressionDataWithCurrentTimestampDefault(): void + { + $column = new Timestamp('created_at'); + $column->setDefault(new Literal('CURRENT_TIMESTAMP')); + + $expressionData = $column->getExpressionData(); + + self::assertEquals('%s %s NOT NULL DEFAULT %s', $expressionData['spec']); + self::assertEquals([ + new Identifier('created_at'), + new Literal('TIMESTAMP'), + new Literal('CURRENT_TIMESTAMP'), + ], $expressionData['values']); + } + + public function testGetExpressionDataWithCurrentTimestampDefaultAndOnUpdate(): void + { + $column = new Timestamp('updated_at'); + $column->setDefault(new Literal('CURRENT_TIMESTAMP')); + $column->setOption('on_update', true); + + $expressionData = $column->getExpressionData(); + + self::assertEquals('%s %s NOT NULL DEFAULT %s %s', $expressionData['spec']); + self::assertEquals([ + new Identifier('updated_at'), + new Literal('TIMESTAMP'), + new Literal('CURRENT_TIMESTAMP'), + new Literal('ON UPDATE CURRENT_TIMESTAMP'), + ], $expressionData['values']); + } + public function testInheritanceFromAbstractTimestampColumn(): void { $column = new Timestamp('test'); From 7ff2273eca32ff91c1c23bfecd62224a194443e7 Mon Sep 17 00:00:00 2001 From: Simon Mundy Date: Tue, 24 Feb 2026 00:21:31 +1100 Subject: [PATCH 4/4] Allow string|int|float|bool|Literal|Value|null for Column defaults --- src/Sql/Ddl/Column/Column.php | 9 +-- src/Sql/Ddl/Column/ColumnInterface.php | 3 +- test/unit/Sql/Ddl/Column/ColumnTest.php | 83 +++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 5 deletions(-) diff --git a/src/Sql/Ddl/Column/Column.php b/src/Sql/Ddl/Column/Column.php index 550c6f8d..dac7bda4 100644 --- a/src/Sql/Ddl/Column/Column.php +++ b/src/Sql/Ddl/Column/Column.php @@ -8,13 +8,14 @@ use PhpDb\Sql\Argument\Identifier; use PhpDb\Sql\Argument\Literal; use PhpDb\Sql\Argument\Value; +use PhpDb\Sql\ArgumentInterface; use PhpDb\Sql\Ddl\Constraint\ConstraintInterface; use function implode; class Column implements ColumnInterface { - protected string|int|Literal|null $default; + protected string|int|float|bool|Literal|Value|null $default; protected bool $isNullable = false; @@ -65,14 +66,14 @@ public function isNullable(): bool return $this->isNullable; } - public function setDefault(string|int|Literal|null $default): static + public function setDefault(string|int|float|bool|Literal|Value|null $default): static { $this->default = $default; return $this; } #[Override] - public function getDefault(): string|int|Literal|null + public function getDefault(): string|int|float|bool|Literal|Value|null { return $this->default; } @@ -118,7 +119,7 @@ public function getExpressionData(): array if ($this->default !== null) { $specParts[] = 'DEFAULT %s'; - $values[] = $this->default instanceof Literal + $values[] = $this->default instanceof ArgumentInterface ? $this->default : new Value($this->default); } diff --git a/src/Sql/Ddl/Column/ColumnInterface.php b/src/Sql/Ddl/Column/ColumnInterface.php index 1f7bc5a1..b9665c5d 100644 --- a/src/Sql/Ddl/Column/ColumnInterface.php +++ b/src/Sql/Ddl/Column/ColumnInterface.php @@ -5,6 +5,7 @@ namespace PhpDb\Sql\Ddl\Column; use PhpDb\Sql\Argument\Literal; +use PhpDb\Sql\Argument\Value; use PhpDb\Sql\ExpressionInterface; /** @@ -16,7 +17,7 @@ public function getName(): string; public function isNullable(): bool; - public function getDefault(): string|int|Literal|null; + public function getDefault(): string|int|float|bool|Literal|Value|null; public function getOptions(): array; } diff --git a/test/unit/Sql/Ddl/Column/ColumnTest.php b/test/unit/Sql/Ddl/Column/ColumnTest.php index 33dbd75a..9b9e9f76 100644 --- a/test/unit/Sql/Ddl/Column/ColumnTest.php +++ b/test/unit/Sql/Ddl/Column/ColumnTest.php @@ -6,6 +6,7 @@ use PhpDb\Sql\Argument; use PhpDb\Sql\Argument\Literal; +use PhpDb\Sql\Argument\Value; use PhpDb\Sql\Ddl\Column\Column; use PHPUnit\Framework\Attributes\CoversMethod; use PHPUnit\Framework\TestCase; @@ -195,4 +196,86 @@ public function testGetExpressionDataWithLiteralDefault(): void Argument::literal('CURRENT_TIMESTAMP'), ], $expressionData['values']); } + + public function testSetDefaultWithValue(): void + { + $column = new Column(); + $column->setName('score'); + + $value = new Value(99); + $result = $column->setDefault($value); + + self::assertSame($column, $result); + self::assertSame($value, $column->getDefault()); + } + + public function testGetExpressionDataWithValueDefault(): void + { + $column = new Column(); + $column->setName('score'); + $column->setDefault(new Value(42)); + + $expressionData = $column->getExpressionData(); + + self::assertEquals('%s %s NOT NULL DEFAULT %s', $expressionData['spec']); + self::assertEquals([ + Argument::identifier('score'), + Argument::literal('INTEGER'), + Argument::value(42), + ], $expressionData['values']); + } + + public function testSetDefaultWithFloat(): void + { + $column = new Column(); + $column->setName('rate'); + + $result = $column->setDefault(3.14); + + self::assertSame($column, $result); + self::assertSame(3.14, $column->getDefault()); + } + + public function testGetExpressionDataWithFloatDefault(): void + { + $column = new Column(); + $column->setName('rate'); + $column->setDefault(9.99); + + $expressionData = $column->getExpressionData(); + + self::assertEquals('%s %s NOT NULL DEFAULT %s', $expressionData['spec']); + self::assertEquals([ + Argument::identifier('rate'), + Argument::literal('INTEGER'), + Argument::value(9.99), + ], $expressionData['values']); + } + + public function testSetDefaultWithBool(): void + { + $column = new Column(); + $column->setName('is_active'); + + $result = $column->setDefault(true); + + self::assertSame($column, $result); + self::assertTrue($column->getDefault()); + } + + public function testGetExpressionDataWithBoolDefault(): void + { + $column = new Column(); + $column->setName('is_active'); + $column->setDefault(false); + + $expressionData = $column->getExpressionData(); + + self::assertEquals('%s %s NOT NULL DEFAULT %s', $expressionData['spec']); + self::assertEquals([ + Argument::identifier('is_active'), + Argument::literal('INTEGER'), + Argument::value(false), + ], $expressionData['values']); + } }