From 1e3ec3063dc859399fe20c8799b101e2d460448f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20=C5=A0kr=C3=A1=C5=A1ek?= Date: Tue, 6 Feb 2024 16:37:24 +0100 Subject: [PATCH] drop required IConventions in DbalTableJoin constructor (#650) --- src/Collection/Aggregations/AnyAggregator.php | 15 ++++-- .../Aggregations/CountAggregator.php | 15 ++++-- .../Aggregations/NoneAggregator.php | 15 ++++-- .../Functions/FetchPropertyFunction.php | 4 +- .../Functions/Result/DbalTableJoin.php | 49 ++++++------------- .../Helpers/DbalQueryBuilderHelper.php | 2 +- 6 files changed, 52 insertions(+), 48 deletions(-) diff --git a/src/Collection/Aggregations/AnyAggregator.php b/src/Collection/Aggregations/AnyAggregator.php index d8bf7de2..d3a8b692 100644 --- a/src/Collection/Aggregations/AnyAggregator.php +++ b/src/Collection/Aggregations/AnyAggregator.php @@ -6,6 +6,7 @@ use Nextras\Dbal\QueryBuilder\QueryBuilder; use Nextras\Orm\Collection\Functions\Result\DbalExpressionResult; use Nextras\Orm\Collection\Functions\Result\DbalTableJoin; +use Nextras\Orm\Exception\InvalidArgumentException; use Nextras\Orm\Exception\InvalidStateException; use function array_merge; use function array_pop; @@ -56,6 +57,14 @@ public function aggregateExpression( if ($join === null) { throw new InvalidStateException('Aggregation applied over expression without a relationship'); } + if (count($join->primaryKeys) === 0) { + throw new InvalidArgumentException('Aggregation applied over a table join without specifying a primary key.'); + } + if (count($join->primaryKeys) > 1) { + throw new InvalidArgumentException( + 'Aggregation applied over a table join with multi column primary key; currently, this is not supported.', + ); + } $joins[] = new DbalTableJoin( toExpression: $join->toExpression, @@ -63,14 +72,12 @@ public function aggregateExpression( toAlias: $join->toAlias, onExpression: "($join->onExpression) AND $expression->expression", onArgs: array_merge($join->onArgs, $expression->args), - conventions: $join->conventions, + primaryKeys: $join->primaryKeys, ); - $primaryKey = $join->conventions->getStoragePrimaryKey()[0]; - return new DbalExpressionResult( expression: 'COUNT(%table.%column) > 0', - args: [$join->toAlias, $primaryKey], + args: [$join->toAlias, $join->primaryKeys[0]], joins: $joins, groupBy: $expression->groupBy, isHavingClause: true, diff --git a/src/Collection/Aggregations/CountAggregator.php b/src/Collection/Aggregations/CountAggregator.php index b1beca6a..a011114b 100644 --- a/src/Collection/Aggregations/CountAggregator.php +++ b/src/Collection/Aggregations/CountAggregator.php @@ -6,6 +6,7 @@ use Nextras\Dbal\QueryBuilder\QueryBuilder; use Nextras\Orm\Collection\Functions\Result\DbalExpressionResult; use Nextras\Orm\Collection\Functions\Result\DbalTableJoin; +use Nextras\Orm\Exception\InvalidArgumentException; use Nextras\Orm\Exception\InvalidStateException; @@ -60,6 +61,14 @@ public function aggregateExpression( if ($join === null) { throw new InvalidStateException('Aggregation applied over expression without a relationship'); } + if (count($join->primaryKeys) === 0) { + throw new InvalidArgumentException('Aggregation applied over a table join without specifying a primary key.'); + } + if (count($join->primaryKeys) > 1) { + throw new InvalidArgumentException( + 'Aggregation applied over a table join with multi column primary key; currently, this is not supported.', + ); + } $joins[] = new DbalTableJoin( toExpression: $join->toExpression, @@ -67,14 +76,12 @@ public function aggregateExpression( toAlias: $join->toAlias, onExpression: "($join->onExpression) AND $expression->expression", onArgs: array_merge($join->onArgs, $expression->args), - conventions: $join->conventions, + primaryKeys: $join->primaryKeys, ); - $primaryKey = $join->conventions->getStoragePrimaryKey()[0]; - return new DbalExpressionResult( expression: 'COUNT(%table.%column) >= %i AND COUNT(%table.%column) <= %i', - args: [$join->toAlias, $primaryKey, $this->atLeast, $join->toAlias, $primaryKey, $this->atMost], + args: [$join->toAlias, $join->primaryKeys[0], $this->atLeast, $join->toAlias, $join->primaryKeys[0], $this->atMost], joins: $joins, groupBy: $expression->groupBy, isHavingClause: true, diff --git a/src/Collection/Aggregations/NoneAggregator.php b/src/Collection/Aggregations/NoneAggregator.php index 827b31de..c02c851e 100644 --- a/src/Collection/Aggregations/NoneAggregator.php +++ b/src/Collection/Aggregations/NoneAggregator.php @@ -6,6 +6,7 @@ use Nextras\Dbal\QueryBuilder\QueryBuilder; use Nextras\Orm\Collection\Functions\Result\DbalExpressionResult; use Nextras\Orm\Collection\Functions\Result\DbalTableJoin; +use Nextras\Orm\Exception\InvalidArgumentException; use Nextras\Orm\Exception\InvalidStateException; use function array_merge; use function array_pop; @@ -56,6 +57,14 @@ public function aggregateExpression( if ($join === null) { throw new InvalidStateException('Aggregation applied over expression without a relationship'); } + if (count($join->primaryKeys) === 0) { + throw new InvalidArgumentException('Aggregation applied over a table join without specifying a primary key.'); + } + if (count($join->primaryKeys) > 1) { + throw new InvalidArgumentException( + 'Aggregation applied over a table join with multi column primary key; currently, this is not supported.', + ); + } $joins[] = new DbalTableJoin( toExpression: $join->toExpression, @@ -63,14 +72,12 @@ public function aggregateExpression( toAlias: $join->toAlias, onExpression: "($join->onExpression) AND $expression->expression", onArgs: array_merge($join->onArgs, $expression->args), - conventions: $join->conventions, + primaryKeys: $join->primaryKeys, ); - $primaryKey = $join->conventions->getStoragePrimaryKey()[0]; - return new DbalExpressionResult( expression: 'COUNT(%table.%column) = 0', - args: [$join->toAlias, $primaryKey], + args: [$join->toAlias, $join->primaryKeys[0]], joins: $joins, groupBy: $expression->groupBy, isHavingClause: true, diff --git a/src/Collection/Functions/FetchPropertyFunction.php b/src/Collection/Functions/FetchPropertyFunction.php index 0b35d4b3..b81baf28 100644 --- a/src/Collection/Functions/FetchPropertyFunction.php +++ b/src/Collection/Functions/FetchPropertyFunction.php @@ -335,7 +335,7 @@ private function processRelationship( toAlias: $joinAlias, onExpression: "%table.%column = %table.%column", onArgs: [$currentAlias, $fromColumn, $joinAlias, $inColumn], - conventions: $currentConventions, + primaryKeys: [$currentConventions->getStoragePrimaryKey()[0]], ); $currentAlias = $joinAlias; @@ -358,7 +358,7 @@ private function processRelationship( toAlias: $targetAlias, onExpression: "%table.%column = %table.%column", onArgs: [$currentAlias, $fromColumn, $targetAlias, $toColumn], - conventions: $targetConventions, + primaryKeys: [$targetConventions->getStoragePrimaryKey()[0]], ); return [$targetAlias, $targetConventions, $targetEntityMetadata, $targetMapper]; diff --git a/src/Collection/Functions/Result/DbalTableJoin.php b/src/Collection/Functions/Result/DbalTableJoin.php index 6d6e60d5..5dacb111 100644 --- a/src/Collection/Functions/Result/DbalTableJoin.php +++ b/src/Collection/Functions/Result/DbalTableJoin.php @@ -4,54 +4,37 @@ use Nextras\Dbal\QueryBuilder\QueryBuilder; -use Nextras\Orm\Mapper\Dbal\Conventions\IConventions; /** + * SQL join metadata holder. + * + * The joins are created lazily and this class holds data for it. + * + * If there is an aggregation, the joined table needs to be grouped by {@see DbalTableJoin::$primaryKeys}, + * if not needed or possible, pass jum an empty array. + * * @experimental */ class DbalTableJoin { - /** @var literal-string */ - public readonly string $toExpression; - - /** @var array */ - public readonly array $toArgs; - - /** @var literal-string */ - public readonly string $toAlias; - - /** @var literal-string */ - public readonly string $onExpression; - - /** @var array */ - public readonly array $onArgs; - - public readonly IConventions $conventions; - - /** - * @param array $toArgs - * @param array $onArgs * @param literal-string $toExpression + * @param array $toArgs * @param literal-string $toAlias * @param literal-string $onExpression + * @param array $onArgs + * @param list $primaryKeys */ public function __construct( - string $toExpression, - array $toArgs, - string $toAlias, - string $onExpression, - array $onArgs, - IConventions $conventions, + public readonly string $toExpression, + public readonly array $toArgs, + public readonly string $toAlias, + public readonly string $onExpression, + public readonly array $onArgs, + public readonly array $primaryKeys = [], ) { - $this->toExpression = $toExpression; - $this->toArgs = $toArgs; - $this->toAlias = $toAlias; - $this->onExpression = $onExpression; - $this->onArgs = $onArgs; - $this->conventions = $conventions; } diff --git a/src/Collection/Helpers/DbalQueryBuilderHelper.php b/src/Collection/Helpers/DbalQueryBuilderHelper.php index 26d94a5b..c512dc84 100644 --- a/src/Collection/Helpers/DbalQueryBuilderHelper.php +++ b/src/Collection/Helpers/DbalQueryBuilderHelper.php @@ -169,7 +169,7 @@ public function mergeJoins(string $dbalModifier, array $joins): array toAlias: $first->toAlias, onExpression: $dbalModifier, onArgs: [$args], - conventions: $first->conventions, + primaryKeys: $first->primaryKeys, ); } }