diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 362adcc8..ed5f2611 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -96,6 +96,12 @@ parameters: count: 1 path: src/Db/Adapter/SqliteAdapter.php + - + message: '#^Strict comparison using \!\=\= between Cake\\Database\\StatementInterface and null will always evaluate to true\.$#' + identifier: notIdentical.alwaysTrue + count: 1 + path: src/Db/Adapter/SqliteAdapter.php + - message: '#^PHPDoc tag @return with type Phinx\\Db\\Adapter\\AdapterInterface is not subtype of native type Migrations\\Db\\Adapter\\AdapterInterface\.$#' identifier: return.phpDocType diff --git a/src/Db/Adapter/MysqlAdapter.php b/src/Db/Adapter/MysqlAdapter.php index 4d260e20..69618b57 100644 --- a/src/Db/Adapter/MysqlAdapter.php +++ b/src/Db/Adapter/MysqlAdapter.php @@ -751,19 +751,22 @@ public function hasPrimaryKey(string $tableName, $columns, ?string $constraint = public function getPrimaryKey(string $tableName): array { $options = $this->getOptions(); - $rows = $this->fetchAll(sprintf( + $params = [ + $options['database'], + $tableName, + ]; + $rows = $this->query( "SELECT k.CONSTRAINT_NAME, k.COLUMN_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS t JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE k USING(CONSTRAINT_NAME,TABLE_SCHEMA,TABLE_NAME) - WHERE t.CONSTRAINT_TYPE='PRIMARY KEY' - AND t.TABLE_SCHEMA='%s' - AND t.TABLE_NAME='%s'", - $options['database'], - $tableName - )); + WHERE t.CONSTRAINT_TYPE = 'PRIMARY KEY' + AND t.TABLE_SCHEMA = ? + AND t.TABLE_NAME = ?", + $params + )->fetchAll('assoc'); $primaryKey = [ 'columns' => [], @@ -809,26 +812,33 @@ public function hasForeignKey(string $tableName, $columns, ?string $constraint = */ protected function getForeignKeys(string $tableName): array { + $schema = null; if (strpos($tableName, '.') !== false) { [$schema, $tableName] = explode('.', $tableName); } - $foreignKeys = []; - $rows = $this->fetchAll(sprintf( - "SELECT + $params = []; + $query = "SELECT CONSTRAINT_NAME, CONCAT(TABLE_SCHEMA, '.', TABLE_NAME) AS TABLE_NAME, COLUMN_NAME, CONCAT(REFERENCED_TABLE_SCHEMA, '.', REFERENCED_TABLE_NAME) AS REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME FROM information_schema.KEY_COLUMN_USAGE - WHERE REFERENCED_TABLE_NAME IS NOT NULL - AND TABLE_SCHEMA = %s - AND TABLE_NAME = '%s' - ORDER BY POSITION_IN_UNIQUE_CONSTRAINT", - empty($schema) ? 'DATABASE()' : "'$schema'", - $tableName - )); + WHERE REFERENCED_TABLE_NAME IS NOT NULL"; + + if ($schema) { + $query .= ' AND TABLE_SCHEMA = ?'; + $params[] = $schema; + } else { + $query .= ' AND TABLE_SCHEMA = DATABASE()'; + } + + $query .= ' AND TABLE_NAME = ? ORDER BY POSITION_IN_UNIQUE_CONSTRAINT'; + $params[] = $tableName; + + $foreignKeys = []; + $rows = $this->query($query, $params)->fetchAll('assoc'); foreach ($rows as $row) { $foreignKeys[$row['CONSTRAINT_NAME']]['table'] = $row['TABLE_NAME']; $foreignKeys[$row['CONSTRAINT_NAME']]['columns'][] = $row['COLUMN_NAME']; @@ -1270,12 +1280,10 @@ public function createDatabase(string $name, array $options = []): void */ public function hasDatabase(string $name): bool { - $rows = $this->fetchAll( - sprintf( - 'SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = \'%s\'', - $name - ) - ); + $rows = $this->query( + 'SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = ?', + [$name] + )->fetchAll('assoc'); foreach ($rows as $row) { if (!empty($row)) { @@ -1470,16 +1478,13 @@ public function describeTable(string $tableName): array $options = $this->getOptions(); // mysql specific - $sql = sprintf( - "SELECT * + $sql = "SELECT * FROM information_schema.tables - WHERE table_schema = '%s' - AND table_name = '%s'", - $options['database'], - $tableName - ); + WHERE table_schema = ? + AND table_name = ?"; + $params = [$options['database'], $tableName]; - $table = $this->fetchRow($sql); + $table = $this->query($sql, $params)->fetch('assoc'); return $table !== false ? $table : []; } diff --git a/src/Db/Adapter/PdoAdapter.php b/src/Db/Adapter/PdoAdapter.php index b1d4452d..e5d0c068 100644 --- a/src/Db/Adapter/PdoAdapter.php +++ b/src/Db/Adapter/PdoAdapter.php @@ -479,31 +479,33 @@ public function migrated(MigrationInterface $migration, string $direction, strin if (strcasecmp($direction, MigrationInterface::UP) === 0) { // up $sql = sprintf( - "INSERT INTO %s (%s, %s, %s, %s, %s) VALUES ('%s', '%s', '%s', '%s', %s);", + 'INSERT INTO %s (%s, %s, %s, %s, %s) VALUES (?, ?, ?, ?, ?);', $this->quoteTableName($this->getSchemaTableName()), $this->quoteColumnName('version'), $this->quoteColumnName('migration_name'), $this->quoteColumnName('start_time'), $this->quoteColumnName('end_time'), $this->quoteColumnName('breakpoint'), + ); + $params = [ $migration->getVersion(), substr($migration->getName(), 0, 100), $startTime, $endTime, - $this->castToBool(false) - ); + $this->castToBool(false), + ]; - $this->execute($sql); + $this->execute($sql, $params); } else { // down $sql = sprintf( - "DELETE FROM %s WHERE %s = '%s'", + 'DELETE FROM %s WHERE %s = ?', $this->quoteTableName($this->getSchemaTableName()), $this->quoteColumnName('version'), - $migration->getVersion() ); + $params = [$migration->getVersion()]; - $this->execute($sql); + $this->execute($sql, $params); } return $this; @@ -514,17 +516,18 @@ public function migrated(MigrationInterface $migration, string $direction, strin */ public function toggleBreakpoint(MigrationInterface $migration): AdapterInterface { + $params = [ + $migration->getVersion(), + ]; $this->query( sprintf( - 'UPDATE %1$s SET %2$s = CASE %2$s WHEN %3$s THEN %4$s ELSE %3$s END, %7$s = %7$s WHERE %5$s = \'%6$s\';', + 'UPDATE %1$s SET %2$s = CASE %2$s WHEN true THEN false ELSE true END, %4$s = %4$s WHERE %3$s = ?;', $this->quoteTableName($this->getSchemaTableName()), $this->quoteColumnName('breakpoint'), - $this->castToBool(true), - $this->castToBool(false), $this->quoteColumnName('version'), - $migration->getVersion(), $this->quoteColumnName('start_time') - ) + ), + $params ); return $this; @@ -575,16 +578,19 @@ public function unsetBreakpoint(MigrationInterface $migration): AdapterInterface */ protected function markBreakpoint(MigrationInterface $migration, bool $state): AdapterInterface { + $params = [ + $this->castToBool($state), + $migration->getVersion(), + ]; $this->query( sprintf( - 'UPDATE %1$s SET %2$s = %3$s, %4$s = %4$s WHERE %5$s = \'%6$s\';', + 'UPDATE %1$s SET %2$s = ?, %3$s = %3$s WHERE %4$s = ?;', $this->quoteTableName($this->getSchemaTableName()), $this->quoteColumnName('breakpoint'), - $this->castToBool($state), $this->quoteColumnName('start_time'), $this->quoteColumnName('version'), - $migration->getVersion() - ) + ), + $params ); return $this; diff --git a/src/Db/Adapter/PostgresAdapter.php b/src/Db/Adapter/PostgresAdapter.php index a525c219..ee67d88b 100644 --- a/src/Db/Adapter/PostgresAdapter.php +++ b/src/Db/Adapter/PostgresAdapter.php @@ -496,16 +496,15 @@ protected function getRenameColumnInstructions( string $newColumnName ): AlterInstructions { $parts = $this->getSchemaName($tableName); - $sql = sprintf( - 'SELECT CASE WHEN COUNT(*) > 0 THEN 1 ELSE 0 END AS column_exists + $sql = 'SELECT CASE WHEN COUNT(*) > 0 THEN 1 ELSE 0 END AS column_exists FROM information_schema.columns - WHERE table_schema = %s AND table_name = %s AND column_name = %s', - $this->quoteString($parts['schema']), - $this->quoteString($parts['table']), - $this->quoteString($columnName) - ); - - $result = $this->fetchRow($sql); + WHERE table_schema = ? AND table_name = ? AND column_name = ?'; + $params = [ + $parts['schema'], + $parts['table'], + $columnName, + ]; + $result = $this->query($sql, $params)->fetch('assoc'); if (!$result || !(bool)$result['column_exists']) { throw new InvalidArgumentException("The specified column does not exist: $columnName"); } @@ -833,7 +832,11 @@ public function hasPrimaryKey(string $tableName, $columns, ?string $constraint = public function getPrimaryKey(string $tableName): array { $parts = $this->getSchemaName($tableName); - $rows = $this->fetchAll(sprintf( + $params = [ + $parts['schema'], + $parts['table'], + ]; + $rows = $this->query( "SELECT tc.constraint_name, kcu.column_name @@ -841,12 +844,11 @@ public function getPrimaryKey(string $tableName): array JOIN information_schema.key_column_usage AS kcu ON tc.constraint_name = kcu.constraint_name WHERE constraint_type = 'PRIMARY KEY' - AND tc.table_schema = %s - AND tc.table_name = %s + AND tc.table_schema = ? + AND tc.table_name = ? ORDER BY kcu.position_in_unique_constraint", - $this->quoteString($parts['schema']), - $this->quoteString($parts['table']) - )); + $params, + )->fetchAll('assoc'); $primaryKey = [ 'columns' => [], @@ -896,7 +898,11 @@ protected function getForeignKeys(string $tableName): array { $parts = $this->getSchemaName($tableName); $foreignKeys = []; - $rows = $this->fetchAll(sprintf( + $params = [ + $parts['schema'], + $parts['table'], + ]; + $rows = $this->query( "SELECT tc.constraint_name, tc.table_name, kcu.column_name, @@ -906,11 +912,10 @@ protected function getForeignKeys(string $tableName): array information_schema.table_constraints AS tc JOIN information_schema.key_column_usage AS kcu ON tc.constraint_name = kcu.constraint_name JOIN information_schema.constraint_column_usage AS ccu ON ccu.constraint_name = tc.constraint_name - WHERE constraint_type = 'FOREIGN KEY' AND tc.table_schema = %s AND tc.table_name = %s + WHERE constraint_type = 'FOREIGN KEY' AND tc.table_schema = ? AND tc.table_name = ? ORDER BY kcu.ordinal_position", - $this->quoteString($parts['schema']), - $this->quoteString($parts['table']) - )); + $params, + )->fetchAll('assoc'); foreach ($rows as $row) { $foreignKeys[$row['constraint_name']]['table'] = $row['table_name']; $foreignKeys[$row['constraint_name']]['columns'][] = $row['column_name']; @@ -1384,13 +1389,8 @@ public function createSchema(string $schemaName = 'public'): void */ public function hasSchema(string $schemaName): bool { - $sql = sprintf( - 'SELECT count(*) - FROM pg_namespace - WHERE nspname = %s', - $this->quoteString($schemaName) - ); - $result = $this->fetchRow($sql); + $sql = 'SELECT count(*) FROM pg_namespace WHERE nspname = ?'; + $result = $this->query($sql, [$schemaName])->fetch('assoc'); if (!$result) { return false; } diff --git a/src/Db/Adapter/SqliteAdapter.php b/src/Db/Adapter/SqliteAdapter.php index 540b675f..09fa5c24 100644 --- a/src/Db/Adapter/SqliteAdapter.php +++ b/src/Db/Adapter/SqliteAdapter.php @@ -326,8 +326,16 @@ protected function resolveTable(string $tableName): array } else { $master = sprintf('%s.%s', $this->quoteColumnName($schema), 'sqlite_master'); } + $rows = []; try { - $rows = $this->fetchAll(sprintf("SELECT name FROM %s WHERE type='table' AND lower(name) = %s", $master, $this->quoteString($table))); + $result = $this->query( + "SELECT name FROM {$master} WHERE type = 'table' AND lower(name) = ?", + [$table] + ); + // null on error + if ($result !== null) { + $rows = $result->fetchAll('assoc'); + } } catch (PDOException $e) { // an exception can occur if the schema part of the table refers to a database which is not attached break; @@ -797,19 +805,17 @@ protected function bufferIndicesAndTriggers(AlterInstructions $instructions, str $state['indices'] = []; $state['triggers'] = []; - $rows = $this->fetchAll( - sprintf( - " - SELECT * - FROM sqlite_master - WHERE - (`type` = 'index' OR `type` = 'trigger') - AND tbl_name = %s - AND sql IS NOT NULL - ", - $this->quoteValue($tableName) - ) - ); + $params = [$tableName]; + $rows = $this->query( + "SELECT * + FROM sqlite_master + WHERE + (`type` = 'index' OR `type` = 'trigger') + AND tbl_name = ? + AND sql IS NOT NULL + ", + $params + )->fetchAll('assoc'); $schema = $this->getSchemaName($tableName, true)['schema']; diff --git a/src/Db/Adapter/SqlserverAdapter.php b/src/Db/Adapter/SqlserverAdapter.php index aa844072..77a77945 100644 --- a/src/Db/Adapter/SqlserverAdapter.php +++ b/src/Db/Adapter/SqlserverAdapter.php @@ -138,11 +138,10 @@ public function hasTable(string $tableName): bool $parts = $this->getSchemaName($tableName); /** @var array $result */ - $result = $this->fetchRow(sprintf( - "SELECT count(*) as [count] FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '%s' AND TABLE_NAME = '%s';", - $parts['schema'], - $parts['table'], - )); + $result = $this->query( + 'SELECT count(*) as [count] FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ?', + [$parts['schema'], $parts['table']] + )->fetch('assoc'); return $result['count'] > 0; } @@ -341,7 +340,7 @@ public function truncateTable(string $tableName): void */ public function getColumnComment(string $tableName, ?string $columnName): ?string { - $sql = sprintf("SELECT cast(extended_properties.[value] as nvarchar(4000)) comment + $sql = "SELECT cast(extended_properties.[value] as nvarchar(4000)) comment FROM sys.schemas INNER JOIN sys.tables ON schemas.schema_id = tables.schema_id @@ -351,8 +350,9 @@ public function getColumnComment(string $tableName, ?string $columnName): ?strin ON tables.object_id = extended_properties.major_id AND columns.column_id = extended_properties.minor_id AND extended_properties.name = 'MS_Description' - WHERE schemas.[name] = '%s' AND tables.[name] = '%s' AND columns.[name] = '%s'", $this->schema, $tableName, (string)$columnName); - $row = $this->fetchRow($sql); + WHERE schemas.[name] = ? AND tables.[name] = ? AND columns.[name] = ?"; + $params = [$this->schema, $tableName, (string)$columnName]; + $row = $this->query($sql, $params)->fetch('assoc'); if ($row) { return trim($row['comment']); @@ -368,20 +368,17 @@ public function getColumns(string $tableName): array { $parts = $this->getSchemaName($tableName); $columns = []; - $sql = sprintf( - "SELECT DISTINCT TABLE_SCHEMA AS [schema], TABLE_NAME as [table_name], COLUMN_NAME AS [name], DATA_TYPE AS [type], + $sql = "SELECT DISTINCT TABLE_SCHEMA AS [schema], TABLE_NAME as [table_name], COLUMN_NAME AS [name], DATA_TYPE AS [type], IS_NULLABLE AS [null], COLUMN_DEFAULT AS [default], CHARACTER_MAXIMUM_LENGTH AS [char_length], NUMERIC_PRECISION AS [precision], NUMERIC_SCALE AS [scale], ORDINAL_POSITION AS [ordinal_position], COLUMNPROPERTY(object_id(TABLE_NAME), COLUMN_NAME, 'IsIdentity') as [identity] FROM INFORMATION_SCHEMA.COLUMNS - WHERE TABLE_SCHEMA = '%s' AND TABLE_NAME = '%s' - ORDER BY ordinal_position", - $parts['schema'], - $parts['table'], - ); - $rows = $this->fetchAll($sql); + WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ? + ORDER BY ordinal_position"; + $rows = $this->query($sql, [$parts['schema'], $parts['table']]) + ->fetchAll('assoc'); foreach ($rows as $columnInfo) { try { $type = $this->getPhinxType($columnInfo['type']); @@ -437,16 +434,11 @@ protected function parseDefault(?string $default): int|string|null public function hasColumn(string $tableName, string $columnName): bool { $parts = $this->getSchemaName($tableName); - $sql = sprintf( - "SELECT count(*) as [count] + $sql = "SELECT count(*) as [count] FROM INFORMATION_SCHEMA.COLUMNS - WHERE TABLE_SCHEMA = '%s' AND TABLE_NAME = '%s' AND COLUMN_NAME = '%s'", - $parts['schema'], - $parts['table'], - $columnName - ); + WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ? AND COLUMN_NAME = ?"; /** @var array $result */ - $result = $this->fetchRow($sql); + $result = $this->query($sql, [$parts['schema'], $parts['table'], $columnName])->fetch('assoc'); return $result['count'] > 0; } @@ -616,29 +608,14 @@ protected function getDropDefaultConstraint(string $tableName, ?string $columnNa */ protected function getDefaultConstraint(string $tableName, string $columnName): string|false { - $sql = "SELECT - default_constraints.name -FROM - sys.all_columns - - INNER JOIN - sys.tables - ON all_columns.object_id = tables.object_id - - INNER JOIN - sys.schemas - ON tables.schema_id = schemas.schema_id - - INNER JOIN - sys.default_constraints - ON all_columns.default_object_id = default_constraints.object_id - -WHERE - schemas.name = 'dbo' - AND tables.name = '{$tableName}' - AND all_columns.name = '{$columnName}'"; + $sql = "SELECT default_constraints.name + FROM sys.all_columns + INNER JOIN sys.tables ON all_columns.object_id = tables.object_id + INNER JOIN sys.schemas ON tables.schema_id = schemas.schema_id + INNER JOIN sys.default_constraints ON all_columns.default_object_id = default_constraints.object_id + WHERE schemas.name = 'dbo' AND tables.name = ? AND all_columns.name = ?"; - $rows = $this->fetchAll($sql); + $rows = $this->query($sql, [$tableName, $columnName])->fetchAll('assoc'); return empty($rows) ? false : $rows[0]['name']; } @@ -650,13 +627,14 @@ protected function getDefaultConstraint(string $tableName, string $columnName): */ protected function getIndexColumns(string $tableId, string $indexId): array { - $sql = "SELECT AC.[name] AS [column_name] + $sql = 'SELECT AC.[name] AS [column_name] FROM sys.[index_columns] IC INNER JOIN sys.[all_columns] AC ON IC.[column_id] = AC.[column_id] -WHERE AC.[object_id] = {$tableId} AND IC.[index_id] = {$indexId} AND IC.[object_id] = {$tableId} -ORDER BY IC.[key_ordinal];"; +WHERE AC.[object_id] = ? AND IC.[index_id] = ? AND IC.[object_id] = ? +ORDER BY IC.[key_ordinal]'; - $rows = $this->fetchAll($sql); + $params = [$tableId, $indexId, $tableId]; + $rows = $this->query($sql, $params)->fetchAll('assoc'); $columns = []; foreach ($rows as $row) { $columns[] = strtolower($row['column_name']); @@ -676,18 +654,14 @@ public function getIndexes(string $tableName): array $parts = $this->getSchemaName($tableName); $indexes = []; - $sql = sprintf( - "SELECT I.[name] AS [index_name], I.[index_id] as [index_id], T.[object_id] as [table_id] + $sql = "SELECT I.[name] AS [index_name], I.[index_id] as [index_id], T.[object_id] as [table_id] FROM sys.[tables] AS T INNER JOIN sys.[indexes] I ON T.[object_id] = I.[object_id] - INNER JOIN sys.[schemas] S ON S.schema_id = T.schema_id -WHERE T.[is_ms_shipped] = 0 AND I.[type_desc] <> 'HEAP' AND S.[name] = '%s' AND T.[name] = '%s' -ORDER BY T.[name], I.[index_id];", - $parts['schema'], - $parts['table'], - ); + INNER JOIN sys.[schemas] S ON s.schema_id = T.schema_id +WHERE T.[is_ms_shipped] = 0 AND I.[type_desc] <> 'HEAP' AND S.[name] = ? AND T.[name] = ? +ORDER BY T.[name], I.[index_id]"; - $rows = $this->fetchAll($sql); + $rows = $this->query($sql, [$parts['schema'], $parts['table']])->fetchAll('assoc'); foreach ($rows as $row) { $columns = $this->getIndexColumns($row['table_id'], $row['index_id']); $indexes[$row['index_name']] = ['columns' => $columns]; @@ -834,7 +808,7 @@ public function hasPrimaryKey(string $tableName, $columns, ?string $constraint = public function getPrimaryKey(string $tableName): array { $parts = $this->getSchemaName($tableName); - $rows = $this->fetchAll(sprintf( + $rows = $this->query( "SELECT tc.CONSTRAINT_NAME, kcu.COLUMN_NAME @@ -842,12 +816,11 @@ public function getPrimaryKey(string $tableName): array JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS kcu ON tc.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME WHERE CONSTRAINT_TYPE = 'PRIMARY KEY' - AND tc.CONSTRAINT_SCHEMA = '%s' - AND tc.TABLE_NAME = '%s' + AND tc.CONSTRAINT_SCHEMA = ? + AND tc.TABLE_NAME = ? ORDER BY kcu.ORDINAL_POSITION", - $parts['schema'], - $parts['table'], - )); + [$parts['schema'], $parts['table']] + )->fetchAll('assoc'); $primaryKey = [ 'columns' => [], @@ -897,21 +870,20 @@ protected function getForeignKeys(string $tableName): array { $parts = $this->getSchemaName($tableName); $foreignKeys = []; - $rows = $this->fetchAll(sprintf( + $rows = $this->query( "SELECT - tc.CONSTRAINT_NAME, - tc.TABLE_NAME, kcu.COLUMN_NAME, - ccu.TABLE_NAME AS REFERENCED_TABLE_NAME, - ccu.COLUMN_NAME AS REFERENCED_COLUMN_NAME - FROM - INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS tc - JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS kcu ON tc.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME - JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE AS ccu ON ccu.CONSTRAINT_NAME = tc.CONSTRAINT_NAME - WHERE CONSTRAINT_TYPE = 'FOREIGN KEY' AND tc.TABLE_SCHEMA = '%s' AND tc.TABLE_NAME = '%s' - ORDER BY kcu.ORDINAL_POSITION", - $parts['schema'], - $parts['table'], - )); + tc.CONSTRAINT_NAME, + tc.TABLE_NAME, kcu.COLUMN_NAME, + ccu.TABLE_NAME AS REFERENCED_TABLE_NAME, + ccu.COLUMN_NAME AS REFERENCED_COLUMN_NAME + FROM + INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS tc + JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS kcu ON tc.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME + JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE AS ccu ON ccu.CONSTRAINT_NAME = tc.CONSTRAINT_NAME + WHERE CONSTRAINT_TYPE = 'FOREIGN KEY' AND tc.TABLE_SCHEMA = ? AND tc.TABLE_NAME = ? + ORDER BY kcu.ORDINAL_POSITION", + [$parts['schema'], $parts['table']] + )->fetchAll('assoc'); foreach ($rows as $row) { $foreignKeys[$row['CONSTRAINT_NAME']]['table'] = $row['TABLE_NAME']; $foreignKeys[$row['CONSTRAINT_NAME']]['columns'][] = $row['COLUMN_NAME']; @@ -1121,12 +1093,10 @@ public function createDatabase(string $name, array $options = []): void public function hasDatabase(string $name): bool { /** @var array $result */ - $result = $this->fetchRow( - sprintf( - "SELECT count(*) as [count] FROM master.dbo.sysdatabases WHERE [name] = '%s'", - $name - ) - ); + $result = $this->query( + 'SELECT count(*) as [count] FROM master.dbo.sysdatabases WHERE [name] = ?', + [$name] + )->fetch('assoc'); return $result['count'] > 0; } @@ -1286,13 +1256,8 @@ public function createSchema(string $schemaName = 'public'): void */ public function hasSchema(string $schemaName): bool { - $sql = sprintf( - 'SELECT count(*) AS [count] - FROM sys.schemas - WHERE name = %s', - $this->quoteString($schemaName) - ); - $result = $this->fetchRow($sql); + $sql = 'SELECT count(*) AS [count] FROM sys.schemas WHERE name = ?'; + $result = $this->query($sql, [$schemaName])->fetch('assoc'); if (!$result) { return false; } diff --git a/tests/TestCase/Command/BakeMigrationDiffCommandTest.php b/tests/TestCase/Command/BakeMigrationDiffCommandTest.php index a7362740..0de89739 100644 --- a/tests/TestCase/Command/BakeMigrationDiffCommandTest.php +++ b/tests/TestCase/Command/BakeMigrationDiffCommandTest.php @@ -170,7 +170,7 @@ public function testBakingDiffAddRemove() */ public function testBakingDiffWithAutoIdCompatibleSignedPrimaryKeys(): void { - $this->skipIf(getenv('DB_URL_COMPARE') === false); + $this->skipIf(!env('DB_URL_COMPARE')); Configure::write('Migrations.unsigned_primary_keys', false); @@ -183,7 +183,7 @@ public function testBakingDiffWithAutoIdCompatibleSignedPrimaryKeys(): void */ public function testBakingDiffWithAutoIdIncompatibleSignedPrimaryKeys(): void { - $this->skipIf(getenv('DB_URL_COMPARE') === false); + $this->skipIf(!env('DB_URL_COMPARE')); $this->runDiffBakingTest('WithAutoIdIncompatibleSignedPrimaryKeys'); } @@ -194,7 +194,7 @@ public function testBakingDiffWithAutoIdIncompatibleSignedPrimaryKeys(): void */ public function testBakingDiffWithAutoIdIncompatibleUnsignedPrimaryKeys(): void { - $this->skipIf(getenv('DB_URL_COMPARE') === false); + $this->skipIf(!env('DB_URL_COMPARE')); Configure::write('Migrations.unsigned_primary_keys', false); @@ -203,6 +203,8 @@ public function testBakingDiffWithAutoIdIncompatibleUnsignedPrimaryKeys(): void protected function runDiffBakingTest(string $scenario): void { + $this->skipIf(!env('DB_URL_COMPARE')); + $diffConfigFolder = Plugin::path('Migrations') . 'tests' . DS . 'comparisons' . DS . 'Diff' . DS . lcfirst($scenario) . DS; $diffMigrationsPath = $diffConfigFolder . 'the_diff_' . Inflector::underscore($scenario) . '_' . env('DB') . '.php'; $diffDumpPath = $diffConfigFolder . 'schema-dump-test_comparisons_' . env('DB') . '.lock'; diff --git a/tests/TestCase/Migration/EnvironmentTest.php b/tests/TestCase/Migration/EnvironmentTest.php index 7e79a780..7863dd34 100644 --- a/tests/TestCase/Migration/EnvironmentTest.php +++ b/tests/TestCase/Migration/EnvironmentTest.php @@ -1,7 +1,7 @@ markTestSkipped('Incompatible with sqlserver right now.'); } + $snapshotConfig = ConnectionManager::getConfig('test_snapshot'); + $this->skipIf(empty($snapshotConfig['database']), 'Requires test_snapshot connection'); if ($flags) { Configure::write('Migrations', $flags + Configure::read('Migrations', []));