Skip to content

Commit

Permalink
Allow to group by uuid/datetime objects without casting them to scala…
Browse files Browse the repository at this point in the history
…r first (#998)
  • Loading branch information
norberttech authored Feb 21, 2024
1 parent ff5fb79 commit 5eb5fc8
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 29 deletions.
38 changes: 24 additions & 14 deletions src/core/etl/src/Flow/ETL/GroupBy.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Flow\ETL\Exception\InvalidArgumentException;
use Flow\ETL\Exception\RuntimeException;
use Flow\ETL\Function\AggregatingFunction;
use Flow\ETL\Row\Entry;
use Flow\ETL\Row\Reference;
use Flow\ETL\Row\References;

Expand Down Expand Up @@ -59,13 +60,7 @@ public function group(Rows $rows) : void
if ($this->pivot) {
foreach ($rows as $row) {
try {
$pivotValue = $row->valueOf($this->pivot);

if (!\is_scalar($pivotValue) && null !== $pivotValue) {
throw new RuntimeException('Pivoting by non scalar values is not supported, given: ' . \gettype($pivotValue));
}

$this->pivotColumns[] = $pivotValue;
$this->pivotColumns[] = $this->toScalar($row->get($this->pivot));
} catch (InvalidArgumentException) {
$this->pivotColumns[] = null;
}
Expand Down Expand Up @@ -99,13 +94,7 @@ public function group(Rows $rows) : void

foreach ($this->refs as $ref) {
try {
$value = $row->valueOf($ref);

if (!\is_scalar($value) && null !== $value) {
throw new RuntimeException('Grouping by non scalar values is not supported, given: ' . \gettype($value));
}

$values[$ref->name()] = $value;
$values[$ref->name()] = $this->toScalar($row->get($ref));
} catch (InvalidArgumentException) {
$values[$ref->name()] = null;
}
Expand Down Expand Up @@ -204,4 +193,25 @@ private function hash(array $values) : string

return \hash('xxh128', \implode('', $stringValues));
}

private function toScalar(Entry $entry) : int|string|float|null
{
if ($entry->value() === null) {
return null;
}

if (\is_bool($entry->value())) {
return $entry->toString();
}

if (\is_scalar($entry->value())) {
return $entry->value();
}

return match ($entry::class) {
Entry\UuidEntry::class => $entry->value()->toString(),
Entry\DateTimeEntry::class => $entry->value()->format(\DateTimeImmutable::ATOM),
default => $entry->toString()
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use function Flow\ETL\DSL\from_memory;
use function Flow\ETL\DSL\from_rows;
use function Flow\ETL\DSL\int_entry;
use function Flow\ETL\DSL\integer_entry;
use function Flow\ETL\DSL\lit;
use function Flow\ETL\DSL\max;
use function Flow\ETL\DSL\null_entry;
Expand All @@ -24,6 +25,7 @@
use Flow\ETL\Row;
use Flow\ETL\Rows;
use Flow\ETL\Tests\Integration\IntegrationTestCase;
use Ramsey\Uuid\Uuid;

final class GroupByTest extends IntegrationTestCase
{
Expand Down Expand Up @@ -216,6 +218,28 @@ public function test_group_by_twice() : void
);
}

public function test_group_by_uuid() : void
{
$rows = df()
->read(from_array([
['id' => Uuid::uuid4()->toString()],
['id' => Uuid::uuid4()->toString()],
['id' => Uuid::uuid4()->toString()],
['id' => Uuid::uuid4()->toString()],
['id' => Uuid::uuid4()->toString()],
['id' => Uuid::uuid4()->toString()],
['id' => Uuid::uuid4()->toString()],
['id' => Uuid::uuid4()->toString()],
]))
->aggregate(count(ref('id')))
->fetch();

$this->assertEquals(
new Rows(Row::create(integer_entry('id_count', 8))),
$rows
);
}

public function test_pivot() : void
{
$dataset1 = [
Expand Down
15 changes: 0 additions & 15 deletions src/core/etl/tests/Flow/ETL/Tests/Unit/GroupByTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

namespace Flow\ETL\Tests\Unit;

use function Flow\ETL\DSL\array_entry;
use function Flow\ETL\DSL\int_entry;
use function Flow\ETL\DSL\null_entry;
use function Flow\ETL\DSL\ref;
Expand All @@ -21,20 +20,6 @@

final class GroupByTest extends TestCase
{
public function test_group_by_array_entry() : void
{
$this->expectExceptionMessage('Grouping by non scalar values is not supported, given: array');
$this->expectException(RuntimeException::class);

$groupBy = new GroupBy('array');

$groupBy->group(new Rows(
Row::create(array_entry('array', [1, 2, 3])),
Row::create(array_entry('array', [1, 2, 3])),
Row::create(array_entry('array', [4, 5, 6]))
));
}

public function test_group_by_missing_entry() : void
{
$groupBy = new GroupBy('type');
Expand Down

0 comments on commit 5eb5fc8

Please sign in to comment.