diff --git a/analyzer-baseline.toml b/analyzer-baseline.toml index f94309d3..0ab2d502 100644 --- a/analyzer-baseline.toml +++ b/analyzer-baseline.toml @@ -1788,12 +1788,6 @@ code = "overly-wide-return-type" message = "Declared return type `null|string` for `processexpressionparametername` has unused branches: `null`." count = 1 -[[issues]] -file = "src/Sql/AbstractSql.php" -code = "possibly-false-argument" -message = 'Argument #1 of method `PhpDb\Adapter\Platform\PlatformInterface::quoteIdentifier` is possibly `false`, but parameter type `string` does not accept it.' -count = 1 - [[issues]] file = "src/Sql/AbstractSql.php" code = "possibly-invalid-argument" @@ -1860,6 +1854,12 @@ code = "possibly-null-argument" message = 'Argument #4 of method `PhpDb\Sql\AbstractSql::processExpressionParameterName` is possibly `null`, but parameter type `PhpDb\Adapter\Driver\DriverInterface` does not accept it.' count = 1 +[[issues]] +file = "src/Sql/AbstractSql.php" +code = "possibly-undefined-string-array-index" +message = 'Possibly undefined array key `string` accessed on `non-empty-array`.' +count = 1 + [[issues]] file = "src/Sql/AbstractSql.php" code = "redundant-cast" @@ -2292,18 +2292,6 @@ code = "missing-api-or-internal" message = 'Abstract class `PhpDb\Sql\Ddl\Constraint\AbstractConstraint` is missing an `@api` or `@internal` annotation.' count = 1 -[[issues]] -file = "src/Sql/Ddl/Constraint/AbstractConstraint.php" -code = "possibly-null-argument" -message = 'Argument #1 of method `PhpDb\Sql\Argument\Identifier::__construct` is possibly `null`, but parameter type `string` does not accept it.' -count = 1 - -[[issues]] -file = "src/Sql/Ddl/Constraint/AbstractConstraint.php" -code = "possibly-undefined-int-array-index" -message = "Possibly undefined array index accessed on `list`." -count = 1 - [[issues]] file = "src/Sql/Ddl/Constraint/Check.php" code = "class-must-be-final" @@ -2478,18 +2466,6 @@ code = "class-must-be-final" message = 'Class `PhpDb\Sql\Ddl\Index\Index` should be declared `final`.' count = 1 -[[issues]] -file = "src/Sql/Ddl/Index/Index.php" -code = "possibly-null-argument" -message = 'Argument #1 of method `PhpDb\Sql\Argument\Identifier::__construct` is possibly `null`, but parameter type `string` does not accept it.' -count = 1 - -[[issues]] -file = "src/Sql/Ddl/Index/Index.php" -code = "possibly-undefined-int-array-index" -message = "Possibly undefined array index accessed on `list`." -count = 1 - [[issues]] file = "src/Sql/Delete.php" code = "class-must-be-final" @@ -3582,12 +3558,6 @@ code = "possible-method-access-on-null" message = "Attempting to call a method on `null`." count = 2 -[[issues]] -file = "src/Sql/Select.php" -code = "possibly-false-argument" -message = 'Argument #1 of method `PhpDb\Sql\AbstractSql::resolveTable` is possibly `false`, but parameter type `PhpDb\Sql\Select|PhpDb\Sql\TableIdentifier|null|string` does not accept it.' -count = 1 - [[issues]] file = "src/Sql/Select.php" code = "possibly-false-iterator" @@ -3636,6 +3606,12 @@ code = "possibly-null-argument" message = 'Argument #1 of method `PhpDb\Sql\AbstractSql::renderTable` is possibly `null`, but parameter type `string` does not accept it.' count = 1 +[[issues]] +file = "src/Sql/Select.php" +code = "possibly-null-array-index" +message = "Possibly using `null` as an array index to access elementof variable $table." +count = 1 + [[issues]] file = "src/Sql/Select.php" code = "possibly-null-operand" @@ -3672,6 +3648,12 @@ code = "possibly-undefined-string-array-index" message = '''Possibly undefined array key 'type' accessed on `array{'modifier'?: truthy-string, 'select'?: PhpDb\Sql\Select, 'type'?: string}`.''' count = 1 +[[issues]] +file = "src/Sql/Select.php" +code = "possibly-undefined-string-array-index" +message = 'Possibly undefined array key `null|string` accessed on `array`.' +count = 1 + [[issues]] file = "src/Sql/Select.php" code = "redundant-comparison" diff --git a/infection.json5.dist b/infection.json5.dist index a91839b3..9297d843 100644 --- a/infection.json5.dist +++ b/infection.json5.dist @@ -22,6 +22,7 @@ // implode() discards keys, so array_fill()'s start index cannot be observed. "PhpDb\\Sql\\Argument\\Identifiers::getSpecification", "PhpDb\\Sql\\Argument\\Values::getSpecification", + "PhpDb\\Sql\\Ddl\\Constraint\\AbstractConstraint::getExpressionData", "PhpDb\\Sql\\Ddl\\Constraint\\ForeignKey::getExpressionData" ] }, @@ -30,6 +31,7 @@ // implode() discards keys, so array_fill()'s start index cannot be observed. "PhpDb\\Sql\\Argument\\Identifiers::getSpecification", "PhpDb\\Sql\\Argument\\Values::getSpecification", + "PhpDb\\Sql\\Ddl\\Constraint\\AbstractConstraint::getExpressionData", "PhpDb\\Sql\\Ddl\\Constraint\\ForeignKey::getExpressionData" ] }, diff --git a/src/Sql/AbstractSql.php b/src/Sql/AbstractSql.php index d290bdab..e3540f77 100644 --- a/src/Sql/AbstractSql.php +++ b/src/Sql/AbstractSql.php @@ -17,13 +17,12 @@ use PhpDb\Sql\Argument\Values; use PhpDb\Sql\Platform\PlatformDecoratorInterface; +use function array_key_first; use function count; -use function current; use function get_object_vars; use function implode; use function is_array; use function is_string; -use function key; use function rtrim; use function str_replace; use function strtoupper; @@ -343,8 +342,9 @@ protected function processJoin( $joinAs = null; $joinNameValue = $join['name']; if (is_array($joinNameValue)) { - $joinName = current($joinNameValue); - $joinAs = $platform->quoteIdentifier(key($joinNameValue)); + $alias = array_key_first($joinNameValue); + $joinName = $joinNameValue[$alias]; + $joinAs = $platform->quoteIdentifier($alias); } else { $joinName = $joinNameValue; } diff --git a/src/Sql/Ddl/Constraint/AbstractConstraint.php b/src/Sql/Ddl/Constraint/AbstractConstraint.php index bea2ecee..687bba42 100644 --- a/src/Sql/Ddl/Constraint/AbstractConstraint.php +++ b/src/Sql/Ddl/Constraint/AbstractConstraint.php @@ -70,8 +70,8 @@ public function getExpressionData(): array if (0 !== $columnCount) { $columnSpec = array_fill(0, count: $columnCount, value: '%s'); $specParts[] = str_replace('%s', implode(', ', $columnSpec), $this->columnSpecification); - for ($i = 0; $i < $columnCount; $i++) { - $values[] = new Identifier($this->columns[$i]); + foreach ($this->columns as $column) { + $values[] = new Identifier($column); } } diff --git a/src/Sql/Ddl/Index/Index.php b/src/Sql/Ddl/Index/Index.php index 04597226..431b5f5a 100644 --- a/src/Sql/Ddl/Index/Index.php +++ b/src/Sql/Ddl/Index/Index.php @@ -8,7 +8,6 @@ use PhpDb\Sql\Argument\Identifier; use PhpDb\Sql\Argument\Literal; -use function count; use function implode; use function str_replace; @@ -36,13 +35,12 @@ public function __construct(array|string|null $columns, ?string $name = null, ar #[Override] public function getExpressionData(): array { - $colCount = count($this->columns); $values = [new Identifier($this->name)]; $specParts = []; - for ($i = 0; $i < $colCount; $i++) { + foreach ($this->columns as $i => $column) { $specPart = '%s'; - $values[] = new Identifier($this->columns[$i]); + $values[] = new Identifier($column); if (null !== ($this->lengths[$i] ?? null)) { $specPart .= "({$this->lengths[$i]})"; diff --git a/src/Sql/Select.php b/src/Sql/Select.php index d761a95e..fe673016 100644 --- a/src/Sql/Select.php +++ b/src/Sql/Select.php @@ -12,8 +12,8 @@ use PhpDb\Sql\Predicate\PredicateInterface; use function array_key_exists; +use function array_key_first; use function count; -use function current; use function explode; use function gettype; use function is_array; @@ -650,7 +650,7 @@ protected function processSelect( } foreach ($this->getJoins()->getJoins() as $join) { - $joinName = is_array($join['name']) ? key($join['name']) : $join['name']; + $joinName = is_array($join['name']) ? array_key_first($join['name']) : $join['name']; $joinName = parent::resolveTable($joinName, $platform, $driver, $parameterContainer); foreach ($join['columns'] as $jKey => $jColumn) { @@ -746,8 +746,8 @@ protected function resolveTable( $alias = null; if (is_array($table)) { - $alias = key($table); - $table = current($table); + $alias = array_key_first($table); + $table = $table[$alias]; } $table = parent::resolveTable($table, $platform, $driver, $parameterContainer); diff --git a/test/unit/Sql/Ddl/Constraint/PrimaryKeyTest.php b/test/unit/Sql/Ddl/Constraint/PrimaryKeyTest.php index b656a204..51db9d7c 100644 --- a/test/unit/Sql/Ddl/Constraint/PrimaryKeyTest.php +++ b/test/unit/Sql/Ddl/Constraint/PrimaryKeyTest.php @@ -28,4 +28,21 @@ public function getExpressionData(): void $expressionData['values'], ); } + + #[Test] + public function getExpressionDataListsEveryColumnInTheSpecification(): void + { + $pk = new PrimaryKey(['foo', 'bar']); + + $expressionData = $pk->getExpressionData(); + + static::assertSame('PRIMARY KEY (%s, %s)', $expressionData['spec']); + static::assertEquals( + [ + Argument::identifier('foo'), + Argument::identifier('bar'), + ], + $expressionData['values'], + ); + } } diff --git a/test/unit/Sql/Ddl/Constraint/UniqueKeyTest.php b/test/unit/Sql/Ddl/Constraint/UniqueKeyTest.php index 8eeef080..1da0f8e5 100644 --- a/test/unit/Sql/Ddl/Constraint/UniqueKeyTest.php +++ b/test/unit/Sql/Ddl/Constraint/UniqueKeyTest.php @@ -29,4 +29,22 @@ public function getExpressionData(): void $expressionData['values'], ); } + + #[Test] + public function getExpressionDataListsEveryColumnInTheSpecification(): void + { + $uk = new UniqueKey(['foo', 'bar'], 'my_uk'); + + $expressionData = $uk->getExpressionData(); + + static::assertSame('CONSTRAINT %s UNIQUE (%s, %s)', $expressionData['spec']); + static::assertEquals( + [ + Argument::identifier('my_uk'), + Argument::identifier('foo'), + Argument::identifier('bar'), + ], + $expressionData['values'], + ); + } }