Skip to content

Commit

Permalink
feat: support clickhouse timezone input in ParamValueConverterRegistry
Browse files Browse the repository at this point in the history
  • Loading branch information
simPod committed Jan 29, 2025
1 parent 9a90f8e commit a024cad
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 22 deletions.
66 changes: 47 additions & 19 deletions src/Param/ParamValueConverterRegistry.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@

use Closure;
use DateTimeInterface;
use DateTimeZone;
use Psr\Http\Message\StreamInterface;
use SimPod\ClickHouseClient\Exception\UnsupportedParamType;
use SimPod\ClickHouseClient\Exception\UnsupportedParamValue;
use SimPod\ClickHouseClient\Sql\Type;

use function array_keys;
Expand All @@ -16,6 +18,8 @@
use function implode;
use function in_array;
use function is_array;
use function is_float;
use function is_int;
use function is_string;
use function json_encode;
use function sprintf;
Expand All @@ -24,11 +28,10 @@
use function strtolower;
use function trim;

/** @phpstan-type Converter = Closure(mixed, Type|string|null, bool):(StreamInterface|string) */
final class ParamValueConverterRegistry
/** @phpstan-type Converter Closure(mixed, Type|string|null, bool):(StreamInterface|string) */
final readonly class ParamValueConverterRegistry
{
/** @var list<string> */
private static array $caseInsensitiveTypes = [
private const CaseInsensitiveTypes = [
'bool',
'date',
'date32',
Expand All @@ -47,8 +50,9 @@ final class ParamValueConverterRegistry
/** @phpstan-var array<string, Converter> */
private array $registry;

public function __construct()
{
public function __construct(
private DateTimeZone|null $clickHouseTimeZone = null,
) {
$formatPoint = static fn (array $point) => sprintf('(%s)', implode(',', $point));
// phpcs:ignore SlevomatCodingStandard.Functions.RequireArrowFunction.RequiredArrowFunction
$formatRingOrLineString = static function (array $v) use ($formatPoint) {
Expand Down Expand Up @@ -85,10 +89,10 @@ public function __construct()

'bool' => static fn (bool $value) => $value,

'date' => self::dateConverter(),
'date32' => self::dateConverter(),
'datetime' => self::dateTimeConverter(),
'datetime32' => self::dateTimeConverter(),
'date' => self::dateConverter($this->clickHouseTimeZone),
'date32' => self::dateConverter($this->clickHouseTimeZone),
'datetime' => self::dateTimeConverter($this->clickHouseTimeZone),
'datetime32' => self::dateTimeConverter($this->clickHouseTimeZone),
'datetime64' => static fn (DateTimeInterface|string|int|float $value) => $value instanceof DateTimeInterface
? $value->format('Y-m-d H:i:s.u')
: $value,
Expand Down Expand Up @@ -227,7 +231,7 @@ public function get(Type|string $type): Closure

$typeName = strtolower($typeName);
$converter = $this->registry[$typeName] ?? null;

Check failure on line 233 in src/Param/ParamValueConverterRegistry.php

View workflow job for this annotation

GitHub Actions / Static Analysis with PHPStan (8.2)

Access to an uninitialized readonly property SimPod\ClickHouseClient\Param\ParamValueConverterRegistry::$registry.

Check failure on line 233 in src/Param/ParamValueConverterRegistry.php

View workflow job for this annotation

GitHub Actions / Static Analysis with PHPStan (8.2)

Access to an uninitialized readonly property SimPod\ClickHouseClient\Param\ParamValueConverterRegistry::$registry.
if ($converter !== null && in_array($typeName, self::$caseInsensitiveTypes, true)) {
if ($converter !== null && in_array($typeName, self::CaseInsensitiveTypes, true)) {
return $converter;
}

Expand Down Expand Up @@ -264,18 +268,42 @@ private static function decimalConverter(): Closure
return static fn (float|int|string $value) => $value;
}

private static function dateConverter(): Closure
private static function dateConverter(DateTimeZone|null $clickHouseTimeZone): Closure
{
return static fn (DateTimeInterface|string|int|float $value) => $value instanceof DateTimeInterface
? $value->format('Y-m-d')
: $value;
return static function (mixed $value) use ($clickHouseTimeZone) {
if ($value instanceof DateTimeInterface) {
if ($clickHouseTimeZone !== null) {
$value = $value->setTimezone($clickHouseTimeZone);

Check failure on line 276 in src/Param/ParamValueConverterRegistry.php

View workflow job for this annotation

GitHub Actions / Static Analysis with PHPStan (8.2)

Call to an undefined method DateTimeInterface::setTimezone().

Check warning on line 276 in src/Param/ParamValueConverterRegistry.php

View check run for this annotation

Codecov / codecov/patch

src/Param/ParamValueConverterRegistry.php#L276

Added line #L276 was not covered by tests
}

return $value->format('Y-m-d');

Check failure on line 279 in src/Param/ParamValueConverterRegistry.php

View workflow job for this annotation

GitHub Actions / Static Analysis with PHPStan (8.2)

Cannot call method format() on mixed.
}

if (is_string($value) || is_float($value) || is_int($value)) {
return $value;
}

throw UnsupportedParamValue::type($value);

Check warning on line 286 in src/Param/ParamValueConverterRegistry.php

View check run for this annotation

Codecov / codecov/patch

src/Param/ParamValueConverterRegistry.php#L286

Added line #L286 was not covered by tests
};
}

private static function dateTimeConverter(): Closure
private static function dateTimeConverter(DateTimeZone|null $clickHouseTimeZone): Closure
{
return static fn (DateTimeInterface|string|int|float $value) => $value instanceof DateTimeInterface
? $value->format('Y-m-d H:i:s')
: $value;
return static function (mixed $value) use ($clickHouseTimeZone) {
if ($value instanceof DateTimeInterface) {
if ($clickHouseTimeZone !== null) {
$value = $value->setTimezone($clickHouseTimeZone);

Check failure on line 295 in src/Param/ParamValueConverterRegistry.php

View workflow job for this annotation

GitHub Actions / Static Analysis with PHPStan (8.2)

Call to an undefined method DateTimeInterface::setTimezone().

Check warning on line 295 in src/Param/ParamValueConverterRegistry.php

View check run for this annotation

Codecov / codecov/patch

src/Param/ParamValueConverterRegistry.php#L295

Added line #L295 was not covered by tests
}

return $value->format('Y-m-d H:i:s');

Check failure on line 298 in src/Param/ParamValueConverterRegistry.php

View workflow job for this annotation

GitHub Actions / Static Analysis with PHPStan (8.2)

Cannot call method format() on mixed.
}

if (is_string($value) || is_float($value) || is_int($value)) {
return $value;

Check warning on line 302 in src/Param/ParamValueConverterRegistry.php

View check run for this annotation

Codecov / codecov/patch

src/Param/ParamValueConverterRegistry.php#L301-L302

Added lines #L301 - L302 were not covered by tests
}

throw UnsupportedParamValue::type($value);

Check warning on line 305 in src/Param/ParamValueConverterRegistry.php

View check run for this annotation

Codecov / codecov/patch

src/Param/ParamValueConverterRegistry.php#L305

Added line #L305 was not covered by tests
};
}

private static function dateIntervalConverter(): Closure
Expand Down
6 changes: 3 additions & 3 deletions src/Sql/ValueFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
/** @internal */
final readonly class ValueFormatter
{
public function __construct(private DateTimeZone|null $dateTimeZone = null)
public function __construct(private DateTimeZone|null $clickHouseTimeZone = null)
{
}

Expand Down Expand Up @@ -67,8 +67,8 @@ public function format(mixed $value, string|null $paramName = null, string|null
}

if ($value instanceof DateTimeImmutable) {
if ($this->dateTimeZone !== null) {
$value = $value->setTimezone($this->dateTimeZone);
if ($this->clickHouseTimeZone !== null) {
$value = $value->setTimezone($this->clickHouseTimeZone);
}

return "'" . $value->format('Y-m-d H:i:s') . "'";
Expand Down

0 comments on commit a024cad

Please sign in to comment.