packages/ztd-query-mysql/src/Shadow/Mutation/Table/Alter/OperationApplier.php
1<?php
2
3declare(strict_types=1);
4
5namespace ZtdQuery\Platform\MySql\Shadow\Mutation\Table\Alter;
6
7use PhpMyAdmin\SqlParser\Components\AlterOperation;
8use PhpMyAdmin\SqlParser\Statements\AlterStatement;
9use PhpMyAdmin\SqlParser\Statements\CreateStatement;
10use ZtdQuery\Exception\UnsupportedSqlException;
11use ZtdQuery\Schema\TableDefinition;
12use ZtdQuery\Schema\TableDefinitionRegistry;
13use ZtdQuery\Shadow\ShadowStore;
14
15/**
16 * Operation Applier.
17 *
18 * @visibility ZtdQuery\Platform\MySql
19 */
20final class OperationApplier
21{
22 /**
23 * Configure the dependencies used by this operation.
24 */
25 public function __construct(private AlterStatement $alterStatement, private TableDefinitionRegistry $registry, private string $tableName)
26 {
27 }
28 /**
29 * Apply a single ALTER operation to the CREATE statement.
30 * @throws UnsupportedSqlException
31 */
32 public function applyOperation(CreateStatement $createStmt, AlterOperation $op, ShadowStore $store, TableDefinition $definition): string
33 {
34 $options = $op->options;
35 if ($options->isEmpty()) {
36 return $this->tableName;
37 }
38
39 $columnAction = (new ColumnAction())->detect($op);
40 if ($columnAction !== null) {
41 $columns = new ColumnAlteration($this->alterStatement, $this->tableName);
42 match ($columnAction) {
43 'add' => $columns->applyAddColumn($createStmt, $op, $definition),
44 'drop' => $columns->applyDropColumn($createStmt, $op, $store, $definition),
45 'modify' => $columns->applyModifyColumn($createStmt, $op, $definition),
46 'change' => $columns->applyChangeColumn($createStmt, $op, $store, $definition),
47 };
48 return $this->tableName;
49 }
50 if (($options->has('RENAME') !== false) && ($options->has('TO') !== false) && !\ZtdQuery\Platform\MySql\Sql\Alter\OptionList::hasAny($options, ['INDEX', 'KEY', 'COLUMN'])) {
51 $this->applyRenameTable($op, $store);
52 } elseif (($options->has('ADD') !== false) && ($options->has('PRIMARY KEY') !== false)) {
53 (new PrimaryKeyAlteration())->applyAddPrimaryKey($createStmt, $op);
54 } elseif (($options->has('DROP') !== false) && ($options->has('PRIMARY KEY') !== false)) {
55 (new PrimaryKeyAlteration())->applyDropPrimaryKey($createStmt);
56 } elseif (($options->has('FOREIGN') !== false) && \ZtdQuery\Platform\MySql\Sql\Alter\OptionList::hasAny($options, ['ADD', 'DROP'])) {
57 return $this->tableName;
58 } elseif (($options->has('RENAME') !== false) && ($options->has('COLUMN') !== false)) {
59 (new ColumnAlteration($this->alterStatement, $this->tableName))->applyRenameColumn($createStmt, $op, $store, $definition);
60 } elseif (($options->has('ALTER') !== false) && (\ZtdQuery\Platform\MySql\Sql\Alter\OptionList::hasAny($options, ['SET DEFAULT', 'DROP DEFAULT']))) {
61 return $this->tableName;
62 } else {
63 throw new UnsupportedSqlException(AlterOperation::build($op), 'ALTER TABLE');
64 }
65 return $this->tableName;
66 }
67
68 /**
69 * Apply Rename Table for the supplied MySQL input.
70 */
71 public function applyRenameTable(AlterOperation $op, ShadowStore $store): void
72 {
73 $toValue = $op->options !== null ? $op->options->has('TO') : false;
74 if (!is_string($toValue) || $toValue === '') {
75 return;
76 }
77
78 $newName = (str_replace('`', '', $toValue));
79
80 $data = $store->get($this->tableName);
81 $store->set($newName, $data);
82 $store->set($this->tableName, []);
83
84 $existingDef = $this->registry->get($this->tableName);
85 if ($existingDef !== null) {
86 $this->registry->unregister($this->tableName);
87 $this->registry->register($newName, $existingDef);
88 }
89
90 $this->tableName = $newName;
91 }
92}
93