|
18 | 18 | use Cake\Console\ConsoleIo; |
19 | 19 | use Cake\Console\ConsoleOptionParser; |
20 | 20 | use Cake\Database\Connection; |
21 | | -use Cake\Database\Driver\Mysql; |
22 | | -use Cake\Database\Driver\Postgres; |
23 | | -use Cake\Database\Driver\Sqlite; |
24 | | -use Cake\Database\Driver\Sqlserver; |
25 | 21 | use Cake\Datasource\ConnectionManager; |
26 | 22 | use Cake\Event\EventDispatcherTrait; |
27 | 23 | use Migrations\Config\ConfigInterface; |
| 24 | +use Migrations\Db\Adapter\AdapterInterface; |
| 25 | +use Migrations\Db\Adapter\DirectActionInterface; |
28 | 26 | use Migrations\Migration\ManagerFactory; |
| 27 | +use RuntimeException; |
29 | 28 | use Throwable; |
30 | 29 |
|
31 | 30 | /** |
@@ -149,7 +148,15 @@ public function execute(Arguments $args, ConsoleIo $io): ?int |
149 | 148 | // Drop tables |
150 | 149 | $io->out(''); |
151 | 150 | if (!$dryRun) { |
152 | | - $this->dropTables($connection, $tablesToDrop, $io); |
| 151 | + $factory = new ManagerFactory([ |
| 152 | + 'plugin' => $args->getOption('plugin'), |
| 153 | + 'source' => $args->getOption('source'), |
| 154 | + 'connection' => $args->getOption('connection'), |
| 155 | + ]); |
| 156 | + $manager = $factory->createManager($io); |
| 157 | + $adapter = $manager->getEnvironment()->getAdapter(); |
| 158 | + |
| 159 | + $this->dropTables($adapter, $tablesToDrop, $io); |
153 | 160 | } else { |
154 | 161 | $io->info('DRY-RUN: Would drop ' . count($tablesToDrop) . ' table(s).'); |
155 | 162 | } |
@@ -182,104 +189,31 @@ protected function getTablesToDrop(Connection $connection): array |
182 | 189 | /** |
183 | 190 | * Drop tables with foreign key handling. |
184 | 191 | * |
185 | | - * @param \Cake\Database\Connection $connection Database connection |
| 192 | + * @param \Migrations\Db\Adapter\AdapterInterface $adapter The adapter |
186 | 193 | * @param array<string> $tables Tables to drop |
187 | 194 | * @param \Cake\Console\ConsoleIo $io Console IO |
188 | 195 | * @return void |
189 | 196 | */ |
190 | | - protected function dropTables(Connection $connection, array $tables, ConsoleIo $io): void |
| 197 | + protected function dropTables(AdapterInterface $adapter, array $tables, ConsoleIo $io): void |
191 | 198 | { |
192 | | - $driver = $connection->getDriver(); |
| 199 | + if (!$adapter instanceof DirectActionInterface) { |
| 200 | + throw new RuntimeException('The adapter must implement DirectActionInterface'); |
| 201 | + } |
193 | 202 |
|
194 | | - // For PostgreSQL and SQL Server, we need to drop foreign keys first |
195 | | - // or use CASCADE in the drop statement |
196 | | - if ($driver instanceof Postgres) { |
197 | | - foreach ($tables as $table) { |
198 | | - $quotedTable = $driver->quoteIdentifier($table); |
199 | | - $io->verbose("Dropping table: {$table}"); |
200 | | - $connection->execute("DROP TABLE IF EXISTS {$quotedTable} CASCADE"); |
201 | | - } |
202 | | - } elseif ($driver instanceof Sqlserver) { |
203 | | - // Drop all foreign key constraints first |
204 | | - $this->dropForeignKeyConstraints($connection, $tables, $io); |
| 203 | + $adapter->disableForeignKeyConstraints(); |
205 | 204 |
|
206 | | - // Then drop tables |
| 205 | + try { |
207 | 206 | foreach ($tables as $table) { |
208 | | - $quotedTable = $driver->quoteIdentifier($table); |
209 | 207 | $io->verbose("Dropping table: {$table}"); |
210 | | - $connection->execute("DROP TABLE IF EXISTS {$quotedTable}"); |
211 | | - } |
212 | | - } else { |
213 | | - // MySQL and SQLite support disabling foreign key checks |
214 | | - $this->setForeignKeyChecks($connection, false); |
215 | | - |
216 | | - try { |
217 | | - foreach ($tables as $table) { |
218 | | - $quotedTable = $driver->quoteIdentifier($table); |
219 | | - $io->verbose("Dropping table: {$table}"); |
220 | | - $connection->execute("DROP TABLE IF EXISTS {$quotedTable}"); |
221 | | - } |
222 | | - } finally { |
223 | | - $this->setForeignKeyChecks($connection, true); |
| 208 | + $adapter->dropTable($table); |
224 | 209 | } |
| 210 | + } finally { |
| 211 | + $adapter->enableForeignKeyConstraints(); |
225 | 212 | } |
226 | 213 |
|
227 | 214 | $io->success('Dropped ' . count($tables) . ' table(s).'); |
228 | 215 | } |
229 | 216 |
|
230 | | - /** |
231 | | - * Drop all foreign key constraints from the given tables. |
232 | | - * |
233 | | - * @param \Cake\Database\Connection $connection Database connection |
234 | | - * @param array<string> $tables Tables to process |
235 | | - * @param \Cake\Console\ConsoleIo $io Console IO |
236 | | - * @return void |
237 | | - */ |
238 | | - protected function dropForeignKeyConstraints(Connection $connection, array $tables, ConsoleIo $io): void |
239 | | - { |
240 | | - $driver = $connection->getDriver(); |
241 | | - |
242 | | - if (!$driver instanceof Sqlserver) { |
243 | | - return; |
244 | | - } |
245 | | - |
246 | | - // Query to find all foreign key constraints on the specified tables |
247 | | - $tableList = implode("','", array_map(fn($t) => addslashes($t), $tables)); |
248 | | - |
249 | | - $sql = "SELECT |
250 | | - fk.name AS constraint_name, |
251 | | - OBJECT_NAME(fk.parent_object_id) AS table_name |
252 | | - FROM sys.foreign_keys fk |
253 | | - WHERE OBJECT_NAME(fk.parent_object_id) IN ('{$tableList}')"; |
254 | | - |
255 | | - $result = $connection->execute($sql)->fetchAll('assoc'); |
256 | | - |
257 | | - foreach ($result as $row) { |
258 | | - $constraintName = $driver->quoteIdentifier($row['constraint_name']); |
259 | | - $tableName = $driver->quoteIdentifier($row['table_name']); |
260 | | - $io->verbose("Dropping foreign key: {$row['constraint_name']} on {$row['table_name']}"); |
261 | | - $connection->execute("ALTER TABLE {$tableName} DROP CONSTRAINT {$constraintName}"); |
262 | | - } |
263 | | - } |
264 | | - |
265 | | - /** |
266 | | - * Enable or disable foreign key checks. |
267 | | - * |
268 | | - * @param \Cake\Database\Connection $connection Database connection |
269 | | - * @param bool $enable Whether to enable or disable |
270 | | - * @return void |
271 | | - */ |
272 | | - protected function setForeignKeyChecks(Connection $connection, bool $enable): void |
273 | | - { |
274 | | - $driver = $connection->getDriver(); |
275 | | - |
276 | | - if ($driver instanceof Mysql) { |
277 | | - $connection->execute('SET FOREIGN_KEY_CHECKS = ' . ($enable ? '1' : '0')); |
278 | | - } elseif ($driver instanceof Sqlite) { |
279 | | - $connection->execute('PRAGMA foreign_keys = ' . ($enable ? 'ON' : 'OFF')); |
280 | | - } |
281 | | - } |
282 | | - |
283 | 217 | /** |
284 | 218 | * Run migrations and dispatch afterReset event. |
285 | 219 | * |
|
0 commit comments