From 67d541412dc6054b1a0afdb3281fa55f287c476a Mon Sep 17 00:00:00 2001 From: MrYamous Date: Sun, 15 Feb 2026 15:00:52 +0100 Subject: [PATCH 1/4] feat(database): use different text type declaration with mysql according to field length --- packages/database/src/Config/MysqlConfig.php | 5 ++++ .../QueryStatements/CreateTableStatement.php | 3 ++- .../src/QueryStatements/TextStatement.php | 18 ++++++++++++- .../CreateTableStatementTest.php | 27 ++++++++++++++++++- 4 files changed, 50 insertions(+), 3 deletions(-) diff --git a/packages/database/src/Config/MysqlConfig.php b/packages/database/src/Config/MysqlConfig.php index e146df0343..8968371db8 100644 --- a/packages/database/src/Config/MysqlConfig.php +++ b/packages/database/src/Config/MysqlConfig.php @@ -15,6 +15,11 @@ final class MysqlConfig implements DatabaseConfig { + public const int LIMIT_TINYTEXT = 255; + public const int LIMIT_TEXT = 65535; + public const int LIMIT_MEDIUMTEXT = 16777215; + public const int LIMIT_LONGTEXT = 4294967295; + public string $dsn { get => sprintf( 'mysql:host=%s:%s;dbname=%s', diff --git a/packages/database/src/QueryStatements/CreateTableStatement.php b/packages/database/src/QueryStatements/CreateTableStatement.php index ab3bba8d73..a4b46ca6cf 100644 --- a/packages/database/src/QueryStatements/CreateTableStatement.php +++ b/packages/database/src/QueryStatements/CreateTableStatement.php @@ -143,12 +143,13 @@ public function foreignKey(string $local, string $foreign, OnDelete $onDelete = /** * Adds a `TEXT` column to the table. */ - public function text(string $name, bool $nullable = false, ?string $default = null): self + public function text(string $name, bool $nullable = false, ?string $default = null, ?int $length = null): self { $this->statements[] = new TextStatement( name: $name, nullable: $nullable, default: $default, + length: $length, ); return $this; diff --git a/packages/database/src/QueryStatements/TextStatement.php b/packages/database/src/QueryStatements/TextStatement.php index 0d65cbccba..0c9b81a864 100644 --- a/packages/database/src/QueryStatements/TextStatement.php +++ b/packages/database/src/QueryStatements/TextStatement.php @@ -5,6 +5,7 @@ namespace Tempest\Database\QueryStatements; use Tempest\Database\Config\DatabaseDialect; +use Tempest\Database\Config\MysqlConfig; use Tempest\Database\QueryStatement; final readonly class TextStatement implements QueryStatement @@ -13,14 +14,16 @@ public function __construct( private string $name, private bool $nullable = false, private ?string $default = null, + private ?int $length = null, ) {} public function compile(DatabaseDialect $dialect): string { return match ($dialect) { DatabaseDialect::MYSQL => sprintf( - '`%s` TEXT %s', + '`%s` %s %s', $this->name, + $this->getSQLTypeDeclaration($this->length), $this->nullable ? '' : 'NOT NULL', ), default => sprintf( @@ -31,4 +34,17 @@ public function compile(DatabaseDialect $dialect): string ), }; } + + private function getSQLTypeDeclaration(?int $length = null): string + { + $type = match (true) { + $length <= MysqlConfig::LIMIT_TINYTEXT => 'TINYTEXT', + $length <= MysqlConfig::LIMIT_TEXT => 'TEXT', + $length <= MysqlConfig::LIMIT_MEDIUMTEXT => 'MEDIUMTEXT', + $length <= MysqlConfig::LIMIT_LONGTEXT => 'LONGTEXT', + default => 'TEXT', + }; + + return $type; + } } diff --git a/tests/Integration/Database/QueryStatements/CreateTableStatementTest.php b/tests/Integration/Database/QueryStatements/CreateTableStatementTest.php index cefccf14af..b5010be5c1 100644 --- a/tests/Integration/Database/QueryStatements/CreateTableStatementTest.php +++ b/tests/Integration/Database/QueryStatements/CreateTableStatementTest.php @@ -225,7 +225,7 @@ public function test_string_method_with_custom_parameters(): void $varcharStatement = new CreateTableStatement('frieren_mages') ->primary() ->varchar('name', length: 120, nullable: true, default: 'Himmel') - ->compile(DatabaseDialect::MYSQL); + ->compile(dialect: DatabaseDialect::MYSQL); $stringStatement = new CreateTableStatement('frieren_mages') ->primary() @@ -235,6 +235,31 @@ public function test_string_method_with_custom_parameters(): void $this->assertSame($varcharStatement, $stringStatement); } + public function test_text_with_length_limit(): void + { + $tinyText = new CreateTableStatement('test-table') + ->text('content', false, null, 255) + ->compile(dialect: DatabaseDialect::MYSQL); + $mediumText = new CreateTableStatement('test-table') + ->text('content', false, null, 65535) + ->compile(dialect: DatabaseDialect::MYSQL); + $text = new CreateTableStatement('test-table') + ->text('content', false, null, 16777215) + ->compile(dialect: DatabaseDialect::MYSQL); + $longText = new CreateTableStatement('test-table') + ->text('content', false, null, 4294967295) + ->compile(dialect: DatabaseDialect::MYSQL); + $default = new CreateTableStatement('test-table') + ->text('content', false, null, null) + ->compile(dialect: DatabaseDialect::MYSQL); + + $this->assertStringContainsString('TINYTEXT', $tinyText); + $this->assertStringContainsString('MEDIUMTEXT', $mediumText); + $this->assertStringContainsString('TEXT', $text); + $this->assertStringContainsString('LONGTEXT', $longText); + $this->assertStringContainsString('TEXT', $default); + } + public function test_object_field(): void { $migration = new class() implements MigratesUp { From aca83ba1b08dc582a3b0db65ff7738aec06dd0f4 Mon Sep 17 00:00:00 2001 From: MrYamous Date: Sun, 15 Feb 2026 15:02:31 +0100 Subject: [PATCH 2/4] feat(database): use different text type declaration with mysql according to field length --- .../Database/QueryStatements/CreateTableStatementTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Integration/Database/QueryStatements/CreateTableStatementTest.php b/tests/Integration/Database/QueryStatements/CreateTableStatementTest.php index b5010be5c1..ff1783202e 100644 --- a/tests/Integration/Database/QueryStatements/CreateTableStatementTest.php +++ b/tests/Integration/Database/QueryStatements/CreateTableStatementTest.php @@ -225,7 +225,7 @@ public function test_string_method_with_custom_parameters(): void $varcharStatement = new CreateTableStatement('frieren_mages') ->primary() ->varchar('name', length: 120, nullable: true, default: 'Himmel') - ->compile(dialect: DatabaseDialect::MYSQL); + ->compile(DatabaseDialect::MYSQL); $stringStatement = new CreateTableStatement('frieren_mages') ->primary() From d7aad4cfacf133295adaa7eecd1cd00f2cfc0497 Mon Sep 17 00:00:00 2001 From: MrYamous Date: Thu, 12 Mar 2026 19:34:19 +0100 Subject: [PATCH 3/4] feat(database): use different text type declaration with mysql according to field length --- packages/database/src/Config/MysqlConfig.php | 5 --- .../database/src/Enums/DatabaseTextLength.php | 34 +++++++++++++++++++ .../QueryStatements/CreateTableStatement.php | 3 +- .../src/QueryStatements/TextStatement.php | 18 ++++------ .../CreateTableStatementTest.php | 15 +++++--- 5 files changed, 53 insertions(+), 22 deletions(-) create mode 100644 packages/database/src/Enums/DatabaseTextLength.php diff --git a/packages/database/src/Config/MysqlConfig.php b/packages/database/src/Config/MysqlConfig.php index 8968371db8..e146df0343 100644 --- a/packages/database/src/Config/MysqlConfig.php +++ b/packages/database/src/Config/MysqlConfig.php @@ -15,11 +15,6 @@ final class MysqlConfig implements DatabaseConfig { - public const int LIMIT_TINYTEXT = 255; - public const int LIMIT_TEXT = 65535; - public const int LIMIT_MEDIUMTEXT = 16777215; - public const int LIMIT_LONGTEXT = 4294967295; - public string $dsn { get => sprintf( 'mysql:host=%s:%s;dbname=%s', diff --git a/packages/database/src/Enums/DatabaseTextLength.php b/packages/database/src/Enums/DatabaseTextLength.php new file mode 100644 index 0000000000..e132b19323 --- /dev/null +++ b/packages/database/src/Enums/DatabaseTextLength.php @@ -0,0 +1,34 @@ + DatabaseTextLength::TINY, + $length <= DatabaseTextLength::DEFAULT => DatabaseTextLength::DEFAULT, + $length <= DatabaseTextLength::MEDIUM => DatabaseTextLength::MEDIUM, + $length <= DatabaseTextLength::LONG => DatabaseTextLength::LONG, + default => DatabaseTextLength::DEFAULT, + }; + } + + public function toString(): string + { + return match ($this) { + DatabaseTextLength::TINY => 'TINYTEXT', + DatabaseTextLength::DEFAULT => 'TEXT', + DatabaseTextLength::MEDIUM => 'MEDIUMTEXT', + DatabaseTextLength::LONG => 'LONGTEXT', + }; + } +} diff --git a/packages/database/src/QueryStatements/CreateTableStatement.php b/packages/database/src/QueryStatements/CreateTableStatement.php index a4b46ca6cf..ebd681fc7c 100644 --- a/packages/database/src/QueryStatements/CreateTableStatement.php +++ b/packages/database/src/QueryStatements/CreateTableStatement.php @@ -7,6 +7,7 @@ use BackedEnum; use Tempest\Database\Builder\TableDefinition; use Tempest\Database\Config\DatabaseDialect; +use Tempest\Database\Enums\DatabaseTextLength; use Tempest\Database\HasTrailingStatements; use Tempest\Database\QueryStatement; use Tempest\Support\Json; @@ -143,7 +144,7 @@ public function foreignKey(string $local, string $foreign, OnDelete $onDelete = /** * Adds a `TEXT` column to the table. */ - public function text(string $name, bool $nullable = false, ?string $default = null, ?int $length = null): self + public function text(string $name, bool $nullable = false, int|DatabaseTextLength $length = DatabaseTextLength::DEFAULT, ?string $default = null): self { $this->statements[] = new TextStatement( name: $name, diff --git a/packages/database/src/QueryStatements/TextStatement.php b/packages/database/src/QueryStatements/TextStatement.php index 0c9b81a864..88c5441584 100644 --- a/packages/database/src/QueryStatements/TextStatement.php +++ b/packages/database/src/QueryStatements/TextStatement.php @@ -5,7 +5,7 @@ namespace Tempest\Database\QueryStatements; use Tempest\Database\Config\DatabaseDialect; -use Tempest\Database\Config\MysqlConfig; +use Tempest\Database\Enums\DatabaseTextLength; use Tempest\Database\QueryStatement; final readonly class TextStatement implements QueryStatement @@ -13,8 +13,8 @@ public function __construct( private string $name, private bool $nullable = false, + private int|DatabaseTextLength $length = DatabaseTextLength::DEFAULT, private ?string $default = null, - private ?int $length = null, ) {} public function compile(DatabaseDialect $dialect): string @@ -35,16 +35,12 @@ public function compile(DatabaseDialect $dialect): string }; } - private function getSQLTypeDeclaration(?int $length = null): string + private function getSQLTypeDeclaration(int|DatabaseTextLength $length): string { - $type = match (true) { - $length <= MysqlConfig::LIMIT_TINYTEXT => 'TINYTEXT', - $length <= MysqlConfig::LIMIT_TEXT => 'TEXT', - $length <= MysqlConfig::LIMIT_MEDIUMTEXT => 'MEDIUMTEXT', - $length <= MysqlConfig::LIMIT_LONGTEXT => 'LONGTEXT', - default => 'TEXT', - }; + if ($length instanceof DatabaseTextLength) { + return $length->toString(); + } - return $type; + return DatabaseTextLength::fromLength($length)->toString(); } } diff --git a/tests/Integration/Database/QueryStatements/CreateTableStatementTest.php b/tests/Integration/Database/QueryStatements/CreateTableStatementTest.php index ff1783202e..0967b5ce24 100644 --- a/tests/Integration/Database/QueryStatements/CreateTableStatementTest.php +++ b/tests/Integration/Database/QueryStatements/CreateTableStatementTest.php @@ -8,6 +8,7 @@ use Tempest\Database\Config\DatabaseDialect; use Tempest\Database\Database; use Tempest\Database\DialectWasNotSupported; +use Tempest\Database\Enums\DatabaseTextLength; use Tempest\Database\Exceptions\DefaultValueWasInvalid; use Tempest\Database\Exceptions\ValueWasInvalid; use Tempest\Database\MigratesUp; @@ -238,19 +239,22 @@ public function test_string_method_with_custom_parameters(): void public function test_text_with_length_limit(): void { $tinyText = new CreateTableStatement('test-table') - ->text('content', false, null, 255) + ->text('content', false, null, DatabaseTextLength::TINY) ->compile(dialect: DatabaseDialect::MYSQL); $mediumText = new CreateTableStatement('test-table') - ->text('content', false, null, 65535) + ->text('content', false, null, DatabaseTextLength::DEFAULT) ->compile(dialect: DatabaseDialect::MYSQL); $text = new CreateTableStatement('test-table') - ->text('content', false, null, 16777215) + ->text('content', false, null, DatabaseTextLength::MEDIUM) ->compile(dialect: DatabaseDialect::MYSQL); $longText = new CreateTableStatement('test-table') - ->text('content', false, null, 4294967295) + ->text('content', false, null, DatabaseTextLength::LONG) ->compile(dialect: DatabaseDialect::MYSQL); $default = new CreateTableStatement('test-table') - ->text('content', false, null, null) + ->text('content', false, null) + ->compile(dialect: DatabaseDialect::MYSQL); + $enum = new CreateTableStatement('test-table') + ->text('content', false, null, 180) ->compile(dialect: DatabaseDialect::MYSQL); $this->assertStringContainsString('TINYTEXT', $tinyText); @@ -258,6 +262,7 @@ public function test_text_with_length_limit(): void $this->assertStringContainsString('TEXT', $text); $this->assertStringContainsString('LONGTEXT', $longText); $this->assertStringContainsString('TEXT', $default); + $this->assertStringContainsString('TINYTEXT', $enum); } public function test_object_field(): void From 1914bbc7cc8b8476a3e3c606c42ba60d4a763e67 Mon Sep 17 00:00:00 2001 From: MrYamous Date: Thu, 12 Mar 2026 19:37:12 +0100 Subject: [PATCH 4/4] feat(database): use different text type declaration with mysql according to field length --- .../QueryStatements/CreateTableStatementTest.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/Integration/Database/QueryStatements/CreateTableStatementTest.php b/tests/Integration/Database/QueryStatements/CreateTableStatementTest.php index 0967b5ce24..797df39c21 100644 --- a/tests/Integration/Database/QueryStatements/CreateTableStatementTest.php +++ b/tests/Integration/Database/QueryStatements/CreateTableStatementTest.php @@ -239,22 +239,22 @@ public function test_string_method_with_custom_parameters(): void public function test_text_with_length_limit(): void { $tinyText = new CreateTableStatement('test-table') - ->text('content', false, null, DatabaseTextLength::TINY) + ->text('content', false, DatabaseTextLength::TINY, null) ->compile(dialect: DatabaseDialect::MYSQL); $mediumText = new CreateTableStatement('test-table') - ->text('content', false, null, DatabaseTextLength::DEFAULT) + ->text('content', false, DatabaseTextLength::DEFAULT) ->compile(dialect: DatabaseDialect::MYSQL); $text = new CreateTableStatement('test-table') - ->text('content', false, null, DatabaseTextLength::MEDIUM) + ->text('content', false, DatabaseTextLength::MEDIUM) ->compile(dialect: DatabaseDialect::MYSQL); $longText = new CreateTableStatement('test-table') - ->text('content', false, null, DatabaseTextLength::LONG) + ->text('content', false, DatabaseTextLength::LONG) ->compile(dialect: DatabaseDialect::MYSQL); $default = new CreateTableStatement('test-table') - ->text('content', false, null) + ->text('content', false) ->compile(dialect: DatabaseDialect::MYSQL); - $enum = new CreateTableStatement('test-table') - ->text('content', false, null, 180) + $value = new CreateTableStatement('test-table') + ->text('content', false, 180) ->compile(dialect: DatabaseDialect::MYSQL); $this->assertStringContainsString('TINYTEXT', $tinyText); @@ -262,7 +262,7 @@ public function test_text_with_length_limit(): void $this->assertStringContainsString('TEXT', $text); $this->assertStringContainsString('LONGTEXT', $longText); $this->assertStringContainsString('TEXT', $default); - $this->assertStringContainsString('TINYTEXT', $enum); + $this->assertStringContainsString('TINYTEXT', $value); } public function test_object_field(): void