Skip to content

Commit

Permalink
reorder entries (#1059)
Browse files Browse the repository at this point in the history
* Allow to change order of entries through select transformation

* Added dedicated transformer allowing developers to reorder entries by custom strategies

* Added entries reorder example

* CS Fixes

* Fixed static analysis errors
  • Loading branch information
norberttech authored Apr 27, 2024
1 parent cc7013a commit 6dd9cce
Show file tree
Hide file tree
Showing 25 changed files with 796 additions and 205 deletions.
10 changes: 5 additions & 5 deletions examples/topics/data_frame/cache/output.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
+----------+----------+---------------------+--------------+-----------+-----------------------------+----------------------+
| login | name | blog | public_repos | followers | html_url | created_at |
+----------+----------+---------------------+--------------+-----------+-----------------------------+----------------------+
| flow-php | Flow PHP | http://flow-php.com | 30 | 89 | https://github.com/flow-php | 2020-10-26T18:40:27Z |
+----------+----------+---------------------+--------------+-----------+-----------------------------+----------------------+
+----------+-----------------------------+---------------------+----------+--------------+-----------+----------------------+
| name | html_url | blog | login | public_repos | followers | created_at |
+----------+-----------------------------+---------------------+----------+--------------+-----------+----------------------+
| Flow PHP | https://github.com/flow-php | http://flow-php.com | flow-php | 30 | 89 | 2020-10-26T18:40:27Z |
+----------+-----------------------------+---------------------+----------+--------------+-----------+----------------------+
1 rows
87 changes: 87 additions & 0 deletions examples/topics/data_frame/reorder_entries/code.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<?php

declare(strict_types=1);

use function Flow\ETL\DSL\{array_entry,
bool_entry,
compare_entries_by_type_and_name,
data_frame,
datetime_entry,
float_entry,
from_rows,
int_entry,
json_entry,
list_entry,
map_entry,
object_entry,
row,
rows,
str_entry,
struct_element,
struct_entry,
struct_type,
to_output,
to_stream,
type_float,
type_int,
type_list,
type_map,
type_string,
uuid_entry};
use Ramsey\Uuid\Uuid;

data_frame()
->read(from_rows(rows(
row(
int_entry('int_a', 1),
int_entry('int_b', 1),
float_entry('float_a', \random_int(100, 100000) / 100),
float_entry('float_b', \random_int(100, 100000) / 100),
bool_entry('bool', false),
bool_entry('bool_a', false),
bool_entry('bool_c', false),
datetime_entry('datetime_d', new DateTimeImmutable('now')),
datetime_entry('datetime_z', new DateTimeImmutable('now')),
str_entry('string_a', 'string'),
str_entry('string_b', 'string'),
uuid_entry('uuid', new Flow\ETL\Row\Entry\Type\Uuid(Uuid::uuid4())),
json_entry('json', ['id' => 1, 'status' => 'NEW']),
array_entry(
'array',
[
['id' => 1, 'status' => 'NEW'],
['id' => 2, 'status' => 'PENDING'],
]
),
list_entry('list', [1, 2, 3], type_list(type_int())),
map_entry('map', [0 => 'zero', 1 => 'one', 2 => 'two'], type_map(type_int(), type_string())),
struct_entry(
'struct',
[
'street' => 'street',
'city' => 'city',
'zip' => 'zip',
'country' => 'country',
'location' => ['lat' => 1.5, 'lon' => 1.5],
],
struct_type([
struct_element('street', type_string()),
struct_element('city', type_string()),
struct_element('zip', type_string()),
struct_element('country', type_string()),
struct_element(
'location',
struct_type([
struct_element('lat', type_float()),
struct_element('lon', type_float()),
])
),
]),
),
object_entry('object', new ArrayIterator([1, 2, 3])),
)
)))
->reorderEntries(compare_entries_by_type_and_name())
->write(to_output(false))
->write(to_stream(__DIR__ . '/output.txt', truncate: false))
->run();
6 changes: 6 additions & 0 deletions examples/topics/data_frame/reorder_entries/output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
+--------------------------------------+-------+-------+-------+--------+--------+---------+---------+---------------------------+---------------------------+----------+----------+-------------------------------------------------------+---------+-------------------------+----------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+
| uuid | int_a | int_b | bool | bool_a | bool_c | float_a | float_b | datetime_d | datetime_z | string_a | string_b | array | list | json | map | object | struct |
+--------------------------------------+-------+-------+-------+--------+--------+---------+---------+---------------------------+---------------------------+----------+----------+-------------------------------------------------------+---------+-------------------------+----------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+
| 1fb2af91-332b-409f-b314-d26969651f1d | 1 | 1 | false | false | false | 468.02 | 75.21 | 2024-04-27T14:24:02+00:00 | 2024-04-27T14:24:02+00:00 | string | string | [{"id":1,"status":"NEW"},{"id":2,"status":"PENDING"}] | [1,2,3] | {"id":1,"status":"NEW"} | ["zero","one","two"] | ArrayIterator Object( [storage:ArrayIterator:private] => Array ( [0] => 1 [1] => 2 [2] => 3 )) | {"street":"street","city":"city","zip":"zip","country":"country","location":{"lat":1.5,"lon":1.5}} |
+--------------------------------------+-------+-------+-------+--------+--------+---------+---------+---------------------------+---------------------------+----------+----------+-------------------------------------------------------+---------+-------------------------+----------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+
1 rows
10 changes: 5 additions & 5 deletions examples/topics/data_source/http_dynamic/output.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
+----------+----------+---------------------+--------------+-----------+-----------------------------+----------------------+
| login | name | blog | public_repos | followers | html_url | created_at |
+----------+----------+---------------------+--------------+-----------+-----------------------------+----------------------+
| flow-php | Flow PHP | http://flow-php.com | 30 | 91 | https://github.com/flow-php | 2020-10-26T18:40:27Z |
+----------+----------+---------------------+--------------+-----------+-----------------------------+----------------------+
+----------+-----------------------------+---------------------+----------+--------------+-----------+----------------------+
| name | html_url | blog | login | public_repos | followers | created_at |
+----------+-----------------------------+---------------------+----------+--------------+-----------+----------------------+
| Flow PHP | https://github.com/flow-php | http://flow-php.com | flow-php | 30 | 91 | 2020-10-26T18:40:27Z |
+----------+-----------------------------+---------------------+----------+--------------+-----------+----------------------+
1 rows
126 changes: 83 additions & 43 deletions src/core/etl/src/Flow/ETL/DSL/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
use Flow\ETL\Row\Factory\NativeEntryFactory;
use Flow\ETL\Row\Schema\Formatter\ASCIISchemaFormatter;
use Flow\ETL\Row\Schema\{Definition, Matcher\EvolvingSchemaMatcher, Matcher\StrictSchemaMatcher, SchemaFormatter};
use Flow\ETL\Row\{EntryFactory, EntryReference, Reference, References, Schema};
use Flow\ETL\Row\{Entry, EntryFactory, EntryReference, Reference, References, Schema};
use Flow\ETL\{Config,
ConfigBuilder,
DataFrame,
Expand Down Expand Up @@ -176,121 +176,124 @@ function to_branch(ScalarFunction $condition, Loader $loader) : Loader
/**
* @param array<mixed> $data
*/
function array_entry(string $array, ?array $data) : Row\Entry\ArrayEntry
function array_entry(string $array, ?array $data) : Entry\ArrayEntry
{
return new Row\Entry\ArrayEntry($array, $data);
return new Entry\ArrayEntry($array, $data);
}

function bool_entry(string $name, ?bool $value) : Row\Entry\BooleanEntry
function bool_entry(string $name, ?bool $value) : Entry\BooleanEntry
{
return new Row\Entry\BooleanEntry($name, $value);
return new Entry\BooleanEntry($name, $value);
}

function boolean_entry(string $name, ?bool $value) : Row\Entry\BooleanEntry
function boolean_entry(string $name, ?bool $value) : Entry\BooleanEntry
{
return bool_entry($name, $value);
}

function datetime_entry(string $name, \DateTimeInterface|string|null $value) : Row\Entry\DateTimeEntry
function datetime_entry(string $name, \DateTimeInterface|string|null $value) : Entry\DateTimeEntry
{
return new Row\Entry\DateTimeEntry($name, $value);
return new Entry\DateTimeEntry($name, $value);
}

function int_entry(string $name, ?int $value) : Row\Entry\IntegerEntry
function int_entry(string $name, ?int $value) : Entry\IntegerEntry
{
return new Row\Entry\IntegerEntry($name, $value);
return new Entry\IntegerEntry($name, $value);
}

function integer_entry(string $name, ?int $value) : Row\Entry\IntegerEntry
function integer_entry(string $name, ?int $value) : Entry\IntegerEntry
{
return int_entry($name, $value);
}

function enum_entry(string $name, ?\UnitEnum $enum) : Row\Entry\EnumEntry
function enum_entry(string $name, ?\UnitEnum $enum) : Entry\EnumEntry
{
return new Row\Entry\EnumEntry($name, $enum);
return new Entry\EnumEntry($name, $enum);
}

function float_entry(string $name, ?float $value) : Row\Entry\FloatEntry
function float_entry(string $name, ?float $value) : Entry\FloatEntry
{
return new Row\Entry\FloatEntry($name, $value);
return new Entry\FloatEntry($name, $value);
}

function json_entry(string $name, array|string|null $data) : Row\Entry\JsonEntry
function json_entry(string $name, array|string|null $data) : Entry\JsonEntry
{
return new Row\Entry\JsonEntry($name, $data);
return new Entry\JsonEntry($name, $data);
}

/**
* @throws InvalidArgumentException
*/
function json_object_entry(string $name, array|string|null $data) : Row\Entry\JsonEntry
function json_object_entry(string $name, array|string|null $data) : Entry\JsonEntry
{
if (\is_string($data)) {
return new Row\Entry\JsonEntry($name, $data);
return new Entry\JsonEntry($name, $data);
}

return Row\Entry\JsonEntry::object($name, $data);
return Entry\JsonEntry::object($name, $data);
}

function object_entry(string $name, ?object $data) : Row\Entry\ObjectEntry
function object_entry(string $name, ?object $data) : Entry\ObjectEntry
{
return new Row\Entry\ObjectEntry($name, $data);
return new Entry\ObjectEntry($name, $data);
}

function obj_entry(string $name, ?object $data) : Row\Entry\ObjectEntry
function obj_entry(string $name, ?object $data) : Entry\ObjectEntry
{
return object_entry($name, $data);
}

function str_entry(string $name, ?string $value) : Row\Entry\StringEntry
function str_entry(string $name, ?string $value) : Entry\StringEntry
{
return new Row\Entry\StringEntry($name, $value);
return new Entry\StringEntry($name, $value);
}

function string_entry(string $name, ?string $value) : Row\Entry\StringEntry
function string_entry(string $name, ?string $value) : Entry\StringEntry
{
return str_entry($name, $value);
}

function uuid_entry(string $name, Row\Entry\Type\Uuid|string|null $value) : Row\Entry\UuidEntry
function uuid_entry(string $name, Entry\Type\Uuid|string|null $value) : Entry\UuidEntry
{
return new Row\Entry\UuidEntry($name, $value);
return new Entry\UuidEntry($name, $value);
}

function xml_entry(string $name, \DOMDocument|string|null $value) : Row\Entry\XMLEntry
function xml_entry(string $name, \DOMDocument|string|null $value) : Entry\XMLEntry
{
return new Row\Entry\XMLEntry($name, $value);
return new Entry\XMLEntry($name, $value);
}

function xml_node_entry(string $name, ?\DOMNode $value) : Row\Entry\XMLNodeEntry
function xml_node_entry(string $name, ?\DOMNode $value) : Entry\XMLNodeEntry
{
return new Row\Entry\XMLNodeEntry($name, $value);
return new Entry\XMLNodeEntry($name, $value);
}

function entries(Row\Entry ...$entries) : Row\Entries
function entries(Entry ...$entries) : Row\Entries
{
return new Row\Entries(...$entries);
}

function struct_entry(string $name, ?array $value, StructureType $type) : Row\Entry\StructureEntry
function struct_entry(string $name, ?array $value, StructureType $type) : Entry\StructureEntry
{
return new Row\Entry\StructureEntry($name, $value, $type);
return new Entry\StructureEntry($name, $value, $type);
}

function structure_entry(string $name, ?array $value, StructureType $type) : Row\Entry\StructureEntry
function structure_entry(string $name, ?array $value, StructureType $type) : Entry\StructureEntry
{
return new Row\Entry\StructureEntry($name, $value, $type);
return new Entry\StructureEntry($name, $value, $type);
}

/**
* @param array<string, StructureElement> $elements
* @param array<StructureElement> $elements
*/
function struct_type(array $elements, bool $nullable = false) : StructureType
{
return new StructureType($elements, $nullable);
}

/**
* @param array<StructureElement> $elements
*/
function structure_type(array $elements, bool $nullable = false) : StructureType
{
return new StructureType($elements, $nullable);
Expand All @@ -314,9 +317,9 @@ function structure_element(string $name, Type $type) : StructureElement
return new StructureElement($name, $type);
}

function list_entry(string $name, array $value, ListType $type) : Row\Entry\ListEntry
function list_entry(string $name, array $value, ListType $type) : Entry\ListEntry
{
return new Row\Entry\ListEntry($name, $value, $type);
return new Entry\ListEntry($name, $value, $type);
}

function type_list(Type $element, bool $nullable = false) : ListType
Expand All @@ -329,9 +332,9 @@ function type_map(ScalarType $key_type, Type $value_type, bool $nullable = false
return new MapType(new MapKey($key_type), new MapValue($value_type), $nullable);
}

function map_entry(string $name, ?array $value, MapType $mapType) : Row\Entry\MapEntry
function map_entry(string $name, ?array $value, MapType $mapType) : Entry\MapEntry
{
return new Row\Entry\MapEntry($name, $value, $mapType);
return new Entry\MapEntry($name, $value, $mapType);
}

function type_json(bool $nullable = false) : JsonType
Expand Down Expand Up @@ -424,7 +427,7 @@ function type_enum(string $class, bool $nullable = false) : EnumType
return new EnumType($class, $nullable);
}

function row(Row\Entry ...$entry) : Row
function row(Entry ...$entry) : Row
{
return Row::create(...$entry);
}
Expand Down Expand Up @@ -1163,3 +1166,40 @@ function join_on(array|Comparison $comparisons, string $joinPrefix = '') : Expre
{
return Expression::on($comparisons, $joinPrefix);
}

function compare_entries_by_name(Transformer\OrderEntries\Order $order = Transformer\OrderEntries\Order::ASC) : Transformer\OrderEntries\Comparator
{
return new Transformer\OrderEntries\NameComparator($order);
}

function compare_entries_by_name_desc() : Transformer\OrderEntries\Comparator
{
return new Transformer\OrderEntries\NameComparator(Transformer\OrderEntries\Order::DESC);
}

/**
* @param array<class-string<Entry>, int> $priorities
*/
function compare_entries_by_type(array $priorities = Transformer\OrderEntries\TypePriorities::PRIORITIES, Transformer\OrderEntries\Order $order = Transformer\OrderEntries\Order::ASC) : Transformer\OrderEntries\Comparator
{
return new Transformer\OrderEntries\TypeComparator(new Transformer\OrderEntries\TypePriorities($priorities), $order);
}

/**
* @param array<class-string<Entry>, int> $priorities
*/
function compare_entries_by_type_desc(array $priorities = Transformer\OrderEntries\TypePriorities::PRIORITIES) : Transformer\OrderEntries\Comparator
{
return new Transformer\OrderEntries\TypeComparator(new Transformer\OrderEntries\TypePriorities($priorities), Transformer\OrderEntries\Order::DESC);
}

/**
* @param array<class-string<Entry>, int> $priorities
*/
function compare_entries_by_type_and_name(array $priorities = Transformer\OrderEntries\TypePriorities::PRIORITIES, Transformer\OrderEntries\Order $order = Transformer\OrderEntries\Order::ASC) : Transformer\OrderEntries\Comparator
{
return new Transformer\OrderEntries\CombinedComparator(
new Transformer\OrderEntries\TypeComparator(new Transformer\OrderEntries\TypePriorities($priorities), $order),
new Transformer\OrderEntries\NameComparator($order)
);
}
Loading

0 comments on commit 6dd9cce

Please sign in to comment.