Skip to content

Commit

Permalink
fix: support for more complex Array Tuple params (#268)
Browse files Browse the repository at this point in the history
  • Loading branch information
simPod authored Oct 21, 2024
1 parent 4384ce7 commit eddc8c2
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 7 deletions.
54 changes: 47 additions & 7 deletions src/Param/ParamValueConverterRegistry.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@
use function explode;
use function implode;
use function in_array;
use function is_array;
use function is_string;
use function json_encode;
use function sprintf;
use function str_replace;
use function strlen;
use function strtolower;
use function trim;

Expand Down Expand Up @@ -101,7 +103,7 @@ public function __construct()
return $v;
}

$types = array_map(static fn ($type) => explode(' ', trim($type))[1], explode(',', $type->params));
$types = array_map(static fn ($type) => explode(' ', trim($type))[1], $this->splitTypes($type->params));

return sprintf('[%s]', implode(',', array_map(
fn (array $row) => sprintf('(%s)', implode(',', array_map(
Expand Down Expand Up @@ -167,17 +169,23 @@ public function __construct()
return $this->get($innerType)($v, $innerType, true);
}, $v),
)),
'Tuple' => function (array|string $v, Type $type) {
if (is_string($v)) {
'Tuple' => function (mixed $v, Type $type) {
if (! is_array($v)) {
return $v;
}

$types = array_map(static fn ($p) => trim($p), explode(',', $type->params));
$innerTypes = $this->splitTypes($type->params);

return '(' . implode(
$innerExpression = implode(
',',
array_map(fn (mixed $i) => $this->get($types[$i])($v[$i], null, true), array_keys($v)),
) . ')';
array_map(function (int $i) use ($innerTypes, $v) {
$innerType = Type::fromString($innerTypes[$i]);

return $this->get($innerType)($v[$i], $innerType, true);
}, array_keys($v)),
);

return '(' . $innerExpression . ')';
},
];
$this->registry = $registry;
Expand Down Expand Up @@ -254,4 +262,36 @@ private static function dateIntervalConverter(): Closure
{
return static fn (int|float $v) => $v;
}

/** @return list<string> */
private function splitTypes(string $types): array
{
$result = [];
$depth = 0;
$current = '';

for ($i = 0; $i < strlen($types); $i++) {
$char = $types[$i];
if ($char === '(') {
$depth++;
} elseif ($char === ')') {
$depth--;
} elseif ($char === ',' && $depth === 0) {
$result[] = $current;
$current = '';

continue;
}

$current .= $char;
}

$current = trim($current);

if ($current !== '') {
$result[] = $current;
}

return $result;
}
}
6 changes: 6 additions & 0 deletions tests/Param/ParamValueConverterRegistryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,12 @@ public static function providerConvert(): Generator
yield 'Array LC' => ['Array(LowCardinality(String))', "['foo','bar']", "['foo','bar']"];
yield 'Array (array)' => ['Array(String)', ['foo', 'bar'], "['foo','bar']"];
yield 'Array Tuple' => ['Array(Tuple(String, String))', [['foo', 'bar']], "[('foo','bar')]"];
yield 'Array Tuple Complex' => [
'Array(Tuple(Tuple(UInt32, UUID), String))',
[[[1, '084caa96-915b-449d-8fc6-0292c73d6399'], 'bar']],
"[((1,'084caa96-915b-449d-8fc6-0292c73d6399'),'bar')]",
];

yield 'Tuple' => ['Tuple(String, Int8)', "('k',1)", "('k',1)"];
yield 'Tuple (array)' => ['Tuple(String, Int8)', ['k', 1], "('k',1)"];

Expand Down

0 comments on commit eddc8c2

Please sign in to comment.