diff --git a/src/Column/AbstractMultiRangeColumn.php b/src/Column/AbstractMultiRangeColumn.php index 6125d3142..bfb71b2fc 100644 --- a/src/Column/AbstractMultiRangeColumn.php +++ b/src/Column/AbstractMultiRangeColumn.php @@ -7,6 +7,7 @@ use Yiisoft\Db\Exception\NotSupportedException; use Yiisoft\Db\Expression\ExpressionInterface; use Yiisoft\Db\Pgsql\Expression\MultiRangeValue; +use Yiisoft\Db\Pgsql\Expression\RangeValueInterface; use Yiisoft\Db\Schema\Column\AbstractColumn; use Yiisoft\Db\Schema\Column\ColumnInterface; @@ -15,7 +16,7 @@ use function is_string; /** - * @template T of ExpressionInterface + * @template T of RangeValueInterface */ abstract class AbstractMultiRangeColumn extends AbstractColumn { @@ -53,7 +54,7 @@ public function dbTypecast(mixed $value): mixed /** * @inheritDoc * - * @return ?ExpressionInterface[] + * @return ?RangeValueInterface[] * * @psalm-return ?T[] */ diff --git a/src/Column/AbstractRangeColumn.php b/src/Column/AbstractRangeColumn.php index 1c4a3fa8e..bcfa4bc4f 100644 --- a/src/Column/AbstractRangeColumn.php +++ b/src/Column/AbstractRangeColumn.php @@ -7,6 +7,7 @@ use InvalidArgumentException; use Yiisoft\Db\Exception\NotSupportedException; use Yiisoft\Db\Expression\ExpressionInterface; +use Yiisoft\Db\Pgsql\Expression\RangeValueInterface; use Yiisoft\Db\Schema\Column\AbstractColumn; use Yiisoft\Db\Schema\Column\ColumnInterface; @@ -16,7 +17,7 @@ use function sprintf; /** - * @template T of ExpressionInterface + * @template T of RangeValueInterface */ abstract class AbstractRangeColumn extends AbstractColumn { @@ -56,7 +57,7 @@ public function dbTypecast(mixed $value): mixed /** * @inheritDoc * - * @return ?ExpressionInterface + * @return ?RangeValueInterface * * @psalm-return ?T */ @@ -88,6 +89,8 @@ abstract protected function getBoundColumn(): ColumnInterface; /** * @throws NotSupportedException * + * @return RangeValueInterface + * * @psalm-return T */ abstract protected function createRangeValue( diff --git a/src/Expression/DateRangeValue.php b/src/Expression/DateRangeValue.php index 9fa76d548..f5c7e50d6 100644 --- a/src/Expression/DateRangeValue.php +++ b/src/Expression/DateRangeValue.php @@ -5,9 +5,11 @@ namespace Yiisoft\Db\Pgsql\Expression; use DateTimeImmutable; -use Yiisoft\Db\Expression\ExpressionInterface; -final class DateRangeValue implements ExpressionInterface +/** + * @implements RangeValueInterface + */ +final class DateRangeValue implements RangeValueInterface { public function __construct( public readonly ?DateTimeImmutable $lower = null, @@ -15,4 +17,17 @@ public function __construct( public readonly bool $includeLower = true, public readonly bool $includeUpper = true, ) {} + + public function getBounds(): array + { + $lower = $this->lower === null || $this->includeLower + ? $this->lower + : $this->lower->modify('+1 day'); + + $upper = $this->upper === null || $this->includeUpper + ? $this->upper + : $this->upper->modify('-1 day'); + + return [$lower, $upper]; + } } diff --git a/src/Expression/Int4RangeValue.php b/src/Expression/Int4RangeValue.php index d65c6efde..4ca7e9f4e 100644 --- a/src/Expression/Int4RangeValue.php +++ b/src/Expression/Int4RangeValue.php @@ -4,9 +4,10 @@ namespace Yiisoft\Db\Pgsql\Expression; -use Yiisoft\Db\Expression\ExpressionInterface; - -final class Int4RangeValue implements ExpressionInterface +/** + * @implements RangeValueInterface + */ +final class Int4RangeValue implements RangeValueInterface { public function __construct( public readonly ?int $lower = null, @@ -14,4 +15,17 @@ public function __construct( public readonly bool $includeLower = true, public readonly bool $includeUpper = true, ) {} + + public function getBounds(): array + { + $lower = $this->lower === null || $this->includeLower + ? $this->lower + : $this->lower + 1; + + $upper = $this->upper === null || $this->includeUpper + ? $this->upper + : $this->upper - 1; + + return [$lower, $upper]; + } } diff --git a/src/Expression/Int8RangeValue.php b/src/Expression/Int8RangeValue.php index 903425569..5cc50e9b9 100644 --- a/src/Expression/Int8RangeValue.php +++ b/src/Expression/Int8RangeValue.php @@ -4,9 +4,15 @@ namespace Yiisoft\Db\Pgsql\Expression; -use Yiisoft\Db\Expression\ExpressionInterface; +use RuntimeException; -final class Int8RangeValue implements ExpressionInterface +use const PHP_INT_MAX; +use const PHP_INT_MIN; + +/** + * @implements RangeValueInterface + */ +final class Int8RangeValue implements RangeValueInterface { public function __construct( public readonly int|string|null $lower = null, @@ -14,4 +20,29 @@ public function __construct( public readonly bool $includeLower = true, public readonly bool $includeUpper = true, ) {} + + public function getBounds(): array + { + $lower = $this->lower === null || $this->includeLower + ? $this->lower + : ( + PHP_INT_MIN <= $this->lower && $this->lower < PHP_INT_MAX + ? (int) $this->lower + 1 + : throw new RuntimeException( + 'Lower bound cannot be determined from the excluded value of a bigint range.', + ) + ); + + $upper = $this->upper === null || $this->includeUpper + ? $this->upper + : ( + PHP_INT_MIN < $this->upper && $this->upper <= PHP_INT_MAX + ? (int) $this->upper - 1 + : throw new RuntimeException( + 'Upper bound cannot be determined from the excluded value of a bigint range.', + ) + ); + + return [$lower, $upper]; + } } diff --git a/src/Expression/NumRangeValue.php b/src/Expression/NumRangeValue.php index 1f5d3f234..7c382a8f9 100644 --- a/src/Expression/NumRangeValue.php +++ b/src/Expression/NumRangeValue.php @@ -4,9 +4,12 @@ namespace Yiisoft\Db\Pgsql\Expression; -use Yiisoft\Db\Expression\ExpressionInterface; +use RuntimeException; -final class NumRangeValue implements ExpressionInterface +/** + * @implements RangeValueInterface + */ +final class NumRangeValue implements RangeValueInterface { public function __construct( public readonly int|float|null $lower = null, @@ -14,4 +17,21 @@ public function __construct( public readonly bool $includeLower = true, public readonly bool $includeUpper = true, ) {} + + public function getBounds(): array + { + $lower = $this->lower === null || $this->includeLower + ? $this->lower + : throw new RuntimeException( + 'Lower bound cannot be determined from the excluded value of a numeric range.', + ); + + $upper = $this->upper === null || $this->includeUpper + ? $this->upper + : throw new RuntimeException( + 'Upper bound cannot be determined from the excluded value of a numeric range.', + ); + + return [$lower, $upper]; + } } diff --git a/src/Expression/RangeValueInterface.php b/src/Expression/RangeValueInterface.php new file mode 100644 index 000000000..e05e13196 --- /dev/null +++ b/src/Expression/RangeValueInterface.php @@ -0,0 +1,24 @@ + + */ +final class TsRangeValue implements RangeValueInterface { public function __construct( public readonly ?DateTimeImmutable $lower = null, @@ -15,4 +17,17 @@ public function __construct( public readonly bool $includeLower = true, public readonly bool $includeUpper = true, ) {} + + public function getBounds(): array + { + $lower = $this->lower === null || $this->includeLower + ? $this->lower + : $this->lower->modify('+1 second'); + + $upper = $this->upper === null || $this->includeUpper + ? $this->upper + : $this->upper->modify('-1 second'); + + return [$lower, $upper]; + } } diff --git a/src/Expression/TsTzRangeValue.php b/src/Expression/TsTzRangeValue.php index 7f08c3aab..df77830ce 100644 --- a/src/Expression/TsTzRangeValue.php +++ b/src/Expression/TsTzRangeValue.php @@ -5,9 +5,11 @@ namespace Yiisoft\Db\Pgsql\Expression; use DateTimeImmutable; -use Yiisoft\Db\Expression\ExpressionInterface; -final class TsTzRangeValue implements ExpressionInterface +/** + * @implements RangeValueInterface + */ +final class TsTzRangeValue implements RangeValueInterface { public function __construct( public readonly ?DateTimeImmutable $lower = null, @@ -15,4 +17,17 @@ public function __construct( public readonly bool $includeLower = true, public readonly bool $includeUpper = true, ) {} + + public function getBounds(): array + { + $lower = $this->lower === null || $this->includeLower + ? $this->lower + : $this->lower->modify('+1 second'); + + $upper = $this->upper === null || $this->includeUpper + ? $this->upper + : $this->upper->modify('-1 second'); + + return [$lower, $upper]; + } }