diff --git a/packages/database/src/QueryStatements/CreateTableStatement.php b/packages/database/src/QueryStatements/CreateTableStatement.php index ab3bba8d7..4ecdc6c94 100644 --- a/packages/database/src/QueryStatements/CreateTableStatement.php +++ b/packages/database/src/QueryStatements/CreateTableStatement.php @@ -199,12 +199,13 @@ public function char(string $name, bool $nullable = false, ?string $default = nu /** * Adds an `INTEGER` column to the table. */ - public function integer(string $name, bool $unsigned = false, bool $nullable = false, ?int $default = null): self + public function integer(string $name, bool $unsigned = false, bool $nullable = false, int $bytes = 4, ?int $default = null): self { $this->statements[] = new IntegerStatement( name: $name, unsigned: $unsigned, nullable: $nullable, + bytes: $bytes, default: $default, ); diff --git a/packages/database/src/QueryStatements/IntegerBytes.php b/packages/database/src/QueryStatements/IntegerBytes.php new file mode 100644 index 000000000..1ec8d80e2 --- /dev/null +++ b/packages/database/src/QueryStatements/IntegerBytes.php @@ -0,0 +1,30 @@ + self::DEFAULT->value => self::BIG, + $bytes > self::SMALL->value => self::DEFAULT, + DEFAULT => self::SMALL, + }; + } + + public function toString(): string + { + return match($this) { + self::SMALL => 'SMALLINT', + self::DEFAULT => 'INTEGER', + self::BIG => 'BIGINT', + }; + } +} diff --git a/packages/database/src/QueryStatements/IntegerStatement.php b/packages/database/src/QueryStatements/IntegerStatement.php index 793ac4899..fcbc90e13 100644 --- a/packages/database/src/QueryStatements/IntegerStatement.php +++ b/packages/database/src/QueryStatements/IntegerStatement.php @@ -13,17 +13,28 @@ public function __construct( private string $name, private bool $unsigned = false, private bool $nullable = false, + private int $bytes = 4, private ?int $default = null, ) {} public function compile(DatabaseDialect $dialect): string { - return sprintf( - '`%s` INTEGER %s %s %s', - $this->name, - $this->unsigned ? 'UNSIGNED' : '', - $this->default !== null ? "DEFAULT {$this->default}" : '', - $this->nullable ? '' : 'NOT NULL', - ); + return match($dialect) { + DatabaseDialect::SQLITE => sprintf( + '`%s` INTEGER %s %s %s', + $this->name, + $this->unsigned ? 'UNSIGNED' : '', + $this->default !== null ? "DEFAULT {$this->default}" : '', + $this->nullable ? '' : 'NOT NULL', + ), + DEFAULT => sprintf( + '`%s` %s %s %s %s', + $this->name, + IntegerBytes::fromBytes($this->bytes)->toString(), + $this->unsigned ? 'UNSIGNED' : '', + $this->default !== null ? "DEFAULT {$this->default}" : '', + $this->nullable ? '' : 'NOT NULL', + ) + }; } } diff --git a/packages/database/tests/QueryStatements/CreateTableStatementTest.php b/packages/database/tests/QueryStatements/CreateTableStatementTest.php index 2d68cefe9..8893315d7 100644 --- a/packages/database/tests/QueryStatements/CreateTableStatementTest.php +++ b/packages/database/tests/QueryStatements/CreateTableStatementTest.php @@ -18,6 +18,10 @@ */ final class CreateTableStatementTest extends TestCase { + public function test_integer_table_database_dialect(): void + { + + } #[DataProvider('provide_create_table_database_dialects')] public function test_create_a_table(DatabaseDialect $dialect, string $validSql): void { diff --git a/tests/Integration/Database/QueryStatements/CreateTableStatementTest.php b/tests/Integration/Database/QueryStatements/CreateTableStatementTest.php index cefccf14a..86863df1f 100644 --- a/tests/Integration/Database/QueryStatements/CreateTableStatementTest.php +++ b/tests/Integration/Database/QueryStatements/CreateTableStatementTest.php @@ -287,6 +287,57 @@ public function test_object_method_produces_same_sql_as_json_and_dto(): void $this->assertSame($jsonStatement, $objectStatement); $this->assertSame($dtoStatement, $objectStatement); } + + public function test_integer_field_with_bytes_mysql(): void + { + $bigInteger = new CreateTableStatement('test-table') + ->integer('content', false, false, 6) + ->compile(dialect: DatabaseDialect::MYSQL); + $defaultInteger = new CreateTableStatement('test-table') + ->integer('content', false, false, 3) + ->compile(dialect: DatabaseDialect::MYSQL); + $smallInteger = new CreateTableStatement('test-table') + ->integer('content', false, false, 2) + ->compile(dialect: DatabaseDialect::MYSQL); + + $this->assertStringContainsString('BIGINT', $bigInteger); + $this->assertStringContainsString('INTEGER', $defaultInteger); + $this->assertStringContainsString('SMALL', $smallInteger); + } + + public function test_integer_field_with_bytes_postgresql(): void + { + $bigInteger = new CreateTableStatement('test-table') + ->integer('content', false, false, 6) + ->compile(dialect: DatabaseDialect::POSTGRESQL); + $defaultInteger = new CreateTableStatement('test-table') + ->integer('content', false, false, 3) + ->compile(dialect: DatabaseDialect::POSTGRESQL); + $smallInteger = new CreateTableStatement('test-table') + ->integer('content', false, false, 2) + ->compile(dialect: DatabaseDialect::POSTGRESQL); + + $this->assertStringContainsString('BIGINT', $bigInteger); + $this->assertStringContainsString('INTEGER', $defaultInteger); + $this->assertStringContainsString('SMALL', $smallInteger); + } + + public function test_integer_field_with_bytes_sqlite(): void + { + $bigInteger = new CreateTableStatement('test-table') + ->integer('content', false, false, 6) + ->compile(dialect: DatabaseDialect::SQLITE); + $defaultInteger = new CreateTableStatement('test-table') + ->integer('content', false, false, 3) + ->compile(dialect: DatabaseDialect::SQLITE); + $smallInteger = new CreateTableStatement('test-table') + ->integer('content', false, false, 2) + ->compile(dialect: DatabaseDialect::SQLITE); + + $this->assertStringContainsString('INTEGER', $bigInteger); + $this->assertStringContainsString('INTEGER', $defaultInteger); + $this->assertStringContainsString('INTEGER', $smallInteger); + } } enum CreateTableStatementTestEnumForCreateTable: string