Skip to content

Commit 55b179a

Browse files
authored
when expression (#364)
* Added When expression * Added one more unit test for when * Make expressions expect other expressions instead of EntryReferences
1 parent f21519b commit 55b179a

31 files changed

Lines changed: 258 additions & 114 deletions
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use function Flow\ETL\DSL\lit;
6+
use function Flow\ETL\DSL\ref;
7+
use function Flow\ETL\DSL\when;
8+
use Flow\ETL\DSL\Entry;
9+
use Flow\ETL\DSL\From;
10+
use Flow\ETL\DSL\To;
11+
use Flow\ETL\Flow;
12+
use Flow\ETL\Row;
13+
use Flow\ETL\Rows;
14+
15+
require __DIR__ . '/../../bootstrap.php';
16+
17+
(new Flow())
18+
->read(From::sequence_number('number', 0, 100))
19+
->collect()
20+
->withEntry(
21+
'type',
22+
when(
23+
ref('number')->isOdd(),
24+
then: lit('odd'),
25+
else: lit('even')
26+
)
27+
)
28+
->write(To::output(false))
29+
->run();
30+
31+
(new Flow())
32+
->read(From::rows(new Rows(
33+
Row::with(Entry::int('id', 1), Entry::int('value', 1)),
34+
Row::with(Entry::int('id', 2), Entry::int('value', 1)),
35+
Row::with(Entry::int('id', 3), Entry::null('value')),
36+
Row::with(Entry::int('id', 4), Entry::int('value', 1)),
37+
Row::with(Entry::int('id', 5), Entry::null('value')),
38+
)))
39+
->withEntry(
40+
'value',
41+
when(ref('value')->isNull(), then: lit(0))
42+
)
43+
->write(To::output(false))
44+
->run();

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Flow\ETL\Exception\InvalidArgumentException;
88
use Flow\ETL\Row\EntryReference;
99
use Flow\ETL\Row\Reference;
10+
use Flow\ETL\Row\Reference\Expression;
1011
use Flow\ETL\Row\Reference\Expression\Literal;
1112
use Flow\ETL\Row\StructureReference;
1213

@@ -43,7 +44,12 @@ function struct(string ...$entries) : StructureReference
4344
return new StructureReference($entry, ...$entries);
4445
}
4546

46-
function lit(mixed $value) : Literal
47+
function lit(mixed $value) : Expression
4748
{
4849
return new Literal($value);
4950
}
51+
52+
function when(Expression $ref, Expression $then, Expression $else = null) : Expression
53+
{
54+
return new Expression\When($ref, $then, $else);
55+
}

