Skip to content

Commit 2faa558

Browse files
authored
Less sprintf in adapters (#788)
* Improve test run without optional connections * Start removing sprintf from PdoAdapter * Use prepared statements in postgres adapter * Remove more sprintf from adapters * Fix more queries from 4.next * Fix errors * Fix another error * phpstan doesn't like this * Another mysql error * Restore fix and suppress phpstan * Fix a missing condition * Fix mistake
1 parent c88055d commit 2faa558

File tree

9 files changed

+176
-184
lines changed

9 files changed

+176
-184
lines changed

phpstan-baseline.neon

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,12 @@ parameters:
9696
count: 1
9797
path: src/Db/Adapter/SqliteAdapter.php
9898

99+
-
100+
message: '#^Strict comparison using \!\=\= between Cake\\Database\\StatementInterface and null will always evaluate to true\.$#'
101+
identifier: notIdentical.alwaysTrue
102+
count: 1
103+
path: src/Db/Adapter/SqliteAdapter.php
104+
99105
-
100106
message: '#^PHPDoc tag @return with type Phinx\\Db\\Adapter\\AdapterInterface is not subtype of native type Migrations\\Db\\Adapter\\AdapterInterface\.$#'
101107
identifier: return.phpDocType

src/Db/Adapter/MysqlAdapter.php

Lines changed: 36 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -751,19 +751,22 @@ public function hasPrimaryKey(string $tableName, $columns, ?string $constraint =
751751
public function getPrimaryKey(string $tableName): array
752752
{
753753
$options = $this->getOptions();
754-
$rows = $this->fetchAll(sprintf(
754+
$params = [
755+
$options['database'],
756+
$tableName,
757+
];
758+
$rows = $this->query(
755759
"SELECT
756760
k.CONSTRAINT_NAME,
757761
k.COLUMN_NAME
758762
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS t
759763
JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE k
760764
USING(CONSTRAINT_NAME,TABLE_SCHEMA,TABLE_NAME)
761-
WHERE t.CONSTRAINT_TYPE='PRIMARY KEY'
762-
AND t.TABLE_SCHEMA='%s'
763-
AND t.TABLE_NAME='%s'",
764-
$options['database'],
765-
$tableName
766-
));
765+
WHERE t.CONSTRAINT_TYPE = 'PRIMARY KEY'
766+
AND t.TABLE_SCHEMA = ?
767+
AND t.TABLE_NAME = ?",
768+
$params
769+
)->fetchAll('assoc');
767770

768771
$primaryKey = [
769772
'columns' => [],
@@ -809,26 +812,33 @@ public function hasForeignKey(string $tableName, $columns, ?string $constraint =
809812
*/
810813
protected function getForeignKeys(string $tableName): array
811814
{
815+
$schema = null;
812816
if (strpos($tableName, '.') !== false) {
813817
[$schema, $tableName] = explode('.', $tableName);
814818
}
815819

816-
$foreignKeys = [];
817-
$rows = $this->fetchAll(sprintf(
818-
"SELECT
820+
$params = [];
821+
$query = "SELECT
819822
CONSTRAINT_NAME,
820823
CONCAT(TABLE_SCHEMA, '.', TABLE_NAME) AS TABLE_NAME,
821824
COLUMN_NAME,
822825
CONCAT(REFERENCED_TABLE_SCHEMA, '.', REFERENCED_TABLE_NAME) AS REFERENCED_TABLE_NAME,
823826
REFERENCED_COLUMN_NAME
824827
FROM information_schema.KEY_COLUMN_USAGE
825-
WHERE REFERENCED_TABLE_NAME IS NOT NULL
826-
AND TABLE_SCHEMA = %s
827-
AND TABLE_NAME = '%s'
828-
ORDER BY POSITION_IN_UNIQUE_CONSTRAINT",
829-
empty($schema) ? 'DATABASE()' : "'$schema'",
830-
$tableName
831-
));
828+
WHERE REFERENCED_TABLE_NAME IS NOT NULL";
829+
830+
if ($schema) {
831+
$query .= ' AND TABLE_SCHEMA = ?';
832+
$params[] = $schema;
833+
} else {
834+
$query .= ' AND TABLE_SCHEMA = DATABASE()';
835+
}
836+
837+
$query .= ' AND TABLE_NAME = ? ORDER BY POSITION_IN_UNIQUE_CONSTRAINT';
838+
$params[] = $tableName;
839+
840+
$foreignKeys = [];
841+
$rows = $this->query($query, $params)->fetchAll('assoc');
832842
foreach ($rows as $row) {
833843
$foreignKeys[$row['CONSTRAINT_NAME']]['table'] = $row['TABLE_NAME'];
834844
$foreignKeys[$row['CONSTRAINT_NAME']]['columns'][] = $row['COLUMN_NAME'];
@@ -1270,12 +1280,10 @@ public function createDatabase(string $name, array $options = []): void
12701280
*/
12711281
public function hasDatabase(string $name): bool
12721282
{
1273-
$rows = $this->fetchAll(
1274-
sprintf(
1275-
'SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = \'%s\'',
1276-
$name
1277-
)
1278-
);
1283+
$rows = $this->query(
1284+
'SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = ?',
1285+
[$name]
1286+
)->fetchAll('assoc');
12791287

12801288
foreach ($rows as $row) {
12811289
if (!empty($row)) {
@@ -1470,16 +1478,13 @@ public function describeTable(string $tableName): array
14701478
$options = $this->getOptions();
14711479

14721480
// mysql specific
1473-
$sql = sprintf(
1474-
"SELECT *
1481+
$sql = "SELECT *
14751482
FROM information_schema.tables
1476-
WHERE table_schema = '%s'
1477-
AND table_name = '%s'",
1478-
$options['database'],
1479-
$tableName
1480-
);
1483+
WHERE table_schema = ?
1484+
AND table_name = ?";
1485+
$params = [$options['database'], $tableName];
14811486

1482-
$table = $this->fetchRow($sql);
1487+
$table = $this->query($sql, $params)->fetch('assoc');
14831488

14841489
return $table !== false ? $table : [];
14851490
}

src/Db/Adapter/PdoAdapter.php

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -479,31 +479,33 @@ public function migrated(MigrationInterface $migration, string $direction, strin
479479
if (strcasecmp($direction, MigrationInterface::UP) === 0) {
480480
// up
481481
$sql = sprintf(
482-
"INSERT INTO %s (%s, %s, %s, %s, %s) VALUES ('%s', '%s', '%s', '%s', %s);",
482+
'INSERT INTO %s (%s, %s, %s, %s, %s) VALUES (?, ?, ?, ?, ?);',
483483
$this->quoteTableName($this->getSchemaTableName()),
484484
$this->quoteColumnName('version'),
485485
$this->quoteColumnName('migration_name'),
486486
$this->quoteColumnName('start_time'),
487487
$this->quoteColumnName('end_time'),
488488
$this->quoteColumnName('breakpoint'),
489+
);
490+
$params = [
489491
$migration->getVersion(),
490492
substr($migration->getName(), 0, 100),
491493
$startTime,
492494
$endTime,
493-
$this->castToBool(false)
494-
);
495+
$this->castToBool(false),
496+
];
495497

496-
$this->execute($sql);
498+
$this->execute($sql, $params);
497499
} else {
498500
// down
499501
$sql = sprintf(
500-
"DELETE FROM %s WHERE %s = '%s'",
502+
'DELETE FROM %s WHERE %s = ?',
501503
$this->quoteTableName($this->getSchemaTableName()),
502504
$this->quoteColumnName('version'),
503-
$migration->getVersion()
504505
);
506+
$params = [$migration->getVersion()];
505507

506-
$this->execute($sql);
508+
$this->execute($sql, $params);
507509
}
508510

509511
return $this;
@@ -514,17 +516,18 @@ public function migrated(MigrationInterface $migration, string $direction, strin
514516
*/
515517
public function toggleBreakpoint(MigrationInterface $migration): AdapterInterface
516518
{
519+
$params = [
520+
$migration->getVersion(),
521+
];
517522
$this->query(
518523
sprintf(
519-
'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\';',
524+
'UPDATE %1$s SET %2$s = CASE %2$s WHEN true THEN false ELSE true END, %4$s = %4$s WHERE %3$s = ?;',
520525
$this->quoteTableName($this->getSchemaTableName()),
521526
$this->quoteColumnName('breakpoint'),
522-
$this->castToBool(true),
523-
$this->castToBool(false),
524527
$this->quoteColumnName('version'),
525-
$migration->getVersion(),
526528
$this->quoteColumnName('start_time')
527-
)
529+
),
530+
$params
528531
);
529532

530533
return $this;
@@ -575,16 +578,19 @@ public function unsetBreakpoint(MigrationInterface $migration): AdapterInterface
575578
*/
576579
protected function markBreakpoint(MigrationInterface $migration, bool $state): AdapterInterface
577580
{
581+
$params = [
582+
$this->castToBool($state),
583+
$migration->getVersion(),
584+
];
578585
$this->query(
579586
sprintf(
580-
'UPDATE %1$s SET %2$s = %3$s, %4$s = %4$s WHERE %5$s = \'%6$s\';',
587+
'UPDATE %1$s SET %2$s = ?, %3$s = %3$s WHERE %4$s = ?;',
581588
$this->quoteTableName($this->getSchemaTableName()),
582589
$this->quoteColumnName('breakpoint'),
583-
$this->castToBool($state),
584590
$this->quoteColumnName('start_time'),
585591
$this->quoteColumnName('version'),
586-
$migration->getVersion()
587-
)
592+
),
593+
$params
588594
);
589595

590596
return $this;

src/Db/Adapter/PostgresAdapter.php

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -496,16 +496,15 @@ protected function getRenameColumnInstructions(
496496
string $newColumnName
497497
): AlterInstructions {
498498
$parts = $this->getSchemaName($tableName);
499-
$sql = sprintf(
500-
'SELECT CASE WHEN COUNT(*) > 0 THEN 1 ELSE 0 END AS column_exists
499+
$sql = 'SELECT CASE WHEN COUNT(*) > 0 THEN 1 ELSE 0 END AS column_exists
501500
FROM information_schema.columns
502-
WHERE table_schema = %s AND table_name = %s AND column_name = %s',
503-
$this->quoteString($parts['schema']),
504-
$this->quoteString($parts['table']),
505-
$this->quoteString($columnName)
506-
);
507-
508-
$result = $this->fetchRow($sql);
501+
WHERE table_schema = ? AND table_name = ? AND column_name = ?';
502+
$params = [
503+
$parts['schema'],
504+
$parts['table'],
505+
$columnName,
506+
];
507+
$result = $this->query($sql, $params)->fetch('assoc');
509508
if (!$result || !(bool)$result['column_exists']) {
510509
throw new InvalidArgumentException("The specified column does not exist: $columnName");
511510
}
@@ -833,20 +832,23 @@ public function hasPrimaryKey(string $tableName, $columns, ?string $constraint =
833832
public function getPrimaryKey(string $tableName): array
834833
{
835834
$parts = $this->getSchemaName($tableName);
836-
$rows = $this->fetchAll(sprintf(
835+
$params = [
836+
$parts['schema'],
837+
$parts['table'],
838+
];
839+
$rows = $this->query(
837840
"SELECT
838841
tc.constraint_name,
839842
kcu.column_name
840843
FROM information_schema.table_constraints AS tc
841844
JOIN information_schema.key_column_usage AS kcu
842845
ON tc.constraint_name = kcu.constraint_name
843846
WHERE constraint_type = 'PRIMARY KEY'
844-
AND tc.table_schema = %s
845-
AND tc.table_name = %s
847+
AND tc.table_schema = ?
848+
AND tc.table_name = ?
846849
ORDER BY kcu.position_in_unique_constraint",
847-
$this->quoteString($parts['schema']),
848-
$this->quoteString($parts['table'])
849-
));
850+
$params,
851+
)->fetchAll('assoc');
850852

851853
$primaryKey = [
852854
'columns' => [],
@@ -896,7 +898,11 @@ protected function getForeignKeys(string $tableName): array
896898
{
897899
$parts = $this->getSchemaName($tableName);
898900
$foreignKeys = [];
899-
$rows = $this->fetchAll(sprintf(
901+
$params = [
902+
$parts['schema'],
903+
$parts['table'],
904+
];
905+
$rows = $this->query(
900906
"SELECT
901907
tc.constraint_name,
902908
tc.table_name, kcu.column_name,
@@ -906,11 +912,10 @@ protected function getForeignKeys(string $tableName): array
906912
information_schema.table_constraints AS tc
907913
JOIN information_schema.key_column_usage AS kcu ON tc.constraint_name = kcu.constraint_name
908914
JOIN information_schema.constraint_column_usage AS ccu ON ccu.constraint_name = tc.constraint_name
909-
WHERE constraint_type = 'FOREIGN KEY' AND tc.table_schema = %s AND tc.table_name = %s
915+
WHERE constraint_type = 'FOREIGN KEY' AND tc.table_schema = ? AND tc.table_name = ?
910916
ORDER BY kcu.ordinal_position",
911-
$this->quoteString($parts['schema']),
912-
$this->quoteString($parts['table'])
913-
));
917+
$params,
918+
)->fetchAll('assoc');
914919
foreach ($rows as $row) {
915920
$foreignKeys[$row['constraint_name']]['table'] = $row['table_name'];
916921
$foreignKeys[$row['constraint_name']]['columns'][] = $row['column_name'];
@@ -1384,13 +1389,8 @@ public function createSchema(string $schemaName = 'public'): void
13841389
*/
13851390
public function hasSchema(string $schemaName): bool
13861391
{
1387-
$sql = sprintf(
1388-
'SELECT count(*)
1389-
FROM pg_namespace
1390-
WHERE nspname = %s',
1391-
$this->quoteString($schemaName)
1392-
);
1393-
$result = $this->fetchRow($sql);
1392+
$sql = 'SELECT count(*) FROM pg_namespace WHERE nspname = ?';
1393+
$result = $this->query($sql, [$schemaName])->fetch('assoc');
13941394
if (!$result) {
13951395
return false;
13961396
}

src/Db/Adapter/SqliteAdapter.php

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -326,8 +326,16 @@ protected function resolveTable(string $tableName): array
326326
} else {
327327
$master = sprintf('%s.%s', $this->quoteColumnName($schema), 'sqlite_master');
328328
}
329+
$rows = [];
329330
try {
330-
$rows = $this->fetchAll(sprintf("SELECT name FROM %s WHERE type='table' AND lower(name) = %s", $master, $this->quoteString($table)));
331+
$result = $this->query(
332+
"SELECT name FROM {$master} WHERE type = 'table' AND lower(name) = ?",
333+
[$table]
334+
);
335+
// null on error
336+
if ($result !== null) {
337+
$rows = $result->fetchAll('assoc');
338+
}
331339
} catch (PDOException $e) {
332340
// an exception can occur if the schema part of the table refers to a database which is not attached
333341
break;
@@ -797,19 +805,17 @@ protected function bufferIndicesAndTriggers(AlterInstructions $instructions, str
797805
$state['indices'] = [];
798806
$state['triggers'] = [];
799807

800-
$rows = $this->fetchAll(
801-
sprintf(
802-
"
803-
SELECT *
804-
FROM sqlite_master
805-
WHERE
806-
(`type` = 'index' OR `type` = 'trigger')
807-
AND tbl_name = %s
808-
AND sql IS NOT NULL
809-
",
810-
$this->quoteValue($tableName)
811-
)
812-
);
808+
$params = [$tableName];
809+
$rows = $this->query(
810+
"SELECT *
811+
FROM sqlite_master
812+
WHERE
813+
(`type` = 'index' OR `type` = 'trigger')
814+
AND tbl_name = ?
815+
AND sql IS NOT NULL
816+
",
817+
$params
818+
)->fetchAll('assoc');
813819

814820
$schema = $this->getSchemaName($tableName, true)['schema'];
815821

0 commit comments

Comments
 (0)