Skip to content

Commit f0db5c8

Browse files
MrYamousbrendt
andauthored
feat(database): add set data type (#725)
Co-authored-by: Brent Roose <[email protected]>
1 parent 5fa27bc commit f0db5c8

File tree

4 files changed

+136
-0
lines changed

4 files changed

+136
-0
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tempest\Database\Exceptions;
6+
7+
use Exception;
8+
9+
final class InvalidValue extends Exception
10+
{
11+
public function __construct(string $field, string $value)
12+
{
13+
parent::__construct("Value '{$value}' provided for {$field} is not valid");
14+
}
15+
}

src/Tempest/Database/src/QueryStatements/CreateTableStatement.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,22 @@ public function json(
180180
return $this;
181181
}
182182

183+
public function set(
184+
string $name,
185+
array $values,
186+
bool $nullable = false,
187+
?string $default = null
188+
): self {
189+
$this->statements[] = new SetStatement(
190+
name: $name,
191+
values: $values,
192+
nullable: $nullable,
193+
default: $default,
194+
);
195+
196+
return $this;
197+
}
198+
183199
public function compile(DatabaseDialect $dialect): string
184200
{
185201
$compiled = sprintf(
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tempest\Database\QueryStatements;
6+
7+
use Tempest\Database\DatabaseDialect;
8+
use Tempest\Database\Exceptions\InvalidValue;
9+
use Tempest\Database\QueryStatement;
10+
use Tempest\Database\UnsupportedDialect;
11+
12+
final readonly class SetStatement implements QueryStatement
13+
{
14+
public function __construct(
15+
private string $name,
16+
private array $values,
17+
private bool $nullable = false,
18+
private ?string $default = null,
19+
) {
20+
}
21+
22+
public function compile(DatabaseDialect $dialect): string
23+
{
24+
if (empty($this->values)) {
25+
throw new InvalidValue($this->name, json_encode($this->values));
26+
}
27+
28+
return match($dialect) {
29+
DatabaseDialect::MYSQL => sprintf(
30+
'`%s` SET (%s) %s %s',
31+
$this->name,
32+
"'" . implode("', '", $this->values) . "'",
33+
$this->default ? "DEFAULT '$this->default'" : '',
34+
$this->nullable ? '' : 'NOT NULL',
35+
),
36+
default => throw new UnsupportedDialect()
37+
};
38+
}
39+
}

tests/Integration/Database/QueryStatements/CreateTableStatementTest.php

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,14 @@
44

55
namespace Tests\Tempest\Integration\Database\QueryStatements;
66

7+
use Tempest\Database\DatabaseDialect;
78
use Tempest\Database\Exceptions\InvalidDefaultValue;
9+
use Tempest\Database\Exceptions\InvalidValue;
810
use Tempest\Database\Migration;
911
use Tempest\Database\Migrations\CreateMigrationsTable;
1012
use Tempest\Database\QueryStatement;
1113
use Tempest\Database\QueryStatements\CreateTableStatement;
14+
use Tempest\Database\UnsupportedDialect;
1215
use Tests\Tempest\Integration\FrameworkIntegrationTestCase;
1316

1417
/**
@@ -53,6 +56,40 @@ public function down(): QueryStatement|null
5356
$this->assertTrue(true);
5457
}
5558

59+
public function test_set_statement(): void
60+
{
61+
$migration = new class () implements Migration {
62+
public function getName(): string
63+
{
64+
return '0';
65+
}
66+
67+
public function up(): QueryStatement|null
68+
{
69+
return (new CreateTableStatement('table'))
70+
->set('set', values: ['foo', 'bar'], default: 'foo');
71+
}
72+
73+
public function down(): QueryStatement|null
74+
{
75+
return null;
76+
}
77+
};
78+
79+
match($this->container->get(DatabaseDialect::class)) {
80+
DatabaseDialect::MYSQL => '',
81+
DatabaseDialect::SQLITE => $this->expectException(UnsupportedDialect::class),
82+
DatabaseDialect::POSTGRESQL => $this->expectException(UnsupportedDialect::class),
83+
};
84+
85+
$this->migrate(
86+
CreateMigrationsTable::class,
87+
$migration
88+
);
89+
90+
$this->assertTrue(true);
91+
}
92+
5693
public function test_invalid_json_default(): void
5794
{
5895
$migration = new class () implements Migration {
@@ -81,4 +118,33 @@ public function down(): QueryStatement|null
81118
$migration
82119
);
83120
}
121+
122+
public function test_invalid_set_values(): void
123+
{
124+
$migration = new class () implements Migration {
125+
public function getName(): string
126+
{
127+
return '0';
128+
}
129+
130+
public function up(): QueryStatement|null
131+
{
132+
return (new CreateTableStatement('table'))
133+
->set('set', values: []);
134+
}
135+
136+
public function down(): QueryStatement|null
137+
{
138+
return null;
139+
}
140+
};
141+
142+
$this->expectException(InvalidValue::class);
143+
$this->expectExceptionMessage("Value '[]' provided for set is not valid");
144+
145+
$this->migrate(
146+
CreateMigrationsTable::class,
147+
$migration
148+
);
149+
}
84150
}

0 commit comments

Comments
 (0)