diff --git a/src/BaseSeed.php b/src/BaseSeed.php index a9d909244..8d115ef2f 100644 --- a/src/BaseSeed.php +++ b/src/BaseSeed.php @@ -204,7 +204,9 @@ public function shouldExecute(): bool public function call(string $seeder, array $options = []): void { $io = $this->getIo(); - assert($io !== null, 'Requires ConsoleIo'); + if ($io === null) { + throw new RuntimeException('ConsoleIo is required for calling other seeders.'); + } $io->out(''); $io->out( ' ====' . @@ -245,7 +247,9 @@ protected function runCall(string $seeder, array $options = []): void 'connection' => $options['connection'] ?? $connection, ]); $io = $this->getIo(); - assert($io !== null, 'Missing ConsoleIo instance'); + if ($io === null) { + throw new RuntimeException('ConsoleIo is required for running seeders.'); + } $manager = $factory->createManager($io); $manager->seed($seeder); } diff --git a/src/Command/DumpCommand.php b/src/Command/DumpCommand.php index 0e694b41c..53c79026e 100644 --- a/src/Command/DumpCommand.php +++ b/src/Command/DumpCommand.php @@ -141,7 +141,7 @@ public function execute(Arguments $args, ConsoleIo $io): ?int return self::CODE_SUCCESS; } - $io->error("An error occurred while writing dump file `{$filePath}`"); + $io->err("An error occurred while writing dump file `{$filePath}`"); return self::CODE_ERROR; } diff --git a/src/Db/Adapter/MysqlAdapter.php b/src/Db/Adapter/MysqlAdapter.php index 76b71f4dc..b00048885 100644 --- a/src/Db/Adapter/MysqlAdapter.php +++ b/src/Db/Adapter/MysqlAdapter.php @@ -612,7 +612,9 @@ protected function getRenameColumnInstructions(string $tableName, string $column foreach ($rows as $row) { if (strcasecmp($row['Field'], $columnName) === 0) { $null = $row['Null'] === 'NO' ? 'NOT NULL' : 'NULL'; - $comment = isset($row['Comment']) ? ' COMMENT ' . '\'' . addslashes($row['Comment']) . '\'' : ''; + $comment = isset($row['Comment']) && $row['Comment'] !== '' + ? ' COMMENT ' . $this->getConnection()->getDriver()->schemaValue($row['Comment']) + : ''; // create the extra string by also filtering out the DEFAULT_GENERATED option (MySQL 8 fix) $extras = array_filter( diff --git a/src/Db/Adapter/PostgresAdapter.php b/src/Db/Adapter/PostgresAdapter.php index e77e7a445..bb204b688 100644 --- a/src/Db/Adapter/PostgresAdapter.php +++ b/src/Db/Adapter/PostgresAdapter.php @@ -972,7 +972,11 @@ public function getPhinxType(string $sqlType): string public function createDatabase(string $name, array $options = []): void { $charset = $options['charset'] ?? 'utf8'; - $this->execute(sprintf("CREATE DATABASE %s WITH ENCODING = '%s'", $name, $charset)); + $this->execute(sprintf( + 'CREATE DATABASE %s WITH ENCODING = %s', + $this->quoteSchemaName($name), + $this->quoteString($charset), + )); } /** @@ -995,7 +999,7 @@ public function hasDatabase(string $name): bool public function dropDatabase($name): void { $this->disconnect(); - $this->execute(sprintf('DROP DATABASE IF EXISTS %s', $name)); + $this->execute(sprintf('DROP DATABASE IF EXISTS %s', $this->quoteSchemaName($name))); $this->createdTables = []; $this->connect(); } @@ -1091,10 +1095,11 @@ protected function getForeignKeySqlDefinition(ForeignKey $foreignKey, string $ta $constraintName = $foreignKey->getName() ?: ( $parts['table'] . '_' . implode('_', $foreignKey->getColumns()) . '_fkey' ); + $columnList = implode(', ', array_map($this->quoteColumnName(...), $foreignKey->getColumns())); + $refColumnList = implode(', ', array_map($this->quoteColumnName(...), $foreignKey->getReferencedColumns())); $def = ' CONSTRAINT ' . $this->quoteColumnName($constraintName) . - ' FOREIGN KEY ("' . implode('", "', $foreignKey->getColumns()) . '")' . - " REFERENCES {$this->quoteTableName($foreignKey->getReferencedTable()->getName())} (\"" . - implode('", "', $foreignKey->getReferencedColumns()) . '")'; + ' FOREIGN KEY (' . $columnList . ')' . + ' REFERENCES ' . $this->quoteTableName($foreignKey->getReferencedTable()->getName()) . ' (' . $refColumnList . ')'; if ($foreignKey->getOnDelete()) { $def .= " ON DELETE {$foreignKey->getOnDelete()}"; } diff --git a/src/Db/Adapter/SqlserverAdapter.php b/src/Db/Adapter/SqlserverAdapter.php index 32d662ee5..ec7bf4865 100644 --- a/src/Db/Adapter/SqlserverAdapter.php +++ b/src/Db/Adapter/SqlserverAdapter.php @@ -248,9 +248,9 @@ protected function getRenameTableInstructions(string $tableName, string $newTabl { $this->updateCreatedTableName($tableName, $newTableName); $sql = sprintf( - "EXEC sp_rename '%s', '%s'", - $tableName, - $newTableName, + 'EXEC sp_rename %s, %s', + $this->quoteString($tableName), + $this->quoteString($newTableName), ); return new AlterInstructions([], [$sql]); @@ -404,23 +404,21 @@ protected function getRenameColumnInstructions(string $tableName, string $column $oldConstraintName = "DF_{$tableName}_{$columnName}"; $newConstraintName = "DF_{$tableName}_{$newColumnName}"; - $sql = <<addPostStep(sprintf( - $sql, - $oldConstraintName, - $newConstraintName, - )); + EXECUTE sp_rename %s, %s, N\'OBJECT\' +END', + $this->quoteString($oldConstraintName), + $this->quoteString($oldConstraintName), + $this->quoteString($newConstraintName), + ); + $instructions->addPostStep($sql); $instructions->addPostStep(sprintf( - "EXECUTE sp_rename N'%s.%s', N'%s', 'COLUMN' ", - $tableName, - $columnName, - $newColumnName, + 'EXECUTE sp_rename %s, %s, N\'COLUMN\'', + $this->quoteString($tableName . '.' . $columnName), + $this->quoteString($newColumnName), )); return $instructions; @@ -970,12 +968,17 @@ public function getPhinxType(string $sqlType): string */ public function createDatabase(string $name, array $options = []): void { + $quotedName = $this->quoteSchemaName($name); if (isset($options['collation'])) { - $this->execute(sprintf('CREATE DATABASE [%s] COLLATE [%s]', $name, $options['collation'])); + $this->execute(sprintf( + 'CREATE DATABASE %s COLLATE %s', + $quotedName, + $this->quoteSchemaName($options['collation']), + )); } else { - $this->execute(sprintf('CREATE DATABASE [%s]', $name)); + $this->execute(sprintf('CREATE DATABASE %s', $quotedName)); } - $this->execute(sprintf('USE [%s]', $name)); + $this->execute(sprintf('USE %s', $quotedName)); } /** @@ -997,12 +1000,16 @@ public function hasDatabase(string $name): bool */ public function dropDatabase(string $name): void { - $sql = <<quoteSchemaName($name); + $sql = sprintf( + 'USE master; +IF EXISTS(select * from sys.databases where name=%s) +ALTER DATABASE %s SET SINGLE_USER WITH ROLLBACK IMMEDIATE; +DROP DATABASE %s;', + $this->quoteString($name), + $quotedName, + $quotedName, + ); $this->execute($sql); $this->createdTables = []; } @@ -1061,10 +1068,12 @@ protected function getIndexSqlDefinition(Index $index, string $tableName): strin protected function getForeignKeySqlDefinition(ForeignKey $foreignKey, string $tableName): string { $constraintName = $foreignKey->getName() ?: $tableName . '_' . implode('_', $foreignKey->getColumns()); + $columnList = implode(', ', array_map($this->quoteColumnName(...), $foreignKey->getColumns())); + $refColumnList = implode(', ', array_map($this->quoteColumnName(...), $foreignKey->getReferencedColumns())); $def = ' CONSTRAINT ' . $this->quoteColumnName($constraintName); - $def .= ' FOREIGN KEY ("' . implode('", "', $foreignKey->getColumns()) . '")'; - $def .= " REFERENCES {$this->quoteTableName($foreignKey->getReferencedTable()->getName())} (\"" . implode('", "', $foreignKey->getReferencedColumns()) . '")'; + $def .= ' FOREIGN KEY (' . $columnList . ')'; + $def .= ' REFERENCES ' . $this->quoteTableName($foreignKey->getReferencedTable()->getName()) . ' (' . $refColumnList . ')'; if ($foreignKey->getOnDelete()) { $def .= " ON DELETE {$foreignKey->getOnDelete()}"; } diff --git a/src/Db/Table.php b/src/Db/Table.php index eb2e29b93..d1c8a34ea 100644 --- a/src/Db/Table.php +++ b/src/Db/Table.php @@ -793,7 +793,7 @@ public function saveData(): void $c = array_keys($row); foreach ($this->getData() as $row) { $k = array_keys($row); - if ($k != $c) { + if ($k !== $c) { $bulk = false; break; } diff --git a/src/Migrations.php b/src/Migrations.php index 993136f23..b889667c3 100644 --- a/src/Migrations.php +++ b/src/Migrations.php @@ -64,7 +64,7 @@ class Migrations * * @var string */ - protected string $command; + protected string $command = ''; /** * Stub input to feed the manager class since we might not have an input ready when we get the Manager using diff --git a/src/TestSuite/Migrator.php b/src/TestSuite/Migrator.php index 598a0780f..6f2400d50 100644 --- a/src/TestSuite/Migrator.php +++ b/src/TestSuite/Migrator.php @@ -199,7 +199,7 @@ protected function shouldDropTables(Migrations $migrations, array $options): boo if (!empty($messages['missing'])) { $hasProblems = true; $output[] = 'Applied but missing migrations:'; - $output = array_merge($output, array_map($itemize, $messages['down'])); + $output = array_merge($output, array_map($itemize, $messages['missing'])); $output[] = ''; } if ($output) {