Skip to content

Commit 669f93f

Browse files
authored
Merge pull request #139 from simon-mundy/ddl-improvements-table
Ddl improvements table
2 parents 9e3ed29 + 571ccbe commit 669f93f

4 files changed

Lines changed: 334 additions & 8 deletions

File tree

‎src/Sql/Ddl/AlterTable.php‎

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,13 @@
66

77
use PhpDb\Adapter\Platform\PlatformInterface;
88
use PhpDb\Sql\AbstractSql;
9+
use PhpDb\Sql\Literal;
910
use PhpDb\Sql\TableIdentifier;
1011

1112
use function array_key_exists;
13+
use function is_bool;
14+
use function is_int;
15+
use function strtoupper;
1216

1317
class AlterTable extends AbstractSql
1418
{
@@ -26,6 +30,8 @@ class AlterTable extends AbstractSql
2630

2731
final public const TABLE = 'table';
2832

33+
final public const TABLE_OPTIONS = 'tableOptions';
34+
2935
protected array $addColumns = [];
3036

3137
protected array $addConstraints = [];
@@ -38,6 +44,8 @@ class AlterTable extends AbstractSql
3844

3945
protected array $dropIndexes = [];
4046

47+
protected array $options = [];
48+
4149
/**
4250
* Specifications for Sql String generation
4351
*/
@@ -73,6 +81,11 @@ class AlterTable extends AbstractSql
7381
[1 => "DROP INDEX %1\$s,\n", 'combinedby' => ''],
7482
],
7583
],
84+
self::TABLE_OPTIONS => [
85+
"%1\$s" => [
86+
[1 => "%1\$s,\n", 'combinedby' => ''],
87+
],
88+
],
7689
];
7790

7891
protected string|TableIdentifier $table = '';
@@ -136,6 +149,23 @@ public function dropIndex(string $name): static
136149
return $this;
137150
}
138151

152+
public function setOption(string $name, Literal|bool|int|string $value): static
153+
{
154+
$this->options[$name] = $value;
155+
return $this;
156+
}
157+
158+
public function setOptions(array $options): static
159+
{
160+
$this->options = $options;
161+
return $this;
162+
}
163+
164+
public function getOptions(): array
165+
{
166+
return $this->options;
167+
}
168+
139169
public function getRawState(?string $key = null): array|string
140170
{
141171
$rawState = [
@@ -146,6 +176,7 @@ public function getRawState(?string $key = null): array|string
146176
self::ADD_CONSTRAINTS => $this->addConstraints,
147177
self::DROP_CONSTRAINTS => $this->dropConstraints,
148178
self::DROP_INDEXES => $this->dropIndexes,
179+
self::TABLE_OPTIONS => $this->options,
149180
];
150181

151182
return isset($key) && array_key_exists($key, $rawState) ? $rawState[$key] : $rawState;
@@ -243,4 +274,31 @@ protected function processDropIndexes(?PlatformInterface $adapterPlatform = null
243274

244275
return [$sqls];
245276
}
277+
278+
/**
279+
* @return string[][]|null
280+
*/
281+
protected function processTableOptions(?PlatformInterface $adapterPlatform = null): ?array
282+
{
283+
if (! $this->options) {
284+
return null;
285+
}
286+
287+
$sqls = [];
288+
foreach ($this->options as $key => $value) {
289+
$key = strtoupper($key);
290+
if ($value instanceof Literal) {
291+
$value = $value->getLiteral();
292+
} elseif (is_bool($value)) {
293+
$value = $value ? '1' : '0';
294+
} elseif (is_int($value)) {
295+
$value = (string) $value;
296+
} else {
297+
$value = $adapterPlatform->quoteTrustedValue($value);
298+
}
299+
$sqls[] = $key . ' = ' . $value;
300+
}
301+
302+
return [$sqls];
303+
}
246304
}

‎src/Sql/Ddl/CreateTable.php‎

Lines changed: 63 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,14 @@
66

77
use PhpDb\Adapter\Platform\PlatformInterface;
88
use PhpDb\Sql\AbstractSql;
9+
use PhpDb\Sql\Literal;
910
use PhpDb\Sql\TableIdentifier;
1011

1112
use function array_key_exists;
13+
use function implode;
14+
use function is_bool;
15+
use function is_int;
16+
use function strtoupper;
1217

