diff --git a/packages/database/src/QueryStatements/CreateTableStatement.php b/packages/database/src/QueryStatements/CreateTableStatement.php index 3e759a985..251f77172 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|DatabaseIntegerSize $size = DatabaseIntegerSize::DEFAULT, ?int $default = null): self { $this->statements[] = new IntegerStatement( name: $name, unsigned: $unsigned, nullable: $nullable, + size: $size, default: $default, ); diff --git a/packages/database/src/QueryStatements/DatabaseIntegerSize.php b/packages/database/src/QueryStatements/DatabaseIntegerSize.php new file mode 100644 index 000000000..4f55be72b --- /dev/null +++ b/packages/database/src/QueryStatements/DatabaseIntegerSize.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..17943e609 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|DatabaseIntegerSize $size = DatabaseIntegerSize::DEFAULT, 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, + DatabaseIntegerSize::fromBytes($this->size)->toString(), + $this->unsigned ? 'UNSIGNED' : '', + $this->default !== null ? "DEFAULT {$this->default}" : '', + $this->nullable ? '' : 'NOT NULL', + ), + }; } } 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