diff --git a/.github/actions/setup-php-env/action.yml b/.github/actions/setup-php-env/action.yml index 231ed03af..62ef31c5c 100644 --- a/.github/actions/setup-php-env/action.yml +++ b/.github/actions/setup-php-env/action.yml @@ -76,7 +76,7 @@ runs: run: sudo apt-get update && sudo apt-get install -y $APT_PACKAGES - name: "Install PHP" - uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # v2 + uses: shivammathur/setup-php@eb7c497e18156a6bbabfef1d3a82760b9eda3962 # 2.40.0 with: tools: ${{ inputs.tools }} php-version: ${{ inputs.php-version }} diff --git a/documentation/upgrading.md b/documentation/upgrading.md index 4f678e750..f91993a8a 100644 --- a/documentation/upgrading.md +++ b/documentation/upgrading.md @@ -141,6 +141,28 @@ $df->withEntry('date', ref('date')->cast(type_date())) `same()` / `notSame()` stay strict. +### 15) `flow-php/etl` - an expanding `withEntry()` emits batches of at most 1,000 rows + +| Before | After | +|---------------------------------------------------|----------------------------------------------------------------------------------| +| one output batch per input batch, of any size | batches of at most 1,000 rows; an input that expands to nothing: one empty batch | +| every input column copied into every expanded row | only the columns a later `select()` / `drop()` keeps | + +### 16) `flow-php/etl` - `ScalarFunctionTransformer` refuses `array_expand()`, `NestedExpandTransformer` removed + +```php +// Before - now throws "transform() cannot contain array_expand() ..." +$df->transform(new ScalarFunctionTransformer('item', array_expand(ref('items')))); + +// After +$df->withEntry('item', array_expand(ref('items'))); +``` + +### 17) `flow-php/etl` - a serialized `Rows` holds a list of frames + +A `Rows` serialized by 0.45 (e.g. a `FilesystemCache` entry) is not read by 0.46: clear such caches after upgrading. A batch +over 2 GiB of strings in one column is now split across frames instead of throwing `OffsetOverflow`. + --- ## Upgrading from 0.44.x to 0.45.x diff --git a/src/core/etl/src/Flow/ETL/DataFrame.php b/src/core/etl/src/Flow/ETL/DataFrame.php index 67a3e7de7..f1156baad 100644 --- a/src/core/etl/src/Flow/ETL/DataFrame.php +++ b/src/core/etl/src/Flow/ETL/DataFrame.php @@ -15,6 +15,7 @@ use Flow\ETL\Executor\StatisticsCollector; use Flow\ETL\Formatter\AsciiTableFormatter; use Flow\ETL\Function\AggregatingFunction; +use Flow\ETL\Function\ExpandingFunctions; use Flow\ETL\Function\ScalarFunction; use Flow\ETL\Function\WindowFunction; use Flow\ETL\Join\Expression; @@ -835,9 +836,11 @@ public function withEntries(array $references): self */ public function withEntry(string|Definition $entry, ScalarFunction|WindowFunction $reference): self { - $this->root = $reference instanceof WindowFunction - ? new Node\WindowColumn($this->root, $entry, $reference) - : new Node\WithColumn($this->root, $entry, $reference); + $this->root = match (true) { + $reference instanceof WindowFunction => new Node\WindowColumn($this->root, $entry, $reference), + (new ExpandingFunctions())->in($reference) !== [] => new Node\ExpandColumn($this->root, $entry, $reference), + default => new Node\WithColumn($this->root, $entry, $reference), + }; return $this; } diff --git a/src/core/etl/src/Flow/ETL/Optimizer.php b/src/core/etl/src/Flow/ETL/Optimizer.php index 507fc28e2..909def532 100644 --- a/src/core/etl/src/Flow/ETL/Optimizer.php +++ b/src/core/etl/src/Flow/ETL/Optimizer.php @@ -12,6 +12,7 @@ use Flow\ETL\Optimizer\Rule\CountFromStatistics; use Flow\ETL\Optimizer\Rule\PushFilterIntoSource; use Flow\ETL\Optimizer\Rule\PushLimitIntoSource; +use Flow\ETL\Optimizer\Rule\PushProjectionIntoExpand; use Flow\ETL\Plan\LogicalPlan; use function array_diff; @@ -39,6 +40,7 @@ public static function default(): self new PushLimitIntoSource(), new PushFilterIntoSource(), new CountFromStatistics(), + new PushProjectionIntoExpand(), ); } diff --git a/src/core/etl/src/Flow/ETL/Optimizer/ProjectionWalk.php b/src/core/etl/src/Flow/ETL/Optimizer/ProjectionWalk.php new file mode 100644 index 000000000..a30634dc8 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Optimizer/ProjectionWalk.php @@ -0,0 +1,37 @@ + RequiredColumns::only(...References::init(...$node->entries)->names()), + $node instanceof Node\Drop => $above->without(...References::init(...$node->entries)->names()), + // an unpack writes "name.*", known only once bound: keep the demand, add what it reads + ($node instanceof Node\WithColumn || $node instanceof Node\ExpandColumn) + && $node->function instanceof UnpackResults + => $above->with(...$refs->in($node->function)->names()), + $node instanceof Node\WithColumn, $node instanceof Node\ExpandColumn => $above + ->without($node->name()) + ->with(...$refs->in($node->function)->names()), + $node instanceof Node\Filter => $above->with(...$refs->in($node->function)->names()), + $node instanceof Node\Limit, $node instanceof Node\Offset => $above, + default => RequiredColumns::all(), + }; + } +} diff --git a/src/core/etl/src/Flow/ETL/Optimizer/Rule/PushProjectionIntoExpand.php b/src/core/etl/src/Flow/ETL/Optimizer/Rule/PushProjectionIntoExpand.php new file mode 100644 index 000000000..4a32d1fd8 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Optimizer/Rule/PushProjectionIntoExpand.php @@ -0,0 +1,72 @@ + $demands */ + $demands = new SplObjectStorage(); + + foreach ($plan->consumerInputs() as $input) { + $required = RequiredColumns::all(); + + for ($node = $input; $node->children() !== []; $node = $node->children()[0]) { + if ($node instanceof Node\ExpandColumn) { + $demands[$node] = $demands->offsetExists($node) ? $demands[$node]->union($required) : $required; + } + + $required = $walk->below($node, $required); + } + } + + $depths = []; + $targets = []; + + foreach ($demands as $node) { + if ($demands[$node]->isAll()) { + continue; + } + + $id = spl_object_id($node); + $targets[$id] = $node; + $depths[$id] = 0; + + for ($below = $node; $below->children() !== []; $below = $below->children()[0]) { + $depths[$id]++; + } + } + + // TransformUp hands Rewrite::of() the node rebuilt over its new children, so a node whose descendant was + // replaced first would no longer be the target; the one farthest from the leaf goes first + arsort($depths); + + foreach ($depths as $id => $_) { + $plan = $plan->transformUp( + new ReplaceLeaf($targets[$id], $targets[$id]->withCarries($demands[$targets[$id]])), + ); + } + + return $plan; + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Explain/Details.php b/src/core/etl/src/Flow/ETL/Plan/Explain/Details.php index fb8733ce7..a6815e653 100644 --- a/src/core/etl/src/Flow/ETL/Plan/Explain/Details.php +++ b/src/core/etl/src/Flow/ETL/Plan/Explain/Details.php @@ -14,6 +14,7 @@ use Flow\ETL\Plan\Node\CrossJoin; use Flow\ETL\Plan\Node\Distinct; use Flow\ETL\Plan\Node\Drop; +use Flow\ETL\Plan\Node\ExpandColumn; use Flow\ETL\Plan\Node\Filter; use Flow\ETL\Plan\Node\Join; use Flow\ETL\Plan\Node\Limit; @@ -73,6 +74,7 @@ public function labelled(Node $node): array $node instanceof Filter => ['Condition: ' . $this->name($node->function)], $node instanceof Until => ['Until: ' . $this->name($node->function)], $node instanceof WithColumn => [sprintf('Column: %s = %s', $node->name(), $this->name($node->function))], + $node instanceof ExpandColumn => $this->expandColumn($node), $node instanceof Write => ['Loader: ' . $this->name($node->loader)], $node instanceof Limit => ['Limit: ' . $node->limit], $node instanceof Offset => ['Skip: ' . $node->offset], @@ -160,6 +162,21 @@ public function columns(array $entries): string : $entry, $entries)); } + /** + * @return list + */ + public function expandColumn(ExpandColumn $node): array + { + $lines = [sprintf('Column: %s = %s', $node->name(), $this->name($node->function))]; + + return match (true) { + $node->carries->isAll() => $lines, + $node->carries->allBut => [...$lines, 'Keeps: every column but ' . implode(', ', $node->carries->names)], + $node->carries->names === [] => [...$lines, 'Keeps: no input column'], + default => [...$lines, 'Keeps: ' . implode(', ', $node->carries->names)], + }; + } + /** * @return list */ diff --git a/src/core/etl/src/Flow/ETL/Plan/Node/ExpandColumn.php b/src/core/etl/src/Flow/ETL/Plan/Node/ExpandColumn.php new file mode 100644 index 000000000..a47633cfd --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Node/ExpandColumn.php @@ -0,0 +1,77 @@ +|string $entry + * @param null|RequiredColumns $carries what the consumers above read; null means every column + */ + public function __construct( + private Node $input, + public string|Definition $entry, + public ScalarFunction $function, + ?RequiredColumns $carries = null, + ) { + $this->carries = $carries ?? RequiredColumns::all(); + } + + /** + * @return list + */ + public function children(): array + { + return [$this->input]; + } + + public function withChildren(array $children): self + { + return $children[0] === $this->input + ? $this + : new self($children[0], $this->entry, $this->function, $this->carries); + } + + public function withCarries(RequiredColumns $carries): self + { + return new self($this->input, $this->entry, $this->function, $carries); + } + + public function rowCount(): RowCount + { + return RowCount::expanding; + } + + public function transparency(): Transparency + { + return Transparency::transparent; + } + + public function materialization(): Materialization + { + return Materialization::streaming; + } + + public function redefines(): Redefined + { + return Redefined::names($this->name()); + } + + public function name(): string + { + return $this->entry instanceof Definition ? $this->entry->entry()->name() : $this->entry; + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Node/WithColumn.php b/src/core/etl/src/Flow/ETL/Plan/Node/WithColumn.php index 45714d3db..ee6664170 100644 --- a/src/core/etl/src/Flow/ETL/Plan/Node/WithColumn.php +++ b/src/core/etl/src/Flow/ETL/Plan/Node/WithColumn.php @@ -4,7 +4,6 @@ namespace Flow\ETL\Plan\Node; -use Flow\ETL\Function\ExpandingFunctions; use Flow\ETL\Function\ScalarFunction; use Flow\ETL\Plan\Materialization; use Flow\ETL\Plan\Node; @@ -16,8 +15,6 @@ final readonly class WithColumn implements Node { - private RowCount $rowCount; - /** * @param Definition|string $entry */ @@ -25,10 +22,7 @@ public function __construct( private Node $input, public string|Definition $entry, public ScalarFunction $function, - ) { - // array_expand() can sit anywhere in the function tree, not only at its root - $this->rowCount = (new ExpandingFunctions())->in($function) === [] ? RowCount::preserving : RowCount::expanding; - } + ) {} /** * @return list @@ -45,7 +39,7 @@ public function withChildren(array $children): self public function rowCount(): RowCount { - return $this->rowCount; + return RowCount::preserving; } public function transparency(): Transparency diff --git a/src/core/etl/src/Flow/ETL/Plan/RequiredColumns.php b/src/core/etl/src/Flow/ETL/Plan/RequiredColumns.php new file mode 100644 index 000000000..9eaa06c20 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/RequiredColumns.php @@ -0,0 +1,74 @@ + $names allBut: the columns NOT required; otherwise: the only columns required + */ + private function __construct( + public bool $allBut, + public array $names, + ) {} + + public static function all(): self + { + return new self(true, []); + } + + public static function allBut(string ...$names): self + { + return new self(true, array_values(array_unique($names))); + } + + public static function only(string ...$names): self + { + return new self(false, array_values(array_unique($names))); + } + + public function isAll(): bool + { + return $this->allBut && $this->names === []; + } + + public function requires(string $name): bool + { + return $this->allBut !== in_array($name, $this->names, true); + } + + /** + * What either of two consumers reads. + */ + public function union(self $other): self + { + return match (true) { + !$this->allBut && !$other->allBut => self::only(...$this->names, ...$other->names), + $this->allBut && $other->allBut => self::allBut(...array_intersect($this->names, $other->names)), + $this->allBut => self::allBut(...array_diff($this->names, $other->names)), + default => self::allBut(...array_diff($other->names, $this->names)), + }; + } + + public function with(string ...$names): self + { + return $this->allBut + ? self::allBut(...array_diff($this->names, $names)) + : self::only(...$this->names, ...$names); + } + + public function without(string ...$names): self + { + return $this->allBut + ? self::allBut(...$this->names, ...$names) + : self::only(...array_diff($this->names, $names)); + } +} diff --git a/src/core/etl/src/Flow/ETL/Planner/NodeTranslator.php b/src/core/etl/src/Flow/ETL/Planner/NodeTranslator.php index eaab7e145..74c2e4f26 100644 --- a/src/core/etl/src/Flow/ETL/Planner/NodeTranslator.php +++ b/src/core/etl/src/Flow/ETL/Planner/NodeTranslator.php @@ -20,6 +20,7 @@ use Flow\ETL\Processor\CollectingProcessor; use Flow\ETL\Processor\ConstrainedProcessor; use Flow\ETL\Processor\CountingProcessor; +use Flow\ETL\Processor\ExpandingProcessor; use Flow\ETL\Processor\OffsetProcessor; use Flow\ETL\Processor\TopNProcessor; use Flow\ETL\Processor\VoidProcessor; @@ -81,6 +82,9 @@ public static function toSteps(Node $node, FlowContext $context, array $frames): $node instanceof Node\Discard => [new VoidProcessor()], $node instanceof Node\Distinct => [new DropDuplicatesTransformer(...$node->entries)], $node instanceof Node\Drop => [new DropEntriesTransformer(...$node->entries)], + $node instanceof Node\ExpandColumn => [ + new ExpandingProcessor($node->entry, $node->function, $node->carries), + ], $node instanceof Node\DuplicateRow => [new DuplicateRowTransformer($node->condition, ...$node->entries)], $node instanceof Node\Filter => [new ScalarFunctionFilterTransformer($node->function)], $node instanceof Node\JoinEach => match ($node->type) { diff --git a/src/core/etl/src/Flow/ETL/Processor/BoundExpansion.php b/src/core/etl/src/Flow/ETL/Processor/BoundExpansion.php new file mode 100644 index 000000000..118127f7f --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Processor/BoundExpansion.php @@ -0,0 +1,159 @@ + $gathered input columns copied into every element row, in input order + */ + public function __construct( + public Expansion $expansion, + public Transformer $inner, + public Schema $output, + public array $gathered, + ) {} + + /** + * @param Definition|string $entry + * + * @throws InvalidLogicException when $function holds no expand + */ + public static function of( + string|Definition $entry, + ScalarFunction $function, + RequiredColumns $carries, + Schema $input, + ): self { + $resolver = new ReferenceResolver(); + $resolved = $resolver->resolve($function, $input); + $resolver->assertResolved($resolved, $input); + (new ExpandingFunctions())->refuseNested($resolved); + + $expansion = Expansion::of($resolved, $input) ?? throw InvalidLogicException::because( + '%s holds no array_expand(), it is not an expansion', + $function::class, + ); + $root = $expansion->root(); + $name = $entry instanceof Definition ? $entry->entry()->name() : $entry; + $synthesized = $expansion->synthesized(); + $synthesizedNames = $synthesized->references()->names(); + $written = [$name]; + + if ($root instanceof UnpackResults) { + $written = []; + + foreach ((new UnpackedColumns()) + ->declared($root) + ->references() + ->names() as $unpacked) { + $written[] = $name . '.' . $unpacked; + } + } + + $inner = new ScalarFunctionTransformer($entry, $root); + $full = $inner->bind($input->add(...array_values($synthesized->definitions())))->output; + $output = []; + + foreach ($full->definitions() as $definition) { + $column = $definition->entry()->name(); + + if ( + !in_array($column, $synthesizedNames, true) + && (in_array($column, $written, true) || $carries->requires($column)) + ) { + $output[] = $definition; + } + } + + $rootReads = array_diff((new ReferencedColumns())->in($root)->names(), $synthesizedNames); + $gathered = []; + + foreach ($input->definitions() as $definition) { + $column = $definition->entry()->name(); + + if ( + !in_array($column, $written, true) && $carries->requires($column) + || in_array($column, $rootReads, true) + ) { + $gathered[] = $column; + } + } + + return new self( + $expansion, + type_instance_of(Transformer::class)->assert($inner->bind($input->keep(...$gathered)->add( + ...array_values($synthesized->definitions()), + ))->step), + new Schema(...$output), + $gathered, + ); + } + + /** + * Output batches of at most $batchSize rows, built one at a time. + * + * @param int<1, max> $batchSize + * + * @return Generator + */ + public function chunks(Rows $rows, FlowContext $context, int $batchSize): Generator + { + [$sources, $cells] = $this->expansion->positions($rows, $context); + + if ($sources === []) { + yield Rows::empty($this->output, $context->backend()); + + return; + } + + $present = []; + + // a batch may lack a nullable column of the bound schema; project() pads it + foreach ($this->gathered as $column) { + if ($rows->schema()->findDefinition($column) !== null) { + $present[] = $column; + } + } + + $selected = $rows->select(...$present); + + for ($offset = 0, $total = count($sources); $offset < $total; $offset += $batchSize) { + yield $this->inner->transform( + $this->expansion->elements( + $selected->gather(array_slice($sources, $offset, $batchSize)), + $cells, + $offset, + $context->backend(), + ), + $context, + )->project($this->output, $context->backend()); + } + } +} diff --git a/src/core/etl/src/Flow/ETL/Processor/ExpandingProcessor.php b/src/core/etl/src/Flow/ETL/Processor/ExpandingProcessor.php new file mode 100644 index 000000000..5e63ddf8d --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Processor/ExpandingProcessor.php @@ -0,0 +1,87 @@ + + */ + private int $batchSize; + + /** + * @param Definition|string $entry + * @param int $batchSize the most rows one output batch holds + * + * @throws InvalidArgumentException + */ + public function __construct( + private string|Definition $entry, + public ScalarFunction $function, + private RequiredColumns $carries, + int $batchSize = 1000, + private ?BoundExpansion $bound = null, + ) { + if ($batchSize < 1) { + throw new InvalidArgumentException('Batch size must be greater than 0, given: ' . $batchSize); + } + + $this->batchSize = $batchSize; + } + + public function bind(Schema $input): BoundStep + { + $bound = BoundExpansion::of($this->entry, $this->function, $this->carries, $input); + + return new BoundStep( + new self($this->entry, $this->function, $this->carries, $this->batchSize, $bound), + $bound->output, + ); + } + + /** + * @param Generator $rows + * + * @return Generator + */ + public function process(Generator $rows, FlowContext $context): Generator + { + while ($rows->valid()) { + /** @var Rows $batch */ + $batch = $rows->current(); + // a plan that refused a schema runs this step unbound + $bound = $this->bound ?? BoundExpansion::of( + $this->entry, + $this->function, + $this->carries, + $batch->schema(), + ); + + foreach ($bound->chunks($batch, $context, $this->batchSize) as $chunk) { + $signal = yield $chunk; + + if ($signal === Signal::STOP) { + $rows->send(Signal::STOP); + + return; + } + } + + $rows->next(); + } + } +} diff --git a/src/core/etl/src/Flow/ETL/Rows.php b/src/core/etl/src/Flow/ETL/Rows.php index 68f35666d..9343f4ac0 100644 --- a/src/core/etl/src/Flow/ETL/Rows.php +++ b/src/core/etl/src/Flow/ETL/Rows.php @@ -20,6 +20,7 @@ use Flow\ETL\Sort\RowOrder; use Flow\Floe\FrameDecoder; use Flow\Floe\FrameEncoder; +use Flow\Floe\SplittingFrameEncoder; use Flow\Types\Value\Json; use Generator; @@ -29,6 +30,7 @@ use function array_key_exists; use function array_keys; use function array_shift; +use function array_slice; use function array_values; use function count; use function implode; @@ -37,7 +39,7 @@ use function sprintf; /** - * @type RowsPayload = array{schema: Schema, frame: string} + * @type RowsPayload = array{schema: Schema, frames: list} */ final class Rows implements Countable { @@ -55,7 +57,13 @@ private function __construct( */ public function __serialize(): array { - return ['schema' => $this->schema, 'frame' => $this->encodeFrame()]; + $frames = []; + + foreach ((new SplittingFrameEncoder())->encode($this) as [$frame]) { + $frames[] = $frame; + } + + return ['schema' => $this->schema, 'frames' => $frames]; } /** @@ -65,7 +73,14 @@ public function __serialize(): array */ public function __unserialize(array $data): void { - $rows = (new FrameDecoder())->decode($data['frame'], $data['schema'], new AdaptiveBackend()); + $backend = new AdaptiveBackend(); + $parts = []; + + foreach ($data['frames'] as $frame) { + $parts[] = (new FrameDecoder())->decode($frame, $data['schema'], $backend); + } + + $rows = $parts[0]->concat($backend, ...array_slice($parts, 1)); $this->schema = $rows->schema; $this->columns = $rows->columns; diff --git a/src/core/etl/src/Flow/ETL/Transformer/NestedExpansion.php b/src/core/etl/src/Flow/ETL/Transformer/Expansion.php similarity index 70% rename from src/core/etl/src/Flow/ETL/Transformer/NestedExpansion.php rename to src/core/etl/src/Flow/ETL/Transformer/Expansion.php index 3b4ba1432..fd6f6f42a 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/NestedExpansion.php +++ b/src/core/etl/src/Flow/ETL/Transformer/Expansion.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Transformer; +use Flow\ETL\Column\Backend; use Flow\ETL\FlowContext; use Flow\ETL\Function\ExpandingFunctions; use Flow\ETL\Function\FunctionTree; @@ -20,6 +21,7 @@ use function array_key_exists; use function array_map; +use function array_slice; use function array_values; use function count; use function Flow\ETL\DSL\definition_from_type; @@ -27,29 +29,25 @@ use function max; use function spl_object_id; -final readonly class NestedExpansion +final readonly class Expansion { /** * @param non-empty-array $expands keyed by the synthesized column the root reads * each element from * @param array> $expandDefinitions the synthesized columns, keyed like $expands - * @param Schema $elementSchema $input with the synthesized columns, built once */ private function __construct( private ScalarFunction $root, private array $expands, - private Schema $input, private array $expandDefinitions, - private Schema $elementSchema, ) {} + /** + * Null only when the tree holds no expand. A root expand is rewritten too: its root becomes the synthesized + * reference, so a root, a nested and an unpacked expand are one shape. + */ public static function of(ScalarFunction $resolved, Schema $input): ?self { - // a root expand runs in ScalarFunctionTransformer's own loop - if ($resolved instanceof ExpandResults) { - return null; - } - $distinct = []; foreach ((new ExpandingFunctions())->in($resolved) as $expand) { @@ -82,24 +80,37 @@ public static function of(ScalarFunction $resolved, Schema $input): ?self $expands[$name] = $expand; } - /** @var ScalarFunction $root the root is not an expand, so rewrite() rebuilds it with its own class */ + /** @var ScalarFunction $root an expand is rewritten into its ResolvedReference, any other node keeps its class */ $root = self::rewrite($resolved, $references); - return new self($root, $expands, $input, $expandDefinitions, $input->add(...array_values($expandDefinitions))); + return new self($root, $expands, $expandDefinitions); } /** - * @return Type + * $gathered - the rows of output positions [$offset, $offset + count) - with the synthesized columns appended. + * + * @param array> $cells from positions() */ - public function returns(): Type + public function elements(Rows $gathered, array $cells, int $offset, Backend $backend): Rows { - return $this->root->returns(); + $columns = []; + + foreach ($cells as $name => $values) { + $builder = $backend->builder($this->expandDefinitions[$name]); + $builder->appendMany(array_slice($values, $offset, $gathered->count())); + $columns[$name] = $builder->finish(); + } + + return $gathered->withColumns($gathered->schema()->add(...array_values($this->expandDefinitions)), $columns); } /** - * @return array{list, list} [$sources, $values] + * The expand operands evaluated once: for every output position the row it comes from, and one cell per + * synthesized column - zipped to the longest list, the shorter ones padded with null. + * + * @return array{list, array>} [$sources, $cells] */ - public function eval(Rows $rows, FlowContext $context): array + public function positions(Rows $rows, FlowContext $context): array { $lists = []; @@ -134,19 +145,28 @@ public function eval(Rows $rows, FlowContext $context): array } } - $elements = $rows->gather($sources); - $schema = $elements->schema()->isSame($this->input) - ? $this->elementSchema - : $elements->schema()->add(...array_values($this->expandDefinitions)); - $columns = []; + return [$sources, $cells]; + } - foreach ($cells as $name => $values) { - $builder = $context->backend()->builder($this->expandDefinitions[$name]); - $builder->appendMany($values); - $columns[$name] = $builder->finish(); - } + /** + * @return Type + */ + public function returns(): Type + { + return $this->root->returns(); + } + + /** + * The tree with every expand replaced by the synthesized column it reads its element from. + */ + public function root(): ScalarFunction + { + return $this->root; + } - return [$sources, (new Parameter($this->root))->values($elements->withColumns($schema, $columns), $context)]; + public function synthesized(): Schema + { + return new Schema(...array_values($this->expandDefinitions)); } /** diff --git a/src/core/etl/src/Flow/ETL/Transformer/NestedExpandTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/NestedExpandTransformer.php deleted file mode 100644 index 008a90be5..000000000 --- a/src/core/etl/src/Flow/ETL/Transformer/NestedExpandTransformer.php +++ /dev/null @@ -1,111 +0,0 @@ -|Schema $declares - */ - public function __construct( - private ScalarFunctionTransformer $unbound, - private string $entryName, - private NestedExpansion $expansion, - private Definition|Schema $declares, - private Schema $output, - ) {} - - public function bind(Schema $input): BoundStep - { - return $this->unbound->bind($input); - } - - public function transform(Rows $rows, FlowContext $context): Rows - { - $context->telemetry()->transformationStarted($this, [ - TelemetryAttributes::ATTR_SCALAR_FUNCTION => $this->unbound->function::class, - ]); - - try { - $result = $this->declares instanceof Definition - ? $this->map($rows, $context, $this->declares) - : $this->unpack($rows, $context, $this->declares); - - $context->telemetry()->transformationCompleted($this, [ - TelemetryAttributes::ATTR_TRANSFORMATION_INPUT_ROWS => $rows->count(), - TelemetryAttributes::ATTR_TRANSFORMATION_OUTPUT_ROWS => $result->count(), - ]); - - return $result; - } catch (Throwable $e) { - $context->telemetry()->transformationFailed($this, $e); - - throw $e; - } - } - - /** - * @param Definition $derived - */ - private function map(Rows $rows, FlowContext $context, Definition $derived): Rows - { - $columns = new DerivedColumns(); - $declared = $columns->declare($rows->schema(), $derived); - [$sources, $values] = $this->expansion->eval($rows, $context); - - $builder = $context->backend()->builder($derived); - $builder->appendMany($values); - - return $columns->rows( - $rows->gather($sources), - $declared, - $this->output, - $derived->entry()->name(), - $builder->finish(), - $context->backend(), - ); - } - - private function unpack(Rows $rows, FlowContext $context, Schema $declared): Rows - { - $columns = new UnpackedColumns(); - $prefix = $this->entryName . '.'; - [$sources, $payloads] = $this->expansion->eval($rows, $context); - $values = []; - - foreach ($declared->definitions() as $name => $_) { - $values[$prefix . $name] = []; - } - - // @mago-ignore analysis:mixed-assignment - foreach ($payloads as $payload) { - // @mago-ignore analysis:mixed-assignment - foreach ($columns->values($prefix, $declared, type_array()->assert($payload)) as $name => $value) { - $values[$name][] = $value; - } - } - - $unpacked = []; - - foreach ($values as $name => $columnValues) { - $builder = $context->backend()->builder($this->output->get((string) $name)); - $builder->appendMany($columnValues); - $unpacked[$name] = $builder->finish(); - } - - return $rows->gather($sources)->withColumns($this->output, $unpacked); - } -} diff --git a/src/core/etl/src/Flow/ETL/Transformer/ScalarFunctionTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/ScalarFunctionTransformer.php index a182cd311..abc43ffca 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/ScalarFunctionTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/ScalarFunctionTransformer.php @@ -7,24 +7,20 @@ use Flow\ETL\BoundStep; use Flow\ETL\Config\Telemetry\TelemetryAttributes; use Flow\ETL\Exception\InvalidArgumentException; -use Flow\ETL\Exception\InvalidLogicException; use Flow\ETL\Exception\SchemaDefinitionNotFoundException; use Flow\ETL\FlowContext; use Flow\ETL\Function\ExpandingFunctions; use Flow\ETL\Function\ReferenceResolver; use Flow\ETL\Function\ScalarFunction; -use Flow\ETL\Function\ScalarFunction\ExpandResults; use Flow\ETL\Function\ScalarFunction\UnpackResults; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\Schema\Definition; use Flow\ETL\Transformer; -use Flow\Types\Type\Logical\StructureType; use Throwable; use function Flow\ETL\DSL\definition_from_type; use function Flow\Types\DSL\type_array; -use function sprintf; final readonly class ScalarFunctionTransformer implements Transformer { @@ -48,41 +44,24 @@ public function bind(Schema $input): BoundStep // withEntry() cannot describe an N-column result if ($this->function instanceof UnpackResults) { $resolved = $this->resolve($input); - $unpacked = $this->unpacked($resolved); - $output = (new UnpackedColumns())->of($input, $this->entryName() . '.', $unpacked); - $expansion = NestedExpansion::of($resolved, $input); - - return new BoundStep( - $expansion === null - ? new self($this->entry, $this->function, $resolved, null, $output) - : new NestedExpandTransformer($this, $this->entryName(), $expansion, $unpacked, $output), - $output, + $output = (new UnpackedColumns())->of( + $input, + $this->entryName() . '.', + (new UnpackedColumns())->declared($resolved), ); + + return new BoundStep(new self($this->entry, $this->function, $resolved, null, $output), $output); } $resolved = $this->resolve($input); - $expansion = NestedExpansion::of($resolved, $input); - $derived = $this->derived($expansion ?? $resolved); + $derived = $this->derived($resolved); $output = (new DerivedColumns())->declare($input, $derived); - return new BoundStep( - $expansion === null - ? new self($this->entry, $this->function, $resolved, $derived, $output) - : new NestedExpandTransformer($this, $this->entryName(), $expansion, $derived, $output), - $output, - ); + return new BoundStep(new self($this->entry, $this->function, $resolved, $derived, $output), $output); } public function transform(Rows $rows, FlowContext $context): Rows { - // only bind() can tell a nested expand from a root one - if ($this->resolved === null && (new ExpandingFunctions())->in($this->function) !== []) { - /** @var Transformer $bound bind() plans a ScalarFunctionTransformer or a NestedExpandTransformer */ - $bound = $this->bind($rows->schema())->step; - - return $bound->transform($rows, $context); - } - $context->telemetry()->transformationStarted($this, [ TelemetryAttributes::ATTR_SCALAR_FUNCTION => $this->function::class, ]); @@ -108,7 +87,7 @@ public function transform(Rows $rows, FlowContext $context): Rows /** * @return Definition */ - private function derived(ScalarFunction|NestedExpansion $source): Definition + private function derived(ScalarFunction $source): Definition { return $this->entry instanceof Definition ? $this->entry @@ -124,7 +103,7 @@ private function resolve(Schema $input): ScalarFunction $resolver = new ReferenceResolver(); $resolved = $resolver->resolve($this->function, $input); $resolver->assertResolved($resolved, $input); - (new ExpandingFunctions())->refuseNested($resolved); + (new ExpandingFunctions())->refuse($resolved, 'transform'); return $resolved; } @@ -141,75 +120,21 @@ private function map(Rows $rows, FlowContext $context): Rows $derived = $this->derived ?? $this->derived($function); $declared = $columns->declare($rows->schema(), $derived); $output = $this->output ?? $declared; - $column = $function->eval($rows, $context); - - if ($function instanceof ExpandResults) { - $sources = []; - $values = []; - - // @mago-ignore analysis:mixed-assignment - foreach ($column->values() as $index => $list) { - // @mago-ignore analysis:mixed-assignment - foreach (type_array()->assert($list) as $value) { - $sources[] = $index; - $values[] = $value; - } - } - - $builder = $context->backend()->builder($derived); - $builder->appendMany($values); - - return $columns->rows( - $rows->gather($sources), - $declared, - $output, - $derived->entry()->name(), - $builder->finish(), - $context->backend(), - ); - } - return $columns->rows( $rows, $declared, $output, $derived->entry()->name(), - $columns->stored($derived, $column, $context->backend()), + $columns->stored($derived, $function->eval($rows, $context), $context->backend()), $context->backend(), ); } - /** - * The columns unpack declares, read off returns() - the contract every ScalarFunction has. - * - * @throws InvalidLogicException - */ - private function unpacked(ScalarFunction $resolved): Schema - { - $returns = $resolved->returns(); - - if (!$returns instanceof StructureType) { - throw new InvalidLogicException(sprintf( - '%s unpacks into N columns, so returns() must be a StructureType, got "%s".', - $resolved::class, - $returns->toString(), - )); - } - - $definitions = []; - - foreach ($returns->elements() as $element) { - $definitions[] = definition_from_type((string) $element->name, $element->type); - } - - return new Schema(...$definitions); - } - private function unpack(Rows $rows, FlowContext $context): Rows { /** @var UnpackResults $function */ $function = $this->resolved ?? $this->resolve($rows->schema()); - $declared = $this->unpacked($function); + $declared = (new UnpackedColumns())->declared($function); $columns = new UnpackedColumns(); $output = $this->output ?? $columns->of($rows->schema(), $this->entryName() . '.', $declared); $prefix = $this->entryName() . '.'; diff --git a/src/core/etl/src/Flow/ETL/Transformer/UnpackedColumns.php b/src/core/etl/src/Flow/ETL/Transformer/UnpackedColumns.php index 7486640ef..00a99b2c7 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/UnpackedColumns.php +++ b/src/core/etl/src/Flow/ETL/Transformer/UnpackedColumns.php @@ -4,10 +4,42 @@ namespace Flow\ETL\Transformer; +use Flow\ETL\Exception\InvalidLogicException; +use Flow\ETL\Function\ScalarFunction; use Flow\ETL\Schema; +use Flow\Types\Type\Logical\StructureType; + +use function Flow\ETL\DSL\definition_from_type; +use function sprintf; final readonly class UnpackedColumns { + /** + * The columns unpack declares, read off returns() - the contract every ScalarFunction has. + * + * @throws InvalidLogicException + */ + public function declared(ScalarFunction $resolved): Schema + { + $returns = $resolved->returns(); + + if (!$returns instanceof StructureType) { + throw new InvalidLogicException(sprintf( + '%s unpacks into N columns, so returns() must be a StructureType, got "%s".', + $resolved::class, + $returns->toString(), + )); + } + + $definitions = []; + + foreach ($returns->elements() as $element) { + $definitions[] = definition_from_type((string) $element->name, $element->type); + } + + return new Schema(...$definitions); + } + /** * One nullable column per declared column of $declared, named "$prefix$column", added to (or * replacing in) $base in declaration order. diff --git a/src/core/etl/src/Flow/Floe/FloeStreamWriter.php b/src/core/etl/src/Flow/Floe/FloeStreamWriter.php index 609094fe8..756096da7 100644 --- a/src/core/etl/src/Flow/Floe/FloeStreamWriter.php +++ b/src/core/etl/src/Flow/Floe/FloeStreamWriter.php @@ -6,20 +6,15 @@ use Composer\InstalledVersions; use Flow\ETL\Column\Backend; -use Flow\ETL\Exception\OffsetOverflow; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\Schema\Metadata; use Flow\ETL\Schema\Validator\EvolvingValidator; use Flow\Filesystem\DestinationStream; use Flow\Floe\Exception\FloeException; -use Flow\Floe\Exception\FrameTooLarge; use Flow\Floe\Exception\IncompatibleSchemaException; use function array_key_exists; -use function array_shift; -use function array_unshift; -use function intdiv; use function sprintf; final class FloeStreamWriter @@ -58,7 +53,7 @@ final class FloeStreamWriter private int $totalRows = 0; - private readonly FrameEncoder $frameEncoder; + private readonly SplittingFrameEncoder $frameEncoder; /** * @throws FloeException @@ -70,7 +65,7 @@ public function __construct( ) { Format::validateCodecId($this->options->codec->id()); $this->sessionSchema = $schema; - $this->frameEncoder = new FrameEncoder($this->options->codec); + $this->frameEncoder = new SplittingFrameEncoder(new FrameEncoder($this->options->codec)); } /** @@ -161,31 +156,7 @@ public function write(Rows $rows): void $matched = $rows->matchTo($this->sessionSchema, $this->backend); } - $bodies = []; - $parts = [[$matched, 0]]; - - while ($parts !== []) { - [$part, $start] = array_shift($parts); - - try { - $bodies[] = [$this->frameEncoder->encode($part), $part->count()]; - } catch (OffsetOverflow|FrameTooLarge $e) { - if ($part->count() === 1) { - $message = sprintf('%s (row %d)', $e->getMessage(), $start); - - throw $e instanceof OffsetOverflow - ? new OffsetOverflow($message, 0, $e) - : new FrameTooLarge($message, 0, $e); - } - - $half = intdiv($part->count(), 2); - array_unshift( - $parts, - [$part->slice(0, $half), $start], - [$part->slice($half, $part->count() - $half), $start + $half], - ); - } - } + $bodies = $this->frameEncoder->encode($matched); $this->startSectionWhenDue(); diff --git a/src/core/etl/src/Flow/Floe/SplittingFrameEncoder.php b/src/core/etl/src/Flow/Floe/SplittingFrameEncoder.php new file mode 100644 index 000000000..0bf6c7b1c --- /dev/null +++ b/src/core/etl/src/Flow/Floe/SplittingFrameEncoder.php @@ -0,0 +1,60 @@ + [frame body, rows it holds], in row order + */ + public function encode(Rows $rows): array + { + $bodies = []; + $parts = [[$rows, 0]]; + + while ($parts !== []) { + [$part, $start] = array_shift($parts); + + try { + $bodies[] = [$this->encoder->encode($part), $part->count()]; + } catch (OffsetOverflow|FrameTooLarge $e) { + if ($part->count() === 1) { + $message = sprintf('%s (row %d)', $e->getMessage(), $start); + + throw $e instanceof OffsetOverflow + ? new OffsetOverflow($message, 0, $e) + : new FrameTooLarge($message, 0, $e); + } + + $half = intdiv($part->count(), 2); + array_unshift( + $parts, + [$part->slice(0, $half), $start], + [$part->slice($half, $part->count() - $half), $start + $half], + ); + } + } + + return $bodies; + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Context/ExpandColumnsContext.php b/src/core/etl/tests/Flow/ETL/Tests/Context/ExpandColumnsContext.php new file mode 100644 index 000000000..1cd4ec252 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Context/ExpandColumnsContext.php @@ -0,0 +1,47 @@ + + */ + public static function carries(LogicalPlan $plan): array + { + $carries = []; + $seen = []; + $pending = [$plan->root]; + + while ($pending !== []) { + $node = array_pop($pending); + + if (array_key_exists(spl_object_id($node), $seen)) { + continue; + } + + $seen[spl_object_id($node)] = true; + + if ($node instanceof ExpandColumn) { + $carries[$node->name()] = $node->carries; + } + + foreach ($node instanceof Node\JoinsFrame ? [$node->children()[0]] : $node->children() as $child) { + $pending[] = $child; + } + } + + return $carries; + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Context/ExpandingProcessorContext.php b/src/core/etl/tests/Flow/ETL/Tests/Context/ExpandingProcessorContext.php new file mode 100644 index 000000000..ac7f1465d --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Context/ExpandingProcessorContext.php @@ -0,0 +1,51 @@ + + */ + public static function batches(FlowContext $context, Processor|Transformer $processor, Rows ...$input): array + { + $generator = (static function () use ($input): Generator { + yield from $input; + })(); + + return iterator_to_array( + type_instance_of(Processor::class)->assert($processor)->process($generator, $context), + false, + ); + } + + /** + * Every row the processor emitted, across its batches. + * + * @return list> + */ + public static function rows(FlowContext $context, Processor|Transformer $processor, Rows ...$input): array + { + $rows = []; + + foreach (self::batches($context, $processor, ...$input) as $batch) { + foreach ($batch->toArray() as $row) { + $rows[] = $row; + } + } + + return $rows; + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Context/NestedExpansionContext.php b/src/core/etl/tests/Flow/ETL/Tests/Context/ExpansionContext.php similarity index 72% rename from src/core/etl/tests/Flow/ETL/Tests/Context/NestedExpansionContext.php rename to src/core/etl/tests/Flow/ETL/Tests/Context/ExpansionContext.php index dd6c8f03c..4ea4f8186 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Context/NestedExpansionContext.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Context/ExpansionContext.php @@ -8,17 +8,17 @@ use Flow\ETL\Function\ScalarFunction; use Flow\ETL\Schema; use Flow\ETL\Tests\Mother\ListColumnsMother; -use Flow\ETL\Transformer\NestedExpansion; +use Flow\ETL\Transformer\Expansion; use function Flow\Types\DSL\type_instance_of; -final class NestedExpansionContext +final class ExpansionContext { - public static function of(ScalarFunction $tree, ?Schema $input = null): NestedExpansion + public static function of(ScalarFunction $tree, ?Schema $input = null): Expansion { $schema = $input ?? ListColumnsMother::schema(); - return type_instance_of(NestedExpansion::class)->assert(NestedExpansion::of( + return type_instance_of(Expansion::class)->assert(Expansion::of( (new ReferenceResolver())->resolve($tree, $schema), $schema, )); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Context/RowsSerializationContext.php b/src/core/etl/tests/Flow/ETL/Tests/Context/RowsSerializationContext.php index fde8d461a..903c884ad 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Context/RowsSerializationContext.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Context/RowsSerializationContext.php @@ -19,7 +19,7 @@ public static function roundTrip(Rows $rows): Rows } /** - * @param array{schema: \Flow\ETL\Schema, frame: string} $payload + * @param array{schema: \Flow\ETL\Schema, frames: list} $payload */ public static function unserialize(array $payload): Rows { diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/ArrayExpandTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/ArrayExpandTest.php index 4523d0995..46a15a3e5 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/ArrayExpandTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/ArrayExpandTest.php @@ -7,16 +7,26 @@ use Flow\ETL\DataFrame; use Flow\ETL\Function\ArrayExpand\ArrayExpand; use Flow\ETL\Memory\ArrayMemory; +use Flow\ETL\Optimizer; +use Flow\ETL\Plan\Explain; +use Flow\ETL\Planner; +use Flow\ETL\Processor\ExpandingProcessor; +use Flow\ETL\Rows; +use Flow\ETL\Tests\Context\PipelineSteps; use Flow\ETL\Tests\FlowTestCase; +use Flow\ETL\Tests\Mother\ExpansionMother; use function Flow\ETL\DSL\array_expand; +use function Flow\ETL\DSL\array_get; use function Flow\ETL\DSL\data_frame; use function Flow\ETL\DSL\from_array; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\list_schema; +use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\optional; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\structure; use function Flow\ETL\DSL\structure_get; use function Flow\ETL\DSL\structure_schema; @@ -29,6 +39,194 @@ final class ArrayExpandTest extends FlowTestCase { + public function test_a_page_of_25_000_structures_expanded_into_a_new_column(): void + { + static::assertSame( + 25_000, + data_frame() + ->read(from_array([['body' => ExpansionMother::page(25_000)]], schema(str_schema('body')))) + ->withEntry( + 'body', + ref('body') + ->jsonDecode() + ->cast(type_structure([ + 'rows' => type_list(ExpansionMother::pageRowType()), + ])), + ) + ->withEntry('record', array_expand(array_get(ref('body'), 'rows'))) + ->select('record') + ->fetch() + ->count(), + ); + } + + public function test_a_page_of_25_000_structures_expanded_in_place(): void + { + static::assertSame( + 25_000, + data_frame() + ->read(from_array([['body' => ExpansionMother::page(25_000)]], schema(str_schema('body')))) + ->withEntry( + 'body', + ref('body') + ->jsonDecode() + ->cast(type_structure([ + 'rows' => type_list(ExpansionMother::pageRowType()), + ])), + ) + ->withEntry('body', array_expand(array_get(ref('body'), 'rows'))) + ->select('body') + ->fetch() + ->count(), + ); + } + + public function test_100_000_short_strings_expanded_into_a_new_column(): void + { + static::assertSame( + 100_000, + data_frame() + ->read(from_array([[ + 'items' => ExpansionMother::terms(100_000), + ]], schema(list_schema('items', type_list(type_string()))))) + ->withEntry('item', array_expand(ref('items'))) + ->select('item') + ->fetch() + ->count(), + ); + } + + public function test_100_000_short_strings_expanded_in_place(): void + { + static::assertSame( + 100_000, + data_frame() + ->read(from_array([[ + 'items' => ExpansionMother::terms(100_000), + ]], schema(list_schema('items', type_list(type_string()))))) + ->withEntry('items', array_expand(ref('items'))) + ->select('items') + ->fetch() + ->count(), + ); + } + + public function test_a_small_input_column_is_copied_to_every_expanded_row(): void + { + $rows = data_frame() + ->read(from_array( + [['id' => 7, 'items' => ExpansionMother::terms(100_000)]], + schema(int_schema('id'), list_schema('items', type_list(type_string()))), + )) + ->withEntry('item', array_expand(ref('items'))) + ->select('id', 'item') + ->fetch(); + + static::assertSame(100_000, $rows->count()); + static::assertSame(['id' => 7, 'item' => 'term-1'], $rows->toArray()[0]); + static::assertSame(['id' => 7, 'item' => 'term-100000'], $rows->toArray()[99_999]); + } + + public function test_a_nested_expand_over_a_page_of_25_000_structures(): void + { + static::assertSame( + 25_000, + data_frame() + ->read(from_array([['body' => ExpansionMother::page(25_000)]], schema(str_schema('body')))) + ->withEntry( + 'body', + ref('body') + ->jsonDecode() + ->cast(type_structure([ + 'rows' => type_list(ExpansionMother::pageRowType()), + ])), + ) + ->withEntry('record', array_get(array_expand(array_get(ref('body'), 'rows')), 'clicks')) + ->select('record') + ->fetch() + ->count(), + ); + } + + public function test_an_unpack_over_a_page_of_25_000_expanded_structures(): void + { + static::assertSame( + 25_000, + data_frame() + ->read(from_array([['body' => ExpansionMother::page(25_000)]], schema(str_schema('body')))) + ->withEntry( + 'body', + ref('body') + ->jsonDecode() + ->cast(type_structure([ + 'rows' => type_list(ExpansionMother::pageRowType()), + ])), + ) + ->withEntry( + 'record', + array_expand(array_get(ref('body'), 'rows'))->unpack(schema(int_schema('clicks'))), + ) + ->select('record.clicks') + ->fetch() + ->count(), + ); + } + + public function test_an_expansion_emits_batches_of_at_most_1_000_rows(): void + { + $batches = data_frame() + ->read(from_array([[ + 'items' => ExpansionMother::terms(2_500), + ]], schema(list_schema('items', type_list(type_string()))))) + ->withEntry('item', array_expand(ref('items'))) + ->get(); + + static::assertSame( + [1000, 1000, 500], + array_map(static fn(Rows $rows): int => $rows->count(), iterator_to_array($batches, false)), + ); + } + + public function test_an_expanding_with_entry_runs_on_the_expanding_processor(): void + { + $steps = static function (DataFrame $frame): array { + $plan = $frame->explain(); + + return PipelineSteps::classes( + (new Planner(Optimizer::default())) + ->plan($plan->logical, $plan->context) + ->root() + ->segments(), + ); + }; + $frame = static fn(): DataFrame => data_frame()->read(from_array([['items' => [ + 'a', + 'b', + ]]], schema(list_schema('items', type_list(type_string()))))); + + static::assertContains( + ExpandingProcessor::class, + $steps($frame()->withEntry('item', array_expand(ref('items')))), + ); + static::assertNotContains(ExpandingProcessor::class, $steps($frame()->withEntry('item', lit(1)))); + } + + public function test_explain_shows_the_columns_an_expand_keeps(): void + { + $plan = data_frame() + ->read(from_array([[ + 'items' => ExpansionMother::terms(3), + ]], schema(list_schema('items', type_list(type_string()))))) + ->withEntry('item', array_expand(ref('items'))) + ->select('item') + ->explain(); + + static::assertStringContainsString( + 'Keeps: item', + (new Explain())->of(Optimizer::default()->optimize($plan->logical, $plan->context)), + ); + } + public function test_expand_nested_in_a_structure_gives_one_row_per_element(): void { $frame = static fn(): DataFrame => data_frame() diff --git a/src/core/etl/tests/Flow/ETL/Tests/Mother/ExpansionMother.php b/src/core/etl/tests/Flow/ETL/Tests/Mother/ExpansionMother.php new file mode 100644 index 000000000..fb3cdfea3 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Mother/ExpansionMother.php @@ -0,0 +1,39 @@ + array_map( + static fn(int $i): array => ['keys' => ['term-' . $i], 'clicks' => 1], + range(1, $rows), + )], JSON_THROW_ON_ERROR); + } + + public static function pageRowType(): StructureType + { + return type_structure(['keys' => type_list(type_string()), 'clicks' => type_integer()]); + } + + /** + * @return list + */ + public static function terms(int $count): array + { + return array_map(static fn(int $i): string => 'term-' . $i, range(1, $count)); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Config/Telemetry/TelemetryContextTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Config/Telemetry/TelemetryContextTest.php index 1ce41a6ec..83d3cdcb0 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Config/Telemetry/TelemetryContextTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Config/Telemetry/TelemetryContextTest.php @@ -14,6 +14,7 @@ use Flow\ETL\Optimizer\Rule\CountFromStatistics; use Flow\ETL\Optimizer\Rule\PushFilterIntoSource; use Flow\ETL\Optimizer\Rule\PushLimitIntoSource; +use Flow\ETL\Optimizer\Rule\PushProjectionIntoExpand; use Flow\ETL\Tests\Context\MemoryTelemetryContext; use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Transformer\LimitTransformer; @@ -992,6 +993,7 @@ public function test_optimizer_rules_are_logged(): void PushLimitIntoSource::class, PushFilterIntoSource::class, CountFromStatistics::class, + PushProjectionIntoExpand::class, ], $debugLogs[0]->record->attributes->get('optimizer_rules'), ); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/ProjectionWalkTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/ProjectionWalkTest.php new file mode 100644 index 000000000..f07e33e88 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/ProjectionWalkTest.php @@ -0,0 +1,123 @@ +below(new Node\Select(NodeMother::read(), [ + 'a', + ref('b'), + ]), RequiredColumns::allBut('x')), + ); + } + + public function test_a_drop_removes_its_columns_from_either_demand(): void + { + $drop = new Node\Drop(NodeMother::read(), ['body']); + + static::assertEquals( + RequiredColumns::allBut('body'), + (new ProjectionWalk())->below($drop, RequiredColumns::all()), + ); + static::assertEquals( + RequiredColumns::only('id'), + (new ProjectionWalk())->below($drop, RequiredColumns::only('id', 'body')), + ); + } + + public function test_a_with_column_replaces_its_own_name_with_what_it_reads(): void + { + $node = new Node\WithColumn(NodeMother::read(), 'y', concat(ref('a'), ref('b'))); + + static::assertEquals( + RequiredColumns::only('x', 'a', 'b'), + (new ProjectionWalk())->below($node, RequiredColumns::only('x', 'y')), + ); + static::assertEquals( + RequiredColumns::allBut('z', 'y'), + (new ProjectionWalk())->below($node, RequiredColumns::allBut('a', 'z')), + ); + } + + public function test_an_expand_column_replaces_its_own_name_with_what_it_reads(): void + { + static::assertEquals( + RequiredColumns::only('items'), + (new ProjectionWalk())->below( + new Node\ExpandColumn(NodeMother::read(), 'item', ref('items')->expand()), + RequiredColumns::only('item'), + ), + ); + } + + public function test_an_unpack_keeps_the_demand_and_adds_what_it_reads(): void + { + static::assertEquals( + RequiredColumns::only('s.a', 'items'), + (new ProjectionWalk())->below( + new Node\ExpandColumn( + NodeMother::read(), + 's', + structure(['a' => ref('items')->expand()])->unpack(schema(int_schema('a'))), + ), + RequiredColumns::only('s.a'), + ), + ); + static::assertEquals( + RequiredColumns::only('s', 'm'), + (new ProjectionWalk())->below( + new Node\WithColumn(NodeMother::read(), 's', ref('m')->unpack(schema(int_schema('a')))), + RequiredColumns::only('s'), + ), + ); + } + + public function test_a_filter_adds_the_source_columns_its_predicate_reads(): void + { + static::assertEquals( + RequiredColumns::only('x', 'id'), + (new ProjectionWalk())->below( + new Node\Filter(NodeMother::read(), ref('id')->as('alias')->isNotNull()), + RequiredColumns::only('x'), + ), + ); + } + + public function test_a_limit_and_an_offset_pass_the_demand_through(): void + { + static::assertEquals( + RequiredColumns::only('x'), + (new ProjectionWalk())->below(NodeMother::limit(NodeMother::read(), 5), RequiredColumns::only('x')), + ); + static::assertEquals( + RequiredColumns::only('x'), + (new ProjectionWalk())->below(new Node\Offset(NodeMother::read(), 5), RequiredColumns::only('x')), + ); + } + + public function test_any_other_node_requires_every_column(): void + { + static::assertEquals(RequiredColumns::all(), (new ProjectionWalk())->below( + new Node\Rename(NodeMother::read(), 'a', 'b'), + RequiredColumns::only('b'), + )); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/Rule/PushLimitIntoSourceTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/Rule/PushLimitIntoSourceTest.php index 3f88de5bc..e72ba207d 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/Rule/PushLimitIntoSourceTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/Rule/PushLimitIntoSourceTest.php @@ -56,10 +56,10 @@ public function test_a_limit_passes_a_select(): void } #[DataProvider('expanding_expressions')] - public function test_a_limit_does_not_pass_a_with_column_that_expands(ScalarFunction $function): void + public function test_a_limit_does_not_pass_an_expand_column(ScalarFunction $function): void { $plan = (new PushLimitIntoSource())->apply( - NodeMother::plan(NodeMother::limit(new Node\WithColumn(NodeMother::read(), 'expanded', $function), 10)), + NodeMother::plan(NodeMother::limit(new Node\ExpandColumn(NodeMother::read(), 'expanded', $function), 10)), NodeMother::context(), ); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/Rule/PushProjectionIntoExpandTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/Rule/PushProjectionIntoExpandTest.php new file mode 100644 index 000000000..f0b74c862 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/Rule/PushProjectionIntoExpandTest.php @@ -0,0 +1,129 @@ +expand()), + 'record', + )); + + static::assertEquals( + ['record' => RequiredColumns::only('record')], + ExpandColumnsContext::carries((new PushProjectionIntoExpand())->apply($plan, NodeMother::context())), + ); + } + + public function test_a_drop_above_an_expand_keeps_every_column_but_the_dropped_ones(): void + { + $plan = NodeMother::plan( + new Node\Drop(new Node\ExpandColumn(NodeMother::read(), 'record', ref('body')->expand()), ['body']), + ); + + static::assertEquals( + ['record' => RequiredColumns::allBut('body')], + ExpandColumnsContext::carries((new PushProjectionIntoExpand())->apply($plan, NodeMother::context())), + ); + } + + public function test_a_column_derived_between_the_expand_and_the_select_adds_what_it_reads(): void + { + $plan = NodeMother::plan(NodeMother::select( + new Node\WithColumn( + new Node\ExpandColumn(NodeMother::read(), 'record', ref('body')->expand()), + 'y', + ref('id'), + ), + 'record', + 'y', + )); + + static::assertEquals( + ['record' => RequiredColumns::only('record', 'id')], + ExpandColumnsContext::carries((new PushProjectionIntoExpand())->apply($plan, NodeMother::context())), + ); + } + + public function test_a_node_it_does_not_understand_leaves_the_plan_as_it_is(): void + { + $plan = NodeMother::plan(NodeMother::select( + new Node\Rename(new Node\ExpandColumn(NodeMother::read(), 'record', ref('body')->expand()), 'record', 'r'), + 'r', + )); + + static::assertSame($plan, (new PushProjectionIntoExpand())->apply($plan, NodeMother::context())); + } + + public function test_an_expand_whose_rows_are_all_consumed_is_left_as_it_is(): void + { + $plan = NodeMother::plan(new Node\ExpandColumn(NodeMother::read(), 'record', ref('body')->expand())); + + static::assertSame($plan, (new PushProjectionIntoExpand())->apply($plan, NodeMother::context())); + } + + public function test_stacked_expands_are_both_pruned(): void + { + $plan = NodeMother::plan(NodeMother::select( + new Node\ExpandColumn( + new Node\ExpandColumn(NodeMother::read(), 'a', ref('items')->expand()), + 'b', + ref('more')->expand(), + ), + 'b', + )); + + static::assertEquals( + ['b' => RequiredColumns::only('b'), 'a' => RequiredColumns::only('more')], + ExpandColumnsContext::carries((new PushProjectionIntoExpand())->apply($plan, NodeMother::context())), + ); + } + + public function test_an_expand_shared_by_two_consumers_keeps_what_either_reads(): void + { + $expand = new Node\ExpandColumn(NodeMother::read(), 'record', ref('body')->expand()); + $plan = new LogicalPlan( + new Outputs( + new Result(NodeMother::select($expand, 'record')), + new Write(NodeMother::select($expand, 'record', 'id'), to_memory(new ArrayMemory())), + ), + ); + + static::assertEquals( + ['record' => RequiredColumns::only('record', 'id')], + ExpandColumnsContext::carries((new PushProjectionIntoExpand())->apply($plan, NodeMother::context())), + ); + } + + public function test_a_consumer_reading_every_column_keeps_the_shared_expand_as_it_is(): void + { + $expand = new Node\ExpandColumn(NodeMother::read(), 'record', ref('body')->expand()); + $plan = new LogicalPlan( + new Outputs( + new Result(NodeMother::select($expand, 'record')), + new Write($expand, to_memory(new ArrayMemory())), + ), + ); + + static::assertSame($plan, (new PushProjectionIntoExpand())->apply($plan, NodeMother::context())); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/OptimizerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/OptimizerTest.php index ab27e626d..fa4487f34 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/OptimizerTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/OptimizerTest.php @@ -12,6 +12,7 @@ use Flow\ETL\Optimizer\Rule\CountFromStatistics; use Flow\ETL\Optimizer\Rule\PushFilterIntoSource; use Flow\ETL\Optimizer\Rule\PushLimitIntoSource; +use Flow\ETL\Optimizer\Rule\PushProjectionIntoExpand; use Flow\ETL\Tests\Double\RecordingRule; use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Tests\Mother\NodeMother; @@ -65,6 +66,7 @@ public function test_default_registers_combine_limits_combine_sort_and_limit_pus PushLimitIntoSource::class, PushFilterIntoSource::class, CountFromStatistics::class, + PushProjectionIntoExpand::class, ], array_map(static fn($rule) => $rule::class, Optimizer::default()->rules()), ); @@ -73,7 +75,13 @@ public function test_default_registers_combine_limits_combine_sort_and_limit_pus public function test_without_drops_the_named_rule_and_keeps_the_rest(): void { static::assertSame( - [CombineLimits::class, CombineSortAndLimit::class, PushFilterIntoSource::class, CountFromStatistics::class], + [ + CombineLimits::class, + CombineSortAndLimit::class, + PushFilterIntoSource::class, + CountFromStatistics::class, + PushProjectionIntoExpand::class, + ], array_map( static fn($rule) => $rule::class, Optimizer::default()->without(PushLimitIntoSource::class)->rules(), diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Explain/DetailsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Explain/DetailsTest.php index 840ec84f8..44e7139c9 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Explain/DetailsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Explain/DetailsTest.php @@ -12,6 +12,7 @@ use Flow\ETL\Plan\Node\Collect; use Flow\ETL\Plan\Node\CollectRefs; use Flow\ETL\Plan\Node\CrossJoin; +use Flow\ETL\Plan\Node\ExpandColumn; use Flow\ETL\Plan\Node\Filter; use Flow\ETL\Plan\Node\Join as JoinNode; use Flow\ETL\Plan\Node\Offset; @@ -22,6 +23,7 @@ use Flow\ETL\Plan\Node\Until; use Flow\ETL\Plan\Node\WithColumn; use Flow\ETL\Plan\Node\Write; +use Flow\ETL\Plan\RequiredColumns; use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Tests\Mother\NodeMother; use Flow\Filesystem\Path\Filter\KeepAll; @@ -142,6 +144,27 @@ public function test_a_blocking_node_says_it_buffers_rows(): void ); } + public function test_an_expand_column_shows_the_columns_it_keeps(): void + { + $read = NodeMother::read(); + $details = new Details(); + $expand = new ExpandColumn($read, 'item', ref('items')->expand()); + + static::assertSame(['Column: item = ArrayExpand'], $details->labelled($expand)); + static::assertSame( + ['Column: item = ArrayExpand', 'Keeps: id, item'], + $details->labelled($expand->withCarries(RequiredColumns::only('id', 'item'))), + ); + static::assertSame( + ['Column: item = ArrayExpand', 'Keeps: no input column'], + $details->labelled($expand->withCarries(RequiredColumns::only())), + ); + static::assertSame( + ['Column: item = ArrayExpand', 'Keeps: every column but items, body'], + $details->labelled($expand->withCarries(RequiredColumns::allBut('items', 'body'))), + ); + } + public function test_redefined_columns_follow_the_labelled_details(): void { $read = NodeMother::read(); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/ExpandColumnTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/ExpandColumnTest.php new file mode 100644 index 000000000..68f6d2e10 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/ExpandColumnTest.php @@ -0,0 +1,98 @@ +children()); + } + + public function test_carries_every_column_until_told_otherwise(): void + { + static::assertEquals( + RequiredColumns::all(), + (new ExpandColumn(NodeMother::read(), 'item', array_expand(ref('items'))))->carries, + ); + } + + public function test_with_children_returns_the_same_instance_when_children_are_identical(): void + { + $input = NodeMother::read(); + $node = new ExpandColumn($input, 'item', array_expand(ref('items'))); + + static::assertSame($node, $node->withChildren([$input])); + } + + public function test_with_children_keeps_entry_function_and_carries(): void + { + $other = NodeMother::read(); + $function = array_expand(ref('items')); + $rebuilt = (new ExpandColumn( + NodeMother::read(), + 'item', + $function, + RequiredColumns::only('item'), + ))->withChildren([$other]); + + static::assertSame([$other], $rebuilt->children()); + static::assertSame('item', $rebuilt->entry); + static::assertSame($function, $rebuilt->function); + static::assertEquals(RequiredColumns::only('item'), $rebuilt->carries); + } + + public function test_with_carries_replaces_only_the_carries(): void + { + $input = NodeMother::read(); + $node = (new ExpandColumn($input, 'item', array_expand(ref('items'))))->withCarries(RequiredColumns::allBut( + 'items', + )); + + static::assertEquals(RequiredColumns::allBut('items'), $node->carries); + static::assertSame([$input], $node->children()); + } + + public function test_declarations(): void + { + $node = new ExpandColumn(NodeMother::read(), 'item', array_expand(ref('items'))); + + static::assertSame(RowCount::expanding, $node->rowCount()); + static::assertSame(Transparency::transparent, $node->transparency()); + static::assertSame(Materialization::streaming, $node->materialization()); + static::assertEquals(Redefined::names('item'), $node->redefines()); + } + + public function test_an_expand_nested_in_a_structure_is_expanding_too(): void + { + static::assertSame(RowCount::expanding, (new ExpandColumn(NodeMother::read(), 'item', structure([ + 'tag' => array_expand(ref('items')), + ])))->rowCount()); + } + + public function test_redefines_the_definitions_name_when_the_entry_is_a_definition(): void + { + $node = new ExpandColumn(NodeMother::read(), str_schema('item'), array_expand(ref('items'))); + + static::assertSame('item', $node->name()); + static::assertEquals(Redefined::names('item'), $node->redefines()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/WithColumnTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/WithColumnTest.php index 61557a5b3..e24ba6fa4 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/WithColumnTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/WithColumnTest.php @@ -12,11 +12,9 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Tests\Mother\NodeMother; -use function Flow\ETL\DSL\array_expand; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\structure; final class WithColumnTest extends FlowTestCase { @@ -68,17 +66,6 @@ public function test_declarations(): void static::assertEquals(Redefined::names('doubled'), $node->redefines()); } - public function test_row_count_is_expanding_when_the_function_tree_contains_array_expand(): void - { - static::assertSame( - RowCount::expanding, - (new WithColumn(NodeMother::read(), 'item', array_expand(ref('items'))))->rowCount(), - ); - static::assertSame(RowCount::expanding, (new WithColumn(NodeMother::read(), 'item', structure([ - 'tag' => array_expand(ref('items')), - ])))->rowCount()); - } - public function test_redefines_the_definitions_name_when_the_entry_is_a_definition(): void { $node = new WithColumn(NodeMother::read(), int_schema('doubled'), ref('id')->multiply(lit(2))); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/RequiredColumnsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/RequiredColumnsTest.php new file mode 100644 index 000000000..bab6fd94b --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/RequiredColumnsTest.php @@ -0,0 +1,92 @@ +isAll()); + static::assertTrue(RequiredColumns::all()->requires('anything')); + } + + public function test_all_but_requires_every_column_except_the_named_ones(): void + { + $required = RequiredColumns::allBut('body'); + + static::assertFalse($required->isAll()); + static::assertFalse($required->requires('body')); + static::assertTrue($required->requires('id')); + } + + public function test_all_but_nothing_is_all(): void + { + static::assertTrue(RequiredColumns::allBut()->isAll()); + } + + public function test_only_requires_exactly_the_named_columns(): void + { + $required = RequiredColumns::only('record'); + + static::assertFalse($required->isAll()); + static::assertTrue($required->requires('record')); + static::assertFalse($required->requires('body')); + } + + public function test_only_nothing_requires_no_column(): void + { + static::assertFalse(RequiredColumns::only()->isAll()); + static::assertFalse(RequiredColumns::only()->requires('id')); + } + + public function test_duplicate_names_collapse(): void + { + static::assertSame(['a', 'b'], RequiredColumns::only('a', 'b', 'a')->names); + static::assertSame(['a'], RequiredColumns::allBut('a', 'a')->names); + } + + public function test_with_adds_to_only_and_removes_from_all_but(): void + { + static::assertEquals(RequiredColumns::only('a', 'b'), RequiredColumns::only('a')->with('b', 'a')); + static::assertEquals(RequiredColumns::allBut('c'), RequiredColumns::allBut('b', 'c')->with('b')); + } + + public function test_without_removes_from_only_and_adds_to_all_but(): void + { + static::assertEquals(RequiredColumns::only('b'), RequiredColumns::only('a', 'b')->without('a', 'x')); + static::assertEquals(RequiredColumns::allBut('a', 'b'), RequiredColumns::allBut('a')->without('b', 'a')); + } + + public function test_union_of_two_only_is_only_their_union(): void + { + static::assertEquals( + RequiredColumns::only('a', 'b', 'c'), + RequiredColumns::only('a', 'b')->union(RequiredColumns::only('b', 'c')), + ); + } + + public function test_union_of_only_and_all_but_is_all_but_what_neither_reads(): void + { + static::assertEquals( + RequiredColumns::allBut('y'), + RequiredColumns::only('x')->union(RequiredColumns::allBut('x', 'y')), + ); + static::assertEquals( + RequiredColumns::allBut('y'), + RequiredColumns::allBut('x', 'y')->union(RequiredColumns::only('x')), + ); + } + + public function test_union_of_two_all_but_excludes_only_what_both_exclude(): void + { + static::assertEquals( + RequiredColumns::allBut('b'), + RequiredColumns::allBut('a', 'b')->union(RequiredColumns::allBut('b', 'c')), + ); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Planner/NodeTranslatorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Planner/NodeTranslatorTest.php index 08272e208..66dee3cce 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Planner/NodeTranslatorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Planner/NodeTranslatorTest.php @@ -23,6 +23,7 @@ use Flow\ETL\Plan\Node\Distinct; use Flow\ETL\Plan\Node\Drop; use Flow\ETL\Plan\Node\DuplicateRow; +use Flow\ETL\Plan\Node\ExpandColumn; use Flow\ETL\Plan\Node\Filter; use Flow\ETL\Plan\Node\Join; use Flow\ETL\Plan\Node\JoinEach; @@ -48,6 +49,7 @@ use Flow\ETL\Processor\CollectingProcessor; use Flow\ETL\Processor\ConstrainedProcessor; use Flow\ETL\Processor\CountingProcessor; +use Flow\ETL\Processor\ExpandingProcessor; use Flow\ETL\Processor\GroupByAggregationProcessor; use Flow\ETL\Processor\HashJoinProcessor; use Flow\ETL\Processor\MemorySortProcessor; @@ -528,6 +530,21 @@ public function test_with_column_steps_are_the_exact_list_in_order(): void ); } + public function test_expand_column_runs_on_one_expanding_processor(): void + { + static::assertSame( + [ExpandingProcessor::class], + array_map( + static fn($step) => $step::class, + NodeTranslator::toSteps( + new ExpandColumn(NodeMother::read(), 'item', ref('items')->expand()), + NodeMother::context(), + [], + ), + ), + ); + } + public function test_write_the_instance_the_node_holds_is_the_step(): void { $loader = to_memory(new ArrayMemory()); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/BoundExpansionTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/BoundExpansionTest.php new file mode 100644 index 000000000..5e58c8028 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/BoundExpansionTest.php @@ -0,0 +1,188 @@ +expand(), + RequiredColumns::all(), + schema(str_schema('id'), list_schema('tags', type_list(type_string())), str_schema('note')), + ); + + static::assertSame(['id', 'note'], $bound->gathered); + static::assertEquals(schema(str_schema('id'), str_schema('tags'), str_schema('note')), $bound->output); + } + + public function test_a_new_column_selected_alone_gathers_no_input_column(): void + { + $bound = BoundExpansion::of( + 'record', + ref('tags')->expand(), + RequiredColumns::only('record'), + ListColumnsMother::tagsSchema(), + ); + + static::assertSame([], $bound->gathered); + static::assertEquals(schema(str_schema('record')), $bound->output); + } + + public function test_all_but_a_column_gathers_every_other_input_column(): void + { + $bound = BoundExpansion::of( + 'tag', + ref('tags')->expand(), + RequiredColumns::allBut('tags'), + ListColumnsMother::schema(), + ); + + static::assertSame(['id', 'nums', 'lists', 'flags'], $bound->gathered); + static::assertSame(['id', 'nums', 'lists', 'flags', 'tag'], $bound->output->references()->names()); + } + + public function test_a_column_the_root_reads_is_gathered_but_not_output(): void + { + $bound = BoundExpansion::of( + 's', + concat(ref('tags')->expand(), ref('id')), + RequiredColumns::only('s'), + ListColumnsMother::tagsSchema(), + ); + + static::assertSame(['id'], $bound->gathered); + static::assertEquals(schema(str_schema('s')), $bound->output); + } + + public function test_an_unpack_gathers_neither_the_columns_it_writes_nor_drops_a_same_prefixed_one(): void + { + $bound = BoundExpansion::of( + 's', + structure(['a' => ref('tags')->expand()])->unpack(schema(str_schema('a'))), + RequiredColumns::all(), + schema(list_schema('tags', type_list(type_string())), int_schema('s.a'), str_schema('s.other')), + ); + + static::assertSame(['tags', 's.other'], $bound->gathered); + static::assertSame( + [['tags' => ['x'], 's.a' => 'x', 's.other' => 'kept']], + iterator_to_array( + $bound->chunks( + array_to_rows( + [['tags' => ['x'], 's.a' => 1, 's.other' => 'kept']], + schema(list_schema('tags', type_list(type_string())), int_schema('s.a'), str_schema('s.other')), + ), + flow_context(), + 1000, + ), + false, + )[0]->toArray(), + ); + } + + public function test_chunks_split_the_output_into_batches_of_at_most_the_batch_size(): void + { + $bound = BoundExpansion::of( + 'tag', + ref('tags')->expand(), + RequiredColumns::only('tag'), + ListColumnsMother::tagsSchema(), + ); + + static::assertSame( + [[['tag' => 'x'], ['tag' => 'y']], [['tag' => 'z']]], + array_map( + static fn(Rows $rows): array => $rows->toArray(), + iterator_to_array( + $bound->chunks( + array_to_rows([['id' => 'a', 'tags' => ['x', 'y', 'z']]], ListColumnsMother::tagsSchema()), + flow_context(), + 2, + ), + false, + ), + ), + ); + } + + public function test_an_input_batch_that_expands_to_nothing_yields_one_empty_batch(): void + { + $bound = BoundExpansion::of( + 'tag', + ref('tags')->expand(), + RequiredColumns::all(), + ListColumnsMother::tagsSchema(), + ); + $batches = iterator_to_array( + $bound->chunks( + array_to_rows([['id' => 'a', 'tags' => []]], ListColumnsMother::tagsSchema()), + flow_context(), + 2, + ), + false, + ); + + static::assertCount(1, $batches); + static::assertSame(0, $batches[0]->count()); + static::assertEquals($bound->output, $batches[0]->schema()); + } + + public function test_a_function_without_an_expand_is_not_an_expansion(): void + { + $this->expectException(InvalidLogicException::class); + $this->expectExceptionMessage('holds no array_expand(), it is not an expansion'); + + BoundExpansion::of( + 's', + structure(['id' => ref('id')]), + RequiredColumns::all(), + ListColumnsMother::tagsSchema(), + ); + } + + public function test_the_output_keeps_the_column_order_of_a_full_expansion(): void + { + static::assertSame( + ['id', 's', 'note'], + BoundExpansion::of( + 's', + structure(['t' => ref('s')->expand()]), + RequiredColumns::allBut('x'), + schema(str_schema('id'), list_schema('s', type_list(type_string())), str_schema('note')), + )->output->references()->names(), + ); + static::assertEquals( + type_structure(['t' => type_string()]), + BoundExpansion::of( + 's', + structure(['t' => ref('s')->expand()]), + RequiredColumns::all(), + schema(str_schema('id'), list_schema('s', type_list(type_string())), str_schema('note')), + )->output->get('s')->type(), + ); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/ExpandingProcessorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/ExpandingProcessorTest.php new file mode 100644 index 000000000..b0e4e87ee --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/ExpandingProcessorTest.php @@ -0,0 +1,526 @@ +expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Batch size must be greater than 0, given: 0'); + + new ExpandingProcessor('v', ref('tags')->expand(), RequiredColumns::all(), 0); + } + + public function test_expand_results(): void + { + static::assertSame( + [['array' => 1], ['array' => 2], ['array' => 3]], + ExpandingProcessorContext::rows( + flow_context(config()), + new ExpandingProcessor( + 'array', + new ArrayExpand(lit([1, 2, 3]), ArrayExpand\ArrayExpand::VALUES), + RequiredColumns::all(), + ), + array_to_rows([[]], schema()), + ), + ); + } + + public function test_output_is_split_into_batches_of_at_most_the_batch_size(): void + { + static::assertSame( + [2, 2, 1], + array_map( + static fn(Rows $rows): int => $rows->count(), + ExpandingProcessorContext::batches( + flow_context(config()), + new ExpandingProcessor('tag', ref('tags')->expand(), RequiredColumns::all(), 2), + array_to_rows([[ + 'id' => 'a', + 'tags' => ['v', 'w', 'x', 'y', 'z'], + ]], ListColumnsMother::tagsSchema()), + ), + ), + ); + } + + public function test_bind_declares_the_output_of_the_bound_expansion(): void + { + static::assertEquals( + schema(str_schema('id'), str_schema('tag')), + (new ExpandingProcessor('tag', ref('tags')->expand(), RequiredColumns::allBut('tags')))->bind( + ListColumnsMother::tagsSchema(), + )->output, + ); + } + + public function test_bound_and_unbound_give_the_same_rows(): void + { + $processor = new ExpandingProcessor('tag', ref('tags')->expand(), RequiredColumns::only('id', 'tag')); + $rows = array_to_rows([['id' => 'a', 'tags' => ['x', 'y']]], ListColumnsMother::tagsSchema()); + + static::assertSame( + [['id' => 'a', 'tag' => 'x'], ['id' => 'a', 'tag' => 'y']], + ExpandingProcessorContext::rows(flow_context(config()), $processor, $rows), + ); + static::assertSame( + ExpandingProcessorContext::rows(flow_context(config()), $processor, $rows), + ExpandingProcessorContext::rows( + flow_context(config()), + $processor->bind(ListColumnsMother::tagsSchema())->step, + $rows, + ), + ); + } + + public function test_stop_after_the_first_batch_is_forwarded_upstream(): void + { + $upstream = (new CountingExtractor(ListColumnsMother::tagsSchema(), array_to_rows([ + ['id' => 'a', 'tags' => ['x', 'y']], + ['id' => 'b', 'tags' => ['z']], + ], ListColumnsMother::tagsSchema()))) + ->withBatchSize(1) + ->extract(flow_context()); + $processed = (new ExpandingProcessor('tag', ref('tags')->expand(), RequiredColumns::all(), 1))->process( + $upstream, + flow_context(), + ); + + static::assertTrue($processed->valid()); + + $processed->send(Signal::STOP); + + static::assertFalse($processed->valid()); + static::assertFalse($upstream->valid()); + } + + public function test_an_expanded_null_under_a_not_null_declaration_names_its_row(): void + { + $this->expectException(SchemaMismatchException::class); + $this->expectExceptionMessage('column "out" (row 1)'); + + ExpandingProcessorContext::rows( + flow_context(config()), + new ExpandingProcessor( + int_schema('out'), + new ArrayExpand(lit([1, null]), ArrayExpand\ArrayExpand::VALUES), + RequiredColumns::all(), + ), + array_to_rows([[]], schema()), + ); + } + + public function test_bind_declares_zipped_expands_nullable(): void + { + static::assertEquals( + schema( + str_schema('id'), + list_schema('tags', type_list(type_string())), + list_schema('nums', type_list(type_integer())), + structure_schema('s', type_structure([ + 'n' => type_optional(type_integer()), + 'tag' => type_optional(type_string()), + ])), + ), + (new ExpandingProcessor( + 's', + structure([ + 'n' => ref('nums')->expand(), + 'tag' => ref('tags')->expand(), + ]), + RequiredColumns::all(), + ))->bind(schema( + str_schema('id'), + list_schema('tags', type_list(type_string())), + list_schema('nums', type_list(type_integer())), + ))->output, + ); + } + + public function test_an_unbound_nested_expand_is_expanded(): void + { + static::assertSame( + [ + ['id' => 'a', 'tags' => ['x', 'y'], 's' => ['tag' => 'x']], + ['id' => 'a', 'tags' => ['x', 'y'], 's' => ['tag' => 'y']], + ], + ExpandingProcessorContext::rows( + flow_context(config()), + new ExpandingProcessor('s', structure(['tag' => ref('tags')->expand()]), RequiredColumns::all()), + array_to_rows([['id' => 'a', 'tags' => ['x', 'y']]], ListColumnsMother::tagsSchema()), + ), + ); + } + + public function test_an_unbound_unpack_over_a_nested_expand_is_expanded(): void + { + static::assertSame( + [ + ['id' => 'a', 'tags' => ['x', 'y'], 'u.tag' => 'x'], + ['id' => 'a', 'tags' => ['x', 'y'], 'u.tag' => 'y'], + ], + ExpandingProcessorContext::rows( + flow_context(config()), + new ExpandingProcessor( + 'u', + structure(['tag' => ref('tags')->expand()])->unpack(schema(str_schema('tag'))), + RequiredColumns::all(), + ), + array_to_rows([['id' => 'a', 'tags' => ['x', 'y']]], ListColumnsMother::tagsSchema()), + ), + ); + } + + public function test_an_expand_explodes_every_row_of_the_batch_in_order(): void + { + static::assertSame( + [['id' => 1, 'value' => 1], ['id' => 1, 'value' => 2], ['id' => 3, 'value' => 3]], + ExpandingProcessorContext::rows( + flow_context(config()), + new ExpandingProcessor('value', ref('list')->expand(), RequiredColumns::only('id', 'value')), + array_to_rows( + [['id' => 1, 'list' => [1, 2]], ['id' => 2, 'list' => []], ['id' => 3, 'list' => [3]]], + schema(int_schema('id'), list_schema('list', type_list(type_integer()))), + ), + ), + ); + } + + public function test_emits_one_row_per_element_and_none_for_an_empty_list(): void + { + static::assertSame( + [ + ['id' => 'a', 'tags' => ['x', 'y'], 's' => ['tag' => 'x']], + ['id' => 'a', 'tags' => ['x', 'y'], 's' => ['tag' => 'y']], + ], + ExpandingProcessorContext::rows( + flow_context(config()), + (new ExpandingProcessor( + 's', + structure(['tag' => ref('tags')->expand()]), + RequiredColumns::all(), + ))->bind(ListColumnsMother::tagsSchema())->step, + array_to_rows([ + ['id' => 'a', 'tags' => ['x', 'y']], + ['id' => 'b', 'tags' => []], + ], ListColumnsMother::tagsSchema()), + ), + ); + } + + public function test_unpack_emits_one_row_per_element(): void + { + static::assertSame( + [ + ['id' => 'a', 'tags' => ['x', 'y'], 'u.tag' => 'x'], + ['id' => 'a', 'tags' => ['x', 'y'], 'u.tag' => 'y'], + ], + ExpandingProcessorContext::rows( + flow_context(config()), + (new ExpandingProcessor( + 'u', + structure(['tag' => ref('tags')->expand()])->unpack(schema(str_schema('tag'))), + RequiredColumns::all(), + ))->bind(ListColumnsMother::tagsSchema())->step, + array_to_rows([['id' => 'a', 'tags' => ['x', 'y']]], ListColumnsMother::tagsSchema()), + ), + ); + } + + public function test_bind_rebinds_against_another_input(): void + { + static::assertEquals( + schema( + list_schema('tags', type_list(type_integer())), + structure_schema('s', type_structure(['tag' => type_integer()])), + ), + (new ExpandingProcessor('s', structure(['tag' => ref('tags')->expand()]), RequiredColumns::all())) + ->bind(ListColumnsMother::tagsSchema()) + ->step->bind(schema(list_schema('tags', type_list(type_integer())))) + ->output, + ); + } + + public function test_a_definition_entry_is_declared_as_given(): void + { + $bound = (new ExpandingProcessor( + str_schema('s', nullable: true), + concat(ref('id'), ref('tags')->expand()), + RequiredColumns::all(), + ))->bind(ListColumnsMother::tagsSchema()); + + static::assertEquals( + schema(str_schema('id'), list_schema('tags', type_list(type_string())), str_schema('s', nullable: true)), + $bound->output, + ); + static::assertSame( + [ + ['id' => 'a', 'tags' => ['x', 'y'], 's' => 'ax'], + ['id' => 'a', 'tags' => ['x', 'y'], 's' => 'ay'], + ], + ExpandingProcessorContext::rows(flow_context(config()), $bound->step, array_to_rows([[ + 'id' => 'a', + 'tags' => ['x', 'y'], + ]], ListColumnsMother::tagsSchema())), + ); + } + + public function test_a_batch_under_another_schema_than_the_bound_one_is_conformed(): void + { + $bound = (new ExpandingProcessor( + 's', + structure(['tag' => ref('tags')->expand()]), + RequiredColumns::all(), + ))->bind(schema( + str_schema('id'), + list_schema('tags', type_list(type_string())), + str_schema('note', nullable: true), + )); + $batch = ExpandingProcessorContext::batches(flow_context(config()), $bound->step, array_to_rows([[ + 'id' => 'a', + 'tags' => ['x'], + ]], ListColumnsMother::tagsSchema()))[0]; + + static::assertEquals( + schema( + str_schema('id'), + list_schema('tags', type_list(type_string())), + str_schema('note', nullable: true), + structure_schema('s', type_structure(['tag' => type_string()])), + ), + $batch->schema(), + ); + static::assertSame([['id' => 'a', 'tags' => ['x'], 'note' => null, 's' => ['tag' => 'x']]], $batch->toArray()); + } + + public function test_a_null_under_a_not_null_definition_names_its_output_row(): void + { + $input = schema(list_schema('tags', type_list(type_optional(type_string())))); + + $this->expectException(SchemaMismatchException::class); + $this->expectExceptionMessage('column "s" (row 1)'); + + ExpandingProcessorContext::rows( + flow_context(config()), + (new ExpandingProcessor(str_schema('s'), ref('tags')->expand()->coalesce(), RequiredColumns::all()))->bind( + $input, + )->step, + array_to_rows([['tags' => ['x']], ['tags' => [null]]], $input), + ); + } + + /** + * @param array $override + * @param list $values + */ + #[DataProvider('zipped_expansions')] + public function test_zipped_expands_give_one_value_per_zipped_position( + ScalarFunction $tree, + array $override, + array $values, + ): void { + static::assertSame($values, array_column( + ExpandingProcessorContext::rows( + flow_context(config()), + new ExpandingProcessor('v', $tree, RequiredColumns::only('v')), + ListColumnsMother::rows($override), + ), + 'v', + )); + } + + /** + * @return Generator, list}> + */ + public static function zipped_expansions(): Generator + { + yield 'one expand' => [ + structure(['tag' => ref('tags')->expand()]), + [], + [['tag' => 'x'], ['tag' => 'y']], + ]; + yield 'zip pads the shorter' => [ + structure(['n' => ref('nums')->expand(), 'tag' => ref('tags')->expand()]), + [], + [['n' => 1, 'tag' => 'x'], ['n' => 2, 'tag' => 'y'], ['n' => 3, 'tag' => null]], + ]; + yield 'concat skips a padded null' => [ + concat(ref('nums')->expand(), ref('tags')->expand()), + [], + ['1x', '2y', '3'], + ]; + yield 'sole empty list' => [ + structure(['tag' => ref('tags')->expand()]), + ['tags' => []], + [], + ]; + yield 'empty beside non-empty' => [ + structure(['n' => ref('nums')->expand(), 'tag' => ref('tags')->expand()]), + ['nums' => [1, 2], 'tags' => []], + [['n' => 1, 'tag' => null], ['n' => 2, 'tag' => null]], + ]; + yield 'onEach operand' => [ + ref('lists')->expand()->onEach(concat(ref('element'), lit('!'))), + [], + [['q!', 'r!'], ['s!']], + ]; + + $tags = ref('tags')->expand(); + + yield 'a node holding a reference, used twice, gives two padded columns' => [ + structure(['a' => $tags, 'b' => $tags]), + [], + [['a' => 'x', 'b' => 'x'], ['a' => 'y', 'b' => 'y']], + ]; + + $literal = lit(['x', 'y'])->expand(); + + yield 'a node without references, used twice, gives one column' => [ + structure(['a' => $literal, 'b' => $literal]), + [], + [['a' => 'x', 'b' => 'x'], ['a' => 'y', 'b' => 'y']], + ]; + yield 'branch not taken still expands' => [ + when(ref('id')->equals(lit('b')), ref('tags')->expand(), lit('none')), + [], + ['none', 'none'], + ]; + yield 'a null list gives no values' => [ + structure(['tag' => ref('tags')->expand()]), + ['tags' => null], + [], + ]; + yield 'a when guard does not stop the expand of a null list' => [ + when(ref('tags')->isNull(), lit('none'), ref('tags')->expand()), + ['tags' => null], + [], + ]; + } + + public function test_a_padded_null_follows_the_null_rule_of_the_function_reading_it(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Plus function requires non-null values'); + + ExpandingProcessorContext::rows( + flow_context(config()), + new ExpandingProcessor( + 'v', + structure([ + 'n' => ref('nums')->expand()->plus(lit(1)), + 't' => ref('tags')->expand(), + ]), + RequiredColumns::only('v'), + ), + ListColumnsMother::rows(['nums' => [1, 2], 'tags' => ['x', 'y', 'z']]), + ); + } + + public function test_an_expand_over_a_map_reads_its_values_by_position(): void + { + static::assertSame( + [['v' => ['v' => 1]], ['v' => ['v' => 2]]], + ExpandingProcessorContext::rows( + flow_context(config()), + new ExpandingProcessor('v', structure(['v' => ref('m')->expand()]), RequiredColumns::only('v')), + array_to_rows([['m' => [ + 'a' => 1, + 'b' => 2, + ]]], schema(map_schema('m', type_map(type_string(), type_integer())))), + ), + ); + } + + public function test_the_synthesized_column_does_not_shadow_an_input_column(): void + { + static::assertSame( + [['v' => ['c' => 'kept', 't' => 'x']]], + ExpandingProcessorContext::rows( + flow_context(config()), + new ExpandingProcessor( + 'v', + structure(['c' => ref("\0expand:0"), 't' => ref('tags')->expand()]), + RequiredColumns::only('v'), + ), + array_to_rows( + [["\0expand:0" => 'kept', 'tags' => ['x']]], + schema(str_schema("\0expand:0"), list_schema('tags', type_list(type_string()))), + ), + ), + ); + } + + #[DataProvider('expands_inside_an_expand')] + public function test_bind_refuses_an_expand_inside_an_expand(ScalarFunction $function): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage( + 'array_expand() cannot contain another array_expand(). Expand one level per withEntry().', + ); + + (new ExpandingProcessor('v', $function, RequiredColumns::all()))->bind(ListColumnsMother::schema()); + } + + /** + * @return Generator + */ + public static function expands_inside_an_expand(): Generator + { + yield 'at the root' => [ref('lists')->expand()->expand()]; + yield 'inside a structure' => [structure(['v' => ref('lists')->expand()->expand()])]; + } + + public function test_an_unbound_expand_inside_an_expand_is_refused(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage( + 'array_expand() cannot contain another array_expand(). Expand one level per withEntry().', + ); + + ExpandingProcessorContext::rows( + flow_context(config()), + new ExpandingProcessor('v', ref('lists')->expand()->expand(), RequiredColumns::all()), + ListColumnsMother::rows(), + ); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsSerializationTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsSerializationTest.php index 5ed2c1d30..8d7ab84d8 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsSerializationTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsSerializationTest.php @@ -214,10 +214,10 @@ public function test_unserialize_refuses_a_frame_that_disagrees_with_the_schema( RowsSerializationContext::unserialize([ 'schema' => schema(int_schema('id')), - 'frame' => array_to_rows( + 'frames' => [array_to_rows( [['id' => 1, 'other' => 2]], schema(int_schema('id'), int_schema('other')), - )->encodeFrame(), + )->encodeFrame()], ]); } @@ -228,7 +228,7 @@ public function test_unserialize_refuses_a_corrupt_buffer(): void RowsSerializationContext::unserialize([ 'schema' => schema(int_schema('id')), - 'frame' => + 'frames' => [ pack('VVV', 1, 1, 2) . pack('VV', 1, 0) . pack('VV', 0, 0) @@ -236,6 +236,7 @@ public function test_unserialize_refuses_a_corrupt_buffer(): void . "\0\0\0\0" . pack('P', -1) . "\x01\x00\0\0\0\0\0\0", + ], ]); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/ExpansionTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/ExpansionTest.php new file mode 100644 index 000000000..718d8360d --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/ExpansionTest.php @@ -0,0 +1,152 @@ +returns()->toString()); + } + + /** + * @return Generator + */ + public static function expansions(): Generator + { + yield 'one expand' => [ + structure(['tag' => ref('tags')->expand()]), + 'structure{tag: string}', + ]; + yield 'zip pads the shorter' => [ + structure(['n' => ref('nums')->expand(), 'tag' => ref('tags')->expand()]), + 'structure{n: ?integer, tag: ?string}', + ]; + yield 'concat skips a padded null' => [ + concat(ref('nums')->expand(), ref('tags')->expand()), + 'string', + ]; + yield 'sole empty list' => [ + structure(['tag' => ref('tags')->expand()]), + 'structure{tag: string}', + ]; + yield 'empty beside non-empty' => [ + structure(['n' => ref('nums')->expand(), 'tag' => ref('tags')->expand()]), + 'structure{n: ?integer, tag: ?string}', + ]; + yield 'onEach operand' => [ + ref('lists')->expand()->onEach(concat(ref('element'), lit('!'))), + 'list', + ]; + + $tags = ref('tags')->expand(); + + yield 'a node holding a reference, used twice, gives two padded columns' => [ + structure(['a' => $tags, 'b' => $tags]), + 'structure{a: ?string, b: ?string}', + ]; + + $literal = lit(['x', 'y'])->expand(); + + yield 'a node without references, used twice, gives one column' => [ + structure(['a' => $literal, 'b' => $literal]), + 'structure{a: string, b: string}', + ]; + yield 'branch not taken still expands' => [ + when(ref('id')->equals(lit('b')), ref('tags')->expand(), lit('none')), + 'string', + ]; + yield 'a null list gives no values' => [ + structure(['tag' => ref('tags')->expand()]), + 'structure{tag: string}', + ]; + yield 'a when guard does not stop the expand of a null list' => [ + when(ref('tags')->isNull(), lit('none'), ref('tags')->expand()), + 'string', + ]; + } + + public function test_a_root_expand_is_rewritten_into_its_synthesized_reference(): void + { + $root = ExpansionContext::of(ref('tags')->expand())->root(); + + static::assertInstanceOf(ResolvedReference::class, $root); + static::assertSame("\0expand:0", $root->name()); + } + + public function test_positions_name_the_source_row_and_the_element_of_every_output_position(): void + { + static::assertSame( + [[0, 0, 1], ["\0expand:0" => ['x', 'y', 'z']]], + ExpansionContext::of(ref('tags')->expand())->positions(array_to_rows([ + ['id' => 'a', 'tags' => ['x', 'y']], + ['id' => 'b', 'tags' => ['z']], + ], ListColumnsMother::tagsSchema()), flow_context(config())), + ); + } + + public function test_elements_append_the_cells_of_the_window_starting_at_the_offset(): void + { + $rows = array_to_rows([ + ['id' => 'a', 'tags' => ['x']], + ['id' => 'b', 'tags' => ['y']], + ], ListColumnsMother::tagsSchema()); + + static::assertSame( + [ + ['id' => 'a', 'tags' => ['x'], "\0expand:0" => 'y'], + ['id' => 'b', 'tags' => ['y'], "\0expand:0" => 'z'], + ], + ExpansionContext::of(ref('tags')->expand())->elements( + $rows, + ["\0expand:0" => ['x', 'y', 'z']], + 1, + flow_context(config())->backend(), + )->toArray(), + ); + } + + public function test_synthesized_declares_one_nullable_column_per_distinct_expand(): void + { + static::assertSame( + ["\0expand:0", "\0expand:1"], + ExpansionContext::of(structure([ + 'n' => ref('nums')->expand(), + 't' => ref('tags')->expand(), + ])) + ->synthesized() + ->references() + ->names(), + ); + } + + public function test_of_is_null_without_an_expand(): void + { + static::assertNull(Expansion::of( + (new ReferenceResolver())->resolve(concat(ref('id'), lit('x')), ListColumnsMother::schema()), + ListColumnsMother::schema(), + )); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/NestedExpandTransformerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/NestedExpandTransformerTest.php deleted file mode 100644 index 85eca30f2..000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/NestedExpandTransformerTest.php +++ /dev/null @@ -1,154 +0,0 @@ - ref('tags')->expand()])))->bind( - ListColumnsMother::tagsSchema(), - )->step; - - static::assertInstanceOf(NestedExpandTransformer::class, $step); - static::assertSame( - [ - ['id' => 'a', 'tags' => ['x', 'y'], 's' => ['tag' => 'x']], - ['id' => 'a', 'tags' => ['x', 'y'], 's' => ['tag' => 'y']], - ], - $step->transform(array_to_rows([ - ['id' => 'a', 'tags' => ['x', 'y']], - ['id' => 'b', 'tags' => []], - ], ListColumnsMother::tagsSchema()), flow_context(config()))->toArray(), - ); - } - - public function test_unpack_emits_one_row_per_element(): void - { - $step = (new ScalarFunctionTransformer( - 'u', - structure(['tag' => ref('tags')->expand()])->unpack(schema(str_schema('tag'))), - ))->bind(ListColumnsMother::tagsSchema())->step; - - static::assertInstanceOf(NestedExpandTransformer::class, $step); - static::assertSame( - [ - ['id' => 'a', 'tags' => ['x', 'y'], 'u.tag' => 'x'], - ['id' => 'a', 'tags' => ['x', 'y'], 'u.tag' => 'y'], - ], - $step->transform(array_to_rows([[ - 'id' => 'a', - 'tags' => ['x', 'y'], - ]], ListColumnsMother::tagsSchema()), flow_context(config()))->toArray(), - ); - } - - public function test_bind_rebinds_against_another_input(): void - { - $step = (new ScalarFunctionTransformer('s', structure(['tag' => ref('tags')->expand()])))->bind( - ListColumnsMother::tagsSchema(), - )->step; - - static::assertInstanceOf(NestedExpandTransformer::class, $step); - - $rebound = $step->bind(schema(list_schema('tags', type_list(type_integer())))); - - static::assertInstanceOf(NestedExpandTransformer::class, $rebound->step); - static::assertEquals( - schema( - list_schema('tags', type_list(type_integer())), - structure_schema('s', type_structure(['tag' => type_integer()])), - ), - $rebound->output, - ); - } - - public function test_a_definition_entry_is_declared_as_given(): void - { - $bound = (new ScalarFunctionTransformer( - str_schema('s', nullable: true), - concat(ref('id'), ref('tags')->expand()), - ))->bind(ListColumnsMother::tagsSchema()); - $step = $bound->step; - - static::assertInstanceOf(NestedExpandTransformer::class, $step); - static::assertEquals( - schema(str_schema('id'), list_schema('tags', type_list(type_string())), str_schema('s', nullable: true)), - $bound->output, - ); - static::assertSame( - [ - ['id' => 'a', 'tags' => ['x', 'y'], 's' => 'ax'], - ['id' => 'a', 'tags' => ['x', 'y'], 's' => 'ay'], - ], - $step->transform(array_to_rows([[ - 'id' => 'a', - 'tags' => ['x', 'y'], - ]], ListColumnsMother::tagsSchema()), flow_context(config()))->toArray(), - ); - } - - public function test_a_batch_under_another_schema_than_the_bound_one_is_conformed(): void - { - $step = (new ScalarFunctionTransformer('s', structure(['tag' => ref('tags')->expand()])))->bind(schema( - str_schema('id'), - list_schema('tags', type_list(type_string())), - str_schema('note', nullable: true), - ))->step; - - static::assertInstanceOf(NestedExpandTransformer::class, $step); - - $result = $step->transform(array_to_rows([[ - 'id' => 'a', - 'tags' => ['x'], - ]], ListColumnsMother::tagsSchema()), flow_context(config())); - - static::assertEquals( - schema( - str_schema('id'), - list_schema('tags', type_list(type_string())), - str_schema('note', nullable: true), - structure_schema('s', type_structure(['tag' => type_string()])), - ), - $result->schema(), - ); - static::assertSame([['id' => 'a', 'tags' => ['x'], 'note' => null, 's' => ['tag' => 'x']]], $result->toArray()); - } - - public function test_a_null_under_a_not_null_definition_names_its_output_row(): void - { - $input = schema(list_schema('tags', type_list(type_optional(type_string())))); - $step = (new ScalarFunctionTransformer(str_schema('s'), ref('tags')->expand()->coalesce()))->bind($input)->step; - - static::assertInstanceOf(NestedExpandTransformer::class, $step); - - $this->expectException(SchemaMismatchException::class); - $this->expectExceptionMessage('column "s" (row 1)'); - - $step->transform(array_to_rows([['tags' => ['x']], ['tags' => [null]]], $input), flow_context(config())); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/NestedExpansionTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/NestedExpansionTest.php deleted file mode 100644 index 5c8562525..000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/NestedExpansionTest.php +++ /dev/null @@ -1,204 +0,0 @@ - $override - * @param list $eval - */ - #[DataProvider('expansions')] - public function test_declares_the_zipped_type_and_gives_one_value_per_zipped_position( - ScalarFunction $tree, - array $override, - string $returns, - array $eval, - ): void { - $expansion = NestedExpansionContext::of($tree); - - static::assertSame($returns, $expansion->returns()->toString()); - static::assertSame($eval, $expansion->eval(ListColumnsMother::rows($override), flow_context(config()))[1]); - } - - /** - * @return Generator, string, list}> - */ - public static function expansions(): Generator - { - yield 'one expand' => [ - structure(['tag' => ref('tags')->expand()]), - [], - 'structure{tag: string}', - [['tag' => 'x'], ['tag' => 'y']], - ]; - yield 'zip pads the shorter' => [ - structure(['n' => ref('nums')->expand(), 'tag' => ref('tags')->expand()]), - [], - 'structure{n: ?integer, tag: ?string}', - [['n' => 1, 'tag' => 'x'], ['n' => 2, 'tag' => 'y'], ['n' => 3, 'tag' => null]], - ]; - yield 'concat skips a padded null' => [ - concat(ref('nums')->expand(), ref('tags')->expand()), - [], - 'string', - ['1x', '2y', '3'], - ]; - yield 'sole empty list' => [ - structure(['tag' => ref('tags')->expand()]), - ['tags' => []], - 'structure{tag: string}', - [], - ]; - yield 'empty beside non-empty' => [ - structure(['n' => ref('nums')->expand(), 'tag' => ref('tags')->expand()]), - ['nums' => [1, 2], 'tags' => []], - 'structure{n: ?integer, tag: ?string}', - [['n' => 1, 'tag' => null], ['n' => 2, 'tag' => null]], - ]; - yield 'onEach operand' => [ - ref('lists')->expand()->onEach(concat(ref('element'), lit('!'))), - [], - 'list', - [['q!', 'r!'], ['s!']], - ]; - - $tags = ref('tags')->expand(); - - yield 'a node holding a reference, used twice, gives two padded columns' => [ - structure(['a' => $tags, 'b' => $tags]), - [], - 'structure{a: ?string, b: ?string}', - [['a' => 'x', 'b' => 'x'], ['a' => 'y', 'b' => 'y']], - ]; - - $literal = lit(['x', 'y'])->expand(); - - yield 'a node without references, used twice, gives one column' => [ - structure(['a' => $literal, 'b' => $literal]), - [], - 'structure{a: string, b: string}', - [['a' => 'x', 'b' => 'x'], ['a' => 'y', 'b' => 'y']], - ]; - yield 'branch not taken still expands' => [ - when(ref('id')->equals(lit('b')), ref('tags')->expand(), lit('none')), - [], - 'string', - ['none', 'none'], - ]; - yield 'a null list gives no values' => [ - structure(['tag' => ref('tags')->expand()]), - ['tags' => null], - 'structure{tag: string}', - [], - ]; - yield 'a when guard does not stop the expand of a null list' => [ - when(ref('tags')->isNull(), lit('none'), ref('tags')->expand()), - ['tags' => null], - 'string', - [], - ]; - } - - public function test_a_padded_null_follows_the_null_rule_of_the_function_reading_it(): void - { - $expansion = NestedExpansionContext::of(structure([ - 'n' => ref('nums')->expand()->plus(lit(1)), - 't' => ref('tags')->expand(), - ])); - - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Plus function requires non-null values'); - - $expansion->eval(ListColumnsMother::rows([ - 'nums' => [1, 2], - 'tags' => ['x', 'y', 'z'], - ]), flow_context(config())); - } - - public function test_of_is_null_for_a_root_expand(): void - { - static::assertNull(NestedExpansion::of( - (new ReferenceResolver())->resolve(ref('tags')->expand(), ListColumnsMother::schema()), - ListColumnsMother::schema(), - )); - } - - public function test_of_is_null_without_an_expand(): void - { - static::assertNull(NestedExpansion::of( - (new ReferenceResolver())->resolve(concat(ref('id'), lit('x')), ListColumnsMother::schema()), - ListColumnsMother::schema(), - )); - } - - public function test_an_expand_over_a_map_reads_its_values_by_position(): void - { - static::assertSame( - [['v' => 1], ['v' => 2]], - NestedExpansionContext::of(structure([ - 'v' => ref('m')->expand(), - ]), schema(map_schema('m', type_map(type_string(), type_integer()))))->eval(array_to_rows([['m' => [ - 'a' => 1, - 'b' => 2, - ]]], schema(map_schema('m', type_map(type_string(), type_integer())))), flow_context(config()))[1], - ); - } - - public function test_every_element_names_the_row_it_comes_from(): void - { - static::assertSame( - [[0, 0, 1], [['tag' => 'x'], ['tag' => 'y'], ['tag' => 'z']]], - NestedExpansionContext::of(structure(['tag' => ref('tags')->expand()]))->eval(array_to_rows([ - ['id' => 'a', 'tags' => ['x', 'y']], - ['id' => 'b', 'tags' => ['z']], - ], ListColumnsMother::tagsSchema()), flow_context(config())), - ); - } - - public function test_the_synthesized_column_does_not_shadow_an_input_column(): void - { - static::assertSame( - [['c' => 'kept', 't' => 'x']], - NestedExpansionContext::of( - structure(['c' => ref("\0expand:0"), 't' => ref('tags')->expand()]), - schema(str_schema("\0expand:0"), list_schema('tags', type_list(type_string()))), - )->eval( - array_to_rows( - [["\0expand:0" => 'kept', 'tags' => ['x']]], - schema(str_schema("\0expand:0"), list_schema('tags', type_list(type_string()))), - ), - flow_context(config()), - )[1], - ); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/ScalarFunctionTransformerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/ScalarFunctionTransformerTest.php index ed2090f73..f5387428e 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/ScalarFunctionTransformerTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/ScalarFunctionTransformerTest.php @@ -13,13 +13,11 @@ use Flow\ETL\Exception\InvalidLogicException; use Flow\ETL\Exception\SchemaDefinitionNotFoundException; use Flow\ETL\Exception\SchemaMismatchException; -use Flow\ETL\Function\ArrayExpand; use Flow\ETL\Function\ArrayUnpack; use Flow\ETL\Function\ScalarFunction; use Flow\ETL\Tests\Double\NonStructureUnpackStub; use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Tests\Mother\ListColumnsMother; -use Flow\ETL\Transformer\NestedExpandTransformer; use Flow\ETL\Transformer\ScalarFunctionTransformer; use Generator; use PHPUnit\Framework\Attributes\DataProvider; @@ -29,7 +27,6 @@ use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; -use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\rows; @@ -76,20 +73,6 @@ public function test_bind_replaces_an_existing_column_with_the_derived_one(): vo ); } - public function test_expand_results(): void - { - static::assertEquals( - [ - ['array' => 1], - ['array' => 2], - ['array' => 3], - ], - (new ScalarFunctionTransformer('array', new ArrayExpand(lit([1, 2, 3]), ArrayExpand\ArrayExpand::VALUES))) - ->transform(array_to_rows([[]], schema()), flow_context(config())) - ->toArray(), - ); - } - public function test_lit_expression_on_empty_rows(): void { static::assertEquals( @@ -273,17 +256,6 @@ public function test_a_batch_arriving_under_another_schema_than_the_bound_one_is ); } - public function test_an_expanded_null_under_a_not_null_declaration_names_its_row(): void - { - $this->expectException(SchemaMismatchException::class); - $this->expectExceptionMessage('column "out" (row 1)'); - - (new ScalarFunctionTransformer( - int_schema('out'), - new ArrayExpand(lit([1, null]), ArrayExpand\ArrayExpand::VALUES), - ))->transform(array_to_rows([[]], schema()), flow_context(config())); - } - public function test_an_empty_batch_is_bound_against_its_own_schema(): void { $this->expectException(SchemaDefinitionNotFoundException::class); @@ -294,8 +266,8 @@ public function test_an_empty_batch_is_bound_against_its_own_schema(): void ); } - #[DataProvider('trees_without_a_nested_expand')] - public function test_bind_keeps_a_tree_without_a_nested_expand_on_itself(ScalarFunction $function): void + #[DataProvider('trees_without_an_expand')] + public function test_bind_keeps_a_tree_without_an_expand_on_itself(ScalarFunction $function): void { static::assertInstanceOf( ScalarFunctionTransformer::class, @@ -306,104 +278,18 @@ public function test_bind_keeps_a_tree_without_a_nested_expand_on_itself(ScalarF /** * @return Generator */ - public static function trees_without_a_nested_expand(): Generator + public static function trees_without_an_expand(): Generator { yield 'no expand' => [concat(ref('id'), lit('x'))]; - yield 'root expand' => [ref('tags')->expand()]; } - public function test_bind_plans_a_nested_expand_on_nested_expand_transformer(): void - { - static::assertInstanceOf( - NestedExpandTransformer::class, - (new ScalarFunctionTransformer('s', structure(['tag' => ref('tags')->expand()])))->bind( - ListColumnsMother::schema(), - )->step, - ); - } - - public function test_bind_declares_zipped_expands_nullable(): void - { - static::assertEquals( - schema( - str_schema('id'), - list_schema('tags', type_list(type_string())), - list_schema('nums', type_list(type_integer())), - structure_schema('s', type_structure([ - 'n' => type_optional(type_integer()), - 'tag' => type_optional(type_string()), - ])), - ), - (new ScalarFunctionTransformer('s', structure([ - 'n' => ref('nums')->expand(), - 'tag' => ref('tags')->expand(), - ])))->bind(schema( - str_schema('id'), - list_schema('tags', type_list(type_string())), - list_schema('nums', type_list(type_integer())), - ))->output, - ); - } - - public function test_bind_plans_an_unpack_over_a_nested_expand_on_nested_expand_transformer(): void - { - $bound = (new ScalarFunctionTransformer( - 'u', - structure(['tag' => ref('tags')->expand()])->unpack(schema(str_schema('tag'))), - ))->bind(ListColumnsMother::tagsSchema()); - - static::assertInstanceOf(NestedExpandTransformer::class, $bound->step); - static::assertEquals( - schema( - str_schema('id'), - list_schema('tags', type_list(type_string())), - str_schema('u.tag', nullable: true), - ), - $bound->output, - ); - } - - public function test_an_unbound_nested_expand_is_expanded(): void - { - static::assertSame( - [ - ['id' => 'a', 'tags' => ['x', 'y'], 's' => ['tag' => 'x']], - ['id' => 'a', 'tags' => ['x', 'y'], 's' => ['tag' => 'y']], - ], - (new ScalarFunctionTransformer('s', structure(['tag' => ref('tags')->expand()]))) - ->transform(array_to_rows([[ - 'id' => 'a', - 'tags' => ['x', 'y'], - ]], ListColumnsMother::tagsSchema()), flow_context(config())) - ->toArray(), - ); - } - - public function test_an_unbound_unpack_over_a_nested_expand_is_expanded(): void - { - static::assertSame( - [ - ['id' => 'a', 'tags' => ['x', 'y'], 'u.tag' => 'x'], - ['id' => 'a', 'tags' => ['x', 'y'], 'u.tag' => 'y'], - ], - (new ScalarFunctionTransformer( - 'u', - structure(['tag' => ref('tags')->expand()])->unpack(schema(str_schema('tag'))), - )) - ->transform(array_to_rows([[ - 'id' => 'a', - 'tags' => ['x', 'y'], - ]], ListColumnsMother::tagsSchema()), flow_context(config())) - ->toArray(), - ); - } - - #[DataProvider('expands_inside_an_expand')] - public function test_bind_refuses_an_expand_inside_an_expand(ScalarFunction $function): void + #[DataProvider('expanding_functions')] + public function test_bind_refuses_an_expanding_function(ScalarFunction $function): void { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage( - 'array_expand() cannot contain another array_expand(). Expand one level per withEntry().', + 'transform() cannot contain array_expand(), it turns one row into many rows. ' + . 'Expand with withEntry() first, then use the new column.', ); (new ScalarFunctionTransformer('v', $function))->bind(ListColumnsMother::schema()); @@ -412,20 +298,19 @@ public function test_bind_refuses_an_expand_inside_an_expand(ScalarFunction $fun /** * @return Generator */ - public static function expands_inside_an_expand(): Generator + public static function expanding_functions(): Generator { - yield 'at the root' => [ref('lists')->expand()->expand()]; - yield 'inside a structure' => [structure(['v' => ref('lists')->expand()->expand()])]; + yield 'at the root' => [ref('tags')->expand()]; + yield 'inside a structure' => [structure(['v' => ref('tags')->expand()])]; + yield 'unpacked' => [structure(['v' => ref('tags')->expand()])->unpack(schema(str_schema('v')))]; } - public function test_an_unbound_expand_inside_an_expand_is_refused(): void + public function test_transform_refuses_an_expanding_function(): void { $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage( - 'array_expand() cannot contain another array_expand(). Expand one level per withEntry().', - ); + $this->expectExceptionMessage('transform() cannot contain array_expand()'); - (new ScalarFunctionTransformer('v', ref('lists')->expand()->expand()))->transform( + (new ScalarFunctionTransformer('v', ref('tags')->expand()))->transform( ListColumnsMother::rows()->matchTo(ListColumnsMother::schema(), new AdaptiveBackend()), flow_context(config()), ); @@ -440,22 +325,6 @@ public function test_bind_refuses_an_unpack_whose_type_is_not_a_structure(): voi (new ScalarFunctionTransformer('u', new NonStructureUnpackStub()))->bind(schema()); } - public function test_an_expand_explodes_every_row_of_the_batch_in_order(): void - { - $rows = array_to_rows( - [['id' => 1, 'list' => [1, 2]], ['id' => 2, 'list' => []], ['id' => 3, 'list' => [3]]], - schema(int_schema('id'), list_schema('list', type_list(type_integer()))), - ); - - static::assertSame( - [['id' => 1, 'value' => 1], ['id' => 1, 'value' => 2], ['id' => 3, 'value' => 3]], - (new ScalarFunctionTransformer('value', ref('list')->expand())) - ->transform($rows, flow_context()) - ->project(schema(int_schema('id'), int_schema('value')), new AdaptiveBackend()) - ->toArray(), - ); - } - public function test_an_unpack_fills_one_column_per_declared_element_for_every_row(): void { $rows = array_to_rows([ diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/SplittingFrameEncoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/SplittingFrameEncoderTest.php new file mode 100644 index 000000000..8e07e5fa8 --- /dev/null +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/SplittingFrameEncoderTest.php @@ -0,0 +1,23 @@ +encode($rows), $rows->count()]], + (new SplittingFrameEncoder())->encode($rows), + ); + } +} diff --git a/src/extension/arrow-ext/src/parquet/canonical.rs b/src/extension/arrow-ext/src/parquet/canonical.rs index 45ddb218c..80b5dfaca 100644 --- a/src/extension/arrow-ext/src/parquet/canonical.rs +++ b/src/extension/arrow-ext/src/parquet/canonical.rs @@ -13,7 +13,7 @@ use arrow_array::types::{ }; use arrow_array::{ make_array, Array, ArrayRef, ArrowPrimitiveType, BinaryArray, FixedSizeBinaryArray, Float64Array, GenericByteArray, - ListArray, MapArray, PrimitiveArray, StructArray, + LargeBinaryArray, ListArray, MapArray, PrimitiveArray, StructArray, }; use arrow_buffer::{OffsetBuffer, ScalarBuffer}; use arrow_schema::{DataType, Field, FieldRef, Fields, TimeUnit}; @@ -74,7 +74,7 @@ fn canonical_data_type(data_type: &DataType) -> Result { | DataType::Binary | DataType::LargeUtf8 | DataType::LargeBinary - | DataType::FixedSizeBinary(_) => DataType::Binary, + | DataType::FixedSizeBinary(_) => DataType::LargeBinary, DataType::Timestamp(_, _) => timestamp(), DataType::Time64(TimeUnit::Microsecond | TimeUnit::Nanosecond) | DataType::Time32(TimeUnit::Millisecond | TimeUnit::Second) => DataType::Duration(TimeUnit::Microsecond), @@ -196,6 +196,7 @@ fn narrowed(offsets: &[i64]) -> Result, Error> { Ok(OffsetBuffer::new(ScalarBuffer::from(narrowed))) } +/// LargeBinary narrowed to Binary for a writer column: past `i32::MAX` bytes in one write it is refused. fn large_binary(array: &ArrayRef) -> Result { let data = array.to_data(); let offsets = data.buffers()[0].typed_data::(); @@ -209,30 +210,31 @@ fn large_binary(array: &ArrayRef) -> Result { ))) } -/// Fixed-size values as Binary over the same value buffer: offsets `n·i`. -fn fixed_binary(array: &ArrayRef) -> Result { +/// Binary or Utf8 as LargeBinary over the same value buffer: the offsets widened to i64. +fn widened_binary(array: &ArrayRef) -> ArrayRef { + let data = array.to_data(); + let offsets = &data.buffers()[0].typed_data::()[data.offset()..data.offset() + data.len() + 1]; + + Arc::new(LargeBinaryArray::new( + OffsetBuffer::new(ScalarBuffer::from( + offsets.iter().map(|offset| i64::from(*offset)).collect::>(), + )), + data.buffers()[1].clone(), + data.nulls().cloned(), + )) +} + +/// Fixed-size values as LargeBinary over the same value buffer: offsets `n·i`. +fn fixed_binary(array: &ArrayRef) -> ArrayRef { let fixed = array.as_fixed_size_binary(); - let size = i32::try_from(fixed.value_size()).map_err(|_| Error::Overflow { - column: String::new(), - row: 0, - })?; - let offsets = (0..=fixed.len()) - .map(|row| { - i32::try_from(row) - .ok() - .and_then(|row| row.checked_mul(size)) - .ok_or(Error::Overflow { - column: String::new(), - row: row.saturating_sub(1), - }) - }) - .collect::, _>>()?; + let size = fixed.value_size() as i64; + let offsets = (0..=fixed.len() as i64).map(|row| row * size).collect::>(); - Ok(Arc::new(BinaryArray::new( + Arc::new(LargeBinaryArray::new( OffsetBuffer::new(ScalarBuffer::from(offsets)), fixed.values().clone(), fixed.nulls().cloned(), - ))) + )) } fn cast(array: &ArrayRef) -> Result { @@ -254,9 +256,9 @@ fn cast(array: &ArrayRef) -> Result { i64::try_from(value).ok() })?), DataType::Float32 => Arc::new(array.as_primitive::().unary::<_, Float64Type>(f64::from)), - DataType::Utf8 | DataType::Binary => retagged(array, DataType::Binary), - DataType::LargeUtf8 | DataType::LargeBinary => large_binary(array)?, - DataType::FixedSizeBinary(_) => fixed_binary(array)?, + DataType::Utf8 | DataType::Binary => widened_binary(array), + DataType::LargeUtf8 | DataType::LargeBinary => retagged(array, DataType::LargeBinary), + DataType::FixedSizeBinary(_) => fixed_binary(array), DataType::Timestamp(TimeUnit::Microsecond, _) => retagged(array, timestamp()), DataType::Timestamp(TimeUnit::Millisecond, _) => { micros::(array, |ms| ms.checked_mul(1_000))? @@ -358,7 +360,8 @@ pub fn to_parquet(array: &ArrayRef, target: &DataType) -> Result utf8(array)?, + (DataType::LargeBinary, DataType::Binary) => large_binary(array)?, + (DataType::LargeBinary, DataType::Utf8) => utf8(&large_binary(array)?)?, (DataType::Int64, DataType::Int8) => Arc::new(narrowed_int::(array)?), (DataType::Int64, DataType::Int16) => Arc::new(narrowed_int::(array)?), (DataType::Int64, DataType::Int32) => Arc::new(narrowed_int::(array)?), @@ -375,7 +378,7 @@ pub fn to_parquet(array: &ArrayRef, target: &DataType) -> Result(array, |value| decimal_unscaled(value, *precision, *scale))? .with_precision_and_scale(*precision, *scale)?, ), - (DataType::Binary, DataType::FixedSizeBinary(size)) => fixed_size(array, *size)?, + (DataType::LargeBinary, DataType::FixedSizeBinary(size)) => fixed_size(&large_binary(array)?, *size)?, (DataType::Duration(TimeUnit::Microsecond), DataType::Time64(TimeUnit::Microsecond)) => { retagged(array, target.clone()) } @@ -733,7 +736,7 @@ mod tests { } #[test] - fn strings_and_binaries_are_binary() { + fn strings_and_binaries_are_large_binary() { let expected: Vec> = vec![Some(b"a"), None, Some(b"")]; for array in [ @@ -744,16 +747,26 @@ mod tests { ] { let canonical = read(array); - assert_eq!(canonical.as_binary::().iter().collect::>(), expected); + assert_eq!(canonical.as_binary::().iter().collect::>(), expected); } } #[test] - fn a_sliced_large_string_is_rebased() { + fn a_sliced_large_string_keeps_its_rows() { let array = LargeStringArray::from(vec!["skipped", "kept", "too"]).slice(1, 2); assert_eq!( - read(Arc::new(array)).as_binary::().iter().collect::>(), + read(Arc::new(array)).as_binary::().iter().collect::>(), + vec![Some(&b"kept"[..]), Some(&b"too"[..])] + ); + } + + #[test] + fn a_sliced_string_is_widened_to_its_rows() { + let array = StringArray::from(vec!["skipped", "kept", "too"]).slice(1, 2); + + assert_eq!( + read(Arc::new(array)).as_binary::().iter().collect::>(), vec![Some(&b"kept"[..]), Some(&b"too"[..])] ); } @@ -908,7 +921,7 @@ mod tests { builder.append(false).unwrap(); let canonical = read(Arc::new(builder.finish())); - assert_eq!(canonical.data_type(), &map_of(DataType::Binary, DataType::Int64)); + assert_eq!(canonical.data_type(), &map_of(DataType::LargeBinary, DataType::Int64)); assert_eq!(int64(canonical.as_map().values()), vec![Some(1)]); assert!(canonical.is_null(1)); } @@ -931,7 +944,7 @@ mod tests { canonical.data_type(), &DataType::Struct(Fields::from(vec![ Field::new("id", DataType::Int64, true), - Field::new("name", DataType::Binary, true), + Field::new("name", DataType::LargeBinary, true), ])) ); assert_eq!(int64(canonical.as_struct().column(0)), vec![Some(1), Some(2)]); @@ -984,7 +997,7 @@ mod tests { } #[test] - fn fixed_size_binaries_of_another_size_than_16_are_binary() { + fn fixed_size_binaries_of_another_size_than_16_are_large_binary() { let array = FixedSizeBinaryArray::try_from_sparse_iter_with_size( vec![Some(*b"abcd"), None, Some(*b"wxyz"), Some(*b"skip")].into_iter(), 4, @@ -994,7 +1007,7 @@ mod tests { let canonical = read(Arc::new(array)); assert_eq!( - canonical.as_binary::().iter().collect::>(), + canonical.as_binary::().iter().collect::>(), vec![Some(&b"abcd"[..]), None, Some(&b"wxyz"[..])] ); } @@ -1151,7 +1164,7 @@ mod tests { #[test] fn to_parquet_writes_fixed_size_binaries_of_their_length() { - let array: ArrayRef = Arc::new(BinaryArray::from(vec![Some(&b"abcd"[..]), None])); + let array: ArrayRef = Arc::new(LargeBinaryArray::from(vec![Some(&b"abcd"[..]), None])); let fixed = to_parquet(&array, &DataType::FixedSizeBinary(4)).unwrap(); assert_eq!( @@ -1268,9 +1281,23 @@ mod tests { ); } + #[test] + fn to_parquet_writes_binary_narrowed() { + let binary: ArrayRef = Arc::new(LargeBinaryArray::from(vec![Some(&b"zazolc"[..]), None])); + + assert_eq!( + to_parquet(&binary, &DataType::Binary) + .unwrap() + .as_binary::() + .iter() + .collect::>(), + vec![Some(&b"zazolc"[..]), None] + ); + } + #[test] fn to_parquet_writes_valid_utf8_as_strings() { - let binary: ArrayRef = Arc::new(BinaryArray::from(vec![Some(&b"zazolc"[..]), None])); + let binary: ArrayRef = Arc::new(LargeBinaryArray::from(vec![Some(&b"zazolc"[..]), None])); assert_eq!( to_parquet(&binary, &DataType::Utf8) @@ -1284,7 +1311,11 @@ mod tests { #[test] fn to_parquet_refuses_invalid_utf8_at_its_row() { - let binary: ArrayRef = Arc::new(BinaryArray::from(vec![Some(&b"ok"[..]), None, Some(&b"\xff\xfe"[..])])); + let binary: ArrayRef = Arc::new(LargeBinaryArray::from(vec![ + Some(&b"ok"[..]), + None, + Some(&b"\xff\xfe"[..]), + ])); assert!(matches!( to_parquet(&binary, &DataType::Utf8), @@ -1295,9 +1326,9 @@ mod tests { #[test] fn to_parquet_refuses_invalid_utf8_at_its_parent_row() { let list: ArrayRef = Arc::new(ListArray::new( - Arc::new(Field::new("item", DataType::Binary, true)), + Arc::new(Field::new("item", DataType::LargeBinary, true)), arrow_buffer::OffsetBuffer::new(vec![0, 1, 3].into()), - Arc::new(BinaryArray::from(vec![&b"a"[..], b"b", b"\xff"])), + Arc::new(LargeBinaryArray::from(vec![&b"a"[..], b"b", b"\xff"])), None, )); let target = DataType::List(Arc::new(Field::new("element", DataType::Utf8, true))); @@ -1329,7 +1360,7 @@ mod tests { false, ); - assert_eq!(map.data_type(), &map_of(DataType::Binary, DataType::Int64)); + assert_eq!(map.data_type(), &map_of(DataType::LargeBinary, DataType::Int64)); assert_eq!(to_parquet(&map, &target).unwrap().data_type(), &target); let structure = read(Arc::new(StructArray::from(vec![( diff --git a/src/extension/arrow-ext/src/parquet/cells.rs b/src/extension/arrow-ext/src/parquet/cells.rs index 34426e151..f5ce878e6 100644 --- a/src/extension/arrow-ext/src/parquet/cells.rs +++ b/src/extension/arrow-ext/src/parquet/cells.rs @@ -5,8 +5,8 @@ use std::any::Any; use std::sync::Arc; use arrow_array::builder::{ - ArrayBuilder, BinaryBuilder, BooleanBuilder, Date32Builder, DurationMicrosecondBuilder, FixedSizeBinaryBuilder, - Float64Builder, Int64Builder, ListBuilder, MapBuilder, MapFieldNames, TimestampMicrosecondBuilder, + ArrayBuilder, BooleanBuilder, Date32Builder, DurationMicrosecondBuilder, FixedSizeBinaryBuilder, Float64Builder, + Int64Builder, LargeBinaryBuilder, ListBuilder, MapBuilder, MapFieldNames, TimestampMicrosecondBuilder, }; use arrow_array::cast::AsArray; use arrow_array::types::{Date32Type, DurationMicrosecondType, Float64Type, Int64Type, TimestampMicrosecondType}; @@ -68,7 +68,7 @@ impl ReadCell { DataType::Boolean => ReadCell::Bool, DataType::Int64 => ReadCell::Int, DataType::Float64 => ReadCell::Float, - DataType::Binary => ReadCell::Bytes, + DataType::LargeBinary => ReadCell::Bytes, DataType::FixedSizeBinary(16) if is_uuid(parquet) => ReadCell::Uuid, DataType::FixedSizeBinary(16) => ReadCell::Bytes, DataType::Date32 => ReadCell::Date, @@ -163,7 +163,7 @@ impl ReadCell { ReadCell::Bytes => { zv = zval_str(match array.data_type() { DataType::FixedSizeBinary(_) => array.as_fixed_size_binary().value(row), - _ => array.as_binary::().value(row), + _ => array.as_binary::().value(row), }); } ReadCell::Uuid => zv = zval_str(&uuid_text(array.as_fixed_size_binary().value(row))), @@ -484,7 +484,7 @@ pub enum ColumnBuilder { Bool(BooleanBuilder), Int(Int64Builder), Float(Float64Builder), - Bytes(BinaryBuilder), + Bytes(LargeBinaryBuilder), Uuid(FixedSizeBinaryBuilder), Date(Date32Builder), Timestamp(TimestampMicrosecondBuilder), @@ -533,7 +533,7 @@ impl ColumnBuilder { DataType::Boolean => ColumnBuilder::Bool(BooleanBuilder::with_capacity(capacity)), DataType::Int64 => ColumnBuilder::Int(Int64Builder::with_capacity(capacity)), DataType::Float64 => ColumnBuilder::Float(Float64Builder::with_capacity(capacity)), - DataType::Binary => ColumnBuilder::Bytes(BinaryBuilder::with_capacity(capacity, 1024)), + DataType::LargeBinary => ColumnBuilder::Bytes(LargeBinaryBuilder::with_capacity(capacity, 1024)), DataType::FixedSizeBinary(size) => { ColumnBuilder::Uuid(FixedSizeBinaryBuilder::with_capacity(capacity, *size)) } @@ -683,9 +683,9 @@ impl WriteCell { | DataType::UInt64 => (WriteCell::Int, DataType::Int64), DataType::Float32 | DataType::Float64 => (WriteCell::Float, DataType::Float64), DataType::Decimal128(_, _) => (WriteCell::Decimal, DataType::Float64), - DataType::Utf8 | DataType::Binary => (WriteCell::Bytes, DataType::Binary), + DataType::Utf8 | DataType::Binary => (WriteCell::Bytes, DataType::LargeBinary), DataType::FixedSizeBinary(16) if is_uuid(target) => (WriteCell::Uuid, DataType::FixedSizeBinary(16)), - DataType::FixedSizeBinary(_) => (WriteCell::Bytes, DataType::Binary), + DataType::FixedSizeBinary(_) => (WriteCell::Bytes, DataType::LargeBinary), DataType::Date32 => (WriteCell::Date, DataType::Date32), DataType::Timestamp(_, _) => ( WriteCell::Timestamp, @@ -889,8 +889,8 @@ impl WriteCell { }) } - /// Whether `builder` takes `values` (one row's, every value bound for it) with its offsets in i32; only cells - /// holding offsets can pass it. + /// Whether `builder` takes `values` (one row's, every value bound for it) with its offsets in i32 - the Parquet + /// target narrows strings to i32; only cells holding offsets can pass it. pub fn fits(&self, builder: &mut ColumnBuilder, values: &[&Validated]) -> bool { match (self, builder) { (WriteCell::Bytes, ColumnBuilder::Bytes(bytes)) => offsets_fit( diff --git a/src/extension/arrow-ext/src/parquet/read.rs b/src/extension/arrow-ext/src/parquet/read.rs index bb661f2cf..5c7f127fc 100644 --- a/src/extension/arrow-ext/src/parquet/read.rs +++ b/src/extension/arrow-ext/src/parquet/read.rs @@ -613,7 +613,7 @@ mod tests { vec![Some(1), None, None] ); assert_eq!( - arrays[1].as_binary::().iter().collect::>(), + arrays[1].as_binary::().iter().collect::>(), vec![Some(&b"a"[..]), None, Some(&b"c"[..])] ); } @@ -624,7 +624,7 @@ mod tests { assert_eq!(reader.fields()[0].name(), "structure.name"); assert!(reader.fields()[0].is_nullable()); - assert_eq!(reader.types(), &[DataType::Binary]); + assert_eq!(reader.types(), &[DataType::LargeBinary]); } #[test] diff --git a/src/extension/flow-php-ext/crates/flow-batch-frame/src/column.rs b/src/extension/flow-php-ext/crates/flow-batch-frame/src/column.rs index 66fcb2c56..063113b16 100644 --- a/src/extension/flow-php-ext/crates/flow-batch-frame/src/column.rs +++ b/src/extension/flow-php-ext/crates/flow-batch-frame/src/column.rs @@ -36,7 +36,7 @@ pub fn encode(data: &ArrayData, kind: &Kind) -> Result>, Error> { }, None, &mut out, - ); + )?; Ok(out) } @@ -79,9 +79,15 @@ impl Rows { } } -fn encode_node(array: &dyn Array, kind: &Kind, rows: &Rows, parent: Option<&[bool]>, out: &mut Vec>) { +fn encode_node( + array: &dyn Array, + kind: &Kind, + rows: &Rows, + parent: Option<&[bool]>, + out: &mut Vec>, +) -> Result<(), Error> { if let Kind::Null = kind { - return; + return Ok(()); } let valid = effective_validity(array, rows, parent); @@ -122,12 +128,12 @@ fn encode_node(array: &dyn Array, kind: &Kind, rows: &Rows, parent: Option<&[boo out.push(bytes); } Kind::Bytes => { - let values = array.as_binary::(); + let values = array.as_binary::(); let offsets = values.value_offsets(); let data = values.value_data(); if let (Rows::Range { start, len }, None) = (rows, valid) { - out.push(rebased(&offsets[*start..=start + len])); + out.push(frame_offsets(&offsets[*start..=start + len])?); out.push(data[offsets[*start] as usize..offsets[start + len] as usize].to_vec()); } else { let mut packed = Vec::with_capacity((rows.len() + 1) * 4); @@ -140,7 +146,7 @@ fn encode_node(array: &dyn Array, kind: &Kind, rows: &Rows, parent: Option<&[boo bytes.extend_from_slice(&data[offsets[i] as usize..offsets[i + 1] as usize]); } - packed.extend_from_slice(&(bytes.len() as u32).to_le_bytes()); + packed.extend_from_slice(&frame_offset(bytes.len() as u64)?.to_le_bytes()); } out.push(packed); @@ -151,24 +157,26 @@ fn encode_node(array: &dyn Array, kind: &Kind, rows: &Rows, parent: Option<&[boo let list = array.as_list::(); let (offsets, children) = compact(list.value_offsets(), rows, valid); out.push(offsets); - encode_node(list.values().as_ref(), &element.kind, &children, None, out); + encode_node(list.values().as_ref(), &element.kind, &children, None, out)?; } Kind::Map(key, value) => { let map = array.as_map(); let (offsets, children) = compact(map.value_offsets(), rows, valid); out.push(offsets); out.push(Vec::new()); - encode_node(map.keys().as_ref(), &key.kind, &children, None, out); - encode_node(map.values().as_ref(), &value.kind, &children, None, out); + encode_node(map.keys().as_ref(), &key.kind, &children, None, out)?; + encode_node(map.values().as_ref(), &value.kind, &children, None, out)?; } Kind::Struct(fields) => { let structure = array.as_struct(); for (i, field) in fields.iter().enumerate() { - encode_node(structure.column(i).as_ref(), &field.kind, rows, valid, out); + encode_node(structure.column(i).as_ref(), &field.kind, rows, valid, out)?; } } } + + Ok(()) } /// The null of a row is its own or its parent structure's; `None` when every row is valid. @@ -254,6 +262,26 @@ fn compact(offsets: &[i32], rows: &Rows, valid: Option<&[bool]>) -> (Vec, Ro (packed, Rows::Indices(children)) } +/// Native string offsets are i64; a frame's are u32 the PHP decoder reads, capped at i32 like PHP's own encode(). A +/// longer range is refused, so a writer can split the batch (FloeStreamWriter halves it). +fn frame_offsets(offsets: &[i64]) -> Result, Error> { + let mut packed = Vec::with_capacity(offsets.len() * 4); + + for offset in offsets { + packed.extend_from_slice(&frame_offset((offset - offsets[0]) as u64)?.to_le_bytes()); + } + + Ok(packed) +} + +fn frame_offset(offset: u64) -> Result { + if offset > i32::MAX as u64 { + return Err(Error::OffsetOverflow { last: offset }); + } + + Ok(offset as u32) +} + fn rebased(offsets: &[i32]) -> Vec { offsets .iter() @@ -351,10 +379,13 @@ fn decode_node( }); } - fits_i32(last)?; + let widened = offsets + .chunks_exact(4) + .map(|offset| i64::from(u32::from_le_bytes(offset.try_into().expect("4-byte chunk")))) + .collect::>(); builder - .add_buffer(Buffer::from_slice_ref(offsets)) + .add_buffer(Buffer::from_vec(widened)) .add_buffer(Buffer::from_slice_ref(data)) } Kind::Null | Kind::List(_) | Kind::Map(_, _) | Kind::Struct(_) => { @@ -533,3 +564,36 @@ fn fits_i32(last: u32) -> Result<(), Error> { Ok(()) } + +#[cfg(test)] +mod tests { + use super::{frame_offsets, Error}; + + #[test] + fn frame_offsets_are_rebased_to_the_first() { + assert_eq!( + frame_offsets(&[10, 12, 17]).expect("a frame range"), + [0u32, 2, 7] + .iter() + .flat_map(|offset| offset.to_le_bytes()) + .collect::>(), + ); + } + + #[test] + fn a_frame_range_past_i32_is_refused() { + let last = i32::MAX as i64 + 1; + + assert!(matches!( + frame_offsets(&[0, last]), + Err(Error::OffsetOverflow { last: refused }) if refused == last as u64 + )); + } + + #[test] + fn a_large_native_offset_within_an_i32_frame_range_is_accepted() { + let start = i64::from(u32::MAX) * 2; + + assert!(frame_offsets(&[start, start + 5]).is_ok()); + } +} diff --git a/src/extension/flow-php-ext/crates/flow-batch-frame/src/kind.rs b/src/extension/flow-php-ext/crates/flow-batch-frame/src/kind.rs index fbc24068a..38a6111f3 100644 --- a/src/extension/flow-php-ext/crates/flow-batch-frame/src/kind.rs +++ b/src/extension/flow-php-ext/crates/flow-batch-frame/src/kind.rs @@ -181,7 +181,7 @@ pub fn data_type(kind: &Kind) -> DataType { Kind::Int32 => DataType::Date32, Kind::Float64 => DataType::Float64, Kind::Uuid => DataType::FixedSizeBinary(16), - Kind::Bytes => DataType::Binary, + Kind::Bytes => DataType::LargeBinary, Kind::Timestamp => DataType::Timestamp(TimeUnit::Microsecond, Some("UTC".into())), Kind::Duration => DataType::Duration(TimeUnit::Microsecond), Kind::List(element) => DataType::List(field("item", &element.kind)), diff --git a/src/extension/flow-php-ext/crates/flow-batch-frame/tests/column.rs b/src/extension/flow-php-ext/crates/flow-batch-frame/tests/column.rs index 36ff0d5b9..4e2d63fd1 100644 --- a/src/extension/flow-php-ext/crates/flow-batch-frame/tests/column.rs +++ b/src/extension/flow-php-ext/crates/flow-batch-frame/tests/column.rs @@ -2,11 +2,11 @@ mod common; use std::sync::Arc; -use arrow_array::builder::{BinaryBuilder, Int64Builder, MapBuilder, MapFieldNames}; +use arrow_array::builder::{Int64Builder, LargeBinaryBuilder, MapBuilder, MapFieldNames}; use arrow_array::types::Int64Type; use arrow_array::{ - Array, ArrayRef, BinaryArray, BooleanArray, Date32Array, FixedSizeBinaryArray, Float64Array, Int64Array, ListArray, - NullArray, StructArray, TimestampMicrosecondArray, + Array, ArrayRef, BooleanArray, Date32Array, FixedSizeBinaryArray, Float64Array, Int64Array, LargeBinaryArray, + ListArray, NullArray, StructArray, TimestampMicrosecondArray, }; use arrow_buffer::NullBuffer; use arrow_data::ArrayData; @@ -67,7 +67,7 @@ fn cases() -> Vec<(&'static str, Kind, ArrayData, Vec<&'static str>)> { key: "key".into(), value: "value".into(), }), - BinaryBuilder::new(), + LargeBinaryBuilder::new(), Int64Builder::new(), ); map.keys().append_value(b"a"); @@ -84,7 +84,7 @@ fn cases() -> Vec<(&'static str, Kind, ArrayData, Vec<&'static str>)> { ( "nullable string", kind_of("{\"type\":\"string\"}"), - BinaryArray::from(vec![Some(b"ab".as_ref()), None]).into_data(), + LargeBinaryArray::from(vec![Some(b"ab".as_ref()), None]).into_data(), vec!["01", "000000000200000002000000", "6162"], ), ( @@ -203,9 +203,13 @@ fn decodes_the_column_encode_test_cases_back() { #[test] fn a_selection_under_a_null_list_slot_is_compacted() { let kind = kind_of("{\"type\":\"list\",\"element\":{\"type\":\"string\"}}"); - let strings = BinaryArray::from(vec![b"a".as_ref(), b"bc", b"d"]); + let strings = LargeBinaryArray::from(vec![b"a".as_ref(), b"bc", b"d"]); let offsets = arrow_buffer::OffsetBuffer::new(vec![0, 1, 2, 3].into()); - let field = Arc::new(arrow_schema::Field::new("item", arrow_schema::DataType::Binary, true)); + let field = Arc::new(arrow_schema::Field::new( + "item", + arrow_schema::DataType::LargeBinary, + true, + )); let list = ListArray::new( field, offsets, @@ -228,7 +232,7 @@ fn a_selection_under_a_null_list_slot_is_compacted() { #[test] fn bytes_that_are_not_utf8_round_trip() { let kind = kind_of("{\"type\":\"string\"}"); - let data = BinaryArray::from(vec![b"a\xFFb".as_ref()]).into_data(); + let data = LargeBinaryArray::from(vec![b"a\xFFb".as_ref()]).into_data(); let buffers = encoded_hex(&data, &kind); let buffers: Vec<&str> = buffers.iter().map(String::as_str).collect(); diff --git a/src/extension/flow-php-ext/src/batch_columns.rs b/src/extension/flow-php-ext/src/batch_columns.rs index c0af6311e..2eaece43e 100644 --- a/src/extension/flow-php-ext/src/batch_columns.rs +++ b/src/extension/flow-php-ext/src/batch_columns.rs @@ -19,7 +19,6 @@ use crate::date_check::iso_instant_micros; use crate::exception::ext_exception; use crate::json_check::json_valid; use crate::kind_builder::KindBuilder; -use crate::physical::overflow; use crate::plan::{type_plan, TypePlan}; use crate::render::invalid_argument; use crate::uuid_check::is_uuid; @@ -249,12 +248,20 @@ pub fn native_text(values: &mut KindBuilder, kind: &Kind, cast: &CastKind, bytes .map(|value| values.append_fixed(&value.to_le_bytes())) .is_some()), (Kind::Boolean, CastKind::Boolean) => Ok(bool_from_str(bytes).map(|value| values.append_bool(value)).is_some()), - (Kind::Bytes, CastKind::String) => values.append_bytes(bytes).map(|()| true).map_err(overflow), + (Kind::Bytes, CastKind::String) => { + values.append_bytes(bytes); + + Ok(true) + } (Kind::Bytes, CastKind::NonEmptyString) if !bytes.is_empty() => { - values.append_bytes(bytes).map(|()| true).map_err(overflow) + values.append_bytes(bytes); + + Ok(true) } (Kind::Bytes, CastKind::Json) if json_gate(bytes) && json_valid(bytes) => { - values.append_bytes(bytes).map(|()| true).map_err(overflow) + values.append_bytes(bytes); + + Ok(true) } (Kind::Uuid, CastKind::Uuid) if is_uuid(bytes) => { Ok(uuid_bytes(bytes).map(|uuid| values.append_fixed(&uuid)).is_some()) diff --git a/src/extension/flow-php-ext/src/builder.rs b/src/extension/flow-php-ext/src/builder.rs index 277b02165..c3aa71d88 100644 --- a/src/extension/flow-php-ext/src/builder.rs +++ b/src/extension/flow-php-ext/src/builder.rs @@ -199,7 +199,7 @@ fn append_cast( true } (MapKeyKind::Str, Some(name), Kind::Bytes) => { - keys.append_bytes(name.as_bytes()).map_err(overflow)?; + keys.append_bytes(name.as_bytes()); true } @@ -337,9 +337,7 @@ pub(crate) fn append_native(builder: &mut KindBuilder, native: Native) -> Result Native::Days(days) => builder.append_fixed(&days.to_le_bytes()), Native::Bool(value) => builder.append_bool(value), Native::Uuid(bytes) => builder.append_fixed(&bytes), - Native::Bytes(string) => builder - .append_bytes(string.zend_str().expect("a native string").as_bytes()) - .map_err(overflow)?, + Native::Bytes(string) => builder.append_bytes(string.zend_str().expect("a native string").as_bytes()), } Ok(()) diff --git a/src/extension/flow-php-ext/src/json/read.rs b/src/extension/flow-php-ext/src/json/read.rs index 7367e286e..61d1eb7a0 100644 --- a/src/extension/flow-php-ext/src/json/read.rs +++ b/src/extension/flow-php-ext/src/json/read.rs @@ -654,7 +654,7 @@ fn into_column(values: &mut KindBuilder, kind: &Kind, cast: &CastKind, text: &st true } (MapKeyKind::Str, None, Kind::Bytes) => { - keys.append_bytes(name.as_bytes()).map_err(overflow)?; + keys.append_bytes(name.as_bytes()); true } diff --git a/src/extension/flow-php-ext/src/kind_builder.rs b/src/extension/flow-php-ext/src/kind_builder.rs index 1445dec92..b2e1b886d 100644 --- a/src/extension/flow-php-ext/src/kind_builder.rs +++ b/src/extension/flow-php-ext/src/kind_builder.rs @@ -10,7 +10,7 @@ use arrow_data::ArrayData; use arrow_schema::ArrowError; use flow_batch_frame::kind::{data_type, Kind}; -/// Offsets are i32 (D5): the last offset a row would reach past `i32::MAX`. +/// List and map offsets are i32 (D5): the last offset a row would reach past `i32::MAX`. String offsets are i64. pub struct OffsetOverflow(pub u64); pub enum KindBuilder { @@ -27,7 +27,7 @@ pub enum KindBuilder { validity: NullBufferBuilder, }, Bytes { - offsets: Vec, + offsets: Vec, data: Vec, validity: NullBufferBuilder, }, @@ -124,9 +124,11 @@ impl KindBuilder { values.append(false); validity.append_null(); } - KindBuilder::Bytes { offsets, validity, .. } - | KindBuilder::List { offsets, validity, .. } - | KindBuilder::Map { offsets, validity, .. } => { + KindBuilder::Bytes { offsets, validity, .. } => { + offsets.push(*offsets.last().expect("offsets start at 0")); + validity.append_null(); + } + KindBuilder::List { offsets, validity, .. } | KindBuilder::Map { offsets, validity, .. } => { offsets.push(*offsets.last().expect("offsets start at 0")); validity.append_null(); } @@ -164,7 +166,7 @@ impl KindBuilder { validity.append_non_null(); } - pub fn append_bytes(&mut self, bytes: &[u8]) -> Result<(), OffsetOverflow> { + pub fn append_bytes(&mut self, bytes: &[u8]) { let KindBuilder::Bytes { offsets, data, @@ -174,12 +176,9 @@ impl KindBuilder { unreachable!("append_bytes on a non bytes kind"); }; - let end = offset(data.len() + bytes.len())?; data.extend_from_slice(bytes); - offsets.push(end); + offsets.push(data.len() as i64); validity.append_non_null(); - - Ok(()) } /// The element builder of a list; call `end_entries` once the row's elements are appended. @@ -321,7 +320,7 @@ impl KindBuilder { Kind::Float64 => self.append_fixed(&array.as_primitive::().value(i).to_le_bytes()), Kind::Uuid => self.append_fixed(array.as_fixed_size_binary().value(i)), Kind::Boolean => self.append_bool(array.as_boolean().value(i)), - Kind::Bytes => self.append_bytes(array.as_binary::().value(i))?, + Kind::Bytes => self.append_bytes(array.as_binary::().value(i)), Kind::List(element) => { let list = array.as_list::(); let offsets = list.value_offsets(); @@ -472,10 +471,10 @@ mod tests { let mut row = |id: i64, tag: &[u8]| { let children = builder.struct_children(); children[0].append_fixed(&id.to_le_bytes()); - children[1].list_element().append_bytes(tag).ok(); + children[1].list_element().append_bytes(tag); children[1].end_entries().ok(); let (keys, values) = children[2].map_entries(); - keys.append_bytes(tag).ok(); + keys.append_bytes(tag); values.append_bool(true); children[2].end_entries().ok(); builder.end_struct(); @@ -497,7 +496,7 @@ mod tests { .column(1) .as_list::() .values() - .as_binary::() + .as_binary::() .value(0), b"kept" ); diff --git a/src/extension/flow-php-ext/src/physical.rs b/src/extension/flow-php-ext/src/physical.rs index e79f1c748..c9a285b3d 100644 --- a/src/extension/flow-php-ext/src/physical.rs +++ b/src/extension/flow-php-ext/src/physical.rs @@ -53,7 +53,7 @@ fn push(ht: &mut ZendHashTable, value: Zval) -> Result<(), PhpException> { /// A map key as `array_keys()` returns it: the int or string key `array_combine()` coerces. fn map_key(ht: &mut ZendHashTable, keys: &dyn Array, key: &Kind, j: usize, value: Zval) { match key { - Kind::Bytes => ht_insert(ht, keys.as_binary::().value(j), value), + Kind::Bytes => ht_insert(ht, keys.as_binary::().value(j), value), _ => { let index = long(keys, key, j); crate::ctx::ht_insert_long(ht, index, value); @@ -73,7 +73,7 @@ pub fn physical_at(array: &dyn Array, kind: &Kind, i: usize) -> Result double(array.as_primitive::().value(i)), Kind::Boolean => boolean(array.as_boolean().value(i)), Kind::Uuid => zval_str(array.as_fixed_size_binary().value(i)), - Kind::Bytes => zval_str(array.as_binary::().value(i)), + Kind::Bytes => zval_str(array.as_binary::().value(i)), Kind::List(element) => { let list = array.as_list::(); let offsets = list.value_offsets(); @@ -133,13 +133,13 @@ pub fn value_at(array: &dyn Array, kind: &Kind, node: &ValueNode, i: usize) -> R (ValueNode::Date, _) => date_from_days(long(array, kind, i)), (ValueNode::Time, _) => interval_from_micros(long(array, kind, i)), (ValueNode::Uuid, _) => uuid_from_bytes(array.as_fixed_size_binary().value(i)), - (ValueNode::Json, _) => json_from_bytes(array.as_binary::().value(i)), - (ValueNode::Enum(class), _) => ctx::enum_case(class, array.as_binary::().value(i)), - (ValueNode::TimeZone, _) => ctx::timezone(array.as_binary::().value(i)), + (ValueNode::Json, _) => json_from_bytes(array.as_binary::().value(i)), + (ValueNode::Enum(class), _) => ctx::enum_case(class, array.as_binary::().value(i)), + (ValueNode::TimeZone, _) => ctx::timezone(array.as_binary::().value(i)), (ValueNode::Markup(physical), _) => call_method( physical, "fromPhysical", - &mut [zval_str(array.as_binary::().value(i))], + &mut [zval_str(array.as_binary::().value(i))], ), (ValueNode::List(element_node), Kind::List(element)) => { let list = array.as_list::(); @@ -240,14 +240,12 @@ pub fn append_physical(builder: &mut KindBuilder, kind: &Kind, physical: &Zval) .ok_or_else(|| wrong_physical(kind, physical))?; builder.append_fixed(bytes); } - Kind::Bytes => builder - .append_bytes( - physical - .zend_str() - .ok_or_else(|| wrong_physical(kind, physical))? - .as_bytes(), - ) - .map_err(overflow)?, + Kind::Bytes => builder.append_bytes( + physical + .zend_str() + .ok_or_else(|| wrong_physical(kind, physical))? + .as_bytes(), + ), Kind::List(element) => { let values = physical.array().ok_or_else(|| wrong_physical(kind, physical))?; diff --git a/src/extension/flow-php-ext/src/text/value.rs b/src/extension/flow-php-ext/src/text/value.rs index 45dfa83b6..0f80d4f4d 100644 --- a/src/extension/flow-php-ext/src/text/value.rs +++ b/src/extension/flow-php-ext/src/text/value.rs @@ -7,8 +7,8 @@ use std::collections::HashMap; use arrow_array::cast::AsArray; use arrow_array::types::{Date32Type, DurationMicrosecondType, Float64Type, Int64Type, TimestampMicrosecondType}; use arrow_array::{ - Array, BinaryArray, BooleanArray, Date32Array, DurationMicrosecondArray, FixedSizeBinaryArray, Float64Array, - Int64Array, ListArray, MapArray, TimestampMicrosecondArray, + Array, BooleanArray, Date32Array, DurationMicrosecondArray, FixedSizeBinaryArray, Float64Array, Int64Array, + LargeBinaryArray, ListArray, MapArray, TimestampMicrosecondArray, }; use arrow_buffer::NullBuffer; use ext_php_rs::exception::PhpException; @@ -45,7 +45,7 @@ const CELL: Flags = Flags { enum MapKeys<'a> { Int(&'a Int64Array), - Bytes(&'a BinaryArray), + Bytes(&'a LargeBinaryArray), } enum Values<'a> { @@ -54,7 +54,7 @@ enum Values<'a> { Duration(&'a DurationMicrosecondArray), Float(&'a Float64Array), Bool(&'a BooleanArray), - Bytes(&'a BinaryArray), + Bytes(&'a LargeBinaryArray), Uuid(&'a FixedSizeBinaryArray), Instant { array: &'a TimestampMicrosecondArray, @@ -128,7 +128,7 @@ impl<'a> Renderer<'a> { (ValueNode::Plain, Kind::Float64) => Values::Float(array.as_primitive::()), (ValueNode::Plain, Kind::Boolean) => Values::Bool(array.as_boolean()), (ValueNode::Plain | ValueNode::Enum(_) | ValueNode::TimeZone | ValueNode::Json, Kind::Bytes) => { - Values::Bytes(array.as_binary::()) + Values::Bytes(array.as_binary::()) } (ValueNode::List(element_node), Kind::List(element)) => { let list = array.as_list::(); @@ -149,7 +149,7 @@ impl<'a> Renderer<'a> { Values::Map { map, keys: match key.kind { - Kind::Bytes => MapKeys::Bytes(map.keys().as_binary::()), + Kind::Bytes => MapKeys::Bytes(map.keys().as_binary::()), Kind::Int64 => MapKeys::Int(map.keys().as_primitive::()), _ => return None, }, @@ -401,7 +401,7 @@ fn entries(keys: &MapKeys<'_>, start: usize, end: usize) -> Vec<(usize, usize)> mod tests { use std::sync::Arc; - use arrow_array::builder::{BinaryBuilder, Int64Builder, MapBuilder}; + use arrow_array::builder::{Int64Builder, LargeBinaryBuilder, MapBuilder}; use arrow_array::types::Int64Type; use arrow_array::{Array, ArrayRef, Int64Array, ListArray, StructArray}; use arrow_schema::{DataType, Field as ArrowField}; @@ -433,7 +433,7 @@ mod tests { } fn string_map(rows: &[&[(&[u8], i64)]]) -> ArrayRef { - let mut builder = MapBuilder::new(None, BinaryBuilder::new(), Int64Builder::new()); + let mut builder = MapBuilder::new(None, LargeBinaryBuilder::new(), Int64Builder::new()); for row in rows { for (key, value) in *row { diff --git a/src/extension/flow-php-ext/tests/phpt/068_parquet_read_parity.phpt b/src/extension/flow-php-ext/tests/phpt/068_parquet_read_parity.phpt index 002a3aa27..201e440f1 100644 --- a/src/extension/flow-php-ext/tests/phpt/068_parquet_read_parity.phpt +++ b/src/extension/flow-php-ext/tests/phpt/068_parquet_read_parity.phpt @@ -122,5 +122,5 @@ EdgeCases/uint64_overflow.parquet 10000: both refuse EdgeCases/unsigned.parquet 100: identical EdgeCases/unsigned.parquet 10000: identical Flow\ETL\Exception\InvalidArgumentException: Parquet column "emptylist" (List(Null)) is read as List(Null), its schema type list stores List(Int64) -Flow\ETL\Exception\InvalidArgumentException: Parquet column "int64" (Int64) is read as Int64, its schema type string stores Binary +Flow\ETL\Exception\InvalidArgumentException: Parquet column "int64" (Int64) is read as Int64, its schema type string stores LargeBinary Flow\Parquet\Exception\InvalidArgumentException: Parquet file has no column "missing" diff --git a/src/extension/flow-php-ext/tests/phpt/090_parquet_schema_refused_at_open.phpt b/src/extension/flow-php-ext/tests/phpt/090_parquet_schema_refused_at_open.phpt index 78da4d24e..deffe049d 100644 --- a/src/extension/flow-php-ext/tests/phpt/090_parquet_schema_refused_at_open.phpt +++ b/src/extension/flow-php-ext/tests/phpt/090_parquet_schema_refused_at_open.phpt @@ -44,7 +44,7 @@ echo outcome(static fn() => new Flow\ETL\Adapter\Parquet\RustParquetOpenSource(n echo outcome(static fn() => new Flow\ETL\Adapter\Parquet\RustParquetOpenSink(new stdClass())), "\n"; ?> --EXPECT-- -Flow\ETL\Exception\InvalidArgumentException: Parquet column "id" (Int64) is read as Int64, its schema type string stores Binary -Flow\ETL\Exception\InvalidArgumentException: Parquet column "id" (Int64) is read as Int64, its schema type string stores Binary +Flow\ETL\Exception\InvalidArgumentException: Parquet column "id" (Int64) is read as Int64, its schema type string stores LargeBinary +Flow\ETL\Exception\InvalidArgumentException: Parquet column "id" (Int64) is read as Int64, its schema type string stores LargeBinary Flow\ETL\Exception\RuntimeException: flow_php expected a Flow\Parquet\Engine\RustParquetFileReader Flow\ETL\Exception\RuntimeException: flow_php expected a Flow\Parquet\Engine\RustParquetFileWriter diff --git a/web/landing/resources/api.json b/web/landing/resources/api.json index 430255d62..46140d0f6 100644 --- a/web/landing/resources/api.json +++ b/web/landing/resources/api.json @@ -1 +1 @@ -[{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":31,"slug":"and","name":"and","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"function","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"All","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":36,"slug":"andnot","name":"andNot","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"function","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"All","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":41,"slug":"append","name":"append","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"suffix","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Append","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":54,"slug":"arrayfilter","name":"arrayFilter","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"value","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ArrayFilter","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBGaWx0ZXJzIGFuIGFycmF5IGJ5IHJlbW92aW5nIGFsbCBlbGVtZW50cyB0aGF0IG1hdGNoZXMgcGFzc2VkIHZhbHVlLgogICAgICogQXBwbGljYWJsZSB0byBhbGwgZGF0YSBzdHJ1Y3R1cmVzIHRoYXQgY2FuIGJlIGNvbnZlcnRlZCB0byBhbiBhcnJheToKICAgICAqICAgIC0ganNvbgogICAgICogICAgLSBsaXN0CiAgICAgKiAgICAtIG1hcAogICAgICogICAgLSBzdHJ1Y3R1cmUuCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":59,"slug":"arrayget","name":"arrayGet","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"path","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ArrayGet","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":67,"slug":"arraygetcollection","name":"arrayGetCollection","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"keys","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ArrayGetCollection","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gU2NhbGFyRnVuY3Rpb258YXJyYXk8YXJyYXkta2V5LCBtaXhlZD4gJGtleXMKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":72,"slug":"arraygetcollectionfirst","name":"arrayGetCollectionFirst","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"keys","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"ArrayGetCollection","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":85,"slug":"arraykeep","name":"arrayKeep","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"value","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ArrayKeep","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBGaWx0ZXJzIGFuIGFycmF5IGJ5IGtlZXBpbmcgb25seSBlbGVtZW50cyB0aGF0IG1hdGNoZXMgcGFzc2VkIHZhbHVlLgogICAgICogQXBwbGljYWJsZSB0byBhbGwgZGF0YSBzdHJ1Y3R1cmVzIHRoYXQgY2FuIGJlIGNvbnZlcnRlZCB0byBhbiBhcnJheToKICAgICAqICAgLSBqc29uCiAgICAgKiAgIC0gbGlzdAogICAgICogICAtIG1hcAogICAgICogICAtIHN0cnVjdHVyZS4KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":98,"slug":"arraykeys","name":"arrayKeys","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"ArrayKeys","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBSZXR1cm5zIGFsbCBrZXlzIGZyb20gYW4gYXJyYXksIGlnbm9yaW5nIHRoZSB2YWx1ZXMuCiAgICAgKiBBcHBsaWNhYmxlIHRvIGFsbCBkYXRhIHN0cnVjdHVyZXMgdGhhdCBjYW4gYmUgY29udmVydGVkIHRvIGFuIGFycmF5OgogICAgICogICAtIGpzb24KICAgICAqICAgLSBsaXN0CiAgICAgKiAgIC0gbWFwCiAgICAgKiAgIC0gc3RydWN0dXJlLgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":106,"slug":"arraymerge","name":"arrayMerge","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"ref","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ArrayMerge","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gU2NhbGFyRnVuY3Rpb258YXJyYXk8YXJyYXkta2V5LCBtaXhlZD4gJHJlZgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":111,"slug":"arraymergecollection","name":"arrayMergeCollection","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"ArrayMergeCollection","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":116,"slug":"arraypathexists","name":"arrayPathExists","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"path","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ArrayPathExists","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":121,"slug":"arrayreverse","name":"arrayReverse","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"preserveKeys","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"ArrayReverse","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":126,"slug":"arraysort","name":"arraySort","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"sortFunction","type":[{"name":"Sort","namespace":"Flow\\ETL\\Function\\ArraySort","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"flags","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"null","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"recursive","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"}],"return_type":[{"name":"ArraySort","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":142,"slug":"arrayvalues","name":"arrayValues","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"ArrayValues","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBSZXR1cm5zIGFsbCB2YWx1ZXMgZnJvbSBhbiBhcnJheSwgaWdub3JpbmcgdGhlIGtleXMuCiAgICAgKiBBcHBsaWNhYmxlIHRvIGFsbCBkYXRhIHN0cnVjdHVyZXMgdGhhdCBjYW4gYmUgY29udmVydGVkIHRvIGFuIGFycmF5OgogICAgICogICAtIGpzb24KICAgICAqICAgLSBsaXN0CiAgICAgKiAgIC0gbWFwCiAgICAgKiAgIC0gc3RydWN0dXJlLgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":147,"slug":"ascii","name":"ascii","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"Ascii","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":157,"slug":"between","name":"between","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"lowerBoundRef","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null},{"name":"upperBoundRef","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null},{"name":"boundary","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"Boundary","namespace":"Flow\\ETL\\Function\\Between","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Function\\Between\\Boundary::..."}],"return_type":[{"name":"Between","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gbWl4ZWR8U2NhbGFyRnVuY3Rpb24gJGxvd2VyQm91bmRSZWYKICAgICAqIEBwYXJhbSBtaXhlZHxTY2FsYXJGdW5jdGlvbiAkdXBwZXJCb3VuZFJlZgogICAgICogQHBhcmFtIEJvdW5kYXJ5fFNjYWxhckZ1bmN0aW9uICRib3VuZGFyeQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":165,"slug":"binarylength","name":"binaryLength","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"BinaryLength","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":174,"slug":"call","name":"call","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"callable","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"returnType","type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"arguments","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"refAlias","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"0"}],"return_type":[{"name":"CallUserFunc","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gYXJyYXk8YXJyYXkta2V5LCBtaXhlZD4gJGFyZ3VtZW50cwogICAgICogQHBhcmFtIFR5cGU8bWl4ZWQ+ICRyZXR1cm5UeXBlCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":183,"slug":"capitalize","name":"capitalize","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"Capitalize","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":191,"slug":"cast","name":"cast","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"type","type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Cast","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gc3RyaW5nfFR5cGU8bWl4ZWQ+ICR0eXBlCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":196,"slug":"chunk","name":"chunk","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"size","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Chunk","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":201,"slug":"coalesce","name":"coalesce","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"params","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"Coalesce","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":206,"slug":"codepointlength","name":"codePointLength","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"CodePointLength","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":211,"slug":"collapsewhitespace","name":"collapseWhitespace","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"CollapseWhitespace","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":216,"slug":"concat","name":"concat","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"params","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"Concat","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":221,"slug":"concatwithseparator","name":"concatWithSeparator","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"separator","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"params","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"ConcatWithSeparator","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":228,"slug":"contains","name":"contains","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"needle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Contains","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":233,"slug":"dateformat","name":"dateFormat","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"format","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'Y-m-d'"}],"return_type":[{"name":"DateTimeFormat","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":238,"slug":"datetimeformat","name":"dateTimeFormat","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"format","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'Y-m-d H:i:s'"}],"return_type":[{"name":"DateTimeFormat","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":243,"slug":"divide","name":"divide","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"value","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"float","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"scale","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"null","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"rounding","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"Rounding","namespace":"Flow\\Calculator","is_nullable":false,"is_variadic":false},{"name":"null","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Divide","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":251,"slug":"domelementattributescount","name":"domElementAttributesCount","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"DOMElementAttributesCount","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":256,"slug":"domelementattributevalue","name":"domElementAttributeValue","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"attribute","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"DOMElementAttributeValue","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":261,"slug":"domelementnamespace","name":"domElementNamespace","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"attribute","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"null","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"DOMElementNamespaceValue","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":266,"slug":"domelementnextsibling","name":"domElementNextSibling","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"DOMElementNextSibling","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":271,"slug":"domelementparent","name":"domElementParent","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"DOMElementParent","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":276,"slug":"domelementprevioussibling","name":"domElementPreviousSibling","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"DOMElementPreviousSibling","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":281,"slug":"domelementvalue","name":"domElementValue","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"DOMElementValue","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":286,"slug":"endswith","name":"endsWith","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"needle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"EndsWith","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":291,"slug":"ensureend","name":"ensureEnd","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"suffix","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"EnsureEnd","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":296,"slug":"ensurestart","name":"ensureStart","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"prefix","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"EnsureStart","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":301,"slug":"enumname","name":"enumName","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"EnumName","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":306,"slug":"enumvalue","name":"enumValue","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"EnumValue","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":311,"slug":"equals","name":"equals","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"ref","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Equals","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":316,"slug":"exists","name":"exists","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"Exists","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":345,"slug":"expand","name":"expand","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"expand","type":[{"name":"ArrayExpand","namespace":"Flow\\ETL\\Function\\ArrayExpand","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Function\\ArrayExpand\\ArrayExpand::..."}],"return_type":[{"name":"ArrayExpand","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBFeHBhbmRzIGVhY2ggdmFsdWUgaW50byBlbnRyeSwgaWYgdGhlcmUgYXJlIG1vcmUgdGhhbiBvbmUgdmFsdWUsIG11bHRpcGxlIHJvd3Mgd2lsbCBiZSBjcmVhdGVkLgogICAgICogQXJyYXkga2V5cyBhcmUgaWdub3JlZCwgb25seSB2YWx1ZXMgYXJlIHVzZWQgdG8gY3JlYXRlIG5ldyByb3dzLgogICAgICogTmVzdGVkIGluIGFub3RoZXIgZnVuY3Rpb24gKHN0cnVjdHVyZSgpLCBjb25jYXQoKSwgLi4uKSBpdCBzdGlsbCBnaXZlcyBvbmUgcm93IHBlciBlbGVtZW50LiBTZXZlcmFsCiAgICAgKiBleHBhbmRzIGluIG9uZSBleHByZXNzaW9uIGFyZSB6aXBwZWQgdG8gdGhlIGxvbmdlc3QgbGlzdDsgYSBzaG9ydGVyIG9uZSBnaXZlcyBudWxsLCBzbyBpdHMgZWxlbWVudAogICAgICogdHlwZSBiZWNvbWVzIG51bGxhYmxlLiBJdCBpcyByZWZ1c2VkIGluc2lkZSBhbm90aGVyIGFycmF5X2V4cGFuZCgpIGFuZCBpbiBmaWx0ZXIoKSwgdW50aWwoKSwKICAgICAqIGR1cGxpY2F0ZVJvdygpLCBhZ2dyZWdhdGUoKSwgb3ZlcigpIGFuZCBvbkVhY2goKS4KICAgICAqCiAgICAgKiBCZWZvcmU6CiAgICAgKiAgICstLSstLS0tLS0tLS0tLS0tLS0tLS0tKwogICAgICogICB8aWR8ICAgICAgICAgICAgICBhcnJheXwKICAgICAqICAgKy0tKy0tLS0tLS0tLS0tLS0tLS0tLS0rCiAgICAgKiAgIHwgMXx7ImEiOjEsImIiOjIsImMiOjN9fAogICAgICogICArLS0rLS0tLS0tLS0tLS0tLS0tLS0tLSsKICAgICAqCiAgICAgKiBBZnRlcjoKICAgICAqICAgKy0tKy0tLS0tLS0tKwogICAgICogICB8aWR8ZXhwYW5kZWR8CiAgICAgKiAgICstLSstLS0tLS0tLSsKICAgICAqICAgfCAxfCAgICAgICAxfAogICAgICogICB8IDF8ICAgICAgIDJ8CiAgICAgKiAgIHwgMXwgICAgICAgM3wKICAgICAqICAgKy0tKy0tLS0tLS0tKwogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":350,"slug":"greaterthan","name":"greaterThan","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"ref","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"GreaterThan","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":355,"slug":"greaterthanequal","name":"greaterThanEqual","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"ref","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"GreaterThanEqual","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":360,"slug":"hash","name":"hash","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"algorithm","type":[{"name":"Algorithm","namespace":"Flow\\ETL\\Hash","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Hash\\NativePHPHash::..."}],"return_type":[{"name":"Hash","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":365,"slug":"htmlqueryselector","name":"htmlQuerySelector","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"path","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"HTMLQuerySelector","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":370,"slug":"htmlqueryselectorall","name":"htmlQuerySelectorAll","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"path","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"HTMLQuerySelectorAll","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":378,"slug":"indexof","name":"indexOf","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"needle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"ignoreCase","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"offset","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"0"}],"return_type":[{"name":"IndexOf","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBSZXR1cm5zIHRoZSBpbmRleCBvZiBnaXZlbiAkbmVlZGxlIGluIHN0cmluZy4KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":389,"slug":"indexoflast","name":"indexOfLast","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"needle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"ignoreCase","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"offset","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"0"}],"return_type":[{"name":"IndexOfLast","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBSZXR1cm5zIHRoZSBsYXN0IGluZGV4IG9mIGdpdmVuICRuZWVkbGUgaW4gc3RyaW5nLgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":397,"slug":"isempty","name":"isEmpty","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"IsEmpty","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":402,"slug":"iseven","name":"isEven","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"Equals","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":407,"slug":"isfalse","name":"isFalse","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"Same","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":415,"slug":"isin","name":"isIn","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"haystack","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"IsIn","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gU2NhbGFyRnVuY3Rpb258YXJyYXk8YXJyYXkta2V5LCBtaXhlZD4gJGhheXN0YWNrCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":420,"slug":"isnotnull","name":"isNotNull","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"IsNotNull","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":425,"slug":"isnotnumeric","name":"isNotNumeric","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"IsNotNumeric","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":430,"slug":"isnull","name":"isNull","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"IsNull","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":435,"slug":"isnumeric","name":"isNumeric","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"IsNumeric","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":440,"slug":"isodd","name":"isOdd","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"NotEquals","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":445,"slug":"istrue","name":"isTrue","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"Same","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":453,"slug":"istype","name":"isType","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"types","type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"IsType","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gc3RyaW5nfFR5cGU8bWl4ZWQ+ICR0eXBlcwogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":465,"slug":"isutf8","name":"isUtf8","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"IsUtf8","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBDaGVjayBzdHJpbmcgaXMgdXRmOCBhbmQgcmV0dXJucyB0cnVlIG9yIGZhbHNlLgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":470,"slug":"jsondecode","name":"jsonDecode","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"flags","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"4194304"}],"return_type":[{"name":"JsonDecode","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":475,"slug":"jsonencode","name":"jsonEncode","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"flags","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"4194304"}],"return_type":[{"name":"JsonEncode","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":480,"slug":"lessthan","name":"lessThan","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"ref","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"LessThan","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":485,"slug":"lessthanequal","name":"lessThanEqual","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"ref","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"LessThanEqual","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":490,"slug":"literal","name":"literal","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"value","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Literal","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":495,"slug":"lower","name":"lower","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"ToLower","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":500,"slug":"minus","name":"minus","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"ref","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"float","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"exact","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"Minus","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":505,"slug":"mod","name":"mod","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"value","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Mod","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":510,"slug":"modifydatetime","name":"modifyDateTime","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"modifier","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ModifyDateTime","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":515,"slug":"multiply","name":"multiply","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"value","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"float","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"exact","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"Multiply","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":520,"slug":"notequals","name":"notEquals","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"value","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"NotEquals","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":525,"slug":"notsame","name":"notSame","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"value","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"NotSame","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":530,"slug":"numberformat","name":"numberFormat","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"decimals","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"2"},{"name":"decimalSeparator","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'.'"},{"name":"thousandsSeparator","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"','"}],"return_type":[{"name":"NumberFormat","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":544,"slug":"oneach","name":"onEach","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"function","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"preserveKeys","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"}],"return_type":[{"name":"OnEach","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBFeGVjdXRlIGEgc2NhbGFyIGZ1bmN0aW9uIG9uIGVhY2ggZWxlbWVudCBvZiBhbiBhcnJheS9saXN0L21hcC9zdHJ1Y3R1cmUgZW50cnkuCiAgICAgKiBJbiBvcmRlciB0byB1c2UgdGhpcyBmdW5jdGlvbiwgeW91IG5lZWQgdG8gcHJvdmlkZSBhIHJlZmVyZW5jZSB0byB0aGUgImVsZW1lbnQiIHRoYXQgd2lsbCBiZSB1c2VkIGluIHRoZSBmdW5jdGlvbi4KICAgICAqCiAgICAgKiBFeGFtcGxlOiAkZGYtPndpdGhFbnRyeSgnYXJyYXknLCByZWYoJ2FycmF5JyktPm9uRWFjaChyZWYoJ2VsZW1lbnQnKS0+Y2FzdCh0eXBlX3N0cmluZygpKSkpCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":549,"slug":"or","name":"or","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"function","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Any","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":554,"slug":"ornot","name":"orNot","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"function","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Any","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":559,"slug":"plus","name":"plus","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"ref","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"float","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"exact","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"Plus","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":564,"slug":"power","name":"power","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"value","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"exact","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"Power","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":569,"slug":"prepend","name":"prepend","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"prefix","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Prepend","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":574,"slug":"regex","name":"regex","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"pattern","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"flags","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"0"},{"name":"offset","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"0"}],"return_type":[{"name":"Regex","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":579,"slug":"regexall","name":"regexAll","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"pattern","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"flags","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"0"},{"name":"offset","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"0"}],"return_type":[{"name":"RegexAll","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":584,"slug":"regexmatch","name":"regexMatch","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"pattern","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"flags","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"0"},{"name":"offset","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"0"}],"return_type":[{"name":"RegexMatch","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":592,"slug":"regexmatchall","name":"regexMatchAll","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"pattern","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"flags","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"0"},{"name":"offset","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"0"}],"return_type":[{"name":"RegexMatchAll","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":600,"slug":"regexreplace","name":"regexReplace","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"pattern","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"replacement","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"limit","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"null","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"RegexReplace","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":608,"slug":"repeat","name":"repeat","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"times","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Repeat","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":613,"slug":"reverse","name":"reverse","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"Reverse","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":618,"slug":"round","name":"round","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"precision","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"2"},{"name":"mode","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"1"}],"return_type":[{"name":"Round","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":623,"slug":"same","name":"same","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"value","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Same","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":628,"slug":"sanitize","name":"sanitize","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"placeholder","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'*'"},{"name":"skipCharacters","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"null","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Sanitize","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":635,"slug":"size","name":"size","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"Size","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":643,"slug":"slug","name":"slug","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"separator","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'-'"},{"name":"locale","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"null","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"symbolsMap","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"null","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Slug","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gU2NhbGFyRnVuY3Rpb258bnVsbHxhcnJheTxhcnJheS1rZXksIG1peGVkPiAkc3ltYm9sc01hcAogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":651,"slug":"split","name":"split","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"separator","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"limit","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"9223372036854775807"}],"return_type":[{"name":"Split","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":656,"slug":"sprintf","name":"sprintf","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"params","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"float","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"null","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":true,"default_value":null}],"return_type":[{"name":"Sprintf","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":661,"slug":"startswith","name":"startsWith","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"needle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"StartsWith","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":669,"slug":"stringafter","name":"stringAfter","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"needle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"includeNeedle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"StringAfter","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBSZXR1cm5zIHRoZSBjb250ZW50cyBmb3VuZCBhZnRlciB0aGUgZmlyc3Qgb2NjdXJyZW5jZSBvZiB0aGUgZ2l2ZW4gc3RyaW5nLgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":677,"slug":"stringafterlast","name":"stringAfterLast","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"needle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"includeNeedle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"StringAfterLast","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBSZXR1cm5zIHRoZSBjb250ZW50cyBmb3VuZCBhZnRlciB0aGUgbGFzdCBvY2N1cnJlbmNlIG9mIHRoZSBnaXZlbiBzdHJpbmcuCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":687,"slug":"stringbefore","name":"stringBefore","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"needle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"includeNeedle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"StringBefore","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBSZXR1cm5zIHRoZSBjb250ZW50cyBmb3VuZCBiZWZvcmUgdGhlIGZpcnN0IG9jY3VycmVuY2Ugb2YgdGhlIGdpdmVuIHN0cmluZy4KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":697,"slug":"stringbeforelast","name":"stringBeforeLast","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"needle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"includeNeedle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"StringBeforeLast","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBSZXR1cm5zIHRoZSBjb250ZW50cyBmb3VuZCBiZWZvcmUgdGhlIGxhc3Qgb2NjdXJyZW5jZSBvZiB0aGUgZ2l2ZW4gc3RyaW5nLgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":707,"slug":"stringcontainsany","name":"stringContainsAny","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"needles","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"StringContainsAny","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gYXJyYXk8c3RyaW5nPnxTY2FsYXJGdW5jdGlvbiAkbmVlZGxlcwogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":712,"slug":"stringequalsto","name":"stringEqualsTo","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"string","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"StringEqualsTo","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":720,"slug":"stringfold","name":"stringFold","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"StringFold","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBSZXR1cm5zIGEgc3RyaW5nIHRoYXQgeW91IGNhbiB1c2UgaW4gY2FzZS1pbnNlbnNpdGl2ZSBjb21wYXJpc29ucy4KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":725,"slug":"stringmatch","name":"stringMatch","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"pattern","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"StringMatch","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":730,"slug":"stringmatchall","name":"stringMatchAll","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"pattern","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"StringMatchAll","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":735,"slug":"stringnormalize","name":"stringNormalize","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"form","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"16"}],"return_type":[{"name":"StringNormalize","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":744,"slug":"stringstyle","name":"stringStyle","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"style","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"StringStyles","namespace":"Flow\\ETL\\String","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"StringStyle","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBDb3ZlcnQgc3RyaW5nIHRvIGEgc3R5bGUgZnJvbSBlbnVtIGxpc3QsIHBhc3NlZCBpbiBwYXJhbWV0ZXIuCiAgICAgKiBDYW4gYmUgc3RyaW5nICJ1cHBlciIgb3IgU3RyaW5nU3R5bGVzOjpVUFBFUiBmb3IgVXBwZXIgKGV4YW1wbGUpLgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":752,"slug":"stringtitle","name":"stringTitle","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"allWords","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"StringTitle","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBDaGFuZ2VzIGFsbCBncmFwaGVtZXMvY29kZSBwb2ludHMgdG8gInRpdGxlIGNhc2UiLgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":757,"slug":"stringwidth","name":"stringWidth","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"StringWidth","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":762,"slug":"strpad","name":"strPad","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"length","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"pad_string","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"' '"},{"name":"type","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"1"}],"return_type":[{"name":"StrPad","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":767,"slug":"strpadboth","name":"strPadBoth","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"length","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"pad_string","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"' '"}],"return_type":[{"name":"StrPad","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":772,"slug":"strpadleft","name":"strPadLeft","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"length","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"pad_string","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"' '"}],"return_type":[{"name":"StrPad","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":777,"slug":"strpadright","name":"strPadRight","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"length","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"pad_string","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"' '"}],"return_type":[{"name":"StrPad","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":786,"slug":"strreplace","name":"strReplace","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"search","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"replace","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"StrReplace","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gYXJyYXk8c3RyaW5nPnxTY2FsYXJGdW5jdGlvbnxzdHJpbmcgJHNlYXJjaAogICAgICogQHBhcmFtIGFycmF5PHN0cmluZz58U2NhbGFyRnVuY3Rpb258c3RyaW5nICRyZXBsYWNlCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":794,"slug":"todate","name":"toDate","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"format","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'Y-m-d\\\\TH:i:sP'"},{"name":"timeZone","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"DateTimeZone","namespace":"","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"DateTimeZone::..."}],"return_type":[{"name":"ToDate","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gU2NhbGFyRnVuY3Rpb258c3RyaW5nICRmb3JtYXQgLSBjdXJyZW50IGZvcm1hdCBvZiB0aGUgZGF0ZSB0aGF0IHdpbGwgYmUgdXNlZCB0byBjcmVhdGUgRGF0ZVRpbWVJbW11dGFibGUgaW5zdGFuY2UKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":805,"slug":"todatetime","name":"toDateTime","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"format","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'Y-m-d H:i:s'"},{"name":"timeZone","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"DateTimeZone","namespace":"","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"DateTimeZone::..."}],"return_type":[{"name":"ToDateTime","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gU2NhbGFyRnVuY3Rpb258c3RyaW5nICRmb3JtYXQgLSBjdXJyZW50IGZvcm1hdCBvZiB0aGUgZGF0ZSB0aGF0IHdpbGwgYmUgdXNlZCB0byBjcmVhdGUgRGF0ZVRpbWVJbW11dGFibGUgaW5zdGFuY2UKICAgICAqIEBwYXJhbSBcRGF0ZVRpbWVab25lfFNjYWxhckZ1bmN0aW9uICR0aW1lWm9uZQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":812,"slug":"trim","name":"trim","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"type","type":[{"name":"Type","namespace":"Flow\\ETL\\Function\\Trim","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Function\\Trim\\Type::..."},{"name":"characters","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"' \\t\\n\\r\\0\u000b'"}],"return_type":[{"name":"Trim","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":817,"slug":"truncate","name":"truncate","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"length","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"ellipsis","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'...'"}],"return_type":[{"name":"Truncate","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":822,"slug":"unicodelength","name":"unicodeLength","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"UnicodeLength","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":846,"slug":"unpack","name":"unpack","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"schema","type":[{"name":"Schema","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ArrayUnpack","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBVbnBhY2tzIGVhY2ggZWxlbWVudCBvZiBhbiBhcnJheSBpbnRvIGEgbmV3IGVudHJ5LCB1c2luZyB0aGUgYXJyYXkga2V5IGFzIHRoZSBlbnRyeSBuYW1lLgogICAgICoKICAgICAqIEJlZm9yZToKICAgICAqICAgKy0tKy0tLS0tLS0tLS0tLS0tLS0tLS0rCiAgICAgKiAgIHxpZHwgICAgICAgICAgICAgIGFycmF5fAogICAgICogICArLS0rLS0tLS0tLS0tLS0tLS0tLS0tLSsKICAgICAqICAgfCAxfHsiYSI6MSwiYiI6MiwiYyI6M318CiAgICAgKiAgIHwgMnx7ImQiOjQsImUiOjUsImYiOjZ9fAogICAgICogICArLS0rLS0tLS0tLS0tLS0tLS0tLS0tLSsKICAgICAqCiAgICAgKiBBZnRlcjoKICAgICAqICAgKy0tKy0tLS0tKy0tLS0tKy0tLS0tKy0tLS0tKy0tLS0tKwogICAgICogICB8aWR8YXJyLmJ8YXJyLmN8YXJyLmR8YXJyLmV8YXJyLmZ8CiAgICAgKiAgICstLSstLS0tLSstLS0tLSstLS0tLSstLS0tLSstLS0tLSsKICAgICAqICAgfCAxfCAgICAyfCAgICAzfCAgICAgfCAgICAgfCAgICAgfAogICAgICogICB8IDJ8ICAgICB8ICAgICB8ICAgIDR8ICAgIDV8ICAgIDZ8CiAgICAgKiAgICstLSstLS0tLSstLS0tLSstLS0tLSstLS0tLSstLS0tLSsKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":851,"slug":"upper","name":"upper","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"ToUpper","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":856,"slug":"wordwrap","name":"wordwrap","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"width","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"break","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'\\n'"},{"name":"cut","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"Wordwrap","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":864,"slug":"xpath","name":"xpath","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"string","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"XPath","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ResolvesFromChildren.php","start_line_in_file":12,"slug":"resolved","name":"resolved","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ResolvesFromChildren.php","start_line_in_file":23,"slug":"deterministic","name":"deterministic","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Flow.php","start_line_in_file":23,"slug":"setup","name":"setUp","class":"Flow\\ETL\\Flow","class_slug":"flow","parameters":[{"name":"config","type":[{"name":"ConfigBuilder","namespace":"Flow\\ETL\\Config","is_nullable":false,"is_variadic":false},{"name":"Config","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Flow.php","start_line_in_file":28,"slug":"extract","name":"extract","class":"Flow\\ETL\\Flow","class_slug":"flow","parameters":[{"name":"extractor","type":[{"name":"Extractor","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"DataFrame","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Flow.php","start_line_in_file":33,"slug":"from","name":"from","class":"Flow\\ETL\\Flow","class_slug":"flow","parameters":[{"name":"extractor","type":[{"name":"Extractor","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"DataFrame","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Flow.php","start_line_in_file":38,"slug":"process","name":"process","class":"Flow\\ETL\\Flow","class_slug":"flow","parameters":[{"name":"rows","type":[{"name":"Rows","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"DataFrame","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Flow.php","start_line_in_file":46,"slug":"read","name":"read","class":"Flow\\ETL\\Flow","class_slug":"flow","parameters":[{"name":"extractor","type":[{"name":"Extractor","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"DataFrame","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBBbGlhcyBmb3IgRmxvdzo6ZXh0cmFjdCBmdW5jdGlvbi4KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":74,"slug":"aggregate","name":"aggregate","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"aggregations","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"algorithm","type":[{"name":"GroupByAlgorithmBuilder","namespace":"Flow\\ETL\\Config\\Grouping","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEBwYXJhbSBBZ2dyZWdhdGlvbnMgJGFnZ3JlZ2F0aW9ucwogICAgICogQHBhcmFtIG51bGx8R3JvdXBCeUFsZ29yaXRobUJ1aWxkZXIgJGFsZ29yaXRobSBudWxsIGRlZmVycyB0byBjb25maWd1cmF0aW9uOyBhIGJ1aWxkZXIgcGlucyB0aGUKICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGdvcml0aG0gZm9yIHRoaXMgb3BlcmF0aW9uIGFuZCBza2lwcyBhbnkgYXV0b21hdGljIGNob2ljZQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":98,"slug":"batchby","name":"batchBy","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"column","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"minSize","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBNZXJnZS9TcGxpdCBSb3dzIHlpZWxkZWQgYnkgRXh0cmFjdG9yIGludG8gYmF0Y2hlcyBidXQga2VlcCB0aG9zZSB3aXRoIGNvbW1vbiB2YWx1ZSBpbiBnaXZlbiBjb2x1bW4gdG9nZXRoZXIuCiAgICAgKiBUaGlzIHdvcmtzIHByb3Blcmx5IG9ubHkgb24gc29ydGVkIGRhdGFzZXRzLgogICAgICoKICAgICAqIFdoZW4gbWluU2l6ZSBpcyBub3QgcHJvdmlkZWQsIGJhdGNoZXMgd2lsbCBiZSBjcmVhdGVkIG9ubHkgd2hlbiB0aGVyZSBpcyBhIGNoYW5nZSBpbiB2YWx1ZSBvZiB0aGUgY29sdW1uLgogICAgICogV2hlbiBtaW5TaXplIGlzIHByb3ZpZGVkLCBiYXRjaGVzIHdpbGwgYmUgY3JlYXRlZCBvbmx5IHdoZW4gdGhlcmUgaXMgYSBjaGFuZ2UgaW4gdmFsdWUgb2YgdGhlIGNvbHVtbiBvcgogICAgICogd2hlbiB0aGVyZSBhcmUgYXQgbGVhc3QgbWluU2l6ZSByb3dzIGluIHRoZSBiYXRjaC4KICAgICAqCiAgICAgKiBAcGFyYW0gUmVmZXJlbmNlfHN0cmluZyAkY29sdW1uIC0gY29sdW1uIHRvIGdyb3VwIGJ5IChhbGwgcm93cyB3aXRoIHNhbWUgdmFsdWUgc3RheSB0b2dldGhlcikKICAgICAqIEBwYXJhbSBudWxsfGludDwxLCBtYXg+ICRtaW5TaXplIC0gb3B0aW9uYWwgbWluaW11bSByb3dzIHBlciBiYXRjaCBmb3IgZWZmaWNpZW5jeQogICAgICoKICAgICAqIEBsYXp5CiAgICAgKgogICAgICogQHRocm93cyBJbnZhbGlkQXJndW1lbnRFeGNlcHRpb24KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":118,"slug":"batchsize","name":"batchSize","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"size","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBNZXJnZS9TcGxpdCBSb3dzIHlpZWxkZWQgYnkgRXh0cmFjdG9yIGludG8gYmF0Y2hlcyBvZiBnaXZlbiBzaXplLgogICAgICogRm9yIGV4YW1wbGUsIHdoZW4gRXh0cmFjdG9yIGlzIHlpZWxkaW5nIG9uZSByb3cgYXQgdGltZSwgdGhpcyBtZXRob2Qgd2lsbCBtZXJnZSB0aGVtIGludG8gYmF0Y2hlcyBvZiBnaXZlbiBzaXplCiAgICAgKiBiZWZvcmUgcGFzc2luZyB0aGVtIHRvIHRoZSBuZXh0IHBpcGVsaW5lIGVsZW1lbnQuCiAgICAgKiBTaW1pbGFybHkgd2hlbiBFeHRyYWN0b3IgaXMgeWllbGRpbmcgYmF0Y2hlcyBvZiByb3dzLCB0aGlzIG1ldGhvZCB3aWxsIHNwbGl0IHRoZW0gaW50byBzbWFsbGVyIGJhdGNoZXMgb2YgZ2l2ZW4KICAgICAqIHNpemUuCiAgICAgKgogICAgICogSW4gb3JkZXIgdG8gbWVyZ2UgYWxsIFJvd3MgaW50byBhIHNpbmdsZSBiYXRjaCB1c2UgRGF0YUZyYW1lOjpjb2xsZWN0KCkgbWV0aG9kIG9yIHNldCBzaXplIHRvIC0xIG9yIDAuCiAgICAgKgogICAgICogQHBhcmFtIGludDwtMSwgbWF4PiAkc2l6ZQogICAgICoKICAgICAqIEBsYXp5CiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":150,"slug":"cache","name":"cache","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"id","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"cacheBatchSize","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"cache","type":[{"name":"Cache","namespace":"Flow\\ETL","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBTdGFydCBwcm9jZXNzaW5nIHJvd3MgdXAgdG8gdGhpcyBtb21lbnQgYW5kIHB1dCBlYWNoIGluc3RhbmNlIG9mIFJvd3MKICAgICAqIGludG8gcHJldmlvdXNseSBkZWZpbmVkIGNhY2hlLgogICAgICogQ2FjaGUgdHlwZSBjYW4gYmUgc2V0IHRocm91Z2ggQ29uZmlnQnVpbGRlci4KICAgICAqIEJ5IGRlZmF1bHQgZXZlcnl0aGluZyBpcyBjYWNoZWQgaW4gc3lzdGVtIHRtcCBkaXIuCiAgICAgKgogICAgICogSW1wb3J0YW50OiBjYWNoZSBiYXRjaCBzaXplIG1pZ2h0IHNpZ25pZmljYW50bHkgaW1wcm92ZSBwZXJmb3JtYW5jZSB3aGVuIHByb2Nlc3NpbmcgbGFyZ2UgYW1vdW50IG9mIHJvd3MuCiAgICAgKiBMYXJnZXIgYmF0Y2ggc2l6ZSB3aWxsIGluY3JlYXNlIG1lbW9yeSBjb25zdW1wdGlvbiBidXQgd2lsbCByZWR1Y2UgbnVtYmVyIG9mIElPIG9wZXJhdGlvbnMuCiAgICAgKiBXaGVuIG5vdCBzZXQsIHRoZSBiYXRjaCBzaXplIGlzIHRha2VuIGZyb20gdGhlIGxhc3QgRGF0YUZyYW1lOjpiYXRjaFNpemUoKSBjYWxsLgogICAgICoKICAgICAqIEBsYXp5CiAgICAgKgogICAgICogQHBhcmFtIG51bGx8c3RyaW5nICRpZAogICAgICogQHBhcmFtIG51bGx8Q2FjaGUgJGNhY2hlIHJlYWRzIG9mIHRoaXMgY2FjaGUgbXVzdCBwYXNzIHRoZSBzYW1lIGluc3RhbmNlIHRvIGZyb21fY2FjaGUoKQogICAgICoKICAgICAqIEB0aHJvd3MgSW52YWxpZEFyZ3VtZW50RXhjZXB0aW9uCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":167,"slug":"collect","name":"collect","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBCZWZvcmUgdHJhbnNmb3JtaW5nIHJvd3MsIGNvbGxlY3QgdGhlbSBhbmQgbWVyZ2UgaW50byBzaW5nbGUgUm93cyBpbnN0YW5jZS4KICAgICAqIFRoaXMgbWlnaHQgbGVhZCB0byBtZW1vcnkgaXNzdWVzIHdoZW4gcHJvY2Vzc2luZyBsYXJnZSBhbW91bnQgb2Ygcm93cywgdXNlIHdpdGggY2F1dGlvbi4KICAgICAqCiAgICAgKiBAbGF6eQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":186,"slug":"collectrefs","name":"collectRefs","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"references","type":[{"name":"References","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBUaGlzIG1ldGhvZCBhbGxvd3MgdG8gY29sbGVjdCByZWZlcmVuY2VzIHRvIGFsbCBlbnRyaWVzIHVzZWQgaW4gdGhpcyBwaXBlbGluZS4KICAgICAqCiAgICAgKiBgYGBwaHAKICAgICAqIChuZXcgRmxvdygpKQogICAgICogICAtPnJlYWQoRnJvbTo6Y2hhaW4oKSkKICAgICAqICAgLT5jb2xsZWN0UmVmcygkcmVmcyA9IHJlZnMoKSkKICAgICAqICAgLT5ydW4oKTsKICAgICAqIGBgYAogICAgICoKICAgICAqIEBsYXp5CiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":193,"slug":"constrain","name":"constrain","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"constraint","type":[{"name":"Constraint","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"constraints","type":[{"name":"Constraint","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":204,"slug":"count","name":"count","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[],"return_type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAdHJpZ2dlcgogICAgICogUmV0dXJuIHRvdGFsIGNvdW50IG9mIHJvd3MgcHJvY2Vzc2VkIGJ5IHRoaXMgcGlwZWxpbmUuCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":224,"slug":"crossjoin","name":"crossJoin","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"dataFrame","type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"prefix","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"''"}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":241,"slug":"display","name":"display","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"limit","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"20"},{"name":"truncate","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"20"},{"name":"formatter","type":[{"name":"Formatter","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Formatter\\AsciiTableFormatter::..."}],"return_type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gaW50ICRsaW1pdCBtYXhpbXVtIG51bWJlcnMgb2Ygcm93cyB0byBkaXNwbGF5CiAgICAgKiBAcGFyYW0gYm9vbHxpbnQgJHRydW5jYXRlIGZhbHNlIG9yIGlmIHNldCB0byAwIGNvbHVtbnMgYXJlIG5vdCB0cnVuY2F0ZWQsIG90aGVyd2lzZSBkZWZhdWx0IHRydW5jYXRlIHRvIDIwCiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoYXJhY3RlcnMKICAgICAqIEBwYXJhbSBGb3JtYXR0ZXIgJGZvcm1hdHRlcgogICAgICoKICAgICAqIEB0cmlnZ2VyCiAgICAgKgogICAgICogQHRocm93cyBJbnZhbGlkQXJndW1lbnRFeGNlcHRpb24KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":268,"slug":"drop","name":"drop","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"entries","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBEcm9wIGdpdmVuIGVudHJpZXMuCiAgICAgKgogICAgICogQGxhenkKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":282,"slug":"dropduplicates","name":"dropDuplicates","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"entries","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gUmVmZXJlbmNlfHN0cmluZyAuLi4kZW50cmllcwogICAgICoKICAgICAqIEBsYXp5CiAgICAgKgogICAgICogQHJldHVybiAkdGhpcwogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":289,"slug":"duplicaterow","name":"duplicateRow","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"condition","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null},{"name":"entries","type":[{"name":"WithEntry","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":308,"slug":"fetch","name":"fetch","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"limit","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Rows","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBCZSBhd2FyZSB0aGF0IGZldGNoIGlzIG5vdCBtZW1vcnkgc2FmZSBhbmQgd2lsbCBsb2FkIGFsbCByb3dzIGludG8gbWVtb3J5LgogICAgICogSWYgeW91IHdhbnQgdG8gc2FmZWx5IGl0ZXJhdGUgb3ZlciBSb3dzIHVzZSBvZSBvZiB0aGUgZm9sbG93aW5nIG1ldGhvZHM6LgogICAgICoKICAgICAqIERhdGFGcmFtZTo6Z2V0KCkgOiBcR2VuZXJhdG9yCiAgICAgKiBEYXRhRnJhbWU6OmdldEFzQXJyYXkoKSA6IFxHZW5lcmF0b3IKICAgICAqIERhdGFGcmFtZTo6Z2V0RWFjaEFzQXJyYXkoKSA6IFxHZW5lcmF0b3IKICAgICAqCiAgICAgKiBAdHJpZ2dlcgogICAgICoKICAgICAqIEB0aHJvd3MgSW52YWxpZEFyZ3VtZW50RXhjZXB0aW9uCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":325,"slug":"filter","name":"filter","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"function","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":337,"slug":"filters","name":"filters","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"functions","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEBwYXJhbSBhcnJheTxTY2FsYXJGdW5jdGlvbj4gJGZ1bmN0aW9ucwogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":351,"slug":"foreach","name":"forEach","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"callback","type":[{"name":"callable","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"void","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAdHJpZ2dlcgogICAgICoKICAgICAqIEBwYXJhbSBudWxsfGNhbGxhYmxlKFJvd3MgJHJvd3MsIEZsb3dDb250ZXh0ICRjb250ZXh0KSA6IHZvaWQgJGNhbGxiYWNrCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":372,"slug":"get","name":"get","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[],"return_type":[{"name":"Generator","namespace":"","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBZaWVsZHMgZWFjaCByb3cgYXMgYW4gaW5zdGFuY2Ugb2YgUm93cy4KICAgICAqCiAgICAgKiBAdHJpZ2dlcgogICAgICoKICAgICAqIEByZXR1cm4gXEdlbmVyYXRvcjxSb3dzPgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":391,"slug":"getasarray","name":"getAsArray","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[],"return_type":[{"name":"Generator","namespace":"","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBZaWVsZHMgZWFjaCByb3cgYXMgYW4gYXJyYXkuCiAgICAgKgogICAgICogQHRyaWdnZXIKICAgICAqCiAgICAgKiBAcmV0dXJuIFxHZW5lcmF0b3I8YXJyYXk8YXJyYXk8bWl4ZWQ+Pj4KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":410,"slug":"geteachasarray","name":"getEachAsArray","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[],"return_type":[{"name":"Generator","namespace":"","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBZaWVsZCBlYWNoIHJvdyBhcyBhbiBhcnJheS4KICAgICAqCiAgICAgKiBAdHJpZ2dlcgogICAgICoKICAgICAqIEByZXR1cm4gXEdlbmVyYXRvcjxhcnJheTxtaXhlZD4+CiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":431,"slug":"groupby","name":"groupBy","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"entries","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"algorithm","type":[{"name":"GroupByAlgorithmBuilder","namespace":"Flow\\ETL\\Config\\Grouping","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"GroupedDataFrame","namespace":"Flow\\ETL\\DataFrame","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEBwYXJhbSBHcm91cEJ5UmVmZXJlbmNlc3xSZWZlcmVuY2V8c3RyaW5nICRlbnRyaWVzIGEgc2luZ2xlIGNvbHVtbiBpcyBncm91cGVkIGJ5IG9uIGl0cyBvd24KICAgICAqIEBwYXJhbSBudWxsfEdyb3VwQnlBbGdvcml0aG1CdWlsZGVyICRhbGdvcml0aG0gbnVsbCBkZWZlcnMgdG8gY29uZmlndXJhdGlvbjsgYSBidWlsZGVyIHBpbnMgdGhlCiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxnb3JpdGhtIGZvciB0aGlzIG9wZXJhdGlvbiBhbmQgc2tpcHMgYW55IGF1dG9tYXRpYyBjaG9pY2UKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":450,"slug":"join","name":"join","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"dataFrame","type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"on","type":[{"name":"Expression","namespace":"Flow\\ETL\\Join","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"type","type":[{"name":"Join","namespace":"Flow\\ETL\\Join","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Join\\Join::..."},{"name":"algorithm","type":[{"name":"JoinAlgorithmBuilder","namespace":"Flow\\ETL\\Config\\Join","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEBwYXJhbSBudWxsfEpvaW5BbGdvcml0aG1CdWlsZGVyICRhbGdvcml0aG0gbnVsbCBkZWZlcnMgdG8gY29uZmlndXJhdGlvbjsgYSBidWlsZGVyIHBpbnMgdGhlIGFsZ29yaXRobQogICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciB0aGlzIG9wZXJhdGlvbiBhbmQgc2tpcHMgYW55IGF1dG9tYXRpYyBjaG9pY2UKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":478,"slug":"joineach","name":"joinEach","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"factory","type":[{"name":"DataFrameFactory","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"on","type":[{"name":"Expression","namespace":"Flow\\ETL\\Join","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"type","type":[{"name":"Join","namespace":"Flow\\ETL\\Join","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Join\\Join::..."}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBKb2lucyBpbiBtZW1vcnkgcGVyIGJhdGNoOyBpdCBpcyBub3QgZ292ZXJuZWQgYnkgdGhlIGpvaW4gYWxnb3JpdGhtIGFuZCB0YWtlcyBubyBhbGdvcml0aG0gb3ZlcnJpZGUuCiAgICAgKgogICAgICogQGxhenkKICAgICAqCiAgICAgKiBAcGFyYW0gc3RyaW5nfEpvaW4gJHR5cGUKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":494,"slug":"limit","name":"limit","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"limit","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEB0aHJvd3MgSW52YWxpZEFyZ3VtZW50RXhjZXB0aW9uCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":508,"slug":"load","name":"load","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"sink","type":[{"name":"Loader","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"Sink","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":554,"slug":"match","name":"match","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"schema","type":[{"name":"Schema","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"validator","type":[{"name":"SchemaValidator","namespace":"Flow\\ETL","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEBwYXJhbSBudWxsfFNjaGVtYVZhbGlkYXRvciAkdmFsaWRhdG9yIC0gd2hlbiBudWxsLCBTdHJpY3RWYWxpZGF0b3IgZ2V0cyBpbml0aWFsaXplZAogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":575,"slug":"offset","name":"offset","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"offset","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBTa2lwIGdpdmVuIG51bWJlciBvZiByb3dzIGZyb20gdGhlIGJlZ2lubmluZyBvZiB0aGUgZGF0YXNldC4KICAgICAqIFdoZW4gJG9mZnNldCBpcyBudWxsLCBub3RoaW5nIGhhcHBlbnMgKG5vIHJvd3MgYXJlIHNraXBwZWQpLgogICAgICoKICAgICAqIFBlcmZvcm1hbmNlIE5vdGU6IERhdGFGcmFtZSBtdXN0IGl0ZXJhdGUgdGhyb3VnaCBhbmQgcHJvY2VzcyBhbGwgc2tpcHBlZCByb3dzCiAgICAgKiB0byByZWFjaCB0aGUgb2Zmc2V0IHBvc2l0aW9uLiBGb3IgbGFyZ2Ugb2Zmc2V0cywgdGhpcyBjYW4gaW1wYWN0IHBlcmZvcm1hbmNlCiAgICAgKiBhcyB0aGUgZGF0YSBzb3VyY2Ugc3RpbGwgbmVlZHMgdG8gYmUgcmVhZCBhbmQgcHJvY2Vzc2VkIHVwIHRvIHRoZSBvZmZzZXQgcG9pbnQuCiAgICAgKgogICAgICogQHBhcmFtID9pbnQ8MCwgbWF4PiAkb2Zmc2V0CiAgICAgKgogICAgICogQGxhenkKICAgICAqCiAgICAgKiBAdGhyb3dzIEludmFsaWRBcmd1bWVudEV4Y2VwdGlvbgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":589,"slug":"onerror","name":"onError","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"handler","type":[{"name":"ErrorHandler","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":601,"slug":"repartition","name":"repartition","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"entry","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"entries","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICogU2h1ZmZsZXMgdGhlIHN0cmVhbSBzbyBldmVyeSByb3cgc2hhcmluZyB0aGUgZ2l2ZW4gY29sdW1ucyBhcnJpdmVzIGluIG9uZSBiYXRjaC4gSXQgZG9lcyBub3QKICAgICAqIHdyaXRlIGRpcmVjdG9yaWVzIC0gdGhhdCBpcyBkZWNsYXJlZCBvbiB0aGUgbG9hZGVyLCBgdG9fY3N2KC4uLiktPnBhcnRpdGlvbkJ5KCdyZWdpb24nKWAuCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":613,"slug":"printrows","name":"printRows","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"limit","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"20"},{"name":"truncate","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"20"},{"name":"formatter","type":[{"name":"Formatter","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Formatter\\AsciiTableFormatter::..."}],"return_type":[{"name":"void","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAdHJpZ2dlcgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":633,"slug":"explain","name":"explain","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"trigger","type":[{"name":"Trigger","namespace":"Flow\\ETL\\Plan","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Plan\\Trigger::..."}],"return_type":[{"name":"Plan","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBUaGUgcGxhbiAkdHJpZ2dlciB3b3VsZCBydW4gb3ZlciB0aGlzIGZyYW1lLCBmcm96ZW46IGxhdGVyIHZlcmJzIG9uIHRoaXMgZnJhbWUgZG8gbm90IHJlYWNoIGl0LiBUaGUgZGVmYXVsdAogICAgICogYWRkcyBubyBjb25zdW1lciBvZiBpdHMgb3duIC0gaXQgZHJhd3MgdGhlIGZyYW1lIGFzIGJ1aWx0LCBpdHMgY2hhaW4gYW5kIGl0cyBzaW5rcy4gdG9TdHJpbmcoKSBwcmludHMgaXQgYXMgYQogICAgICogdHJlZS4gQW5zd2VycyBmcm9tIHRoZSBwbGFuIHdpdGhvdXQgcmVhZGluZyBhIHJvdy4KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":643,"slug":"printschema","name":"printSchema","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"formatter","type":[{"name":"SchemaFormatter","namespace":"Flow\\ETL\\Schema","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Row\\Formatter\\ASCIISchemaFormatter::..."}],"return_type":[{"name":"void","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEB0aHJvd3MgU2NoZW1hTm90RGVyaXZhYmxlRXhjZXB0aW9uCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":651,"slug":"rename","name":"rename","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"from","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"to","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":658,"slug":"renameeach","name":"renameEach","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"strategies","type":[{"name":"RenameEntryStrategy","namespace":"Flow\\ETL\\Transformer\\Rename","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":669,"slug":"rows","name":"rows","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"transformer","type":[{"name":"Transformer","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"Transformation","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICogQWxpYXMgZm9yIEVUTDo6dHJhbnNmb3JtIG1ldGhvZC4KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":686,"slug":"run","name":"run","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"analyze","type":[{"name":"Analyze","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"Report","namespace":"Flow\\ETL\\Dataset","is_nullable":true,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAdHJpZ2dlcgogICAgICoKICAgICAqIFdoZW4gYW5hbHl6aW5nIHBpcGVsaW5lIGV4ZWN1dGlvbiB3ZSBjYW4gY2hvc2UgdG8gY29sbGVjdCB2YXJpb3VzIG1ldHJpY3MgdGhyb3VnaCBhbmFseXplKCktPndpdGgqKCkgbWV0aG9kCiAgICAgKgogICAgICogLSBjb2x1bW4gc3RhdGlzdGljcyAtIGFuYWx5emUoKS0+d2l0aENvbHVtblN0YXRpc3RpY3MoKQogICAgICogLSBzY2hlbWEgLSBhbmFseXplKCktPndpdGhTY2hlbWEoKQogICAgICoKICAgICAqIEBwYXJhbSBBbmFseXplfGJvb2wgJGFuYWx5emUgLSB3aGVuIHNldCBydW4gd2lsbCByZXR1cm4gUmVwb3J0CiAgICAgKgogICAgICogQHJldHVybiAoJGFuYWx5emUgaXMgQW5hbHl6ZXx0cnVlID8gUmVwb3J0IDogbnVsbCkKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":714,"slug":"schema","name":"schema","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[],"return_type":[{"name":"Schema","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEB0aHJvd3MgU2NoZW1hTm90RGVyaXZhYmxlRXhjZXB0aW9uCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":727,"slug":"select","name":"select","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"entries","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICogS2VlcCBvbmx5IGdpdmVuIGVudHJpZXMuCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":741,"slug":"sortby","name":"sortBy","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"entries","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"algorithm","type":[{"name":"SortAlgorithmBuilder","namespace":"Flow\\ETL\\Config\\Sort","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEBwYXJhbSBSZWZlcmVuY2V8U29ydFJlZmVyZW5jZXN8c3RyaW5nICRlbnRyaWVzIGEgc2luZ2xlIGNvbHVtbiBpcyBzb3J0ZWQgYnkgb24gaXRzIG93bgogICAgICogQHBhcmFtIG51bGx8U29ydEFsZ29yaXRobUJ1aWxkZXIgJGFsZ29yaXRobSBudWxsIGRlZmVycyB0byBjb25maWd1cmF0aW9uOyBhIGJ1aWxkZXIgcGlucyB0aGUgYWxnb3JpdGhtCiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIHRoaXMgb3BlcmF0aW9uIGFuZCBza2lwcyBhbnkgYXV0b21hdGljIGNob2ljZQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":755,"slug":"transform","name":"transform","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"transformer","type":[{"name":"Transformer","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"Transformation","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"Transformations","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"WithEntry","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBBbGlhcyBmb3IgRGF0YUZyYW1lOjp3aXRoKCkuCiAgICAgKgogICAgICogQGxhenkKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":766,"slug":"until","name":"until","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"function","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBUaGUgZGlmZmVyZW5jZSBiZXR3ZWVuIGZpbHRlciBhbmQgdW50aWwgaXMgdGhhdCBmaWx0ZXIgd2lsbCBrZWVwIGZpbHRlcmluZyByb3dzIHVudGlsIGV4dHJhY3RvcnMgZmluaXNoIHlpZWxkaW5nCiAgICAgKiByb3dzLiBVbnRpbCB3aWxsIHNlbmQgYSBTVE9QIHNpZ25hbCB0byB0aGUgRXh0cmFjdG9yIHdoZW4gdGhlIGNvbmRpdGlvbiBpcyBub3QgbWV0LgogICAgICoKICAgICAqIEBsYXp5CiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":780,"slug":"void","name":"void","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICogVGhpcyBtZXRob2QgaXMgdXNlZnVsIG1vc3RseSBpbiBkZXZlbG9wbWVudCB3aGVuCiAgICAgKiB5b3Ugd2FudCB0byBwYXVzZSBwcm9jZXNzaW5nIGF0IGNlcnRhaW4gbW9tZW50IHdpdGhvdXQKICAgICAqIHJlbW92aW5nIGNvZGUuIEFsbCBvcGVyYXRpb25zIHdpbGwgZ2V0IHByb2Nlc3NlZCB1cCB0byB0aGlzIHBvaW50LAogICAgICogZnJvbSBoZXJlIG5vIHJvd3MgYXJlIHBhc3NlZCBmb3J3YXJkLgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":790,"slug":"with","name":"with","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"transformer","type":[{"name":"Transformer","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"Transformation","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"Transformations","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"WithEntry","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":818,"slug":"withentries","name":"withEntries","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"references","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEBwYXJhbSBhcnJheTxpbnQsIFdpdGhFbnRyeT58YXJyYXk8c3RyaW5nLCBTY2FsYXJGdW5jdGlvbnxXaW5kb3dGdW5jdGlvbnxXaXRoRW50cnk+ICRyZWZlcmVuY2VzCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":836,"slug":"withentry","name":"withEntry","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"entry","type":[{"name":"Definition","namespace":"Flow\\ETL\\Schema","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"reference","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"WindowFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gRGVmaW5pdGlvbjxtaXhlZD58c3RyaW5nICRlbnRyeQogICAgICoKICAgICAqIEBsYXp5CiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":849,"slug":"write","name":"write","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"sink","type":[{"name":"Loader","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"Sink","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICogQWxpYXMgZm9yIEVUTDo6bG9hZCBmdW5jdGlvbi4KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame\/GroupedDataFrame.php","start_line_in_file":21,"slug":"aggregate","name":"aggregate","class":"Flow\\ETL\\DataFrame\\GroupedDataFrame","class_slug":"groupeddataframe","parameters":[{"name":"aggregations","type":[{"name":"AggregatingFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"DataFrame","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame\/GroupedDataFrame.php","start_line_in_file":28,"slug":"pivot","name":"pivot","class":"Flow\\ETL\\DataFrame\\GroupedDataFrame","class_slug":"groupeddataframe","parameters":[{"name":"ref","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"values","type":[{"name":"PivotValues","namespace":"Flow\\ETL\\GroupBy","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null}] \ No newline at end of file +[{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":31,"slug":"and","name":"and","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"function","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"All","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":36,"slug":"andnot","name":"andNot","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"function","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"All","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":41,"slug":"append","name":"append","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"suffix","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Append","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":54,"slug":"arrayfilter","name":"arrayFilter","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"value","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ArrayFilter","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBGaWx0ZXJzIGFuIGFycmF5IGJ5IHJlbW92aW5nIGFsbCBlbGVtZW50cyB0aGF0IG1hdGNoZXMgcGFzc2VkIHZhbHVlLgogICAgICogQXBwbGljYWJsZSB0byBhbGwgZGF0YSBzdHJ1Y3R1cmVzIHRoYXQgY2FuIGJlIGNvbnZlcnRlZCB0byBhbiBhcnJheToKICAgICAqICAgIC0ganNvbgogICAgICogICAgLSBsaXN0CiAgICAgKiAgICAtIG1hcAogICAgICogICAgLSBzdHJ1Y3R1cmUuCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":59,"slug":"arrayget","name":"arrayGet","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"path","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ArrayGet","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":67,"slug":"arraygetcollection","name":"arrayGetCollection","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"keys","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ArrayGetCollection","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gU2NhbGFyRnVuY3Rpb258YXJyYXk8YXJyYXkta2V5LCBtaXhlZD4gJGtleXMKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":72,"slug":"arraygetcollectionfirst","name":"arrayGetCollectionFirst","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"keys","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"ArrayGetCollection","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":85,"slug":"arraykeep","name":"arrayKeep","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"value","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ArrayKeep","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBGaWx0ZXJzIGFuIGFycmF5IGJ5IGtlZXBpbmcgb25seSBlbGVtZW50cyB0aGF0IG1hdGNoZXMgcGFzc2VkIHZhbHVlLgogICAgICogQXBwbGljYWJsZSB0byBhbGwgZGF0YSBzdHJ1Y3R1cmVzIHRoYXQgY2FuIGJlIGNvbnZlcnRlZCB0byBhbiBhcnJheToKICAgICAqICAgLSBqc29uCiAgICAgKiAgIC0gbGlzdAogICAgICogICAtIG1hcAogICAgICogICAtIHN0cnVjdHVyZS4KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":98,"slug":"arraykeys","name":"arrayKeys","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"ArrayKeys","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBSZXR1cm5zIGFsbCBrZXlzIGZyb20gYW4gYXJyYXksIGlnbm9yaW5nIHRoZSB2YWx1ZXMuCiAgICAgKiBBcHBsaWNhYmxlIHRvIGFsbCBkYXRhIHN0cnVjdHVyZXMgdGhhdCBjYW4gYmUgY29udmVydGVkIHRvIGFuIGFycmF5OgogICAgICogICAtIGpzb24KICAgICAqICAgLSBsaXN0CiAgICAgKiAgIC0gbWFwCiAgICAgKiAgIC0gc3RydWN0dXJlLgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":106,"slug":"arraymerge","name":"arrayMerge","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"ref","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ArrayMerge","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gU2NhbGFyRnVuY3Rpb258YXJyYXk8YXJyYXkta2V5LCBtaXhlZD4gJHJlZgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":111,"slug":"arraymergecollection","name":"arrayMergeCollection","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"ArrayMergeCollection","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":116,"slug":"arraypathexists","name":"arrayPathExists","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"path","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ArrayPathExists","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":121,"slug":"arrayreverse","name":"arrayReverse","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"preserveKeys","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"ArrayReverse","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":126,"slug":"arraysort","name":"arraySort","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"sortFunction","type":[{"name":"Sort","namespace":"Flow\\ETL\\Function\\ArraySort","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"flags","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"null","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"recursive","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"}],"return_type":[{"name":"ArraySort","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":142,"slug":"arrayvalues","name":"arrayValues","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"ArrayValues","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBSZXR1cm5zIGFsbCB2YWx1ZXMgZnJvbSBhbiBhcnJheSwgaWdub3JpbmcgdGhlIGtleXMuCiAgICAgKiBBcHBsaWNhYmxlIHRvIGFsbCBkYXRhIHN0cnVjdHVyZXMgdGhhdCBjYW4gYmUgY29udmVydGVkIHRvIGFuIGFycmF5OgogICAgICogICAtIGpzb24KICAgICAqICAgLSBsaXN0CiAgICAgKiAgIC0gbWFwCiAgICAgKiAgIC0gc3RydWN0dXJlLgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":147,"slug":"ascii","name":"ascii","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"Ascii","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":157,"slug":"between","name":"between","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"lowerBoundRef","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null},{"name":"upperBoundRef","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null},{"name":"boundary","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"Boundary","namespace":"Flow\\ETL\\Function\\Between","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Function\\Between\\Boundary::..."}],"return_type":[{"name":"Between","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gbWl4ZWR8U2NhbGFyRnVuY3Rpb24gJGxvd2VyQm91bmRSZWYKICAgICAqIEBwYXJhbSBtaXhlZHxTY2FsYXJGdW5jdGlvbiAkdXBwZXJCb3VuZFJlZgogICAgICogQHBhcmFtIEJvdW5kYXJ5fFNjYWxhckZ1bmN0aW9uICRib3VuZGFyeQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":165,"slug":"binarylength","name":"binaryLength","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"BinaryLength","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":174,"slug":"call","name":"call","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"callable","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"returnType","type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"arguments","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"refAlias","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"0"}],"return_type":[{"name":"CallUserFunc","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gYXJyYXk8YXJyYXkta2V5LCBtaXhlZD4gJGFyZ3VtZW50cwogICAgICogQHBhcmFtIFR5cGU8bWl4ZWQ+ICRyZXR1cm5UeXBlCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":183,"slug":"capitalize","name":"capitalize","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"Capitalize","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":191,"slug":"cast","name":"cast","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"type","type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Cast","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gc3RyaW5nfFR5cGU8bWl4ZWQ+ICR0eXBlCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":196,"slug":"chunk","name":"chunk","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"size","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Chunk","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":201,"slug":"coalesce","name":"coalesce","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"params","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"Coalesce","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":206,"slug":"codepointlength","name":"codePointLength","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"CodePointLength","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":211,"slug":"collapsewhitespace","name":"collapseWhitespace","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"CollapseWhitespace","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":216,"slug":"concat","name":"concat","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"params","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"Concat","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":221,"slug":"concatwithseparator","name":"concatWithSeparator","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"separator","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"params","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"ConcatWithSeparator","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":228,"slug":"contains","name":"contains","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"needle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Contains","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":233,"slug":"dateformat","name":"dateFormat","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"format","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'Y-m-d'"}],"return_type":[{"name":"DateTimeFormat","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":238,"slug":"datetimeformat","name":"dateTimeFormat","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"format","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'Y-m-d H:i:s'"}],"return_type":[{"name":"DateTimeFormat","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":243,"slug":"divide","name":"divide","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"value","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"float","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"scale","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"null","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"rounding","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"Rounding","namespace":"Flow\\Calculator","is_nullable":false,"is_variadic":false},{"name":"null","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Divide","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":251,"slug":"domelementattributescount","name":"domElementAttributesCount","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"DOMElementAttributesCount","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":256,"slug":"domelementattributevalue","name":"domElementAttributeValue","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"attribute","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"DOMElementAttributeValue","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":261,"slug":"domelementnamespace","name":"domElementNamespace","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"attribute","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"null","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"DOMElementNamespaceValue","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":266,"slug":"domelementnextsibling","name":"domElementNextSibling","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"DOMElementNextSibling","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":271,"slug":"domelementparent","name":"domElementParent","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"DOMElementParent","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":276,"slug":"domelementprevioussibling","name":"domElementPreviousSibling","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"DOMElementPreviousSibling","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":281,"slug":"domelementvalue","name":"domElementValue","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"DOMElementValue","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":286,"slug":"endswith","name":"endsWith","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"needle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"EndsWith","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":291,"slug":"ensureend","name":"ensureEnd","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"suffix","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"EnsureEnd","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":296,"slug":"ensurestart","name":"ensureStart","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"prefix","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"EnsureStart","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":301,"slug":"enumname","name":"enumName","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"EnumName","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":306,"slug":"enumvalue","name":"enumValue","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"EnumValue","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":311,"slug":"equals","name":"equals","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"ref","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Equals","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":316,"slug":"exists","name":"exists","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"Exists","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":345,"slug":"expand","name":"expand","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"expand","type":[{"name":"ArrayExpand","namespace":"Flow\\ETL\\Function\\ArrayExpand","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Function\\ArrayExpand\\ArrayExpand::..."}],"return_type":[{"name":"ArrayExpand","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBFeHBhbmRzIGVhY2ggdmFsdWUgaW50byBlbnRyeSwgaWYgdGhlcmUgYXJlIG1vcmUgdGhhbiBvbmUgdmFsdWUsIG11bHRpcGxlIHJvd3Mgd2lsbCBiZSBjcmVhdGVkLgogICAgICogQXJyYXkga2V5cyBhcmUgaWdub3JlZCwgb25seSB2YWx1ZXMgYXJlIHVzZWQgdG8gY3JlYXRlIG5ldyByb3dzLgogICAgICogTmVzdGVkIGluIGFub3RoZXIgZnVuY3Rpb24gKHN0cnVjdHVyZSgpLCBjb25jYXQoKSwgLi4uKSBpdCBzdGlsbCBnaXZlcyBvbmUgcm93IHBlciBlbGVtZW50LiBTZXZlcmFsCiAgICAgKiBleHBhbmRzIGluIG9uZSBleHByZXNzaW9uIGFyZSB6aXBwZWQgdG8gdGhlIGxvbmdlc3QgbGlzdDsgYSBzaG9ydGVyIG9uZSBnaXZlcyBudWxsLCBzbyBpdHMgZWxlbWVudAogICAgICogdHlwZSBiZWNvbWVzIG51bGxhYmxlLiBJdCBpcyByZWZ1c2VkIGluc2lkZSBhbm90aGVyIGFycmF5X2V4cGFuZCgpIGFuZCBpbiBmaWx0ZXIoKSwgdW50aWwoKSwKICAgICAqIGR1cGxpY2F0ZVJvdygpLCBhZ2dyZWdhdGUoKSwgb3ZlcigpIGFuZCBvbkVhY2goKS4KICAgICAqCiAgICAgKiBCZWZvcmU6CiAgICAgKiAgICstLSstLS0tLS0tLS0tLS0tLS0tLS0tKwogICAgICogICB8aWR8ICAgICAgICAgICAgICBhcnJheXwKICAgICAqICAgKy0tKy0tLS0tLS0tLS0tLS0tLS0tLS0rCiAgICAgKiAgIHwgMXx7ImEiOjEsImIiOjIsImMiOjN9fAogICAgICogICArLS0rLS0tLS0tLS0tLS0tLS0tLS0tLSsKICAgICAqCiAgICAgKiBBZnRlcjoKICAgICAqICAgKy0tKy0tLS0tLS0tKwogICAgICogICB8aWR8ZXhwYW5kZWR8CiAgICAgKiAgICstLSstLS0tLS0tLSsKICAgICAqICAgfCAxfCAgICAgICAxfAogICAgICogICB8IDF8ICAgICAgIDJ8CiAgICAgKiAgIHwgMXwgICAgICAgM3wKICAgICAqICAgKy0tKy0tLS0tLS0tKwogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":350,"slug":"greaterthan","name":"greaterThan","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"ref","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"GreaterThan","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":355,"slug":"greaterthanequal","name":"greaterThanEqual","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"ref","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"GreaterThanEqual","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":360,"slug":"hash","name":"hash","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"algorithm","type":[{"name":"Algorithm","namespace":"Flow\\ETL\\Hash","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Hash\\NativePHPHash::..."}],"return_type":[{"name":"Hash","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":365,"slug":"htmlqueryselector","name":"htmlQuerySelector","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"path","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"HTMLQuerySelector","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":370,"slug":"htmlqueryselectorall","name":"htmlQuerySelectorAll","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"path","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"HTMLQuerySelectorAll","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":378,"slug":"indexof","name":"indexOf","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"needle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"ignoreCase","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"offset","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"0"}],"return_type":[{"name":"IndexOf","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBSZXR1cm5zIHRoZSBpbmRleCBvZiBnaXZlbiAkbmVlZGxlIGluIHN0cmluZy4KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":389,"slug":"indexoflast","name":"indexOfLast","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"needle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"ignoreCase","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"offset","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"0"}],"return_type":[{"name":"IndexOfLast","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBSZXR1cm5zIHRoZSBsYXN0IGluZGV4IG9mIGdpdmVuICRuZWVkbGUgaW4gc3RyaW5nLgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":397,"slug":"isempty","name":"isEmpty","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"IsEmpty","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":402,"slug":"iseven","name":"isEven","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"Equals","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":407,"slug":"isfalse","name":"isFalse","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"Same","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":415,"slug":"isin","name":"isIn","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"haystack","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"IsIn","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gU2NhbGFyRnVuY3Rpb258YXJyYXk8YXJyYXkta2V5LCBtaXhlZD4gJGhheXN0YWNrCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":420,"slug":"isnotnull","name":"isNotNull","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"IsNotNull","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":425,"slug":"isnotnumeric","name":"isNotNumeric","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"IsNotNumeric","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":430,"slug":"isnull","name":"isNull","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"IsNull","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":435,"slug":"isnumeric","name":"isNumeric","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"IsNumeric","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":440,"slug":"isodd","name":"isOdd","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"NotEquals","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":445,"slug":"istrue","name":"isTrue","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"Same","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":453,"slug":"istype","name":"isType","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"types","type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"IsType","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gc3RyaW5nfFR5cGU8bWl4ZWQ+ICR0eXBlcwogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":465,"slug":"isutf8","name":"isUtf8","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"IsUtf8","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBDaGVjayBzdHJpbmcgaXMgdXRmOCBhbmQgcmV0dXJucyB0cnVlIG9yIGZhbHNlLgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":470,"slug":"jsondecode","name":"jsonDecode","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"flags","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"4194304"}],"return_type":[{"name":"JsonDecode","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":475,"slug":"jsonencode","name":"jsonEncode","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"flags","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"4194304"}],"return_type":[{"name":"JsonEncode","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":480,"slug":"lessthan","name":"lessThan","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"ref","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"LessThan","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":485,"slug":"lessthanequal","name":"lessThanEqual","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"ref","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"LessThanEqual","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":490,"slug":"literal","name":"literal","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"value","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Literal","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":495,"slug":"lower","name":"lower","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"ToLower","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":500,"slug":"minus","name":"minus","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"ref","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"float","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"exact","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"Minus","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":505,"slug":"mod","name":"mod","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"value","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Mod","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":510,"slug":"modifydatetime","name":"modifyDateTime","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"modifier","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ModifyDateTime","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":515,"slug":"multiply","name":"multiply","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"value","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"float","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"exact","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"Multiply","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":520,"slug":"notequals","name":"notEquals","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"value","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"NotEquals","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":525,"slug":"notsame","name":"notSame","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"value","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"NotSame","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":530,"slug":"numberformat","name":"numberFormat","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"decimals","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"2"},{"name":"decimalSeparator","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'.'"},{"name":"thousandsSeparator","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"','"}],"return_type":[{"name":"NumberFormat","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":544,"slug":"oneach","name":"onEach","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"function","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"preserveKeys","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"}],"return_type":[{"name":"OnEach","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBFeGVjdXRlIGEgc2NhbGFyIGZ1bmN0aW9uIG9uIGVhY2ggZWxlbWVudCBvZiBhbiBhcnJheS9saXN0L21hcC9zdHJ1Y3R1cmUgZW50cnkuCiAgICAgKiBJbiBvcmRlciB0byB1c2UgdGhpcyBmdW5jdGlvbiwgeW91IG5lZWQgdG8gcHJvdmlkZSBhIHJlZmVyZW5jZSB0byB0aGUgImVsZW1lbnQiIHRoYXQgd2lsbCBiZSB1c2VkIGluIHRoZSBmdW5jdGlvbi4KICAgICAqCiAgICAgKiBFeGFtcGxlOiAkZGYtPndpdGhFbnRyeSgnYXJyYXknLCByZWYoJ2FycmF5JyktPm9uRWFjaChyZWYoJ2VsZW1lbnQnKS0+Y2FzdCh0eXBlX3N0cmluZygpKSkpCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":549,"slug":"or","name":"or","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"function","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Any","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":554,"slug":"ornot","name":"orNot","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"function","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Any","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":559,"slug":"plus","name":"plus","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"ref","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"float","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"exact","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"Plus","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":564,"slug":"power","name":"power","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"value","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"exact","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"Power","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":569,"slug":"prepend","name":"prepend","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"prefix","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Prepend","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":574,"slug":"regex","name":"regex","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"pattern","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"flags","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"0"},{"name":"offset","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"0"}],"return_type":[{"name":"Regex","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":579,"slug":"regexall","name":"regexAll","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"pattern","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"flags","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"0"},{"name":"offset","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"0"}],"return_type":[{"name":"RegexAll","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":584,"slug":"regexmatch","name":"regexMatch","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"pattern","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"flags","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"0"},{"name":"offset","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"0"}],"return_type":[{"name":"RegexMatch","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":592,"slug":"regexmatchall","name":"regexMatchAll","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"pattern","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"flags","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"0"},{"name":"offset","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"0"}],"return_type":[{"name":"RegexMatchAll","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":600,"slug":"regexreplace","name":"regexReplace","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"pattern","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"replacement","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"limit","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"null","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"RegexReplace","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":608,"slug":"repeat","name":"repeat","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"times","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Repeat","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":613,"slug":"reverse","name":"reverse","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"Reverse","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":618,"slug":"round","name":"round","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"precision","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"2"},{"name":"mode","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"1"}],"return_type":[{"name":"Round","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":623,"slug":"same","name":"same","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"value","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Same","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":628,"slug":"sanitize","name":"sanitize","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"placeholder","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'*'"},{"name":"skipCharacters","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"null","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Sanitize","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":635,"slug":"size","name":"size","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"Size","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":643,"slug":"slug","name":"slug","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"separator","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'-'"},{"name":"locale","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"null","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"symbolsMap","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"null","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Slug","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gU2NhbGFyRnVuY3Rpb258bnVsbHxhcnJheTxhcnJheS1rZXksIG1peGVkPiAkc3ltYm9sc01hcAogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":651,"slug":"split","name":"split","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"separator","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"limit","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"9223372036854775807"}],"return_type":[{"name":"Split","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":656,"slug":"sprintf","name":"sprintf","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"params","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"float","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"null","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":true,"default_value":null}],"return_type":[{"name":"Sprintf","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":661,"slug":"startswith","name":"startsWith","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"needle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"StartsWith","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":669,"slug":"stringafter","name":"stringAfter","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"needle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"includeNeedle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"StringAfter","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBSZXR1cm5zIHRoZSBjb250ZW50cyBmb3VuZCBhZnRlciB0aGUgZmlyc3Qgb2NjdXJyZW5jZSBvZiB0aGUgZ2l2ZW4gc3RyaW5nLgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":677,"slug":"stringafterlast","name":"stringAfterLast","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"needle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"includeNeedle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"StringAfterLast","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBSZXR1cm5zIHRoZSBjb250ZW50cyBmb3VuZCBhZnRlciB0aGUgbGFzdCBvY2N1cnJlbmNlIG9mIHRoZSBnaXZlbiBzdHJpbmcuCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":687,"slug":"stringbefore","name":"stringBefore","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"needle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"includeNeedle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"StringBefore","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBSZXR1cm5zIHRoZSBjb250ZW50cyBmb3VuZCBiZWZvcmUgdGhlIGZpcnN0IG9jY3VycmVuY2Ugb2YgdGhlIGdpdmVuIHN0cmluZy4KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":697,"slug":"stringbeforelast","name":"stringBeforeLast","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"needle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"includeNeedle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"StringBeforeLast","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBSZXR1cm5zIHRoZSBjb250ZW50cyBmb3VuZCBiZWZvcmUgdGhlIGxhc3Qgb2NjdXJyZW5jZSBvZiB0aGUgZ2l2ZW4gc3RyaW5nLgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":707,"slug":"stringcontainsany","name":"stringContainsAny","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"needles","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"StringContainsAny","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gYXJyYXk8c3RyaW5nPnxTY2FsYXJGdW5jdGlvbiAkbmVlZGxlcwogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":712,"slug":"stringequalsto","name":"stringEqualsTo","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"string","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"StringEqualsTo","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":720,"slug":"stringfold","name":"stringFold","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"StringFold","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBSZXR1cm5zIGEgc3RyaW5nIHRoYXQgeW91IGNhbiB1c2UgaW4gY2FzZS1pbnNlbnNpdGl2ZSBjb21wYXJpc29ucy4KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":725,"slug":"stringmatch","name":"stringMatch","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"pattern","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"StringMatch","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":730,"slug":"stringmatchall","name":"stringMatchAll","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"pattern","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"StringMatchAll","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":735,"slug":"stringnormalize","name":"stringNormalize","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"form","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"16"}],"return_type":[{"name":"StringNormalize","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":744,"slug":"stringstyle","name":"stringStyle","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"style","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"StringStyles","namespace":"Flow\\ETL\\String","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"StringStyle","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBDb3ZlcnQgc3RyaW5nIHRvIGEgc3R5bGUgZnJvbSBlbnVtIGxpc3QsIHBhc3NlZCBpbiBwYXJhbWV0ZXIuCiAgICAgKiBDYW4gYmUgc3RyaW5nICJ1cHBlciIgb3IgU3RyaW5nU3R5bGVzOjpVUFBFUiBmb3IgVXBwZXIgKGV4YW1wbGUpLgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":752,"slug":"stringtitle","name":"stringTitle","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"allWords","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"StringTitle","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBDaGFuZ2VzIGFsbCBncmFwaGVtZXMvY29kZSBwb2ludHMgdG8gInRpdGxlIGNhc2UiLgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":757,"slug":"stringwidth","name":"stringWidth","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"StringWidth","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":762,"slug":"strpad","name":"strPad","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"length","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"pad_string","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"' '"},{"name":"type","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"1"}],"return_type":[{"name":"StrPad","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":767,"slug":"strpadboth","name":"strPadBoth","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"length","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"pad_string","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"' '"}],"return_type":[{"name":"StrPad","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":772,"slug":"strpadleft","name":"strPadLeft","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"length","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"pad_string","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"' '"}],"return_type":[{"name":"StrPad","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":777,"slug":"strpadright","name":"strPadRight","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"length","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"pad_string","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"' '"}],"return_type":[{"name":"StrPad","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":786,"slug":"strreplace","name":"strReplace","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"search","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"replace","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"StrReplace","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gYXJyYXk8c3RyaW5nPnxTY2FsYXJGdW5jdGlvbnxzdHJpbmcgJHNlYXJjaAogICAgICogQHBhcmFtIGFycmF5PHN0cmluZz58U2NhbGFyRnVuY3Rpb258c3RyaW5nICRyZXBsYWNlCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":794,"slug":"todate","name":"toDate","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"format","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'Y-m-d\\\\TH:i:sP'"},{"name":"timeZone","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"DateTimeZone","namespace":"","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"DateTimeZone::..."}],"return_type":[{"name":"ToDate","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gU2NhbGFyRnVuY3Rpb258c3RyaW5nICRmb3JtYXQgLSBjdXJyZW50IGZvcm1hdCBvZiB0aGUgZGF0ZSB0aGF0IHdpbGwgYmUgdXNlZCB0byBjcmVhdGUgRGF0ZVRpbWVJbW11dGFibGUgaW5zdGFuY2UKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":805,"slug":"todatetime","name":"toDateTime","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"format","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'Y-m-d H:i:s'"},{"name":"timeZone","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"DateTimeZone","namespace":"","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"DateTimeZone::..."}],"return_type":[{"name":"ToDateTime","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gU2NhbGFyRnVuY3Rpb258c3RyaW5nICRmb3JtYXQgLSBjdXJyZW50IGZvcm1hdCBvZiB0aGUgZGF0ZSB0aGF0IHdpbGwgYmUgdXNlZCB0byBjcmVhdGUgRGF0ZVRpbWVJbW11dGFibGUgaW5zdGFuY2UKICAgICAqIEBwYXJhbSBcRGF0ZVRpbWVab25lfFNjYWxhckZ1bmN0aW9uICR0aW1lWm9uZQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":812,"slug":"trim","name":"trim","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"type","type":[{"name":"Type","namespace":"Flow\\ETL\\Function\\Trim","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Function\\Trim\\Type::..."},{"name":"characters","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"' \\t\\n\\r\\0\u000b'"}],"return_type":[{"name":"Trim","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":817,"slug":"truncate","name":"truncate","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"length","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"ellipsis","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'...'"}],"return_type":[{"name":"Truncate","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":822,"slug":"unicodelength","name":"unicodeLength","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"UnicodeLength","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":846,"slug":"unpack","name":"unpack","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"schema","type":[{"name":"Schema","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ArrayUnpack","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBVbnBhY2tzIGVhY2ggZWxlbWVudCBvZiBhbiBhcnJheSBpbnRvIGEgbmV3IGVudHJ5LCB1c2luZyB0aGUgYXJyYXkga2V5IGFzIHRoZSBlbnRyeSBuYW1lLgogICAgICoKICAgICAqIEJlZm9yZToKICAgICAqICAgKy0tKy0tLS0tLS0tLS0tLS0tLS0tLS0rCiAgICAgKiAgIHxpZHwgICAgICAgICAgICAgIGFycmF5fAogICAgICogICArLS0rLS0tLS0tLS0tLS0tLS0tLS0tLSsKICAgICAqICAgfCAxfHsiYSI6MSwiYiI6MiwiYyI6M318CiAgICAgKiAgIHwgMnx7ImQiOjQsImUiOjUsImYiOjZ9fAogICAgICogICArLS0rLS0tLS0tLS0tLS0tLS0tLS0tLSsKICAgICAqCiAgICAgKiBBZnRlcjoKICAgICAqICAgKy0tKy0tLS0tKy0tLS0tKy0tLS0tKy0tLS0tKy0tLS0tKwogICAgICogICB8aWR8YXJyLmJ8YXJyLmN8YXJyLmR8YXJyLmV8YXJyLmZ8CiAgICAgKiAgICstLSstLS0tLSstLS0tLSstLS0tLSstLS0tLSstLS0tLSsKICAgICAqICAgfCAxfCAgICAyfCAgICAzfCAgICAgfCAgICAgfCAgICAgfAogICAgICogICB8IDJ8ICAgICB8ICAgICB8ICAgIDR8ICAgIDV8ICAgIDZ8CiAgICAgKiAgICstLSstLS0tLSstLS0tLSstLS0tLSstLS0tLSstLS0tLSsKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":851,"slug":"upper","name":"upper","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"ToUpper","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":856,"slug":"wordwrap","name":"wordwrap","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"width","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"break","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'\\n'"},{"name":"cut","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"Wordwrap","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":864,"slug":"xpath","name":"xpath","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"string","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"XPath","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ResolvesFromChildren.php","start_line_in_file":12,"slug":"resolved","name":"resolved","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ResolvesFromChildren.php","start_line_in_file":23,"slug":"deterministic","name":"deterministic","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Flow.php","start_line_in_file":23,"slug":"setup","name":"setUp","class":"Flow\\ETL\\Flow","class_slug":"flow","parameters":[{"name":"config","type":[{"name":"ConfigBuilder","namespace":"Flow\\ETL\\Config","is_nullable":false,"is_variadic":false},{"name":"Config","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Flow.php","start_line_in_file":28,"slug":"extract","name":"extract","class":"Flow\\ETL\\Flow","class_slug":"flow","parameters":[{"name":"extractor","type":[{"name":"Extractor","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"DataFrame","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Flow.php","start_line_in_file":33,"slug":"from","name":"from","class":"Flow\\ETL\\Flow","class_slug":"flow","parameters":[{"name":"extractor","type":[{"name":"Extractor","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"DataFrame","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Flow.php","start_line_in_file":38,"slug":"process","name":"process","class":"Flow\\ETL\\Flow","class_slug":"flow","parameters":[{"name":"rows","type":[{"name":"Rows","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"DataFrame","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Flow.php","start_line_in_file":46,"slug":"read","name":"read","class":"Flow\\ETL\\Flow","class_slug":"flow","parameters":[{"name":"extractor","type":[{"name":"Extractor","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"DataFrame","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBBbGlhcyBmb3IgRmxvdzo6ZXh0cmFjdCBmdW5jdGlvbi4KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":75,"slug":"aggregate","name":"aggregate","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"aggregations","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"algorithm","type":[{"name":"GroupByAlgorithmBuilder","namespace":"Flow\\ETL\\Config\\Grouping","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEBwYXJhbSBBZ2dyZWdhdGlvbnMgJGFnZ3JlZ2F0aW9ucwogICAgICogQHBhcmFtIG51bGx8R3JvdXBCeUFsZ29yaXRobUJ1aWxkZXIgJGFsZ29yaXRobSBudWxsIGRlZmVycyB0byBjb25maWd1cmF0aW9uOyBhIGJ1aWxkZXIgcGlucyB0aGUKICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGdvcml0aG0gZm9yIHRoaXMgb3BlcmF0aW9uIGFuZCBza2lwcyBhbnkgYXV0b21hdGljIGNob2ljZQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":99,"slug":"batchby","name":"batchBy","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"column","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"minSize","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBNZXJnZS9TcGxpdCBSb3dzIHlpZWxkZWQgYnkgRXh0cmFjdG9yIGludG8gYmF0Y2hlcyBidXQga2VlcCB0aG9zZSB3aXRoIGNvbW1vbiB2YWx1ZSBpbiBnaXZlbiBjb2x1bW4gdG9nZXRoZXIuCiAgICAgKiBUaGlzIHdvcmtzIHByb3Blcmx5IG9ubHkgb24gc29ydGVkIGRhdGFzZXRzLgogICAgICoKICAgICAqIFdoZW4gbWluU2l6ZSBpcyBub3QgcHJvdmlkZWQsIGJhdGNoZXMgd2lsbCBiZSBjcmVhdGVkIG9ubHkgd2hlbiB0aGVyZSBpcyBhIGNoYW5nZSBpbiB2YWx1ZSBvZiB0aGUgY29sdW1uLgogICAgICogV2hlbiBtaW5TaXplIGlzIHByb3ZpZGVkLCBiYXRjaGVzIHdpbGwgYmUgY3JlYXRlZCBvbmx5IHdoZW4gdGhlcmUgaXMgYSBjaGFuZ2UgaW4gdmFsdWUgb2YgdGhlIGNvbHVtbiBvcgogICAgICogd2hlbiB0aGVyZSBhcmUgYXQgbGVhc3QgbWluU2l6ZSByb3dzIGluIHRoZSBiYXRjaC4KICAgICAqCiAgICAgKiBAcGFyYW0gUmVmZXJlbmNlfHN0cmluZyAkY29sdW1uIC0gY29sdW1uIHRvIGdyb3VwIGJ5IChhbGwgcm93cyB3aXRoIHNhbWUgdmFsdWUgc3RheSB0b2dldGhlcikKICAgICAqIEBwYXJhbSBudWxsfGludDwxLCBtYXg+ICRtaW5TaXplIC0gb3B0aW9uYWwgbWluaW11bSByb3dzIHBlciBiYXRjaCBmb3IgZWZmaWNpZW5jeQogICAgICoKICAgICAqIEBsYXp5CiAgICAgKgogICAgICogQHRocm93cyBJbnZhbGlkQXJndW1lbnRFeGNlcHRpb24KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":119,"slug":"batchsize","name":"batchSize","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"size","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBNZXJnZS9TcGxpdCBSb3dzIHlpZWxkZWQgYnkgRXh0cmFjdG9yIGludG8gYmF0Y2hlcyBvZiBnaXZlbiBzaXplLgogICAgICogRm9yIGV4YW1wbGUsIHdoZW4gRXh0cmFjdG9yIGlzIHlpZWxkaW5nIG9uZSByb3cgYXQgdGltZSwgdGhpcyBtZXRob2Qgd2lsbCBtZXJnZSB0aGVtIGludG8gYmF0Y2hlcyBvZiBnaXZlbiBzaXplCiAgICAgKiBiZWZvcmUgcGFzc2luZyB0aGVtIHRvIHRoZSBuZXh0IHBpcGVsaW5lIGVsZW1lbnQuCiAgICAgKiBTaW1pbGFybHkgd2hlbiBFeHRyYWN0b3IgaXMgeWllbGRpbmcgYmF0Y2hlcyBvZiByb3dzLCB0aGlzIG1ldGhvZCB3aWxsIHNwbGl0IHRoZW0gaW50byBzbWFsbGVyIGJhdGNoZXMgb2YgZ2l2ZW4KICAgICAqIHNpemUuCiAgICAgKgogICAgICogSW4gb3JkZXIgdG8gbWVyZ2UgYWxsIFJvd3MgaW50byBhIHNpbmdsZSBiYXRjaCB1c2UgRGF0YUZyYW1lOjpjb2xsZWN0KCkgbWV0aG9kIG9yIHNldCBzaXplIHRvIC0xIG9yIDAuCiAgICAgKgogICAgICogQHBhcmFtIGludDwtMSwgbWF4PiAkc2l6ZQogICAgICoKICAgICAqIEBsYXp5CiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":151,"slug":"cache","name":"cache","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"id","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"cacheBatchSize","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"cache","type":[{"name":"Cache","namespace":"Flow\\ETL","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBTdGFydCBwcm9jZXNzaW5nIHJvd3MgdXAgdG8gdGhpcyBtb21lbnQgYW5kIHB1dCBlYWNoIGluc3RhbmNlIG9mIFJvd3MKICAgICAqIGludG8gcHJldmlvdXNseSBkZWZpbmVkIGNhY2hlLgogICAgICogQ2FjaGUgdHlwZSBjYW4gYmUgc2V0IHRocm91Z2ggQ29uZmlnQnVpbGRlci4KICAgICAqIEJ5IGRlZmF1bHQgZXZlcnl0aGluZyBpcyBjYWNoZWQgaW4gc3lzdGVtIHRtcCBkaXIuCiAgICAgKgogICAgICogSW1wb3J0YW50OiBjYWNoZSBiYXRjaCBzaXplIG1pZ2h0IHNpZ25pZmljYW50bHkgaW1wcm92ZSBwZXJmb3JtYW5jZSB3aGVuIHByb2Nlc3NpbmcgbGFyZ2UgYW1vdW50IG9mIHJvd3MuCiAgICAgKiBMYXJnZXIgYmF0Y2ggc2l6ZSB3aWxsIGluY3JlYXNlIG1lbW9yeSBjb25zdW1wdGlvbiBidXQgd2lsbCByZWR1Y2UgbnVtYmVyIG9mIElPIG9wZXJhdGlvbnMuCiAgICAgKiBXaGVuIG5vdCBzZXQsIHRoZSBiYXRjaCBzaXplIGlzIHRha2VuIGZyb20gdGhlIGxhc3QgRGF0YUZyYW1lOjpiYXRjaFNpemUoKSBjYWxsLgogICAgICoKICAgICAqIEBsYXp5CiAgICAgKgogICAgICogQHBhcmFtIG51bGx8c3RyaW5nICRpZAogICAgICogQHBhcmFtIG51bGx8Q2FjaGUgJGNhY2hlIHJlYWRzIG9mIHRoaXMgY2FjaGUgbXVzdCBwYXNzIHRoZSBzYW1lIGluc3RhbmNlIHRvIGZyb21fY2FjaGUoKQogICAgICoKICAgICAqIEB0aHJvd3MgSW52YWxpZEFyZ3VtZW50RXhjZXB0aW9uCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":168,"slug":"collect","name":"collect","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBCZWZvcmUgdHJhbnNmb3JtaW5nIHJvd3MsIGNvbGxlY3QgdGhlbSBhbmQgbWVyZ2UgaW50byBzaW5nbGUgUm93cyBpbnN0YW5jZS4KICAgICAqIFRoaXMgbWlnaHQgbGVhZCB0byBtZW1vcnkgaXNzdWVzIHdoZW4gcHJvY2Vzc2luZyBsYXJnZSBhbW91bnQgb2Ygcm93cywgdXNlIHdpdGggY2F1dGlvbi4KICAgICAqCiAgICAgKiBAbGF6eQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":187,"slug":"collectrefs","name":"collectRefs","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"references","type":[{"name":"References","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBUaGlzIG1ldGhvZCBhbGxvd3MgdG8gY29sbGVjdCByZWZlcmVuY2VzIHRvIGFsbCBlbnRyaWVzIHVzZWQgaW4gdGhpcyBwaXBlbGluZS4KICAgICAqCiAgICAgKiBgYGBwaHAKICAgICAqIChuZXcgRmxvdygpKQogICAgICogICAtPnJlYWQoRnJvbTo6Y2hhaW4oKSkKICAgICAqICAgLT5jb2xsZWN0UmVmcygkcmVmcyA9IHJlZnMoKSkKICAgICAqICAgLT5ydW4oKTsKICAgICAqIGBgYAogICAgICoKICAgICAqIEBsYXp5CiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":194,"slug":"constrain","name":"constrain","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"constraint","type":[{"name":"Constraint","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"constraints","type":[{"name":"Constraint","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":205,"slug":"count","name":"count","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[],"return_type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAdHJpZ2dlcgogICAgICogUmV0dXJuIHRvdGFsIGNvdW50IG9mIHJvd3MgcHJvY2Vzc2VkIGJ5IHRoaXMgcGlwZWxpbmUuCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":225,"slug":"crossjoin","name":"crossJoin","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"dataFrame","type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"prefix","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"''"}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":242,"slug":"display","name":"display","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"limit","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"20"},{"name":"truncate","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"20"},{"name":"formatter","type":[{"name":"Formatter","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Formatter\\AsciiTableFormatter::..."}],"return_type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gaW50ICRsaW1pdCBtYXhpbXVtIG51bWJlcnMgb2Ygcm93cyB0byBkaXNwbGF5CiAgICAgKiBAcGFyYW0gYm9vbHxpbnQgJHRydW5jYXRlIGZhbHNlIG9yIGlmIHNldCB0byAwIGNvbHVtbnMgYXJlIG5vdCB0cnVuY2F0ZWQsIG90aGVyd2lzZSBkZWZhdWx0IHRydW5jYXRlIHRvIDIwCiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoYXJhY3RlcnMKICAgICAqIEBwYXJhbSBGb3JtYXR0ZXIgJGZvcm1hdHRlcgogICAgICoKICAgICAqIEB0cmlnZ2VyCiAgICAgKgogICAgICogQHRocm93cyBJbnZhbGlkQXJndW1lbnRFeGNlcHRpb24KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":269,"slug":"drop","name":"drop","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"entries","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBEcm9wIGdpdmVuIGVudHJpZXMuCiAgICAgKgogICAgICogQGxhenkKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":283,"slug":"dropduplicates","name":"dropDuplicates","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"entries","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gUmVmZXJlbmNlfHN0cmluZyAuLi4kZW50cmllcwogICAgICoKICAgICAqIEBsYXp5CiAgICAgKgogICAgICogQHJldHVybiAkdGhpcwogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":290,"slug":"duplicaterow","name":"duplicateRow","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"condition","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null},{"name":"entries","type":[{"name":"WithEntry","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":309,"slug":"fetch","name":"fetch","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"limit","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Rows","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBCZSBhd2FyZSB0aGF0IGZldGNoIGlzIG5vdCBtZW1vcnkgc2FmZSBhbmQgd2lsbCBsb2FkIGFsbCByb3dzIGludG8gbWVtb3J5LgogICAgICogSWYgeW91IHdhbnQgdG8gc2FmZWx5IGl0ZXJhdGUgb3ZlciBSb3dzIHVzZSBvZSBvZiB0aGUgZm9sbG93aW5nIG1ldGhvZHM6LgogICAgICoKICAgICAqIERhdGFGcmFtZTo6Z2V0KCkgOiBcR2VuZXJhdG9yCiAgICAgKiBEYXRhRnJhbWU6OmdldEFzQXJyYXkoKSA6IFxHZW5lcmF0b3IKICAgICAqIERhdGFGcmFtZTo6Z2V0RWFjaEFzQXJyYXkoKSA6IFxHZW5lcmF0b3IKICAgICAqCiAgICAgKiBAdHJpZ2dlcgogICAgICoKICAgICAqIEB0aHJvd3MgSW52YWxpZEFyZ3VtZW50RXhjZXB0aW9uCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":326,"slug":"filter","name":"filter","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"function","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":338,"slug":"filters","name":"filters","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"functions","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEBwYXJhbSBhcnJheTxTY2FsYXJGdW5jdGlvbj4gJGZ1bmN0aW9ucwogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":352,"slug":"foreach","name":"forEach","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"callback","type":[{"name":"callable","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"void","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAdHJpZ2dlcgogICAgICoKICAgICAqIEBwYXJhbSBudWxsfGNhbGxhYmxlKFJvd3MgJHJvd3MsIEZsb3dDb250ZXh0ICRjb250ZXh0KSA6IHZvaWQgJGNhbGxiYWNrCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":373,"slug":"get","name":"get","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[],"return_type":[{"name":"Generator","namespace":"","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBZaWVsZHMgZWFjaCByb3cgYXMgYW4gaW5zdGFuY2Ugb2YgUm93cy4KICAgICAqCiAgICAgKiBAdHJpZ2dlcgogICAgICoKICAgICAqIEByZXR1cm4gXEdlbmVyYXRvcjxSb3dzPgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":392,"slug":"getasarray","name":"getAsArray","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[],"return_type":[{"name":"Generator","namespace":"","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBZaWVsZHMgZWFjaCByb3cgYXMgYW4gYXJyYXkuCiAgICAgKgogICAgICogQHRyaWdnZXIKICAgICAqCiAgICAgKiBAcmV0dXJuIFxHZW5lcmF0b3I8YXJyYXk8YXJyYXk8bWl4ZWQ+Pj4KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":411,"slug":"geteachasarray","name":"getEachAsArray","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[],"return_type":[{"name":"Generator","namespace":"","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBZaWVsZCBlYWNoIHJvdyBhcyBhbiBhcnJheS4KICAgICAqCiAgICAgKiBAdHJpZ2dlcgogICAgICoKICAgICAqIEByZXR1cm4gXEdlbmVyYXRvcjxhcnJheTxtaXhlZD4+CiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":432,"slug":"groupby","name":"groupBy","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"entries","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"algorithm","type":[{"name":"GroupByAlgorithmBuilder","namespace":"Flow\\ETL\\Config\\Grouping","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"GroupedDataFrame","namespace":"Flow\\ETL\\DataFrame","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEBwYXJhbSBHcm91cEJ5UmVmZXJlbmNlc3xSZWZlcmVuY2V8c3RyaW5nICRlbnRyaWVzIGEgc2luZ2xlIGNvbHVtbiBpcyBncm91cGVkIGJ5IG9uIGl0cyBvd24KICAgICAqIEBwYXJhbSBudWxsfEdyb3VwQnlBbGdvcml0aG1CdWlsZGVyICRhbGdvcml0aG0gbnVsbCBkZWZlcnMgdG8gY29uZmlndXJhdGlvbjsgYSBidWlsZGVyIHBpbnMgdGhlCiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxnb3JpdGhtIGZvciB0aGlzIG9wZXJhdGlvbiBhbmQgc2tpcHMgYW55IGF1dG9tYXRpYyBjaG9pY2UKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":451,"slug":"join","name":"join","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"dataFrame","type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"on","type":[{"name":"Expression","namespace":"Flow\\ETL\\Join","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"type","type":[{"name":"Join","namespace":"Flow\\ETL\\Join","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Join\\Join::..."},{"name":"algorithm","type":[{"name":"JoinAlgorithmBuilder","namespace":"Flow\\ETL\\Config\\Join","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEBwYXJhbSBudWxsfEpvaW5BbGdvcml0aG1CdWlsZGVyICRhbGdvcml0aG0gbnVsbCBkZWZlcnMgdG8gY29uZmlndXJhdGlvbjsgYSBidWlsZGVyIHBpbnMgdGhlIGFsZ29yaXRobQogICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciB0aGlzIG9wZXJhdGlvbiBhbmQgc2tpcHMgYW55IGF1dG9tYXRpYyBjaG9pY2UKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":479,"slug":"joineach","name":"joinEach","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"factory","type":[{"name":"DataFrameFactory","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"on","type":[{"name":"Expression","namespace":"Flow\\ETL\\Join","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"type","type":[{"name":"Join","namespace":"Flow\\ETL\\Join","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Join\\Join::..."}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBKb2lucyBpbiBtZW1vcnkgcGVyIGJhdGNoOyBpdCBpcyBub3QgZ292ZXJuZWQgYnkgdGhlIGpvaW4gYWxnb3JpdGhtIGFuZCB0YWtlcyBubyBhbGdvcml0aG0gb3ZlcnJpZGUuCiAgICAgKgogICAgICogQGxhenkKICAgICAqCiAgICAgKiBAcGFyYW0gc3RyaW5nfEpvaW4gJHR5cGUKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":495,"slug":"limit","name":"limit","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"limit","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEB0aHJvd3MgSW52YWxpZEFyZ3VtZW50RXhjZXB0aW9uCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":509,"slug":"load","name":"load","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"sink","type":[{"name":"Loader","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"Sink","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":555,"slug":"match","name":"match","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"schema","type":[{"name":"Schema","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"validator","type":[{"name":"SchemaValidator","namespace":"Flow\\ETL","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEBwYXJhbSBudWxsfFNjaGVtYVZhbGlkYXRvciAkdmFsaWRhdG9yIC0gd2hlbiBudWxsLCBTdHJpY3RWYWxpZGF0b3IgZ2V0cyBpbml0aWFsaXplZAogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":576,"slug":"offset","name":"offset","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"offset","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBTa2lwIGdpdmVuIG51bWJlciBvZiByb3dzIGZyb20gdGhlIGJlZ2lubmluZyBvZiB0aGUgZGF0YXNldC4KICAgICAqIFdoZW4gJG9mZnNldCBpcyBudWxsLCBub3RoaW5nIGhhcHBlbnMgKG5vIHJvd3MgYXJlIHNraXBwZWQpLgogICAgICoKICAgICAqIFBlcmZvcm1hbmNlIE5vdGU6IERhdGFGcmFtZSBtdXN0IGl0ZXJhdGUgdGhyb3VnaCBhbmQgcHJvY2VzcyBhbGwgc2tpcHBlZCByb3dzCiAgICAgKiB0byByZWFjaCB0aGUgb2Zmc2V0IHBvc2l0aW9uLiBGb3IgbGFyZ2Ugb2Zmc2V0cywgdGhpcyBjYW4gaW1wYWN0IHBlcmZvcm1hbmNlCiAgICAgKiBhcyB0aGUgZGF0YSBzb3VyY2Ugc3RpbGwgbmVlZHMgdG8gYmUgcmVhZCBhbmQgcHJvY2Vzc2VkIHVwIHRvIHRoZSBvZmZzZXQgcG9pbnQuCiAgICAgKgogICAgICogQHBhcmFtID9pbnQ8MCwgbWF4PiAkb2Zmc2V0CiAgICAgKgogICAgICogQGxhenkKICAgICAqCiAgICAgKiBAdGhyb3dzIEludmFsaWRBcmd1bWVudEV4Y2VwdGlvbgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":590,"slug":"onerror","name":"onError","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"handler","type":[{"name":"ErrorHandler","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":602,"slug":"repartition","name":"repartition","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"entry","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"entries","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICogU2h1ZmZsZXMgdGhlIHN0cmVhbSBzbyBldmVyeSByb3cgc2hhcmluZyB0aGUgZ2l2ZW4gY29sdW1ucyBhcnJpdmVzIGluIG9uZSBiYXRjaC4gSXQgZG9lcyBub3QKICAgICAqIHdyaXRlIGRpcmVjdG9yaWVzIC0gdGhhdCBpcyBkZWNsYXJlZCBvbiB0aGUgbG9hZGVyLCBgdG9fY3N2KC4uLiktPnBhcnRpdGlvbkJ5KCdyZWdpb24nKWAuCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":614,"slug":"printrows","name":"printRows","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"limit","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"20"},{"name":"truncate","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"20"},{"name":"formatter","type":[{"name":"Formatter","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Formatter\\AsciiTableFormatter::..."}],"return_type":[{"name":"void","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAdHJpZ2dlcgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":634,"slug":"explain","name":"explain","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"trigger","type":[{"name":"Trigger","namespace":"Flow\\ETL\\Plan","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Plan\\Trigger::..."}],"return_type":[{"name":"Plan","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBUaGUgcGxhbiAkdHJpZ2dlciB3b3VsZCBydW4gb3ZlciB0aGlzIGZyYW1lLCBmcm96ZW46IGxhdGVyIHZlcmJzIG9uIHRoaXMgZnJhbWUgZG8gbm90IHJlYWNoIGl0LiBUaGUgZGVmYXVsdAogICAgICogYWRkcyBubyBjb25zdW1lciBvZiBpdHMgb3duIC0gaXQgZHJhd3MgdGhlIGZyYW1lIGFzIGJ1aWx0LCBpdHMgY2hhaW4gYW5kIGl0cyBzaW5rcy4gdG9TdHJpbmcoKSBwcmludHMgaXQgYXMgYQogICAgICogdHJlZS4gQW5zd2VycyBmcm9tIHRoZSBwbGFuIHdpdGhvdXQgcmVhZGluZyBhIHJvdy4KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":644,"slug":"printschema","name":"printSchema","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"formatter","type":[{"name":"SchemaFormatter","namespace":"Flow\\ETL\\Schema","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Row\\Formatter\\ASCIISchemaFormatter::..."}],"return_type":[{"name":"void","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEB0aHJvd3MgU2NoZW1hTm90RGVyaXZhYmxlRXhjZXB0aW9uCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":652,"slug":"rename","name":"rename","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"from","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"to","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":659,"slug":"renameeach","name":"renameEach","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"strategies","type":[{"name":"RenameEntryStrategy","namespace":"Flow\\ETL\\Transformer\\Rename","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":670,"slug":"rows","name":"rows","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"transformer","type":[{"name":"Transformer","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"Transformation","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICogQWxpYXMgZm9yIEVUTDo6dHJhbnNmb3JtIG1ldGhvZC4KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":687,"slug":"run","name":"run","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"analyze","type":[{"name":"Analyze","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"Report","namespace":"Flow\\ETL\\Dataset","is_nullable":true,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAdHJpZ2dlcgogICAgICoKICAgICAqIFdoZW4gYW5hbHl6aW5nIHBpcGVsaW5lIGV4ZWN1dGlvbiB3ZSBjYW4gY2hvc2UgdG8gY29sbGVjdCB2YXJpb3VzIG1ldHJpY3MgdGhyb3VnaCBhbmFseXplKCktPndpdGgqKCkgbWV0aG9kCiAgICAgKgogICAgICogLSBjb2x1bW4gc3RhdGlzdGljcyAtIGFuYWx5emUoKS0+d2l0aENvbHVtblN0YXRpc3RpY3MoKQogICAgICogLSBzY2hlbWEgLSBhbmFseXplKCktPndpdGhTY2hlbWEoKQogICAgICoKICAgICAqIEBwYXJhbSBBbmFseXplfGJvb2wgJGFuYWx5emUgLSB3aGVuIHNldCBydW4gd2lsbCByZXR1cm4gUmVwb3J0CiAgICAgKgogICAgICogQHJldHVybiAoJGFuYWx5emUgaXMgQW5hbHl6ZXx0cnVlID8gUmVwb3J0IDogbnVsbCkKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":715,"slug":"schema","name":"schema","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[],"return_type":[{"name":"Schema","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEB0aHJvd3MgU2NoZW1hTm90RGVyaXZhYmxlRXhjZXB0aW9uCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":728,"slug":"select","name":"select","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"entries","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICogS2VlcCBvbmx5IGdpdmVuIGVudHJpZXMuCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":742,"slug":"sortby","name":"sortBy","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"entries","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"algorithm","type":[{"name":"SortAlgorithmBuilder","namespace":"Flow\\ETL\\Config\\Sort","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEBwYXJhbSBSZWZlcmVuY2V8U29ydFJlZmVyZW5jZXN8c3RyaW5nICRlbnRyaWVzIGEgc2luZ2xlIGNvbHVtbiBpcyBzb3J0ZWQgYnkgb24gaXRzIG93bgogICAgICogQHBhcmFtIG51bGx8U29ydEFsZ29yaXRobUJ1aWxkZXIgJGFsZ29yaXRobSBudWxsIGRlZmVycyB0byBjb25maWd1cmF0aW9uOyBhIGJ1aWxkZXIgcGlucyB0aGUgYWxnb3JpdGhtCiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIHRoaXMgb3BlcmF0aW9uIGFuZCBza2lwcyBhbnkgYXV0b21hdGljIGNob2ljZQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":756,"slug":"transform","name":"transform","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"transformer","type":[{"name":"Transformer","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"Transformation","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"Transformations","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"WithEntry","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBBbGlhcyBmb3IgRGF0YUZyYW1lOjp3aXRoKCkuCiAgICAgKgogICAgICogQGxhenkKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":767,"slug":"until","name":"until","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"function","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBUaGUgZGlmZmVyZW5jZSBiZXR3ZWVuIGZpbHRlciBhbmQgdW50aWwgaXMgdGhhdCBmaWx0ZXIgd2lsbCBrZWVwIGZpbHRlcmluZyByb3dzIHVudGlsIGV4dHJhY3RvcnMgZmluaXNoIHlpZWxkaW5nCiAgICAgKiByb3dzLiBVbnRpbCB3aWxsIHNlbmQgYSBTVE9QIHNpZ25hbCB0byB0aGUgRXh0cmFjdG9yIHdoZW4gdGhlIGNvbmRpdGlvbiBpcyBub3QgbWV0LgogICAgICoKICAgICAqIEBsYXp5CiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":781,"slug":"void","name":"void","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICogVGhpcyBtZXRob2QgaXMgdXNlZnVsIG1vc3RseSBpbiBkZXZlbG9wbWVudCB3aGVuCiAgICAgKiB5b3Ugd2FudCB0byBwYXVzZSBwcm9jZXNzaW5nIGF0IGNlcnRhaW4gbW9tZW50IHdpdGhvdXQKICAgICAqIHJlbW92aW5nIGNvZGUuIEFsbCBvcGVyYXRpb25zIHdpbGwgZ2V0IHByb2Nlc3NlZCB1cCB0byB0aGlzIHBvaW50LAogICAgICogZnJvbSBoZXJlIG5vIHJvd3MgYXJlIHBhc3NlZCBmb3J3YXJkLgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":791,"slug":"with","name":"with","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"transformer","type":[{"name":"Transformer","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"Transformation","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"Transformations","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"WithEntry","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":819,"slug":"withentries","name":"withEntries","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"references","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEBwYXJhbSBhcnJheTxpbnQsIFdpdGhFbnRyeT58YXJyYXk8c3RyaW5nLCBTY2FsYXJGdW5jdGlvbnxXaW5kb3dGdW5jdGlvbnxXaXRoRW50cnk+ICRyZWZlcmVuY2VzCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":837,"slug":"withentry","name":"withEntry","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"entry","type":[{"name":"Definition","namespace":"Flow\\ETL\\Schema","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"reference","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"WindowFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gRGVmaW5pdGlvbjxtaXhlZD58c3RyaW5nICRlbnRyeQogICAgICoKICAgICAqIEBsYXp5CiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":852,"slug":"write","name":"write","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"sink","type":[{"name":"Loader","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"Sink","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICogQWxpYXMgZm9yIEVUTDo6bG9hZCBmdW5jdGlvbi4KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame\/GroupedDataFrame.php","start_line_in_file":21,"slug":"aggregate","name":"aggregate","class":"Flow\\ETL\\DataFrame\\GroupedDataFrame","class_slug":"groupeddataframe","parameters":[{"name":"aggregations","type":[{"name":"AggregatingFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"DataFrame","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame\/GroupedDataFrame.php","start_line_in_file":28,"slug":"pivot","name":"pivot","class":"Flow\\ETL\\DataFrame\\GroupedDataFrame","class_slug":"groupeddataframe","parameters":[{"name":"ref","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"values","type":[{"name":"PivotValues","namespace":"Flow\\ETL\\GroupBy","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null}] \ No newline at end of file