1318
class CreateTable extends AbstractSql
1419
{
@@ -18,6 +23,8 @@ class CreateTable extends AbstractSql
1823

1924
final public const TABLE = 'table';
2025

26+
final public const TABLE_OPTIONS = 'tableOptions';
27+
2128
protected array $columns = [];
2229

2330
protected array $constraints = [];
@@ -26,23 +33,26 @@ class CreateTable extends AbstractSql
2633

2734
protected bool $isTemporary = false;
2835

36+
protected array $options = [];
37+
2938
/**
3039
* {@inheritDoc}
3140
*/
3241
protected array $specifications = [
33-
self::TABLE => 'CREATE %1$sTABLE %2$s%3$s (',
34-
self::COLUMNS => [
42+
self::TABLE => 'CREATE %1$sTABLE %2$s%3$s (',
43+
self::COLUMNS => [
3544
"\n %1\$s" => [
3645
[1 => '%1$s', 'combinedby' => ",\n "],
3746
],
3847
],
39-
'combinedBy' => ',',
40-
self::CONSTRAINTS => [
48+
'combinedBy' => ',',
49+
self::CONSTRAINTS => [
4150
"\n %1\$s" => [
4251
[1 => '%1$s', 'combinedby' => ",\n "],
4352
],
4453
],
45-
'statementEnd' => '%1$s',
54+
'statementEnd' => '%1$s',
55+
self::TABLE_OPTIONS => '%1$s',
4656
];
4757

4858
protected string|TableIdentifier $table = '';
@@ -93,16 +103,34 @@ public function addConstraint(Constraint\ConstraintInterface $constraint): stati
93103
return $this;
94104
}
95105

106+
public function setOption(string $name, Literal|bool|int|string $value): static
107+
{
108+
$this->options[$name] = $value;
109+
return $this;
110+
}
111+
112+
public function setOptions(array $options): static
113+
{
114+
$this->options = $options;
115+
return $this;
116+
}
117+
118+
public function getOptions(): array
119+
{
120+
return $this->options;
121+
}
122+
96123
/**
97124
* @return ((Column\ColumnInterface|string)[]|Column\ColumnInterface|string)[]|string
98125
* @psalm-return array<Column\ColumnInterface|array<Column\ColumnInterface|string>|string>|string
99126
*/
100127
public function getRawState(?string $key = null): array|string
101128
{
102129
$rawState = [
103-
self::COLUMNS => $this->columns,
104-
self::CONSTRAINTS => $this->constraints,
105-
self::TABLE => $this->table,
130+
self::COLUMNS => $this->columns,
131+
self::CONSTRAINTS => $this->constraints,
132+
self::TABLE => $this->table,
133+
self::TABLE_OPTIONS => $this->options,
106134
];
107135

108136
return isset($key) && array_key_exists($key, $rawState) ? $rawState[$key] : $rawState;
@@ -172,4 +200,31 @@ protected function processStatementEnd(?PlatformInterface $adapterPlatform = nul
172200
{
173201
return ["\n)"];
174202
}
203+
204+
/**
205+
* @return string[]|null
206+
*/
207+
protected function processTableOptions(?PlatformInterface $adapterPlatform = null): ?array
208+
{
209+
if (! $this->options) {
210+
return null;
211+
}
212+
213+
$parts = [];
214+
foreach ($this->options as $key => $value) {
215+
$key = strtoupper($key);
216+
if ($value instanceof Literal) {
217+
$value = $value->getLiteral();
218+
} elseif (is_bool($value)) {
219+
$value = $value ? '1' : '0';
220+
} elseif (is_int($value)) {
221+
$value = (string) $value;
222+
} else {
223+
$value = $adapterPlatform->quoteTrustedValue($value);
224+
}
225+
$parts[] = $key . ' = ' . $value;
226+
}
227+
228+
return [implode(' ', $parts)];
229+
}
175230
}

‎test/unit/Sql/Ddl/AlterTableTest.php‎

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use PhpDb\Sql\Ddl\Column\ColumnInterface;
1010
use PhpDb\Sql\Ddl\Constraint;
1111
use PhpDb\Sql\Ddl\Constraint\ConstraintInterface;
12+
use PhpDb\Sql\Literal;
1213
use PhpDb\Sql\TableIdentifier;
1314
use PHPUnit\Framework\Attributes\CoversMethod;
1415
use PHPUnit\Framework\TestCase;
@@ -31,6 +32,10 @@
3132
#[CoversMethod(AlterTable::class, 'processAddConstraints')]
3233
#[CoversMethod(AlterTable::class, 'processDropConstraints')]
3334
#[CoversMethod(AlterTable::class, 'processDropIndexes')]
35+
#[CoversMethod(AlterTable::class, 'setOption')]
36+
#[CoversMethod(AlterTable::class, 'setOptions')]
37+
#[CoversMethod(AlterTable::class, 'getOptions')]
38+
#[CoversMethod(AlterTable::class, 'processTableOptions')]
3439
class AlterTableTest extends TestCase
3540
{
3641
public function testSetTable(): void
@@ -346,4 +351,99 @@ public function testTableIdentifierInChangeColumn(): void
346351
self::assertStringContainsString('"schema"."table"', $sql);
347352
self::assertStringContainsString('CHANGE COLUMN "col1" "col1_new"', $sql);
348353
}
354+
355+
public function testSetOptionFluentInterface(): void
356+
{
357+
$at = new AlterTable('foo');
358+
$result = $at->setOption('engine', new Literal('InnoDB'));
359+
360+
self::assertSame($at, $result);
361+
self::assertEquals(['engine' => new Literal('InnoDB')], $at->getOptions());
362+
}
363+
364+
public function testSetOptionsReplacesAll(): void
365+
{
366+
$at = new AlterTable('foo');
367+
$at->setOption('engine', new Literal('InnoDB'));
368+
369+
$at->setOptions(['charset' => new Literal('utf8mb4')]);
370+
371+
self::assertEquals(['charset' => new Literal('utf8mb4')], $at->getOptions());
372+
}
373+
374+
public function testGetOptionsReturnsEmpty(): void
375+
{
376+
$at = new AlterTable('foo');
377+
self::assertEquals([], $at->getOptions());
378+
}
379+
380+
public function testGetRawStateIncludesTableOptions(): void
381+
{
382+
$at = new AlterTable('foo');
383+
$at->setOption('engine', new Literal('InnoDB'));
384+
385+
$rawState = $at->getRawState();
386+
387+
self::assertArrayHasKey(AlterTable::TABLE_OPTIONS, $rawState);
388+
self::assertEquals(['engine' => new Literal('InnoDB')], $rawState[AlterTable::TABLE_OPTIONS]);
389+
}
390+
391+
public function testGetSqlStringWithEngineOption(): void
392+
{
393+
$at = new AlterTable('foo');
394+
$at->setOption('engine', new Literal('InnoDB'));
395+
396+
$sql = $at->getSqlString();
397+
self::assertStringContainsString('ALTER TABLE "foo"', $sql);
398+
self::assertStringContainsString('ENGINE = InnoDB', $sql);
399+
}
400+
401+
public function testGetSqlStringWithColumnAndEngineOption(): void
402+
{
403+
$at = new AlterTable('foo');
404+
$at->addColumn(new Column\Column('bar'));
405+
$at->setOption('engine', new Literal('InnoDB'));
406+
407+
$sql = $at->getSqlString();
408+
self::assertStringContainsString('ADD COLUMN "bar" INTEGER NOT NULL', $sql);
409+
self::assertStringContainsString('ENGINE = InnoDB', $sql);
410+
}
411+
412+
public function testGetSqlStringWithStringOption(): void
413+
{
414+
$at = new AlterTable('foo');
415+
$at->setOption('comment', 'My table');
416+
417+
$sql = $at->getSqlString();
418+
self::assertStringContainsString('COMMENT = \'My table\'', $sql);
419+
}
420+
421+
public function testGetSqlStringWithIntOption(): void
422+
{
423+
$at = new AlterTable('foo');
424+
$at->setOption('auto_increment', 100);
425+
426+
$sql = $at->getSqlString();
427+
self::assertStringContainsString('AUTO_INCREMENT = 100', $sql);
428+
}
429+
430+
public function testGetSqlStringWithBoolOption(): void
431+
{
432+
$at = new AlterTable('foo');
433+
$at->setOption('pack_keys', true);
434+
435+
$sql = $at->getSqlString();
436+
self::assertStringContainsString('PACK_KEYS = 1', $sql);
437+
}
438+
439+
public function testGetSqlStringWithMultipleOptions(): void
440+
{
441+
$at = new AlterTable('foo');
442+
$at->setOption('engine', new Literal('InnoDB'));
443+
$at->setOption('auto_increment', 100);
444+
445+
$sql = $at->getSqlString();
446+
self::assertStringContainsString('ENGINE = InnoDB', $sql);
447+
self::assertStringContainsString('AUTO_INCREMENT = 100', $sql);
448+
}
349449
}

0 commit comments

Comments
 (0)