Skip to content

Commit 7bc7779

Browse files
authored
Added coalesce scalar function (#1268)
1 parent 9a9b956 commit 7bc7779

File tree

4 files changed

+87
-4
lines changed

4 files changed

+87
-4
lines changed

src/core/etl/src/Flow/ETL/DSL/functions.php

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@
1414
use Flow\ETL\Function\ArraySort\Sort;
1515
use Flow\ETL\Function\Between\Boundary;
1616
use Flow\ETL\Function\StyleConverter\StringStyles;
17-
use Flow\ETL\Function\{
18-
All,
17+
use Flow\ETL\Function\{All,
1918
Any,
2019
ArrayGet,
2120
ArrayGetCollection,
@@ -32,6 +31,7 @@
3231
CallMethod,
3332
Capitalize,
3433
Cast,
34+
Coalesce,
3535
Collect,
3636
CollectUnique,
3737
Combine,
@@ -74,8 +74,7 @@
7474
ToUpper,
7575
Ulid,
7676
Uuid,
77-
When
78-
};
77+
When};
7978
use Flow\ETL\Loader\StreamLoader\Output;
8079
use Flow\ETL\Loader\{ArrayLoader, CallbackLoader, MemoryLoader, StreamLoader, TransformerLoader};
8180
use Flow\ETL\Memory\Memory;
@@ -834,6 +833,12 @@ function cast(mixed $value, ScalarFunction|string|Type $type) : Cast
834833
return new Cast($value, $type);
835834
}
836835

836+
#[DocumentationDSL(module: Module::CORE, type: DSLType::SCALAR_FUNCTION)]
837+
function coalesce(ScalarFunction ...$values) : Coalesce
838+
{
839+
return new Coalesce(...$values);
840+
}
841+
837842
#[DocumentationDSL(module: Module::CORE, type: DSLType::AGGREGATING_FUNCTION)]
838843
function count(EntryReference $function) : Count
839844
{
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Flow\ETL\Function;
6+
7+
use Flow\ETL\Row;
8+
9+
final class Coalesce extends ScalarFunctionChain
10+
{
11+
/**
12+
* @param array<ScalarFunction> $values
13+
*/
14+
private array $values;
15+
16+
public function __construct(
17+
ScalarFunction ...$values,
18+
) {
19+
$this->values = $values;
20+
}
21+
22+
public function eval(Row $row) : mixed
23+
{
24+
foreach ($this->values as $value) {
25+
try {
26+
$result = (new Parameter($value))->eval($row);
27+
} catch (\Exception $e) {
28+
continue;
29+
}
30+
31+
if ($result !== null) {
32+
return $result;
33+
}
34+
}
35+
36+
return null;
37+
}
38+
}

src/core/etl/src/Flow/ETL/Function/ScalarFunctionChain.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@ public function cast(ScalarFunction|string|Type $type) : self
7676
return new Cast($this, $type);
7777
}
7878

79+
public function coalesce(ScalarFunction ...$params) : self
80+
{
81+
return new Coalesce($this, ...$params);
82+
}
83+
7984
public function concat(ScalarFunction|string ...$params) : self
8085
{
8186
return new Concat($this, ...$params);
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Flow\ETL\Tests\Unit\Function;
6+
7+
use function Flow\ETL\DSL\{coalesce, int_entry, lit, ref, row};
8+
use PHPUnit\Framework\TestCase;
9+
10+
final class CoalesceTest extends TestCase
11+
{
12+
public function test_coalesce_entries() : void
13+
{
14+
self::assertSame(
15+
1,
16+
coalesce(ref('name'), ref('id'), lit('N/A'))->eval(row(int_entry('id', 1)))
17+
);
18+
}
19+
20+
public function test_coalesce_on_lit_and_non_existing_entries() : void
21+
{
22+
self::assertSame(
23+
'N/A',
24+
coalesce(ref('non_existing'), ref('string'), lit('N/A'))->eval(row(int_entry('id', 1)))
25+
);
26+
}
27+
28+
public function test_coalesce_on_ref() : void
29+
{
30+
self::assertSame(
31+
1,
32+
ref('name')->coalesce(ref('id'), lit('N/A'))->eval(row(int_entry('id', 1)))
33+
);
34+
}
35+
}

0 commit comments

Comments
 (0)