Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions packages/database/src/QueryStatements/IntegerStatement.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ public function compile(DatabaseDialect $dialect): string
{
$name = $dialect->quoteIdentifier($this->name);

$type = is_int($this->size)
? DatabaseIntegerSize::fromBytes($this->size)->toString()
: $this->size->toString();

return match ($dialect) {
DatabaseDialect::SQLITE => sprintf(
'%s INTEGER %s %s %s',
Expand All @@ -29,10 +33,18 @@ public function compile(DatabaseDialect $dialect): string
$this->default !== null ? "DEFAULT {$this->default}" : '',
$this->nullable ? '' : 'NOT NULL',
),
default => sprintf(
// Postgres has no unsigned integer type, so omit the keyword there.
DatabaseDialect::POSTGRESQL => sprintf(
'%s %s %s %s',
$name,
$type,
$this->default !== null ? "DEFAULT {$this->default}" : '',
$this->nullable ? '' : 'NOT NULL',
),
DatabaseDialect::MYSQL => sprintf(
'%s %s %s %s %s',
$name,
is_int($this->size) ? DatabaseIntegerSize::fromBytes($this->size)->toString() : $this->size->toString(),
$type,
$this->unsigned ? 'UNSIGNED' : '',
$this->default !== null ? "DEFAULT {$this->default}" : '',
$this->nullable ? '' : 'NOT NULL',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ public static function provide_fk_create_table_database_drivers(): Generator
<<<SQL
CREATE TABLE "books" (
"id" SERIAL PRIMARY KEY,
"author_id" INTEGER NOT NULL,
"author_id" INTEGER NOT NULL,
CONSTRAINT "fk_authors_books_author_id" FOREIGN KEY(author_id) REFERENCES authors(id) ON DELETE CASCADE ON UPDATE NO ACTION,
"name" VARCHAR(255) NOT NULL
);
Expand Down Expand Up @@ -165,7 +165,7 @@ public static function provide_fk_create_table_database_drivers_explicit(): Gene
<<<SQL
CREATE TABLE "books" (
"id" SERIAL PRIMARY KEY,
"author_id" INTEGER NOT NULL,
"author_id" INTEGER NOT NULL,
CONSTRAINT "fk_authors_books_author_id" FOREIGN KEY(author_id) REFERENCES authors(id) ON DELETE CASCADE ON UPDATE NO ACTION,
"name" VARCHAR(255) NOT NULL
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<?php

declare(strict_types=1);

namespace Tests\Tempest\Integration\Database\QueryStatements;

use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\Attributes\TestWith;
use Tempest\Database\Config\DatabaseDialect;
use Tempest\Database\MigratesUp;
use Tempest\Database\Migrations\CreateMigrationsTable;
use Tempest\Database\QueryStatement;
use Tempest\Database\QueryStatements\CreateTableStatement;
use Tempest\Database\QueryStatements\DatabaseIntegerSize;
use Tempest\Database\QueryStatements\IntegerStatement;
use Tests\Tempest\Integration\FrameworkIntegrationTestCase;

/**
* @internal
*/
final class IntegerStatementTest extends FrameworkIntegrationTestCase
{
#[Test]
public function unsigned_columns_are_valid_ddl(): void
{
$migration = new class() implements MigratesUp {
private(set) string $name = '0000_create_unsigned_integers_table';

public function up(): QueryStatement
{
return new CreateTableStatement('unsigned_integers')
->primary()
->integer('small', unsigned: true, size: DatabaseIntegerSize::SMALL)
->integer('regular', unsigned: true)
->integer('big', unsigned: true, size: DatabaseIntegerSize::BIG)
->integer('nullable_with_default', unsigned: true, nullable: true, default: 1);
}
};

$this->database->migrate(CreateMigrationsTable::class, $migration);

$this->expectNotToPerformAssertions();
}

#[Test]
#[TestWith([DatabaseDialect::MYSQL, true])]
#[TestWith([DatabaseDialect::SQLITE, true])]
#[TestWith([DatabaseDialect::POSTGRESQL, false])]
public function unsigned_is_only_emitted_on_dialects_that_have_it(DatabaseDialect $dialect, bool $expected): void
{
$statement = new IntegerStatement('votes', unsigned: true)->compile($dialect);

if ($expected) {
$this->assertStringContainsString('UNSIGNED', $statement);
} else {
$this->assertStringNotContainsString('UNSIGNED', $statement);
}
}

#[Test]
#[TestWith([DatabaseDialect::MYSQL])]
#[TestWith([DatabaseDialect::POSTGRESQL])]
public function the_size_chooses_the_type(DatabaseDialect $dialect): void
{
$this->assertStringContainsString(
'SMALLINT',
new IntegerStatement('n', size: DatabaseIntegerSize::SMALL)->compile($dialect),
);

$this->assertStringContainsString(
'BIGINT',
new IntegerStatement('n', size: DatabaseIntegerSize::BIG)->compile($dialect),
);

// A byte count is rounded up to the size that can hold it.
$this->assertStringContainsString(
'BIGINT',
new IntegerStatement('n', size: 8)->compile($dialect),
);
}
}
Loading