diff --git a/analyzer-baseline.toml b/analyzer-baseline.toml index 062e927c..6f5fb0e5 100644 --- a/analyzer-baseline.toml +++ b/analyzer-baseline.toml @@ -1776,6 +1776,12 @@ code = "possibly-invalid-argument" message = 'Possible argument type mismatch for argument #1 of `PhpDb\Adapter\Platform\PlatformInterface::quoteIdentifierInFragment`: expected `string`, but possibly received `bool|int|string`.' count = 1 +[[issues]] +file = "src/Sql/AbstractSql.php" +code = "possibly-invalid-argument" +message = 'Possible argument type mismatch for argument #1 of `PhpDb\Adapter\Platform\PlatformInterface::quoteIdentifier`: expected `string`, but possibly received `non-empty-array|null|string`.' +count = 1 + [[issues]] file = "src/Sql/AbstractSql.php" code = "possibly-invalid-argument" @@ -2160,12 +2166,6 @@ code = "mixed-argument" message = 'Invalid argument type for argument #1 of `PhpDb\Sql\Ddl\Column\Column::setDefault`: expected `PhpDb\Sql\Argument\Literal|PhpDb\Sql\Argument\Value|null|scalar`, but found `mixed`.' count = 1 -[[issues]] -file = "src/Sql/Ddl/Column/Column.php" -code = "redundant-comparison" -message = "Avoid direct comparison with boolean literals." -count = 1 - [[issues]] file = "src/Sql/Ddl/Column/Column.php" code = "uninitialized-property" @@ -2601,7 +2601,7 @@ count = 1 [[issues]] file = "src/Sql/Insert.php" code = "less-specific-nested-argument-type" -message = "Argument type mismatch for argument #2 of `implode`: expected `array|null`, but provided type `non-empty-list` is less specific." +message = "Argument type mismatch for argument #2 of `implode`: expected `array|null`, but provided type `list` is less specific." count = 1 [[issues]] @@ -3309,7 +3309,7 @@ count = 1 [[issues]] file = "src/Sql/Select.php" code = "invalid-return-statement" -message = 'Invalid return type for function `PhpDb\Sql\Select::resolveTable`: expected `array{0: null|string, 1: string}`, but found `list{array|null|string, string}`.' +message = '''Invalid return type for function `PhpDb\Sql\Select::resolveTable`: expected `array{0: null|string, 1: string}`, but found `list{array|null|string, string('')|truthy-string}`.''' count = 1 [[issues]] diff --git a/lint-baseline.toml b/lint-baseline.toml index 3f9a3f36..98558a29 100644 --- a/lint-baseline.toml +++ b/lint-baseline.toml @@ -354,18 +354,6 @@ code = "kan-defect" message = "Class has a high kan defect score." count = 1 -[[issues]] -file = "src/Sql/AbstractSql.php" -code = "no-else-clause" -message = "Avoid `else` clauses." -count = 8 - -[[issues]] -file = "src/Sql/AbstractSql.php" -code = "no-else-clause" -message = "Avoid `elseif` clauses." -count = 5 - [[issues]] file = "src/Sql/AbstractSql.php" code = "too-many-methods" @@ -396,18 +384,6 @@ code = "kan-defect" message = "Class has a high kan defect score." count = 1 -[[issues]] -file = "src/Sql/Ddl/AlterTable.php" -code = "no-else-clause" -message = "Avoid `else` clauses." -count = 1 - -[[issues]] -file = "src/Sql/Ddl/AlterTable.php" -code = "no-else-clause" -message = "Avoid `elseif` clauses." -count = 2 - [[issues]] file = "src/Sql/Ddl/AlterTable.php" code = "too-many-methods" @@ -426,138 +402,36 @@ code = "halstead" message = "Method has a high halstead difficulty" count = 1 -[[issues]] -file = "src/Sql/Ddl/Column/Column.php" -code = "no-else-clause" -message = "Avoid `else` clauses." -count = 1 - -[[issues]] -file = "src/Sql/Ddl/Column/Column.php" -code = "no-else-clause" -message = "Avoid `elseif` clauses." -count = 1 - [[issues]] file = "src/Sql/Ddl/Constraint/ForeignKey.php" code = "excessive-parameter-list" message = "Parameter list is too long." count = 1 -[[issues]] -file = "src/Sql/Ddl/CreateTable.php" -code = "cyclomatic-complexity" -message = "Class has high complexity." -count = 1 - -[[issues]] -file = "src/Sql/Ddl/CreateTable.php" -code = "no-else-clause" -message = "Avoid `else` clauses." -count = 1 - -[[issues]] -file = "src/Sql/Ddl/CreateTable.php" -code = "no-else-clause" -message = "Avoid `elseif` clauses." -count = 2 - [[issues]] file = "src/Sql/Ddl/CreateTable.php" code = "too-many-methods" message = "Class has too many methods." count = 1 -[[issues]] -file = "src/Sql/Delete.php" -code = "no-else-clause" -message = "Avoid `else` clauses." -count = 1 - -[[issues]] -file = "src/Sql/Expression.php" -code = "halstead" -message = "Method has a high halstead difficulty" -count = 1 - -[[issues]] -file = "src/Sql/Expression.php" -code = "no-else-clause" -message = "Avoid `elseif` clauses." -count = 2 - [[issues]] file = "src/Sql/Insert.php" code = "cyclomatic-complexity" message = "Class has high complexity." count = 1 -[[issues]] -file = "src/Sql/Insert.php" -code = "no-else-clause" -message = "Avoid `else` clauses." -count = 2 - [[issues]] file = "src/Sql/Insert.php" code = "too-many-methods" message = "Class has too many methods." count = 1 -[[issues]] -file = "src/Sql/Predicate/In.php" -code = "halstead" -message = "Method has a high halstead difficulty" -count = 1 - -[[issues]] -file = "src/Sql/Predicate/In.php" -code = "no-else-clause" -message = "Avoid `else` clauses." -count = 1 - -[[issues]] -file = "src/Sql/Predicate/In.php" -code = "no-else-clause" -message = "Avoid `elseif` clauses." -count = 1 - -[[issues]] -file = "src/Sql/Predicate/Operator.php" -code = "halstead" -message = "Method has a high halstead difficulty" -count = 2 - -[[issues]] -file = "src/Sql/Predicate/Operator.php" -code = "no-else-clause" -message = "Avoid `else` clauses." -count = 2 - -[[issues]] -file = "src/Sql/Predicate/Operator.php" -code = "no-else-clause" -message = "Avoid `elseif` clauses." -count = 2 - -[[issues]] -file = "src/Sql/Predicate/Predicate.php" -code = "no-else-clause" -message = "Avoid `else` clauses." -count = 1 - [[issues]] file = "src/Sql/Predicate/Predicate.php" code = "too-many-methods" message = "Class has too many methods." count = 1 -[[issues]] -file = "src/Sql/Predicate/PredicateSet.php" -code = "cyclomatic-complexity" -message = "Class has high complexity." -count = 1 - [[issues]] file = "src/Sql/Predicate/PredicateSet.php" code = "halstead" @@ -570,18 +444,6 @@ code = "kan-defect" message = "Class has a high kan defect score." count = 1 -[[issues]] -file = "src/Sql/Predicate/PredicateSet.php" -code = "no-else-clause" -message = "Avoid `else` clauses." -count = 2 - -[[issues]] -file = "src/Sql/Predicate/PredicateSet.php" -code = "no-else-clause" -message = "Avoid `elseif` clauses." -count = 5 - [[issues]] file = "src/Sql/Select.php" code = "cyclomatic-complexity" @@ -594,30 +456,12 @@ code = "halstead" message = "Method has a high halstead difficulty" count = 2 -[[issues]] -file = "src/Sql/Select.php" -code = "halstead" -message = "Method has a high halstead effort" -count = 1 - [[issues]] file = "src/Sql/Select.php" code = "kan-defect" message = "Class has a high kan defect score." count = 1 -[[issues]] -file = "src/Sql/Select.php" -code = "no-else-clause" -message = "Avoid `else` clauses." -count = 8 - -[[issues]] -file = "src/Sql/Select.php" -code = "no-else-clause" -message = "Avoid `elseif` clauses." -count = 3 - [[issues]] file = "src/Sql/Select.php" code = "too-many-methods" @@ -642,12 +486,6 @@ code = "halstead" message = "Method has a high halstead difficulty" count = 1 -[[issues]] -file = "src/Sql/Update.php" -code = "no-else-clause" -message = "Avoid `else` clauses." -count = 2 - [[issues]] file = "src/Sql/Update.php" code = "too-many-methods" diff --git a/src/Sql/AbstractSql.php b/src/Sql/AbstractSql.php index 6a6852bb..abd5cc0d 100644 --- a/src/Sql/AbstractSql.php +++ b/src/Sql/AbstractSql.php @@ -90,7 +90,10 @@ protected function buildSqlString( if (is_array($result)) { $sqls[$name] = $this->createSqlFromSpecificationAndParameters($specification, $result); - } elseif (null !== $result) { + continue; + } + + if (null !== $result) { $sqls[$name] = $result; } } @@ -131,13 +134,12 @@ protected function createSqlFromSpecificationAndParameters(array|string $specifi if (null !== ($paramSpecs[$position]['combinedby'] ?? null)) { $multiParamValues = []; foreach ($paramsForPosition as $multiParamsForPosition) { - if (is_array($multiParamsForPosition)) { - $ppCount = count($multiParamsForPosition); - } else { - $ppCount = 1; + if (! is_array($multiParamsForPosition)) { $multiParamsForPosition = [$multiParamsForPosition]; } + $ppCount = count($multiParamsForPosition); + if (null === ($paramSpecs[$position][$ppCount] ?? null)) { throw Exception\RuntimeException::forUnsupportedParameterCountOf($ppCount); } @@ -146,16 +148,20 @@ protected function createSqlFromSpecificationAndParameters(array|string $specifi } $topParameters[] = implode($paramSpecs[$position]['combinedby'], $multiParamValues); - } elseif (null !== $paramSpecs[$position]) { - $ppCount = count($paramsForPosition); - if (null === ($paramSpecs[$position][$ppCount] ?? null)) { - throw Exception\RuntimeException::forUnsupportedParameterCountOf($ppCount); - } + continue; + } - $topParameters[] = vsprintf($paramSpecs[$position][$ppCount], $paramsForPosition); - } else { + if (null === $paramSpecs[$position]) { $topParameters[] = $paramsForPosition; + continue; } + + $ppCount = count($paramsForPosition); + if (null === ($paramSpecs[$position][$ppCount] ?? null)) { + throw Exception\RuntimeException::forUnsupportedParameterCountOf($ppCount); + } + + $topParameters[] = vsprintf($paramSpecs[$position][$ppCount], $paramsForPosition); } return vsprintf($specificationString, $topParameters); @@ -185,12 +191,13 @@ protected function flattenExpressionValues(array $arguments): array $values = []; foreach ($arguments as $argument) { - if ($argument instanceof Values) { - foreach ($argument->getValue() as $v) { - $values[] = new Value($v); - } - } else { + if (! $argument instanceof Values) { $values[] = $argument; + continue; + } + + foreach ($argument->getValue() as $v) { + $values[] = new Value($v); } } @@ -228,15 +235,13 @@ protected function processExpression( return str_replace('%%', replace: '%', subject: $specification); } - if (null === $namedParameterPrefix || '' === $namedParameterPrefix) { - $namedParameterPrefix = $parameterContainer + $namedParameterPrefix = match (true) { + null === $namedParameterPrefix || '' === $namedParameterPrefix => $parameterContainer ? 'expr' . $runtimeExpressionPrefix++ . 'Param' - : ''; - } else { - $namedParameterPrefix = - $this->processInfo['paramPrefix'] - . str_replace([' ', "\t", "\n", "\r"], replace: '__', subject: $namedParameterPrefix); - } + : '', + default => $this->processInfo['paramPrefix'] + . str_replace([' ', "\t", "\n", "\r"], replace: '__', subject: $namedParameterPrefix), + }; $this->instanceParameterIndex[$namedParameterPrefix] ??= 1; @@ -341,49 +346,42 @@ protected function processJoin( foreach ($joins->getJoins() as $j => $join) { $joinAs = null; $joinNameValue = $join['name']; + $joinName = $joinNameValue; if (is_array($joinNameValue)) { $alias = array_key_first($joinNameValue); $joinName = $joinNameValue[$alias]; $joinAs = $platform->quoteIdentifier($alias); - } else { - $joinName = $joinNameValue; } - if ($joinName instanceof Expression) { - $joinName = $joinName->getExpression(); - } elseif ($joinName instanceof TableIdentifier) { - $joinName = $joinName->getTableAndSchema(); - $joinName = ( - $joinName[1] - ? $platform->quoteIdentifier($joinName[1]) . $platform->getIdentifierSeparator() - : '' - ) - . $platform->quoteIdentifier($joinName[0]); - } elseif ($joinName instanceof Select) { - $joinName = "({$this->processSubSelect($joinName, $platform, $driver, $parameterContainer)})"; - } else { - $joinName = $platform->quoteIdentifier($joinName); - } + $joinName = match (true) { + $joinName instanceof Expression => $joinName->getExpression(), + $joinName instanceof TableIdentifier => $this->quoteJoinTableIdentifier($joinName, $platform), + $joinName instanceof Select => "({$this->processSubSelect( + $joinName, + $platform, + $driver, + $parameterContainer, + )})", + default => $platform->quoteIdentifier($joinName), + }; $joinSpecArgArray[$j] = [ strtoupper($join['type']), $this->renderTable($joinName, $joinAs), ]; - if ($join['on'] instanceof ExpressionInterface) { - $joinSpecArgArray[$j][] = $this->processExpression( + $joinSpecArgArray[$j][] = $join['on'] instanceof ExpressionInterface + ? $this->processExpression( $join['on'], $platform, $driver, $parameterContainer, 'join' . ($j + 1) . 'part', - ); - } else { - $joinSpecArgArray[$j][] = $platform->quoteIdentifierInFragment( + ) + : $platform->quoteIdentifierInFragment( $join['on'], ['=', 'AND', 'OR', '(', ')', 'BETWEEN', '<', '>'], ); - } } return [$joinSpecArgArray]; @@ -395,11 +393,10 @@ protected function processSubSelect( ?DriverInterface $driver = null, ?ParameterContainer $parameterContainer = null, ): string { + $decorator = $subselect; if ($this instanceof PlatformDecoratorInterface) { $decorator = clone $this; $decorator->setSubject($subselect); - } else { - $decorator = $subselect; } if ($parameterContainer instanceof ParameterContainer) { @@ -477,15 +474,29 @@ protected function resolveTable( } if ($table instanceof Select) { - $table = "({$this->processSubSelect($table, $platform, $driver, $parameterContainer)})"; - } elseif ($table) { - $table = $platform->quoteIdentifier($table); + return "({$this->processSubSelect($table, $platform, $driver, $parameterContainer)})"; + } + + if (! $table) { + return $table; } - if ($schema && $table) { + $table = $platform->quoteIdentifier($table); + + if ($schema) { $table = $platform->quoteIdentifier($schema) . $platform->getIdentifierSeparator() . $table; } return $table; } + + private function quoteJoinTableIdentifier(TableIdentifier $identifier, PlatformInterface $platform): string + { + [$table, $schema] = $identifier->getTableAndSchema(); + + return ( + ($schema ? $platform->quoteIdentifier($schema) . $platform->getIdentifierSeparator() : '') + . $platform->quoteIdentifier($table) + ); + } } diff --git a/src/Sql/Ddl/AlterTable.php b/src/Sql/Ddl/AlterTable.php index 2c51e564..7dae6e5a 100644 --- a/src/Sql/Ddl/AlterTable.php +++ b/src/Sql/Ddl/AlterTable.php @@ -294,16 +294,13 @@ protected function processTableOptions(?PlatformInterface $adapterPlatform = nul $sqls = []; foreach ($this->options as $key => $value) { - $key = strtoupper($key); - if ($value instanceof Literal) { - $value = $value->getLiteral(); - } elseif (is_bool($value)) { - $value = $value ? '1' : '0'; - } elseif (is_int($value)) { - $value = (string) $value; - } else { - $value = $adapterPlatform->quoteTrustedValue($value); - } + $key = strtoupper($key); + $value = match (true) { + $value instanceof Literal => $value->getLiteral(), + is_bool($value) => $value ? '1' : '0', + is_int($value) => (string) $value, + default => $adapterPlatform->quoteTrustedValue($value), + }; $sqls[] = "{$key} = {$value}"; } diff --git a/src/Sql/Ddl/Column/Column.php b/src/Sql/Ddl/Column/Column.php index 25f8862b..c921ce9a 100644 --- a/src/Sql/Ddl/Column/Column.php +++ b/src/Sql/Ddl/Column/Column.php @@ -67,18 +67,16 @@ public function getExpressionData(): array new Literal($this->type), ]; - if (false === $this->isNullable) { - $specParts[] = 'NOT NULL'; - } else { - $specParts[] = 'NULL'; - } + $specParts[] = $this->isNullable ? 'NULL' : 'NOT NULL'; if (null !== $this->default) { $specParts[] = 'DEFAULT %s'; $values[] = $this->default instanceof ArgumentInterface ? $this->default : new Value($this->default); - } elseif ($this->isNullable) { + } + + if (null === $this->default && $this->isNullable) { $specParts[] = 'DEFAULT NULL'; } diff --git a/src/Sql/Ddl/CreateTable.php b/src/Sql/Ddl/CreateTable.php index 5189b312..ac5fc91b 100644 --- a/src/Sql/Ddl/CreateTable.php +++ b/src/Sql/Ddl/CreateTable.php @@ -218,16 +218,13 @@ protected function processTableOptions(?PlatformInterface $adapterPlatform = nul $parts = []; foreach ($this->options as $key => $value) { - $key = strtoupper($key); - if ($value instanceof Literal) { - $value = $value->getLiteral(); - } elseif (is_bool($value)) { - $value = $value ? '1' : '0'; - } elseif (is_int($value)) { - $value = (string) $value; - } else { - $value = $adapterPlatform->quoteTrustedValue($value); - } + $key = strtoupper($key); + $value = match (true) { + $value instanceof Literal => $value->getLiteral(), + is_bool($value) => $value ? '1' : '0', + is_int($value) => (string) $value, + default => $adapterPlatform->quoteTrustedValue($value), + }; $parts[] = "{$key} = {$value}"; } diff --git a/src/Sql/Delete.php b/src/Sql/Delete.php index 5d6a0058..20fb69f1 100644 --- a/src/Sql/Delete.php +++ b/src/Sql/Delete.php @@ -85,10 +85,12 @@ public function where( ): static { if ($predicate instanceof Where) { $this->where = $predicate; - } else { - $this->getWhere()->addPredicates($predicate, $combination); + + return $this; } + $this->getWhere()->addPredicates($predicate, $combination); + return $this; } diff --git a/src/Sql/Expression.php b/src/Sql/Expression.php index 001dbc5a..1bc313ef 100644 --- a/src/Sql/Expression.php +++ b/src/Sql/Expression.php @@ -132,15 +132,12 @@ public function setParameters( } foreach ($parameters as $parameter) { - if (is_array($parameter)) { - $parameter = new Values($parameter); - } elseif ($parameter instanceof ExpressionInterface) { - $parameter = new SelectArgument($parameter); - } elseif (! $parameter instanceof ArgumentInterface) { - $parameter = new Value($parameter); - } - - $this->parameters[] = $parameter; + $this->parameters[] = match (true) { + is_array($parameter) => new Values($parameter), + $parameter instanceof ExpressionInterface => new SelectArgument($parameter), + $parameter instanceof ArgumentInterface => $parameter, + default => new Value($parameter), + }; } return $this; diff --git a/src/Sql/Insert.php b/src/Sql/Insert.php index f046917e..52fb1a70 100644 --- a/src/Sql/Insert.php +++ b/src/Sql/Insert.php @@ -132,10 +132,12 @@ public function values(array|Select $values, string $flag = self::VALUES_SET): s $this->columns = $this->isAssocativeArray($values) ? $values : array_combine(array_keys($this->columns), array_values($values)); - } else { - foreach ($values as $column => $value) { - $this->columns[$column] = $value; - } + + return $this; + } + + foreach ($values as $column => $value) { + $this->columns[$column] = $value; } return $this; @@ -170,14 +172,15 @@ protected function processInsert( $values[] = $driver->formatParameterName($column); $parameterContainer->offsetSet($column, $value); - } else { - $values[] = $this->resolveColumnValue( - $value, - $platform, - $driver, - $parameterContainer, - ); + continue; } + + $values[] = $this->resolveColumnValue( + $value, + $platform, + $driver, + $parameterContainer, + ); } return str_replace( diff --git a/src/Sql/Predicate/In.php b/src/Sql/Predicate/In.php index d8c2cc3b..bc744c70 100644 --- a/src/Sql/Predicate/In.php +++ b/src/Sql/Predicate/In.php @@ -93,13 +93,11 @@ public function setIdentifier(string|ArgumentInterface $identifier): static */ public function setValueSet(array|Select|ArgumentInterface $valueSet): static { - if ($valueSet instanceof ArgumentInterface) { - $this->valueSet = $valueSet; - } elseif ($valueSet instanceof Select) { - $this->valueSet = new ArgumentSelect($valueSet); - } else { - $this->valueSet = new Values($valueSet); - } + $this->valueSet = match (true) { + $valueSet instanceof ArgumentInterface => $valueSet, + $valueSet instanceof Select => new ArgumentSelect($valueSet), + default => new Values($valueSet), + }; return $this; } diff --git a/src/Sql/Predicate/Operator.php b/src/Sql/Predicate/Operator.php index a4971d4b..379c0e45 100644 --- a/src/Sql/Predicate/Operator.php +++ b/src/Sql/Predicate/Operator.php @@ -115,13 +115,11 @@ public function getRight(): ?ArgumentInterface */ public function setLeft(string|ArgumentInterface|ExpressionInterface|SqlInterface $left): static { - if ($left instanceof ArgumentInterface) { - $this->left = $left; - } elseif ($left instanceof ExpressionInterface || $left instanceof SqlInterface) { - $this->left = new Select($left); - } else { - $this->left = new Identifier($left); - } + $this->left = match (true) { + $left instanceof ArgumentInterface => $left, + $left instanceof ExpressionInterface, $left instanceof SqlInterface => new Select($left), + default => new Identifier($left), + }; return $this; } @@ -142,13 +140,11 @@ public function setOperator(string $operator): static public function setRight( bool|string|int|float|ArgumentInterface|ExpressionInterface|SqlInterface|null $right, ): static { - if ($right instanceof ArgumentInterface) { - $this->right = $right; - } elseif ($right instanceof ExpressionInterface || $right instanceof SqlInterface) { - $this->right = new Select($right); - } else { - $this->right = new Value($right); - } + $this->right = match (true) { + $right instanceof ArgumentInterface => $right, + $right instanceof ExpressionInterface, $right instanceof SqlInterface => new Select($right), + default => new Value($right), + }; return $this; } diff --git a/src/Sql/Predicate/Predicate.php b/src/Sql/Predicate/Predicate.php index 9704d52f..2750da93 100644 --- a/src/Sql/Predicate/Predicate.php +++ b/src/Sql/Predicate/Predicate.php @@ -68,17 +68,10 @@ public function expression( string $expression, string|float|int|array|ArgumentInterface|ExpressionInterface|null $parameters = [], ): static { - if ([] !== $parameters) { - $this->addPredicate( - new Expression($expression, $parameters), - $this->getNextPredicateCombineOperator(), - ); - } else { - $this->addPredicate( - new Expression($expression), - $this->getNextPredicateCombineOperator(), - ); - } + $this->addPredicate( + [] === $parameters ? new Expression($expression) : new Expression($expression, $parameters), + $this->getNextPredicateCombineOperator(), + ); return $this; } diff --git a/src/Sql/Predicate/PredicateSet.php b/src/Sql/Predicate/PredicateSet.php index 2f8ac0ab..c4e015a9 100644 --- a/src/Sql/Predicate/PredicateSet.php +++ b/src/Sql/Predicate/PredicateSet.php @@ -100,30 +100,23 @@ public function addPredicates( } foreach ($predicates as $pkey => $pvalue) { - if (is_string($pkey)) { - if (str_contains($pkey, '?')) { - $predicate = new PredicateExpression($pkey, $pvalue); - } elseif (null === $pvalue) { - $predicate = new IsNull($pkey); - } elseif (is_array($pvalue)) { - $predicate = new In($pkey, $pvalue); - } elseif ($pvalue instanceof PredicateInterface) { - throw Exception\InvalidArgumentException::forPredicateWithStringKey(); - } else { - $predicate = new Operator($pkey, Operator::OP_EQ, $pvalue); - } - } elseif ($pvalue instanceof PredicateInterface) { - $predicate = $pvalue; - } elseif ($pvalue instanceof Expression) { - $predicate = new PredicateExpression( + $predicate = match (true) { + is_string($pkey) => match (true) { + str_contains($pkey, '?') => new PredicateExpression($pkey, $pvalue), + null === $pvalue => new IsNull($pkey), + is_array($pvalue) => new In($pkey, $pvalue), + $pvalue instanceof PredicateInterface + => throw Exception\InvalidArgumentException::forPredicateWithStringKey(), + default => new Operator($pkey, Operator::OP_EQ, $pvalue), + }, + $pvalue instanceof PredicateInterface => $pvalue, + $pvalue instanceof Expression => new PredicateExpression( $pvalue->getExpression(), $pvalue->getParameters(), - ); - } else { - $predicate = str_contains($pvalue, Expression::PLACEHOLDER) - ? new Expression($pvalue) - : new Literal($pvalue); - } + ), + str_contains($pvalue, Expression::PLACEHOLDER) => new Expression($pvalue), + default => new Literal($pvalue), + }; $this->addPredicate($predicate, $combination); } diff --git a/src/Sql/Select.php b/src/Sql/Select.php index fe673016..dbde02f5 100644 --- a/src/Sql/Select.php +++ b/src/Sql/Select.php @@ -265,12 +265,14 @@ public function getRawState(?string $key = null): mixed */ public function group(mixed $group): static { - if (is_array($group)) { - foreach ($group as $o) { - $this->group[] = $o; - } - } else { + if (! is_array($group)) { $this->group[] = $group; + + return $this; + } + + foreach ($group as $o) { + $this->group[] = $o; } return $this; @@ -288,10 +290,12 @@ public function having( ): static { if ($predicate instanceof Having) { $this->having = $predicate; - } else { - $this->getHaving()->addPredicates($predicate, $combination); + + return $this; } + $this->getHaving()->addPredicates($predicate, $combination); + return $this; } @@ -353,18 +357,19 @@ public function offset(int|string $offset): static */ public function order(ExpressionInterface|array|string $order): static { - if (is_string($order)) { - $order = str_contains($order, ',') ? preg_split('#,\s+#', $order) : (array) $order; - } elseif (! is_array($order)) { - $order = [$order]; - } + $order = match (true) { + is_string($order) => str_contains($order, ',') ? preg_split('#,\s+#', $order) : (array) $order, + is_array($order) => $order, + default => [$order], + }; foreach ($order as $k => $v) { if (is_string($k)) { $this->order[$k] = $v; - } else { - $this->order[] = $v; + continue; } + + $this->order[] = $v; } return $this; @@ -454,10 +459,12 @@ public function where( ): self { if ($predicate instanceof Where) { $this->where = $predicate; - } else { - $this->getWhere()->addPredicates($predicate, $combination); + + return $this; } + $this->getWhere()->addPredicates($predicate, $combination); + return $this; } @@ -590,19 +597,17 @@ protected function processOrder( } if (is_int($k)) { - if (str_contains($v, ' ')) { - [$k, $v] = explode(' ', $v, limit: 2); - } else { - $k = $v; - $v = self::ORDER_ASCENDING; - } + [$k, $v] = str_contains($v, ' ') + ? explode(' ', $v, limit: 2) + : [$v, self::ORDER_ASCENDING]; } - if (strcasecmp(trim($v), self::ORDER_DESCENDING) === 0) { - $orders[] = [$platform->quoteIdentifierInFragment($k), self::ORDER_DESCENDING]; - } else { - $orders[] = [$platform->quoteIdentifierInFragment($k), self::ORDER_ASCENDING]; - } + $orders[] = [ + $platform->quoteIdentifierInFragment($k), + strcasecmp(trim($v), self::ORDER_DESCENDING) === 0 + ? self::ORDER_DESCENDING + : self::ORDER_ASCENDING, + ]; } return [$orders]; @@ -639,12 +644,13 @@ protected function processSelect( $parameterContainer, is_string($columnIndexOrAs) ? $columnIndexOrAs : 'column', ); - $columnAs = null; - if (is_string($columnIndexOrAs)) { - $columnAs = $platform->quoteIdentifier($columnIndexOrAs); - } elseif (stripos($columnName, needle: ' as ') === false) { - $columnAs = is_string($column) ? $platform->quoteIdentifier($column) : 'Expression' . $expr++; - } + $columnAs = match (true) { + is_string($columnIndexOrAs) => $platform->quoteIdentifier($columnIndexOrAs), + stripos($columnName, needle: ' as ') === false => is_string($column) + ? $platform->quoteIdentifier($column) + : 'Expression' . $expr++, + default => null, + }; $columns[] = null === $columnAs ? [$columnName] : [$columnName, $columnAs]; } @@ -671,7 +677,9 @@ protected function processSelect( ); if (is_string($jKey)) { $jColumns[] = $platform->quoteIdentifier($jKey); - } elseif (self::SQL_STAR !== $jColumn) { + } + + if (! is_string($jKey) && self::SQL_STAR !== $jColumn) { $jColumns[] = $platform->quoteIdentifier($jColumn); } @@ -752,18 +760,15 @@ protected function resolveTable( $table = parent::resolveTable($table, $platform, $driver, $parameterContainer); + $fromTable = $table; if ($alias) { $fromTable = $platform->quoteIdentifier($alias); $table = $this->renderTable($table, $fromTable); - } else { - $fromTable = $table; } - if ($this->prefixColumnsWithTable && $fromTable) { - $fromTable .= $platform->getIdentifierSeparator(); - } else { - $fromTable = ''; - } + $fromTable = $this->prefixColumnsWithTable && $fromTable + ? $fromTable . $platform->getIdentifierSeparator() + : ''; return [ $table, diff --git a/src/Sql/Update.php b/src/Sql/Update.php index d82b585c..fe6db09d 100644 --- a/src/Sql/Update.php +++ b/src/Sql/Update.php @@ -152,10 +152,12 @@ public function where( ): static { if ($predicate instanceof Where) { $this->where = $predicate; - } else { - $this->getWhere()->addPredicates($predicate, $combination); + + return $this; } + $this->getWhere()->addPredicates($predicate, $combination); + return $this; } @@ -199,15 +201,16 @@ protected function processSet( $setSql[] = $prefix . $driver->formatParameterName($column); $parameterContainer->offsetSet($column, $value); - } else { - $setSql[] = $prefix - . $this->resolveColumnValue( - $value, - $platform, - $driver, - $parameterContainer, - ); + continue; } + + $setSql[] = $prefix + . $this->resolveColumnValue( + $value, + $platform, + $driver, + $parameterContainer, + ); } return str_replace( diff --git a/test/unit/Sql/AbstractSqlTest.php b/test/unit/Sql/AbstractSqlTest.php index 93b90d5e..fdfcfe01 100644 --- a/test/unit/Sql/AbstractSqlTest.php +++ b/test/unit/Sql/AbstractSqlTest.php @@ -26,6 +26,7 @@ use PhpDbTest\TestAsset\SelectDecorator; use PhpDbTest\TestAsset\TrustingSql92Platform; use PHPUnit\Framework\Attributes\CoversMethod; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\Attributes\RequiresPhp; @@ -60,12 +61,22 @@ #[CoversMethod(AbstractSql::class, 'resolveColumnValue')] #[CoversMethod(AbstractSql::class, 'resolveTable')] #[CoversMethod(AbstractSql::class, 'localizeVariables')] +#[CoversMethod(AbstractSql::class, 'quoteJoinTableIdentifier')] final class AbstractSqlTest extends TestCase { protected AbstractSql&MockObject $abstractSql; protected DriverInterface&MockObject $mockDriver; + /** @return array */ + public static function emptyTableProvider(): array + { + return [ + 'null' => [null], + 'empty string' => [''], + ]; + } + /** * @throws ReflectionException */ @@ -422,6 +433,28 @@ public function processExpressionWorksWithNamedParameterPrefixContainingWhitespa static::assertSame('string__containing__white__space1', key($parameterContainer->getNamedArray())); } + /** + * @throws ReflectionException + */ + #[Test] + public function processJoinQuotesTableIdentifierWithoutSchemaAsBareTable(): void + { + $join = new Join(); + $join->join(new TableIdentifier('bar'), 'foo.id = bar.foo_id'); + + $method = new ReflectionMethod($this->abstractSql, 'processJoin'); + $result = $method->invoke( + $this->abstractSql, + $join, + new TrustingSql92Platform(), + null, + null, + ); + + static::assertNotNull($result); + static::assertSame('"bar"', $result[0][0][1]); + } + /** * @throws ReflectionException */ @@ -718,6 +751,26 @@ public function resolveColumnValueWithSelect(): void static::assertStringEndsWith(')', $result); } + /** + * @throws ReflectionException + */ + #[Test] + #[DataProvider('emptyTableProvider')] + public function resolveTableReturnsEmptyTableUnquoted(?string $table): void + { + $method = new ReflectionMethod($this->abstractSql, 'resolveTable'); + + $result = $method->invoke( + $this->abstractSql, + $table, + new TrustingSql92Platform(), + $this->mockDriver, + null, + ); + + static::assertSame($table, $result); + } + /** * @throws ReflectionException */