src/core/etl/src/Flow/ETL/DataFrame.php

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
use Flow\ETL\Pipeline\VoidPipeline;
2424
use Flow\ETL\Row\EntryReference;
2525
use Flow\ETL\Row\Reference;
26-
use Flow\ETL\Row\Reference\Expression\Literal;
2726
use Flow\ETL\Row\References;
2827
use Flow\ETL\Row\Schema;
2928
use Flow\ETL\Row\Sort;
@@ -163,9 +162,9 @@ public function fetch(?int $limit = null) : Rows
163162
/**
164163
* @param callable(Row $row) : bool|EntryReference $callback
165164
*/
166-
public function filter(callable|EntryReference $callback) : self
165+
public function filter(callable|Reference\Expression $callback) : self
167166
{
168-
if ($callback instanceof EntryReference) {
167+
if ($callback instanceof Reference\Expression) {
169168
$this->pipeline->add(new EntryExpressionFilterTransformer($callback));
170169
}
171170

@@ -460,7 +459,7 @@ public function void() : self
460459
return $this;
461460
}
462461

463-
public function withEntry(string $entryName, EntryReference|Literal $ref) : self
462+
public function withEntry(string $entryName, Reference\Expression $ref) : self
464463
{
465464
$this->transform(new EntryExpressionEvalTransformer($entryName, $ref));
466465

src/core/etl/src/Flow/ETL/Row/EntryReference.php

Lines changed: 57 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44

55
namespace Flow\ETL\Row;
66

7+
use function Flow\ETL\DSL\lit;
78
use Flow\ETL\Exception\InvalidArgumentException;
89
use Flow\ETL\Row;
10+
use Flow\ETL\Row\Reference\Expression;
911
use Flow\ETL\Row\Reference\Expression\Contains;
1012
use Flow\ETL\Row\Reference\Expression\Divide;
1113
use Flow\ETL\Row\Reference\Expression\EndsWith;
@@ -34,7 +36,7 @@
3436
/**
3537
* @implements Reference<array{entry: string, alias: ?string, expressions: Expressions}>
3638
*/
37-
final class EntryReference implements Reference
39+
final class EntryReference implements Expression, Reference
3840
{
3941
private ?string $alias = null;
4042

@@ -91,9 +93,9 @@ public function asc() : self
9193
return $this;
9294
}
9395

94-
public function contains(self|string|Literal $needle) : self
96+
public function contains(string|Expression $needle) : self
9597
{
96-
$this->expressions->add(new Contains($this, $needle instanceof Literal ? $needle : self::init($needle)));
98+
$this->expressions->add(new Contains($this, \is_string($needle) ? self::init($needle) : $needle));
9799

98100
return $this;
99101
}
@@ -105,23 +107,23 @@ public function desc() : self
105107
return $this;
106108
}
107109

108-
public function divide(self|string|Literal $ref) : self
110+
public function divide(string|Expression $ref) : self
109111
{
110-
$this->expressions = $this->expressions->add(new Divide($this, $ref instanceof Literal ? $ref : self::init($ref)));
112+
$this->expressions = $this->expressions->add(new Divide($this, \is_string($ref)? self::init($ref) : $ref));
111113

112114
return $this;
113115
}
114116

115-
public function endsWith(self|string|Literal $needle) : self
117+
public function endsWith(string|Expression $needle) : self
116118
{
117-
$this->expressions->add(new EndsWith($this, $needle instanceof Literal ? $needle : self::init($needle)));
119+
$this->expressions->add(new EndsWith($this, \is_string($needle) ? self::init($needle) : $needle));
118120

119121
return $this;
120122
}
121123

122-
public function equals(self|string|Literal $ref) : self
124+
public function equals(string|Expression $ref) : self
123125
{
124-
$this->expressions = $this->expressions->add(new Equals($this, $ref instanceof Literal ? $ref : self::init($ref)));
126+
$this->expressions = $this->expressions->add(new Equals($this, \is_string($ref) ? self::init($ref) : $ref));
125127

126128
return $this;
127129
}
@@ -136,16 +138,16 @@ public function expressions() : Expressions
136138
return $this->expressions;
137139
}
138140

139-
public function greaterThan(self|string|Literal $ref) : self
141+
public function greaterThan(string|Expression $ref) : self
140142
{
141-
$this->expressions = $this->expressions->add(new GreaterThan($this, $ref instanceof Literal ? $ref : self::init($ref)));
143+
$this->expressions = $this->expressions->add(new GreaterThan($this, \is_string($ref) ? self::init($ref) : $ref));
142144

143145
return $this;
144146
}
145147

146-
public function greaterThanEqual(self|string|Literal $ref) : self
148+
public function greaterThanEqual(string|Expression $ref) : self
147149
{
148-
$this->expressions = $this->expressions->add(new GreaterThanEqual($this, $ref instanceof Literal ? $ref : self::init($ref)));
150+
$this->expressions = $this->expressions->add(new GreaterThanEqual($this, \is_string($ref) ? self::init($ref) : $ref));
149151

150152
return $this;
151153
}
@@ -160,9 +162,18 @@ public function is(Reference $ref) : bool
160162
return $this->name() === $ref->name();
161163
}
162164

163-
public function isIn(self|string|Literal $haystack) : self
165+
public function isEven() : self
164166
{
165-
$this->expressions->add(new IsIn($haystack instanceof Literal ? $haystack : self::init($haystack), $this));
167+
$this->expressions = $this->expressions
168+
->add(new Mod($this, lit(2)))
169+
->add(new Equals($this, lit(0)));
170+
171+
return $this;
172+
}
173+
174+
public function isIn(string|Expression $haystack) : self
175+
{
176+
$this->expressions->add(new IsIn(\is_string($haystack) ? self::init($haystack) : $haystack, $this));
166177

167178
return $this;
168179
}
@@ -181,6 +192,15 @@ public function isNull() : self
181192
return $this;
182193
}
183194

195+
public function isOdd() : self
196+
{
197+
$this->expressions = $this->expressions
198+
->add(new Mod($this, lit(2)))
199+
->add(new NotEquals($this, lit(0)));
200+
201+
return $this;
202+
}
203+
184204
/**
185205
* @param class-string<Entry> ...$entryClass
186206
*/
@@ -195,16 +215,16 @@ public function isType(string ...$entryClass) : self
195215
return $this;
196216
}
197217

198-
public function lessThan(self|string|Literal $ref) : self
218+
public function lessThan(string|Expression $ref) : self
199219
{
200-
$this->expressions = $this->expressions->add(new LessThan($this, $ref instanceof Literal ? $ref : self::init($ref)));
220+
$this->expressions = $this->expressions->add(new LessThan($this, \is_string($ref) ? self::init($ref) : $ref));
201221

202222
return $this;
203223
}
204224

205-
public function lessThanEqual(self|string|Literal $ref) : self
225+
public function lessThanEqual(string|Expression $ref) : self
206226
{
207-
$this->expressions = $this->expressions->add(new LessThanEqual($this, $ref instanceof Literal ? $ref : self::init($ref)));
227+
$this->expressions = $this->expressions->add(new LessThanEqual($this, \is_string($ref) ? self::init($ref) : $ref));
208228

209229
return $this;
210230
}
@@ -216,23 +236,23 @@ public function literal(mixed $value) : self
216236
return $this;
217237
}
218238

219-
public function minus(self|string|Literal $ref) : self
239+
public function minus(string|Expression $ref) : self
220240
{
221-
$this->expressions = $this->expressions->add(new Minus($this, $ref instanceof Literal ? $ref : self::init($ref)));
241+
$this->expressions = $this->expressions->add(new Minus($this, \is_string($ref) ? self::init($ref) : $ref));
222242

223243
return $this;
224244
}
225245

226-
public function mod(self|string|Literal $ref) : self
246+
public function mod(string|Expression $ref) : self
227247
{
228-
$this->expressions = $this->expressions->add(new Mod($this, $ref instanceof Literal ? $ref : self::init($ref)));
248+
$this->expressions = $this->expressions->add(new Mod($this, \is_string($ref) ? self::init($ref) : $ref));
229249

230250
return $this;
231251
}
232252

233-
public function multiply(self|string|Literal $ref) : self
253+
public function multiply(string|Expression $ref) : self
234254
{
235-
$this->expressions = $this->expressions->add(new Multiply($this, $ref instanceof Literal ? $ref : self::init($ref)));
255+
$this->expressions = $this->expressions->add(new Multiply($this, \is_string($ref) ? self::init($ref) : $ref));
236256

237257
return $this;
238258
}
@@ -242,37 +262,37 @@ public function name() : string
242262
return $this->alias ?? $this->entry;
243263
}
244264

245-
public function notEquals(self|string|Literal $ref) : self
265+
public function notEquals(string|Expression $ref) : self
246266
{
247-
$this->expressions = $this->expressions->add(new NotEquals($this, $ref instanceof Literal ? $ref : self::init($ref)));
267+
$this->expressions = $this->expressions->add(new NotEquals($this, \is_string($ref) ? self::init($ref) : $ref));
248268

249269
return $this;
250270
}
251271

252-
public function notSame(self|string|Literal $ref) : self
272+
public function notSame(string|Expression $ref) : self
253273
{
254-
$this->expressions = $this->expressions->add(new NotSame($this, $ref instanceof Literal ? $ref : self::init($ref)));
274+
$this->expressions = $this->expressions->add(new NotSame($this, \is_string($ref) ? self::init($ref) : $ref));
255275

256276
return $this;
257277
}
258278

259-
public function plus(self|string|Literal $ref) : self
279+
public function plus(string|Expression $ref) : self
260280
{
261-
$this->expressions = $this->expressions->add(new Plus($this, $ref instanceof Literal ? $ref : self::init($ref)));
281+
$this->expressions = $this->expressions->add(new Plus($this, \is_string($ref) ? self::init($ref) : $ref));
262282

263283
return $this;
264284
}
265285

266-
public function power(self|string|Literal $ref) : self
286+
public function power(string|Expression $ref) : self
267287
{
268-
$this->expressions = $this->expressions->add(new Power($this, $ref instanceof Literal ? $ref : self::init($ref)));
288+
$this->expressions = $this->expressions->add(new Power($this, \is_string($ref) ? self::init($ref) : $ref));
269289

270290
return $this;
271291
}
272292

273-
public function same(self|string|Literal $ref) : self
293+
public function same(string|Expression $ref) : self
274294
{
275-
$this->expressions = $this->expressions->add(new Same($this, $ref instanceof Literal ? $ref : self::init($ref)));
295+
$this->expressions = $this->expressions->add(new Same($this, \is_string($ref) ? self::init($ref) : $ref));
276296

277297
return $this;
278298
}
@@ -282,9 +302,9 @@ public function sort() : SortOrder
282302
return $this->sort;
283303
}
284304

285-
public function startsWith(self|string|Literal $needle) : self
305+
public function startsWith(string|Expression $needle) : self
286306
{
287-
$this->expressions->add(new StartsWith($this, $needle instanceof Literal ? $needle : self::init($needle)));
307+
$this->expressions->add(new StartsWith($this, \is_string($needle) ? self::init($needle) : $needle));
288308

289309
return $this;
290310
}

src/core/etl/src/Flow/ETL/Row/Reference/Expression/Contains.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,12 @@
55
namespace Flow\ETL\Row\Reference\Expression;
66

77
use Flow\ETL\Row;
8-
use Flow\ETL\Row\EntryReference;
98
use Flow\ETL\Row\Reference\Expression;
109
use Flow\ETL\Row\Reference\ValueExtractor;
1110

1211
final class Contains implements Expression
1312
{
14-
public function __construct(private readonly EntryReference $haystack, private readonly EntryReference|Literal $needle)
13+
public function __construct(private readonly Expression $haystack, private readonly Expression $needle)
1514
{
1615
}
1716

src/core/etl/src/Flow/ETL/Row/Reference/Expression/Divide.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,14 @@
55
namespace Flow\ETL\Row\Reference\Expression;
66

77
use Flow\ETL\Row;
8-
use Flow\ETL\Row\EntryReference;
98
use Flow\ETL\Row\Reference\Expression;
109
use Flow\ETL\Row\Reference\ValueExtractor;
1110

1211
final class Divide implements Expression
1312
{
1413
public function __construct(
15-
private readonly EntryReference|Literal $leftRef,
16-
private readonly EntryReference|Literal $rightRef
14+
private readonly Expression $leftRef,
15+
private readonly Expression $rightRef
1716
) {
1817
}
1918

src/core/etl/src/Flow/ETL/Row/Reference/Expression/EndsWith.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,14 @@
55
namespace Flow\ETL\Row\Reference\Expression;
66

77
use Flow\ETL\Row;
8-
use Flow\ETL\Row\EntryReference;
98
use Flow\ETL\Row\Reference\Expression;
109
use Flow\ETL\Row\Reference\ValueExtractor;
1110

1211
final class EndsWith implements Expression
1312
{
1413
public function __construct(
15-
private readonly EntryReference|Literal $haystack,
16-
private readonly EntryReference|Literal $needle
14+
private readonly Expression $haystack,
15+
private readonly Expression $needle
1716
) {
1817
}
1918

src/core/etl/src/Flow/ETL/Row/Reference/Expression/Equals.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,14 @@
55
namespace Flow\ETL\Row\Reference\Expression;
66

77
use Flow\ETL\Row;
8-
use Flow\ETL\Row\EntryReference;
98
use Flow\ETL\Row\Reference\Expression;
109
use Flow\ETL\Row\Reference\ValueExtractor;
1110

1211
final class Equals implements Expression
1312
{
1413
public function __construct(
15-
private readonly EntryReference|Literal $base,
16-
private readonly EntryReference|Literal $next
14+
private readonly Expression $base,
15+
private readonly Expression $next
1716
) {
1817
}
1918

0 commit comments

Comments
 (0)