From 69e29ba278f833f3e3d1c50ce1dd9ad5aa3461b5 Mon Sep 17 00:00:00 2001 From: Norbert Orzechowicz Date: Sun, 20 Sep 2026 19:14:42 +0200 Subject: [PATCH] feat(flow-php/etl): plan the query before running it - DataFrame builds a logical plan of Nodes; a Planner lowers it to pipelines an Executor runs - nodes declare their own row count, transparency, materialization and redefined columns, so optimizer rules read declarations instead of hardcoded class lists - sinks are plan roots: write() fans out, and a Transaction commits per batch (DbalTransaction, PostgreSqlTransaction replace TransactionalDbalLoader) - limits and partition filters are pushed into the source; filterPartitions() is gone, filter() does it - explain() prints any stage (unoptimized, optimized, physical) in four formats - run($callback) splits into run() and forEach() --- .../Partitioning/PartitionedReadScenario.php | 4 +- .../src/Partitioning/PartitionedTree.php | 2 +- benchmarks/src/Pipeline/PlanDepthScenario.php | 6 +- .../Doctrine/DoctrineWrappedWriteScenario.php | 3 +- .../NestedTransformationScenario.php | 5 +- .../NestedTransformationBench.php | 21 +- documentation/components/adapters/doctrine.md | 33 +- .../components/adapters/postgresql.md | 55 +- documentation/components/core/core.md | 181 +++- .../components/core/data-retrieval.md | 12 +- documentation/components/core/group-by.md | 4 +- documentation/components/core/join.md | 3 +- documentation/components/core/limit.md | 22 +- documentation/components/core/partitioning.md | 14 +- documentation/components/core/pivot.md | 4 +- documentation/components/core/retry.md | 311 ------- documentation/components/core/telemetry.md | 14 +- .../components/core/transformations.md | 74 +- documentation/components/libs/postgresql.md | 8 +- documentation/upgrading.md | 285 ++++-- phpunit.xml.dist | 3 + .../Adapter/Avro/FlixTech/AvroExtractor.php | 10 +- .../Tests/Unit/FlixTech/AvroExtractorTest.php | 23 + .../src/Flow/ETL/Adapter/CSV/CSVExtractor.php | 17 +- .../Tests/Integration/CSVExtractorTest.php | 8 +- .../Adapter/CSV/Tests/Integration/CSVTest.php | 11 +- .../Adapter/Doctrine/DbalKeySetExtractor.php | 12 +- .../Doctrine/DbalLimitOffsetExtractor.php | 13 +- .../Adapter/Doctrine/DbalQueryExtractor.php | 12 +- .../ETL/Adapter/Doctrine/DbalTransaction.php | 102 +++ .../Doctrine/IsolationLevelRestore.php | 29 + .../Adapter/Doctrine/PlaceholderRewriter.php | 2 +- .../Doctrine/TransactionalDbalLoader.php | 162 ---- .../Flow/ETL/Adapter/Doctrine/functions.php | 28 +- .../Doctrine/Tests/Context/CommitCounter.php | 20 + .../Tests/Context/DatabaseContext.php | 6 + ...rTest.php => MySQLTransactionSinkTest.php} | 98 ++- ....php => PostgreSQLTransactionSinkTest.php} | 98 ++- ...Test.php => SqliteTransactionSinkTest.php} | 98 ++- .../Doctrine/Tests/IntegrationTestCase.php | 8 + .../Tests/Unit/DbalKeySetExtractorTest.php | 3 +- .../Unit/DbalLimitOffsetExtractorTest.php | 3 +- .../Tests/Unit/DbalQueryExtractorTest.php | 3 +- ...onTest.php => DbalTransactionSinkTest.php} | 64 +- .../Tests/Unit/DbalTransactionTest.php | 138 +++ .../Tests/Unit/IsolationLevelRestoreTest.php | 35 + .../Unit/TransactionalDbalLoaderTest.php | 120 --- .../Flow/ETL/Adapter/Excel/ExcelExtractor.php | 21 +- .../Tests/Integration/ExcelExtractorTest.php | 29 +- .../GoogleSheet/GoogleSheetExtractor.php | 11 +- .../Integration/GoogleSheetExtractorTest.php | 8 +- .../Http/PsrHttpClientDynamicExtractor.php | 2 +- .../Http/PsrHttpClientPaginatedExtractor.php | 2 +- .../Http/PsrHttpClientStaticExtractor.php | 2 +- .../JSON/JSONMachine/JsonExtractor.php | 17 +- .../JSON/JSONMachine/JsonLinesExtractor.php | 17 +- .../JSONMachine/JsonExtractorTest.php | 7 +- .../JSONMachine/JsonLinesExtractorTest.php | 7 +- .../ETL/Adapter/Parquet/ParquetExtractor.php | 29 +- .../Integration/ParquetExtractorTest.php | 34 +- .../PostgreSql/PostgreSqlCursorExtractor.php | 13 +- .../PostgreSql/PostgreSqlKeySetExtractor.php | 12 +- .../PostgreSqlLimitOffsetExtractor.php | 13 +- .../PostgreSql/PostgreSqlTransaction.php | 64 ++ .../TransactionalPostgreSqlLoader.php | 126 --- .../Flow/ETL/Adapter/PostgreSql/functions.php | 14 +- .../Tests/Context/TableRowsContext.php | 54 ++ .../PostgreSqlTransactionSinkTest.php | 360 ++++++++ ...ctionalPostgreSqlLoaderIntegrationTest.php | 107 --- ...SqlLoaderTransformationIntegrationTest.php | 168 ---- .../Unit/PostgreSqlCursorExtractorTest.php | 3 +- .../Unit/PostgreSqlKeySetExtractorTest.php | 3 +- .../PostgreSqlLimitOffsetExtractorTest.php | 3 +- .../Tests/Unit/PostgreSqlTransactionTest.php | 82 ++ .../TransactionalPostgreSqlLoaderTest.php | 186 ---- .../Flow/ETL/Adapter/Text/TextExtractor.php | 19 +- .../Tests/Integration/TextExtractorTest.php | 10 +- .../ETL/Adapter/XML/XMLParserExtractor.php | 19 +- .../ETL/Adapter/XML/XMLReaderExtractor.php | 19 +- .../Integration/XMLParserExtractorTest.php | 10 +- .../Integration/XMLReaderExtractorTest.php | 7 +- .../Flow/CLI/Command/FileAnalyzeCommand.php | 6 +- .../src/Flow/CLI/Command/FileReadCommand.php | 2 +- .../src/Flow/CLI/Loader/ProgressBarLoader.php | 22 + .../Unit/Loader/ProgressBarLoaderTest.php | 52 ++ .../src/Flow/ETL/{Pipeline => }/BoundStep.php | 6 +- .../etl/src/Flow/ETL/Bucketing/BucketRun.php | 2 - src/core/etl/src/Flow/ETL/Config.php | 18 +- .../etl/src/Flow/ETL/Config/ConfigBuilder.php | 19 +- .../ETL/Config/Telemetry/TelemetryContext.php | 12 +- src/core/etl/src/Flow/ETL/DSL/functions.php | 114 +-- src/core/etl/src/Flow/ETL/DataFrame.php | 426 ++++----- .../Flow/ETL/DataFrame/GroupedDataFrame.php | 8 +- .../ETL/Exception/FailedRetryException.php | 25 - .../ETL/Exception/InvalidLogicException.php | 67 +- .../Exception/SchemaNotDerivableException.php | 11 +- .../src/Flow/ETL/Exception/SinkFailure.php | 20 + .../ETL/Exception/TransactionRolledBack.php | 22 + src/core/etl/src/Flow/ETL/Executor.php | 153 ++++ .../etl/src/Flow/ETL/Executor/Described.php | 25 + .../src/Flow/ETL/Executor/PhysicalPlan.php | 23 + .../etl/src/Flow/ETL/Executor/Pipeline.php | 65 ++ src/core/etl/src/Flow/ETL/Executor/Raw.php | 30 + .../ETL/{Pipeline => Executor}/Segment.php | 75 +- .../etl/src/Flow/ETL/Executor/Segments.php | 51 ++ .../etl/src/Flow/ETL/Executor/SinkFeed.php | 107 +++ .../etl/src/Flow/ETL/Executor/SinkOffers.php | 60 ++ .../etl/src/Flow/ETL/Executor/SinkRun.php | 75 ++ .../StatisticsCollector.php | 12 +- .../Flow/ETL/Executor/TransactionRollback.php | 28 + .../Flow/ETL/Executor/TransactionalSinks.php | 95 ++ src/core/etl/src/Flow/ETL/Extractor.php | 9 +- .../src/Flow/ETL/Extractor/ArrayExtractor.php | 2 +- .../Flow/ETL/Extractor/BatchByExtractor.php | 2 +- .../src/Flow/ETL/Extractor/BatchExtractor.php | 2 +- .../src/Flow/ETL/Extractor/CacheExtractor.php | 2 +- .../src/Flow/ETL/Extractor/ChainExtractor.php | 2 +- .../ETL/Extractor/CollectingExtractor.php | 2 +- .../Flow/ETL/Extractor/DataFrameExtractor.php | 50 +- .../src/Flow/ETL/Extractor/FeedExtractor.php | 4 +- .../src/Flow/ETL/Extractor/FileColumns.php | 15 + .../src/Flow/ETL/Extractor/FileExtractor.php | 28 +- .../src/Flow/ETL/Extractor/FileReading.php | 6 +- .../src/Flow/ETL/Extractor/FilesExtractor.php | 32 +- .../src/Flow/ETL/Extractor/LimitPushDown.php | 24 - .../Flow/ETL/Extractor/ListingPartitions.php | 29 + .../Flow/ETL/Extractor/MemoryExtractor.php | 2 +- .../ETL/Extractor/OverridingExtractor.php | 6 +- .../src/Flow/ETL/Extractor/PathFiltering.php | 37 +- .../ETL/Extractor/PathPartitionsExtractor.php | 38 +- .../src/Flow/ETL/Extractor/PushesLimit.php | 28 - .../src/Flow/ETL/Extractor/Repeatability.php | 32 + .../src/Flow/ETL/Extractor/RowsExtractor.php | 2 +- .../Flow/ETL/Extractor/SequenceExtractor.php | 2 +- .../ETL/Filesystem/ScalarFunctionFilter.php | 6 +- src/core/etl/src/Flow/ETL/Flow.php | 4 +- src/core/etl/src/Flow/ETL/FlowContext.php | 8 + .../src/Flow/ETL/Function/CallUserFunc.php | 8 + .../src/Flow/ETL/Function/FunctionTree.php | 7 + src/core/etl/src/Flow/ETL/Function/Now.php | 5 + .../src/Flow/ETL/Function/RandomString.php | 5 + .../src/Flow/ETL/Function/ReferenceRename.php | 50 ++ .../Flow/ETL/Function/ReferencedColumns.php | 32 + .../ETL/Function/ResolvesFromChildren.php | 11 + .../etl/src/Flow/ETL/Function/ToDateTime.php | 33 +- .../Function/ToDateTime/PatternCoverage.php | 56 ++ src/core/etl/src/Flow/ETL/Function/Ulid.php | 6 + src/core/etl/src/Flow/ETL/Function/Uuid.php | 6 + src/core/etl/src/Flow/ETL/GroupBy.php | 8 + .../ETL/GroupBy/DiscoveredPivotValues.php | 5 +- .../etl/src/Flow/ETL/GroupBy/GroupBySteps.php | 3 - src/core/etl/src/Flow/ETL/Join/JoinSteps.php | 8 +- .../src/Flow/ETL/Loader/BranchingLoader.php | 143 --- .../etl/src/Flow/ETL/Loader/LoaderTree.php | 46 - .../src/Flow/ETL/Loader/OverridingLoader.php | 21 - .../etl/src/Flow/ETL/Loader/ReplayAware.php | 17 - .../etl/src/Flow/ETL/Loader/RetryLoader.php | 96 -- .../src/Flow/ETL/Loader/TransformerLoader.php | 132 --- src/core/etl/src/Flow/ETL/Optimizer.php | 116 +++ .../etl/src/Flow/ETL/Optimizer/FilterWalk.php | 78 ++ .../etl/src/Flow/ETL/Optimizer/JoinSides.php | 35 + .../etl/src/Flow/ETL/Optimizer/LimitWalk.php | 50 ++ src/core/etl/src/Flow/ETL/Optimizer/Rule.php | 19 + .../Flow/ETL/Optimizer/Rule/CombineLimits.php | 36 + .../Optimizer/Rule/CombineSortAndLimit.php | 25 + .../Optimizer/Rule/PushFilterIntoSource.php | 76 ++ .../Optimizer/Rule/PushLimitIntoSource.php | 39 + .../src/Flow/ETL/Optimizer/TopNRewrite.php | 45 + src/core/etl/src/Flow/ETL/Pipeline.php | 168 ---- .../etl/src/Flow/ETL/Pipeline/BoundPlan.php | 20 - .../etl/src/Flow/ETL/Pipeline/Optimizer.php | 56 -- .../Pipeline/Optimizer/LimitOptimization.php | 109 --- .../ETL/Pipeline/Optimizer/Optimization.php | 16 - .../etl/src/Flow/ETL/Pipeline/PlanBinder.php | 35 - .../etl/src/Flow/ETL/Pipeline/Segments.php | 134 --- .../ETL/Pipeline/TransformationStream.php | 79 -- src/core/etl/src/Flow/ETL/Plan.php | 49 ++ src/core/etl/src/Flow/ETL/Plan/Explain.php | 38 + .../src/Flow/ETL/Plan/Explain/BoxLayout.php | 222 +++++ .../src/Flow/ETL/Plan/Explain/Branches.php | 29 + .../src/Flow/ETL/Plan/Explain/Condition.php | 66 ++ .../etl/src/Flow/ETL/Plan/Explain/Details.php | 249 ++++++ .../etl/src/Flow/ETL/Plan/Explain/Entry.php | 55 ++ .../src/Flow/ETL/Plan/Explain/FlowLayout.php | 85 ++ .../etl/src/Flow/ETL/Plan/Explain/Layout.php | 10 + .../etl/src/Flow/ETL/Plan/Explain/Outline.php | 84 ++ .../Flow/ETL/Plan/Explain/PhysicalOutline.php | 122 +++ .../src/Flow/ETL/Plan/Explain/StepDetails.php | 215 +++++ .../src/Flow/ETL/Plan/Explain/TreeLayout.php | 45 + src/core/etl/src/Flow/ETL/Plan/Format.php | 28 + .../etl/src/Flow/ETL/Plan/LogicalPlan.php | 126 +++ .../etl/src/Flow/ETL/Plan/Materialization.php | 11 + src/core/etl/src/Flow/ETL/Plan/Node.php | 62 ++ .../etl/src/Flow/ETL/Plan/Node/Aggregate.php | 58 ++ src/core/etl/src/Flow/ETL/Plan/Node/Batch.php | 63 ++ .../etl/src/Flow/ETL/Plan/Node/BatchBy.php | 65 ++ src/core/etl/src/Flow/ETL/Plan/Node/Cache.php | 63 ++ .../etl/src/Flow/ETL/Plan/Node/Collect.php | 51 ++ .../src/Flow/ETL/Plan/Node/CollectRefs.php | 56 ++ .../etl/src/Flow/ETL/Plan/Node/Constrain.php | 59 ++ .../etl/src/Flow/ETL/Plan/Node/CrossJoin.php | 73 ++ .../etl/src/Flow/ETL/Plan/Node/Discard.php | 51 ++ .../etl/src/Flow/ETL/Plan/Node/Distinct.php | 66 ++ src/core/etl/src/Flow/ETL/Plan/Node/Drop.php | 56 ++ .../src/Flow/ETL/Plan/Node/DuplicateRow.php | 59 ++ .../etl/src/Flow/ETL/Plan/Node/Filter.php | 53 ++ src/core/etl/src/Flow/ETL/Plan/Node/Join.php | 80 ++ .../etl/src/Flow/ETL/Plan/Node/JoinEach.php | 60 ++ .../etl/src/Flow/ETL/Plan/Node/JoinsFrame.php | 15 + src/core/etl/src/Flow/ETL/Plan/Node/Limit.php | 60 ++ .../etl/src/Flow/ETL/Plan/Node/Offset.php | 64 ++ .../etl/src/Flow/ETL/Plan/Node/Outputs.php | 99 +++ src/core/etl/src/Flow/ETL/Plan/Node/Read.php | 122 +++ .../etl/src/Flow/ETL/Plan/Node/Rename.php | 53 ++ .../etl/src/Flow/ETL/Plan/Node/RenameEach.php | 63 ++ .../src/Flow/ETL/Plan/Node/Repartition.php | 56 ++ .../etl/src/Flow/ETL/Plan/Node/Result.php | 55 ++ .../etl/src/Flow/ETL/Plan/Node/Select.php | 56 ++ src/core/etl/src/Flow/ETL/Plan/Node/Sort.php | 58 ++ src/core/etl/src/Flow/ETL/Plan/Node/TopN.php | 66 ++ .../src/Flow/ETL/Plan/Node/Transaction.php | 79 ++ .../etl/src/Flow/ETL/Plan/Node/Transform.php | 57 ++ src/core/etl/src/Flow/ETL/Plan/Node/Until.php | 53 ++ .../etl/src/Flow/ETL/Plan/Node/Validate.php | 58 ++ .../src/Flow/ETL/Plan/Node/WindowColumn.php | 66 ++ .../etl/src/Flow/ETL/Plan/Node/WithColumn.php | 73 ++ src/core/etl/src/Flow/ETL/Plan/Node/Write.php | 56 ++ src/core/etl/src/Flow/ETL/Plan/Redefined.php | 62 ++ .../etl/src/Flow/ETL/Plan/ReplaceLeaf.php | 18 + src/core/etl/src/Flow/ETL/Plan/Rewrite.php | 16 + src/core/etl/src/Flow/ETL/Plan/RowCount.php | 14 + src/core/etl/src/Flow/ETL/Plan/Sinks.php | 47 + src/core/etl/src/Flow/ETL/Plan/Stage.php | 18 + .../etl/src/Flow/ETL/Plan/TransformUp.php | 46 + .../etl/src/Flow/ETL/Plan/Transparency.php | 11 + src/core/etl/src/Flow/ETL/Plan/Trigger.php | 31 + src/core/etl/src/Flow/ETL/Planner.php | 103 +++ .../src/Flow/ETL/Planner/NodeTranslator.php | 121 +++ .../src/Flow/ETL/Planner/PipelineSplit.php | 92 ++ .../etl/src/Flow/ETL/Planner/PlannedNode.php | 26 + .../etl/src/Flow/ETL/Planner/PlannedNodes.php | 87 ++ .../src/Flow/ETL/Planner/SinkAttachment.php | 295 +++++++ .../src/Flow/ETL/Planner/SinkFeedFactory.php | 61 ++ src/core/etl/src/Flow/ETL/Processor.php | 3 - .../ETL/Processor/BatchingByProcessor.php | 8 +- .../Flow/ETL/Processor/BatchingProcessor.php | 6 +- .../Flow/ETL/Processor/BucketingProcessor.php | 9 +- .../Flow/ETL/Processor/CachingProcessor.php | 8 +- .../ETL/Processor/CollectingProcessor.php | 6 +- .../ETL/Processor/ConstrainedProcessor.php | 6 +- .../Processor/GroupByAggregationProcessor.php | 10 +- .../Flow/ETL/Processor/HashJoinProcessor.php | 26 +- .../ETL/Processor/MemorySortProcessor.php | 6 +- .../Flow/ETL/Processor/MergeSortProcessor.php | 12 +- .../Flow/ETL/Processor/OffsetProcessor.php | 6 +- .../src/Flow/ETL/Processor/PivotProcessor.php | 9 +- .../ETL/Processor/RepartitionProcessor.php | 10 +- .../src/Flow/ETL/Processor/TopNProcessor.php | 88 ++ .../src/Flow/ETL/Processor/VoidProcessor.php | 4 +- .../Flow/ETL/Processor/WindowProcessor.php | 10 +- .../Flow/ETL/Repartition/RepartitionSteps.php | 3 - .../etl/src/Flow/ETL/Retry/DelayFactory.php | 12 - .../ETL/Retry/DelayFactory/Exponential.php | 30 - .../src/Flow/ETL/Retry/DelayFactory/Fixed.php | 20 - .../DelayFactory/Fixed/FixedMilliseconds.php | 20 - .../Flow/ETL/Retry/DelayFactory/Jitter.php | 40 - .../Flow/ETL/Retry/DelayFactory/Linear.php | 23 - .../etl/src/Flow/ETL/Retry/FailedRetry.php | 23 - .../etl/src/Flow/ETL/Retry/RetriesRecord.php | 45 - .../etl/src/Flow/ETL/Retry/RetryStrategy.php | 12 - .../ETL/Retry/RetryStrategy/AnyThrowable.php | 25 - .../RetryStrategy/AnyThrowableExcept.php | 67 -- .../Retry/RetryStrategy/OnExceptionTypes.php | 67 -- src/core/etl/src/Flow/ETL/Rows.php | 4 +- src/core/etl/src/Flow/ETL/Sink.php | 14 + src/core/etl/src/Flow/ETL/Sink/Branched.php | 32 + .../etl/src/Flow/ETL/Sink/Transactional.php | 50 ++ .../etl/src/Flow/ETL/Sink/Transformed.php | 29 + src/core/etl/src/Flow/ETL/Sort/SortSteps.php | 3 - src/core/etl/src/Flow/ETL/Time/Duration.php | 61 -- src/core/etl/src/Flow/ETL/Time/FakeSleep.php | 57 -- src/core/etl/src/Flow/ETL/Time/Sleep.php | 10 - .../etl/src/Flow/ETL/Time/SystemSleep.php | 16 - src/core/etl/src/Flow/ETL/Transaction.php | 19 + .../Flow/ETL/Transformation/AddRowIndex.php | 2 +- src/core/etl/src/Flow/ETL/Transformer.php | 1 - .../Transformer/AddRowIndexTransformer.php | 12 +- .../CollectReferencesTransformer.php | 2 +- .../Transformer/CrossJoinRowsTransformer.php | 14 +- .../Transformer/DropDuplicatesTransformer.php | 2 +- .../Transformer/DropEntriesTransformer.php | 3 +- .../Transformer/DuplicateRowTransformer.php | 2 +- .../Transformer/JoinEachRowsTransformer.php | 2 +- .../Flow/ETL/Transformer/LimitTransformer.php | 2 +- .../Transformer/NestedExpandTransformer.php | 2 +- .../Transformer/PruneEntriesTransformer.php | 2 +- .../RenameEachEntryTransformer.php | 2 +- .../Transformer/RenameEntryTransformer.php | 2 +- .../ScalarFunctionFilterTransformer.php | 2 +- .../Transformer/ScalarFunctionTransformer.php | 2 +- .../Transformer/SelectEntriesTransformer.php | 3 +- .../ETL/Transformer/SerializeTransformer.php | 2 +- .../etl/src/Flow/ETL/Transformer/Stateful.php | 19 + .../Transformer/UnserializeTransformer.php | 2 +- .../Flow/ETL/Transformer/UntilTransformer.php | 2 +- .../etl/src/Flow/ETL/Window/BoundWindow.php | 3 - src/core/etl/src/Flow/Floe/FloeExtractor.php | 21 +- .../etl/src/Flow/Serializer/Serializer.php | 3 - .../Flow/ETL/Tests/Context/ExecutedPlan.php | 23 + .../ETL/Tests/Context/ExecutedSegments.php | 29 + .../Flow/ETL/Tests/Context/ExtractedRows.php | 16 +- .../ETL/Tests/Context/LoaderEndingContext.php | 9 +- .../Flow/ETL/Tests/Context/PipelineSteps.php | 45 + .../Flow/ETL/Tests/Context/ScoredRows.php | 55 ++ .../AddStampToStringEntryTransformer.php | 2 +- .../Flow/ETL/Tests/Double/CallOrderLoader.php | 26 + .../Flow/ETL/Tests/Double/ChildlessNode.php | 48 + .../Double/ContextRecordingTransformer.php | 31 + .../ETL/Tests/Double/CountingExtractor.php | 8 +- .../Flow/ETL/Tests/Double/EmptyExtractor.php | 2 +- .../Flow/ETL/Tests/Double/FakeExtractor.php | 2 +- .../Double/FakeRandomOrdersExtractor.php | 2 +- .../Double/FakeStaticOrdersExtractor.php | 2 +- .../Flow/ETL/Tests/Double/FanOutSink.php | 32 + .../ETL/Tests/Double/FileReadingExtractor.php | 6 +- .../Double/FixedRandomValueGenerator.php | 25 + .../Tests/Double/OneRowBatchesExtractor.php | 2 +- .../ETL/Tests/Double/PassThroughProcessor.php | 24 + .../Tests/Double/PlanDrainingTransformer.php | 47 + ...pagatingTransformationsSkippingLoaders.php | 31 + .../Tests/Double/ReadsBackOnSecondBatch.php | 2 +- .../ETL/Tests/Double/RecordingExtractor.php | 55 ++ .../Tests/Double/RecordingFileExtractor.php | 87 ++ .../Flow/ETL/Tests/Double/RecordingLoader.php | 68 ++ .../Flow/ETL/Tests/Double/RecordingRule.php | 31 + .../ETL/Tests/Double/RecordingTransaction.php | 59 ++ .../Flow/ETL/Tests/Double/RedefiningNode.php | 55 ++ .../ETL/Tests/Double/RenameSelectRewrite.php | 18 + .../ETL/Tests/Double/RepeatableExtractor.php | 2 +- .../ETL/Tests/Double/RowLessExtractor.php | 2 +- .../ETL/Tests/Double/SpineCopyingRule.php | 31 + .../tests/Flow/ETL/Tests/Double/SpySink.php | 18 + .../Flow/ETL/Tests/Double/SpyTransformer.php | 28 + .../Tests/Double/StopIgnoringExtractor.php | 2 +- .../ETL/Tests/Double/ThrowWhenRowMatches.php | 2 +- .../ThrowingAfterFirstBatchExtractor.php | 2 +- .../ETL/Tests/Double/ThrowingTransformer.php | 2 +- .../Double/UndescribableRowLessExtractor.php | 2 +- .../Tests/Double/VaryingBatchesExtractor.php | 2 +- .../Flow/ETL/Tests/Double/WrappingLoader.php | 45 - .../ETL/Tests/Fixtures/Join/AlwaysMeets.php | 26 + .../tests/Flow/ETL/Tests/Fixtures/orders.csv | 7 + .../tests/Flow/ETL/Tests/Fixtures/sellers.csv | 4 + .../etl/tests/Flow/ETL/Tests/FlowTestCase.php | 39 +- .../Integration/DataFrame/AnalyzeTest.php | 16 +- .../Integration/DataFrame/BatchByTest.php | 12 +- .../Integration/DataFrame/BranchingTest.php | 51 +- .../Tests/Integration/DataFrame/CacheTest.php | 2 +- .../DataFrame/ConfigBuilderTest.php | 35 + .../Integration/DataFrame/DisplayTest.php | 4 +- .../Integration/DataFrame/GroupByTest.php | 2 +- .../Tests/Integration/DataFrame/LimitTest.php | 94 +- .../Tests/Integration/DataFrame/MathTest.php | 9 +- .../Integration/DataFrame/OffsetTest.php | 8 +- .../DataFrame/PartitioningTest.php | 109 ++- .../Integration/DataFrame/PerRunPlanTest.php | 64 ++ .../Integration/DataFrame/PlanBindTest.php | 54 +- .../Integration/DataFrame/SinglePlanTest.php | 156 ++++ .../SinkRootBlockingOperationsTest.php} | 70 +- .../Integration/DataFrame/SinkRootTest.php | 821 ++++++++++++++++++ .../Integration/DataFrame/TelemetryTest.php | 208 ++++- .../Integration/DataFrame/TriggerPlanTest.php | 94 ++ .../Extractor/PathPartitionsExtractorTest.php | 45 + .../Integration/Loader/RetryLoaderTest.php | 54 -- .../Loader/TransformerLoaderTest.php | 323 ------- .../Pipeline/BatchingPipelineTest.php | 27 +- .../Pipeline/CollectingPipelineTest.php | 9 +- .../Integration/Pipeline/OptimizerTest.php | 27 - .../Integration/Pipeline/PipelineTest.php | 73 +- .../Sort/MemorySort/MemorySortTest.php | 7 +- .../Flow/ETL/Tests/Mother/EntryMother.php | 25 + .../Tests/Mother/HashJoinProcessorMother.php | 10 +- .../Flow/ETL/Tests/Mother/NodeMother.php | 80 ++ .../Tests/Mother/PartitionedSourceMother.php | 45 + .../ETL/Tests/Mother/PhysicalPlanMother.php | 32 + .../ETL/Tests/Mother/SinkAttachmentMother.php | 39 + .../Flow/ETL/Tests/Mother/SinkFeedMother.php | 69 ++ .../Config/Telemetry/TelemetryContextTest.php | 35 + .../Flow/ETL/Tests/Unit/DataFrameTest.php | 564 +++++++++++- .../ETL/Tests/Unit/ETLErrorHandlingTest.php | 8 +- .../Exception/InvalidLogicExceptionTest.php | 6 - .../SchemaNotDerivableExceptionTest.php | 8 +- .../{Pipeline => Executor}/ClosureTest.php | 2 +- .../ETL/Tests/Unit/Executor/DescribedTest.php | 30 + .../DiscardableTest.php | 33 +- .../OffsetPipelineTest.php | 87 +- .../ETL/Tests/Unit/Executor/PipelineTest.php | 43 + .../Flow/ETL/Tests/Unit/Executor/RawTest.php | 55 ++ .../{Pipeline => Executor}/SegmentTest.php | 17 +- .../ETL/Tests/Unit/Executor/SegmentsTest.php | 199 +++++ .../ETL/Tests/Unit/Executor/SinkFeedTest.php | 230 +++++ .../Tests/Unit/Executor/SinkOffersTest.php | 87 ++ .../ETL/Tests/Unit/Executor/SinkRunTest.php | 142 +++ .../StatisticsCollectorTest.php | 53 +- .../Unit/Executor/TransactionRollbackTest.php | 38 + .../Unit/Executor/TransactionalSinksTest.php | 294 +++++++ .../WindowFunctionPipelineTest.php | 41 +- .../Flow/ETL/Tests/Unit/ExecutorTest.php | 478 ++++++++++ .../Unit/Extractor/ChainExtractorTest.php | 4 +- .../Unit/Extractor/DataFrameExtractorTest.php | 213 ++++- .../Tests/Unit/Extractor/FileColumnsTest.php | 27 + .../Tests/Unit/Extractor/FileReadingTest.php | 33 +- .../Unit/Extractor/FilesExtractorTest.php | 41 +- .../Tests/Unit/Extractor/PushesLimitTest.php | 43 - .../Unit/Extractor/RepeatabilityTest.php | 97 +++ .../Flow/ETL/Tests/Unit/FlowContextTest.php | 36 +- ...llFunctionsDeclareTheirDeterminismTest.php | 85 ++ .../Tests/Unit/Function/CallUserFuncTest.php | 5 + .../Unit/Function/ReferenceRenameTest.php | 45 + .../Unit/Function/ReferencedColumnsTest.php | 37 + .../ToDateTime/PatternCoverageTest.php | 44 + .../Tests/Unit/Function/ToDateTimeTest.php | 45 + .../ETL/Tests/Unit/Join/JoinStepsTest.php | 24 +- .../Tests/Unit/Loader/BranchingLoaderTest.php | 498 ----------- .../ETL/Tests/Unit/Loader/LoaderTreeTest.php | 72 -- .../ETL/Tests/Unit/Loader/RetryLoaderTest.php | 350 -------- .../Unit/Loader/TransformerLoaderTest.php | 555 ------------ .../Tests/Unit/Optimizer/FilterWalkTest.php | 330 +++++++ .../Tests/Unit/Optimizer/JoinSidesTest.php | 54 ++ .../Tests/Unit/Optimizer/LimitWalkTest.php | 72 ++ .../Unit/Optimizer/Rule/CombineLimitsTest.php | 51 ++ .../Rule/CombineSortAndLimitTest.php | 78 ++ .../Rule/PushFilterIntoSourceTest.php | 442 ++++++++++ .../Rule/PushLimitIntoSourceTest.php | 294 +++++++ .../Tests/Unit/Optimizer/TopNRewriteTest.php | 76 ++ .../Flow/ETL/Tests/Unit/OptimizerTest.php | 130 +++ .../Optimizer/LimitOptimizationTest.php | 194 ----- .../Tests/Unit/Pipeline/PlanBinderTest.php | 97 --- .../ETL/Tests/Unit/Pipeline/SegmentsTest.php | 347 -------- .../Pipeline/TransformationStreamTest.php | 197 ----- .../Tests/Unit/Plan/Explain/BoxLayoutTest.php | 170 ++++ .../Tests/Unit/Plan/Explain/BranchesTest.php | 33 + .../Tests/Unit/Plan/Explain/ConditionTest.php | 52 ++ .../Tests/Unit/Plan/Explain/DetailsTest.php | 193 ++++ .../ETL/Tests/Unit/Plan/Explain/EntryTest.php | 36 + .../Unit/Plan/Explain/FlowLayoutTest.php | 100 +++ .../Tests/Unit/Plan/Explain/OutlineTest.php | 95 ++ .../Unit/Plan/Explain/PhysicalOutlineTest.php | 106 +++ .../Unit/Plan/Explain/StepDetailsTest.php | 230 +++++ .../Unit/Plan/Explain/TreeLayoutTest.php | 249 ++++++ .../Flow/ETL/Tests/Unit/Plan/ExplainTest.php | 39 + .../ETL/Tests/Unit/Plan/LogicalPlanTest.php | 298 +++++++ .../Tests/Unit/Plan/Node/AggregateTest.php | 55 ++ .../ETL/Tests/Unit/Plan/Node/BatchByTest.php | 64 ++ .../ETL/Tests/Unit/Plan/Node/BatchTest.php | 59 ++ .../ETL/Tests/Unit/Plan/Node/CacheTest.php | 53 ++ .../Tests/Unit/Plan/Node/CollectRefsTest.php | 52 ++ .../ETL/Tests/Unit/Plan/Node/CollectTest.php | 48 + .../Tests/Unit/Plan/Node/ConstrainTest.php | 51 ++ .../Tests/Unit/Plan/Node/CrossJoinTest.php | 108 +++ .../ETL/Tests/Unit/Plan/Node/DiscardTest.php | 48 + .../ETL/Tests/Unit/Plan/Node/DistinctTest.php | 58 ++ .../ETL/Tests/Unit/Plan/Node/DropTest.php | 49 ++ .../Tests/Unit/Plan/Node/DuplicateRowTest.php | 55 ++ .../ETL/Tests/Unit/Plan/Node/FilterTest.php | 53 ++ .../ETL/Tests/Unit/Plan/Node/JoinEachTest.php | 69 ++ .../ETL/Tests/Unit/Plan/Node/JoinTest.php | 118 +++ .../ETL/Tests/Unit/Plan/Node/LimitTest.php | 58 ++ .../ETL/Tests/Unit/Plan/Node/OffsetTest.php | 59 ++ .../ETL/Tests/Unit/Plan/Node/OutputsTest.php | 132 +++ .../ETL/Tests/Unit/Plan/Node/ReadTest.php | 115 +++ .../Tests/Unit/Plan/Node/RenameEachTest.php | 60 ++ .../ETL/Tests/Unit/Plan/Node/RenameTest.php | 50 ++ .../Tests/Unit/Plan/Node/RepartitionTest.php | 52 ++ .../ETL/Tests/Unit/Plan/Node/ResultTest.php | 45 + .../ETL/Tests/Unit/Plan/Node/SelectTest.php | 49 ++ .../ETL/Tests/Unit/Plan/Node/SortTest.php | 56 ++ .../ETL/Tests/Unit/Plan/Node/TopNTest.php | 65 ++ .../Tests/Unit/Plan/Node/TransactionTest.php | 110 +++ .../Tests/Unit/Plan/Node/TransformTest.php | 51 ++ .../ETL/Tests/Unit/Plan/Node/UntilTest.php | 53 ++ .../ETL/Tests/Unit/Plan/Node/ValidateTest.php | 56 ++ .../Tests/Unit/Plan/Node/WindowColumnTest.php | 55 ++ .../Tests/Unit/Plan/Node/WithColumnTest.php | 102 +++ .../ETL/Tests/Unit/Plan/Node/WriteTest.php | 53 ++ .../ETL/Tests/Unit/Plan/RedefinedTest.php | 52 ++ .../ETL/Tests/Unit/Plan/ReplaceLeafTest.php | 27 + .../Flow/ETL/Tests/Unit/Plan/SinksTest.php | 52 ++ .../ETL/Tests/Unit/Plan/TransformUpTest.php | 110 +++ .../Flow/ETL/Tests/Unit/Plan/TriggerTest.php | 101 +++ .../tests/Flow/ETL/Tests/Unit/PlanTest.php | 106 +++ .../Tests/Unit/Planner/NodeTranslatorTest.php | 548 ++++++++++++ .../Tests/Unit/Planner/PipelineSplitTest.php | 670 ++++++++++++++ .../Tests/Unit/Planner/PlannedNodeTest.php | 28 + .../Tests/Unit/Planner/PlannedNodesTest.php | 64 ++ .../Tests/Unit/Planner/SinkAttachmentTest.php | 156 ++++ .../Unit/Planner/SinkFeedFactoryTest.php | 95 ++ .../tests/Flow/ETL/Tests/Unit/PlannerTest.php | 553 ++++++++++++ .../Unit/Processor/HashJoinProcessorTest.php | 61 +- .../Unit/Processor/TopNProcessorTest.php | 100 +++ .../Retry/DelayFactory/ExponentialTest.php | 66 -- .../Unit/Retry/DelayFactory/FixedTest.php | 34 - .../Unit/Retry/DelayFactory/JitterTest.php | 108 --- .../Unit/Retry/DelayFactory/LinearTest.php | 58 -- .../RetryStrategy/AnyThrowableExceptTest.php | 90 -- .../Retry/RetryStrategy/AnyThrowableTest.php | 69 -- .../RetryStrategy/OnExceptionTypesTest.php | 133 --- .../Flow/ETL/Tests/Unit/Sink/BranchedTest.php | 82 ++ .../ETL/Tests/Unit/Sink/TransactionalTest.php | 226 +++++ .../ETL/Tests/Unit/Sink/TransformedTest.php | 111 +++ .../Flow/ETL/Tests/Unit/Time/DurationTest.php | 111 --- .../ETL/Tests/Unit/Time/FakeSleepTest.php | 96 -- .../AddRowIndexTransformerTest.php | 18 + .../CrossJoinRowsTransformerTest.php | 33 +- .../Floe/Tests/Unit/FloeExtractorTest.php | 52 +- .../codemirror/completions/dataframe.js | 64 +- .../assets/codemirror/completions/dsl.js | 215 +---- .../completions/scalarfunctionchain.js | 23 +- web/landing/assets/wasm/tools/flow.phar | Bin 3889012 -> 3932617 bytes .../topics/errors/throw/documentation.md | 1 - .../examples/topics/joins/join_each/code.php | 2 +- .../partition_placeholders/description.md | 2 +- .../partitioning/partition_pruning/code.php | 2 +- .../partition_pruning/description.md | 2 +- .../writing/postgresql/transaction/code.php | 2 +- .../postgresql/transaction/description.md | 6 +- web/landing/resources/api.json | 2 +- web/landing/resources/dsl.json | 2 +- 528 files changed, 23602 insertions(+), 8477 deletions(-) delete mode 100644 documentation/components/core/retry.md create mode 100644 src/adapter/etl-adapter-avro/tests/Flow/ETL/Adapter/Avro/Tests/Unit/FlixTech/AvroExtractorTest.php create mode 100644 src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/DbalTransaction.php create mode 100644 src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/IsolationLevelRestore.php delete mode 100644 src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/TransactionalDbalLoader.php create mode 100644 src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Context/CommitCounter.php rename src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/{MySQLTransactionalDbalLoaderTest.php => MySQLTransactionSinkTest.php} (66%) rename src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/{PostgreSQLTransactionalDbalLoaderTest.php => PostgreSQLTransactionSinkTest.php} (66%) rename src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/{SqliteTransactionalDbalLoaderTest.php => SqliteTransactionSinkTest.php} (66%) rename src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/{TransactionalDbalLoaderTransformationTest.php => DbalTransactionSinkTest.php} (76%) create mode 100644 src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/DbalTransactionTest.php create mode 100644 src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/IsolationLevelRestoreTest.php delete mode 100644 src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/TransactionalDbalLoaderTest.php create mode 100644 src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/PostgreSqlTransaction.php delete mode 100644 src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/TransactionalPostgreSqlLoader.php create mode 100644 src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Context/TableRowsContext.php create mode 100644 src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Integration/PostgreSqlTransactionSinkTest.php delete mode 100644 src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Integration/TransactionalPostgreSqlLoaderIntegrationTest.php delete mode 100644 src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Integration/TransactionalPostgreSqlLoaderTransformationIntegrationTest.php create mode 100644 src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/PostgreSqlTransactionTest.php delete mode 100644 src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/TransactionalPostgreSqlLoaderTest.php create mode 100644 src/cli/src/Flow/CLI/Loader/ProgressBarLoader.php create mode 100644 src/cli/tests/Flow/CLI/Tests/Unit/Loader/ProgressBarLoaderTest.php rename src/core/etl/src/Flow/ETL/{Pipeline => }/BoundStep.php (64%) delete mode 100644 src/core/etl/src/Flow/ETL/Exception/FailedRetryException.php create mode 100644 src/core/etl/src/Flow/ETL/Exception/SinkFailure.php create mode 100644 src/core/etl/src/Flow/ETL/Exception/TransactionRolledBack.php create mode 100644 src/core/etl/src/Flow/ETL/Executor.php create mode 100644 src/core/etl/src/Flow/ETL/Executor/Described.php create mode 100644 src/core/etl/src/Flow/ETL/Executor/PhysicalPlan.php create mode 100644 src/core/etl/src/Flow/ETL/Executor/Pipeline.php create mode 100644 src/core/etl/src/Flow/ETL/Executor/Raw.php rename src/core/etl/src/Flow/ETL/{Pipeline => Executor}/Segment.php (83%) create mode 100644 src/core/etl/src/Flow/ETL/Executor/Segments.php create mode 100644 src/core/etl/src/Flow/ETL/Executor/SinkFeed.php create mode 100644 src/core/etl/src/Flow/ETL/Executor/SinkOffers.php create mode 100644 src/core/etl/src/Flow/ETL/Executor/SinkRun.php rename src/core/etl/src/Flow/ETL/{Execution => Executor}/StatisticsCollector.php (90%) create mode 100644 src/core/etl/src/Flow/ETL/Executor/TransactionRollback.php create mode 100644 src/core/etl/src/Flow/ETL/Executor/TransactionalSinks.php delete mode 100644 src/core/etl/src/Flow/ETL/Extractor/LimitPushDown.php create mode 100644 src/core/etl/src/Flow/ETL/Extractor/ListingPartitions.php delete mode 100644 src/core/etl/src/Flow/ETL/Extractor/PushesLimit.php create mode 100644 src/core/etl/src/Flow/ETL/Function/ReferenceRename.php create mode 100644 src/core/etl/src/Flow/ETL/Function/ReferencedColumns.php create mode 100644 src/core/etl/src/Flow/ETL/Function/ToDateTime/PatternCoverage.php delete mode 100644 src/core/etl/src/Flow/ETL/Loader/BranchingLoader.php delete mode 100644 src/core/etl/src/Flow/ETL/Loader/LoaderTree.php delete mode 100644 src/core/etl/src/Flow/ETL/Loader/OverridingLoader.php delete mode 100644 src/core/etl/src/Flow/ETL/Loader/ReplayAware.php delete mode 100644 src/core/etl/src/Flow/ETL/Loader/RetryLoader.php delete mode 100644 src/core/etl/src/Flow/ETL/Loader/TransformerLoader.php create mode 100644 src/core/etl/src/Flow/ETL/Optimizer.php create mode 100644 src/core/etl/src/Flow/ETL/Optimizer/FilterWalk.php create mode 100644 src/core/etl/src/Flow/ETL/Optimizer/JoinSides.php create mode 100644 src/core/etl/src/Flow/ETL/Optimizer/LimitWalk.php create mode 100644 src/core/etl/src/Flow/ETL/Optimizer/Rule.php create mode 100644 src/core/etl/src/Flow/ETL/Optimizer/Rule/CombineLimits.php create mode 100644 src/core/etl/src/Flow/ETL/Optimizer/Rule/CombineSortAndLimit.php create mode 100644 src/core/etl/src/Flow/ETL/Optimizer/Rule/PushFilterIntoSource.php create mode 100644 src/core/etl/src/Flow/ETL/Optimizer/Rule/PushLimitIntoSource.php create mode 100644 src/core/etl/src/Flow/ETL/Optimizer/TopNRewrite.php delete mode 100644 src/core/etl/src/Flow/ETL/Pipeline.php delete mode 100644 src/core/etl/src/Flow/ETL/Pipeline/BoundPlan.php delete mode 100644 src/core/etl/src/Flow/ETL/Pipeline/Optimizer.php delete mode 100644 src/core/etl/src/Flow/ETL/Pipeline/Optimizer/LimitOptimization.php delete mode 100644 src/core/etl/src/Flow/ETL/Pipeline/Optimizer/Optimization.php delete mode 100644 src/core/etl/src/Flow/ETL/Pipeline/PlanBinder.php delete mode 100644 src/core/etl/src/Flow/ETL/Pipeline/Segments.php delete mode 100644 src/core/etl/src/Flow/ETL/Pipeline/TransformationStream.php create mode 100644 src/core/etl/src/Flow/ETL/Plan.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Explain.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Explain/BoxLayout.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Explain/Branches.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Explain/Condition.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Explain/Details.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Explain/Entry.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Explain/FlowLayout.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Explain/Layout.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Explain/Outline.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Explain/PhysicalOutline.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Explain/StepDetails.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Explain/TreeLayout.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Format.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/LogicalPlan.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Materialization.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Node.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Node/Aggregate.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Node/Batch.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Node/BatchBy.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Node/Cache.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Node/Collect.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Node/CollectRefs.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Node/Constrain.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Node/CrossJoin.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Node/Discard.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Node/Distinct.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Node/Drop.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Node/DuplicateRow.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Node/Filter.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Node/Join.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Node/JoinEach.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Node/JoinsFrame.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Node/Limit.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Node/Offset.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Node/Outputs.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Node/Read.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Node/Rename.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Node/RenameEach.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Node/Repartition.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Node/Result.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Node/Select.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Node/Sort.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Node/TopN.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Node/Transaction.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Node/Transform.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Node/Until.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Node/Validate.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Node/WindowColumn.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Node/WithColumn.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Node/Write.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Redefined.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/ReplaceLeaf.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Rewrite.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/RowCount.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Sinks.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Stage.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/TransformUp.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Transparency.php create mode 100644 src/core/etl/src/Flow/ETL/Plan/Trigger.php create mode 100644 src/core/etl/src/Flow/ETL/Planner.php create mode 100644 src/core/etl/src/Flow/ETL/Planner/NodeTranslator.php create mode 100644 src/core/etl/src/Flow/ETL/Planner/PipelineSplit.php create mode 100644 src/core/etl/src/Flow/ETL/Planner/PlannedNode.php create mode 100644 src/core/etl/src/Flow/ETL/Planner/PlannedNodes.php create mode 100644 src/core/etl/src/Flow/ETL/Planner/SinkAttachment.php create mode 100644 src/core/etl/src/Flow/ETL/Planner/SinkFeedFactory.php create mode 100644 src/core/etl/src/Flow/ETL/Processor/TopNProcessor.php delete mode 100644 src/core/etl/src/Flow/ETL/Retry/DelayFactory.php delete mode 100644 src/core/etl/src/Flow/ETL/Retry/DelayFactory/Exponential.php delete mode 100644 src/core/etl/src/Flow/ETL/Retry/DelayFactory/Fixed.php delete mode 100644 src/core/etl/src/Flow/ETL/Retry/DelayFactory/Fixed/FixedMilliseconds.php delete mode 100644 src/core/etl/src/Flow/ETL/Retry/DelayFactory/Jitter.php delete mode 100644 src/core/etl/src/Flow/ETL/Retry/DelayFactory/Linear.php delete mode 100644 src/core/etl/src/Flow/ETL/Retry/FailedRetry.php delete mode 100644 src/core/etl/src/Flow/ETL/Retry/RetriesRecord.php delete mode 100644 src/core/etl/src/Flow/ETL/Retry/RetryStrategy.php delete mode 100644 src/core/etl/src/Flow/ETL/Retry/RetryStrategy/AnyThrowable.php delete mode 100644 src/core/etl/src/Flow/ETL/Retry/RetryStrategy/AnyThrowableExcept.php delete mode 100644 src/core/etl/src/Flow/ETL/Retry/RetryStrategy/OnExceptionTypes.php create mode 100644 src/core/etl/src/Flow/ETL/Sink.php create mode 100644 src/core/etl/src/Flow/ETL/Sink/Branched.php create mode 100644 src/core/etl/src/Flow/ETL/Sink/Transactional.php create mode 100644 src/core/etl/src/Flow/ETL/Sink/Transformed.php delete mode 100644 src/core/etl/src/Flow/ETL/Time/Duration.php delete mode 100644 src/core/etl/src/Flow/ETL/Time/FakeSleep.php delete mode 100644 src/core/etl/src/Flow/ETL/Time/Sleep.php delete mode 100644 src/core/etl/src/Flow/ETL/Time/SystemSleep.php create mode 100644 src/core/etl/src/Flow/ETL/Transaction.php create mode 100644 src/core/etl/src/Flow/ETL/Transformer/Stateful.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Context/ExecutedPlan.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Context/ExecutedSegments.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Context/PipelineSteps.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Context/ScoredRows.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Double/CallOrderLoader.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Double/ChildlessNode.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Double/ContextRecordingTransformer.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Double/FanOutSink.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Double/FixedRandomValueGenerator.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Double/PassThroughProcessor.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Double/PlanDrainingTransformer.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Double/PropagatingTransformationsSkippingLoaders.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Double/RecordingExtractor.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Double/RecordingFileExtractor.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Double/RecordingLoader.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Double/RecordingRule.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Double/RecordingTransaction.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Double/RedefiningNode.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Double/RenameSelectRewrite.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Double/SpineCopyingRule.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Double/SpySink.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Double/SpyTransformer.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Double/WrappingLoader.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Fixtures/Join/AlwaysMeets.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Fixtures/orders.csv create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Fixtures/sellers.csv create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/PerRunPlanTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/SinglePlanTest.php rename src/core/etl/tests/Flow/ETL/Tests/Integration/{Loader/TransformerLoaderBlockingOperationsTest.php => DataFrame/SinkRootBlockingOperationsTest.php} (83%) create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/SinkRootTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/TriggerPlanTest.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/RetryLoaderTest.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/TransformerLoaderTest.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Integration/Pipeline/OptimizerTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Mother/EntryMother.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Mother/NodeMother.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Mother/PartitionedSourceMother.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Mother/PhysicalPlanMother.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Mother/SinkAttachmentMother.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Mother/SinkFeedMother.php rename src/core/etl/tests/Flow/ETL/Tests/Unit/{Pipeline => Executor}/ClosureTest.php (96%) create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/DescribedTest.php rename src/core/etl/tests/Flow/ETL/Tests/Unit/{Pipeline => Executor}/DiscardableTest.php (78%) rename src/core/etl/tests/Flow/ETL/Tests/Unit/{Pipeline => Executor}/OffsetPipelineTest.php (73%) create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/PipelineTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/RawTest.php rename src/core/etl/tests/Flow/ETL/Tests/Unit/{Pipeline => Executor}/SegmentTest.php (93%) create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/SegmentsTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/SinkFeedTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/SinkOffersTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/SinkRunTest.php rename src/core/etl/tests/Flow/ETL/Tests/Unit/{Execution => Executor}/StatisticsCollectorTest.php (77%) create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/TransactionRollbackTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/TransactionalSinksTest.php rename src/core/etl/tests/Flow/ETL/Tests/Unit/{Pipeline => Executor}/WindowFunctionPipelineTest.php (77%) create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/ExecutorTest.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/PushesLimitTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AllFunctionsDeclareTheirDeterminismTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ReferenceRenameTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ReferencedColumnsTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ToDateTime/PatternCoverageTest.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/BranchingLoaderTest.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/LoaderTreeTest.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/RetryLoaderTest.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/TransformerLoaderTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/FilterWalkTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/JoinSidesTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/LimitWalkTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/Rule/CombineLimitsTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/Rule/CombineSortAndLimitTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/Rule/PushFilterIntoSourceTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/Rule/PushLimitIntoSourceTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/TopNRewriteTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/OptimizerTest.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Pipeline/Optimizer/LimitOptimizationTest.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Pipeline/PlanBinderTest.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Pipeline/SegmentsTest.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Pipeline/TransformationStreamTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Explain/BoxLayoutTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Explain/BranchesTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Explain/ConditionTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Explain/DetailsTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Explain/EntryTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Explain/FlowLayoutTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Explain/OutlineTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Explain/PhysicalOutlineTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Explain/StepDetailsTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Explain/TreeLayoutTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/ExplainTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/LogicalPlanTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/AggregateTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/BatchByTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/BatchTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/CacheTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/CollectRefsTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/CollectTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/ConstrainTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/CrossJoinTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/DiscardTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/DistinctTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/DropTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/DuplicateRowTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/FilterTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/JoinEachTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/JoinTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/LimitTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/OffsetTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/OutputsTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/ReadTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/RenameEachTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/RenameTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/RepartitionTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/ResultTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/SelectTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/SortTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/TopNTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/TransactionTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/TransformTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/UntilTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/ValidateTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/WindowColumnTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/WithColumnTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/WriteTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/RedefinedTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/ReplaceLeafTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/SinksTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/TransformUpTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/TriggerTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/PlanTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Planner/NodeTranslatorTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Planner/PipelineSplitTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Planner/PlannedNodeTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Planner/PlannedNodesTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Planner/SinkAttachmentTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Planner/SinkFeedFactoryTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/PlannerTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/TopNProcessorTest.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Retry/DelayFactory/ExponentialTest.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Retry/DelayFactory/FixedTest.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Retry/DelayFactory/JitterTest.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Retry/DelayFactory/LinearTest.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Retry/RetryStrategy/AnyThrowableExceptTest.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Retry/RetryStrategy/AnyThrowableTest.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Retry/RetryStrategy/OnExceptionTypesTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Sink/BranchedTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Sink/TransactionalTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Sink/TransformedTest.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Time/DurationTest.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Time/FakeSleepTest.php diff --git a/benchmarks/src/Partitioning/PartitionedReadScenario.php b/benchmarks/src/Partitioning/PartitionedReadScenario.php index e2bbd355f0..86ff133c75 100644 --- a/benchmarks/src/Partitioning/PartitionedReadScenario.php +++ b/benchmarks/src/Partitioning/PartitionedReadScenario.php @@ -27,12 +27,12 @@ public function run(): int $frame = data_frame(BenchmarkConfig::builder())->read(from_csv($tree->glob())); if ($this->pruned) { - $frame = $frame->filterPartitions(ref($this->cardinality->column())->equals(lit($tree->firstValue()))); + $frame = $frame->filter(ref($this->cardinality->column())->equals(lit($tree->firstValue()))); } $rows = 0; - $frame->run(static function (Rows $batch) use (&$rows): void { + $frame->forEach(static function (Rows $batch) use (&$rows): void { $rows += $batch->count(); }); diff --git a/benchmarks/src/Partitioning/PartitionedTree.php b/benchmarks/src/Partitioning/PartitionedTree.php index facf071da2..4cf0492f4f 100644 --- a/benchmarks/src/Partitioning/PartitionedTree.php +++ b/benchmarks/src/Partitioning/PartitionedTree.php @@ -23,7 +23,7 @@ * every phpbench iteration rebuild the whole tree before it could measure a read. * * The read path must be a glob. from_csv() over a bare partitioned directory silently reads 0 rows, - * and a following filterPartitions() then throws "Column ... does not exist." from Row.php. + * and a following partition filter() then fails at bind: "Schema definition for entry ... not found." */ final class PartitionedTree { diff --git a/benchmarks/src/Pipeline/PlanDepthScenario.php b/benchmarks/src/Pipeline/PlanDepthScenario.php index dd4807092f..681f3644f3 100644 --- a/benchmarks/src/Pipeline/PlanDepthScenario.php +++ b/benchmarks/src/Pipeline/PlanDepthScenario.php @@ -12,10 +12,10 @@ use function Flow\ETL\DSL\ref; /** - * schema() answers from the plan without executing it, so this prices PlanBinder::bind() alone rather - * than $depth withEntry calls per row. + * schema() answers from the plan without executing it, so this prices Planner::plan() alone (optimize, translate, + * bind, split) rather than $depth withEntry calls per row. * - * One call binds PLANS identical plans, because a single bind is far below timer resolution. + * One call plans PLANS identical plans, because a single plan is far below timer resolution. */ final readonly class PlanDepthScenario { diff --git a/benchmarks/src/Service/Doctrine/DoctrineWrappedWriteScenario.php b/benchmarks/src/Service/Doctrine/DoctrineWrappedWriteScenario.php index fa3017dc1f..1fb8efae84 100644 --- a/benchmarks/src/Service/Doctrine/DoctrineWrappedWriteScenario.php +++ b/benchmarks/src/Service/Doctrine/DoctrineWrappedWriteScenario.php @@ -8,7 +8,6 @@ use function Flow\ETL\Adapter\Doctrine\to_dbal_table_insert; use function Flow\ETL\DSL\data_frame; -use function Flow\ETL\DSL\write_with_retries; use function Flow\Floe\DSL\from_floe; final readonly class DoctrineWrappedWriteScenario @@ -39,7 +38,7 @@ public function run(): void data_frame() ->read(from_floe(Datasets::orders($this->rows)->floe())) ->batchSize(1000) - ->write(write_with_retries(to_dbal_table_insert($connection, $this->table()))) + ->write(to_dbal_table_insert($connection, $this->table())) ->run(); $connection->close(); diff --git a/benchmarks/src/Transformation/NestedTransformationScenario.php b/benchmarks/src/Transformation/NestedTransformationScenario.php index e6ae958de5..304c42f86b 100644 --- a/benchmarks/src/Transformation/NestedTransformationScenario.php +++ b/benchmarks/src/Transformation/NestedTransformationScenario.php @@ -7,6 +7,7 @@ use Flow\Benchmarks\BenchmarkConfig; use Flow\Benchmarks\Datasets\Datasets; use Flow\ETL\Loader; +use Flow\ETL\Sink; use function Flow\ETL\DSL\data_frame; use function Flow\Floe\DSL\from_floe; @@ -15,7 +16,7 @@ { public function __construct( private int $rows, - private Loader $loader, + private Loader|Sink $sink, ) {} public function run(): void @@ -23,7 +24,7 @@ public function run(): void data_frame(BenchmarkConfig::builder()) ->read(from_floe(Datasets::orders($this->rows)->floe())) ->batchSize(1000) - ->write($this->loader) + ->write($this->sink) ->run(); } } diff --git a/benchmarks/suites/Transformation/NestedTransformationBench.php b/benchmarks/suites/Transformation/NestedTransformationBench.php index f4dfa1fedc..f194ecf5bc 100644 --- a/benchmarks/suites/Transformation/NestedTransformationBench.php +++ b/benchmarks/suites/Transformation/NestedTransformationBench.php @@ -22,31 +22,40 @@ public function warm(array $params): void Datasets::orders((int) $params['rows'])->floe(); } + #[Bench\ParamProviders('rows')] + #[Bench\Groups(['transformation'])] + public function bench_bare_branch(array $params): void + { + $sink = to_branch(ref('order_id')->isNotNull(), new NoopLoader()); + + (new NestedTransformationScenario((int) $params['rows'], $sink))->run(); + } + #[Bench\ParamProviders('rows')] #[Bench\Groups(['transformation'])] public function bench_blocking_transformation(array $params): void { - $loader = to_transformation(new SortByCreatedAt(), new NoopLoader()); + $sink = to_transformation(new SortByCreatedAt(), new NoopLoader()); - (new NestedTransformationScenario((int) $params['rows'], $loader))->run(); + (new NestedTransformationScenario((int) $params['rows'], $sink))->run(); } #[Bench\ParamProviders('rows')] #[Bench\Groups(['transformation'])] public function bench_branch_with_transformation(array $params): void { - $loader = to_branch(ref('order_id')->isNotNull(), new NoopLoader())->withTransformation(new SortByCreatedAt()); + $sink = to_branch(ref('order_id')->isNotNull(), new NoopLoader())->withTransformation(new SortByCreatedAt()); - (new NestedTransformationScenario((int) $params['rows'], $loader))->run(); + (new NestedTransformationScenario((int) $params['rows'], $sink))->run(); } #[Bench\ParamProviders('rows')] #[Bench\Groups(['transformation'])] public function bench_streaming_transformation(array $params): void { - $loader = to_transformation(select('order_id'), new NoopLoader()); + $sink = to_transformation(select('order_id'), new NoopLoader()); - (new NestedTransformationScenario((int) $params['rows'], $loader))->run(); + (new NestedTransformationScenario((int) $params['rows'], $sink))->run(); } public function rows(): Generator diff --git a/documentation/components/adapters/doctrine.md b/documentation/components/adapters/doctrine.md index 90aa3bea9a..f2830d4353 100644 --- a/documentation/components/adapters/doctrine.md +++ b/documentation/components/adapters/doctrine.md @@ -123,8 +123,8 @@ data_frame() ## Transactional Loading -`to_dbal_transaction()` wraps one or more loaders so every delivery happens inside a transaction: each batch of rows -is loaded in its own transaction, and if any loader throws, the open transaction is rolled back: +`to_dbal_transaction()` writes one or more sinks inside transactions: each batch of rows is written in its own +transaction, and if any sink throws, the open transaction is rolled back: ```php use function Flow\ETL\DSL\{data_frame, from_array}; @@ -140,29 +140,32 @@ data_frame() ->run(); ``` -Atomicity requires every wrapped loader to use the same connection as the wrapper - pass one live `Connection` to -`to_dbal_transaction()` and to every wrapped loader. A loader built from array params (like +A plain loader child is a bare sink root; a `to_transformation(...)` child delivers inside the same transaction. +Every child's loader must use the same connection as the transaction - pass one live `Connection` to +`to_dbal_transaction()` and to every child. A loader built from array params (like `to_dbal_table_insert(['url' => $url], 'users')`) opens its own connection and escapes the transaction. -Wrapped `to_transformation()` / `to_branch(...)->withTransformation(...)` steps with blocking operations (`sortBy()`, +Sinks with blocking operations (`to_transformation()` / `to_branch(...)->withTransformation(...)` with `sortBy()`, `aggregate()`, `groupBy()->aggregate()`, `pivot()`, window functions, `collect()`, `join()` - see -[transformations](../core/transformations.md)) buffer the stream and deliver it when the pipeline closes the loader; +[transformations](../core/transformations.md)) buffer the stream and deliver it when the run ends; `to_dbal_transaction()` opens one final transaction around that delivery - the whole drained stream commits -atomically, a failure during it rolls back. +atomically, a failure during it rolls back and surfaces from `run()`. -Do not place `write_with_retries()` inside the wrapper: on databases that abort the transaction after a failed -statement (PostgreSQL), every retry attempt fails too. Wrap the transaction instead - -`write_with_retries(to_dbal_transaction(...))` gives each attempt a fresh transaction (see -[retry](../core/retry.md)). +Inside the transaction every sink runs throw-only: a failure rolls the batch back first, and only then the frame's +`onError()` handler decides whether the run continues. -Use `withIsolationLevel()` to set the transaction isolation level; it applies to every transaction the wrapper opens, -including the final one: +To set the isolation level, build the transaction yourself; it applies to every transaction opened, including the +final one, and the previous level is restored when each one ends: ```php use Doctrine\DBAL\TransactionIsolationLevel; +use Flow\ETL\Adapter\Doctrine\DbalTransaction; +use Flow\ETL\Sink\Transactional; -to_dbal_transaction($connection, to_dbal_table_insert($connection, 'users')) - ->withIsolationLevel(TransactionIsolationLevel::SERIALIZABLE); +new Transactional( + DbalTransaction::fromConnection($connection)->withIsolationLevel(TransactionIsolationLevel::SERIALIZABLE), + to_dbal_table_insert($connection, 'users'), +); ``` ## Extractor - DbalQuery diff --git a/documentation/components/adapters/postgresql.md b/documentation/components/adapters/postgresql.md index b173e67fe6..639a1ef91f 100644 --- a/documentation/components/adapters/postgresql.md +++ b/documentation/components/adapters/postgresql.md @@ -390,12 +390,10 @@ df() ### Transactional Loading -`to_pgsql_transaction()` wraps one or more loaders so every delivery happens inside a transaction: each batch of rows -is loaded in its own transaction, and if any loader throws, the open transaction is rolled back: +`to_pgsql_transaction()` writes one or more sinks inside transactions: each batch of rows is written in its own +transaction, and if any sink throws, the open transaction is rolled back: ```php -use Flow\PostgreSql\QueryBuilder\Transaction\IsolationLevel; - use function Flow\ETL\Adapter\PostgreSql\{to_pgsql_table, to_pgsql_transaction}; df() @@ -408,24 +406,29 @@ df() ->run(); ``` -Wrapped `to_transformation()` / `to_branch(...)->withTransformation(...)` steps with blocking operations (`sortBy()`, +Sinks with blocking operations (`to_transformation()` / `to_branch(...)->withTransformation(...)` with `sortBy()`, `aggregate()`, `groupBy()->aggregate()`, `pivot()`, window functions, `collect()`, `join()` - see -[transformations](../core/transformations.md)) buffer the stream and deliver it when the pipeline closes the loader; +[transformations](../core/transformations.md)) buffer the stream and deliver it when the run ends; `to_pgsql_transaction()` opens one final transaction around that delivery - the whole drained stream commits -atomically, a failure during it rolls back. Every wrapped loader must use the same `Client` instance as the wrapper - -a loader holding its own `Client` escapes the transaction. +atomically, a failure during it rolls back and surfaces from `run()`. A plain loader child is a bare sink root; a +`to_transformation(...)` child delivers inside the same transaction. Every sink's loader must use the same `Client` +instance as the transaction - a loader holding its own `Client` escapes it. -Do not place `write_with_retries()` inside the wrapper: after a failed statement PostgreSQL aborts the whole -transaction, so every retry attempt fails too. Wrap the transaction instead - -`write_with_retries(to_pgsql_transaction(...))` gives each attempt a fresh transaction (see -[retry](../core/retry.md)). +Inside the transaction every sink runs throw-only: a failure rolls the batch back first, and only then the frame's +`onError()` handler decides whether the run continues. -Use `withIsolationLevel()` to set the transaction isolation level; it applies to every transaction the wrapper opens, -including the final one: +To set the isolation level, build the transaction yourself; it applies to every transaction opened, including the +final one: ```php -to_pgsql_transaction($client, to_pgsql_table($client, 'users')) - ->withIsolationLevel(IsolationLevel::SERIALIZABLE); +use Flow\ETL\Adapter\PostgreSql\PostgreSqlTransaction; +use Flow\ETL\Sink\Transactional; +use Flow\PostgreSql\QueryBuilder\Transaction\IsolationLevel; + +new Transactional( + (new PostgreSqlTransaction($client))->withIsolationLevel(IsolationLevel::SERIALIZABLE), + to_pgsql_table($client, 'users'), +); ``` ## Loader DSL Functions Reference @@ -433,7 +436,7 @@ to_pgsql_transaction($client, to_pgsql_table($client, 'users')) | Function | Description | |------------------------------------------------|-----------------------------------------------------------| | `to_pgsql_table($client, $table)` | Create a PostgreSQL loader for a table | -| `to_pgsql_transaction($client, ...$loaders)` | Run multiple loaders, every delivery inside a transaction | +| `to_pgsql_transaction($client, ...$sinks)` | Write sinks, every delivery inside a transaction | | `pgsql_insert_options(...)` | Configure insert behavior (conflicts, upsert) | | `pgsql_update_options($primaryKeys)` | Configure update behavior (primary key columns) | | `pgsql_delete_options($primaryKeys)` | Configure delete behavior (primary key columns) | @@ -502,16 +505,16 @@ $schema = schema( ); ``` -| Metadata | Effect on the generated column | -|-----------------------------------|------------------------------------------------------------| -| `PostgreSqlMetadata::type($name)` | Force a specific PostgreSQL type, bypassing the type map | -| `PostgreSqlMetadata::length($n)` | Emit `varchar($n)` | -| `PostgreSqlMetadata::precision($p)` / `::scale($s)` | Emit `numeric($p, $s)` | -| `PostgreSqlMetadata::default($v)` | Set a column `DEFAULT` | -| `PostgreSqlMetadata::primaryKey($name)` | Include the column in the table primary key | +| Metadata | Effect on the generated column | +|-----------------------------------------------------|---------------------------------------------------------------------------------------| +| `PostgreSqlMetadata::type($name)` | Force a specific PostgreSQL type, bypassing the type map | +| `PostgreSqlMetadata::length($n)` | Emit `varchar($n)` | +| `PostgreSqlMetadata::precision($p)` / `::scale($s)` | Emit `numeric($p, $s)` | +| `PostgreSqlMetadata::default($v)` | Set a column `DEFAULT` | +| `PostgreSqlMetadata::primaryKey($name)` | Include the column in the table primary key | | `PostgreSqlMetadata::indexUnique($name, $position)` | Include the column in a named `UNIQUE` constraint, optionally at an explicit position | -| `PostgreSqlMetadata::index($name, $position)` | Include the column in a named index, optionally at an explicit position | -| `PostgreSqlMetadata::identity($generation)` | Make the column an identity column | +| `PostgreSqlMetadata::index($name, $position)` | Include the column in a named index, optionally at an explicit position | +| `PostgreSqlMetadata::identity($generation)` | Make the column an identity column | | `PostgreSqlMetadata::generated($expr)` | Make the column a generated column | Columns sharing the same primary key, unique constraint, or index name are grouped together, so composite keys are diff --git a/documentation/components/core/core.md b/documentation/components/core/core.md index bf44d645bd..4835c72fc9 100644 --- a/documentation/components/core/core.md +++ b/documentation/components/core/core.md @@ -42,7 +42,149 @@ These methods execute the entire pipeline and return results: - **Output operations**: `run()`, `forEach()`, `printRows()` - **Schema inspection**: `display()` -`schema()` and `printSchema()` are **not** triggers - they answer from the plan without reading a row. +`schema()`, `printSchema()` and `explain()` are **not** triggers - they answer from the plan without reading a row. +`explain()` returns the frame's `Plan`. Its `toString()` prints the plan after the configured optimizer ran, as a +tree read from the bottom up: a node's children are where its rows come from, and nodes are numbered in the order +rows reach them - the source is `#1`. What a node does is listed under it. + +The verbs build a plan with no consumer on top; **the trigger adds the one it needs**, so `explain()` takes the +trigger it should print - `Trigger::rows` by default, `Trigger::run` for the plan `run()` executes. + +```php +echo data_frame() + ->read(from_csv('orders.csv')) + ->filter(ref('email')->isNotNull()) + ->write(to_json('out.json')) + ->explain()->toString(); +``` + +```text +Outputs +├─ #3 Result +│ │ Rows this plan hands out: to the trigger, or to the node reading it +│ └─ #2 Filter +│ │ Condition: IsNotNull +│ └─ #1 Read +│ Extractor: CSVExtractor +└─ #4 Write + │ Loader: JsonLoader + └─ #2 Filter (shared) +``` + +```php +echo $dataFrame->explain(Trigger::run)->toString(); +``` + +```text +#3 Write +│ Loader: JsonLoader +└─ #2 Filter + │ Condition: IsNotNull + └─ #1 Read + Extractor: CSVExtractor +``` + +`run()` takes no rows, so its plan carries only the sinks - the `Write` is the root and there is no `Result`. A +`Result` comes back only when a verb follows the last `write()`: nothing would read that chain end, so one is put on +it to pull the rows, and `run(analyze: ...)` still counts them. + +`Outputs` lists everything the frame produces: `Result` is what a rows-returning trigger reads, `Write` is the sink, +and both read the same rows. A node several consumers read is printed once, and every other consumer points back at it by +number - `#2 Filter (shared)` is that same filter, not a second one. A node keeps its number in every format. +A frame joined with `join()` / `crossJoin()` is part of the same tree: the join reads it the way it reads any other +input, numbered with the rest of the plan, and it runs with this frame's configuration. A frame read with +`from_data_frame()` is a `Read` of `DataFrameExtractor` and runs with its own. + +`toString()` takes the stage and the format to print: + +| Argument | Prints | +|------------------------------|-------------------------------------------------------------------------------------| +| `Stage::optimized` (default) | the plan the optimizer hands to the planner | +| `Stage::unoptimized` | the plan as the frame built it | +| `Stage::physical` | the plan the executor runs: pipelines, their steps, and every setting each was given | +| `Format::tree` (default) | the tree above: every node above the nodes it reads | +| `Format::flow` | the same tree turned around: sources first, every node above the nodes that read it | +| `Format::boxes` | a box per node, children side by side | +| `Format::declarations` | the tree with the declarations optimizer rules read on every node's line | + +```php +echo $dataFrame->explain()->toString(format: Format::flow); +``` + +```text +#1 Read +│ Extractor: CSVExtractor +└─ #2 Filter + │ Condition: IsNotNull + ├─ #3 Result + │ Rows this plan hands out: to the trigger, or to the node reading it + └─ #4 Write + Loader: JsonLoader +``` + +```php +echo $dataFrame->explain()->toString(format: Format::boxes); +``` + +```text +┌───────────────────────────┐ +│ Outputs ├──────────────┐ +└─────────────┬─────────────┘ │ +┌─────────────┴─────────────┐┌─────────────┴─────────────┐ +│ #3 Result ││ #4 Write │ +│ ──────────────────── ││ ──────────────────── │ +│ Rows this plan hands out: ││ Loader: JsonLoader │ +│ to the trigger, or to the ││ │ +│ node reading it ││ │ +└─────────────┬─────────────┘└─────────────┬─────────────┘ +┌─────────────┴─────────────┐┌─────────────┴─────────────┐ +│ #2 Filter ││ #2 Filter │ +│ ──────────────────── ││ (shared) │ +│ Condition: IsNotNull ││ │ +└─────────────┬─────────────┘└───────────────────────────┘ +┌─────────────┴─────────────┐ +│ #1 Read │ +│ ──────────────────── │ +│ Extractor: CSVExtractor │ +└───────────────────────────┘ +``` + +`Stage::physical` prints what the executor runs. A pipeline ends where a blocking step cuts it, so the pipeline a +step sits in is where rows stop flowing through, and every step lists the settings it was given - the algorithm's +storage among them, which the logical stages cannot know because the planner picks it. + +```php +echo data_frame() + ->read(from_array($users)) + ->join(data_frame()->read(from_array($emails)), join_on(['id' => 'id'], join_prefix: 'joined_'), Join::left) + ->collect() + ->write(to_output(truncate: false)) + ->explain()->toString(Stage::physical); +``` + +```text +Physical plan +│ Schema: derived +└─ Pipeline #1 + │ Processor: CollectingProcessor + │ Schema: declared + │ Loader: StreamLoader + └─ Pipeline #0 + │ Extractor: ArrayExtractor + │ Processor: HashJoinProcessor + │ Join: left + │ On: id = id + │ Prefix: joined_ + │ Storage: FilesystemBuckets + │ Buckets: 64 + │ Batch: 1000 + └─ Right side: Pipeline #0 + Extractor: ArrayExtractor +``` + +A joined frame is planned apart, so its pipelines are numbered apart - `Right side:` says which plan they belong to. +Reaching this stage plans the frame, so a source that infers its schema by reading is read here; the logical stages +never read a row. > **Important**: Build your complete pipeline with lazy operations, then execute once with a trigger operation for optimal performance. @@ -83,6 +225,40 @@ $dataFrame = data_frame() - **Cache Strategically**: Only cache expensive operations that will be reused multiple times - **Avoid Large Offsets**: Use data source pagination instead of DataFrame `offset()` for large skips +### Optimizer + +Before a frame runs, the optimizer rewrites its plan. `Optimizer::default()` runs these rules, in order: + +| Rule | Rewrite | +|------------------------|----------------------------------------------------------------------------------| +| `CombineLimits` | two stacked `limit()` calls become one, with the smaller limit | +| `CombineSortAndLimit` | `sortBy()` followed by `limit()` keeps only the top rows instead of sorting all | +| `PushLimitIntoSource` | the extractor stops reading once the limit (plus any `offset()`) is reached | +| `PushFilterIntoSource` | a `filter()` on partition columns skips whole partition directories | + +Rules live in `Flow\ETL\Optimizer\Rule` and are configured through `config_builder()->optimizer()`: + +```php +optimizer(new Optimizer())); + +// the defaults without one rule +data_frame(config_builder()->optimizer(Optimizer::default()->without(CombineSortAndLimit::class))); + +// the defaults followed by your own Optimizer\Rule implementation +data_frame(config_builder()->optimizer(Optimizer::default()->with(new MyRule()))); +``` + +`without()` throws on a rule that is not registered, `with()` on a rule class that already is. +`explain()->toString()` prints the plan after the configured optimizer ran. + ## Component Documentation For detailed information about specific DataFrame operations, see the following component documentation: @@ -117,9 +293,6 @@ For detailed information about specific DataFrame operations, see the following - **[Constraints](/documentation/components/core/constraints.md)** - Data integrity constraints and business rules - **[Error Handling](/documentation/components/core/error-handling.md)** - Error management strategies -### Reliability & Recovery -- **[Retry Mechanisms](/documentation/components/core/retry.md)** - Automatic retry for transient failures - ### Observability - **[Telemetry](/documentation/components/core/telemetry.md)** - Distributed tracing, metrics, and logging integration diff --git a/documentation/components/core/data-retrieval.md b/documentation/components/core/data-retrieval.md index bb7f069312..b321e488cc 100644 --- a/documentation/components/core/data-retrieval.md +++ b/documentation/components/core/data-retrieval.md @@ -112,6 +112,16 @@ echo "Total rows: $totalCount\n"; $dataFrame->forEach(function (Rows $rows) { echo "Processing batch of " . $rows->count() . " rows\n"; - // Custom processing logic }); +``` + +`forEach()` owns the streaming loop. `run(bool|Analyze $analyze = false)` takes no callback: it executes the frame's +sinks and returns a `Report` when asked to analyze. + +```php +write(to_json('out.json'))->run(); + +$report = $dataFrame->write(to_json('out.json'))->run(analyze: analyze()->withSchema()); ``` \ No newline at end of file diff --git a/documentation/components/core/group-by.md b/documentation/components/core/group-by.md index 76cc22eb33..3412d5681e 100644 --- a/documentation/components/core/group-by.md +++ b/documentation/components/core/group-by.md @@ -52,8 +52,8 @@ spilled to the local filesystem cache directory (as Floe files), so memory usage largest bucket instead of the whole grouped dataset. Other implementations are `MemoryBuckets` (buckets kept in memory) and `PSRCacheBuckets` (buckets in any PSR-16 cache). -`groupBy()` and `aggregate()` each take an optional trailing `GroupByAlgorithmBuilder`, so one operation can -override the configured algorithm: +`groupBy()` takes an optional trailing `GroupByAlgorithmBuilder`, so one operation can override the configured +algorithm: ```php ignore ->groupBy([ref('country')], hash_group_by()->storage(new MemoryBuckets())) diff --git a/documentation/components/core/join.md b/documentation/components/core/join.md index b83e702757..32cfd74263 100644 --- a/documentation/components/core/join.md +++ b/documentation/components/core/join.md @@ -6,7 +6,8 @@ Joining two data frames is a common operation in data processing that combines data from two different sources. Flow PHP implements joins using a **hash join algorithm** that creates a hash table from the right DataFrame and probes it with -rows from the left DataFrame. +rows from the left DataFrame. The right DataFrame becomes part of the left one's plan when `join()` / `crossJoin()` is +called, and runs with the left DataFrame's configuration and error handler. ## Join Methods diff --git a/documentation/components/core/limit.md b/documentation/components/core/limit.md index 65b315e6b9..2c4e89a24d 100644 --- a/documentation/components/core/limit.md +++ b/documentation/components/core/limit.md @@ -39,4 +39,24 @@ from the source, like, for example, when you need to expand an array of elements In that case, Flow will detect the expansion, and it will cut rows accordingly to the total limit, however, it will happen only after expanding transformation. It's done this way because there is no way to predict -the result of the expansion. \ No newline at end of file +the result of the expansion. +## Limit Push-Down + +When nothing between `read()` and `limit()` can change the number of rows, the optimizer hands the limit to the +extractor, so a source that supports it reads only what is needed (`offset()` in between adds the skipped rows). A +frame read with `from_data_frame()` passes the limit on to its own source the same way. + +```php +read(from_csv(__DIR__ . '/orders.csv'))->select('id', 'total'); + +data_frame() + ->read(from_data_frame($orders)) + ->offset(10) + ->limit(5) + ->fetch(); // the CSV extractor is asked for 15 rows +``` diff --git a/documentation/components/core/partitioning.md b/documentation/components/core/partitioning.md index ab33b941d0..3ab9e81c47 100644 --- a/documentation/components/core/partitioning.md +++ b/documentation/components/core/partitioning.md @@ -112,7 +112,7 @@ use function Flow\ETL\DSL\{data_frame, lit, ref, to_output}; data_frame() ->read(from_csv(__DIR__ . '/output/date=*/{department}.csv')) - ->filterPartitions(ref('department')->equals(lit('sales'))) + ->filter(ref('department')->equals(lit('sales'))) ->write(to_output()) ->run(); ``` @@ -227,8 +227,11 @@ it as another type. ### Partition Pruning -`filterPartitions()` evaluates partition metadata and skips whole directories; `filter()` reads -everything and then discards. +The optimizer pushes a `filter()` that reads only partition columns into the source, so whole directories +are skipped; a filter on a body column still reads everything and then discards. A partition column renamed +with `rename()` or copied with `withEntry('day', ref('date'))` is still pruned; any other redefinition of it +stops the push. A filter whose answer can change between two evaluations - `call()`, `now()`, `uuid()`, +`to_date_time()` with a format that leaves fields out (`'Y-m-d'`) - still filters rows but prunes nothing. ```php read(from_csv(__DIR__ . '/output/date=*/department=*/*.csv')) - ->filterPartitions(ref('date')->greaterThanEqual(lit('2024-01-01'))) + ->filter(ref('date')->greaterThanEqual(lit('2024-01-01'))) ->write(to_output()) ->run(); ``` @@ -258,7 +261,8 @@ data_frame() ->run(); ``` -Output carries `path` and `partitions` columns. +Output carries `path`, a `partitions` map, and one string column per partition (`date`, `department`), so a +`filter()` on a partition column prunes the listing like any other file source. ## Repartitioning diff --git a/documentation/components/core/pivot.md b/documentation/components/core/pivot.md index 78dc416008..1ff890945e 100644 --- a/documentation/components/core/pivot.md +++ b/documentation/components/core/pivot.md @@ -107,6 +107,6 @@ more than 50 distinct values. Because it reads the frame before the real run, it twice, and refuses one it cannot: ``` -Flow\ETL\Extractor\DataFrameExtractor cannot read its dataset twice, so describing it would consume the -rows before they are extracted. Pass an array, or declare the schema with ->withSchema(). +The frame reads a source that cannot read its dataset twice, so discover_pivot_values() cannot scan it +before the pivot runs. Declare the values with pivot_values(...). ``` diff --git a/documentation/components/core/retry.md b/documentation/components/core/retry.md deleted file mode 100644 index 131568eb64..0000000000 --- a/documentation/components/core/retry.md +++ /dev/null @@ -1,311 +0,0 @@ -# Retry Mechanisms - -[DOC_LINK:/documentation/components/core/core] - -- [API Reference](/documentation/api/core) - -[TOC] - -The Flow ETL framework provides robust retry mechanisms to handle transient failures during data loading operations. -This is essential for building resilient data pipelines that can recover from temporary network issues, database -connection problems, or resource availability conflicts. - -## Overview - -The retry system focuses on **loader operations** - the final step where processed data is written to its destination. -When a loader encounters a temporary failure, the retry mechanism can automatically reattempt the operation according to -configurable strategies. - -## Key Components - -### RetryLoader - -The `RetryLoader` is a decorator that wraps any existing loader with retry capabilities. It implements `Loader` and -`Loader\Closure`, and forwards `closure()` to the wrapped loader, so file loaders finalize and publish their -destination as they normally would. - -Only `load()` is retried. A failure while closing is not retried, because closing publishes the destination and cannot -be resumed from a partial state. - -A run that never reaches its last batch - it threw, or the caller walked away from the generator - ends through -`Loader\Discardable::discard()` instead of `closure()`, so a half-written destination is removed rather than -published. The pipeline walks the whole loader tree to do it, so a wrapped file loader is discarded whether or not -`RetryLoader` forwards anything. - -```php -read(from_array([ - ['id' => 1, 'name' => 'John'], - ['id' => 2, 'name' => 'Jane'] - ])) - ->write(write_with_retries( - to_output(), - retry_any_throwable(3), // Retry up to 3 times - delay_fixed(duration_milliseconds(500)) // Wait 500ms between retries - )) - ->run(); -``` - -## Retry Strategies - -Retry strategies determine **when** to retry an operation based on the type of exception thrown. - -### AnyThrowable Strategy - -Retries on any thrown exception up to the specified limit: - -```php -use function Flow\ETL\DSL\retry_any_throwable; - -$strategy = retry_any_throwable(5); // Retry up to 5 times on any exception -``` - -### Specific Exception Types Strategy - -Retries only for specified exception types, allowing you to be selective about which failures should trigger retries: - -```php -use function Flow\ETL\DSL\retry_on_exception_types; - -$strategy = retry_on_exception_types([ - \PDOException::class, // Database connection issues - \RuntimeException::class, // Runtime problems - ConnectException::class, // Network connectivity issues -], 3); -``` - -This is useful when you want to retry transient failures but immediately fail on logic errors or data validation issues. - -### Any Throwable Except Strategy - -Retries on any thrown exception except the listed types, which fail immediately: - -```php -use function Flow\ETL\DSL\retry_any_throwable_except; - -$strategy = retry_any_throwable_except([ - \Flow\ETL\Exception\InvalidLogicException::class, -], 3); -``` - -This is the default strategy for both `new RetryLoader($loader)` and `write_with_retries($loader)`: -`AnyThrowableExcept([InvalidLogicException::class], 3)` - every throwable is retried up to 3 times except -`InvalidLogicException`, which fails after a single attempt with no delay. - -## Delay Factories - -Delay factories determine **how long** to wait between retry attempts. Different strategies help avoid overwhelming -failing services while providing appropriate backoff behavior. - -### Fixed Delay - -Wait a consistent amount of time between each retry: - -```php -use function Flow\ETL\DSL\{delay_fixed, duration_milliseconds, duration_seconds}; - -$delay = delay_fixed(duration_milliseconds(200)); // Wait 200ms between retries -$delay = delay_fixed(duration_seconds(1)); // Wait 1 second between retries -``` - -### Linear Backoff - -Increase the delay by a fixed increment on each retry: - -```php -use function Flow\ETL\DSL\delay_linear; - -// Start with 100ms, add 50ms each retry: 100ms, 150ms, 200ms, 250ms... -$delay = delay_linear( - duration_milliseconds(100), // Initial delay - duration_milliseconds(50) // Increment per retry -); -``` - -### Exponential Backoff - -Double (or multiply by a factor) the delay on each retry: - -```php -use function Flow\ETL\DSL\delay_exponential; - -// Start with 100ms, double each retry: 100ms, 200ms, 400ms, 800ms... -$delay = delay_exponential( - duration_milliseconds(100), // Base delay - 2, // Multiplier - duration_seconds(5) // Maximum delay cap -); -``` - -### Jitter - -Add randomness to any delay strategy to prevent "thundering herd" problems when multiple processes retry simultaneously: - -```php -use function Flow\ETL\DSL\delay_jitter; - -// Add ±20% random variation to a fixed delay -$delay = delay_jitter( - delay_fixed(duration_milliseconds(500)), - 0.2 // 20% jitter factor (0.0 to 1.0) -); -``` - -## Idempotent vs Non-Idempotent Operations - -Understanding the difference between idempotent and non-idempotent operations is crucial for designing reliable retry -mechanisms. - -### Idempotent Operations (Recommended) - -Idempotent operations can be safely repeated without causing unintended side effects. The same operation executed -multiple times produces the same result. - -**Examples of idempotent loader operations:** - -- Database `UPSERT` (INSERT ON CONFLICT UPDATE) -- HTTP PUT requests -- Database UPDATE with specific WHERE clauses - -```php -// Idempotent: Safe to retry -$loader = new DatabaseUpsertLoader($connection, 'users'); -$retryLoader = write_with_retries($loader, retry_any_throwable(5)); -``` - -### Non-Idempotent Operations (Use with Caution) - -Non-idempotent operations may produce different results or unintended side effects when repeated. - -**Examples of non-idempotent operations:** - -- Database `INSERT` without conflict resolution -- File appends -- Counter increments - -### File Loaders - -Do not wrap file loaders such as `to_csv()`, `to_json()` or `to_parquet()` in `write_with_retries()`, regardless of the -save mode. A file loader appends each batch to a stream that stays open for the whole run, and a retry has nothing to -roll back, so a batch that fails after part of it reached the stream is written twice: - -```php -data_frame() - ->read(from_array([['id' => 1], ['id' => 2], ['id' => 3], ['id' => 4]])) - ->batchSize(2) - // a transient failure in the first batch leaves ids 1 and 2 in the file twice - ->write(write_with_retries(to_csv($path)->saveMode(overwrite()))) - ->run(); -``` - -`overwrite()` replaces the destination once per run, not once per batch, so it does not undo a duplicated batch. - -### Transformation Loaders - -Wrapping `to_transformation(...)` or a `to_branch(...)` armed with `withTransformation(...)` in -`write_with_retries()` or `RetryLoader` throws `InvalidLogicException` at the first `load()`, at any nesting -depth. These loaders hold state across `load()` calls and cannot replay a failed batch. Retry the destination -instead: - -```php -to_transformation($transformation, write_with_retries($loader)); -to_branch($condition, write_with_retries($loader))->withTransformation($transformation); -``` - -When the destination is a transactional wrapper (`to_dbal_transaction()`, `to_pgsql_transaction()`), put the -wrapper inside `write_with_retries()`, not the other way around - a retry inside an aborted database -transaction can never succeed; wrapping the transaction gives every attempt a fresh one: - -```php -to_transformation($transformation, write_with_retries(to_pgsql_transaction($client, $loader))); -``` - -## Advanced Configuration - -### Custom Sleep Implementation - -For testing or special requirements, you can provide a custom sleep implementation: - -```php -use Flow\ETL\Time\FakeSleep; - -$sleep = new FakeSleep(); // For testing - doesn't actually sleep -$retryLoader = write_with_retries( - $loader, - retry_any_throwable(3), - delay_fixed(duration_milliseconds(100)), - $sleep -); -``` - -### Complete Configuration Example - -```php -read(from_array($largeDataset)) - ->write(write_with_retries( - to_dbal_table_insert($connection, 'transactions'), - - // Only retry on specific transient failures - retry_on_exception_types([ - \PDOException::class, - \RuntimeException::class - ], 5), - - // Exponential backoff with jitter - delay_jitter( - delay_exponential( - duration_milliseconds(200), // Start with 200ms - 2, // Double each time - duration_seconds(10) // Cap at 10 seconds - ), - 0.3 // 30% jitter to prevent thundering herd - ) - )) - ->run(); -``` - -## Error Information - -When all retries are exhausted, a `FailedRetryException` is thrown containing detailed information about all attempts: - -```php -use Flow\ETL\Exception\FailedRetryException; - -try { - $dataFrame->write($retryLoader)->run(); -} catch (FailedRetryException $e) { - echo "Failed after {$e->record->count()} attempts\n"; - - // Access individual retry attempts - foreach ($e->record->all() as $retry) { - echo "Attempt {$retry->attempt()}: {$retry->exception()->getMessage()}\n"; - echo "Timestamp: {$retry->timestamp()->format('Y-m-d H:i:s')}\n"; - } -} -``` \ No newline at end of file diff --git a/documentation/components/core/telemetry.md b/documentation/components/core/telemetry.md index 5e7d1801fa..9af0cf5d47 100644 --- a/documentation/components/core/telemetry.md +++ b/documentation/components/core/telemetry.md @@ -199,12 +199,12 @@ $transport = otlp_grpc_transport(endpoint: 'localhost:4317'); Every DataFrame execution creates a root span with the following attributes: -| Attribute | Description | -|---------------------------------------|-----------------------------------------------| -| `flow.etl.dataframe.id` | Unique identifier for the DataFrame execution | -| `flow.etl.dataframe.name` | Configured DataFrame name | -| `flow.etl.rows.total` | Total number of rows processed | -| `flow.etl.rows.throughput.per_second` | Processing throughput | +| Attribute | Description | +|---------------------------------------|--------------------------------------------------| +| `flow.etl.dataframe.id` | Unique identifier for the DataFrame execution | +| `flow.etl.dataframe.name` | Configured DataFrame name | +| `flow.etl.rows.total` | Total number of rows processed | +| `flow.etl.rows.throughput.per_second` | Processing throughput | | `flow.etl.memory.min` | Minimum memory consumption during execution (MB) | | `flow.etl.memory.max` | Maximum memory consumption during execution (MB) | @@ -233,7 +233,7 @@ When `collect_metrics` is enabled: Structured logs are emitted at DEBUG level for pipeline events: -- **Pipeline start** - Logged with configuration details (cache type, serializer, optimizers, spill storages) +- **Pipeline start** - Logged with configuration details (cache type, serializer, optimizer rules, spill storages) - **Pipeline completion** - Logged with summary statistics (total rows, memory usage) - **Errors** - Logged at ERROR level with exception details diff --git a/documentation/components/core/transformations.md b/documentation/components/core/transformations.md index e068862572..08b5e4afc6 100644 --- a/documentation/components/core/transformations.md +++ b/documentation/components/core/transformations.md @@ -141,6 +141,10 @@ df() ->run(); ``` +The index starts again on every run of the frame. A custom `Transformer` that keeps state between batches does the +same by implementing `Flow\ETL\Transformer\Stateful`: its `fresh()` returns a new instance in its constructed state, +and every run uses that instance. + ### Limit Restrict the number of rows processed, useful for debugging or sampling data. @@ -207,40 +211,33 @@ df() ->run(); ``` -## Using with to_transformation Loader +## Transformations as Sinks -The `to_transformation` loader allows you to apply transformations as part of the loading phase, enabling complex ETL -patterns: +`to_transformation()` and `to_branch()` are sinks: each becomes its own root of the plan, fed the rows of the node it +was written at, and planned and bound together with the rest of the frame. ```php -use function Flow\ETL\DSL\{df, from_array, to_transformation, to_csv, select}; +use function Flow\ETL\DSL\{df, from_array, lit, ref, select, to_branch, to_csv, to_transformation}; -// Apply transformation before loading df() ->read(from_array([/* ... */])) - ->write( - to_transformation( - select('id', 'name'), // Transform data - to_csv('output.csv') // Then write to CSV - ) - ) + ->write(to_transformation(select('id', 'name'), to_csv('names.csv'))) + ->write(to_branch(ref('active')->equals(lit(true)), to_csv('active.csv'))) ->run(); ``` -This pattern is particularly useful when you need to: - -- Apply different transformations to the same data for multiple outputs -- Create transformation pipelines that can be reused -- Separate transformation logic from extraction and loading +A branch filters first; `withTransformation()`, called before `write()`, transforms what passed the condition. Sinks +nest - wherever a sink takes a loader, it also takes another sink: -The `Transformation` is expanded **once per loader instance**, on the first batch, and the nested pipeline is then -driven a single time over the whole stream. Every operation inside it answers exactly as it does on the outer frame - -`limit()` and `add_row_index()` apply across the stream, not per batch. +```php +to_branch(ref('active')->equals(lit(true)), to_csv('active.csv'))->withTransformation($sortById); +to_branch(ref('active')->equals(lit(true)), to_transformation($sortById, to_csv('active.csv'))); +``` -`to_branch($condition, $loader, $transformation)` (or `->withTransformation($transformation)`, which replaces the one -given to `to_branch()`) drives its `Transformation` the same way: the condition filters each batch first, and one -nested pipeline then spans the whole filtered stream. The memory cost, chunk -shape and failure behaviour below apply to it unchanged. +The `Transformation` runs once per run over the whole stream it is fed, so `limit()` and `add_row_index()` apply across +the stream, not per batch. A triggering verb (`fetch()`, `count()`, `schema()`, ...) inside it executes the prefix plan, +as `from_data_frame()` executes a frame. `onError()` inside it throws `InvalidLogicException` at `write()` - set the +error handler on the outer frame. ```php use Flow\ETL\{DataFrame, Transformation}; @@ -263,7 +260,7 @@ df() ### Memory Cost Correctness is the same everywhere; what differs between operations is how much they hold, and they hold it inside the -loader. Three groups: +sink. Three groups: | Cost | Operations | |----------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------| @@ -277,7 +274,7 @@ batch as it passes. They need the whole stream to answer correctly, not to accum ### Chunk Shape and Order -`batch_size()`, `batchBy()` and `repartition()` change only which rows are grouped into the `Rows` handed to the wrapped +`batch_size()`, `batchBy()` and `repartition()` change only which rows are grouped into the `Rows` handed to the sink's loader. No row is lost or mis-assigned. `repartition()` and `join()` also change the **order** the rows arrive in: both group their output by key rather than @@ -287,27 +284,28 @@ emitting it in input order. `batchBy()` preserves input order and only cuts the arrives together, so it belongs in the first group above, alongside `sortBy()` and `join()`. Writing one directory per key is a separate thing, declared on the loader: `to_csv(...)->partitionBy('region')`. -To re-batch the pipeline itself rather than what reaches the wrapped loader, call `$df->batchSize(...)` on the frame. +To re-batch the pipeline itself rather than what reaches the sink's loader, call `$df->batchSize(...)` on the frame. ### Failure Behaviour -A failure inside a `Transformation` propagates out of the loader, and no loader in that segment is closed - exactly as a -failing loader on an outer frame is never closed. - -`->onError(...)` on the outer frame governs that propagation the same way it does for a plain loader. When the handler -declines to propagate, the run continues, later batches are processed through a fresh nested pipeline, and the wrapped -loader is closed. A rebuilt pipeline starts empty: anything the previous one had accumulated is gone, and stateful -operations such as `add_row_index()` restart their counters. - -The handler is **not** inherited by the nested pipeline, which always propagates. To make a failure between the -transformation's own steps recoverable, set the handler inside it: +A sink runs under the frame's `->onError(...)` handler, and each failure is offered to it exactly once: ```php -$dataFrame->onError(ignore_error_handler())->with(/* ... */); +df() + ->read(from_array([/* ... */])) + ->onError(skip_rows_handler()) // a failing step inside the sink skips that batch + ->write(to_transformation($sortById, to_csv('sorted.csv'))) + ->run(); ``` +A failing step inside the `Transformation` is a transformation failure - for a blocking operation the skipped batch is +everything it had buffered. Under the default handler the failure propagates and no loader of the run is closed. + +A loader whose `closure()` fails is never offered to the handler: its own exception surfaces from `run()`. + None of this is durability or atomicity: `closure()` both commits and closes, so a destination written up to the point -of failure can be left behind. +of failure can be left behind. For all-or-nothing batches wrap the sinks in a transaction - +`to_dbal_transaction()`, `to_pgsql_transaction()`. ## Creating Custom Transformations diff --git a/documentation/components/libs/postgresql.md b/documentation/components/libs/postgresql.md index d3d1faeaaf..bfb5f9cf8d 100644 --- a/documentation/components/libs/postgresql.md +++ b/documentation/components/libs/postgresql.md @@ -369,11 +369,11 @@ interface RowMapper The library ships two default mappers, both available via DSL functions, plus an optional bridge for [cuyz/valinor](https://valinor.cuyz.io). -| Mapper | Use for | -| --- | --- | -| [ConstructorMapper](/documentation/components/libs/postgresql/client-constructor-mapper.md) | Map row columns directly to constructor parameters by name (1:1). No type coercion. | +| Mapper | Use for | +|--------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| [ConstructorMapper](/documentation/components/libs/postgresql/client-constructor-mapper.md) | Map row columns directly to constructor parameters by name (1:1). No type coercion. | | [StaticFactoryMapper](/documentation/components/libs/postgresql/client-static-factory-mapper.md) | Delegate row → object construction to a public static factory method (`self::fromRow(array $row)`). Useful when the target class has a private constructor or needs custom coercion inside the factory. | -| [TypeMapper](/documentation/components/libs/postgresql/client-type-mapper.md) | Validate and coerce the row via [flow-php/types](/documentation/components/libs/types.md) (JSONB → structure, date string → `\DateTimeImmutable`, ...). Optionally chains into another `RowMapper`. | +| [TypeMapper](/documentation/components/libs/postgresql/client-type-mapper.md) | Validate and coerce the row via [flow-php/types](/documentation/components/libs/types.md) (JSONB → structure, date string → `\DateTimeImmutable`, ...). Optionally chains into another `RowMapper`. | | [PostgreSQL Valinor Bridge](/documentation/components/bridges/postgresql-valinor-bridge.md) | Strict object hydration of complex graphs via cuyz/valinor. **Requires the separate `flow-php/postgresql-valinor-bridge` package.** | ### Detailed Documentation diff --git a/documentation/upgrading.md b/documentation/upgrading.md index 59b7605b39..75bc0a4d67 100644 --- a/documentation/upgrading.md +++ b/documentation/upgrading.md @@ -7,6 +7,222 @@ specific version to ensure a smooth upgrade process. --- +## Upgrading from 0.44.x to 0.45.x + +### 1) `flow-php/etl-adapter-postgresql` - a failed `from_pgsql_cursor()` read throws its own error and rolls back + +| Before | After | +|-----------------------------------------------------------------------------------------------------------------|----------------------------------------------| +| `QueryException` `[25P02] Invalid transaction state. SQL: CLOSE flow_cursor_...`, real error in `getPrevious()` | the failing statement's own `QueryException` | +| the client left inside an aborted transaction - every later query fails with `25P02` | the extractor's own transaction rolled back | +| a failure while reading rows (e.g. a row that does not match the schema) committed the transaction | rolled back | + +### 2) `flow-php/etl-adapter-postgresql` - `from_pgsql_*()` read exactly one read-only `SELECT` or `VALUES` statement + +| Query | Before | After | +|-----------------------------------------------------------------------------|--------------------------------------------------------------------------|------------------------------------------| +| `INSERT ... RETURNING` through `from_pgsql_cursor()` | the PHP process crashes (segfault) | `InvalidArgumentException`, nothing runs | +| `INSERT ... RETURNING` through `from_pgsql_key_set()` | the `INSERT` runs, then `QueryException` `08P01` | `InvalidArgumentException`, nothing runs | +| two statements through `from_pgsql_cursor()` | the second statement silently dropped | `InvalidArgumentException` | +| two statements through `from_pgsql_limit_offset()` / `from_pgsql_key_set()` | `QueryException` `42601` | `InvalidArgumentException` | +| a data-modifying `WITH` through `from_pgsql_key_set()` | the write runs once per page - an `INSERT` twice, an `UPDATE` never ends | `InvalidArgumentException`, nothing runs | +| `SELECT ... INTO` through `from_pgsql_key_set()` | the table is created | `InvalidArgumentException`, nothing runs | +| either through `from_pgsql_cursor()` / `from_pgsql_limit_offset()` | `QueryException` after a round trip | `InvalidArgumentException`, nothing runs | + +### 3) `flow-php/postgresql` - `declare_cursor()` over SQL takes exactly one `SELECT` or `VALUES` + +| Before | After | +|-------------------------------------------------------------------------------------|----------------------------| +| `declare_cursor('c', 'INSERT INTO t VALUES (1) RETURNING id')->toSql()` - segfault | `InvalidArgumentException` | +| `declare_cursor('c', 'SELECT 1; SELECT 2')` - the second statement silently dropped | `InvalidArgumentException` | + +### 4) `flow-php/postgresql` - `SelectStatement::hasIntoClause()` sees `SELECT ... INTO` in a `UNION` / `INTERSECT` / `EXCEPT` + +| `sql_parse($sql)->statements()->first()->hasIntoClause()`, `$sql` | Before | After | +|-------------------------------------------------------------------|---------|--------| +| `SELECT id INTO t FROM x UNION SELECT 1` | `false` | `true` | + +### 5) `flow-php/postgresql` - `sql_to_*_query()` and the pagination modifiers take exactly one read-only `SELECT` or `VALUES` + +| Before | After | +|--------------------------------------------------------------------------------------|-----------------------------| +| `sql_to_paginated_query('UPDATE t SET a = 1 RETURNING id', 10)` - returned unchanged | `InvalidStatementException` | +| `sql_to_limited_query('SELECT 1; SELECT 2', 10)` - every statement paginated | `InvalidStatementException` | +| `sql_to_keyset_query()` over a data-modifying `WITH` - the write paginated | `InvalidStatementException` | +| `sql_to_count_query('SELECT id INTO t FROM x')` - counted | `InvalidStatementException` | + +Applies to `PaginationModifier`, `CountModifier` and `KeysetPaginationModifier` passed to `ParsedQuery::traverse()`. + +### 6) `flow-php/etl-adapter-postgresql` - `from_pgsql_limit_offset()` requires the query's own `ORDER BY` + +| Query | Before | After | +|--------------------------------------------------|-----------------------------|----------------------------| +| `SELECT * FROM (SELECT id FROM t ORDER BY id) s` | pages in no defined order | `InvalidArgumentException` | + +### 7) `flow-php/etl` - `Pipeline\Optimizer` replaced by `Optimizer` + `Planner`, the `Pipeline` class removed + +| Before | After | +|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `Config::optimizer()`, `new Config(..., Optimizer $optimizer, ...)` | `Config::optimizer(): Flow\ETL\Optimizer`, `new Config(..., Optimizer $optimizer, Executor $executor, ...)`; added `Config::planner()` / `Config::executor()` | +| `config_builder()->optimizer($optimizer)` | `config_builder()->optimizer(Flow\ETL\Optimizer $optimizer)`, `->executor(Executor $executor)` | +| `Flow\ETL\Pipeline` (class, with `Pipeline::has()`), `Pipeline\Optimizer`, `Pipeline\Optimizer\Optimization`, `Pipeline\Optimizer\LimitOptimization`, `Pipeline\BoundPlan`, `Pipeline\PlanBinder` | removed - an `Optimizer\Rule` rewrites the `Plan\LogicalPlan`: `apply(LogicalPlan $plan, FlowContext $context): LogicalPlan`; drop one with `Optimizer::default()->without(Rule::class)`, add one with `->with(new MyRule())` | +| `new Pipeline\Optimizer(Optimization ...)`, `->disabled()`, `->optimizations()` | `new Optimizer(Rule ...)`, `new Optimizer()` (no rules - nothing is rewritten), `->rules()`; `Optimizer::default()` holds the built-in rules, `->without(Rule::class)` / `->with(new MyRule())` change them | +| - | `Flow\ETL\Executor\PhysicalPlan` interface (`root(): Executor\Pipeline`, `schema(): Schema`): `Executor\Described` returns its schema, `Executor\Raw` throws its `SchemaNotDerivableException` | +| `Segments::replaceExtractor()` / `has()` / `current()` / `segmentFor()`, `Segment::withExtractor()` / `has()` / `contains()` | removed - `Segments::extractor()` / `Segment::extractor()` | +| `new DataFrame(Pipeline $pipeline, $context)` | `new DataFrame(Extractor $extractor, Config\|FlowContext $context)` | +| `new HashJoinProcessor(DataFrame $right, ...)`, `new CrossJoinRowsTransformer(DataFrame $frame, ...)` | take the right side's `Executor\PhysicalPlan` and an `Executor` | +| `JoinSteps::of(DataFrame $right, ...)` | `JoinSteps::of(PhysicalPlan $right, Expression $expression, Join $type, Config $config, ?JoinAlgorithmBuilder $algorithm)` | +| `InvalidLogicException::cyclicPlanOnDescribe()` | removed | +| telemetry debug-log field `optimizers` | `optimizer_rules` | + +### 8) `flow-php/etl` - `extract()` receives the pushed limit and path filter, `LimitPushDown` and `withPathFilter()` removed + +| Before | After | +|----------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------| +| `Extractor::extract(FlowContext $context): Generator` | `extract(FlowContext $context, ?int $limit = null): Generator` - every implementation adds the parameter, and may ignore it | +| `Extractor\LimitPushDown` + `PushesLimit` trait, `pushLimit()` / `pushedLimit()` | removed - read `$limit` in `extract()` | +| `FileExtractor::withPathFilter($filter)` / `filter()`, `PathFiltering` held the filter | removed - `FileExtractor::extract(FlowContext $context, ?int $limit = null, Filter $pathFilter = new OnlyFiles()): Generator` | +| `interface FileExtractor` | gains `partitionSchema(): Schema` - every implementor must add it | +| `interface Function\FunctionTree` | gains `deterministic(): bool` - implementors using neither `ScalarFunctionChain` nor `ResolvesFromChildren` must add it | + +### 9) `flow-php/etl` - `filterPartitions()` removed, the optimizer pushes `filter()` into the source + +| Before | After | +|-------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `$df->filterPartitions(ref('date')->equals(lit('2024-01-01')))` | `$df->filter(ref('date')->equals(lit('2024-01-01')))` - pushed into the source as a path filter, only matching partitions are read | +| `$df->filterPartitions(new OnlyFiles())` (`Path\Filter` form) | removed, no replacement | +| `$df->read(files($glob))->filterPartitions(...)`, same over `from_path_partitions($glob)` | `filter()` on the partition column - both sources now emit one string column per `key=value` directory (next to `partitions`), and the filter is pushed into the listing | +| a partition-predicate error was thrown by the verb | thrown at plan / bind time - an optimizer rule can fail a plan | +| `->write($sink)->filter(...)` narrowed the earlier sink | a filter is pushed only when every root reaches the source through it - the sink gets every row | + +### 10) `flow-php/etl` - frames are snapshotted when embedded, fewer limits are pushed + +| Before | After | +|------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------| +| `$left->join($right, ...); $right->select('id');` - the `select()` was part of the join's right side | ignored - a frame is snapshotted at `join()` / `from_data_frame()` time | +| `$frame->join(df()->read(from_data_frame($frame)), ...)` threw `InvalidLogicException` "Cannot describe this plan:" | runs as a self-join against the snapshot; a run-time cycle still throws `cyclicPlanOnRun()` | +| `->rows($t)->limit(n)`, `->transform($t)->limit(n)`, `->void()->limit(n)` pushed the limit into the source for seven allow-listed transformers | not pushed - `->withEntry(...)->limit(n)` still pushes; with several sinks the widest limit is pushed, a `limit(3)` inside a sink limits the whole run | +| - | `schema()` followed by a terminal verb plans twice, `Extractor::schema()` is called once per planning - memoise a sniffing extractor | +| `add_row_index()` on a frame run twice continued counting (`[0,1,2]` then `[3,4,5]`) | starts again on every run; a `Transformer` keeping state between batches implements `Flow\ETL\Transformer\Stateful` (`fresh()`) to do the same | +| a joined frame ran with its own config and `onError()` | runs with the outer frame's config, optimizer and error handler; its own `onError()` is ignored - a `from_data_frame()` frame still runs with its own | +| each joined frame opened its own `DataFrame` span | one `DataFrame` span per run; a `from_data_frame()` frame still opens its own | + +### 11) `flow-php/etl` - one balanced `DataFrame` telemetry span per run + +| Before | After | +|---------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------| +| the `DataFrame` span started when the frame was built | starts when the plan executes - `Executor::execute()` owns both ends | +| a planning failure under `schema()` emitted no span | `dataFrameStarted` + `dataFrameFailed` for every verb | +| an abandoned `get*()` generator left its span open | closes it | +| a failure inside a verb's own loop body (a `forEach` callback, the formatter) closed the span as failed | closed as completed | +| a `from_data_frame()` frame emitted no span | one balanced span per run | +| `to_dbal_transaction()` / `to_pgsql_transaction()` emitted their own span | no span | + +### 12) `flow-php/etl` - `to_branch()` / `to_transformation()` return a `Sink`, the wrapper loaders are removed + +| Before | After | +|----------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `to_branch($condition, $loader, $transformation)` returned `BranchingLoader` | `to_branch($condition, $sink)->withTransformation($transformation)` returns `Sink\Branched` | +| `to_transformation($transformation, $loader)` returned `TransformerLoader` | returns `Sink\Transformed`; both take a `Loader` or another `Sink`, neither is accepted where a `Loader` is required | +| `Loader\OverridingLoader`, `Loader\LoaderTree`, `Loader\TransformerLoader`, `Loader\BranchingLoader` | removed - `Flow\ETL\Sink` interface (`write(DataFrame $prefix): void`) | +| a `Transformation` calling `$df->fetch()` / `count()` / `schema()` / `run()` inside `to_transformation()` or `to_branch()` threw `InvalidLogicException` | executes the prefix plan, as `from_data_frame()` executes a frame | +| `onError()` inside a sink's `Transformation` | throws `InvalidLogicException` at `write()` - set it on the frame | +| an unresolved column or a non-boolean condition in a sink failed at the first batch | fails at plan time; one undescribable sink operation makes the whole plan run raw; `schema()` still describes the frame's own rows | +| a transformer failing inside a non-transactional sink was a LOADING error | a TRANSFORMATION error offered to `onTransformation()` once: `SkipRows` / `IgnoreError` drop the batch (after a blocking operation, the whole buffered batch); a `limit()` completing the sink mid-load is a LOADING error on `Executor\SinkFeed` | +| `write_with_retries($loader)` around `to_transformation(...)` or `to_branch(...)` threw at the first `load()` | removed with the retry surface, see 14) | +| telemetry `flow.etl.loading.rows` counted the rows offered to the branch | counts the rows the branch's loader writes; an empty batch never reaches the loader | +| `SkipRows`: a drain failure of `to_transformation()` / `to_branch()` at `closure()` was rethrown | offered to `onTransformation()` once - `SkipRows` drops the buffered batch | +| `$df->load(loader: $l)`, `$df->write(loader: $l)`, `to_transformation($t, loader: $l)`, `to_branch($c, loader: $l)` | the named argument is `sink:` | + +### 13) `flow-php/etl-adapter-doctrine`, `-postgresql` - `to_dbal_transaction()` / `to_pgsql_transaction()` are transaction roots + +| Before | After | +|-----------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `to_dbal_transaction($connection, Loader ...$loaders): TransactionalDbalLoader` | `to_dbal_transaction($connection, Loader\|Sink ...$sinks): Transactional` - `Sink\Transactional` over a `DbalTransaction`; `TransactionalDbalLoader` removed | +| `to_pgsql_transaction($client, Loader ...$loaders): TransactionalPostgreSqlLoader` | `to_pgsql_transaction($client, Loader\|Sink ...$sinks): Transactional` - over a `PostgreSqlTransaction`; `TransactionalPostgreSqlLoader` removed | +| `to_dbal_transaction(...)->withIsolationLevel($level)` | `new Transactional(DbalTransaction::fromConnection($connection)->withIsolationLevel($level), ...$sinks)` - returns a new instance; the same on `PostgreSqlTransaction`, which runs `SET TRANSACTION` after `BEGIN` and rolls back a failed `SET` | +| a failure a non-throwing `onError()` handler suppressed still committed the batch | the batch (or the closure drain) rolls back and is never re-delivered; the handler only decides whether the run continues - the failing sink restarts on the next batch, its buffered rows lost | +| `LoadingError::$loader` for a `begin()` / `commit()` failure was `TransactionalDbalLoader` | `Executor\TransactionalSinks`; for a sink failure, the sink's own loader when bare, `Executor\SinkFeed` otherwise; the exception is always the cause, never `TransactionRolledBack` | +| `withIsolationLevel()` on `to_dbal_transaction()` / `to_pgsql_transaction()` applied to every transaction the wrapper opens | set on `DbalTransaction` / `PostgreSqlTransaction`; applies to every transaction opened | + +### 14) `flow-php/etl` - `write_with_retries()` and the retry surface are removed + +| Before | After | +|--------------------------------------------------------------------------------|-------------------------------------------------| +| `write_with_retries($loader, retry_any_throwable(3))` | removed, no replacement | +| `Loader\RetryLoader`, `FailedRetryException`, `ReplayAware`, `Flow\ETL\Time\*` | removed | +| `retry_*()`, `delay_*()`, `duration_*()` DSL functions | removed | +| `$df->write(write_with_retries(to_csv($p)->saveMode(overwrite())))` | `$df->write(to_csv($p)->saveMode(overwrite()))` | + +### 15) `flow-php/etl-adapter-doctrine` - a DBAL read the driver cannot describe keeps the database error + +| Before | After | +|--------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| a query the driver cannot describe (multi-statement, data-modifying CTE, `INSERT ... RETURNING`) threw `SchemaNotDerivableException` | a missing table or column throws what the read throws (`TableNotFoundException`, `InvalidFieldNameException`, on SQLite `DriverException`); any other query the driver refuses to describe throws `SchemaNotDerivableException` with the DBAL exception as `getPrevious()` | + +### 16) `flow-php/etl-adapter-postgresql` - a PostgreSQL read keeps the database error, reads that write are refused + +| Before | After | +|-----------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| a query that cannot run as a subquery (multi-statement, data-modifying CTE, `INSERT ... RETURNING`) threw `SchemaNotDerivableException` | a missing table, column, function, type or privilege throws PostgreSQL's `QueryException`, as the read does; a query that writes (a data-modifying `WITH`, `SELECT ... INTO`) throws `InvalidArgumentException` before any query runs | + +### 17) `flow-php/flow-php-ext` - the `flow_php` extension is versioned with `flow-php/etl` + +| Before | After | +|-------------------------------------------------------------|---------------------------------------------| +| `flow_php` extension 0.3.0, required by this `flow-php/etl` | same version as this `flow-php/etl` release | + +### 18) `flow-php/etl` - `DataFrame` has no `@internal` methods + +| Before | After | +|---------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------| +| `DataFrame::extractor()` (`@internal`) | removed - `(new Repeatability())->ofPlan($dataFrame->explain()->logical)` answers whether every source the frame reads can be read twice | +| `DataFrame::registerGroupBy($groupBy, $algorithm)` (`@internal`) | removed - `groupBy($entries, $algorithm)->aggregate(...)` | +| `new GroupedDataFrame($df, $groupBy, $algorithm)` | `new GroupedDataFrame($df, $input, $groupBy)` - built by `DataFrame::groupBy()` | +| `SchemaNotDerivableException::nonRewindable($extractorClass)` | `nonRewindable()`; the message no longer names the extractor | +| `discover_pivot_values()` over a frame joining a source that cannot be read twice - pivot silently null | throws `SchemaNotDerivableException` | +| `discover_pivot_values()` over `from_data_frame()` of a repeatable frame - refused | allowed | +| a `Transformation` writing inside a sink - its write ran after the sink's own write | runs before it; a transaction's writes run in `write()` call order | +| a `Transformation` inside a sink returning another frame - failed at `run()` "A sink root shares no node with the plan" | throws at `write()` | +| `$frame->onError()` after `join($frame)` / `from_data_frame($frame)` - reached the embedded frame | ignored - a joined frame runs with the outer frame's handler, a `from_data_frame()` frame with the one it had when embedded | +| an embedded frame sharing the outer `FlowContext` left a `DataFrame` span open | balanced spans | +| `discover_pivot_values()` over a frame with `write()` before `groupBy()` - the sink received every row twice (discovery ran it) | discovery reads only the rows feeding the pivot, sinks run once | + +### 19) `flow-php/etl` - `Pipeline\` and `Execution\` merged into `Executor\`, `BoundStep` moved to the root + +| Before | After | +|------------------------------------------|-----------------------------------------| +| `Flow\ETL\Pipeline\BoundStep` | `Flow\ETL\BoundStep` | +| `Flow\ETL\Pipeline\Segments` | `Flow\ETL\Executor\Segments` | +| `Flow\ETL\Pipeline\Segment` | `Flow\ETL\Executor\Segment` | +| `Flow\ETL\Execution\StatisticsCollector` | `Flow\ETL\Executor\StatisticsCollector` | + +### 20) `flow-php/etl` - the trigger builds the plan's consumer, `run()` takes no callback + +| Before | After | +|--------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------| +| `$frame->run(fn (Rows $rows) => ...)` | `$frame->forEach(fn (Rows $rows) => ...)`; `run(bool\|Analyze $analyze = false)` | +| `$frame->explain()` on a frame ending in `write()` - printed a `Result` nobody reads | prints the writes; `explain(Trigger::run)` for the plan `run()` executes | +| `Plan\LogicalPlan::of()` / `cursor()` / `withCursor()` / `withSinks()` | removed - `Trigger::rows->plan($root, $sinks)`, `LogicalPlan::$root`, `LogicalPlan::spine()` | +| `new Plan\Node\Outputs(Result $result, Sinks $sinks)` | `new Plan\Node\Outputs(Result\|Write\|Transaction ...$consumers)` - two or more | +| `InvalidLogicException::resultRewritten()` | `consumerRewritten()`; a `Transaction` as the first consumer is refused | + +### 21) `flow-php/etl` - explain layouts render a described entry, a joined frame is drawn without its `Result` + +`Plan\Explain\Outline` now applies `Details` while it builds, so a layout prints what the entry carries instead of +asking for it. A joined frame's `Result` is no longer drawn: the join reads its right side directly, and the numbers +after it shift by one. `Stage::physical` is new - see the core documentation. + +| Before | After | +|---------------------------------------------------------|-----------------------------------------------------------------------------------| +| `new Explain\Entry($node, $number, $shared, $children)` | `new Explain\Entry($source, $name, $lines, $number, $shared, $children, $suffix)` | +| `$entry->node` | `$entry->source` | +| `$entry->title($name)` | `$entry->title()` - the name is the entry's own | +| `new Explain\TreeLayout($details, declarations: true)` | `new Explain\Outline(declarations: true)`, the layout takes no arguments | +| `new Explain\BoxLayout($details)` | `new Explain\BoxLayout()` | + +--- + ## Upgrading from 0.43.x to 0.44.x ### 1) `flow-php/etl-adapter-json` - `to_json()`/`to_json_lines()` write list/map/structure/array entries as nested JSON @@ -1258,10 +1474,8 @@ Keep every column a string: `from_csv($path)->inferSchema(infer_schema()->allStr | `pdo_pgsql`, `pdo_mysql`, any other | every column | driver values | throws `SchemaNotDerivableException` - use the `pgsql` / `mysqli` driver or `->withSchema(...)` | Applies to `from_dbal_query()`, `from_dbal_queries()`, `from_dbal_limit_offset()`, `from_dbal_limit_offset_qb()` and -`from_dbal_key_set_qb()` without `->withSchema()`. A missing table or column throws what the read throws -(`TableNotFoundException`, `InvalidFieldNameException`, on SQLite `DriverException`); any other query the driver -refuses to describe throws -`SchemaNotDerivableException` with the DBAL exception as `getPrevious()`. Declare `->withSchema(...)` to pick the types. +`from_dbal_key_set_qb()` without `->withSchema()`. A query the driver cannot describe (multi-statement, data-modifying +CTE, `INSERT ... RETURNING`) also throws. Declare `->withSchema(...)` to pick the types. ### 83) `flow-php/etl-adapter-doctrine`, `-postgresql` - `withPageSize()` / `withFetchSize()` become `withBatchSize()` @@ -1375,9 +1589,8 @@ Applies to `from_json()` and `from_json_lines()` unless the row names one. | `record`, `point`, `line`, `lseg`, `box`, `path`, `polygon`, `circle` | `string` | throws `SchemaNotDerivableException` | Applies to `from_pgsql_cursor()`, `from_pgsql_limit_offset()` and `from_pgsql_key_set()` without `->withSchema()`. A -missing table, column, function, type or privilege throws PostgreSQL's `QueryException`, as the read does; a query -that writes (a data-modifying `WITH`, `SELECT ... INTO`) throws `InvalidArgumentException` before any query runs. -Declare `->withSchema(...)` to pick the types. +query that cannot run as a subquery (multi-statement, data-modifying CTE, `INSERT ... RETURNING`) also throws +`SchemaNotDerivableException`. Declare `->withSchema(...)` to pick the types. ### 93) `flow-php/etl-adapter-postgresql` - `pgsql_table_to_flow_schema()` maps arrays, text-like types, `oid`, `timetz` @@ -1431,9 +1644,9 @@ Registering the commands in your own console application: drop the `setName()` / ### 98) `flow-php/flow-php-ext` - the `flow_php` extension must be reinstalled -| Before | After | -|----------------------------|---------------------------------------------| -| `flow_php` extension 0.1.0 | same version as this `flow-php/etl` release | +| Before | After | +|----------------------------|----------------------------------------| +| `flow_php` extension 0.1.0 | 0.3.0, required by this `flow-php/etl` | Reinstall it with the new release: `pie install flow-php/flow-php-ext`. @@ -1535,56 +1748,6 @@ Recurse with `data/**/*.parquet`, not `data/**.parquet`. `webmozart/glob` is no | `partitionBy(partition_by('date'))` - file body carries an all-null `date` column | file body without `date` | | `from_parquet()` types `date` from that body column, e.g. `datetime` | `string` - declare it: `from_parquet($path)->partitionTypes(partition_types(date: type_datetime()))` | -### 109) `flow-php/etl-adapter-postgresql` - a failed `from_pgsql_cursor()` read throws its own error and rolls back - -| Before | After | -|------------------------------------------------------------------------------------------------------------|---------------------------------------------------------| -| `QueryException` `[25P02] Invalid transaction state. SQL: CLOSE flow_cursor_...`, real error in `getPrevious()` | the failing statement's own `QueryException` | -| the client left inside an aborted transaction - every later query fails with `25P02` | the extractor's own transaction rolled back | -| a failure while reading rows (e.g. a row that does not match the schema) committed the transaction | rolled back | - -### 110) `flow-php/etl-adapter-postgresql` - `from_pgsql_*()` read exactly one read-only `SELECT` or `VALUES` statement - -| Query | Before | After | -|---------------------------------------------------------------------------|-----------------------------------------------|-----------------------------------------| -| `INSERT ... RETURNING` through `from_pgsql_cursor()` | the PHP process crashes (segfault) | `InvalidArgumentException`, nothing runs | -| `INSERT ... RETURNING` through `from_pgsql_key_set()` | the `INSERT` runs, then `QueryException` `08P01` | `InvalidArgumentException`, nothing runs | -| two statements through `from_pgsql_cursor()` | the second statement silently dropped | `InvalidArgumentException` | -| two statements through `from_pgsql_limit_offset()` / `from_pgsql_key_set()` | `QueryException` `42601` | `InvalidArgumentException` | -| a data-modifying `WITH` through `from_pgsql_key_set()` | the write runs once per page - an `INSERT` twice, an `UPDATE` never ends | `InvalidArgumentException`, nothing runs | -| `SELECT ... INTO` through `from_pgsql_key_set()` | the table is created | `InvalidArgumentException`, nothing runs | -| either through `from_pgsql_cursor()` / `from_pgsql_limit_offset()` | `QueryException` after a round trip | `InvalidArgumentException`, nothing runs | - -### 111) `flow-php/postgresql` - `declare_cursor()` over SQL takes exactly one `SELECT` or `VALUES` - -| Before | After | -|----------------------------------------------------------------------------------------|-----------------------------| -| `declare_cursor('c', 'INSERT INTO t VALUES (1) RETURNING id')->toSql()` - segfault | `InvalidArgumentException` | -| `declare_cursor('c', 'SELECT 1; SELECT 2')` - the second statement silently dropped | `InvalidArgumentException` | - -### 112) `flow-php/postgresql` - `SelectStatement::hasIntoClause()` sees `SELECT ... INTO` in a `UNION` / `INTERSECT` / `EXCEPT` - -| `sql_parse($sql)->statements()->first()->hasIntoClause()`, `$sql` | Before | After | -|-------------------------------------------------------------------|---------|--------| -| `SELECT id INTO t FROM x UNION SELECT 1` | `false` | `true` | - -### 113) `flow-php/postgresql` - `sql_to_*_query()` and the pagination modifiers take exactly one read-only `SELECT` or `VALUES` - -| Before | After | -|-------------------------------------------------------------------------------------|-----------------------------| -| `sql_to_paginated_query('UPDATE t SET a = 1 RETURNING id', 10)` - returned unchanged | `InvalidStatementException` | -| `sql_to_limited_query('SELECT 1; SELECT 2', 10)` - every statement paginated | `InvalidStatementException` | -| `sql_to_keyset_query()` over a data-modifying `WITH` - the write paginated | `InvalidStatementException` | -| `sql_to_count_query('SELECT id INTO t FROM x')` - counted | `InvalidStatementException` | - -Applies to `PaginationModifier`, `CountModifier` and `KeysetPaginationModifier` passed to `ParsedQuery::traverse()`. - -### 114) `flow-php/etl-adapter-postgresql` - `from_pgsql_limit_offset()` requires the query's own `ORDER BY` - -| Query | Before | After | -|--------------------------------------------------|-----------------------------|----------------------------| -| `SELECT * FROM (SELECT id FROM t ORDER BY id) s` | pages in no defined order | `InvalidArgumentException` | - --- ## Upgrading from 0.42.x to 0.43.x @@ -3350,6 +3513,8 @@ This applies to all Definition implementations: `BooleanDefinition`, `DateDefini | `FileExtractor::addFilter()` | `FileExtractor::withPathFilter()` | | `PathFiltering::addFilter()` | `PathFiltering::withPathFilter()` | +`withPathFilter()` is removed in 0.45 - see 8) of that version. + ### 7) Removed deprecated ScalarFunctionChain methods | Removed Method | Replacement | diff --git a/phpunit.xml.dist b/phpunit.xml.dist index ac21aa10de..81344c346a 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -202,6 +202,9 @@ src/bridge/telemetry/otlp/tests/Flow/Bridge/Telemetry/OTLP/Tests/Integration + + src/adapter/etl-adapter-avro/tests/Flow/ETL/Adapter/Avro/Tests/Unit + src/adapter/etl-adapter-avro/tests/Flow/ETL/Adapter/Avro/Tests/Integration diff --git a/src/adapter/etl-adapter-avro/src/Flow/ETL/Adapter/Avro/FlixTech/AvroExtractor.php b/src/adapter/etl-adapter-avro/src/Flow/ETL/Adapter/Avro/FlixTech/AvroExtractor.php index 6436d0e266..5bc3921307 100644 --- a/src/adapter/etl-adapter-avro/src/Flow/ETL/Adapter/Avro/FlixTech/AvroExtractor.php +++ b/src/adapter/etl-adapter-avro/src/Flow/ETL/Adapter/Avro/FlixTech/AvroExtractor.php @@ -15,6 +15,8 @@ use Flow\Filesystem\Filesystem; use Flow\Filesystem\Local\NativeLocalFilesystem; use Flow\Filesystem\Path; +use Flow\Filesystem\Path\Filter; +use Flow\Filesystem\Path\Filter\OnlyFiles; use Generator; final class AvroExtractor implements Extractor, FileExtractor @@ -32,7 +34,7 @@ public function __construct( ); } - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null, Filter $pathFilter = new OnlyFiles()): Generator { yield new Rows(new Schema()); } @@ -46,6 +48,12 @@ public function schema(): Schema throw SchemaNotDerivableException::extractor(self::class); } + public function partitionSchema(): Schema + { + // the constructor always throws, so no instance ever lists a partition + return new Schema(); + } + public function source(): Path { return $this->path; diff --git a/src/adapter/etl-adapter-avro/tests/Flow/ETL/Adapter/Avro/Tests/Unit/FlixTech/AvroExtractorTest.php b/src/adapter/etl-adapter-avro/tests/Flow/ETL/Adapter/Avro/Tests/Unit/FlixTech/AvroExtractorTest.php new file mode 100644 index 0000000000..26d331f1bd --- /dev/null +++ b/src/adapter/etl-adapter-avro/tests/Flow/ETL/Adapter/Avro/Tests/Unit/FlixTech/AvroExtractorTest.php @@ -0,0 +1,23 @@ +newInstanceWithoutConstructor()->partitionSchema(), + ); + } +} diff --git a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVExtractor.php b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVExtractor.php index f639930e8c..534ebc7af9 100644 --- a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVExtractor.php +++ b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVExtractor.php @@ -12,9 +12,7 @@ use Flow\ETL\Extractor\FileExtractor; use Flow\ETL\Extractor\FileReading; use Flow\ETL\Extractor\InfersSchema; -use Flow\ETL\Extractor\LimitPushDown; use Flow\ETL\Extractor\MetadataColumnsExtractor; -use Flow\ETL\Extractor\PushesLimit; use Flow\ETL\Extractor\RewindableExtractor; use Flow\ETL\Extractor\Signal; use Flow\ETL\FlowContext; @@ -27,6 +25,8 @@ use Flow\Filesystem\Filesystem; use Flow\Filesystem\Local\NativeLocalFilesystem; use Flow\Filesystem\Path; +use Flow\Filesystem\Path\Filter; +use Flow\Filesystem\Path\Filter\OnlyFiles; use Flow\Types\Type\Native\String\StringTypeNarrower; use Generator; @@ -42,12 +42,10 @@ final class CSVExtractor implements Extractor, FileExtractor, InfersSchema, - LimitPushDown, MetadataColumnsExtractor, RewindableExtractor { use Batches; - use PushesLimit; use FileReading; private SchemaInference $inference; @@ -85,13 +83,13 @@ public function isRepeatable(): bool /** * @return Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null, Filter $pathFilter = new OnlyFiles()): Generator { $hydrator = $context->hydrator(); $batchSize = $this->batchSize(); $yielded = 0; $fileColumns = $this->fileColumns($this->filesystem, $this->path); - $sources = iterator_to_array($this->sourceFiles($this->filesystem, $this->path), false); + $sources = iterator_to_array($this->sourceFiles($this->filesystem, $this->path, $pathFilter), false); $reader = new CSVFileReader(new CSVSourceOpener($this->filesystem, $this->readOptions), $sources); if ($this->schema !== null) { @@ -158,8 +156,6 @@ public function extract(FlowContext $context): Generator return; } - $limit = $this->pushedLimit(); - if ($limit !== null && $yielded >= $limit) { return; } @@ -219,6 +215,11 @@ public function schema(): Schema return $fileColumns->declare($fileColumns->withoutTail($derived)); } + public function partitionSchema(): Schema + { + return $this->fileColumns($this->filesystem, $this->path)->partitions($this->schema ?? new Schema()); + } + public function source(): Path { return $this->path; diff --git a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/CSVExtractorTest.php b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/CSVExtractorTest.php index ce505bbc6d..af2d2932f4 100644 --- a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/CSVExtractorTest.php +++ b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/CSVExtractorTest.php @@ -545,9 +545,7 @@ public function test_a_stream_is_closed_when_the_read_stops_early(string $mode): $extractor = from_csv(CSVFixtureContext::path('orders_flow.csv'), filesystem: $counting); if ($mode === 'limit') { - $extractor->pushLimit(2); - - iterator_to_array($extractor->extract(flow_context(config()))); + iterator_to_array($extractor->extract(flow_context(config()), limit: 2)); } else { $rows = $extractor->extract(flow_context(config())); $rows->current(); @@ -981,9 +979,9 @@ public function test_extracting_csv_with_multiline_strings(): void public function test_limit(): void { $extractor = from_csv(path_real(__DIR__ . '/../Fixtures/orders_flow.csv')); - $extractor->withBatchSize(1)->pushLimit(2); + $extractor->withBatchSize(1); - self::assertExtractedRowsCount(2, $extractor, flow_context(config())); + self::assertExtractedRowsCount(2, $extractor, flow_context(config()), limit: 2); } /** diff --git a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/CSVTest.php b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/CSVTest.php index 093786cf92..b0cb478ccd 100644 --- a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/CSVTest.php +++ b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/CSVTest.php @@ -28,7 +28,6 @@ use function Flow\ETL\DSL\select; use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\to_transformation; -use function Flow\ETL\DSL\write_with_retries; use function Flow\Filesystem\DSL\memory_filesystem; use function Flow\Filesystem\DSL\path; use function implode; @@ -106,14 +105,12 @@ public function test_loading_csv_files(): void } } - public function test_retry_loader_publishes_csv_under_overwrite(): void + public function test_a_batched_write_publishes_csv_under_overwrite(): void { df() ->read(from_array([['id' => 1], ['id' => 2], ['id' => 3], ['id' => 4]])) ->batchSize(2) - ->write(write_with_retries( - to_csv($path = __DIR__ . '/var/test_retry_loader_overwrite.csv')->saveMode(overwrite()), - )) + ->write(to_csv($path = __DIR__ . '/var/test_batched_write_overwrite.csv')->saveMode(overwrite())) ->run(); static::assertFileExists($path); @@ -124,7 +121,7 @@ public function test_retry_loader_publishes_csv_under_overwrite(): void } } - public function test_transformation_loader_writes_all_batches_to_csv(): void + public function test_a_transformation_sink_writes_all_batches_to_csv(): void { df() ->read(from_sequence_number('id', 1, 12)) @@ -174,7 +171,7 @@ public function test_writing_and_reading_csv_files_with_partition_placeholders() $prunedRows = df() ->read(from_csv($dir . '/year=*/{name}.csv')) - ->filterPartitions(ref('name')->equals(lit('789-DE'))) + ->filter(ref('name')->equals(lit('789-DE'))) ->fetch(); static::assertCount(1, $prunedRows); diff --git a/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/DbalKeySetExtractor.php b/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/DbalKeySetExtractor.php index 5516d0b16c..208bdc3d78 100644 --- a/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/DbalKeySetExtractor.php +++ b/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/DbalKeySetExtractor.php @@ -14,8 +14,6 @@ use Flow\ETL\Extractor; use Flow\ETL\Extractor\BatchableExtractor; use Flow\ETL\Extractor\Batches; -use Flow\ETL\Extractor\LimitPushDown; -use Flow\ETL\Extractor\PushesLimit; use Flow\ETL\Extractor\RewindableExtractor; use Flow\ETL\Extractor\Signal; use Flow\ETL\FlowContext; @@ -38,10 +36,9 @@ * and sort orders for pagination. The key columns must be non-null and provide a unique * ordering to ensure correct pagination. */ -final class DbalKeySetExtractor implements BatchableExtractor, Extractor, LimitPushDown, RewindableExtractor +final class DbalKeySetExtractor implements BatchableExtractor, Extractor, RewindableExtractor { use Batches; - use PushesLimit; private string $keyAliasSuffix = '_previous'; @@ -82,17 +79,16 @@ public function isRepeatable(): bool /** * @return Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { $schema = $this->schema(); $yielded = 0; $lastRow = null; $encoder = new DbalEncoder(); - $pushed = $this->pushedLimit(); $maximum = match (true) { - $this->maximum !== null && $pushed !== null => min($this->maximum, $pushed), + $this->maximum !== null && $limit !== null => min($this->maximum, $limit), $this->maximum !== null => $this->maximum, - default => $pushed, + default => $limit, }; $keyAliases = array_map($this->keyAlias(...), $this->keySet->keys); diff --git a/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/DbalLimitOffsetExtractor.php b/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/DbalLimitOffsetExtractor.php index 424fc9ba02..e48762273c 100644 --- a/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/DbalLimitOffsetExtractor.php +++ b/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/DbalLimitOffsetExtractor.php @@ -11,8 +11,6 @@ use Flow\ETL\Extractor; use Flow\ETL\Extractor\BatchableExtractor; use Flow\ETL\Extractor\Batches; -use Flow\ETL\Extractor\LimitPushDown; -use Flow\ETL\Extractor\PushesLimit; use Flow\ETL\Extractor\RewindableExtractor; use Flow\ETL\Extractor\Signal; use Flow\ETL\FlowContext; @@ -24,10 +22,9 @@ use function is_numeric; use function min; -final class DbalLimitOffsetExtractor implements BatchableExtractor, Extractor, LimitPushDown, RewindableExtractor +final class DbalLimitOffsetExtractor implements BatchableExtractor, Extractor, RewindableExtractor { use Batches; - use PushesLimit; private ?int $maximum = null; @@ -76,7 +73,7 @@ public function isRepeatable(): bool /** * @return Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { $schema = $this->schema(); @@ -87,12 +84,10 @@ public function extract(FlowContext $context): Generator if ($this->offset === 0 && $this->queryBuilder->getFirstResult()) { $this->offset = $this->queryBuilder->getFirstResult(); } - - $pushed = $this->pushedLimit(); $maximum = match (true) { - $this->maximum !== null && $pushed !== null => min($this->maximum, $pushed), + $this->maximum !== null && $limit !== null => min($this->maximum, $limit), $this->maximum !== null => $this->maximum, - default => $pushed, + default => $limit, }; if (null !== $maximum) { diff --git a/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/DbalQueryExtractor.php b/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/DbalQueryExtractor.php index 394e387036..83728fd81c 100644 --- a/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/DbalQueryExtractor.php +++ b/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/DbalQueryExtractor.php @@ -12,8 +12,6 @@ use Flow\ETL\Extractor; use Flow\ETL\Extractor\BatchableExtractor; use Flow\ETL\Extractor\Batches; -use Flow\ETL\Extractor\LimitPushDown; -use Flow\ETL\Extractor\PushesLimit; use Flow\ETL\Extractor\RewindableExtractor; use Flow\ETL\Extractor\Signal; use Flow\ETL\FlowContext; @@ -31,10 +29,9 @@ * A pushed limit is global across parameter sets - their batches are concatenated - and no set is queried * once it is reached. The query is a raw string, so the first queried set is never bounded server-side. */ -final class DbalQueryExtractor implements BatchableExtractor, Extractor, LimitPushDown, RewindableExtractor +final class DbalQueryExtractor implements BatchableExtractor, Extractor, RewindableExtractor { use Batches; - use PushesLimit; private ParametersSet $parametersSet; @@ -87,16 +84,15 @@ public static function single( /** * @return Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { $schema = $this->schema(); $hydrator = $context->hydrator(); $encoder = new DbalEncoder(); $yielded = 0; - $maximum = $this->pushedLimit(); foreach ($this->parametersSet->all() as $parameters) { - if ($maximum !== null && $yielded >= $maximum) { + if ($limit !== null && $yielded >= $limit) { return; } @@ -122,7 +118,7 @@ public function extract(FlowContext $context): Generator $buffer = []; - if ($maximum !== null && $yielded >= $maximum) { + if ($limit !== null && $yielded >= $limit) { return; } } diff --git a/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/DbalTransaction.php b/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/DbalTransaction.php new file mode 100644 index 0000000000..d72fbe264a --- /dev/null +++ b/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/DbalTransaction.php @@ -0,0 +1,102 @@ + $connectionParams + */ + public function __construct(array $connectionParams) + { + /** @var Params $connectionParams */ + $this->connectionParams = $connectionParams; + } + + /** + * Since Connection::getParams() is marked as an internal method, please use this constructor with caution. + */ + public static function fromConnection(Connection $connection): self + { + $transaction = new self($connection->getParams()); + $transaction->connection = $connection; + + return $transaction; + } + + /** + * The previous level is restored when the transaction ends, so the user's Connection is never left changed. + */ + public function withIsolationLevel(TransactionIsolationLevel $level): self + { + $transaction = new self($this->connectionParams); + $transaction->connection = $this->connection; + $transaction->isolationLevel = $level; + + return $transaction; + } + + public function begin(): void + { + $connection = $this->connection ??= DriverManager::getConnection($this->connectionParams); + + if ($this->isolationLevel !== null) { + $this->restore = new IsolationLevelRestore($connection, $connection->getTransactionIsolation()); + $connection->setTransactionIsolation($this->isolationLevel); + } + + try { + $connection->beginTransaction(); + } catch (Throwable $failure) { + $this->restore?->restore(); + $this->restore = null; + + throw $failure; + } + } + + /** + * A failed commit keeps the changed level: the transaction is still open, so the rollback() that follows restores it. + */ + public function commit(): void + { + ($this->connection ??= DriverManager::getConnection($this->connectionParams))->commit(); + + $this->restore?->restore(); + $this->restore = null; + } + + public function rollback(Throwable $cause): void + { + try { + ($this->connection ??= DriverManager::getConnection($this->connectionParams))->rollBack(); + } catch (Throwable) { + // $cause is the actionable failure - a rollback failure must not mask it + } finally { + $this->restore?->restore(); + $this->restore = null; + } + } +} diff --git a/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/IsolationLevelRestore.php b/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/IsolationLevelRestore.php new file mode 100644 index 0000000000..1eb73edf54 --- /dev/null +++ b/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/IsolationLevelRestore.php @@ -0,0 +1,29 @@ +connection->setTransactionIsolation($this->previous); + } catch (Throwable) { + // restoring connection state must not mask an in-flight failure + } + } +} diff --git a/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/PlaceholderRewriter.php b/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/PlaceholderRewriter.php index 005b5ebf92..c2c61c20f8 100644 --- a/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/PlaceholderRewriter.php +++ b/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/PlaceholderRewriter.php @@ -10,7 +10,7 @@ use function implode; /** - * @internal implements a DBAL-internal Visitor; use NativePlaceholders instead + * Implements a DBAL-internal Visitor; use NativePlaceholders instead. */ final class PlaceholderRewriter implements Visitor { diff --git a/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/TransactionalDbalLoader.php b/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/TransactionalDbalLoader.php deleted file mode 100644 index 92573fb196..0000000000 --- a/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/TransactionalDbalLoader.php +++ /dev/null @@ -1,162 +0,0 @@ - - */ - private readonly array $loaders; - - /** - * @param array $connectionParams - * @param Loader ...$loaders - */ - public function __construct( - private readonly array $connectionParams, - Loader ...$loaders, - ) { - if (count($loaders) === 0) { - throw new InvalidArgumentException('At least one loader must be provided'); - } - - $this->loaders = $loaders; - } - - /** - * Since Connection::getParams() is marked as an internal method, please - * use this constructor with caution. - */ - public static function fromConnection(Connection $connection, Loader ...$loaders): self - { - $loader = new self($connection->getParams(), ...$loaders); - $loader->connection = $connection; - - return $loader; - } - - /** - * Rows a wrapped Transformation buffered (blocking operations - sortBy, aggregate, groupBy->aggregate, - * pivot, window functions, collect, join) are delivered during the forwarded closure() drain, so delivery - * here must be transactional too: one transaction over everything the drain flushes, rolled back when it fails. - */ - public function closure(FlowContext $context): void - { - $this->inTransaction($this->connection(), function () use ($context): void { - foreach ($this->loaders as $loader) { - if ($loader instanceof Closure) { - $loader->closure($context); - } - } - }); - } - - public function load(Rows $rows, FlowContext $context): void - { - if ($rows->count() === 0) { - return; - } - - $context->telemetry()->loadingStarted($this); - - try { - $this->inTransaction($this->connection(), function () use ($rows, $context): void { - foreach ($this->loaders as $loader) { - $loader->load($rows, $context); - } - }); - - $context->telemetry()->loadingCompleted($this, [TelemetryAttributes::ATTR_LOADING_ROWS => $rows->count()]); - } catch (Throwable $e) { - $context->telemetry()->loadingFailed($this, $e); - - throw $e; - } - } - - public function loaders(): array - { - return $this->loaders; - } - - public function withIsolationLevel(TransactionIsolationLevel $level): self - { - $this->isolationLevel = $level; - - return $this; - } - - private function connection(): Connection - { - if ($this->connection === null) { - /** @var Params $connectionParams */ - $connectionParams = $this->connectionParams; - $this->connection = DriverManager::getConnection($connectionParams); - } - - return $this->connection; - } - - /** - * @param callable(): void $operation - */ - private function inTransaction(Connection $connection, callable $operation): void - { - $previousIsolationLevel = null; - - if ($this->isolationLevel !== null) { - $previousIsolationLevel = $connection->getTransactionIsolation(); - $connection->setTransactionIsolation($this->isolationLevel); - } - - try { - $connection->beginTransaction(); - - try { - $operation(); - - $connection->commit(); - } catch (Throwable $e) { - try { - $connection->rollBack(); - } catch (Throwable) { - // the load/drain failure is the actionable error - a rollback failure must not mask it - } - - throw $e; - } - } finally { - if ($previousIsolationLevel !== null) { - try { - $connection->setTransactionIsolation($previousIsolationLevel); - } catch (Throwable) { - // restoring connection state must not mask an in-flight failure - } - } - } - } -} diff --git a/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/functions.php b/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/functions.php index 896ac49790..11b4e78c41 100644 --- a/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/functions.php +++ b/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/functions.php @@ -26,6 +26,8 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Loader; use Flow\ETL\Schema; +use Flow\ETL\Sink; +use Flow\ETL\Sink\Transactional; use function is_array; use function is_string; @@ -318,25 +320,27 @@ function postgresql_update_options(array $primary_key_columns = [], array $updat } /** - * Execute multiple loaders within database transactions. - * Each batch of rows is loaded in its own transaction; rows a wrapped Transformation delivers when - * the loader is closed (blocking operations drain there) are committed in one final transaction. - * If any loader fails, the open transaction is rolled back. - * Atomicity requires every wrapped loader to use the same connection as the wrapper: pass one live - * Connection to both - a wrapped loader built from array params opens its own connection and - * escapes the transaction. + * Write every sink within database transactions. + * Each batch of rows is written in its own transaction; rows a sink's Transformation delivers when + * the run ends (blocking operations drain there) are committed in one final transaction. + * If any sink fails, the open transaction is rolled back. + * A plain Loader child is a bare sink root; a to_transformation(...) child delivers inside the same + * transaction. Every child's loader must use the same connection as the transaction: pass one live + * Connection to both - a loader built from array params opens its own connection and escapes the + * transaction. * * @param array|Connection $connection - * @param Loader ...$loaders - Loaders to execute within the transaction + * @param Loader|Sink ...$sinks - sinks written within the transaction * * @throws InvalidArgumentException */ #[DocumentationDSL(module: Module::DOCTRINE, type: DSLType::LOADER)] -function to_dbal_transaction(array|Connection $connection, Loader ...$loaders): TransactionalDbalLoader +function to_dbal_transaction(array|Connection $connection, Loader|Sink ...$sinks): Transactional { - return is_array($connection) - ? new TransactionalDbalLoader($connection, ...$loaders) - : TransactionalDbalLoader::fromConnection($connection, ...$loaders); + return new Transactional( + is_array($connection) ? new DbalTransaction($connection) : DbalTransaction::fromConnection($connection), + ...$sinks, + ); } #[DocumentationDSL(module: Module::DOCTRINE, type: DSLType::HELPER)] diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Context/CommitCounter.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Context/CommitCounter.php new file mode 100644 index 0000000000..62e919705f --- /dev/null +++ b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Context/CommitCounter.php @@ -0,0 +1,20 @@ +count++; + } + } +} diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Context/DatabaseContext.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Context/DatabaseContext.php index 9b64b4005e..4b59d7adfb 100644 --- a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Context/DatabaseContext.php +++ b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Context/DatabaseContext.php @@ -22,6 +22,7 @@ public function __construct( private readonly Connection $connection, private readonly InsertQueryCounter $insertQueryCounter, private readonly SelectQueryCounter $selectQueryCounter, + private readonly CommitCounter $commitCounter, ) {} public function connection(): Connection @@ -69,6 +70,11 @@ public function insert(string $tableName, array $data, array $types = []): void $this->connection->insert($tableName, $data, $doctrineTypes); } + public function numberOfCommits(): int + { + return $this->commitCounter->count; + } + public function numberOfExecutedInsertQueries(): int { return $this->insertQueryCounter->count; diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/MySQLTransactionalDbalLoaderTest.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/MySQLTransactionSinkTest.php similarity index 66% rename from src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/MySQLTransactionalDbalLoaderTest.php rename to src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/MySQLTransactionSinkTest.php index e2dca605bd..b5d7764ce9 100644 --- a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/MySQLTransactionalDbalLoaderTest.php +++ b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/MySQLTransactionSinkTest.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Adapter\Doctrine\Tests\Integration\Dialects; +use Doctrine\DBAL\Exception\UniqueConstraintViolationException; use Doctrine\DBAL\Schema\Column; use Doctrine\DBAL\Schema\PrimaryKeyConstraint; use Doctrine\DBAL\Schema\Table; @@ -11,13 +12,15 @@ use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Types\Types; use Exception; +use Flow\ETL\Adapter\Doctrine\DbalTransaction; use Flow\ETL\Adapter\Doctrine\Tests\IntegrationTestCase; +use Flow\ETL\Sink\Transactional; use function Flow\ETL\Adapter\Doctrine\to_dbal_table_delete; use function Flow\ETL\Adapter\Doctrine\to_dbal_table_insert; use function Flow\ETL\Adapter\Doctrine\to_dbal_transaction; -use function Flow\ETL\DSL\config; -use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\df; +use function Flow\ETL\DSL\from_rows; use function Flow\ETL\DSL\integer_schema; use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\rows; @@ -25,7 +28,7 @@ use function Flow\ETL\DSL\string_schema; use function getenv; -final class MySQLTransactionalDbalLoaderTest extends IntegrationTestCase +final class MySQLTransactionSinkTest extends IntegrationTestCase { public function test_multiple_batches_in_separate_transactions(): void { @@ -43,15 +46,16 @@ public function test_multiple_batches_in_separate_transactions(): void $connection = $this->mysqlDatabaseContext->connection(); - $loader = to_dbal_transaction($connection, to_dbal_table_insert($connection, 'test_table')); + df() + ->read(from_rows( + rows(schema(integer_schema('id'), integer_schema('value')), row(['id' => 1, 'value' => 100])), + rows(schema(integer_schema('id'), integer_schema('value')), row(['id' => 2, 'value' => 200])), + )) + ->write(to_dbal_transaction($connection, to_dbal_table_insert($connection, 'test_table'))) + ->run(); - $batch1 = rows(schema(integer_schema('id'), integer_schema('value')), row(['id' => 1, 'value' => 100])); - $batch2 = rows(schema(integer_schema('id'), integer_schema('value')), row(['id' => 2, 'value' => 200])); - - $context = flow_context(config()); - - $loader->load($batch1, $context); - $loader->load($batch2, $context); + // one commit per batch, one for the drain + static::assertSame(3, $this->mysqlDatabaseContext->numberOfCommits()); $result = $this->mysqlDatabaseContext->selectAll('test_table'); @@ -80,19 +84,26 @@ public function test_rollback_on_failure(): void $connection = $this->mysqlDatabaseContext->connection(); - $rows = rows(schema(integer_schema('id'), string_schema('name')), row(['id' => 1, 'name' => 'Should fail'])); - - $loader = to_dbal_transaction( - $connection, - to_dbal_table_delete($connection, 'test_table'), - to_dbal_table_insert($connection, 'test_table'), - ); + $thrown = null; try { - $loader->load($rows, flow_context(config())); - } catch (Exception) { + df() + ->read(from_rows(rows( + schema(integer_schema('id'), string_schema('name')), + row(['id' => 1, 'name' => 'Should fail']), + ))) + ->write(to_dbal_transaction( + $connection, + to_dbal_table_delete($connection, 'test_table'), + to_dbal_table_insert($connection, 'test_table'), + )) + ->run(); + } catch (Exception $e) { + $thrown = $e; } + static::assertInstanceOf(UniqueConstraintViolationException::class, $thrown); + $result = $this->mysqlDatabaseContext->selectAll('test_table'); static::assertCount(2, $result); @@ -118,19 +129,18 @@ public function test_transactional_delete_and_insert(): void $connection = $this->mysqlDatabaseContext->connection(); - $rows = rows( - schema(integer_schema('id'), string_schema('name')), - row(['id' => 1, 'name' => 'Updated']), - row(['id' => 2, 'name' => 'Updated']), - ); - - $loader = to_dbal_transaction( - $connection, - to_dbal_table_delete($connection, 'test_table'), - to_dbal_table_insert($connection, 'test_table'), - ); - - $loader->load($rows, flow_context(config())); + df() + ->read(from_rows(rows( + schema(integer_schema('id'), string_schema('name')), + row(['id' => 1, 'name' => 'Updated']), + row(['id' => 2, 'name' => 'Updated']), + ))) + ->write(to_dbal_transaction( + $connection, + to_dbal_table_delete($connection, 'test_table'), + to_dbal_table_insert($connection, 'test_table'), + )) + ->run(); $result = $this->mysqlDatabaseContext->selectAll('test_table'); @@ -157,14 +167,20 @@ public function test_with_isolation_level(): void $connection = $this->mysqlDatabaseContext->connection(); - $rows = rows(schema(integer_schema('id'), string_schema('name')), row(['id' => 1, 'name' => 'Test'])); - - $loader = to_dbal_transaction($connection, to_dbal_table_insert( - $connection, - 'test_table', - ))->withIsolationLevel(TransactionIsolationLevel::SERIALIZABLE); - - $loader->load($rows, flow_context(config())); + df() + ->read(from_rows(rows( + schema(integer_schema('id'), string_schema('name')), + row(['id' => 1, 'name' => 'Test']), + ))) + ->write( + new Transactional( + DbalTransaction::fromConnection( + $connection, + )->withIsolationLevel(TransactionIsolationLevel::SERIALIZABLE), + to_dbal_table_insert($connection, 'test_table'), + ), + ) + ->run(); $result = $this->mysqlDatabaseContext->selectAll('test_table'); diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/PostgreSQLTransactionalDbalLoaderTest.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/PostgreSQLTransactionSinkTest.php similarity index 66% rename from src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/PostgreSQLTransactionalDbalLoaderTest.php rename to src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/PostgreSQLTransactionSinkTest.php index 32dccc7551..95ce25b075 100644 --- a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/PostgreSQLTransactionalDbalLoaderTest.php +++ b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/PostgreSQLTransactionSinkTest.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Adapter\Doctrine\Tests\Integration\Dialects; +use Doctrine\DBAL\Exception\UniqueConstraintViolationException; use Doctrine\DBAL\Schema\Column; use Doctrine\DBAL\Schema\PrimaryKeyConstraint; use Doctrine\DBAL\Schema\Table; @@ -11,13 +12,15 @@ use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Types\Types; use Exception; +use Flow\ETL\Adapter\Doctrine\DbalTransaction; use Flow\ETL\Adapter\Doctrine\Tests\IntegrationTestCase; +use Flow\ETL\Sink\Transactional; use function Flow\ETL\Adapter\Doctrine\to_dbal_table_delete; use function Flow\ETL\Adapter\Doctrine\to_dbal_table_insert; use function Flow\ETL\Adapter\Doctrine\to_dbal_transaction; -use function Flow\ETL\DSL\config; -use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\df; +use function Flow\ETL\DSL\from_rows; use function Flow\ETL\DSL\integer_schema; use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\rows; @@ -25,7 +28,7 @@ use function Flow\ETL\DSL\string_schema; use function getenv; -final class PostgreSQLTransactionalDbalLoaderTest extends IntegrationTestCase +final class PostgreSQLTransactionSinkTest extends IntegrationTestCase { public function test_multiple_batches_in_separate_transactions(): void { @@ -43,15 +46,16 @@ public function test_multiple_batches_in_separate_transactions(): void $connection = $this->pgsqlDatabaseContext->connection(); - $loader = to_dbal_transaction($connection, to_dbal_table_insert($connection, 'test_table')); + df() + ->read(from_rows( + rows(schema(integer_schema('id'), integer_schema('value')), row(['id' => 1, 'value' => 100])), + rows(schema(integer_schema('id'), integer_schema('value')), row(['id' => 2, 'value' => 200])), + )) + ->write(to_dbal_transaction($connection, to_dbal_table_insert($connection, 'test_table'))) + ->run(); - $batch1 = rows(schema(integer_schema('id'), integer_schema('value')), row(['id' => 1, 'value' => 100])); - $batch2 = rows(schema(integer_schema('id'), integer_schema('value')), row(['id' => 2, 'value' => 200])); - - $context = flow_context(config()); - - $loader->load($batch1, $context); - $loader->load($batch2, $context); + // one commit per batch, one for the drain + static::assertSame(3, $this->pgsqlDatabaseContext->numberOfCommits()); $result = $this->pgsqlDatabaseContext->selectAll('test_table'); @@ -80,19 +84,26 @@ public function test_rollback_on_failure(): void $connection = $this->pgsqlDatabaseContext->connection(); - $rows = rows(schema(integer_schema('id'), string_schema('name')), row(['id' => 1, 'name' => 'Should fail'])); - - $loader = to_dbal_transaction( - $connection, - to_dbal_table_delete($connection, 'test_table'), - to_dbal_table_insert($connection, 'test_table'), - ); + $thrown = null; try { - $loader->load($rows, flow_context(config())); - } catch (Exception) { + df() + ->read(from_rows(rows( + schema(integer_schema('id'), string_schema('name')), + row(['id' => 1, 'name' => 'Should fail']), + ))) + ->write(to_dbal_transaction( + $connection, + to_dbal_table_delete($connection, 'test_table'), + to_dbal_table_insert($connection, 'test_table'), + )) + ->run(); + } catch (Exception $e) { + $thrown = $e; } + static::assertInstanceOf(UniqueConstraintViolationException::class, $thrown); + $result = $this->pgsqlDatabaseContext->selectAll('test_table'); static::assertCount(2, $result); @@ -118,19 +129,18 @@ public function test_transactional_delete_and_insert(): void $connection = $this->pgsqlDatabaseContext->connection(); - $rows = rows( - schema(integer_schema('id'), string_schema('name')), - row(['id' => 1, 'name' => 'Updated']), - row(['id' => 2, 'name' => 'Updated']), - ); - - $loader = to_dbal_transaction( - $connection, - to_dbal_table_delete($connection, 'test_table'), - to_dbal_table_insert($connection, 'test_table'), - ); - - $loader->load($rows, flow_context(config())); + df() + ->read(from_rows(rows( + schema(integer_schema('id'), string_schema('name')), + row(['id' => 1, 'name' => 'Updated']), + row(['id' => 2, 'name' => 'Updated']), + ))) + ->write(to_dbal_transaction( + $connection, + to_dbal_table_delete($connection, 'test_table'), + to_dbal_table_insert($connection, 'test_table'), + )) + ->run(); $result = $this->pgsqlDatabaseContext->selectAll('test_table'); @@ -157,14 +167,20 @@ public function test_with_isolation_level(): void $connection = $this->pgsqlDatabaseContext->connection(); - $rows = rows(schema(integer_schema('id'), string_schema('name')), row(['id' => 1, 'name' => 'Test'])); - - $loader = to_dbal_transaction($connection, to_dbal_table_insert( - $connection, - 'test_table', - ))->withIsolationLevel(TransactionIsolationLevel::SERIALIZABLE); - - $loader->load($rows, flow_context(config())); + df() + ->read(from_rows(rows( + schema(integer_schema('id'), string_schema('name')), + row(['id' => 1, 'name' => 'Test']), + ))) + ->write( + new Transactional( + DbalTransaction::fromConnection( + $connection, + )->withIsolationLevel(TransactionIsolationLevel::SERIALIZABLE), + to_dbal_table_insert($connection, 'test_table'), + ), + ) + ->run(); $result = $this->pgsqlDatabaseContext->selectAll('test_table'); diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/SqliteTransactionalDbalLoaderTest.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/SqliteTransactionSinkTest.php similarity index 66% rename from src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/SqliteTransactionalDbalLoaderTest.php rename to src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/SqliteTransactionSinkTest.php index a9b10b9e3f..082d2e69e7 100644 --- a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/SqliteTransactionalDbalLoaderTest.php +++ b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/SqliteTransactionSinkTest.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Adapter\Doctrine\Tests\Integration\Dialects; +use Doctrine\DBAL\Exception\UniqueConstraintViolationException; use Doctrine\DBAL\Schema\Column; use Doctrine\DBAL\Schema\PrimaryKeyConstraint; use Doctrine\DBAL\Schema\Table; @@ -11,13 +12,15 @@ use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Types\Types; use Exception; +use Flow\ETL\Adapter\Doctrine\DbalTransaction; use Flow\ETL\Adapter\Doctrine\Tests\IntegrationTestCase; +use Flow\ETL\Sink\Transactional; use function Flow\ETL\Adapter\Doctrine\to_dbal_table_delete; use function Flow\ETL\Adapter\Doctrine\to_dbal_table_insert; use function Flow\ETL\Adapter\Doctrine\to_dbal_transaction; -use function Flow\ETL\DSL\config; -use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\df; +use function Flow\ETL\DSL\from_rows; use function Flow\ETL\DSL\integer_schema; use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\rows; @@ -25,7 +28,7 @@ use function Flow\ETL\DSL\string_schema; use function getenv; -final class SqliteTransactionalDbalLoaderTest extends IntegrationTestCase +final class SqliteTransactionSinkTest extends IntegrationTestCase { public function test_multiple_batches_in_separate_transactions(): void { @@ -43,15 +46,16 @@ public function test_multiple_batches_in_separate_transactions(): void $connection = $this->sqliteDatabaseContext->connection(); - $loader = to_dbal_transaction($connection, to_dbal_table_insert($connection, 'test_table')); + df() + ->read(from_rows( + rows(schema(integer_schema('id'), integer_schema('value')), row(['id' => 1, 'value' => 100])), + rows(schema(integer_schema('id'), integer_schema('value')), row(['id' => 2, 'value' => 200])), + )) + ->write(to_dbal_transaction($connection, to_dbal_table_insert($connection, 'test_table'))) + ->run(); - $batch1 = rows(schema(integer_schema('id'), integer_schema('value')), row(['id' => 1, 'value' => 100])); - $batch2 = rows(schema(integer_schema('id'), integer_schema('value')), row(['id' => 2, 'value' => 200])); - - $context = flow_context(config()); - - $loader->load($batch1, $context); - $loader->load($batch2, $context); + // one commit per batch, one for the drain + static::assertSame(3, $this->sqliteDatabaseContext->numberOfCommits()); $result = $this->sqliteDatabaseContext->selectAll('test_table'); @@ -80,19 +84,26 @@ public function test_rollback_on_failure(): void $connection = $this->sqliteDatabaseContext->connection(); - $rows = rows(schema(integer_schema('id'), string_schema('name')), row(['id' => 1, 'name' => 'Should fail'])); - - $loader = to_dbal_transaction( - $connection, - to_dbal_table_delete($connection, 'test_table'), - to_dbal_table_insert($connection, 'test_table'), - ); + $thrown = null; try { - $loader->load($rows, flow_context(config())); - } catch (Exception) { + df() + ->read(from_rows(rows( + schema(integer_schema('id'), string_schema('name')), + row(['id' => 1, 'name' => 'Should fail']), + ))) + ->write(to_dbal_transaction( + $connection, + to_dbal_table_delete($connection, 'test_table'), + to_dbal_table_insert($connection, 'test_table'), + )) + ->run(); + } catch (Exception $e) { + $thrown = $e; } + static::assertInstanceOf(UniqueConstraintViolationException::class, $thrown); + $result = $this->sqliteDatabaseContext->selectAll('test_table'); static::assertCount(2, $result); @@ -118,19 +129,18 @@ public function test_transactional_delete_and_insert(): void $connection = $this->sqliteDatabaseContext->connection(); - $rows = rows( - schema(integer_schema('id'), string_schema('name')), - row(['id' => 1, 'name' => 'Updated']), - row(['id' => 2, 'name' => 'Updated']), - ); - - $loader = to_dbal_transaction( - $connection, - to_dbal_table_delete($connection, 'test_table'), - to_dbal_table_insert($connection, 'test_table'), - ); - - $loader->load($rows, flow_context(config())); + df() + ->read(from_rows(rows( + schema(integer_schema('id'), string_schema('name')), + row(['id' => 1, 'name' => 'Updated']), + row(['id' => 2, 'name' => 'Updated']), + ))) + ->write(to_dbal_transaction( + $connection, + to_dbal_table_delete($connection, 'test_table'), + to_dbal_table_insert($connection, 'test_table'), + )) + ->run(); $result = $this->sqliteDatabaseContext->selectAll('test_table'); @@ -157,14 +167,20 @@ public function test_with_isolation_level(): void $connection = $this->sqliteDatabaseContext->connection(); - $rows = rows(schema(integer_schema('id'), string_schema('name')), row(['id' => 1, 'name' => 'Test'])); - - $loader = to_dbal_transaction($connection, to_dbal_table_insert( - $connection, - 'test_table', - ))->withIsolationLevel(TransactionIsolationLevel::SERIALIZABLE); - - $loader->load($rows, flow_context(config())); + df() + ->read(from_rows(rows( + schema(integer_schema('id'), string_schema('name')), + row(['id' => 1, 'name' => 'Test']), + ))) + ->write( + new Transactional( + DbalTransaction::fromConnection( + $connection, + )->withIsolationLevel(TransactionIsolationLevel::SERIALIZABLE), + to_dbal_table_insert($connection, 'test_table'), + ), + ) + ->run(); $result = $this->sqliteDatabaseContext->selectAll('test_table'); diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/IntegrationTestCase.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/IntegrationTestCase.php index e1d00c361e..a7885dfa77 100644 --- a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/IntegrationTestCase.php +++ b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/IntegrationTestCase.php @@ -8,6 +8,7 @@ use Doctrine\DBAL\DriverManager; use Doctrine\DBAL\Logging\Middleware; use Doctrine\DBAL\Tools\DsnParser; +use Flow\ETL\Adapter\Doctrine\Tests\Context\CommitCounter; use Flow\ETL\Adapter\Doctrine\Tests\Context\DatabaseContext; use Flow\ETL\Adapter\Doctrine\Tests\Context\InsertQueryCounter; use Flow\ETL\Adapter\Doctrine\Tests\Context\SelectQueryCounter; @@ -32,15 +33,18 @@ protected function setUp(): void { $insertQueryCounter = new InsertQueryCounter(); $selectQueryCounter = new SelectQueryCounter(); + $commitCounter = new CommitCounter(); $pgsqlParams = $this->postgresqlConnectionParams(); $this->pgsqlDatabaseContext = new DatabaseContext( DriverManager::getConnection($pgsqlParams, (new Configuration())->setMiddlewares([ new Middleware($insertQueryCounter), new Middleware($selectQueryCounter), + new Middleware($commitCounter), ])), $insertQueryCounter, $selectQueryCounter, + $commitCounter, ); $mysqlParams = $this->mysqlConnectionParams(); @@ -48,9 +52,11 @@ protected function setUp(): void DriverManager::getConnection($mysqlParams, (new Configuration())->setMiddlewares([ new Middleware($insertQueryCounter), new Middleware($selectQueryCounter), + new Middleware($commitCounter), ])), $insertQueryCounter, $selectQueryCounter, + $commitCounter, ); $sqliteParams = $this->sqliteConnectionParams(); @@ -58,9 +64,11 @@ protected function setUp(): void DriverManager::getConnection($sqliteParams, (new Configuration())->setMiddlewares([ new Middleware($insertQueryCounter), new Middleware($selectQueryCounter), + new Middleware($commitCounter), ])), $insertQueryCounter, $selectQueryCounter, + $commitCounter, ); } diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/DbalKeySetExtractorTest.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/DbalKeySetExtractorTest.php index e3984f0f98..7076e5bf52 100644 --- a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/DbalKeySetExtractorTest.php +++ b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/DbalKeySetExtractorTest.php @@ -103,10 +103,9 @@ public function test_pushed_limit_issues_no_query_once_satisfied(): void $connection->createQueryBuilder()->select('*')->from('users'), pagination_key_set(pagination_key_asc('id')), ); - $extractor->pushLimit(1500); $counter->reset(); - self::assertExtractedRowsCount(1500, $extractor); + self::assertExtractedRowsCount(1500, $extractor, limit: 1500); // 1000, then a page narrowed to the 500 still wanted - and no third query for row 1501 static::assertSame(2, $counter->count); } diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/DbalLimitOffsetExtractorTest.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/DbalLimitOffsetExtractorTest.php index 9c7e5cdd18..68e4d9bfbe 100644 --- a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/DbalLimitOffsetExtractorTest.php +++ b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/DbalLimitOffsetExtractorTest.php @@ -207,10 +207,9 @@ public function test_pushed_limit_skips_the_count_query(): void $connection, $connection->createQueryBuilder()->select('*')->from('users')->orderBy('id'), ))->withBatchSize(2); - $extractor->pushLimit(5); $counter->reset(); - self::assertExtractedRowsCount(5, $extractor); + self::assertExtractedRowsCount(5, $extractor, limit: 5); // the three pages of the unlimited read, without the COUNT(*) in front of them static::assertSame(3, $counter->count); static::assertStringNotContainsString('COUNT(*)', implode(' ', $counter->queries)); diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/DbalQueryExtractorTest.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/DbalQueryExtractorTest.php index d1a0bbcb50..18257d0bb7 100644 --- a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/DbalQueryExtractorTest.php +++ b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/DbalQueryExtractorTest.php @@ -120,11 +120,10 @@ public function test_pushed_limit_stops_querying_further_parameter_sets(int $bat new ParametersSet(['min' => 0, 'max' => 10], ['min' => 10, 'max' => 20], ['min' => 20, 'max' => 30]), ) ->withBatchSize($batchSize); - $extractor->pushLimit(5); $counter->reset(); // at 100 the first set is one batch that overshoots the limit - trimming it is the limit operator's job - self::assertExtractedRowsCount($extractedRows, $extractor); + self::assertExtractedRowsCount($extractedRows, $extractor, limit: 5); static::assertSame(1, $counter->count); } diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/TransactionalDbalLoaderTransformationTest.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/DbalTransactionSinkTest.php similarity index 76% rename from src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/TransactionalDbalLoaderTransformationTest.php rename to src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/DbalTransactionSinkTest.php index 2c2d466233..cae29ca424 100644 --- a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/TransactionalDbalLoaderTransformationTest.php +++ b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/DbalTransactionSinkTest.php @@ -10,18 +10,20 @@ use Doctrine\DBAL\TransactionIsolationLevel; use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Types\Types; +use Flow\ETL\Adapter\Doctrine\DbalTransaction; +use Flow\ETL\Adapter\Doctrine\Tests\Context\CommitCounter; use Flow\ETL\Adapter\Doctrine\Tests\Context\DatabaseContext; use Flow\ETL\Adapter\Doctrine\Tests\Context\InsertQueryCounter; use Flow\ETL\Adapter\Doctrine\Tests\Context\SelectQueryCounter; use Flow\ETL\Adapter\Doctrine\Tests\Double\TransactionSpyLoader; use Flow\ETL\DataFrame; +use Flow\ETL\Sink\Transactional; use Flow\ETL\Tests\Double\CallbackTransformation; use Flow\ETL\Tests\Double\ClosureThrowingLoader; use Flow\ETL\Tests\Double\LoadThenThrowLoader; use Flow\ETL\Tests\FlowTestCase; use RuntimeException; -use function array_column; use function Flow\ETL\Adapter\Doctrine\to_dbal_table_insert; use function Flow\ETL\Adapter\Doctrine\to_dbal_transaction; use function Flow\ETL\DSL\df; @@ -32,12 +34,17 @@ use function Flow\ETL\DSL\to_branch; use function Flow\ETL\DSL\to_transformation; -final class TransactionalDbalLoaderTransformationTest extends FlowTestCase +final class DbalTransactionSinkTest extends FlowTestCase { - public function test_a_drain_failure_suppressed_by_the_error_handler_commits_the_rows_delivered_before_the_failure(): void + public function test_a_drain_failure_suppressed_by_the_error_handler_rolls_back_the_delivery_and_surfaces_the_failure(): void { $connection = DriverManager::getConnection(['driver' => 'pdo_sqlite', 'memory' => true]); - $databaseContext = new DatabaseContext($connection, new InsertQueryCounter(), new SelectQueryCounter()); + $databaseContext = new DatabaseContext( + $connection, + new InsertQueryCounter(), + new SelectQueryCounter(), + new CommitCounter(), + ); $databaseContext->createTable(new Table('tx_drain', [new Column('id', Type::getType(Types::INTEGER), [ 'notnull' => true, ])])); @@ -47,25 +54,37 @@ public function test_a_drain_failure_suppressed_by_the_error_handler_commits_the new RuntimeException('sink failed'), ); - df() - ->read(from_array([['id' => 3], ['id' => 1], ['id' => 4], ['id' => 2]])) - ->onError(ignore_error_handler()) - ->batchSize(2) - ->write(to_dbal_transaction($connection, to_transformation( - new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df->sortBy([ref('id')])), - $sink, - ))) - ->run(); + // a drain failure is never offered to the handler: the drain rolls back and the user's exception surfaces + try { + df() + ->read(from_array([['id' => 3], ['id' => 1], ['id' => 4], ['id' => 2]])) + ->onError(ignore_error_handler()) + ->batchSize(2) + ->write(to_dbal_transaction($connection, to_transformation( + new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df->sortBy([ref('id')])), + $sink, + ))) + ->run(); + + static::fail('Expected the drain failure to surface'); + } catch (RuntimeException $e) { + static::assertSame('sink failed', $e->getMessage()); + } static::assertSame(1, $sink->loadsCount); - static::assertSame([1, 2, 3, 4], array_column($databaseContext->selectAll('tx_drain'), 'id')); + static::assertSame([], $databaseContext->selectAll('tx_drain')); static::assertFalse($connection->isTransactionActive()); } public function test_a_failure_during_the_closure_transaction_rolls_back_the_drained_delivery(): void { $connection = DriverManager::getConnection(['driver' => 'pdo_sqlite', 'memory' => true]); - $databaseContext = new DatabaseContext($connection, new InsertQueryCounter(), new SelectQueryCounter()); + $databaseContext = new DatabaseContext( + $connection, + new InsertQueryCounter(), + new SelectQueryCounter(), + new CommitCounter(), + ); $databaseContext->createTable(new Table('tx_drain', [new Column('id', Type::getType(Types::INTEGER), [ 'notnull' => true, ])])); @@ -145,10 +164,17 @@ public function test_isolation_level_applies_to_the_closure_transaction_and_is_r df() ->read(from_array([['id' => 3], ['id' => 1], ['id' => 4], ['id' => 2]])) ->batchSize(2) - ->write(to_dbal_transaction($connection, to_transformation( - new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df->sortBy([ref('id')])), - $spy, - ))->withIsolationLevel(TransactionIsolationLevel::SERIALIZABLE)) + ->write( + new Transactional( + DbalTransaction::fromConnection( + $connection, + )->withIsolationLevel(TransactionIsolationLevel::SERIALIZABLE), + to_transformation( + new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df->sortBy([ref('id')])), + $spy, + ), + ), + ) ->run(); static::assertSame([['rows' => 4, 'inTransaction' => true]], $spy->deliveries); diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/DbalTransactionTest.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/DbalTransactionTest.php new file mode 100644 index 0000000000..f16186f38a --- /dev/null +++ b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/DbalTransactionTest.php @@ -0,0 +1,138 @@ + 'not_a_driver']); + + $this->expectException(DbalException::class); + + $transaction->begin(); + } + + public function test_begin_leaves_the_isolation_level_alone_when_none_is_set(): void + { + $connection = $this->createMock(Connection::class); + $connection->method('getParams')->willReturn([]); + $connection->expects(self::once())->method('beginTransaction'); + $connection->expects(self::never())->method('setTransactionIsolation'); + + DbalTransaction::fromConnection($connection)->begin(); + } + + public function test_the_isolation_level_is_set_before_begin_and_restored_after_commit(): void + { + $levels = []; + $connection = $this->createStub(Connection::class); + $connection->method('getParams')->willReturn([]); + $connection->method('getTransactionIsolation')->willReturn(TransactionIsolationLevel::READ_COMMITTED); + $connection + ->method('setTransactionIsolation') + ->willReturnCallback(static function (TransactionIsolationLevel $level) use (&$levels): void { + $levels[] = $level; + }); + $transaction = DbalTransaction::fromConnection( + $connection, + )->withIsolationLevel(TransactionIsolationLevel::SERIALIZABLE); + + $transaction->begin(); + $transaction->commit(); + + static::assertSame( + [TransactionIsolationLevel::SERIALIZABLE, TransactionIsolationLevel::READ_COMMITTED], + $levels, + ); + } + + public function test_begin_restores_the_isolation_level_when_begin_throws(): void + { + $levels = []; + $failure = new RuntimeException('begin failed'); + $connection = $this->createStub(Connection::class); + $connection->method('getParams')->willReturn([]); + $connection->method('getTransactionIsolation')->willReturn(TransactionIsolationLevel::READ_COMMITTED); + $connection->method('beginTransaction')->willThrowException($failure); + $connection + ->method('setTransactionIsolation') + ->willReturnCallback(static function (TransactionIsolationLevel $level) use (&$levels): void { + $levels[] = $level; + }); + + try { + DbalTransaction::fromConnection($connection) + ->withIsolationLevel(TransactionIsolationLevel::SERIALIZABLE) + ->begin(); + static::fail('begin() must rethrow'); + } catch (RuntimeException $thrown) { + static::assertSame($failure, $thrown); + } + + static::assertSame( + [TransactionIsolationLevel::SERIALIZABLE, TransactionIsolationLevel::READ_COMMITTED], + $levels, + ); + } + + public function test_a_failed_commit_leaves_the_restore_to_the_rollback_that_follows(): void + { + $levels = []; + $connection = $this->createStub(Connection::class); + $connection->method('getParams')->willReturn([]); + $connection->method('getTransactionIsolation')->willReturn(TransactionIsolationLevel::READ_COMMITTED); + $connection->method('commit')->willThrowException(new RuntimeException('commit failed')); + $connection + ->method('setTransactionIsolation') + ->willReturnCallback(static function (TransactionIsolationLevel $level) use (&$levels): void { + $levels[] = $level; + }); + $transaction = DbalTransaction::fromConnection( + $connection, + )->withIsolationLevel(TransactionIsolationLevel::SERIALIZABLE); + $transaction->begin(); + + try { + $transaction->commit(); + static::fail('commit() must rethrow the commit failure'); + } catch (RuntimeException $failure) { + static::assertSame([TransactionIsolationLevel::SERIALIZABLE], $levels); + + $transaction->rollback($failure); + } + + static::assertSame( + [TransactionIsolationLevel::SERIALIZABLE, TransactionIsolationLevel::READ_COMMITTED], + $levels, + ); + } + + public function test_rollback_rolls_back_and_suppresses_its_own_failure(): void + { + $connection = $this->createMock(Connection::class); + $connection->method('getParams')->willReturn([]); + $connection + ->expects(self::once()) + ->method('rollBack') + ->willThrowException(new RuntimeException('rollback failed')); + + DbalTransaction::fromConnection($connection)->rollback(new RuntimeException('load failed')); + } + + public function test_with_isolation_level_returns_a_new_instance(): void + { + $transaction = new DbalTransaction(['driver' => 'pdo_sqlite', 'memory' => true]); + + static::assertNotSame($transaction, $transaction->withIsolationLevel(TransactionIsolationLevel::SERIALIZABLE)); + } +} diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/IsolationLevelRestoreTest.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/IsolationLevelRestoreTest.php new file mode 100644 index 0000000000..0a6929e539 --- /dev/null +++ b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/IsolationLevelRestoreTest.php @@ -0,0 +1,35 @@ +createMock(Connection::class); + $connection + ->expects(self::once()) + ->method('setTransactionIsolation') + ->with(TransactionIsolationLevel::READ_COMMITTED); + + (new IsolationLevelRestore($connection, TransactionIsolationLevel::READ_COMMITTED))->restore(); + } + + public function test_a_failing_restore_is_suppressed(): void + { + $connection = $this->createStub(Connection::class); + $connection->method('setTransactionIsolation')->willThrowException(new RuntimeException('restore failed')); + + (new IsolationLevelRestore($connection, TransactionIsolationLevel::READ_COMMITTED))->restore(); + + $this->addToAssertionCount(1); + } +} diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/TransactionalDbalLoaderTest.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/TransactionalDbalLoaderTest.php deleted file mode 100644 index c891ca9abb..0000000000 --- a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/TransactionalDbalLoaderTest.php +++ /dev/null @@ -1,120 +0,0 @@ - 'pdo_sqlite', 'memory' => true]; - $loader1 = new DbalLoader('test_table1', $params); - $loader2 = new DbalLoader('test_table2', $params); - - $transactionalLoader = new TransactionalDbalLoader($params, $loader1, $loader2); - - static::assertInstanceOf(TransactionalDbalLoader::class, $transactionalLoader); - } - - public function test_closure_is_forwarded_to_every_closure_aware_loader(): void - { - $context = flow_context(config()); - $spy1 = new SpyLoader(); - $spy2 = new SpyLoader(); - - (new TransactionalDbalLoader( - ['driver' => 'pdo_sqlite', 'memory' => true], - $spy1, - new DbalLoader('test_table', ['driver' => 'pdo_sqlite', 'memory' => true]), - $spy2, - ))->closure($context); - - static::assertSame(1, $spy1->closureCount); - static::assertSame(1, $spy2->closureCount); - static::assertSame([$context], $spy1->closureContexts); - static::assertSame([$context], $spy2->closureContexts); - } - - public function test_connection_from_params(): void - { - $params = ['driver' => 'pdo_sqlite', 'memory' => true]; - $loader = new DbalLoader('test_table', $params); - - $transactionalLoader = new TransactionalDbalLoader($params, $loader); - - static::assertInstanceOf(TransactionalDbalLoader::class, $transactionalLoader); - } - - public function test_exposing_the_wrapped_loaders(): void - { - $params = ['driver' => 'pdo_sqlite', 'memory' => true]; - $loader1 = new DbalLoader('test_table1', $params); - $loader2 = new DbalLoader('test_table2', $params); - - static::assertSame([$loader1, $loader2], (new TransactionalDbalLoader($params, $loader1, $loader2))->loaders()); - } - - public function test_from_connection_static_method(): void - { - $params = ['driver' => 'pdo_sqlite', 'memory' => true]; - $connection = $this->createStub(Connection::class); - $connection->method('getParams')->willReturn($params); - - $loader = new DbalLoader('test_table', $params); - $transactionalLoader = TransactionalDbalLoader::fromConnection($connection, $loader); - - static::assertInstanceOf(TransactionalDbalLoader::class, $transactionalLoader); - } - - public function test_requires_at_least_one_loader(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('At least one loader must be provided'); - - new TransactionalDbalLoader([]); - } - - public function test_the_original_failure_propagates_when_rollback_also_fails(): void - { - $connection = $this->createMock(Connection::class); - $connection->expects(self::once())->method('beginTransaction'); - $connection->expects(self::never())->method('commit'); - $connection - ->expects(self::once()) - ->method('rollBack') - ->willThrowException(new RuntimeException('rollback failed')); - - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('closure failed'); - - TransactionalDbalLoader::fromConnection( - $connection, - new ClosureThrowingLoader(new RuntimeException('closure failed')), - )->closure(flow_context(config())); - } - - public function test_sets_isolation_level(): void - { - $params = ['driver' => 'pdo_sqlite', 'memory' => true]; - $loader = new DbalLoader('test_table', $params); - - $transactionalLoader = new TransactionalDbalLoader($params, $loader); - $result = $transactionalLoader->withIsolationLevel(TransactionIsolationLevel::SERIALIZABLE); - - static::assertSame($transactionalLoader, $result); - } -} diff --git a/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/ExcelExtractor.php b/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/ExcelExtractor.php index e6153a9f89..95d71f3cc7 100644 --- a/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/ExcelExtractor.php +++ b/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/ExcelExtractor.php @@ -12,9 +12,7 @@ use Flow\ETL\Extractor\FileExtractor; use Flow\ETL\Extractor\FileReading; use Flow\ETL\Extractor\InfersSchema; -use Flow\ETL\Extractor\LimitPushDown; use Flow\ETL\Extractor\MetadataColumnsExtractor; -use Flow\ETL\Extractor\PushesLimit; use Flow\ETL\Extractor\RewindableExtractor; use Flow\ETL\Extractor\Signal; use Flow\ETL\FlowContext; @@ -27,6 +25,8 @@ use Flow\Filesystem\Filesystem; use Flow\Filesystem\Local\NativeLocalFilesystem; use Flow\Filesystem\Path; +use Flow\Filesystem\Path\Filter; +use Flow\Filesystem\Path\Filter\OnlyFiles; use Generator; use Throwable; @@ -41,12 +41,10 @@ final class ExcelExtractor implements Extractor, FileExtractor, InfersSchema, - LimitPushDown, MetadataColumnsExtractor, RewindableExtractor { use Batches; - use PushesLimit; use FileReading; private SchemaInference $inference; @@ -55,7 +53,7 @@ final class ExcelExtractor implements /** * The sheets the last inference sampled, still open: the next extract() reads on from where the sample stopped - * instead of parsing the sample again. DuckDB keeps its CSV sniffer's buffers for the scan the same way. + * instead of parsing the sample again. */ private ?WorkbookSampler $sampled = null; @@ -110,13 +108,13 @@ public function isRepeatable(): bool /** * @return Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null, Filter $pathFilter = new OnlyFiles()): Generator { $hydrator = $context->hydrator(); $batchSize = $this->batchSize(); $yielded = 0; $fileColumns = $this->fileColumns($this->filesystem, $this->path); - $sources = iterator_to_array($this->sourceFiles($this->filesystem, $this->path), false); + $sources = iterator_to_array($this->sourceFiles($this->filesystem, $this->path, $pathFilter), false); $workbook = new WorkbookReader($this->readOptions, new ExcelFormatDetector($this->filesystem)); // only the first extract() after an inference reads on from its sample; every later one parses afresh $sampled = $this->sampled; @@ -202,8 +200,6 @@ public function extract(FlowContext $context): Generator return; } - $limit = $this->pushedLimit(); - if ($limit !== null && $yielded >= $limit) { return; } @@ -223,8 +219,6 @@ public function extract(FlowContext $context): Generator return; } - $limit = $this->pushedLimit(); - if ($limit !== null && $yielded >= $limit) { return; } @@ -285,6 +279,11 @@ public function schema(): Schema return $fileColumns->declare($fileColumns->withoutTail($derived)); } + public function partitionSchema(): Schema + { + return $this->fileColumns($this->filesystem, $this->path)->partitions($this->schema ?? new Schema()); + } + public function source(): Path { return $this->path; diff --git a/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/ExcelExtractorTest.php b/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/ExcelExtractorTest.php index 72e626cb47..c4b2e5e64f 100644 --- a/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/ExcelExtractorTest.php +++ b/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/ExcelExtractorTest.php @@ -87,9 +87,9 @@ public function test_extract_excel_file_with_empty_cells(string $fixtureName): v public function test_extract_excel_file_with_limit(string $fixtureName): void { $extractor = from_excel($fixtureName); - $extractor->withBatchSize(1)->pushLimit(5); + $extractor->withBatchSize(1); - $rows = df()->extract($extractor)->fetch()->toArray(); + $rows = df()->read($extractor)->limit(5)->fetch()->toArray(); static::assertCount(5, $rows); @@ -304,10 +304,12 @@ public function test_extract_does_not_mutate_user_provided_schema(): void public function test_loading_data_from_all_partitions(): void { - df()->read(from_excel(__DIR__ . '/../Fixtures/partitioned/group=*/*.xlsx'))->run(function (Rows $rows): void { - // the partition column comes back as a column, discovered from the path - $this->assertContains('group', $rows->schema()->references()->names()); - }); + df() + ->read(from_excel(__DIR__ . '/../Fixtures/partitioned/group=*/*.xlsx')) + ->forEach(function (Rows $rows): void { + // the partition column comes back as a column, discovered from the path + $this->assertContains('group', $rows->schema()->references()->names()); + }); } public function test_partition_columns_are_not_leaking_between_streams(): void @@ -489,10 +491,10 @@ public function test_limit_leaves_no_shared_strings_temp_folder(): void { $before = ExcelFixtureContext::sharedStringsFolders(); - $extractor = from_excel(ExcelFixtureContext::file('orders_flow.xlsx')); - $extractor->pushLimit(1); - - df()->read($extractor)->run(); + df() + ->read(from_excel(ExcelFixtureContext::file('orders_flow.xlsx'))) + ->limit(1) + ->run(); static::assertSame([], ExcelFixtureContext::leakedSharedStringsFoldersSince($before)); } @@ -500,9 +502,9 @@ public function test_limit_leaves_no_shared_strings_temp_folder(): void public function test_limit_pays_the_sample_but_yields_only_the_limit(): void { $extractor = from_excel(ExcelFixtureContext::file('orders_1k.xlsx')); - $extractor->withBatchSize(1)->pushLimit(5); + $extractor->withBatchSize(1); - static::assertCount(5, df()->extract($extractor)->fetch()->toArray()); + static::assertCount(5, df()->read($extractor)->limit(5)->fetch()->toArray()); static::assertNotEmpty($extractor->schema()->references()->names()); } @@ -771,8 +773,7 @@ public function test_signal_stop_on_the_first_file_tail_batch_skips_the_remainin public function test_limit_reached_on_the_first_file_tail_batch_skips_the_remaining_files(): void { $extractor = from_excel(ExcelFixtureContext::file('cross_stream/*/*.xlsx'))->withBatchSize(10); - $extractor->pushLimit(2); - static::assertCount(2, ExtractedRows::of($extractor)); + static::assertCount(2, ExtractedRows::of($extractor, limit: 2)); } } diff --git a/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetExtractor.php b/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetExtractor.php index 93e41bca0a..b2711f71e3 100644 --- a/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetExtractor.php +++ b/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetExtractor.php @@ -10,10 +10,8 @@ use Flow\ETL\Extractor\BatchableExtractor; use Flow\ETL\Extractor\Batches; use Flow\ETL\Extractor\InfersSchema; -use Flow\ETL\Extractor\LimitPushDown; use Flow\ETL\Extractor\MetadataColumns; use Flow\ETL\Extractor\MetadataColumnsExtractor; -use Flow\ETL\Extractor\PushesLimit; use Flow\ETL\Extractor\RewindableExtractor; use Flow\ETL\Extractor\Signal; use Flow\ETL\FlowContext; @@ -39,19 +37,16 @@ final class GoogleSheetExtractor implements BatchableExtractor, Extractor, InfersSchema, - LimitPushDown, MetadataColumnsExtractor, RewindableExtractor { use Batches; - use PushesLimit; use MetadataColumns; /** * Core defaults to 20 480. A sheet range is an HTTP * request and the range clamps to the grid, so that default samples the WHOLE sheet for anything under - * ~20 000 rows - and the read then fetches it again. Polars' 100 keeps the sample proportionally small. - * Widen it per read with ->inferSchema(infer_schema()->sampleSize(...)), or -1 for the whole sheet. + * ~20 000 rows - and the read then fetches it again. */ private const int SAMPLE_ROWS = 100; @@ -82,7 +77,7 @@ public function isRepeatable(): bool /** * @return Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { $reader = new GoogleSheetReader($this->service, $this->spreadsheetId, $this->columnRange, $this->readOptions); $sampler = new GoogleSheetSampler($reader, $this->inference->sampleSize); @@ -158,8 +153,6 @@ function (RawRowValues $rowValues): RawRowValues { return; } - $limit = $this->pushedLimit(); - if ($limit !== null && $yielded >= $limit) { return; } diff --git a/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Integration/GoogleSheetExtractorTest.php b/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Integration/GoogleSheetExtractorTest.php index 157c82f039..57fdafba71 100644 --- a/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Integration/GoogleSheetExtractorTest.php +++ b/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Integration/GoogleSheetExtractorTest.php @@ -191,9 +191,9 @@ public function test_extract_with_limit(): void '1234567890', 'Sheet', ); - $extractor->withBatchSize(1)->pushLimit(2); + $extractor->withBatchSize(1); - static::assertCount(2, df()->extract($extractor)->fetch()->toArray()); + static::assertCount(2, df()->read($extractor)->limit(2)->fetch()->toArray()); } public function test_extract_without_cut_extra_columns(): void @@ -378,9 +378,9 @@ public function test_limit_still_pays_the_sample(): void '1234567890', 'Sheet', ); - $extractor->withBatchSize(1)->pushLimit(1); + $extractor->withBatchSize(1); - static::assertCount(1, df()->extract($extractor)->fetch()->toArray()); + static::assertCount(1, df()->read($extractor)->limit(1)->fetch()->toArray()); static::assertCount(4, $this->context->requests()); } } diff --git a/src/adapter/etl-adapter-http/src/Flow/ETL/Adapter/Http/PsrHttpClientDynamicExtractor.php b/src/adapter/etl-adapter-http/src/Flow/ETL/Adapter/Http/PsrHttpClientDynamicExtractor.php index 6eda95f661..9f38ffddf5 100644 --- a/src/adapter/etl-adapter-http/src/Flow/ETL/Adapter/Http/PsrHttpClientDynamicExtractor.php +++ b/src/adapter/etl-adapter-http/src/Flow/ETL/Adapter/Http/PsrHttpClientDynamicExtractor.php @@ -45,7 +45,7 @@ public function __construct( /** * @return Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { $encoder = new HttpEncoder(); $hydrator = $context->hydrator(); diff --git a/src/adapter/etl-adapter-http/src/Flow/ETL/Adapter/Http/PsrHttpClientPaginatedExtractor.php b/src/adapter/etl-adapter-http/src/Flow/ETL/Adapter/Http/PsrHttpClientPaginatedExtractor.php index 84d99d1b00..3b51857e37 100644 --- a/src/adapter/etl-adapter-http/src/Flow/ETL/Adapter/Http/PsrHttpClientPaginatedExtractor.php +++ b/src/adapter/etl-adapter-http/src/Flow/ETL/Adapter/Http/PsrHttpClientPaginatedExtractor.php @@ -47,7 +47,7 @@ public function __construct( /** * @return Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { $encoder = new HttpEncoder(); $hydrator = $context->hydrator(); diff --git a/src/adapter/etl-adapter-http/src/Flow/ETL/Adapter/Http/PsrHttpClientStaticExtractor.php b/src/adapter/etl-adapter-http/src/Flow/ETL/Adapter/Http/PsrHttpClientStaticExtractor.php index eb39a92d07..1c1f880c36 100644 --- a/src/adapter/etl-adapter-http/src/Flow/ETL/Adapter/Http/PsrHttpClientStaticExtractor.php +++ b/src/adapter/etl-adapter-http/src/Flow/ETL/Adapter/Http/PsrHttpClientStaticExtractor.php @@ -47,7 +47,7 @@ public function __construct( /** * @return Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { $encoder = new HttpEncoder(); $hydrator = $context->hydrator(); diff --git a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONMachine/JsonExtractor.php b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONMachine/JsonExtractor.php index 10d4d61052..23af3904af 100644 --- a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONMachine/JsonExtractor.php +++ b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONMachine/JsonExtractor.php @@ -11,9 +11,7 @@ use Flow\ETL\Extractor\FileExtractor; use Flow\ETL\Extractor\FileReading; use Flow\ETL\Extractor\InfersSchema; -use Flow\ETL\Extractor\LimitPushDown; use Flow\ETL\Extractor\MetadataColumnsExtractor; -use Flow\ETL\Extractor\PushesLimit; use Flow\ETL\Extractor\RewindableExtractor; use Flow\ETL\Extractor\Signal; use Flow\ETL\FlowContext; @@ -26,6 +24,8 @@ use Flow\Filesystem\Filesystem; use Flow\Filesystem\Local\NativeLocalFilesystem; use Flow\Filesystem\Path; +use Flow\Filesystem\Path\Filter; +use Flow\Filesystem\Path\Filter\OnlyFiles; use Flow\Types\Type\Logical\InstanceOfTypeNarrower; use Generator; @@ -37,12 +37,10 @@ final class JsonExtractor implements Extractor, FileExtractor, InfersSchema, - LimitPushDown, MetadataColumnsExtractor, RewindableExtractor { use Batches; - use PushesLimit; use FileReading; private SchemaInference $inference; @@ -81,13 +79,13 @@ public function isRepeatable(): bool /** * @return Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null, Filter $pathFilter = new OnlyFiles()): Generator { $hydrator = $context->hydrator(); $batchSize = $this->batchSize(); $yielded = 0; $fileColumns = $this->fileColumns($this->filesystem, $this->path); - $sources = iterator_to_array($this->sourceFiles($this->filesystem, $this->path), false); + $sources = iterator_to_array($this->sourceFiles($this->filesystem, $this->path, $pathFilter), false); $reader = new JsonFileReader( $this->filesystem, JsonFormat::Document, @@ -136,8 +134,6 @@ public function extract(FlowContext $context): Generator return; } - $limit = $this->pushedLimit(); - if ($limit !== null && $yielded >= $limit) { return; } @@ -183,6 +179,11 @@ public function schema(): Schema return $fileColumns->declare($fileColumns->withoutTail($derived)); } + public function partitionSchema(): Schema + { + return $this->fileColumns($this->filesystem, $this->path)->partitions($this->schema ?? new Schema()); + } + public function source(): Path { return $this->path; diff --git a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONMachine/JsonLinesExtractor.php b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONMachine/JsonLinesExtractor.php index 01585402e0..768b3a295f 100644 --- a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONMachine/JsonLinesExtractor.php +++ b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONMachine/JsonLinesExtractor.php @@ -11,9 +11,7 @@ use Flow\ETL\Extractor\FileExtractor; use Flow\ETL\Extractor\FileReading; use Flow\ETL\Extractor\InfersSchema; -use Flow\ETL\Extractor\LimitPushDown; use Flow\ETL\Extractor\MetadataColumnsExtractor; -use Flow\ETL\Extractor\PushesLimit; use Flow\ETL\Extractor\RewindableExtractor; use Flow\ETL\Extractor\Signal; use Flow\ETL\FlowContext; @@ -26,6 +24,8 @@ use Flow\Filesystem\Filesystem; use Flow\Filesystem\Local\NativeLocalFilesystem; use Flow\Filesystem\Path; +use Flow\Filesystem\Path\Filter; +use Flow\Filesystem\Path\Filter\OnlyFiles; use Flow\Types\Type\Logical\InstanceOfTypeNarrower; use Generator; @@ -37,12 +37,10 @@ final class JsonLinesExtractor implements Extractor, FileExtractor, InfersSchema, - LimitPushDown, MetadataColumnsExtractor, RewindableExtractor { use Batches; - use PushesLimit; use FileReading; private SchemaInference $inference; @@ -81,13 +79,13 @@ public function isRepeatable(): bool /** * @return Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null, Filter $pathFilter = new OnlyFiles()): Generator { $hydrator = $context->hydrator(); $batchSize = $this->batchSize(); $yielded = 0; $fileColumns = $this->fileColumns($this->filesystem, $this->path); - $sources = iterator_to_array($this->sourceFiles($this->filesystem, $this->path), false); + $sources = iterator_to_array($this->sourceFiles($this->filesystem, $this->path, $pathFilter), false); $reader = new JsonFileReader( $this->filesystem, JsonFormat::Lines, @@ -136,8 +134,6 @@ public function extract(FlowContext $context): Generator return; } - $limit = $this->pushedLimit(); - if ($limit !== null && $yielded >= $limit) { return; } @@ -183,6 +179,11 @@ public function schema(): Schema return $fileColumns->declare($fileColumns->withoutTail($derived)); } + public function partitionSchema(): Schema + { + return $this->fileColumns($this->filesystem, $this->path)->partitions($this->schema ?? new Schema()); + } + public function source(): Path { return $this->path; diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonExtractorTest.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonExtractorTest.php index d533cf5912..b867f3fc00 100644 --- a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonExtractorTest.php +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonExtractorTest.php @@ -184,9 +184,9 @@ public function test_partition_columns_are_not_leaking_between_streams(): void public function test_limit(): void { $extractor = from_json(path(__DIR__ . '/../../Fixtures/timezones.json')); - $extractor->withBatchSize(1)->pushLimit(2); + $extractor->withBatchSize(1); - self::assertExtractedRowsCount(2, $extractor, flow_context(config())); + self::assertExtractedRowsCount(2, $extractor, flow_context(config()), limit: 2); } public function test_schema_appends_the_metadata_column(): void @@ -516,8 +516,7 @@ public function test_a_stream_is_closed_when_the_read_stops_early(string $mode): } if ($mode === 'limit') { - $extractor->pushLimit(2); - iterator_to_array($extractor->extract(flow_context(config()))); + iterator_to_array($extractor->extract(flow_context(config()), limit: 2)); } if ($mode === 'stop') { diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonLinesExtractorTest.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonLinesExtractorTest.php index 2e77db7526..b3bb2c4d44 100644 --- a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonLinesExtractorTest.php +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonLinesExtractorTest.php @@ -180,9 +180,9 @@ public function test_partition_columns_are_not_leaking_between_streams(): void public function test_limit(): void { $extractor = from_json_lines(path(__DIR__ . '/../../Fixtures/timezones.jsonl')); - $extractor->withBatchSize(1)->pushLimit(2); + $extractor->withBatchSize(1); - self::assertExtractedRowsCount(2, $extractor, flow_context(config())); + self::assertExtractedRowsCount(2, $extractor, flow_context(config()), limit: 2); } public function test_schema_appends_the_metadata_column(): void @@ -533,8 +533,7 @@ public function test_a_stream_is_closed_when_the_read_stops_early(string $mode): } if ($mode === 'limit') { - $extractor->pushLimit(2); - iterator_to_array($extractor->extract(flow_context(config()))); + iterator_to_array($extractor->extract(flow_context(config()), limit: 2)); } if ($mode === 'stop') { diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetExtractor.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetExtractor.php index 592186a5bc..a43c8f7fcd 100644 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetExtractor.php +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetExtractor.php @@ -11,9 +11,7 @@ use Flow\ETL\Extractor\Batches; use Flow\ETL\Extractor\FileExtractor; use Flow\ETL\Extractor\FileReading; -use Flow\ETL\Extractor\LimitPushDown; use Flow\ETL\Extractor\MetadataColumnsExtractor; -use Flow\ETL\Extractor\PushesLimit; use Flow\ETL\Extractor\RewindableExtractor; use Flow\ETL\Extractor\Signal; use Flow\ETL\FlowContext; @@ -23,6 +21,8 @@ use Flow\Filesystem\Filesystem; use Flow\Filesystem\Local\NativeLocalFilesystem; use Flow\Filesystem\Path; +use Flow\Filesystem\Path\Filter; +use Flow\Filesystem\Path\Filter\OnlyFiles; use Flow\Parquet\Binary\ByteOrder; use Flow\Parquet\Options; use Flow\Parquet\ParquetEngine; @@ -38,14 +38,12 @@ final class ParquetExtractor implements BatchableExtractor, Extractor, FileExtractor, - LimitPushDown, MetadataColumnsExtractor, RewindableExtractor { private ?Schema $schema = null; use Batches; - use PushesLimit; use FileReading; private ByteOrder $byteOrder = ByteOrder::LITTLE_ENDIAN; @@ -97,7 +95,7 @@ public function isRepeatable(): bool /** * @return Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null, Filter $pathFilter = new OnlyFiles()): Generator { $hydrator = $context->hydrator(); $batchSize = $this->batchSize(); @@ -111,7 +109,7 @@ public function extract(FlowContext $context): Generator $fileColumns = $this->fileColumns($this->filesystem, $this->path); - foreach ($this->files() as $file) { + foreach ($this->files($pathFilter) as $file) { // finally, not a close() per exit: the limit/STOP returns below and an abandoned // generator have to release the handle too (b73) try { @@ -144,7 +142,11 @@ public function extract(FlowContext $context): Generator $rawBatch = []; - foreach ($file->file->values($this->columns, $this->pushedLimit(), $fileOffset) as $row) { + foreach ($file->file->values( + $this->columns, + $limit === null ? null : $limit - $yielded, + $fileOffset, + ) as $row) { $rawBatch[] = $constants->fill($row); if (count($rawBatch) >= $batchSize) { @@ -162,8 +164,6 @@ public function extract(FlowContext $context): Generator return; } - $limit = $this->pushedLimit(); - if ($limit !== null && $yielded >= $limit) { return; } @@ -187,8 +187,6 @@ public function extract(FlowContext $context): Generator return; } - $limit = $this->pushedLimit(); - if ($limit !== null && $yielded >= $limit) { return; } @@ -219,6 +217,11 @@ public function unionByName(bool $union = true): self return $this; } + public function partitionSchema(): Schema + { + return $this->fileColumns($this->filesystem, $this->path)->partitions($this->schema ?? new Schema()); + } + public function source(): Path { return $this->path; @@ -273,9 +276,9 @@ public function withOptions(Options $options): self /** * @return Generator */ - private function files(): Generator + private function files(Filter $pathFilter = new OnlyFiles()): Generator { - foreach ($this->sourceFiles($this->filesystem, $this->path) as $source) { + foreach ($this->sourceFiles($this->filesystem, $this->path, $pathFilter) as $source) { $stream = $this->filesystem->readFrom($source->path); yield new ParquetSourceFile( diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/ParquetExtractorTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/ParquetExtractorTest.php index f5e5a301e7..ef49fcc324 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/ParquetExtractorTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/ParquetExtractorTest.php @@ -12,7 +12,7 @@ use Flow\ETL\Tests\Double\CountingFilesystem; use Flow\ETL\Tests\FlowTestCase; use Flow\Filesystem\Local\NativeLocalFilesystem; -use Flow\Filesystem\Path\Filter\OnlyFiles; +use Flow\Filesystem\Tests\Double\RejectingFilter; use Flow\Parquet\Binary\ByteOrder; use Flow\Parquet\Engine\PhpParquetEngine; use Flow\Parquet\Options; @@ -40,11 +40,10 @@ final class ParquetExtractorTest extends FlowTestCase public function test_limit(): void { $extractor = from_parquet(path(__DIR__ . '/Fixtures/orders_1k.parquet')); - $extractor->pushLimit(2); $extractedRows = 0; - foreach ($extractor->extract(flow_context(config())) as $batch) { + foreach ($extractor->extract(flow_context(config()), limit: 2) as $batch) { $extractedRows += $batch->count(); } @@ -317,7 +316,7 @@ public function test_schema_forgets_the_fold_when_the_options_change(): void static::assertSame(2, $filesystem->readFromCalls); } - public function test_schema_forgets_the_fold_when_the_path_filter_narrows(): void + public function test_a_path_filter_narrows_the_read_but_not_the_schema(): void { $filesystem = new CountingFilesystem(new NativeLocalFilesystem()); @@ -325,10 +324,13 @@ public function test_schema_forgets_the_fold_when_the_path_filter_narrows(): voi path(__DIR__ . '/Fixtures/Pagination/partitioned/*/*.parquet'), filesystem: $filesystem, ); - $extractor->schema(); - $extractor->withPathFilter(new OnlyFiles())->schema(); + $schema = $extractor->schema(); - static::assertSame(2, $filesystem->readFromCalls); + $batches = iterator_to_array($extractor->extract(flow_context(config()), pathFilter: new RejectingFilter())); + + static::assertSame([], $batches); + static::assertSame(1, $filesystem->readFromCalls); + static::assertEquals($schema, $extractor->schema()); } public function test_signal_stop(): void @@ -358,17 +360,27 @@ public function test_signal_stop_on_the_first_file_tail_batch_skips_the_remainin public function test_limit_reached_on_the_first_file_tail_batch_skips_the_remaining_files(): void { $extractor = from_parquet(path(__DIR__ . '/Fixtures/Pagination/*.parquet'))->withBatchSize(1500); - $extractor->pushLimit(1000); - static::assertCount(1000, ExtractedRows::of($extractor)); + static::assertCount(1000, ExtractedRows::of($extractor, limit: 1000)); + } + + public function test_the_second_file_is_asked_for_the_remainder_of_the_limit(): void + { + $extractor = from_parquet(path(__DIR__ . '/Fixtures/Pagination/*.parquet'))->withBatchSize(1000); + + // 01_1000.parquet fills the first batch; 02_500.parquet must be read up to the 200 rows still + // wanted, not up to the full limit again + $batches = iterator_to_array($extractor->extract(flow_context(config()), limit: 1200), false); + + static::assertCount(2, $batches); + static::assertSame(1200, $batches[0]->count() + $batches[1]->count()); } public function test_limit_reached_on_a_full_batch_of_the_first_file_skips_the_remaining_files(): void { $extractor = from_parquet(path(__DIR__ . '/Fixtures/Pagination/*.parquet'))->withBatchSize(500); - $extractor->pushLimit(1000); - static::assertCount(1000, ExtractedRows::of($extractor)); + static::assertCount(1000, ExtractedRows::of($extractor, limit: 1000)); } public function test_is_repeatable(): void diff --git a/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/PostgreSqlCursorExtractor.php b/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/PostgreSqlCursorExtractor.php index c2e0422a2e..c8efec2ff5 100644 --- a/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/PostgreSqlCursorExtractor.php +++ b/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/PostgreSqlCursorExtractor.php @@ -9,8 +9,6 @@ use Flow\ETL\Extractor; use Flow\ETL\Extractor\BatchableExtractor; use Flow\ETL\Extractor\Batches; -use Flow\ETL\Extractor\LimitPushDown; -use Flow\ETL\Extractor\PushesLimit; use Flow\ETL\Extractor\RewindableExtractor; use Flow\ETL\Extractor\Signal; use Flow\ETL\FlowContext; @@ -36,10 +34,9 @@ * * Note: Requires a transaction context (auto-started if not in one). */ -final class PostgreSqlCursorExtractor implements BatchableExtractor, Extractor, LimitPushDown, RewindableExtractor +final class PostgreSqlCursorExtractor implements BatchableExtractor, Extractor, RewindableExtractor { use Batches; - use PushesLimit; private ?string $cursorName = null; @@ -68,7 +65,7 @@ public function __construct( /** * @return Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { $read = $this->read ??= ReadQuery::of($this->query, self::class); @@ -89,12 +86,10 @@ public function extract(FlowContext $context): Generator try { $this->client->execute($read->declareCursor($cursorName), $this->parameters); $declared = true; - - $pushed = $this->pushedLimit(); $maximum = match (true) { - $this->maximum !== null && $pushed !== null => min($this->maximum, $pushed), + $this->maximum !== null && $limit !== null => min($this->maximum, $limit), $this->maximum !== null => $this->maximum, - default => $pushed, + default => $limit, }; $yielded = 0; diff --git a/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/PostgreSqlKeySetExtractor.php b/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/PostgreSqlKeySetExtractor.php index a3e79ca94e..bb15917b57 100644 --- a/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/PostgreSqlKeySetExtractor.php +++ b/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/PostgreSqlKeySetExtractor.php @@ -12,8 +12,6 @@ use Flow\ETL\Extractor; use Flow\ETL\Extractor\BatchableExtractor; use Flow\ETL\Extractor\Batches; -use Flow\ETL\Extractor\LimitPushDown; -use Flow\ETL\Extractor\PushesLimit; use Flow\ETL\Extractor\RewindableExtractor; use Flow\ETL\Extractor\Signal; use Flow\ETL\FlowContext; @@ -35,10 +33,9 @@ use function min; use function sprintf; -final class PostgreSqlKeySetExtractor implements BatchableExtractor, Extractor, LimitPushDown, RewindableExtractor +final class PostgreSqlKeySetExtractor implements BatchableExtractor, Extractor, RewindableExtractor { use Batches; - use PushesLimit; private ?int $maximum = null; @@ -66,7 +63,7 @@ public function __construct( /** * @return Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { $read = $this->read ??= ReadQuery::of($this->query, self::class); @@ -75,11 +72,10 @@ public function extract(FlowContext $context): Generator $encoder = new PostgreSqlEncoder(); $yielded = 0; $cursorValues = null; - $pushed = $this->pushedLimit(); $maximum = match (true) { - $this->maximum !== null && $pushed !== null => min($this->maximum, $pushed), + $this->maximum !== null && $limit !== null => min($this->maximum, $limit), $this->maximum !== null => $this->maximum, - default => $pushed, + default => $limit, }; $first = count($this->parameters) + 1; $firstPage = $read->keySetFirstPage($this->keySet, $first); diff --git a/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/PostgreSqlLimitOffsetExtractor.php b/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/PostgreSqlLimitOffsetExtractor.php index e1b676190a..b89e26476c 100644 --- a/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/PostgreSqlLimitOffsetExtractor.php +++ b/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/PostgreSqlLimitOffsetExtractor.php @@ -9,8 +9,6 @@ use Flow\ETL\Extractor; use Flow\ETL\Extractor\BatchableExtractor; use Flow\ETL\Extractor\Batches; -use Flow\ETL\Extractor\LimitPushDown; -use Flow\ETL\Extractor\PushesLimit; use Flow\ETL\Extractor\RewindableExtractor; use Flow\ETL\Extractor\Signal; use Flow\ETL\FlowContext; @@ -24,10 +22,9 @@ use function count; use function min; -final class PostgreSqlLimitOffsetExtractor implements BatchableExtractor, Extractor, LimitPushDown, RewindableExtractor +final class PostgreSqlLimitOffsetExtractor implements BatchableExtractor, Extractor, RewindableExtractor { use Batches; - use PushesLimit; private ?int $maximum = null; @@ -54,7 +51,7 @@ public function __construct( /** * @return Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { $read = $this->read ??= ReadQuery::of($this->query, self::class); @@ -65,12 +62,10 @@ public function extract(FlowContext $context): Generator } $schema = $this->schema(); - - $pushed = $this->pushedLimit(); $maximum = match (true) { - $this->maximum !== null && $pushed !== null => min($this->maximum, $pushed), + $this->maximum !== null && $limit !== null => min($this->maximum, $limit), $this->maximum !== null => $this->maximum, - default => $pushed, + default => $limit, }; $total = $maximum ?? $this->client->fetchScalarInt($read->count(), $this->parameters); diff --git a/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/PostgreSqlTransaction.php b/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/PostgreSqlTransaction.php new file mode 100644 index 0000000000..7bdd255a74 --- /dev/null +++ b/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/PostgreSqlTransaction.php @@ -0,0 +1,64 @@ +client); + $transaction->isolationLevel = $level; + + return $transaction; + } + + public function begin(): void + { + $this->client->beginTransaction(); + + if ($this->isolationLevel === null) { + return; + } + + try { + $this->client->execute(set_transaction()->isolationLevel($this->isolationLevel)); + } catch (Throwable $failure) { + // a failed begin() is never rolled back by its caller, so the transaction it opened is closed here + $this->rollback($failure); + + throw $failure; + } + } + + public function commit(): void + { + $this->client->commit(); + } + + public function rollback(Throwable $cause): void + { + try { + $this->client->rollBack(); + } catch (Throwable) { + // $cause is the actionable failure - a rollback failure must not mask it + } + } +} diff --git a/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/TransactionalPostgreSqlLoader.php b/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/TransactionalPostgreSqlLoader.php deleted file mode 100644 index 72600a9704..0000000000 --- a/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/TransactionalPostgreSqlLoader.php +++ /dev/null @@ -1,126 +0,0 @@ - - */ - private readonly array $loaders; - - public function __construct( - private readonly Client $client, - Loader ...$loaders, - ) { - if (count($loaders) === 0) { - throw new InvalidArgumentException('At least one loader must be provided'); - } - - $this->loaders = $loaders; - } - - /** - * Rows a wrapped Transformation buffered (blocking operations - sortBy, aggregate, groupBy->aggregate, - * pivot, window functions, collect, join) are delivered during the forwarded closure() drain, so delivery - * here must be transactional too: one transaction over everything the drain flushes, rolled back when it fails. - */ - public function closure(FlowContext $context): void - { - $this->inTransaction(function () use ($context): void { - foreach ($this->loaders as $loader) { - if ($loader instanceof Closure) { - $loader->closure($context); - } - } - }); - } - - public function load(Rows $rows, FlowContext $context): void - { - if ($rows->count() === 0) { - return; - } - - $context->telemetry()->loadingStarted($this); - - try { - $this->inTransaction(function () use ($rows, $context): void { - foreach ($this->loaders as $loader) { - $loader->load($rows, $context); - } - }); - - $context->telemetry()->loadingCompleted($this, [TelemetryAttributes::ATTR_LOADING_ROWS => $rows->count()]); - } catch (Throwable $e) { - $context->telemetry()->loadingFailed($this, $e); - - throw $e; - } - } - - public function loaders(): array - { - return $this->loaders; - } - - public function withIsolationLevel(IsolationLevel $level): self - { - $this->isolationLevel = $level; - - return $this; - } - - /** - * @param callable(): void $operation - */ - private function inTransaction(callable $operation): void - { - $this->client->beginTransaction(); - - try { - if ($this->isolationLevel !== null) { - $this->client->execute(set_transaction()->isolationLevel($this->isolationLevel)); - } - - $operation(); - - $this->client->commit(); - } catch (Throwable $e) { - try { - $this->client->rollBack(); - } catch (Throwable) { - // the load/drain failure is the actionable error - a rollback failure must not mask it - } - - throw $e; - } - } -} diff --git a/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/functions.php b/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/functions.php index f857766491..3fdd4d271d 100644 --- a/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/functions.php +++ b/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/functions.php @@ -16,6 +16,8 @@ use Flow\ETL\Adapter\PostgreSql\Schema\SortingStrategy\TypeStrategy; use Flow\ETL\Loader; use Flow\ETL\Schema; +use Flow\ETL\Sink; +use Flow\ETL\Sink\Transactional; use Flow\PostgreSql\Client\Client; use Flow\PostgreSql\QueryBuilder\Sql; use Flow\PostgreSql\Schema\Table; @@ -104,18 +106,12 @@ function to_pgsql_table(Client $client, string $table): PostgreSqlLoader } /** - * Execute multiple loaders within PostgreSQL transactions. - * - * Each batch of rows is loaded in its own transaction; rows a wrapped Transformation delivers when - * the loader is closed (blocking operations drain there) are committed in one final transaction. - * If any loader fails, the open transaction is rolled back. - * All wrapped loaders must use the same Client instance as the wrapper - a loader holding its own - * Client escapes the transaction. + * Write every sink within PostgreSQL transactions. */ #[DocumentationDSL(module: Module::POSTGRESQL, type: DSLType::LOADER)] -function to_pgsql_transaction(Client $client, Loader ...$loaders): TransactionalPostgreSqlLoader +function to_pgsql_transaction(Client $client, Loader|Sink ...$sinks): Transactional { - return new TransactionalPostgreSqlLoader($client, ...$loaders); + return new Transactional(new PostgreSqlTransaction($client), ...$sinks); } /** diff --git a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Context/TableRowsContext.php b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Context/TableRowsContext.php new file mode 100644 index 0000000000..9cc612e675 --- /dev/null +++ b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Context/TableRowsContext.php @@ -0,0 +1,54 @@ +> + */ + public static function fetchAll(Client $client, string $table): array + { + return df() + ->read(from_pgsql_limit_offset($client, select(star())->from(table($table))->orderBy(asc(col('id'))))) + ->fetch() + ->toArray(); + } + + /** + * Rows a (sub)transaction wrote carry its xid as `xmin`, so one group is one committed transaction. + * + * @return list> the values of $column, grouped by the transaction that wrote them, ordered by $column + */ + public static function groupedByWritingTransaction(Client $client, string $table, string $column): array + { + $groups = []; + + foreach ($client->fetchAll( + select(cast(col('xmin'), column_type_text())->as('xmin'), col($column)) + ->from(table($table)) + ->orderBy(asc(col($column))), + ) as $row) { + $groups[type_string()->assert($row['xmin'])][] = type_integer()->assert($row[$column]); + } + + return array_values($groups); + } +} diff --git a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Integration/PostgreSqlTransactionSinkTest.php b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Integration/PostgreSqlTransactionSinkTest.php new file mode 100644 index 0000000000..c303451c02 --- /dev/null +++ b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Integration/PostgreSqlTransactionSinkTest.php @@ -0,0 +1,360 @@ +client->execute( + create() + ->table($tableName) + ->column(column('id', column_type_integer())->primaryKey()) + ->column(column('name', column_type_text())), + ); + } + + $this->client->execute( + create()->table('flow_pgsql_tx_deleted')->column(column('transaction_id', column_type_integer())), + ); + $this->client->execute( + create() + ->table('flow_pgsql_tx_inserted') + ->column(column('id', column_type_integer())->primaryKey()) + ->column(column('transaction_id', column_type_integer())), + ); + $this->client->execute( + create()->table('flow_pgsql_tx_drain')->column(column('id', column_type_integer())->primaryKey()), + ); + } + + public function test_commits_every_loader_in_a_single_transaction(): void + { + df() + ->read(from_array([ + ['id' => 1, 'name' => 'Alice'], + ['id' => 2, 'name' => 'Bob'], + ])) + ->write(to_pgsql_transaction( + $this->client, + to_pgsql_table($this->client, 'flow_pgsql_tx_primary'), + to_pgsql_table($this->client, 'flow_pgsql_tx_mirror'), + )) + ->run(); + + $expected = [['id' => 1, 'name' => 'Alice'], ['id' => 2, 'name' => 'Bob']]; + + static::assertSame($expected, TableRowsContext::fetchAll($this->client, 'flow_pgsql_tx_primary')); + static::assertSame($expected, TableRowsContext::fetchAll($this->client, 'flow_pgsql_tx_mirror')); + } + + public function test_rolls_back_all_loaders_when_one_fails(): void + { + df() + ->read(from_array([['id' => 1, 'name' => 'Existing']])) + ->write(to_pgsql_table($this->client, 'flow_pgsql_tx_mirror')) + ->run(); + + $thrown = null; + + try { + df() + ->read(from_array([ + ['id' => 1, 'name' => 'Alice'], + ['id' => 2, 'name' => 'Bob'], + ])) + ->write(to_pgsql_transaction( + $this->client, + to_pgsql_table($this->client, 'flow_pgsql_tx_primary'), + to_pgsql_table($this->client, 'flow_pgsql_tx_mirror'), + )) + ->run(); + } catch (Throwable $e) { + $thrown = $e; + } + + // id=1 already exists in the mirror table; the whole batch must roll back + static::assertInstanceOf(Throwable::class, $thrown); + static::assertSame([], TableRowsContext::fetchAll($this->client, 'flow_pgsql_tx_primary')); + static::assertSame( + [['id' => 1, 'name' => 'Existing']], + TableRowsContext::fetchAll($this->client, 'flow_pgsql_tx_mirror'), + ); + } + + public function test_a_batched_transaction_sink_commits_once_per_batch(): void + { + $baseline = $this->client->getTransactionNestingLevel(); + $del = new TransactionSpyLoader($this->client); + $ins = new TransactionSpyLoader($this->client); + $rows = []; + + for ($id = 1; $id <= 5; $id++) { + $rows[] = ['transaction_id' => 7, 'id' => $id]; + } + + for ($id = 6; $id <= 8; $id++) { + $rows[] = ['transaction_id' => 9, 'id' => $id]; + } + + df() + ->read(from_array($rows)) + ->batchBy(ref('transaction_id'), 5) + ->write(to_pgsql_transaction( + $this->client, + to_transformation(new CallbackTransformation( + static fn(DataFrame $df): DataFrame => $df->select('transaction_id'), + ), $del), + to_transformation(batch_size(3), $ins), + )) + ->run(); + + // one transaction per source batch (tx 7, tx 9), and the 2 rows batch_size(3) still buffers at the end of the + // stream are delivered in the final transaction the drain opens + static::assertSame( + [['rows' => 5, 'nestingLevel' => $baseline + 1], ['rows' => 3, 'nestingLevel' => $baseline + 1]], + $del->deliveries, + ); + static::assertSame( + [ + ['rows' => 3, 'nestingLevel' => $baseline + 1], + ['rows' => 3, 'nestingLevel' => $baseline + 1], + ['rows' => 2, 'nestingLevel' => $baseline + 1], + ], + $ins->deliveries, + ); + static::assertSame([$baseline + 1], $del->closureNestingLevels); + static::assertSame([$baseline + 1], $ins->closureNestingLevels); + } + + public function test_every_batch_and_the_drain_commit_in_their_own_transaction(): void + { + df() + ->read(from_array([ + ['transaction_id' => 7, 'id' => 1], + ['transaction_id' => 7, 'id' => 2], + ['transaction_id' => 7, 'id' => 3], + ['transaction_id' => 7, 'id' => 4], + ['transaction_id' => 7, 'id' => 5], + ['transaction_id' => 9, 'id' => 6], + ['transaction_id' => 9, 'id' => 7], + ['transaction_id' => 9, 'id' => 8], + ])) + ->batchBy(ref('transaction_id'), 5) + ->write(to_pgsql_transaction( + $this->client, + to_transformation( + new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df->select('transaction_id')), + to_pgsql_table($this->client, 'flow_pgsql_tx_deleted'), + ), + to_transformation(batch_size(3), to_pgsql_table($this->client, 'flow_pgsql_tx_inserted')), + )) + ->run(); + + static::assertSame( + [[7, 7, 7, 7, 7], [9, 9, 9]], + TableRowsContext::groupedByWritingTransaction($this->client, 'flow_pgsql_tx_deleted', 'transaction_id'), + ); + static::assertSame( + [[1, 2, 3], [4, 5, 6], [7, 8]], + TableRowsContext::groupedByWritingTransaction($this->client, 'flow_pgsql_tx_inserted', 'id'), + ); + } + + public function test_two_sinks_on_one_connection_commit_together(): void + { + df() + ->read(from_array([ + ['id' => 1, 'name' => 'Alice'], + ['id' => 2, 'name' => 'Bob'], + ])) + ->write(to_pgsql_transaction( + $this->client, + to_transformation( + new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df->select('id', 'name')), + to_pgsql_table($this->client, 'flow_pgsql_tx_primary'), + ), + to_branch(ref('id')->greaterThan(lit(0)), to_pgsql_table($this->client, 'flow_pgsql_tx_mirror')), + )) + ->run(); + + $expected = [['id' => 1, 'name' => 'Alice'], ['id' => 2, 'name' => 'Bob']]; + + static::assertSame($expected, TableRowsContext::fetchAll($this->client, 'flow_pgsql_tx_primary')); + static::assertSame($expected, TableRowsContext::fetchAll($this->client, 'flow_pgsql_tx_mirror')); + } + + public function test_a_rolled_back_child_keeps_writing_later_batches(): void + { + df() + ->read(from_array([ + ['id' => 1, 'name' => 'Alice'], + ['id' => 2, 'name' => 'Bob'], + ])) + ->batchSize(1) + ->onError(ignore_error_handler()) + ->write(to_pgsql_transaction( + $this->client, + to_transformation( + new ThrowWhenRowMatches('id', 1, new RuntimeException('boom')), + to_pgsql_table($this->client, 'flow_pgsql_tx_primary'), + ), + to_pgsql_table($this->client, 'flow_pgsql_tx_mirror'), + )) + ->run(); + + // the first batch rolled back for every child and is never re-delivered; the failing child was restarted + static::assertSame( + [['id' => 2, 'name' => 'Bob']], + TableRowsContext::fetchAll($this->client, 'flow_pgsql_tx_primary'), + ); + static::assertSame( + [['id' => 2, 'name' => 'Bob']], + TableRowsContext::fetchAll($this->client, 'flow_pgsql_tx_mirror'), + ); + } + + public function test_a_drain_failure_suppressed_by_the_error_handler_rolls_back_the_delivery_and_surfaces_the_failure(): void + { + $sink = new LoadThenThrowLoader( + to_pgsql_table($this->client, 'flow_pgsql_tx_drain'), + new RuntimeException('sink failed'), + ); + + // a drain failure is never offered to the handler: the drain rolls back and the user's exception surfaces + try { + df() + ->read(from_array([['id' => 3], ['id' => 1], ['id' => 4], ['id' => 2]])) + ->onError(ignore_error_handler()) + ->batchSize(2) + ->write(to_pgsql_transaction($this->client, to_transformation( + new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df->sortBy([ref('id')])), + $sink, + ))) + ->run(); + + static::fail('Expected the drain failure to surface'); + } catch (RuntimeException $e) { + static::assertSame('sink failed', $e->getMessage()); + } + + static::assertSame(1, $sink->loadsCount); + static::assertSame([], TableRowsContext::fetchAll($this->client, 'flow_pgsql_tx_drain')); + } + + public function test_a_failure_during_the_closure_transaction_rolls_back_the_drained_delivery(): void + { + $thrown = null; + + try { + df() + ->read(from_array([['id' => 3], ['id' => 1], ['id' => 4], ['id' => 2]])) + ->batchSize(2) + ->write(to_pgsql_transaction( + $this->client, + to_transformation( + new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df->sortBy([ref('id')])), + to_pgsql_table($this->client, 'flow_pgsql_tx_drain'), + ), + new ClosureThrowingLoader(new RuntimeException('closure failed')), + )) + ->run(); + } catch (RuntimeException $e) { + $thrown = $e; + } + + static::assertInstanceOf(RuntimeException::class, $thrown); + static::assertSame('closure failed', $thrown->getMessage()); + + static::assertSame([], TableRowsContext::fetchAll($this->client, 'flow_pgsql_tx_drain')); + } + + public function test_blocking_transformation_delivers_its_whole_stream_at_closure_inside_a_transaction(): void + { + $spy = new TransactionSpyLoader($this->client); + $baseline = $this->client->getTransactionNestingLevel(); + + df() + ->read(from_array([['id' => 3], ['id' => 1], ['id' => 4], ['id' => 2]])) + ->batchSize(2) + ->write(to_pgsql_transaction($this->client, to_transformation( + new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df->sortBy([ref('id')])), + $spy, + ))) + ->run(); + + static::assertSame([['rows' => 4, 'nestingLevel' => $baseline + 1]], $spy->deliveries); + static::assertSame([$baseline + 1], $spy->closureNestingLevels); + } + + public function test_branch_armed_with_a_blocking_transformation_delivers_at_closure_inside_a_transaction(): void + { + $spy = new TransactionSpyLoader($this->client); + $baseline = $this->client->getTransactionNestingLevel(); + + df() + ->read(from_array([['id' => 3], ['id' => 1], ['id' => 4], ['id' => 2]])) + ->batchSize(2) + ->write(to_pgsql_transaction($this->client, to_branch( + lit(true), + $spy, + )->withTransformation(new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df->sortBy([ref( + 'id', + )]))))) + ->run(); + + static::assertSame([['rows' => 4, 'nestingLevel' => $baseline + 1]], $spy->deliveries); + static::assertSame([$baseline + 1], $spy->closureNestingLevels); + } + + public function test_streaming_transformation_delivers_each_batch_inside_a_transaction(): void + { + $spy = new TransactionSpyLoader($this->client); + $baseline = $this->client->getTransactionNestingLevel(); + + df() + ->read(from_array([['id' => 3], ['id' => 1], ['id' => 4], ['id' => 2]])) + ->batchSize(2) + ->write(to_pgsql_transaction($this->client, to_transformation(new CallbackTransformation( + static fn(DataFrame $df): DataFrame => $df->select('id'), + ), $spy))) + ->run(); + + static::assertSame( + [['rows' => 2, 'nestingLevel' => $baseline + 1], ['rows' => 2, 'nestingLevel' => $baseline + 1]], + $spy->deliveries, + ); + static::assertSame([$baseline + 1], $spy->closureNestingLevels); + } +} diff --git a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Integration/TransactionalPostgreSqlLoaderIntegrationTest.php b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Integration/TransactionalPostgreSqlLoaderIntegrationTest.php deleted file mode 100644 index 47f2cb9d26..0000000000 --- a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Integration/TransactionalPostgreSqlLoaderIntegrationTest.php +++ /dev/null @@ -1,107 +0,0 @@ -primaryTable, $this->mirrorTable] as $tableName) { - $this->client->execute( - create() - ->table($tableName) - ->column(column('id', column_type_integer())->primaryKey()) - ->column(column('name', column_type_text())), - ); - } - } - - public function test_commits_every_loader_in_a_single_transaction(): void - { - df() - ->read(from_array([ - ['id' => 1, 'name' => 'Alice'], - ['id' => 2, 'name' => 'Bob'], - ])) - ->write(to_pgsql_transaction( - $this->client, - to_pgsql_table($this->client, $this->primaryTable), - to_pgsql_table($this->client, $this->mirrorTable), - )) - ->run(); - - $expected = [['id' => 1, 'name' => 'Alice'], ['id' => 2, 'name' => 'Bob']]; - - static::assertSame($expected, $this->fetchAll($this->primaryTable)); - static::assertSame($expected, $this->fetchAll($this->mirrorTable)); - } - - public function test_rolls_back_all_loaders_when_one_fails(): void - { - df() - ->read(from_array([['id' => 1, 'name' => 'Existing']])) - ->write(to_pgsql_table($this->client, $this->mirrorTable)) - ->run(); - - try { - df() - ->read(from_array([ - ['id' => 1, 'name' => 'Alice'], - ['id' => 2, 'name' => 'Bob'], - ])) - ->write(to_pgsql_transaction( - $this->client, - to_pgsql_table($this->client, $this->primaryTable), - to_pgsql_table($this->client, $this->mirrorTable), - )) - ->run(); - - static::fail('Expected a primary key violation to be thrown'); - } catch (Throwable) { - // id=1 already exists in the mirror table; the whole batch must roll back - } - - static::assertSame([], $this->fetchAll($this->primaryTable)); - static::assertSame([['id' => 1, 'name' => 'Existing']], $this->fetchAll($this->mirrorTable)); - } - - /** - * @return array> - */ - private function fetchAll(string $tableName): array - { - return df() - ->read(from_pgsql_limit_offset( - $this->client, - select(star())->from(table($tableName))->orderBy(asc(col('id'))), - )) - ->fetch() - ->toArray(); - } -} diff --git a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Integration/TransactionalPostgreSqlLoaderTransformationIntegrationTest.php b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Integration/TransactionalPostgreSqlLoaderTransformationIntegrationTest.php deleted file mode 100644 index b09349d731..0000000000 --- a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Integration/TransactionalPostgreSqlLoaderTransformationIntegrationTest.php +++ /dev/null @@ -1,168 +0,0 @@ -client->execute( - create()->table('flow_pgsql_tx_drain')->column(column('id', column_type_integer())->primaryKey()), - ); - } - - public function test_a_drain_failure_suppressed_by_the_error_handler_commits_the_rows_delivered_before_the_failure(): void - { - $sink = new LoadThenThrowLoader( - to_pgsql_table($this->client, 'flow_pgsql_tx_drain'), - new RuntimeException('sink failed'), - ); - - df() - ->read(from_array([['id' => 3], ['id' => 1], ['id' => 4], ['id' => 2]])) - ->onError(ignore_error_handler()) - ->batchSize(2) - ->write(to_pgsql_transaction($this->client, to_transformation( - new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df->sortBy([ref('id')])), - $sink, - ))) - ->run(); - - static::assertSame(1, $sink->loadsCount); - static::assertSame( - [['id' => 1], ['id' => 2], ['id' => 3], ['id' => 4]], - df() - ->read(from_pgsql_limit_offset( - $this->client, - select(star())->from(table('flow_pgsql_tx_drain'))->orderBy(asc(col('id'))), - )) - ->fetch() - ->toArray(), - ); - } - - public function test_a_failure_during_the_closure_transaction_rolls_back_the_drained_delivery(): void - { - $thrown = null; - - try { - df() - ->read(from_array([['id' => 3], ['id' => 1], ['id' => 4], ['id' => 2]])) - ->batchSize(2) - ->write(to_pgsql_transaction( - $this->client, - to_transformation( - new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df->sortBy([ref('id')])), - to_pgsql_table($this->client, 'flow_pgsql_tx_drain'), - ), - new ClosureThrowingLoader(new RuntimeException('closure failed')), - )) - ->run(); - } catch (RuntimeException $e) { - $thrown = $e; - } - - static::assertInstanceOf(RuntimeException::class, $thrown); - static::assertSame('closure failed', $thrown->getMessage()); - - static::assertSame( - [], - df() - ->read(from_pgsql_limit_offset( - $this->client, - select(star())->from(table('flow_pgsql_tx_drain'))->orderBy(asc(col('id'))), - )) - ->fetch() - ->toArray(), - ); - } - - public function test_blocking_transformation_delivers_its_whole_stream_at_closure_inside_a_transaction(): void - { - $spy = new TransactionSpyLoader($this->client); - $baseline = $this->client->getTransactionNestingLevel(); - - df() - ->read(from_array([['id' => 3], ['id' => 1], ['id' => 4], ['id' => 2]])) - ->batchSize(2) - ->write(to_pgsql_transaction($this->client, to_transformation( - new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df->sortBy([ref('id')])), - $spy, - ))) - ->run(); - - static::assertSame([['rows' => 4, 'nestingLevel' => $baseline + 1]], $spy->deliveries); - static::assertSame([$baseline + 1], $spy->closureNestingLevels); - } - - public function test_branch_armed_with_a_blocking_transformation_delivers_at_closure_inside_a_transaction(): void - { - $spy = new TransactionSpyLoader($this->client); - $baseline = $this->client->getTransactionNestingLevel(); - - df() - ->read(from_array([['id' => 3], ['id' => 1], ['id' => 4], ['id' => 2]])) - ->batchSize(2) - ->write(to_pgsql_transaction($this->client, to_branch( - lit(true), - $spy, - )->withTransformation(new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df->sortBy([ref( - 'id', - )]))))) - ->run(); - - static::assertSame([['rows' => 4, 'nestingLevel' => $baseline + 1]], $spy->deliveries); - static::assertSame([$baseline + 1], $spy->closureNestingLevels); - } - - public function test_streaming_transformation_delivers_each_batch_inside_a_transaction(): void - { - $spy = new TransactionSpyLoader($this->client); - $baseline = $this->client->getTransactionNestingLevel(); - - df() - ->read(from_array([['id' => 3], ['id' => 1], ['id' => 4], ['id' => 2]])) - ->batchSize(2) - ->write(to_pgsql_transaction($this->client, to_transformation(new CallbackTransformation( - static fn(DataFrame $df): DataFrame => $df->select('id'), - ), $spy))) - ->run(); - - static::assertSame( - [['rows' => 2, 'nestingLevel' => $baseline + 1], ['rows' => 2, 'nestingLevel' => $baseline + 1]], - $spy->deliveries, - ); - static::assertSame([$baseline + 1], $spy->closureNestingLevels); - } -} diff --git a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/PostgreSqlCursorExtractorTest.php b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/PostgreSqlCursorExtractorTest.php index 6c1d1c3d6d..d3ecbeba17 100644 --- a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/PostgreSqlCursorExtractorTest.php +++ b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/PostgreSqlCursorExtractorTest.php @@ -319,9 +319,8 @@ public function test_pushed_limit_issues_no_query_once_satisfied(): void new StubCursor(array_map(static fn(int $id): array => ['id' => (string) $id], range(1501, 2500))), ); $extractor = from_pgsql_cursor($client, 'SELECT id FROM t'); - $extractor->pushLimit(1500); - self::assertExtractedRowsCount(1500, $extractor); + self::assertExtractedRowsCount(1500, $extractor, limit: 1500); // FETCH 1000, then FETCH 500 - a full narrowed fetch, which only the limit itself can stop static::assertSame(2, $client->callsTo('cursor')); } diff --git a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/PostgreSqlKeySetExtractorTest.php b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/PostgreSqlKeySetExtractorTest.php index 3d53834c1a..05b1d7e9f2 100644 --- a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/PostgreSqlKeySetExtractorTest.php +++ b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/PostgreSqlKeySetExtractorTest.php @@ -321,9 +321,8 @@ public function test_pushed_limit_issues_no_query_once_satisfied(): void 'SELECT id FROM t', pgsql_pagination_key_set(pgsql_pagination_key_asc('id')), ); - $extractor->pushLimit(1500); - self::assertExtractedRowsCount(1500, $extractor); + self::assertExtractedRowsCount(1500, $extractor, limit: 1500); // 1000, then a page narrowed to the 500 still wanted - and no third query for row 1501 static::assertSame(2, $client->callsTo('cursor')); } diff --git a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/PostgreSqlLimitOffsetExtractorTest.php b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/PostgreSqlLimitOffsetExtractorTest.php index 3238903547..e68e4ae5f1 100644 --- a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/PostgreSqlLimitOffsetExtractorTest.php +++ b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/PostgreSqlLimitOffsetExtractorTest.php @@ -298,9 +298,8 @@ public function test_pushed_limit_skips_the_count_query(): void ->willCountTotal(1000) ->willReturnCursors(new StubCursor([['id' => '1'], ['id' => '2']]), new StubCursor([['id' => '3']])); $extractor = from_pgsql_limit_offset($client, 'SELECT id FROM t ORDER BY id')->withBatchSize(2); - $extractor->pushLimit(3); - self::assertExtractedRowsCount(3, $extractor); + self::assertExtractedRowsCount(3, $extractor, limit: 3); // the count query is the only caller of fetchScalarInt() static::assertSame(0, $client->callsTo('fetchScalarInt')); } diff --git a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/PostgreSqlTransactionTest.php b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/PostgreSqlTransactionTest.php new file mode 100644 index 0000000000..a70ec4136f --- /dev/null +++ b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/PostgreSqlTransactionTest.php @@ -0,0 +1,82 @@ +createMock(Client::class); + $client->expects(self::once())->method('beginTransaction'); + $client->expects(self::never())->method('execute'); + + (new PostgreSqlTransaction($client))->begin(); + } + + public function test_begin_sets_the_isolation_level_inside_the_transaction(): void + { + $client = $this->createMock(Client::class); + $client->expects(self::once())->method('beginTransaction'); + $client + ->expects(self::once()) + ->method('execute') + ->with(static::callback( + static fn(Sql|string $sql): bool => $sql instanceof Sql + && str_contains($sql->toSql(), 'ISOLATION LEVEL SERIALIZABLE'), + )) + ->willReturn(0); + + (new PostgreSqlTransaction($client)) + ->withIsolationLevel(IsolationLevel::SERIALIZABLE) + ->begin(); + } + + public function test_a_failing_isolation_level_closes_the_transaction_begin_opened(): void + { + $failure = new RuntimeException('set failed'); + $client = $this->createMock(Client::class); + $client->expects(self::once())->method('beginTransaction'); + $client->method('execute')->willThrowException($failure); + $client->expects(self::once())->method('rollBack'); + + $this->expectExceptionObject($failure); + + (new PostgreSqlTransaction($client)) + ->withIsolationLevel(IsolationLevel::SERIALIZABLE) + ->begin(); + } + + public function test_commit_commits(): void + { + $client = $this->createMock(Client::class); + $client->expects(self::once())->method('commit'); + + (new PostgreSqlTransaction($client))->commit(); + } + + public function test_rollback_rolls_back_and_suppresses_its_own_failure(): void + { + $client = $this->createMock(Client::class); + $client->expects(self::once())->method('rollBack')->willThrowException(new RuntimeException('rollback failed')); + + (new PostgreSqlTransaction($client))->rollback(new RuntimeException('load failed')); + } + + public function test_with_isolation_level_returns_a_new_instance(): void + { + $transaction = new PostgreSqlTransaction($this->createStub(Client::class)); + + static::assertNotSame($transaction, $transaction->withIsolationLevel(IsolationLevel::SERIALIZABLE)); + } +} diff --git a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/TransactionalPostgreSqlLoaderTest.php b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/TransactionalPostgreSqlLoaderTest.php deleted file mode 100644 index ec3e436d16..0000000000 --- a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/TransactionalPostgreSqlLoaderTest.php +++ /dev/null @@ -1,186 +0,0 @@ -createMock(Client::class); - $client->expects(self::once())->method('beginTransaction'); - $client->expects(self::once())->method('commit'); - $client->expects(self::never())->method('rollBack'); - - $context = flow_context(); - $spy1 = new SpyLoader(); - $spy2 = new SpyLoader(); - - (new TransactionalPostgreSqlLoader($client, $spy1, $this->createStub(Loader::class), $spy2))->closure($context); - - static::assertSame(1, $spy1->closureCount); - static::assertSame(1, $spy2->closureCount); - static::assertSame([$context], $spy1->closureContexts); - static::assertSame([$context], $spy2->closureContexts); - } - - public function test_closure_rolls_back_and_rethrows_when_a_forwarded_closure_fails(): void - { - $client = $this->createMock(Client::class); - $client->expects(self::once())->method('beginTransaction'); - $client->expects(self::never())->method('commit'); - $client->expects(self::once())->method('rollBack'); - - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('closure failed'); - - (new TransactionalPostgreSqlLoader( - $client, - new ClosureThrowingLoader(new RuntimeException('closure failed')), - ))->closure(flow_context()); - } - - public function test_the_original_failure_propagates_when_rollback_also_fails(): void - { - $client = $this->createMock(Client::class); - $client->expects(self::once())->method('beginTransaction'); - $client->expects(self::never())->method('commit'); - $client->expects(self::once())->method('rollBack')->willThrowException(new RuntimeException('rollback failed')); - - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('closure failed'); - - (new TransactionalPostgreSqlLoader( - $client, - new ClosureThrowingLoader(new RuntimeException('closure failed')), - ))->closure(flow_context()); - } - - public function test_closure_sets_isolation_level_inside_its_transaction(): void - { - $client = $this->createMock(Client::class); - $client->expects(self::once())->method('beginTransaction'); - $client - ->expects(self::once()) - ->method('execute') - ->with(static::callback( - static fn(Sql|string $sql): bool => $sql instanceof Sql - && str_contains($sql->toSql(), 'ISOLATION LEVEL SERIALIZABLE'), - )) - ->willReturn(0); - $client->expects(self::once())->method('commit'); - - (new TransactionalPostgreSqlLoader($client, new SpyLoader())) - ->withIsolationLevel(IsolationLevel::SERIALIZABLE) - ->closure(flow_context()); - } - - public function test_commits_after_running_every_loader(): void - { - $client = $this->createMock(Client::class); - $client->expects(self::once())->method('beginTransaction'); - $client->expects(self::once())->method('commit'); - $client->expects(self::never())->method('rollBack'); - - $rows = rows(schema(int_schema('id')), row(['id' => 1])); - - $first = $this->createMock(Loader::class); - $first->expects(self::once())->method('load')->with($rows); - $second = $this->createMock(Loader::class); - $second->expects(self::once())->method('load')->with($rows); - - (new TransactionalPostgreSqlLoader($client, $first, $second))->load($rows, flow_context()); - } - - public function test_rolls_back_and_rethrows_when_a_loader_fails(): void - { - $client = $this->createMock(Client::class); - $client->expects(self::once())->method('beginTransaction'); - $client->expects(self::never())->method('commit'); - $client->expects(self::once())->method('rollBack'); - - $failing = $this->createStub(Loader::class); - $failing->method('load')->willThrowException(new RuntimeException('loader failed')); - - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('loader failed'); - - (new TransactionalPostgreSqlLoader($client, $failing))->load( - rows(schema(int_schema('id')), row(['id' => 1])), - flow_context(), - ); - } - - public function test_exposing_the_wrapped_loaders(): void - { - $first = $this->createStub(Loader::class); - $second = $this->createStub(Loader::class); - - static::assertSame( - [$first, $second], - (new TransactionalPostgreSqlLoader($this->createStub(Client::class), $first, $second))->loaders(), - ); - } - - public function test_requires_at_least_one_loader(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('At least one loader must be provided'); - - new TransactionalPostgreSqlLoader($this->createStub(Client::class)); - } - - public function test_sets_isolation_level_before_running_loaders(): void - { - $client = $this->createMock(Client::class); - $client->expects(self::once())->method('beginTransaction'); - $client - ->expects(self::once()) - ->method('execute') - ->with(static::callback( - static fn(Sql|string $sql): bool => $sql instanceof Sql - && str_contains($sql->toSql(), 'ISOLATION LEVEL SERIALIZABLE'), - )) - ->willReturn(0); - $client->expects(self::once())->method('commit'); - - $loader = $this->createMock(Loader::class); - $loader->expects(self::once())->method('load'); - - (new TransactionalPostgreSqlLoader($client, $loader)) - ->withIsolationLevel(IsolationLevel::SERIALIZABLE) - ->load(rows(schema(int_schema('id')), row(['id' => 1])), flow_context()); - } - - public function test_skips_transaction_for_empty_rows(): void - { - $client = $this->createMock(Client::class); - $client->expects(self::never())->method('beginTransaction'); - $client->expects(self::never())->method('commit'); - $client->expects(self::never())->method('rollBack'); - - $loader = $this->createMock(Loader::class); - $loader->expects(self::never())->method('load'); - - (new TransactionalPostgreSqlLoader($client, $loader))->load(rows(schema()), flow_context()); - } -} diff --git a/src/adapter/etl-adapter-text/src/Flow/ETL/Adapter/Text/TextExtractor.php b/src/adapter/etl-adapter-text/src/Flow/ETL/Adapter/Text/TextExtractor.php index 60ba69e365..abd8604eec 100644 --- a/src/adapter/etl-adapter-text/src/Flow/ETL/Adapter/Text/TextExtractor.php +++ b/src/adapter/etl-adapter-text/src/Flow/ETL/Adapter/Text/TextExtractor.php @@ -10,9 +10,7 @@ use Flow\ETL\Extractor\Batches; use Flow\ETL\Extractor\FileExtractor; use Flow\ETL\Extractor\FileReading; -use Flow\ETL\Extractor\LimitPushDown; use Flow\ETL\Extractor\MetadataColumnsExtractor; -use Flow\ETL\Extractor\PushesLimit; use Flow\ETL\Extractor\RewindableExtractor; use Flow\ETL\Extractor\Signal; use Flow\ETL\FlowContext; @@ -22,6 +20,8 @@ use Flow\Filesystem\Filesystem; use Flow\Filesystem\Local\NativeLocalFilesystem; use Flow\Filesystem\Path; +use Flow\Filesystem\Path\Filter; +use Flow\Filesystem\Path\Filter\OnlyFiles; use Generator; use function count; @@ -33,14 +33,12 @@ final class TextExtractor implements BatchableExtractor, Extractor, FileExtractor, - LimitPushDown, MetadataColumnsExtractor, RewindableExtractor { private ?Schema $schema = null; use Batches; - use PushesLimit; use FileReading; private readonly Filesystem $filesystem; @@ -70,7 +68,7 @@ public function isRepeatable(): bool /** * @return Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null, Filter $pathFilter = new OnlyFiles()): Generator { $hydrator = $context->hydrator(); $batchSize = $this->batchSize(); @@ -82,7 +80,7 @@ public function extract(FlowContext $context): Generator $fileColumns = $this->fileColumns($this->filesystem, $this->path); $schema = $fileColumns->declare($baseSchema); - foreach ($this->sourceFiles($this->filesystem, $this->path) as $source) { + foreach ($this->sourceFiles($this->filesystem, $this->path, $pathFilter) as $source) { $stream = $this->filesystem->readFrom($source->path); try { @@ -112,8 +110,6 @@ public function extract(FlowContext $context): Generator return; } - $limit = $this->pushedLimit(); - if ($limit !== null && $yielded >= $limit) { return; } @@ -137,8 +133,6 @@ public function extract(FlowContext $context): Generator return; } - $limit = $this->pushedLimit(); - if ($limit !== null && $yielded >= $limit) { return; } @@ -154,6 +148,11 @@ public function schema(): Schema return $this->fileColumns($this->filesystem, $this->path)->declare($this->schema ?? schema(str_schema('text'))); } + public function partitionSchema(): Schema + { + return $this->fileColumns($this->filesystem, $this->path)->partitions($this->schema ?? new Schema()); + } + public function source(): Path { return $this->path; diff --git a/src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Integration/TextExtractorTest.php b/src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Integration/TextExtractorTest.php index a95ad0a824..517321fd33 100644 --- a/src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Integration/TextExtractorTest.php +++ b/src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Integration/TextExtractorTest.php @@ -36,9 +36,9 @@ public function test_extracting_text_file(): void public function test_limit(): void { $extractor = from_text(path_real(__DIR__ . '/../Fixtures/orders_flow.csv')); - $extractor->withBatchSize(1)->pushLimit(2); + $extractor->withBatchSize(1); - self::assertExtractedRowsCount(2, $extractor, flow_context(config())); + self::assertExtractedRowsCount(2, $extractor, flow_context(config()), limit: 2); } public function test_partition_columns_are_not_leaking_between_streams(): void @@ -97,9 +97,8 @@ public function test_signal_stop_on_the_first_file_tail_batch_skips_the_remainin public function test_limit_reached_on_the_first_file_tail_batch_skips_the_remaining_files(): void { $extractor = from_text(__DIR__ . '/../Fixtures/cross_stream/*/data.txt')->withBatchSize(10); - $extractor->pushLimit(1); - static::assertCount(1, ExtractedRows::of($extractor)); + static::assertCount(1, ExtractedRows::of($extractor, limit: 1)); } public function test_metadata_columns_extend_a_declared_schema(): void @@ -125,9 +124,8 @@ public function test_a_limited_read_closes_its_stream(): void path_real(__DIR__ . '/../Fixtures/parity_lines.txt'), $filesystem, ))->withBatchSize(1); - $extractor->pushLimit(1); - iterator_to_array($extractor->extract(flow_context(config()))); + iterator_to_array($extractor->extract(flow_context(config()), limit: 1)); static::assertContains('closeSource', $filesystem->calls); } diff --git a/src/adapter/etl-adapter-xml/src/Flow/ETL/Adapter/XML/XMLParserExtractor.php b/src/adapter/etl-adapter-xml/src/Flow/ETL/Adapter/XML/XMLParserExtractor.php index af8db58a3d..952b94f36b 100644 --- a/src/adapter/etl-adapter-xml/src/Flow/ETL/Adapter/XML/XMLParserExtractor.php +++ b/src/adapter/etl-adapter-xml/src/Flow/ETL/Adapter/XML/XMLParserExtractor.php @@ -10,9 +10,7 @@ use Flow\ETL\Extractor\Batches; use Flow\ETL\Extractor\FileExtractor; use Flow\ETL\Extractor\FileReading; -use Flow\ETL\Extractor\LimitPushDown; use Flow\ETL\Extractor\MetadataColumnsExtractor; -use Flow\ETL\Extractor\PushesLimit; use Flow\ETL\Extractor\RewindableExtractor; use Flow\ETL\Extractor\Signal; use Flow\ETL\FlowContext; @@ -22,6 +20,8 @@ use Flow\Filesystem\Filesystem; use Flow\Filesystem\Local\NativeLocalFilesystem; use Flow\Filesystem\Path; +use Flow\Filesystem\Path\Filter; +use Flow\Filesystem\Path\Filter\OnlyFiles; use Generator; use function count; @@ -33,12 +33,10 @@ final class XMLParserExtractor implements BatchableExtractor, Extractor, FileExtractor, - LimitPushDown, MetadataColumnsExtractor, RewindableExtractor { use Batches; - use PushesLimit; use FileReading; /** @@ -92,7 +90,7 @@ public function isRepeatable(): bool /** * @return Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null, Filter $pathFilter = new OnlyFiles()): Generator { $hydrator = $context->hydrator(); $batchSize = $this->batchSize(); @@ -104,7 +102,7 @@ public function extract(FlowContext $context): Generator $fileColumns = $this->fileColumns($this->filesystem, $this->path); $schema = $fileColumns->declare($baseSchema); - foreach ($this->sourceFiles($this->filesystem, $this->path) as $source) { + foreach ($this->sourceFiles($this->filesystem, $this->path, $pathFilter) as $source) { $stream = $this->filesystem->readFrom($source->path); try { @@ -128,8 +126,6 @@ public function extract(FlowContext $context): Generator return; } - $limit = $this->pushedLimit(); - if ($limit !== null && $yielded >= $limit) { return; } @@ -147,8 +143,6 @@ public function extract(FlowContext $context): Generator return; } - $limit = $this->pushedLimit(); - if ($limit !== null && $yielded >= $limit) { return; } @@ -164,6 +158,11 @@ public function schema(): Schema return $this->fileColumns($this->filesystem, $this->path)->declare($this->schema ?? schema(xml_schema('node'))); } + public function partitionSchema(): Schema + { + return $this->fileColumns($this->filesystem, $this->path)->partitions($this->schema ?? new Schema()); + } + public function source(): Path { return $this->path; diff --git a/src/adapter/etl-adapter-xml/src/Flow/ETL/Adapter/XML/XMLReaderExtractor.php b/src/adapter/etl-adapter-xml/src/Flow/ETL/Adapter/XML/XMLReaderExtractor.php index a201f838ac..45b0e0bc74 100644 --- a/src/adapter/etl-adapter-xml/src/Flow/ETL/Adapter/XML/XMLReaderExtractor.php +++ b/src/adapter/etl-adapter-xml/src/Flow/ETL/Adapter/XML/XMLReaderExtractor.php @@ -11,9 +11,7 @@ use Flow\ETL\Extractor\Batches; use Flow\ETL\Extractor\FileExtractor; use Flow\ETL\Extractor\FileReading; -use Flow\ETL\Extractor\LimitPushDown; use Flow\ETL\Extractor\MetadataColumnsExtractor; -use Flow\ETL\Extractor\PushesLimit; use Flow\ETL\Extractor\RewindableExtractor; use Flow\ETL\Extractor\Signal; use Flow\ETL\FlowContext; @@ -23,6 +21,8 @@ use Flow\Filesystem\Filesystem; use Flow\Filesystem\Local\NativeLocalFilesystem; use Flow\Filesystem\Path; +use Flow\Filesystem\Path\Filter; +use Flow\Filesystem\Path\Filter\OnlyFiles; use Generator; use XMLReader; @@ -40,14 +40,12 @@ final class XMLReaderExtractor implements BatchableExtractor, Extractor, FileExtractor, - LimitPushDown, MetadataColumnsExtractor, RewindableExtractor { private ?Schema $schema = null; use Batches; - use PushesLimit; use FileReading; private readonly Filesystem $filesystem; @@ -99,7 +97,7 @@ public function isRepeatable(): bool /** * @return Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null, Filter $pathFilter = new OnlyFiles()): Generator { $hydrator = $context->hydrator(); $batchSize = $this->batchSize(); @@ -111,7 +109,7 @@ public function extract(FlowContext $context): Generator $fileColumns = $this->fileColumns($this->filesystem, $this->path); $schema = $fileColumns->declare($baseSchema); - foreach ($this->sourceFiles($this->filesystem, $this->path) as $source) { + foreach ($this->sourceFiles($this->filesystem, $this->path, $pathFilter) as $source) { $constants = $fileColumns->forFile($source, $schema); $xmlReader = new XMLReader(); @@ -168,8 +166,6 @@ public function extract(FlowContext $context): Generator return; } - $limit = $this->pushedLimit(); - if ($limit !== null && $yielded >= $limit) { return; } @@ -197,8 +193,6 @@ public function extract(FlowContext $context): Generator return; } - $limit = $this->pushedLimit(); - if ($limit !== null && $yielded >= $limit) { return; } @@ -214,6 +208,11 @@ public function schema(): Schema return $this->fileColumns($this->filesystem, $this->path)->declare($this->schema ?? schema(xml_schema('node'))); } + public function partitionSchema(): Schema + { + return $this->fileColumns($this->filesystem, $this->path)->partitions($this->schema ?? new Schema()); + } + public function source(): Path { return $this->path; diff --git a/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Integration/XMLParserExtractorTest.php b/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Integration/XMLParserExtractorTest.php index 3b084df176..2cf17beecb 100644 --- a/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Integration/XMLParserExtractorTest.php +++ b/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Integration/XMLParserExtractorTest.php @@ -49,9 +49,9 @@ public function test_extract_does_not_mutate_user_provided_schema(): void public function test_limit(): void { $extractor = from_xml(path_real(__DIR__ . '/../Fixtures/flow_orders.xml'))->withXMLNodePath('root/row'); - $extractor->withBatchSize(1)->pushLimit(2); + $extractor->withBatchSize(1); - $rows = df()->extract($extractor)->fetch()->toArray(); + $rows = df()->read($extractor)->limit(2)->fetch()->toArray(); static::assertCount(2, $rows); } @@ -315,9 +315,8 @@ public function test_signal_stop_on_the_first_file_tail_batch_skips_the_remainin public function test_limit_reached_on_the_first_file_tail_batch_skips_the_remaining_files(): void { $extractor = from_xml(__DIR__ . '/../Fixtures/cross_stream/*/file.xml', 'root/item')->withBatchSize(10); - $extractor->pushLimit(1); - static::assertCount(1, ExtractedRows::of($extractor)); + static::assertCount(1, ExtractedRows::of($extractor, limit: 1)); } public function test_is_repeatable(): void @@ -331,9 +330,8 @@ public function test_a_limited_read_closes_its_stream(): void $extractor = (new XMLParserExtractor(path_real(__DIR__ . '/../Fixtures/simple_items.xml'), $filesystem)) ->withXMLNodePath('root/items/item') ->withBatchSize(1); - $extractor->pushLimit(1); - foreach ($extractor->extract(flow_context(config())) as $_rows) { + foreach ($extractor->extract(flow_context(config()), limit: 1) as $_rows) { } static::assertContains('closeSource', $filesystem->calls); diff --git a/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Integration/XMLReaderExtractorTest.php b/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Integration/XMLReaderExtractorTest.php index a59746aa46..e8f03eaea1 100644 --- a/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Integration/XMLReaderExtractorTest.php +++ b/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Integration/XMLReaderExtractorTest.php @@ -27,9 +27,9 @@ public function test_limit(): void { // @mago-ignore analysis:deprecated-class $extractor = new XMLReaderExtractor(path_real(__DIR__ . '/../Fixtures/flow_orders.xml'), 'root/row'); - $extractor->withBatchSize(1)->pushLimit(2); + $extractor->withBatchSize(1); - self::assertExtractedRowsCount(2, $extractor, flow_context(config())); + self::assertExtractedRowsCount(2, $extractor, flow_context(config()), limit: 2); } public function test_partition_columns_are_not_leaking_between_streams(): void @@ -182,9 +182,8 @@ public function test_limit_reached_on_the_first_file_tail_batch_skips_the_remain path(__DIR__ . '/../Fixtures/cross_stream/*/file.xml'), 'root/item', ))->withBatchSize(10); - $extractor->pushLimit(1); - static::assertCount(1, ExtractedRows::of($extractor)); + static::assertCount(1, ExtractedRows::of($extractor, limit: 1)); } public function test_is_repeatable(): void diff --git a/src/cli/src/Flow/CLI/Command/FileAnalyzeCommand.php b/src/cli/src/Flow/CLI/Command/FileAnalyzeCommand.php index 83d4aab693..dbdc07576d 100644 --- a/src/cli/src/Flow/CLI/Command/FileAnalyzeCommand.php +++ b/src/cli/src/Flow/CLI/Command/FileAnalyzeCommand.php @@ -15,12 +15,12 @@ use Flow\CLI\Command\Traits\XMLOptions; use Flow\CLI\Factory\ExtractorFactory; use Flow\CLI\Formatter\PipelineReportFormatter; +use Flow\CLI\Loader\ProgressBarLoader; use Flow\CLI\Options\ConfigOption; use Flow\CLI\Options\FileFormat; use Flow\CLI\Options\FileFormatOption; use Flow\CLI\Style\FlowStyle; use Flow\ETL\Config; -use Flow\ETL\Rows; use Flow\Filesystem\Path; use RuntimeException; use Symfony\Component\Console\Attribute\AsCommand; @@ -157,9 +157,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $analyze->withSchema()->withColumnStatistics(); } - $report = $df->run(static function (Rows $rows) use ($progress): void { - $progress->advance($rows->count()); - }, analyze: $analyze); + $report = $df->write(new ProgressBarLoader($progress))->run(analyze: $analyze); $progress->finish(); diff --git a/src/cli/src/Flow/CLI/Command/FileReadCommand.php b/src/cli/src/Flow/CLI/Command/FileReadCommand.php index 46ce7a1be2..bab31d5eb9 100644 --- a/src/cli/src/Flow/CLI/Command/FileReadCommand.php +++ b/src/cli/src/Flow/CLI/Command/FileReadCommand.php @@ -161,7 +161,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $formatter = new AsciiTableFormatter(); - $df->run(static function (Rows $rows) use ($style, $formatter, $outputTruncate): void { + $df->forEach(static function (Rows $rows) use ($style, $formatter, $outputTruncate): void { $style->write($formatter->format($rows, $outputTruncate)); }); diff --git a/src/cli/src/Flow/CLI/Loader/ProgressBarLoader.php b/src/cli/src/Flow/CLI/Loader/ProgressBarLoader.php new file mode 100644 index 0000000000..658a9059d1 --- /dev/null +++ b/src/cli/src/Flow/CLI/Loader/ProgressBarLoader.php @@ -0,0 +1,22 @@ +progressBar->advance($rows->count()); + } +} diff --git a/src/cli/tests/Flow/CLI/Tests/Unit/Loader/ProgressBarLoaderTest.php b/src/cli/tests/Flow/CLI/Tests/Unit/Loader/ProgressBarLoaderTest.php new file mode 100644 index 0000000000..78211be901 --- /dev/null +++ b/src/cli/tests/Flow/CLI/Tests/Unit/Loader/ProgressBarLoaderTest.php @@ -0,0 +1,52 @@ +load( + rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])), + flow_context(), + ); + + static::assertSame(3, $progressBar->getProgress()); + } + + public function test_every_batch_adds_to_the_progress_so_far(): void + { + $progressBar = new ProgressBar(new BufferedOutput()); + $loader = new ProgressBarLoader($progressBar); + $context = flow_context(); + + $loader->load(rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])), $context); + $loader->load(rows(schema(int_schema('id')), row(['id' => 3])), $context); + + static::assertSame(3, $progressBar->getProgress()); + } + + public function test_an_empty_batch_leaves_the_bar_where_it_was(): void + { + $progressBar = new ProgressBar(new BufferedOutput()); + + (new ProgressBarLoader($progressBar))->load(rows(schema(int_schema('id'))), flow_context()); + + static::assertSame(0, $progressBar->getProgress()); + } +} diff --git a/src/core/etl/src/Flow/ETL/Pipeline/BoundStep.php b/src/core/etl/src/Flow/ETL/BoundStep.php similarity index 64% rename from src/core/etl/src/Flow/ETL/Pipeline/BoundStep.php rename to src/core/etl/src/Flow/ETL/BoundStep.php index 446a1a3bd1..d8f41dec27 100644 --- a/src/core/etl/src/Flow/ETL/Pipeline/BoundStep.php +++ b/src/core/etl/src/Flow/ETL/BoundStep.php @@ -2,11 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Pipeline; - -use Flow\ETL\Processor; -use Flow\ETL\Schema; -use Flow\ETL\Transformer; +namespace Flow\ETL; final readonly class BoundStep { diff --git a/src/core/etl/src/Flow/ETL/Bucketing/BucketRun.php b/src/core/etl/src/Flow/ETL/Bucketing/BucketRun.php index 92020cffda..a32654cbf3 100644 --- a/src/core/etl/src/Flow/ETL/Bucketing/BucketRun.php +++ b/src/core/etl/src/Flow/ETL/Bucketing/BucketRun.php @@ -11,8 +11,6 @@ * Carries the pairing so KWayMerge can hold spill runs and merged runs in one ordered list while each resolves * through its own storage. A mismatched pair is constructible; the invariant is upheld at the mint sites in * MergeSortProcessor, the only class where both storages are in scope. - * - * @internal */ final readonly class BucketRun { diff --git a/src/core/etl/src/Flow/ETL/Config.php b/src/core/etl/src/Flow/ETL/Config.php index 2b1d6e8e31..11d2f8015e 100644 --- a/src/core/etl/src/Flow/ETL/Config.php +++ b/src/core/etl/src/Flow/ETL/Config.php @@ -13,7 +13,6 @@ use Flow\ETL\Config\Sort\ExternalSortConfig; use Flow\ETL\Config\Sort\MemorySortConfig; use Flow\ETL\Config\Telemetry\TelemetryConfig; -use Flow\ETL\Pipeline\Optimizer; use Flow\ETL\Row\Hydrator; use Flow\Serializer\Serializer; use Psr\Clock\ClockInterface; @@ -24,6 +23,8 @@ */ final readonly class Config { + private Planner $planner; + /** * @param Hydrator $hydrator */ @@ -34,6 +35,7 @@ public function __construct( private Serializer $serializer, private ClockInterface $clock, private Optimizer $optimizer, + private Executor $executor, private Hydrator $hydrator, public CacheConfig $cache, public MemorySortConfig|ExternalSortConfig $sort, @@ -44,7 +46,9 @@ public function __construct( public HashRepartitionConfig $repartition, private Calculator $calculator = new Calculator(), private RandomValueGenerator $randomValueGenerator = new NativePHPRandomValueGenerator(), - ) {} + ) { + $this->planner = new Planner($optimizer); + } public static function builder(): ConfigBuilder { @@ -71,6 +75,11 @@ public function clock(): ClockInterface return $this->clock; } + public function executor(): Executor + { + return $this->executor; + } + /** * @return Hydrator */ @@ -94,6 +103,11 @@ public function optimizer(): Optimizer return $this->optimizer; } + public function planner(): Planner + { + return $this->planner; + } + public function randomValueGenerator(): RandomValueGenerator { return $this->randomValueGenerator; diff --git a/src/core/etl/src/Flow/ETL/Config/ConfigBuilder.php b/src/core/etl/src/Flow/ETL/Config/ConfigBuilder.php index 36eecc6c2f..d6f23317ea 100644 --- a/src/core/etl/src/Flow/ETL/Config/ConfigBuilder.php +++ b/src/core/etl/src/Flow/ETL/Config/ConfigBuilder.php @@ -19,9 +19,9 @@ use Flow\ETL\Config\Sort\SortAlgorithmBuilder; use Flow\ETL\Config\Telemetry\TelemetryConfig; use Flow\ETL\Config\Telemetry\TelemetryOptions; +use Flow\ETL\Executor; use Flow\ETL\NativePHPRandomValueGenerator; -use Flow\ETL\Pipeline\Optimizer; -use Flow\ETL\Pipeline\Optimizer\LimitOptimization; +use Flow\ETL\Optimizer; use Flow\ETL\RandomValueGenerator; use Flow\ETL\Row\AdaptiveRowHydrator; use Flow\ETL\Row\Hydrator; @@ -57,6 +57,8 @@ final class ConfigBuilder private ?Optimizer $optimizer; + private ?Executor $executor; + private readonly RandomValueGenerator $randomValueGenerator; private ?Serializer $serializer; @@ -74,6 +76,7 @@ public function __construct() $this->serializer = null; $this->hydrator = null; $this->optimizer = null; + $this->executor = null; $this->clock = null; $this->cache = new CacheConfigBuilder(); $this->groupBy = null; @@ -98,13 +101,15 @@ public function analyze(Analyze $analyze): self public function build(): Config { $id = $this->id ??= 'flow-php-' . $this->randomValueGenerator->string(32); - $this->optimizer ??= new Optimizer(new LimitOptimization()); + $this->optimizer ??= Optimizer::default(); + $this->executor ??= new Executor(); $this->hydrator ??= new AdaptiveRowHydrator(); // the default serializer shares the context hydrator - one source of Row objects $this->serializer ??= new FloeSerializer(hydrator: $this->hydrator); $serializer = $this->serializer; $optimizer = $this->optimizer; + $executor = $this->executor; $hydrator = $this->hydrator; $dataframeName = $this->name ?? 'flow_dataframe'; @@ -117,6 +122,7 @@ public function build(): Config $serializer, $this->getClock(), $optimizer, + $executor, $hydrator, $cacheConfig, ($this->sort ?? new ExternalSortBuilder())->build($cacheConfig->localFilesystemCacheDir), @@ -195,6 +201,13 @@ public function optimizer(Optimizer $optimizer): self return $this; } + public function executor(Executor $executor): self + { + $this->executor = $executor; + + return $this; + } + public function reset(): self { return new self(); diff --git a/src/core/etl/src/Flow/ETL/Config/Telemetry/TelemetryContext.php b/src/core/etl/src/Flow/ETL/Config/Telemetry/TelemetryContext.php index ac4a3ed404..34dc7e072b 100644 --- a/src/core/etl/src/Flow/ETL/Config/Telemetry/TelemetryContext.php +++ b/src/core/etl/src/Flow/ETL/Config/Telemetry/TelemetryContext.php @@ -10,7 +10,7 @@ use Flow\ETL\Dataset\Statistics\HighResolutionTime; use Flow\ETL\FlowContext; use Flow\ETL\Loader; -use Flow\ETL\Pipeline\Optimizer\Optimization; +use Flow\ETL\Optimizer\Rule; use Flow\ETL\Rows; use Flow\ETL\Transformer; use Flow\Telemetry\Attributes; @@ -226,9 +226,9 @@ public function dataFrameStarted(FlowContext $context): void 'dataframe_name' => $context->config->name(), 'cache' => $context->cache()::class, 'serializer' => $context->config->serializer()::class, - 'optimizers' => array_map( - static fn(Optimization $optimization) => $optimization::class, - $context->config->optimizer()->optimizations(), + 'optimizer_rules' => array_map( + static fn(Rule $rule) => $rule::class, + $context->config->optimizer()->rules(), ), 'telemetry' => [ 'trace_loading' => $this->options->traceLoading, @@ -412,10 +412,6 @@ private function dataFrameParent(): ?Context return $this->tracer->context()->withActiveSpan($dataFrameSpan->context()); } - /** - * Transformations drain first: TransformerLoader nests transform() inside load(), so a transformation - * scope is always the inner one and must be detached before the loading scope that wraps it. - */ private function drain(): void { $this->transformationSpans->drain($this->tracer, self::SPAN_NEVER_COMPLETED); diff --git a/src/core/etl/src/Flow/ETL/DSL/functions.php b/src/core/etl/src/Flow/ETL/DSL/functions.php index 3cc9eb9282..4e45c76ff9 100644 --- a/src/core/etl/src/Flow/ETL/DSL/functions.php +++ b/src/core/etl/src/Flow/ETL/DSL/functions.php @@ -32,7 +32,6 @@ use Flow\ETL\ErrorHandler\SkipRows; use Flow\ETL\ErrorHandler\ThrowError; use Flow\ETL\Exception\InvalidArgumentException; -use Flow\ETL\Exception\InvalidLogicException; use Flow\ETL\Exception\RuntimeException; use Flow\ETL\Exception\UnsupportedUnionTypeException; use Flow\ETL\Extractor; @@ -139,26 +138,13 @@ use Flow\ETL\Join\Expression; use Flow\ETL\Loader; use Flow\ETL\Loader\ArrayLoader; -use Flow\ETL\Loader\BranchingLoader; use Flow\ETL\Loader\MemoryLoader; use Flow\ETL\Loader\Partitioning; -use Flow\ETL\Loader\RetryLoader; use Flow\ETL\Loader\StreamLoader; use Flow\ETL\Loader\StreamLoader\Output; -use Flow\ETL\Loader\TransformerLoader; use Flow\ETL\Memory\Memory; use Flow\ETL\NativePHPRandomValueGenerator; use Flow\ETL\RandomValueGenerator; -use Flow\ETL\Retry\DelayFactory; -use Flow\ETL\Retry\DelayFactory\Exponential; -use Flow\ETL\Retry\DelayFactory\Fixed; -use Flow\ETL\Retry\DelayFactory\Fixed\FixedMilliseconds; -use Flow\ETL\Retry\DelayFactory\Jitter; -use Flow\ETL\Retry\DelayFactory\Linear; -use Flow\ETL\Retry\RetryStrategy; -use Flow\ETL\Retry\RetryStrategy\AnyThrowable; -use Flow\ETL\Retry\RetryStrategy\AnyThrowableExcept; -use Flow\ETL\Retry\RetryStrategy\OnExceptionTypes; use Flow\ETL\Row; use Flow\ETL\Row\AdaptiveRowHydrator; use Flow\ETL\Row\ColumnName; @@ -209,10 +195,10 @@ use Flow\ETL\Schema\Validator\StrictValidator; use Flow\ETL\Schema\Validator\ValidationContext; use Flow\ETL\SchemaValidator; +use Flow\ETL\Sink; +use Flow\ETL\Sink\Branched; +use Flow\ETL\Sink\Transformed; use Flow\ETL\String\StringStyles; -use Flow\ETL\Time\Duration; -use Flow\ETL\Time\Sleep; -use Flow\ETL\Time\SystemSleep; use Flow\ETL\Transformation; use Flow\ETL\Transformation\AddRowIndex; use Flow\ETL\Transformation\AddRowIndex\StartFrom; @@ -263,7 +249,6 @@ use Flow\Types\Type\Native\UnionType; use Flow\Types\Type\TypeFactory; use Psr\Clock\ClockInterface; -use Throwable; use UnitEnum; use function array_is_list; @@ -547,15 +532,15 @@ function to_stream( } #[DocumentationDSL(module: Module::CORE, type: DSLType::LOADER)] -function to_transformation(Transformer|Transformation $transformer, Loader $loader): TransformerLoader +function to_transformation(Transformer|Transformation $transformer, Loader|Sink $sink): Transformed { - return new TransformerLoader($transformer, $loader); + return new Transformed($transformer, $sink); } #[DocumentationDSL(module: Module::CORE, type: DSLType::LOADER)] -function to_branch(ScalarFunction $condition, Loader $loader, ?Transformation $transformation = null): BranchingLoader +function to_branch(ScalarFunction $condition, Loader|Sink $sink): Branched { - return new BranchingLoader($condition, $loader, $transformation); + return new Branched($condition, $sink); } #[DocumentationDSL(module: Module::CORE, type: DSLType::TRANSFORMER)] @@ -2143,91 +2128,6 @@ function match_condition(mixed $condition, mixed $then): MatchCondition return new MatchCondition($condition, $then); } -#[DocumentationDSL(module: Module::CORE, type: DSLType::HELPER)] -function retry_any_throwable(int $limit): AnyThrowable -{ - return new AnyThrowable($limit); -} - -/** - * @param array> $exception_types - */ -#[DocumentationDSL(module: Module::CORE, type: DSLType::HELPER)] -function retry_on_exception_types(array $exception_types, int $limit): OnExceptionTypes -{ - return new OnExceptionTypes($exception_types, $limit); -} - -/** - * @param array> $exception_types - */ -#[DocumentationDSL(module: Module::CORE, type: DSLType::HELPER)] -function retry_any_throwable_except(array $exception_types, int $limit): AnyThrowableExcept -{ - return new AnyThrowableExcept($exception_types, $limit); -} - -#[DocumentationDSL(module: Module::CORE, type: DSLType::HELPER)] -function delay_linear(Duration $delay, Duration $increment): Linear -{ - return new Linear($delay, $increment); -} - -#[DocumentationDSL(module: Module::CORE, type: DSLType::HELPER)] -function delay_exponential(Duration $base, int $multiplier = 2, ?Duration $max_delay = null): Exponential -{ - return new Exponential($base, $multiplier, $max_delay); -} - -/** - * @param float $jitter_factor a value between 0 and 1 representing the maximum percentage of jitter to apply - */ -#[DocumentationDSL(module: Module::CORE, type: DSLType::HELPER)] -function delay_jitter(DelayFactory $delay, float $jitter_factor): Jitter -{ - return new Jitter($delay, $jitter_factor); -} - -#[DocumentationDSL(module: Module::CORE, type: DSLType::HELPER)] -function delay_fixed(Duration $delay): Fixed -{ - return new Fixed($delay); -} - -#[DocumentationDSL(module: Module::CORE, type: DSLType::HELPER)] -function duration_seconds(int $seconds): Duration -{ - return Duration::fromSeconds($seconds); -} - -#[DocumentationDSL(module: Module::CORE, type: DSLType::HELPER)] -function duration_milliseconds(int $milliseconds): Duration -{ - return Duration::fromMilliseconds($milliseconds); -} - -#[DocumentationDSL(module: Module::CORE, type: DSLType::HELPER)] -function duration_microseconds(int $microseconds): Duration -{ - return Duration::fromMicroseconds($microseconds); -} - -#[DocumentationDSL(module: Module::CORE, type: DSLType::HELPER)] -function duration_minutes(int $minutes): Duration -{ - return Duration::fromMinutes($minutes); -} - -#[DocumentationDSL(module: Module::CORE, type: DSLType::LOADER)] -function write_with_retries( - Loader $loader, - RetryStrategy $retry_strategy = new AnyThrowableExcept([InvalidLogicException::class], 3), - DelayFactory $delay_factory = new FixedMilliseconds(200), - Sleep $sleep = new SystemSleep(), -): RetryLoader { - return new RetryLoader($loader, $retry_strategy, $delay_factory, $sleep); -} - #[DocumentationDSL(module: Module::CORE, type: DSLType::HELPER)] function clock(string $time_zone = 'UTC'): ClockInterface { diff --git a/src/core/etl/src/Flow/ETL/DataFrame.php b/src/core/etl/src/Flow/ETL/DataFrame.php index 8198858416..327c3bd11b 100644 --- a/src/core/etl/src/Flow/ETL/DataFrame.php +++ b/src/core/etl/src/Flow/ETL/DataFrame.php @@ -10,30 +10,19 @@ use Flow\ETL\DataFrame\GroupedDataFrame; use Flow\ETL\Dataset\Report; use Flow\ETL\Exception\InvalidArgumentException; -use Flow\ETL\Exception\RuntimeException; +use Flow\ETL\Exception\InvalidLogicException; use Flow\ETL\Exception\SchemaNotDerivableException; -use Flow\ETL\Execution\StatisticsCollector; -use Flow\ETL\Extractor\FileExtractor; -use Flow\ETL\Filesystem\ScalarFunctionFilter; +use Flow\ETL\Executor\StatisticsCollector; use Flow\ETL\Formatter\AsciiTableFormatter; use Flow\ETL\Function\AggregatingFunction; use Flow\ETL\Function\ScalarFunction; use Flow\ETL\Function\WindowFunction; -use Flow\ETL\GroupBy\GroupBySteps; use Flow\ETL\Join\Expression; use Flow\ETL\Join\Join; -use Flow\ETL\Join\JoinSteps; -use Flow\ETL\Loader\SchemaValidationLoader; use Flow\ETL\Loader\StreamLoader\Output; -use Flow\ETL\Processor\BatchingByProcessor; -use Flow\ETL\Processor\BatchingProcessor; -use Flow\ETL\Processor\CachingProcessor; -use Flow\ETL\Processor\CollectingProcessor; -use Flow\ETL\Processor\ConstrainedProcessor; -use Flow\ETL\Processor\OffsetProcessor; -use Flow\ETL\Processor\VoidProcessor; -use Flow\ETL\Processor\WindowProcessor; -use Flow\ETL\Repartition\RepartitionSteps; +use Flow\ETL\Plan\Node; +use Flow\ETL\Plan\Sinks; +use Flow\ETL\Plan\Trigger; use Flow\ETL\Row\Formatter\ASCIISchemaFormatter; use Flow\ETL\Row\Reference; use Flow\ETL\Row\References; @@ -41,27 +30,11 @@ use Flow\ETL\Schema\Definition; use Flow\ETL\Schema\SchemaFormatter; use Flow\ETL\Schema\Validator\StrictValidator; -use Flow\ETL\Sort\SortSteps; -use Flow\ETL\Transformer\CollectReferencesTransformer; -use Flow\ETL\Transformer\CrossJoinRowsTransformer; -use Flow\ETL\Transformer\DropDuplicatesTransformer; -use Flow\ETL\Transformer\DropEntriesTransformer; -use Flow\ETL\Transformer\DuplicateRowTransformer; -use Flow\ETL\Transformer\JoinEachRowsTransformer; -use Flow\ETL\Transformer\LimitTransformer; use Flow\ETL\Transformer\Rename\RenameEntryStrategy; -use Flow\ETL\Transformer\RenameEachEntryTransformer; -use Flow\ETL\Transformer\RenameEntryTransformer; -use Flow\ETL\Transformer\ScalarFunctionFilterTransformer; -use Flow\ETL\Transformer\ScalarFunctionTransformer; -use Flow\ETL\Transformer\SelectEntriesTransformer; -use Flow\ETL\Transformer\UntilTransformer; -use Flow\Filesystem\Path\Filter; use Generator; -use Throwable; -use function array_merge; use function array_unshift; +use function array_values; use function count; use function Flow\ETL\DSL\refs; use function Flow\ETL\DSL\to_output; @@ -76,12 +49,18 @@ final class DataFrame { private readonly FlowContext $context; - public function __construct( - private Pipeline $pipeline, - Config|FlowContext $context, - ) { + private readonly Extractor $extractor; + + private Node $root; + + private Sinks $sinks; + + public function __construct(Extractor $extractor, Config|FlowContext $context) + { $this->context = $context instanceof FlowContext ? $context : new FlowContext($context); - $this->context->telemetry()->dataFrameStarted($this->context); + $this->extractor = $extractor; + $this->root = new Node\Read($extractor); + $this->sinks = new Sinks(); } /** @@ -95,8 +74,7 @@ public function aggregate(array $aggregations, ?GroupByAlgorithmBuilder $algorit { $groupBy = new GroupBy(); $groupBy->aggregate(...$aggregations); - - $this->registerGroupBy($groupBy, $algorithm); + $this->root = new Node\Aggregate($this->root, $groupBy, $algorithm); return $this; } @@ -118,7 +96,7 @@ public function aggregate(array $aggregations, ?GroupByAlgorithmBuilder $algorit */ public function batchBy(string|Reference $column, ?int $minSize = null): self { - $this->pipeline->add(new BatchingByProcessor(UnresolvedReference::init($column), $minSize)); + $this->root = new Node\BatchBy($this->root, UnresolvedReference::init($column), $minSize); return $this; } @@ -146,7 +124,7 @@ public function batchSize(int $size): self return $this->collect(); } - $this->pipeline->add(new BatchingProcessor($size)); + $this->root = new Node\Batch($this->root, $size); return $this; } @@ -174,11 +152,7 @@ public function cache(?string $id = null, ?int $cacheBatchSize = null, ?Cache $c throw new InvalidArgumentException('Cache batch size must be greater than 0'); } - if ($cacheBatchSize) { - $this->pipeline->add(new BatchingProcessor($cacheBatchSize)); - } - - $this->pipeline->add(new CachingProcessor($id, $cache)); + $this->root = new Node\Cache($this->root, $id, $cacheBatchSize, $cache); return $this; } @@ -191,7 +165,7 @@ public function cache(?string $id = null, ?int $cacheBatchSize = null, ?Cache $c */ public function collect(): self { - $this->pipeline->add(new CollectingProcessor()); + $this->root = new Node\Collect($this->root); return $this; } @@ -210,16 +184,14 @@ public function collect(): self */ public function collectRefs(References $references): self { - $this->with(new CollectReferencesTransformer($references)); + $this->root = new Node\CollectRefs($this->root, $references); return $this; } public function constrain(Constraint $constraint, Constraint ...$constraints): self { - $constraints = array_merge([$constraint], $constraints); - - $this->pipeline->add(new ConstrainedProcessor($constraints)); + $this->root = new Node\Constrain($this->root, [$constraint, ...$constraints]); return $this; } @@ -232,15 +204,13 @@ public function count(): int { $total = 0; - try { - foreach ($this->pipeline->process($this->context) as $rows) { - $total += $rows->count(); - } - $this->context->telemetry()->dataFrameCompleted($this->context); - } catch (Throwable $e) { - $this->context->telemetry()->dataFrameFailed($this->context, $e); - - throw $e; + foreach ($this->context + ->config + ->executor() + ->execute( + $this->context->config->planner()->plan(Trigger::rows->plan($this->root, $this->sinks), $this->context), + ) as $rows) { + $total += $rows->count(); } return $total; @@ -251,7 +221,7 @@ public function count(): int */ public function crossJoin(self $dataFrame, string $prefix = ''): self { - $this->pipeline->add(new CrossJoinRowsTransformer($dataFrame, $prefix)); + $this->root = new Node\CrossJoin($this->root, $dataFrame->explain(Trigger::rows)->logical->root, $prefix); return $this; } @@ -276,15 +246,13 @@ public function display( $output = ''; - try { - foreach ($this->pipeline->process($this->context) as $rows) { - $output .= $formatter->format($rows, $truncate); - } - $this->context->telemetry()->dataFrameCompleted($this->context); - } catch (Throwable $e) { - $this->context->telemetry()->dataFrameFailed($this->context, $e); - - throw $e; + foreach ($this->context + ->config + ->executor() + ->execute( + $this->context->config->planner()->plan(Trigger::rows->plan($this->root, $this->sinks), $this->context), + ) as $rows) { + $output .= $formatter->format($rows, $truncate); } return $output; @@ -297,7 +265,7 @@ public function display( */ public function drop(string|Reference ...$entries): self { - $this->pipeline->add(new DropEntriesTransformer(...$entries)); + $this->root = new Node\Drop($this->root, array_values($entries)); return $this; } @@ -311,14 +279,14 @@ public function drop(string|Reference ...$entries): self */ public function dropDuplicates(string|Reference ...$entries): self { - $this->pipeline->add(new DropDuplicatesTransformer(...$entries)); + $this->root = new Node\Distinct($this->root, array_values($entries)); return $this; } public function duplicateRow(mixed $condition, WithEntry ...$entries): self { - $this->pipeline->add(new DuplicateRowTransformer($condition, ...$entries)); + $this->root = new Node\DuplicateRow($this->root, $condition, array_values($entries)); return $this; } @@ -342,26 +310,12 @@ public function fetch(?int $limit = null): Rows $this->limit($limit); } - $rows = null; - - try { - foreach ($this->pipeline->process($this->context) as $nextRows) { - $rows = $rows === null ? $nextRows : $rows->merge($nextRows); - } - $this->context->telemetry()->dataFrameCompleted($this->context); - } catch (Throwable $e) { - $this->context->telemetry()->dataFrameFailed($this->context, $e); - - throw $e; - } - - if ($rows !== null) { - return $rows; - } - - // the plan already describes what it would have produced; only a plan the bind refused has - // nothing to answer with - return new Rows($this->pipeline->boundOrNull()->schema ?? new Schema()); + return $this->context + ->config + ->executor() + ->fetch( + $this->context->config->planner()->plan(Trigger::rows->plan($this->root, $this->sinks), $this->context), + ); } /** @@ -369,43 +323,7 @@ public function fetch(?int $limit = null): Rows */ public function filter(ScalarFunction $function): self { - $this->pipeline->add(new ScalarFunctionFilterTransformer($function)); - - return $this; - } - - /** - * @internal engine paths only - a build-time scan has to know whether the source can be read twice - */ - public function extractor(): Extractor - { - return $this->pipeline->extractor(); - } - - /** - * @lazy - * - * @throws RuntimeException - */ - public function filterPartitions(Filter|ScalarFunction $filter): self - { - $extractor = $this->pipeline->extractor(); - - if (!$extractor instanceof FileExtractor) { - throw new RuntimeException( - 'filterPartitions can be used only with extractors that implement FileExtractor interface', - ); - } - - if ($filter instanceof Filter) { - $extractor->withPathFilter($filter); - $this->pipeline->invalidateBind(); - - return $this; - } - - $extractor->withPathFilter(new ScalarFunctionFilter($filter, $extractor->schema(), $this->context)); - $this->pipeline->invalidateBind(); + $this->root = new Node\Filter($this->root, $function); return $this; } @@ -427,11 +345,20 @@ public function filters(array $functions): self /** * @trigger * - * @param null|callable(Rows $rows) : void $callback + * @param null|callable(Rows $rows, FlowContext $context) : void $callback */ public function forEach(?callable $callback = null): void { - $this->run($callback); + foreach ($this->context + ->config + ->executor() + ->execute( + $this->context->config->planner()->plan(Trigger::rows->plan($this->root, $this->sinks), $this->context), + ) as $rows) { + if ($callback !== null) { + $callback($rows, $this->context); + } + } } /** @@ -443,15 +370,13 @@ public function forEach(?callable $callback = null): void */ public function get(): Generator { - try { - foreach ($this->pipeline->process($this->context) as $rows) { - yield $rows; - } - $this->context->telemetry()->dataFrameCompleted($this->context); - } catch (Throwable $e) { - $this->context->telemetry()->dataFrameFailed($this->context, $e); - - throw $e; + foreach ($this->context + ->config + ->executor() + ->execute( + $this->context->config->planner()->plan(Trigger::rows->plan($this->root, $this->sinks), $this->context), + ) as $rows) { + yield $rows; } } @@ -464,15 +389,13 @@ public function get(): Generator */ public function getAsArray(): Generator { - try { - foreach ($this->pipeline->process($this->context) as $rows) { - yield $rows->toArray(); - } - $this->context->telemetry()->dataFrameCompleted($this->context); - } catch (Throwable $e) { - $this->context->telemetry()->dataFrameFailed($this->context, $e); - - throw $e; + foreach ($this->context + ->config + ->executor() + ->execute( + $this->context->config->planner()->plan(Trigger::rows->plan($this->root, $this->sinks), $this->context), + ) as $rows) { + yield $rows->toArray(); } } @@ -485,17 +408,15 @@ public function getAsArray(): Generator */ public function getEach(): Generator { - try { - foreach ($this->pipeline->process($this->context) as $rows) { - foreach ($rows as $row) { - yield $row; - } + foreach ($this->context + ->config + ->executor() + ->execute( + $this->context->config->planner()->plan(Trigger::rows->plan($this->root, $this->sinks), $this->context), + ) as $rows) { + foreach ($rows as $row) { + yield $row; } - $this->context->telemetry()->dataFrameCompleted($this->context); - } catch (Throwable $e) { - $this->context->telemetry()->dataFrameFailed($this->context, $e); - - throw $e; } } @@ -508,17 +429,15 @@ public function getEach(): Generator */ public function getEachAsArray(): Generator { - try { - foreach ($this->pipeline->process($this->context) as $rows) { - foreach ($rows as $row) { - yield $row->toArray(); - } + foreach ($this->context + ->config + ->executor() + ->execute( + $this->context->config->planner()->plan(Trigger::rows->plan($this->root, $this->sinks), $this->context), + ) as $rows) { + foreach ($rows as $row) { + yield $row->toArray(); } - $this->context->telemetry()->dataFrameCompleted($this->context); - } catch (Throwable $e) { - $this->context->telemetry()->dataFrameFailed($this->context, $e); - - throw $e; } } @@ -533,9 +452,13 @@ public function groupBy( array|Reference|string $entries, ?GroupByAlgorithmBuilder $algorithm = null, ): GroupedDataFrame { - $references = is_array($entries) ? $entries : [$entries]; + $groupBy = new GroupBy(...is_array($entries) ? $entries : [$entries]); + // the rows feeding the aggregate, without the frame's writes - what pivot discovery scans + $input = new self($this->extractor, $this->context); + $input->root = $this->root; + $this->root = new Node\Aggregate($this->root, $groupBy, $algorithm); - return new GroupedDataFrame($this, new GroupBy(...$references), $algorithm); + return new GroupedDataFrame($this, $input, $groupBy); } /** @@ -554,9 +477,13 @@ public function join( $type = Join::from($type); } - foreach (JoinSteps::of($dataFrame, $on, $type, $this->context->config, $algorithm) as $step) { - $this->pipeline->add($step); - } + $this->root = new Node\Join( + $this->root, + $dataFrame->explain(Trigger::rows)->logical->root, + $on, + $type, + $algorithm, + ); return $this; } @@ -570,18 +497,11 @@ public function join( */ public function joinEach(DataFrameFactory $factory, Expression $on, string|Join $type = Join::left): self { - if ($type instanceof Join) { - $type = $type->name; + if (is_string($type)) { + $type = Join::tryFrom($type) ?? throw new InvalidArgumentException('Unsupported join type'); } - $transformer = match ($type) { - Join::left->value => JoinEachRowsTransformer::left($factory, $on), - Join::left_anti->value => JoinEachRowsTransformer::leftAnti($factory, $on), - Join::right->value => JoinEachRowsTransformer::right($factory, $on), - Join::inner->value => JoinEachRowsTransformer::inner($factory, $on), - default => throw new InvalidArgumentException('Unsupported join type'), - }; - $this->pipeline->add($transformer); + $this->root = new Node\JoinEach($this->root, $factory, $on, $type); return $this; } @@ -597,7 +517,7 @@ public function limit(?int $limit): self return $this; } - $this->pipeline = $this->context->config->optimizer()->optimize(new LimitTransformer($limit), $this->pipeline); + $this->root = new Node\Limit($this->root, $limit); return $this; } @@ -605,9 +525,43 @@ public function limit(?int $limit): self /** * @lazy */ - public function load(Loader $loader): self + public function load(Loader|Sink $sink): self { - $this->pipeline = $this->context->config->optimizer()->optimize($loader, $this->pipeline); + if ($sink instanceof Loader) { + $this->sinks = $this->sinks->merge(new Sinks(new Node\Write($this->root, $sink))); + + return $this; + } + + $prefix = new self($this->extractor, $this->context->withErrorHandler($this->context->errorHandler())); + $prefix->root = $this->root; + + if ($sink instanceof Sink\Transactional) { + foreach ($sink->sinks() as $child) { + $prefix->load($child); + } + + $writes = []; + + foreach ($prefix->sinks as $sinkRoot) { + // checked BEFORE the splat below, or PHP raises a TypeError first + $writes[] = $sinkRoot instanceof Node\Transaction + ? throw InvalidLogicException::nestedTransaction() + : $sinkRoot; + } + + $this->sinks = $this->sinks->merge(new Sinks(new Node\Transaction($sink->transaction(), ...$writes))); + + return $this; + } + + $sink->write($prefix); + + if ($prefix->context->errorHandler() !== $this->context->errorHandler()) { + throw InvalidLogicException::errorHandlerInsideSink($sink::class); + } + + $this->sinks = $this->sinks->merge($prefix->sinks); return $this; } @@ -619,7 +573,7 @@ public function load(Loader $loader): self */ public function match(Schema $schema, ?SchemaValidator $validator = null): self { - $this->pipeline->add(new SchemaValidationLoader($schema, $validator ?? new StrictValidator())); + $this->root = new Node\Validate($this->root, $schema, $validator ?? new StrictValidator()); return $this; } @@ -644,7 +598,7 @@ public function offset(?int $offset): self return $this; } - $this->pipeline->add(new OffsetProcessor($offset)); + $this->root = new Node\Offset($this->root, $offset); return $this; } @@ -668,9 +622,7 @@ public function repartition(string|Reference $entry, string|Reference ...$entrie { array_unshift($entries, $entry); - foreach (RepartitionSteps::of(References::init(...$entries), $this->context->config) as $step) { - $this->pipeline->add($step); - } + $this->root = new Node\Repartition($this->root, References::init(...$entries)); return $this; } @@ -694,23 +646,23 @@ public function printRows( } /** - * @lazy - * - * @throws SchemaNotDerivableException + * The plan $trigger would run over this frame, frozen: later verbs on this frame do not reach it. The default + * adds no consumer of its own - it draws the frame as built, its chain and its sinks. toString() prints it as a + * tree. Answers from the plan without reading a row. */ - public function printSchema(SchemaFormatter $formatter = new ASCIISchemaFormatter()): void + public function explain(Trigger $trigger = Trigger::run): Plan { - echo $formatter->format($this->schema()); + return Plan::of($trigger->plan($this->root, $this->sinks), $this->context); } /** - * @internal engine paths only - GroupedDataFrame builds its steps against this frame's plan + * @lazy + * + * @throws SchemaNotDerivableException */ - public function registerGroupBy(GroupBy $groupBy, ?GroupByAlgorithmBuilder $algorithm = null): void + public function printSchema(SchemaFormatter $formatter = new ASCIISchemaFormatter()): void { - foreach (GroupBySteps::of($groupBy, $this->context->config, $algorithm) as $step) { - $this->pipeline->add($step); - } + echo $formatter->format($this->schema()); } /** @@ -718,14 +670,14 @@ public function registerGroupBy(GroupBy $groupBy, ?GroupByAlgorithmBuilder $algo */ public function rename(string $from, string $to): self { - $this->pipeline->add(new RenameEntryTransformer($from, $to)); + $this->root = new Node\Rename($this->root, $from, $to); return $this; } public function renameEach(RenameEntryStrategy ...$strategies): self { - $this->pipeline->add(new RenameEachEntryTransformer(...$strategies)); + $this->root = new Node\RenameEach($this->root, array_values($strategies)); return $this; } @@ -747,12 +699,11 @@ public function rows(Transformer|Transformation $transformer): self * - column statistics - analyze()->withColumnStatistics() * - schema - analyze()->withSchema() * - * @param null|callable(Rows $rows, FlowContext $context): void $callback * @param Analyze|bool $analyze - when set run will return Report * * @return ($analyze is Analyze|true ? Report : null) */ - public function run(?callable $callback = null, bool|Analyze $analyze = false): ?Report + public function run(bool|Analyze $analyze = false): ?Report { if ($analyze === false) { $analyze = $this->context->config->analyze(); @@ -760,20 +711,13 @@ public function run(?callable $callback = null, bool|Analyze $analyze = false): $collector = new StatisticsCollector($analyze, $this->context); - try { - foreach ($this->pipeline->process($this->context) as $rows) { - if ($callback !== null) { - $callback($rows, $this->context); - } - - $collector->capture($rows); - } - - $collector->end(); - } catch (Throwable $e) { - $collector->end($e); - - throw $e; + foreach ($this->context + ->config + ->executor() + ->execute( + $this->context->config->planner()->plan(Trigger::run->plan($this->root, $this->sinks), $this->context), + ) as $rows) { + $collector->capture($rows); } return $collector->report(); @@ -786,7 +730,11 @@ public function run(?callable $callback = null, bool|Analyze $analyze = false): */ public function schema(): Schema { - return $this->pipeline->bind()->schema; + return $this->context + ->config + ->planner() + ->plan(Trigger::rows->plan($this->root, $this->sinks), $this->context) + ->schema(); } /** @@ -795,7 +743,7 @@ public function schema(): Schema */ public function select(string|Reference ...$entries): self { - $this->pipeline->add(new SelectEntriesTransformer(...$entries)); + $this->root = new Node\Select($this->root, array_values($entries)); return $this; } @@ -811,9 +759,7 @@ public function sortBy(array|Reference|string $entries, ?SortAlgorithmBuilder $a { $references = is_array($entries) ? $entries : [$entries]; - foreach (SortSteps::of(refs(...$references), $this->context->config, $algorithm) as $step) { - $this->pipeline->add($step); - } + $this->root = new Node\Sort($this->root, refs(...$references), $algorithm); return $this; } @@ -836,7 +782,7 @@ public function transform(Transformer|Transformation|Transformations|WithEntry $ */ public function until(ScalarFunction $function): self { - $this->pipeline->add(new UntilTransformer($function)); + $this->root = new Node\Until($this->root, $function); return $this; } @@ -850,7 +796,7 @@ public function until(ScalarFunction $function): self */ public function void(): self { - $this->pipeline->add(new VoidProcessor()); + $this->root = new Node\Discard($this->root); return $this; } @@ -861,7 +807,7 @@ public function void(): self public function with(Transformer|Transformation|Transformations|WithEntry $transformer): self { if ($transformer instanceof Transformer) { - $this->pipeline->add($transformer); + $this->root = new Node\Transform($this->root, $transformer); return $this; } @@ -906,19 +852,9 @@ public function withEntries(array $references): self */ public function withEntry(string|Definition $entry, ScalarFunction|WindowFunction $reference): self { - if ($reference instanceof WindowFunction) { - if ($reference->window()->partitions()->count()) { - foreach (RepartitionSteps::of($reference->window()->partitions(), $this->context->config) as $step) { - $this->pipeline->add($step); - } - } else { - $this->pipeline->add(new CollectingProcessor()); - } - - $this->pipeline->add(new WindowProcessor($entry, $reference)); - } else { - $this->with(new ScalarFunctionTransformer($entry, $reference)); - } + $this->root = $reference instanceof WindowFunction + ? new Node\WindowColumn($this->root, $entry, $reference) + : new Node\WithColumn($this->root, $entry, $reference); return $this; } @@ -927,8 +863,8 @@ public function withEntry(string|Definition $entry, ScalarFunction|WindowFunctio * @lazy * Alias for ETL::load function. */ - public function write(Loader $loader): self + public function write(Loader|Sink $sink): self { - return $this->load($loader); + return $this->load($sink); } } diff --git a/src/core/etl/src/Flow/ETL/DataFrame/GroupedDataFrame.php b/src/core/etl/src/Flow/ETL/DataFrame/GroupedDataFrame.php index c888c15d76..8e712096e3 100644 --- a/src/core/etl/src/Flow/ETL/DataFrame/GroupedDataFrame.php +++ b/src/core/etl/src/Flow/ETL/DataFrame/GroupedDataFrame.php @@ -4,7 +4,6 @@ namespace Flow\ETL\DataFrame; -use Flow\ETL\Config\Grouping\GroupByAlgorithmBuilder; use Flow\ETL\DataFrame; use Flow\ETL\Function\AggregatingFunction; use Flow\ETL\GroupBy; @@ -15,23 +14,20 @@ { public function __construct( private DataFrame $df, + private DataFrame $input, private GroupBy $groupBy, - private ?GroupByAlgorithmBuilder $algorithm = null, ) {} public function aggregate(AggregatingFunction ...$aggregations): DataFrame { $this->groupBy->aggregate(...$aggregations); - $this->df->registerGroupBy($this->groupBy, $this->algorithm); return $this->df; } public function pivot(Reference $ref, PivotValues $values): self { - // a discovering form scans here, above the plan and over this frame, so the processor only - // ever holds concrete literals - $this->groupBy->pivot($ref, $values->resolve($this->df, $ref)); + $this->groupBy->pivot($ref, $values->resolve($this->input, $ref)); return $this; } diff --git a/src/core/etl/src/Flow/ETL/Exception/FailedRetryException.php b/src/core/etl/src/Flow/ETL/Exception/FailedRetryException.php deleted file mode 100644 index bd9ef532e4..0000000000 --- a/src/core/etl/src/Flow/ETL/Exception/FailedRetryException.php +++ /dev/null @@ -1,25 +0,0 @@ -count(); - - $message = sprintf('Retry failed after %d attempts.', $totalAttempts); - } - - parent::__construct($message, 0, $record->last()?->exception); - } -} diff --git a/src/core/etl/src/Flow/ETL/Exception/InvalidLogicException.php b/src/core/etl/src/Flow/ETL/Exception/InvalidLogicException.php index fec51ba7fe..b463774c34 100644 --- a/src/core/etl/src/Flow/ETL/Exception/InvalidLogicException.php +++ b/src/core/etl/src/Flow/ETL/Exception/InvalidLogicException.php @@ -13,14 +13,73 @@ public static function because(string $format, float|int|string ...$parameters): return new self(sprintf($format, ...$parameters)); } - public static function cyclicPlanOnDescribe(): self + public static function cyclicPlanOnRun(): self { - return self::cyclicPlan('describe'); + return self::cyclicPlan('run'); } - public static function cyclicPlanOnRun(): self + public static function nestedTransaction(): self { - return self::cyclicPlan('run'); + return self::because('A transaction cannot contain another transaction'); + } + + public static function nodeNotTranslatable(string $kind): self + { + return self::because('No physical steps are known for node %s', $kind); + } + + public static function pipelineWithoutSource(string $what): self + { + return self::because('%s has no source extractor', $what); + } + + public static function sinkNotOnSpine(string $sink): self + { + return self::because('A sink root shares no node with the plan: %s', $sink); + } + + public static function sinkRootRewritten(string $given): self + { + return self::because('A sink root rewrite must return a Write or a Transaction, %s given', $given); + } + + public static function joinSideIsNotAPlanRoot(string $given): self + { + return self::because( + 'The right side of a join must be a frame\'s plan root (Result or Outputs), %s given', + $given, + ); + } + + public static function firstConsumerIsATransaction(): self + { + return self::because('The first consumer of a plan cannot be a Transaction'); + } + + public static function consumerRewritten(string $given): self + { + return self::because( + 'An Outputs consumer rewrite must return a Result, a Write or a Transaction, %s given', + $given, + ); + } + + public static function transformationReturnedAnotherFrame(string $transformation): self + { + return self::because( + 'A Transformation inside a sink must return the frame it was given; %s returned another frame, so its ' + . 'writes would never run', + $transformation, + ); + } + + public static function errorHandlerInsideSink(string $sink): self + { + return self::because( + 'onError() inside a sink cannot apply, because a plan runs under one error handler: call onError() on ' + . 'the frame, not inside %s', + $sink, + ); } private static function cyclicPlan(string $operation): self diff --git a/src/core/etl/src/Flow/ETL/Exception/SchemaNotDerivableException.php b/src/core/etl/src/Flow/ETL/Exception/SchemaNotDerivableException.php index 8b00fcba60..abe02bfbeb 100644 --- a/src/core/etl/src/Flow/ETL/Exception/SchemaNotDerivableException.php +++ b/src/core/etl/src/Flow/ETL/Exception/SchemaNotDerivableException.php @@ -47,12 +47,11 @@ public static function probeRefused(string $extractor, string $refusal, Throwabl ); } - public static function nonRewindable(string $extractor): self + public static function nonRewindable(): self { - return new self(sprintf( - '%s cannot read its dataset twice, so discover_pivot_values() cannot scan it before the pivot ' - . 'runs. Declare the values with pivot_values(...).', - $extractor, - )); + return new self( + 'The frame reads a source that cannot read its dataset twice, so discover_pivot_values() cannot scan it ' + . 'before the pivot runs. Declare the values with pivot_values(...).', + ); } } diff --git a/src/core/etl/src/Flow/ETL/Exception/SinkFailure.php b/src/core/etl/src/Flow/ETL/Exception/SinkFailure.php new file mode 100644 index 0000000000..837970dfaf --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Exception/SinkFailure.php @@ -0,0 +1,20 @@ +getMessage(), 0, $cause); + } +} diff --git a/src/core/etl/src/Flow/ETL/Exception/TransactionRolledBack.php b/src/core/etl/src/Flow/ETL/Exception/TransactionRolledBack.php new file mode 100644 index 0000000000..825766bbf1 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Exception/TransactionRolledBack.php @@ -0,0 +1,22 @@ +getMessage(), 0, $cause); + } +} diff --git a/src/core/etl/src/Flow/ETL/Executor.php b/src/core/etl/src/Flow/ETL/Executor.php new file mode 100644 index 0000000000..84a8975b9e --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Executor.php @@ -0,0 +1,153 @@ + + */ + private WeakMap $advancing; + + public function __construct() + { + /** @var WeakMap $advancing */ + $advancing = new WeakMap(); + $this->advancing = $advancing; + } + + /** + * Runs a whole plan inside one DataFrame span of the plan's context. + * + * @throws InvalidLogicException when the plan's context is already being advanced + * + * @return Generator + */ + public function execute(PhysicalPlan $plan): Generator + { + // the plan was built with this context (PipelineSplit hands it to the root Pipeline), so there is + // no way to open a span on a context the plan does not belong to + $context = $plan->root()->context(); + + if ($this->advancing->offsetExists($context)) { + throw InvalidLogicException::cyclicPlanOnRun(); + } + + $this->advancing[$context] = true; + $context->telemetry()->dataFrameStarted($context); + + try { + foreach ($this->executePipeline($plan->root()) as $rows) { + // disarmed across our own yield: while parked we are not advancing, so a second read + // arriving here is another reader of the same plan, not recursion + $this->advancing->offsetUnset($context); + + yield $rows; + + $this->advancing[$context] = true; + } + } catch (Throwable $e) { + $context->telemetry()->dataFrameFailed($context, $e); + + throw $e; + } finally { + $this->advancing->offsetUnset($context); + // drained, abandoned, or destroyed because the consumer's body threw - PHP runs this finally in + // every case, and it is a no-op once dataFrameFailed() closed the span + $context->telemetry()->dataFrameCompleted($context); + } + } + + /** + * Executes $plan and merges every batch into one Rows. + * + * @throws InvalidLogicException when the plan's context is already being advanced + */ + public function fetch(PhysicalPlan $plan): Rows + { + return $this->merge($this->execute($plan), $plan); + } + + /** + * Merges every batch into one Rows. An empty result still carries the plan's schema, or an empty one when the + * plan cannot describe its rows. + * + * @param Generator $batches $plan's rows + */ + public function merge(Generator $batches, PhysicalPlan $plan): Rows + { + $rows = null; + + foreach ($batches as $nextRows) { + $rows = $rows === null ? $nextRows : $rows->merge($nextRows); + } + + if ($rows !== null) { + return $rows; + } + + try { + return new Rows($plan->schema()); + } catch (SchemaNotDerivableException) { + return new Rows(new Schema()); + } + } + + /** + * Drives one pipeline and the pipelines it reads, with no DataFrame span - the pipeline's context belongs to + * whoever runs it. + * + * @return Generator + */ + public function executePipeline(Pipeline $pipeline): Generator + { + $chain = []; + + for ($stage = $pipeline; $stage !== null; $stage = $stage->input()) { + $chain[] = $stage; + } + + $chain = array_reverse($chain); + $leaf = $chain[0]; + $source = $leaf->segments()->extractor() ?? throw InvalidLogicException::pipelineWithoutSource(sprintf( + 'pipeline #%d', + $leaf->id, + )); + $generator = $source instanceof FileExtractor + ? $source->extract($leaf->context(), $leaf->limit(), $leaf->pathFilter()) + : $source->extract($leaf->context(), $leaf->limit()); + + foreach ($chain as $stage) { + foreach ($stage->segments()->all() as $segment) { + $generator = $segment->execute($generator, $stage->context()); + $processor = $segment->processor(); + + if ($processor !== null) { + $generator = $processor->process($generator, $stage->context()); + } + } + } + + // a foreach, never `yield from`: the re-yield must not forward the consumer's sent signal + foreach ($generator as $rows) { + yield $rows; + } + } +} diff --git a/src/core/etl/src/Flow/ETL/Executor/Described.php b/src/core/etl/src/Flow/ETL/Executor/Described.php new file mode 100644 index 0000000000..b181cb0b30 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Executor/Described.php @@ -0,0 +1,25 @@ +root; + } + + public function schema(): Schema + { + return $this->schema; + } +} diff --git a/src/core/etl/src/Flow/ETL/Executor/PhysicalPlan.php b/src/core/etl/src/Flow/ETL/Executor/PhysicalPlan.php new file mode 100644 index 0000000000..5404902a02 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Executor/PhysicalPlan.php @@ -0,0 +1,23 @@ + $limit handed to the source extractor when this pipeline reads it; meaningless + * behind an input edge + * @param Filter $pathFilter handed to a FileExtractor source when this pipeline reads it; meaningless + * behind an input edge + */ + public function __construct( + public int $id, + private Segments $segments, + private FlowContext $context, + private ?self $input = null, + private ?int $limit = null, + private Filter $pathFilter = new OnlyFiles(), + ) {} + + public function segments(): Segments + { + return $this->segments; + } + + public function context(): FlowContext + { + return $this->context; + } + + /** + * @return null|int<1, max> + */ + public function limit(): ?int + { + return $this->limit; + } + + public function pathFilter(): Filter + { + return $this->pathFilter; + } + + /** + * The upstream stage, cut off after a blocking node. The Executor flattens the chain. + */ + public function input(): ?self + { + return $this->input; + } +} diff --git a/src/core/etl/src/Flow/ETL/Executor/Raw.php b/src/core/etl/src/Flow/ETL/Executor/Raw.php new file mode 100644 index 0000000000..387e96ed53 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Executor/Raw.php @@ -0,0 +1,30 @@ +root; + } + + public function schema(): Schema + { + return $this->schema ?? throw $this->why; + } +} diff --git a/src/core/etl/src/Flow/ETL/Pipeline/Segment.php b/src/core/etl/src/Flow/ETL/Executor/Segment.php similarity index 83% rename from src/core/etl/src/Flow/ETL/Pipeline/Segment.php rename to src/core/etl/src/Flow/ETL/Executor/Segment.php index 786b8fc57b..09eb6554be 100644 --- a/src/core/etl/src/Flow/ETL/Pipeline/Segment.php +++ b/src/core/etl/src/Flow/ETL/Executor/Segment.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Pipeline; +namespace Flow\ETL\Executor; use Flow\ETL\ErrorHandler\ExtractionAction; use Flow\ETL\ErrorHandler\ExtractionError; @@ -11,13 +11,14 @@ use Flow\ETL\ErrorHandler\TransformationAction; use Flow\ETL\ErrorHandler\TransformationError; use Flow\ETL\Exception\LimitReachedException; +use Flow\ETL\Exception\SinkFailure; +use Flow\ETL\Exception\TransactionRolledBack; use Flow\ETL\Extractor; use Flow\ETL\Extractor\Signal; use Flow\ETL\FlowContext; use Flow\ETL\Loader; use Flow\ETL\Loader\Closure; use Flow\ETL\Loader\Discardable; -use Flow\ETL\Loader\LoaderTree; use Flow\ETL\Processor; use Flow\ETL\Rows; use Flow\ETL\Transformer; @@ -25,14 +26,10 @@ use SplObjectStorage; use Throwable; -use function array_map; -use function array_merge; use function count; /** * A segment of the pipeline containing Transformers/Loaders until a Processor boundary. - * - * @internal */ final readonly class Segment { @@ -56,15 +53,6 @@ public function add(Transformer|Loader $step): void $this->steps->offsetSet($step); } - public function contains(Transformer|Loader|Processor $step): bool - { - if ($step instanceof Processor) { - return $this->processor === $step; - } - - return $this->steps->offsetExists($step); - } - /** * Execute this segment's Transformers and Loaders on the input generator. * @@ -145,6 +133,15 @@ public function execute(Generator $input, FlowContext $context): Generator $rows = $limit->rows ?? new Rows($rows->schema()); $stop = true; } catch (Throwable $failure) { + if ($failure instanceof SinkFailure) { + throw $failure->cause; + } + + if ($failure instanceof TransactionRolledBack) { + $step = $failure->loader; + $failure = $failure->cause; + } + if ($step instanceof Transformer) { if ( $context->errorHandler()->onTransformation(new TransformationError( @@ -222,9 +219,8 @@ public function execute(Generator $input, FlowContext $context): Generator } /** - * A completed run ends only the outermost loader: a wrapper's closure() drains its stream before forwarding, and - * that ordering is the wrapper's to own. A dead run has no such ordering, and a wrapper that forgets to forward - * would strand the sink it wraps - so discarding walks the whole loader tree instead of trusting each wrapper. + * Every planner-built wrapper forwards discard() to its children (SinkFeed, TransactionalSinks), so each step is + * ended directly - there is no user-supplied wrapper left to distrust. * * @param array $loaders * @@ -234,11 +230,6 @@ private function endLoaders(array $loaders, FlowContext $context, bool $complete { $ending = []; - if (!$completed) { - $tree = new LoaderTree(); - $loaders = array_merge(...array_map(static fn(Loader $loader): array => $tree->flatten($loader), $loaders)); - } - foreach ($loaders as $loader) { try { if ($completed) { @@ -255,13 +246,9 @@ private function endLoaders(array $loaders, FlowContext $context, bool $complete // a closure() that threw published at most part of its output; the rest is abandoned as on // a failed run - foreach ((new LoaderTree())->flatten($loader) as $node) { - if (!$node instanceof Discardable) { - continue; - } - + if ($loader instanceof Discardable) { try { - $node->discard($context); + $loader->discard($context); } catch (Throwable $discardFailure) { $context ->telemetry() @@ -285,24 +272,9 @@ private function endLoaders(array $loaders, FlowContext $context, bool $complete return $ending; } - /** - * Check if segment contains a step of the given class. - * - * @param class-string $class - */ - public function has(string $class): bool + public function extractor(): ?Extractor { - if ($this->processor instanceof $class) { - return true; - } - - foreach ($this->steps as $step) { - if ($step instanceof $class) { - return true; - } - } - - return false; + return $this->extractor; } public function processor(): ?Processor @@ -318,17 +290,6 @@ public function steps(): array return iterator_to_array($this->steps); } - public function withExtractor(Extractor $extractor): self - { - $segment = new self($this->processor, $extractor); - - foreach ($this->steps as $step) { - $segment->steps->offsetSet($step); - } - - return $segment; - } - public function withProcessor(Processor $processor): self { $segment = new self($processor, $this->extractor); diff --git a/src/core/etl/src/Flow/ETL/Executor/Segments.php b/src/core/etl/src/Flow/ETL/Executor/Segments.php new file mode 100644 index 0000000000..802131144b --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Executor/Segments.php @@ -0,0 +1,51 @@ + */ + private array $segments = []; + + public function __construct(?Extractor $extractor = null) + { + $this->currentSegment = new Segment(extractor: $extractor); + } + + public function add(Transformer|Loader|Processor $step): void + { + if ($step instanceof Processor) { + $this->segments[] = $this->currentSegment->withProcessor($step); + $this->currentSegment = new Segment(); + } else { + $this->currentSegment->add($step); + } + } + + public function extractor(): ?Extractor + { + return ($this->segments[0] ?? $this->currentSegment)->extractor(); + } + + /** + * Get all segments including the current one. + * + * @return array + */ + public function all(): array + { + return [...$this->segments, $this->currentSegment]; + } +} diff --git a/src/core/etl/src/Flow/ETL/Executor/SinkFeed.php b/src/core/etl/src/Flow/ETL/Executor/SinkFeed.php new file mode 100644 index 0000000000..590b54c95a --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Executor/SinkFeed.php @@ -0,0 +1,107 @@ + + */ + private readonly array $consumers; + + /** + * @param Loader ...$consumers the sink pipeline's last steps, which a completed run's discard() is forwarded to + * + * @throws InvalidArgumentException when no consumer is given + */ + public function __construct( + private readonly FeedExtractor $feed, + private readonly SinkRun $run, + private readonly SinkOffers $offers, + Loader ...$consumers, + ) { + $consumers = array_values($consumers); + + if ($consumers === []) { + throw new InvalidArgumentException('At least one consumer must be provided'); + } + + $this->consumers = $consumers; + } + + public function load(Rows $rows, FlowContext $context): void + { + $this->feed->feed($rows); + $this->offers->forget(); + + // offered INSIDE the sink pipeline -> wrapped, so the outer Segment does not offer it twice. An ENDING + // failure (a limit inside the sink pipeline completed it mid-load) was offered to nobody -> raw, so the outer + // Segment offers it exactly once, against this step. + try { + $this->run->advance(); + } catch (Throwable $failure) { + throw $this->offers->offered($failure) ? new SinkFailure($failure) : $failure; + } + } + + public function closure(FlowContext $context): void + { + $this->feed->finish(); + + // raw: endLoaders() never offers, so the user's own exception class must surface + try { + $this->run->advance(); + } finally { + $this->run->drop(); + } + } + + public function discard(FlowContext $context): void + { + if ($this->run->terminated()) { + // the side Segment's finally already ended the consumers - closure() on completion, discard() on + // failure - so forward only after a completed run, and never twice + if ($this->run->completed()) { + foreach ($this->consumers as $consumer) { + if ($consumer instanceof Discardable) { + $consumer->discard($context); + } + } + } + + return; + } + + // start-or-resume and unwind: the side Segment ends its consumers with completed: false + try { + $this->run->advance(); + } finally { + $this->run->drop(); + } + } + + /** + * After a rollback: the next batch runs a fresh fiber over the same sink pipeline. + */ + public function restart(): void + { + $this->run->drop(); + } +} diff --git a/src/core/etl/src/Flow/ETL/Executor/SinkOffers.php b/src/core/etl/src/Flow/ETL/Executor/SinkOffers.php new file mode 100644 index 0000000000..c3bfcd863e --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Executor/SinkOffers.php @@ -0,0 +1,60 @@ +last = $error->cause; + + return $this->handler->onExtraction($error); + } + + public function onTransformation(TransformationError $error): TransformationAction + { + $this->last = $error->cause; + + return $this->handler->onTransformation($error); + } + + public function onLoading(LoadingError $error): LoadingAction + { + $this->last = $error->cause; + + return $this->handler->onLoading($error); + } + + /** + * By identity: Segment hands the handler the failure and rethrows the same instance. + */ + public function offered(Throwable $failure): bool + { + return $this->last === $failure; + } + + public function forget(): void + { + $this->last = null; + } +} diff --git a/src/core/etl/src/Flow/ETL/Executor/SinkRun.php b/src/core/etl/src/Flow/ETL/Executor/SinkRun.php new file mode 100644 index 0000000000..2547e0a1d1 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Executor/SinkRun.php @@ -0,0 +1,75 @@ +fiber ??= new Fiber(function (): void { + foreach ($this->executor->executePipeline($this->side) as $_) { + } + }); + + if ($this->fiber->isTerminated()) { + return; + } + + try { + $this->fiber->isStarted() ? $this->fiber->resume() : $this->fiber->start(); + } catch (Throwable $failure) { + $this->completed = false; + + throw $failure; + } + + $this->completed = $this->fiber->isTerminated(); + } + + public function terminated(): bool + { + return $this->fiber?->isTerminated() ?? $this->ended; + } + + public function completed(): bool + { + return $this->completed; + } + + /** + * Destroying a SUSPENDED fiber unwinds it into the side Segment's finally, now rather than at the next GC; after a + * TERMINATED one the next advance() builds a fresh Fiber over the same pipeline, whose bound steps carry over. + */ + public function drop(): void + { + $this->ended = $this->terminated(); + $this->fiber = null; + } +} diff --git a/src/core/etl/src/Flow/ETL/Execution/StatisticsCollector.php b/src/core/etl/src/Flow/ETL/Executor/StatisticsCollector.php similarity index 90% rename from src/core/etl/src/Flow/ETL/Execution/StatisticsCollector.php rename to src/core/etl/src/Flow/ETL/Executor/StatisticsCollector.php index b3cd24a979..b354ceeb52 100644 --- a/src/core/etl/src/Flow/ETL/Execution/StatisticsCollector.php +++ b/src/core/etl/src/Flow/ETL/Executor/StatisticsCollector.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Execution; +namespace Flow\ETL\Executor; use DateTimeImmutable; use Flow\ETL\Analyze; @@ -15,7 +15,6 @@ use Flow\ETL\FlowContext; use Flow\ETL\Rows; use Flow\ETL\Schema; -use Throwable; use function gc_collect_cycles; @@ -93,15 +92,6 @@ public function capture(Rows $rows): void } } - public function end(?Throwable $exception = null): void - { - if ($exception !== null) { - $this->context->telemetry()->dataFrameFailed($this->context, $exception); - } else { - $this->context->telemetry()->dataFrameCompleted($this->context); - } - } - /** * @return (T is Analyze|true ? Report : null) */ diff --git a/src/core/etl/src/Flow/ETL/Executor/TransactionRollback.php b/src/core/etl/src/Flow/ETL/Executor/TransactionRollback.php new file mode 100644 index 0000000000..48ba2b84f4 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Executor/TransactionRollback.php @@ -0,0 +1,28 @@ +transaction->rollback($cause); + } catch (Throwable $rollback) { + $context->telemetry()->logger()->error('Transaction failed to roll back.', ['exception' => $rollback]); + } + } +} diff --git a/src/core/etl/src/Flow/ETL/Executor/TransactionalSinks.php b/src/core/etl/src/Flow/ETL/Executor/TransactionalSinks.php new file mode 100644 index 0000000000..52f8c6b39d --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Executor/TransactionalSinks.php @@ -0,0 +1,95 @@ + $children + */ + public function __construct( + private Transaction $transaction, + private array $children, + ) { + $this->rollback = new TransactionRollback($transaction); + } + + public function load(Rows $rows, FlowContext $context): void + { + $this->transaction->begin(); + + foreach ($this->children as $child) { + try { + $child->load($rows, $context); + } catch (Throwable $failure) { + $this->rollback->rollback($failure, $context); + + // the FAILING child only: restarting a live sibling would unwind its fiber and lose what it buffered + if ($child instanceof SinkFeed) { + $child->restart(); + } + + throw new TransactionRolledBack($child, $failure instanceof SinkFailure ? $failure->cause : $failure); + } + } + + try { + $this->transaction->commit(); + } catch (Throwable $failure) { + $this->rollback->rollback($failure, $context); + + throw $failure; + } + } + + /** + * The endings path offers nothing, so nothing is wrapped: a failing drain surfaces as the user's own exception. + */ + public function closure(FlowContext $context): void + { + $this->transaction->begin(); + + try { + foreach ($this->children as $child) { + if ($child instanceof Closure) { + $child->closure($context); + } + } + + $this->transaction->commit(); + } catch (Throwable $failure) { + $this->rollback->rollback($failure, $context); + + throw $failure; + } + } + + /** + * No transaction: nothing is written on a dead run. + */ + public function discard(FlowContext $context): void + { + foreach ($this->children as $child) { + if ($child instanceof Discardable) { + $child->discard($context); + } + } + } +} diff --git a/src/core/etl/src/Flow/ETL/Extractor.php b/src/core/etl/src/Flow/ETL/Extractor.php index 2f869bef1b..af514a1d7f 100644 --- a/src/core/etl/src/Flow/ETL/Extractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor.php @@ -18,15 +18,22 @@ interface Extractor * yield from is forbidden here: it routes send() into the delegate, so Signal::STOP is never * observed by this generator. * + * @param null|int<1, max> $limit rows in total the plan needs from this read. A hint: the Limit step above the + * source enforces the exact count, so a source that reads more, or ignores it, + * is still correct. + * * @return Generator */ - public function extract(FlowContext $context): Generator; + public function extract(FlowContext $context, ?int $limit = null): Generator; /** * Answers before extract() runs, so every batch it yields carries this shape. Takes no * FlowContext: a source that needs the pipeline's context to describe itself has not moved * the answer to bind time. * + * Called once per RUN - every run plans afresh - so it MUST be idempotent and cheap on repeat: memoise + * what it sniffs, as CSVExtractor and ArrayExtractor do. + * * @throws SchemaNotDerivableException when the source cannot describe what it will produce */ public function schema(): Schema; diff --git a/src/core/etl/src/Flow/ETL/Extractor/ArrayExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/ArrayExtractor.php index 77d929e48e..43b97b2610 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/ArrayExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/ArrayExtractor.php @@ -62,7 +62,7 @@ public function isRepeatable(): bool /** * @return Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { $batchSize = $this->batchSize(); $schema = $this->schema(); diff --git a/src/core/etl/src/Flow/ETL/Extractor/BatchByExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/BatchByExtractor.php index a45219a8d4..55dc468c9b 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/BatchByExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/BatchByExtractor.php @@ -42,7 +42,7 @@ public function isRepeatable(): bool /** * @return Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { // pinned from the declaration or the first child batch, then every later batch is matched to // it - a buffer spans child batches, so its rows must all answer to one schema before trusted() diff --git a/src/core/etl/src/Flow/ETL/Extractor/BatchExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/BatchExtractor.php index ae5e5c1645..35b6f9dfd3 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/BatchExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/BatchExtractor.php @@ -28,7 +28,7 @@ public function __construct( /** * @return Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { // pinned from the declaration or the first child batch, then every later batch is matched to // it - a buffer spans child batches, so its rows must all answer to one schema before trusted() diff --git a/src/core/etl/src/Flow/ETL/Extractor/CacheExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/CacheExtractor.php index 074f8bac82..681b6d595f 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/CacheExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/CacheExtractor.php @@ -28,7 +28,7 @@ public function __construct( /** * @return Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { $cache = $this->cache ?? $context->cache(); // A declared schema describes both arms. Without one, schema() answers from whichever source diff --git a/src/core/etl/src/Flow/ETL/Extractor/ChainExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/ChainExtractor.php index 792b61fb54..6648e8bde5 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/ChainExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/ChainExtractor.php @@ -32,7 +32,7 @@ public function isRepeatable(): bool /** * @return Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { // Every child's batches are projected onto the folded shape, so each yields the union // rather than only the columns its own source happens to carry. A child that cannot diff --git a/src/core/etl/src/Flow/ETL/Extractor/CollectingExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/CollectingExtractor.php index a31036982c..35d5593ec6 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/CollectingExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/CollectingExtractor.php @@ -18,7 +18,7 @@ public function __construct( private Extractor $extractor, ) {} - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { $schema = $this->schema; diff --git a/src/core/etl/src/Flow/ETL/Extractor/DataFrameExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/DataFrameExtractor.php index 4cca673cb6..049478c3e1 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/DataFrameExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/DataFrameExtractor.php @@ -5,27 +5,46 @@ namespace Flow\ETL\Extractor; use Flow\ETL\DataFrame; -use Flow\ETL\Extractor; +use Flow\ETL\Exception\SchemaNotDerivableException; use Flow\ETL\FlowContext; +use Flow\ETL\Plan; +use Flow\ETL\Plan\Node\Limit; +use Flow\ETL\Plan\Trigger; +use Flow\ETL\Rows; use Flow\ETL\Schema; use Generator; use function Flow\ETL\DSL\array_to_rows; -final class DataFrameExtractor implements Extractor +final class DataFrameExtractor implements RewindableExtractor { private ?Schema $schema = null; - public function __construct( - private DataFrame $dataFrame, - ) {} + private readonly Plan $plan; + + public function __construct(DataFrame $dataFrame) + { + $this->plan = $dataFrame->explain(Trigger::rows); + } /** - * @return Generator + * Runs the frame with its own configuration; a limit stops the frame's rows, so its own rules push it into its + * source. + * + * @param null|positive-int $limit + * + * @return Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { - foreach ($this->dataFrame->get() as $rows) { + $logical = $this->plan->logical; + $config = $this->plan->context->config; + + if ($limit !== null) { + $logical = Trigger::rows->plan(new Limit($logical->spine(), $limit), $logical->sinks()); + } + + foreach ($config->executor()->execute($config->planner()->plan($logical, $this->plan->context)) as $rows) { if ($this->schema !== null) { $rows = array_to_rows($rows->toArray(), $this->schema, $context->hydrator()); } @@ -38,13 +57,26 @@ public function extract(FlowContext $context): Generator } } + public function isRepeatable(): bool + { + return (new Repeatability())->ofPlan($this->plan->logical); + } + + /** + * @throws SchemaNotDerivableException + */ public function schema(): Schema { if ($this->schema !== null) { return $this->schema; } - return $this->dataFrame->schema(); + return $this->plan + ->context + ->config + ->planner() + ->plan($this->plan->logical, $this->plan->context) + ->schema(); } public function withSchema(Schema $schema): static diff --git a/src/core/etl/src/Flow/ETL/Extractor/FeedExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/FeedExtractor.php index 55663f151e..79048d0016 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/FeedExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/FeedExtractor.php @@ -18,8 +18,6 @@ * same resume that fed it and a late Signal::STOP still lands on a live yield. * * Must be driven from inside a Fiber - extract() calls Fiber::suspend(). - * - * @internal */ final class FeedExtractor implements Extractor { @@ -34,7 +32,7 @@ public function __construct( /** * @return Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { while (true) { if ($this->batch === null) { diff --git a/src/core/etl/src/Flow/ETL/Extractor/FileColumns.php b/src/core/etl/src/Flow/ETL/Extractor/FileColumns.php index ebc728a4f7..9d86a02afb 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/FileColumns.php +++ b/src/core/etl/src/Flow/ETL/Extractor/FileColumns.php @@ -11,6 +11,7 @@ use Throwable; use function array_key_exists; +use function array_keys; use function array_values; use function Flow\ETL\DSL\str_schema; use function sprintf; @@ -44,6 +45,20 @@ public function declare(Schema $schema): Schema ); } + /** + * $declared carries a withSchema()d partition column's type; keep() drops the body columns it brings. + */ + public function partitions(Schema $declared): Schema + { + if ($this->partitionNames === []) { + return new Schema(); + } + + return $this->partitionColumns + ->declare($declared, $this->partitionNames, $this->partitionTypes) + ->keep(...array_keys($this->partitionNames)); + } + /** * Takes the schema declare() already produced, so the values and the schema they are written under * can never come from two different declarations. diff --git a/src/core/etl/src/Flow/ETL/Extractor/FileExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/FileExtractor.php index 0140e788d6..a86f5ded4a 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/FileExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/FileExtractor.php @@ -4,14 +4,36 @@ namespace Flow\ETL\Extractor; +use Flow\ETL\Extractor; +use Flow\ETL\FlowContext; +use Flow\ETL\Rows; +use Flow\ETL\Schema; use Flow\Filesystem\Path; use Flow\Filesystem\Path\Filter; +use Flow\Filesystem\Path\Filter\OnlyFiles; +use Generator; -interface FileExtractor +/** + * A source that lists files under a path. Its schema is a property of the source - derived from the full + * listing - and a pruned read does not change it. + */ +interface FileExtractor extends Extractor { - public function filter(): Filter; + /** + * @param null|int<1, max> $limit see Extractor::extract() + * @param Filter $pathFilter what this read lists. The Filter step stays in the plan, so a source that lists + * more, or ignores it, is still correct. + * + * @return Generator + */ + public function extract(FlowContext $context, ?int $limit = null, Filter $pathFilter = new OnlyFiles()): Generator; public function source(): Path; - public function withPathFilter(Filter $filter): static; + /** + * The partition block of this source's schema and nothing else - typed exactly as the read emits it, + * empty when the source declares no partition columns. The planner asks it to decide whether a predicate + * can be evaluated from the path alone. + */ + public function partitionSchema(): Schema; } diff --git a/src/core/etl/src/Flow/ETL/Extractor/FileReading.php b/src/core/etl/src/Flow/ETL/Extractor/FileReading.php index 93c78c52a3..370c6706b3 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/FileReading.php +++ b/src/core/etl/src/Flow/ETL/Extractor/FileReading.php @@ -7,6 +7,8 @@ use Flow\Filesystem\FileListing; use Flow\Filesystem\Filesystem; use Flow\Filesystem\Path; +use Flow\Filesystem\Path\Filter; +use Flow\Filesystem\Path\Filter\OnlyFiles; use Generator; trait FileReading @@ -30,9 +32,9 @@ private function fileColumns(Filesystem $filesystem, Path $path): FileColumns /** * @return Generator */ - private function sourceFiles(Filesystem $filesystem, Path $path): Generator + private function sourceFiles(Filesystem $filesystem, Path $path, Filter $pathFilter = new OnlyFiles()): Generator { - foreach ((new FileListing($filesystem))->list($path, $this->filter()) as $status) { + foreach ((new FileListing($filesystem))->list($path, $pathFilter) as $status) { yield new SourceFile($status->path); } } diff --git a/src/core/etl/src/Flow/ETL/Extractor/FilesExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/FilesExtractor.php index 3b22308934..c4f52896b6 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/FilesExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/FilesExtractor.php @@ -12,6 +12,8 @@ use Flow\Filesystem\Filesystem; use Flow\Filesystem\Local\NativeLocalFilesystem; use Flow\Filesystem\Path; +use Flow\Filesystem\Path\Filter; +use Flow\Filesystem\Path\Filter\OnlyFiles; use Generator; use function count; @@ -21,13 +23,12 @@ use function Flow\ETL\DSL\str_schema; use function sprintf; -final class FilesExtractor implements BatchableExtractor, Extractor, FileExtractor, LimitPushDown, RewindableExtractor +final class FilesExtractor implements BatchableExtractor, Extractor, FileExtractor, RewindableExtractor { private ?Schema $schema = null; use Batches; - use PathFiltering; - use PushesLimit; + use ListingPartitions; private readonly Filesystem $filesystem; @@ -56,17 +57,19 @@ public function isRepeatable(): bool /** * @return Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null, Filter $pathFilter = new OnlyFiles()): Generator { $batchSize = $this->batchSize(); + $fileColumns = $this->fileColumns($this->filesystem, $this->path); $schema = $this->schema(); $buffer = []; $yielded = 0; - foreach ((new FileListing($this->filesystem))->list($this->path, $this->filter()) as $fileStatus) { + foreach ((new FileListing($this->filesystem))->list($this->path, $pathFilter) as $fileStatus) { + $constants = $fileColumns->forFile(new SourceFile($fileStatus->path), $schema); $extension = $fileStatus->path->extension(); - $buffer[] = [ + $buffer[] = $constants->fill([ 'path' => $fileStatus->path->path(), 'protocol' => $fileStatus->path->protocol(), 'file_name' => $fileStatus->path->filename(), @@ -76,7 +79,7 @@ public function extract(FlowContext $context): Generator // Path::extension() answers false for an extensionless file; the column is one // type, so the absence is spelled null rather than a boolean in a string column. 'extension' => $extension === false ? null : $extension, - ]; + ]); if (count($buffer) < $batchSize) { continue; @@ -92,8 +95,6 @@ public function extract(FlowContext $context): Generator $buffer = []; - $limit = $this->pushedLimit(); - if ($limit !== null && $yielded >= $limit) { return; } @@ -104,6 +105,11 @@ public function extract(FlowContext $context): Generator } } + public function partitionSchema(): Schema + { + return $this->fileColumns($this->filesystem, $this->path)->partitions($this->schema ?? new Schema()); + } + public function source(): Path { return $this->path; @@ -111,11 +117,13 @@ public function source(): Path public function schema(): Schema { + $fileColumns = $this->fileColumns($this->filesystem, $this->path); + if ($this->schema !== null) { - return $this->schema; + return $fileColumns->declare($this->schema); } - return schema( + return $fileColumns->declare(schema( str_schema('path'), str_schema('protocol'), str_schema('file_name'), @@ -123,7 +131,7 @@ public function schema(): Schema bool_schema('is_file'), bool_schema('is_dir'), str_schema('extension', nullable: true), - ); + )); } public function withSchema(Schema $schema): static diff --git a/src/core/etl/src/Flow/ETL/Extractor/LimitPushDown.php b/src/core/etl/src/Flow/ETL/Extractor/LimitPushDown.php deleted file mode 100644 index 34ef964c41..0000000000 --- a/src/core/etl/src/Flow/ETL/Extractor/LimitPushDown.php +++ /dev/null @@ -1,24 +0,0 @@ -partitionNames($partitionColumns, $path), + new PartitionTypes(), + false, + ); + } +} diff --git a/src/core/etl/src/Flow/ETL/Extractor/MemoryExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/MemoryExtractor.php index 258c57514c..51cf095249 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/MemoryExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/MemoryExtractor.php @@ -40,7 +40,7 @@ public function isRepeatable(): bool /** * @return Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { $batchSize = $this->batchSize(); $schema = $this->schema(); diff --git a/src/core/etl/src/Flow/ETL/Extractor/OverridingExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/OverridingExtractor.php index 50ed90d80d..bf511a518c 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/OverridingExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/OverridingExtractor.php @@ -7,10 +7,10 @@ use Flow\ETL\Extractor; /** - * Extractors implementing OverridingExtractor interface overrides one or more extractors. - * This interface is required by Execution Plan / Optimizer to fully understand execution plan. + * A wrapper exposes the extractors it reads so Repeatability can answer for it. The planner does not + * descend through a wrapper: a wrapped source receives no pushed limit and no path filter. * - * Examples: ChainLoader + * Examples: ChainExtractor, BatchExtractor */ interface OverridingExtractor { diff --git a/src/core/etl/src/Flow/ETL/Extractor/PathFiltering.php b/src/core/etl/src/Flow/ETL/Extractor/PathFiltering.php index 22816ec58f..23e13d22a5 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/PathFiltering.php +++ b/src/core/etl/src/Flow/ETL/Extractor/PathFiltering.php @@ -6,8 +6,6 @@ use Flow\ETL\Schema; use Flow\Filesystem\Path; -use Flow\Filesystem\Path\Filter; -use Flow\Filesystem\Path\Filter\Filters; use Flow\Filesystem\Path\Filter\OnlyFiles; use Generator; @@ -20,12 +18,8 @@ trait PathFiltering private string $derivedFrom = ''; - private ?Filter $filter = null; - /** - * Which partition columns a read discovers is a function of the path and this filter, so the - * listing is cached next to the filter that invalidates it: one listing per extractor instance, - * however often schema() is asked. + * One listing per extractor instance, however often schema() is asked. * * @var null|array */ @@ -65,38 +59,11 @@ private function derivedSchema(Generator $files, bool $unionByName): Schema return $this->derivedSchema = $schema; } - public function filter(): Filter - { - return $this->filter ?? new OnlyFiles(); - } - /** * @return array */ public function partitionNames(PartitionColumns $partitionColumns, Path $path): array { - return $this->partitionNames ??= $partitionColumns->names($path, $this->filter()); - } - - public function withPathFilter(Filter $filter): static - { - $this->partitionNames = null; - $this->derivedSchema = null; - - if ($this->filter === null) { - $this->filter = $filter; - - return $this; - } - - if ($this->filter instanceof Filters) { - $this->filter = $this->filter->add($filter); - - return $this; - } - - $this->filter = new Filters($this->filter, $filter); - - return $this; + return $this->partitionNames ??= $partitionColumns->names($path, new OnlyFiles()); } } diff --git a/src/core/etl/src/Flow/ETL/Extractor/PathPartitionsExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/PathPartitionsExtractor.php index b38dfd5e17..a655bdc357 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/PathPartitionsExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/PathPartitionsExtractor.php @@ -13,6 +13,8 @@ use Flow\Filesystem\Local\NativeLocalFilesystem; use Flow\Filesystem\Partition; use Flow\Filesystem\Path; +use Flow\Filesystem\Path\Filter; +use Flow\Filesystem\Path\Filter\OnlyFiles; use Generator; use function array_map; @@ -27,18 +29,12 @@ use function Flow\Types\DSL\type_string; use function sprintf; -final class PathPartitionsExtractor implements - BatchableExtractor, - Extractor, - FileExtractor, - LimitPushDown, - RewindableExtractor +final class PathPartitionsExtractor implements BatchableExtractor, Extractor, FileExtractor, RewindableExtractor { private ?Schema $schema = null; use Batches; - use PathFiltering; - use PushesLimit; + use ListingPartitions; private readonly Filesystem $filesystem; @@ -67,20 +63,22 @@ public function isRepeatable(): bool /** * @return Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null, Filter $pathFilter = new OnlyFiles()): Generator { $batchSize = $this->batchSize(); + $fileColumns = $this->fileColumns($this->filesystem, $this->path); $schema = $this->schema(); $buffer = []; $yielded = 0; - foreach ((new FileListing($this->filesystem))->list($this->path, $this->filter()) as $fileStatus) { - $buffer[] = [ + foreach ((new FileListing($this->filesystem))->list($this->path, $pathFilter) as $fileStatus) { + $constants = $fileColumns->forFile(new SourceFile($fileStatus->path), $schema); + $buffer[] = $constants->fill([ 'path' => $fileStatus->path->uri(), 'partitions' => array_merge(...array_values(array_map(static fn(Partition $p) => [ $p->name => $p->value, ], $fileStatus->path->partitions()->toArray()))), - ]; + ]); if (count($buffer) < $batchSize) { continue; @@ -96,8 +94,6 @@ public function extract(FlowContext $context): Generator $buffer = []; - $limit = $this->pushedLimit(); - if ($limit !== null && $yielded >= $limit) { return; } @@ -108,6 +104,11 @@ public function extract(FlowContext $context): Generator } } + public function partitionSchema(): Schema + { + return $this->fileColumns($this->filesystem, $this->path)->partitions($this->schema ?? new Schema()); + } + public function source(): Path { return $this->path; @@ -115,11 +116,16 @@ public function source(): Path public function schema(): Schema { + $fileColumns = $this->fileColumns($this->filesystem, $this->path); + if ($this->schema !== null) { - return $this->schema; + return $fileColumns->declare($this->schema); } - return schema(str_schema('path'), map_schema('partitions', type_map(type_string(), type_string()))); + return $fileColumns->declare(schema( + str_schema('path'), + map_schema('partitions', type_map(type_string(), type_string())), + )); } public function withSchema(Schema $schema): static diff --git a/src/core/etl/src/Flow/ETL/Extractor/PushesLimit.php b/src/core/etl/src/Flow/ETL/Extractor/PushesLimit.php deleted file mode 100644 index c8f0acebc9..0000000000 --- a/src/core/etl/src/Flow/ETL/Extractor/PushesLimit.php +++ /dev/null @@ -1,28 +0,0 @@ -pushedLimit = $this->pushedLimit === null ? $limit : min($this->pushedLimit, $limit); - } - - public function pushedLimit(): ?int - { - return $this->pushedLimit; - } -} diff --git a/src/core/etl/src/Flow/ETL/Extractor/Repeatability.php b/src/core/etl/src/Flow/ETL/Extractor/Repeatability.php index 78e9f5db0a..baadf23de2 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/Repeatability.php +++ b/src/core/etl/src/Flow/ETL/Extractor/Repeatability.php @@ -5,6 +5,13 @@ namespace Flow\ETL\Extractor; use Flow\ETL\Extractor; +use Flow\ETL\Plan\LogicalPlan; +use Flow\ETL\Plan\Node; +use Flow\ETL\Plan\Node\Read; +use SplObjectStorage; + +use function array_pop; +use function array_push; final readonly class Repeatability { @@ -20,4 +27,29 @@ public function of(Extractor $extractor): bool return $extractor instanceof RewindableExtractor && $extractor->isRepeatable(); } + + public function ofPlan(LogicalPlan $plan): bool + { + /** @var SplObjectStorage $seen */ + $seen = new SplObjectStorage(); + $stack = [$plan->root]; + + while ($stack !== []) { + $node = array_pop($stack); + + if ($seen->offsetExists($node)) { + continue; + } + + $seen[$node] = null; + + if ($node instanceof Read && !$this->of($node->extractor())) { + return false; + } + + array_push($stack, ...$node->children()); + } + + return true; + } } diff --git a/src/core/etl/src/Flow/ETL/Extractor/RowsExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/RowsExtractor.php index 7c4efddd34..1d83eef516 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/RowsExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/RowsExtractor.php @@ -32,7 +32,7 @@ public function isRepeatable(): bool /** * @return Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { $schema = $this->schema(); diff --git a/src/core/etl/src/Flow/ETL/Extractor/SequenceExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/SequenceExtractor.php index c51daceeb1..39985cb7d1 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/SequenceExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/SequenceExtractor.php @@ -42,7 +42,7 @@ public function isRepeatable(): bool /** * @return Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { $batchSize = $this->batchSize(); $schema = $this->schema(); diff --git a/src/core/etl/src/Flow/ETL/Filesystem/ScalarFunctionFilter.php b/src/core/etl/src/Flow/ETL/Filesystem/ScalarFunctionFilter.php index 4d1ce131d6..6288a731be 100644 --- a/src/core/etl/src/Flow/ETL/Filesystem/ScalarFunctionFilter.php +++ b/src/core/etl/src/Flow/ETL/Filesystem/ScalarFunctionFilter.php @@ -26,7 +26,7 @@ public function __construct( private FlowContext $context, ) { // The comparability gate belongs here, where the function and the schema it binds against - // are both in hand - a filter reaching withPathFilter() any other way is gated too. + // are both in hand - a filter reaching a Read any other way is gated too. // resolved() guards it: files() and from_path_partitions() declare no partition columns, so // their reference never resolves and returns() would throw instead of answering. $this->resolved = (new ReferenceResolver())->resolve($function, $partitions); @@ -41,8 +41,8 @@ public function accept(FileStatus $status): bool $values = []; foreach ($status->path->partitions()->toArray() as $partition) { - // findDefinition(), not get(): files() and from_path_partitions() declare no partition - // columns and filterPartitions() works on both, while Schema::get() would throw. + // findDefinition(), not get(): a source that declares no partition columns hands an empty schema + // here, and Schema::get() would throw. $definition = $this->partitions->findDefinition($partition->name); if ($definition === null || $definition->matches($partition->value)) { diff --git a/src/core/etl/src/Flow/ETL/Flow.php b/src/core/etl/src/Flow/ETL/Flow.php index c7da9f8926..21a15e32fd 100644 --- a/src/core/etl/src/Flow/ETL/Flow.php +++ b/src/core/etl/src/Flow/ETL/Flow.php @@ -27,7 +27,7 @@ public static function setUp(ConfigBuilder|Config $config): self public function extract(Extractor $extractor): DataFrame { - return new DataFrame(new Pipeline($extractor), $this->config); + return new DataFrame($extractor, $this->config); } public function from(Extractor $extractor): DataFrame @@ -37,7 +37,7 @@ public function from(Extractor $extractor): DataFrame public function process(Rows ...$rows): DataFrame { - return new DataFrame(new Pipeline(new RowsExtractor(...$rows)), $this->config); + return new DataFrame(new RowsExtractor(...$rows), $this->config); } /** diff --git a/src/core/etl/src/Flow/ETL/FlowContext.php b/src/core/etl/src/Flow/ETL/FlowContext.php index fb8549657f..9a81873b84 100644 --- a/src/core/etl/src/Flow/ETL/FlowContext.php +++ b/src/core/etl/src/Flow/ETL/FlowContext.php @@ -55,6 +55,14 @@ public function setErrorHandler(ErrorHandler $handler): self return $this; } + public function withErrorHandler(ErrorHandler $handler): self + { + $new = new self($this->config); + $new->telemetryContext = $this->telemetry(); + + return $new->setErrorHandler($handler); + } + public function telemetry(): TelemetryContext { return $this->telemetryContext ??= new TelemetryContext( diff --git a/src/core/etl/src/Flow/ETL/Function/CallUserFunc.php b/src/core/etl/src/Flow/ETL/Function/CallUserFunc.php index b43cbc478a..3404632072 100644 --- a/src/core/etl/src/Flow/ETL/Function/CallUserFunc.php +++ b/src/core/etl/src/Flow/ETL/Function/CallUserFunc.php @@ -50,6 +50,14 @@ public function children(): array return [$this->callable, ...array_values($this->parameters)]; } + /** + * A user callable may keep state or read the outside world, so it is never assumed to answer the same twice. + */ + public function deterministic(): bool + { + return false; + } + /** * The callable leads the child list; string keys in the parameter bag become PHP named * arguments at call time, so the key list is carried as a field and restored here diff --git a/src/core/etl/src/Flow/ETL/Function/FunctionTree.php b/src/core/etl/src/Flow/ETL/Function/FunctionTree.php index 0c1b7b0337..e6d73c9c7f 100644 --- a/src/core/etl/src/Flow/ETL/Function/FunctionTree.php +++ b/src/core/etl/src/Flow/ETL/Function/FunctionTree.php @@ -19,6 +19,13 @@ public function children(): array; */ public function resolved(): bool; + /** + * True when this node and every node in children() produce the same value for the same input row. + * False for a generator (now(), uuid, a random string): a caller that evaluates the tree once per FILE + * or per partition instead of once per row must refuse a non-deterministic one. + */ + public function deterministic(): bool; + /** * A copy of this node with $children in place of children(): same count, same order, same * per-element narrowing. Never mutates $this. diff --git a/src/core/etl/src/Flow/ETL/Function/Now.php b/src/core/etl/src/Flow/ETL/Function/Now.php index 4aef89b6c8..77a19047e4 100644 --- a/src/core/etl/src/Flow/ETL/Function/Now.php +++ b/src/core/etl/src/Flow/ETL/Function/Now.php @@ -33,6 +33,11 @@ public function children(): array return [$this->timeZone]; } + public function deterministic(): bool + { + return false; + } + /** * @param list $children */ diff --git a/src/core/etl/src/Flow/ETL/Function/RandomString.php b/src/core/etl/src/Flow/ETL/Function/RandomString.php index 2716acbade..5bc0953d62 100644 --- a/src/core/etl/src/Flow/ETL/Function/RandomString.php +++ b/src/core/etl/src/Flow/ETL/Function/RandomString.php @@ -35,6 +35,11 @@ public function children(): array return [$this->length]; } + public function deterministic(): bool + { + return false; + } + /** * @param list $children */ diff --git a/src/core/etl/src/Flow/ETL/Function/ReferenceRename.php b/src/core/etl/src/Flow/ETL/Function/ReferenceRename.php new file mode 100644 index 0000000000..a740ac9eac --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Function/ReferenceRename.php @@ -0,0 +1,50 @@ +to() === $this->from) { + if (!$tree instanceof UnresolvedReference) { + return null; + } + + $renamed = new UnresolvedReference($this->to); + + return $tree->hasAlias() ? $renamed->as($tree->name()) : $renamed; + } + + $children = []; + + foreach ($tree->children() as $child) { + $renamed = $this->in($child); + + if ($renamed === null) { + return null; + } + + $children[] = $renamed; + } + + return $children === $tree->children() ? $tree : $tree->withChildren($children); + } +} diff --git a/src/core/etl/src/Flow/ETL/Function/ReferencedColumns.php b/src/core/etl/src/Flow/ETL/Function/ReferencedColumns.php new file mode 100644 index 0000000000..b0f6265fe3 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Function/ReferencedColumns.php @@ -0,0 +1,32 @@ +add($tree->to()); + } + + foreach ($tree->children() as $child) { + foreach ($this->in($child)->all() as $ref) { + $refs = $refs->add($ref->to()); + } + } + + return $refs; + } +} diff --git a/src/core/etl/src/Flow/ETL/Function/ResolvesFromChildren.php b/src/core/etl/src/Flow/ETL/Function/ResolvesFromChildren.php index 5eec25270a..2a6fd58759 100644 --- a/src/core/etl/src/Flow/ETL/Function/ResolvesFromChildren.php +++ b/src/core/etl/src/Flow/ETL/Function/ResolvesFromChildren.php @@ -19,4 +19,15 @@ public function resolved(): bool return true; } + + public function deterministic(): bool + { + foreach ($this->children() as $child) { + if (!$child->deterministic()) { + return false; + } + } + + return true; + } } diff --git a/src/core/etl/src/Flow/ETL/Function/ToDateTime.php b/src/core/etl/src/Flow/ETL/Function/ToDateTime.php index c8ffde68eb..6e5e4bbbc8 100644 --- a/src/core/etl/src/Flow/ETL/Function/ToDateTime.php +++ b/src/core/etl/src/Flow/ETL/Function/ToDateTime.php @@ -9,6 +9,7 @@ use DateTimeZone; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; +use Flow\ETL\Function\ToDateTime\PatternCoverage; use Flow\ETL\Row; use Flow\Types\Type; @@ -28,6 +29,11 @@ final class ToDateTime implements ScalarFunction private readonly ScalarFunction $format; private readonly ScalarFunction $timeZone; + /** + * The format as given when it was a plain string; kept across a rebuild that leaves the format child as it is. + */ + private ?string $pattern; + public function __construct( mixed $value, ScalarFunction|string $format, @@ -36,6 +42,7 @@ public function __construct( $this->value = $value instanceof ScalarFunction ? $value : lit($value); $this->format = $format instanceof ScalarFunction ? $format : lit($format); $this->timeZone = $timeZone instanceof ScalarFunction ? $timeZone : lit($timeZone); + $this->pattern = is_string($format) ? $format : null; } /** @@ -52,7 +59,31 @@ public function children(): array public function withChildren(array $children): static { /** @var list $children */ - return new self($children[0], $children[1], $children[2]); + $rebuilt = new self($children[0], $children[1], $children[2]); + + if ($children[1] === $this->format) { + $rebuilt->pattern = $this->pattern; + } + + return $rebuilt; + } + + /** + * createFromFormat() fills what the format does not parse from the clock; a format only known at run time may. + */ + public function deterministic(): bool + { + if ($this->pattern === null || (new PatternCoverage($this->pattern))->fillsFromClock()) { + return false; + } + + foreach ($this->children() as $child) { + if (!$child->deterministic()) { + return false; + } + } + + return true; } /** diff --git a/src/core/etl/src/Flow/ETL/Function/ToDateTime/PatternCoverage.php b/src/core/etl/src/Flow/ETL/Function/ToDateTime/PatternCoverage.php new file mode 100644 index 0000000000..0af91ad3f0 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Function/ToDateTime/PatternCoverage.php @@ -0,0 +1,56 @@ +pattern); $i < $length; $i++) { + if ($this->pattern[$i] === '\\') { + $i++; + + continue; + } + + $parsed .= $this->pattern[$i]; + } + + if ($this->any($parsed, '!|U')) { + return false; + } + + $date = + $this->any($parsed, 'YyXxo') + && ($this->any($parsed, 'z') || $this->any($parsed, 'mnMF') && $this->any($parsed, 'dj')); + + return !$date || !$this->any($parsed, 'HGhgisvu'); + } + + public function any(string $parsed, string $characters): bool + { + for ($i = 0, $length = strlen($characters); $i < $length; $i++) { + if (str_contains($parsed, $characters[$i])) { + return true; + } + } + + return false; + } +} diff --git a/src/core/etl/src/Flow/ETL/Function/Ulid.php b/src/core/etl/src/Flow/ETL/Function/Ulid.php index 9e50a2e47d..d661a56a43 100644 --- a/src/core/etl/src/Flow/ETL/Function/Ulid.php +++ b/src/core/etl/src/Flow/ETL/Function/Ulid.php @@ -44,6 +44,12 @@ public function children(): array return $this->ref === null ? [] : [$this->ref]; } + public function deterministic(): bool + { + // ulid() generates, ulid($ref) only converts $ref + return $this->ref !== null && $this->ref->deterministic(); + } + /** * @param list $children */ diff --git a/src/core/etl/src/Flow/ETL/Function/Uuid.php b/src/core/etl/src/Flow/ETL/Function/Uuid.php index 52be4aa55c..9330d999c8 100644 --- a/src/core/etl/src/Flow/ETL/Function/Uuid.php +++ b/src/core/etl/src/Flow/ETL/Function/Uuid.php @@ -53,6 +53,12 @@ public function children(): array return $this->value === null ? [] : [$this->value]; } + public function deterministic(): bool + { + // both generate: uuid7 over the same timestamp still draws a new random tail + return false; + } + /** * @param list $children */ diff --git a/src/core/etl/src/Flow/ETL/GroupBy.php b/src/core/etl/src/Flow/ETL/GroupBy.php index d443742cb9..9fa6ab4d08 100644 --- a/src/core/etl/src/Flow/ETL/GroupBy.php +++ b/src/core/etl/src/Flow/ETL/GroupBy.php @@ -67,6 +67,14 @@ public function aggregatedRow(GroupKey $key, Aggregators $aggregators, Schema $o return new Row($values); } + /** + * The columns rows are grouped by. + */ + public function refs(): References + { + return $this->refs; + } + public function aggregations(): Aggregators { return $this->aggregations; diff --git a/src/core/etl/src/Flow/ETL/GroupBy/DiscoveredPivotValues.php b/src/core/etl/src/Flow/ETL/GroupBy/DiscoveredPivotValues.php index d159979606..995d9857c1 100644 --- a/src/core/etl/src/Flow/ETL/GroupBy/DiscoveredPivotValues.php +++ b/src/core/etl/src/Flow/ETL/GroupBy/DiscoveredPivotValues.php @@ -8,6 +8,7 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\SchemaNotDerivableException; use Flow\ETL\Extractor\Repeatability; +use Flow\ETL\Plan\Trigger; use Flow\ETL\Row\Reference; use function array_values; @@ -31,8 +32,8 @@ public function __construct( public function resolve(DataFrame $source, Reference $pivot): DeclaredPivotValues { - if (!(new Repeatability())->of($source->extractor())) { - throw SchemaNotDerivableException::nonRewindable($source->extractor()::class); + if (!(new Repeatability())->ofPlan($source->explain(Trigger::rows)->logical)) { + throw SchemaNotDerivableException::nonRewindable(); } $distinct = []; diff --git a/src/core/etl/src/Flow/ETL/GroupBy/GroupBySteps.php b/src/core/etl/src/Flow/ETL/GroupBy/GroupBySteps.php index 9de601bdd4..8913b23e28 100644 --- a/src/core/etl/src/Flow/ETL/GroupBy/GroupBySteps.php +++ b/src/core/etl/src/Flow/ETL/GroupBy/GroupBySteps.php @@ -19,9 +19,6 @@ use function array_values; -/** - * @internal - */ final readonly class GroupBySteps { /** diff --git a/src/core/etl/src/Flow/ETL/Join/JoinSteps.php b/src/core/etl/src/Flow/ETL/Join/JoinSteps.php index d58a356656..8ab7bf631c 100644 --- a/src/core/etl/src/Flow/ETL/Join/JoinSteps.php +++ b/src/core/etl/src/Flow/ETL/Join/JoinSteps.php @@ -7,13 +7,10 @@ use Flow\ETL\Bucketing\Buckets; use Flow\ETL\Config; use Flow\ETL\Config\Join\JoinAlgorithmBuilder; -use Flow\ETL\DataFrame; +use Flow\ETL\Executor\PhysicalPlan; use Flow\ETL\Processor; use Flow\ETL\Processor\HashJoinProcessor; -/** - * @internal - */ final readonly class JoinSteps { /** @@ -23,7 +20,7 @@ * @return list */ public static function of( - DataFrame $right, + PhysicalPlan $right, Expression $on, Join $type, Config $config, @@ -34,6 +31,7 @@ public static function of( return [ new HashJoinProcessor( $right, + $config->executor(), $on, $type, new Buckets($join->bucketing->storage), diff --git a/src/core/etl/src/Flow/ETL/Loader/BranchingLoader.php b/src/core/etl/src/Flow/ETL/Loader/BranchingLoader.php deleted file mode 100644 index e3100d3f0d..0000000000 --- a/src/core/etl/src/Flow/ETL/Loader/BranchingLoader.php +++ /dev/null @@ -1,143 +0,0 @@ -stream !== null && $this->stream->drivenBy($context)) { - $this->stream->drain(); - } - } catch (Throwable $failure) { - // Same ruling as TransformerLoader::closure(): a drain failure never reached load(), so the - // ErrorHandler rules here; declining means the run continues and the loader must still close. - if ( - $context->errorHandler()->onLoading(new LoadingError($failure, $this, new Rows(new Schema()))) - === LoadingAction::propagate - ) { - throw $failure; - } - } - - if ($this->loader instanceof Closure) { - $this->loader->closure($context); - } - } finally { - $this->stream = null; - $this->limitReached = false; - $this->runContext = null; - } - } - - public function discard(FlowContext $context): void - { - // The stream is never drained here - draining would commit the dead run's buffered rows. The wrapped loader - // is discarded by the pipeline, which walks the whole loader tree. - $this->stream = null; - $this->limitReached = false; - $this->runContext = null; - } - - public function load(Rows $rows, FlowContext $context): void - { - $context->telemetry()->loadingStarted($this); - - try { - // Same ruling split as TransformerLoader::load(): drivenBy() decides rebuild, this field decides the - // limit-dedup reset - a mid-run stream rebuild must not re-arm limit reporting. - if ($this->runContext !== $context) { - $this->runContext = $context; - $this->limitReached = false; - } - - $branchRows = (new ScalarFunctionFilterTransformer($this->condition))->transform($rows, $context); - - if ($this->transformation === null) { - $this->loader->load($branchRows, $context); - } else { - if ($this->stream === null || !$this->stream->drivenBy($context)) { - $this->stream = new TransformationStream( - $this->transformation, - $branchRows->schema(), - $this->loader, - $context, - ); - } - - try { - $this->stream->feed($branchRows); - } catch (Throwable $failure) { - $this->stream = null; - - throw $failure; - } - } - - $context->telemetry()->loadingCompleted($this, [TelemetryAttributes::ATTR_LOADING_ROWS => $rows->count()]); - } catch (LimitReachedException $e) { - if (!$this->limitReached) { - $this->limitReached = true; - $context->telemetry()->limitReached(['limit' => $e->limit]); - } - - $context->telemetry()->loadingCompleted($this, [TelemetryAttributes::ATTR_LOADING_ROWS => 0]); - } catch (Throwable $e) { - $context->telemetry()->loadingFailed($this, $e); - - throw $e; - } - } - - public function loaders(): array - { - return [ - $this->loader, - ]; - } - - public function replaySafe(): bool - { - // No transformation: a fresh stateless ScalarFunctionFilterTransformer per call - replay-safe. - return $this->transformation === null; - } - - public function withTransformation(Transformation $transformation): self - { - $this->transformation = $transformation; - - return $this; - } -} diff --git a/src/core/etl/src/Flow/ETL/Loader/LoaderTree.php b/src/core/etl/src/Flow/ETL/Loader/LoaderTree.php deleted file mode 100644 index 3b96eac5c9..0000000000 --- a/src/core/etl/src/Flow/ETL/Loader/LoaderTree.php +++ /dev/null @@ -1,46 +0,0 @@ - - */ - public function flatten(Loader $root): array - { - /** @var SplObjectStorage $visited */ - $visited = new SplObjectStorage(); - $queue = [$root]; - $flattened = []; - - while ($queue !== []) { - $loader = array_shift($queue); - - if ($visited->offsetExists($loader)) { - continue; - } - - $visited->offsetSet($loader); - $flattened[] = $loader; - - if ($loader instanceof OverridingLoader) { - foreach ($loader->loaders() as $overridden) { - $queue[] = $overridden; - } - } - } - - return $flattened; - } -} diff --git a/src/core/etl/src/Flow/ETL/Loader/OverridingLoader.php b/src/core/etl/src/Flow/ETL/Loader/OverridingLoader.php deleted file mode 100644 index 11f664e55f..0000000000 --- a/src/core/etl/src/Flow/ETL/Loader/OverridingLoader.php +++ /dev/null @@ -1,21 +0,0 @@ - - */ - public function loaders(): array; -} diff --git a/src/core/etl/src/Flow/ETL/Loader/ReplayAware.php b/src/core/etl/src/Flow/ETL/Loader/ReplayAware.php deleted file mode 100644 index 15ae2041ac..0000000000 --- a/src/core/etl/src/Flow/ETL/Loader/ReplayAware.php +++ /dev/null @@ -1,17 +0,0 @@ -loaderTree = new LoaderTree(); - } - - public function closure(FlowContext $context): void - { - if ($this->loader instanceof Closure) { - $this->loader->closure($context); - } - } - - public function load(Rows $rows, FlowContext $context): void - { - $context->telemetry()->loadingStarted($this); - - try { - foreach ($this->loaderTree->flatten($this->loader) as $wrapped) { - if ($wrapped instanceof ReplayAware && !$wrapped->replaySafe()) { - throw new InvalidLogicException( - 'RetryLoader cannot wrap this loader: it holds state across load() calls that cannot be ' - . 'rewound, so Flow cannot tell whether re-offering a failed batch is safe. Retry the ' - . 'destination instead: to_transformation($transformation, write_with_retries($loader)) or ' - . 'to_branch($condition, write_with_retries($loader))->withTransformation($transformation).', - ); - } - } - - $attemptNumber = 0; - $retriesRecord = new RetriesRecord(); - - while (true) { - $attemptNumber++; - - try { - $this->loader->load($rows, $context); - - $context->telemetry()->loadingCompleted($this, [ - TelemetryAttributes::ATTR_LOADING_ROWS => $rows->count(), - ]); - - return; - } catch (Throwable $exception) { - $retriesRecord->add(FailedRetry::create($context->config->clock(), $exception, $attemptNumber)); - - if (!$this->retryStrategy->shouldRetry($exception, $attemptNumber)) { - throw new FailedRetryException($retriesRecord); - } - - $this->sleep->for($this->delayFactory->delay($attemptNumber)); - } - } - } catch (Throwable $e) { - $context->telemetry()->loadingFailed($this, $e); - - throw $e; - } - } - - public function loaders(): array - { - return [ - $this->loader, - ]; - } -} diff --git a/src/core/etl/src/Flow/ETL/Loader/TransformerLoader.php b/src/core/etl/src/Flow/ETL/Loader/TransformerLoader.php deleted file mode 100644 index b5590c93a8..0000000000 --- a/src/core/etl/src/Flow/ETL/Loader/TransformerLoader.php +++ /dev/null @@ -1,132 +0,0 @@ -stream !== null && $this->stream->drivenBy($context)) { - $this->stream->drain(); - } - } catch (Throwable $failure) { - if ( - $context->errorHandler()->onLoading(new LoadingError($failure, $this, new Rows(new Schema()))) - === LoadingAction::propagate - ) { - throw $failure; - } - } - - if ($this->loader instanceof Closure) { - $this->loader->closure($context); - } - } finally { - $this->stream = null; - $this->limitReached = false; - $this->runContext = null; - } - } - - public function discard(FlowContext $context): void - { - // The stream is never drained here - draining would commit the dead run's buffered rows. The wrapped loader - // is discarded by the pipeline, which walks the whole loader tree. - $this->stream = null; - $this->limitReached = false; - $this->runContext = null; - } - - public function load(Rows $rows, FlowContext $context): void - { - $context->telemetry()->loadingStarted($this); - - try { - if ($this->runContext !== $context) { - $this->runContext = $context; - $this->limitReached = false; - } - - $transformer = $this->transformer; - - if ($transformer instanceof Transformer) { - try { - // @mago-ignore analysis:invalid-argument,too-many-arguments,possibly-invalid-argument - $transformed = $transformer->transform($rows, $context); - } catch (LimitReachedException $limit) { - // the batch that fills the limit rides the exception, and still belongs in the sink - if ($limit->rows !== null && $limit->rows->count()) { - $this->loader->load($limit->rows, $context); - } - - throw $limit; - } - - $this->loader->load($transformed, $context); - } else { - if ($this->stream === null || !$this->stream->drivenBy($context)) { - $this->stream = new TransformationStream($transformer, $rows->schema(), $this->loader, $context); - } - - try { - $this->stream->feed($rows); - } catch (Throwable $failure) { - $this->stream = null; - - throw $failure; - } - } - - $context->telemetry()->loadingCompleted($this, [TelemetryAttributes::ATTR_LOADING_ROWS => $rows->count()]); - } catch (LimitReachedException $e) { - if (!$this->limitReached) { - $this->limitReached = true; - $context->telemetry()->limitReached(['limit' => $e->limit]); - } - - $context->telemetry()->loadingCompleted($this, [TelemetryAttributes::ATTR_LOADING_ROWS => 0]); - } catch (Throwable $e) { - $context->telemetry()->loadingFailed($this, $e); - - throw $e; - } - } - - public function loaders(): array - { - return [$this->loader]; - } - - public function replaySafe(): bool - { - return false; - } -} diff --git a/src/core/etl/src/Flow/ETL/Optimizer.php b/src/core/etl/src/Flow/ETL/Optimizer.php new file mode 100644 index 0000000000..6095cde1d0 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Optimizer.php @@ -0,0 +1,116 @@ + + */ + private array $rules; + + public function __construct(Rule ...$rules) + { + $this->rules = array_values($rules); + } + + public static function default(): self + { + return new self( + new CombineLimits(), + new CombineSortAndLimit(), + new PushLimitIntoSource(), + new PushFilterIntoSource(), + ); + } + + /** + * Rewrites every join's right side as a plan of its own, then $plan with every rule, in order. + */ + public function optimize(LogicalPlan $plan, FlowContext $context): LogicalPlan + { + $plan = $plan->transformUp(new JoinSides($this, $context)); + + foreach ($this->rules as $rule) { + $plan = $rule->apply($plan, $context); + } + + return $plan; + } + + /** + * @return list + */ + public function rules(): array + { + return $this->rules; + } + + /** + * This optimizer's rules followed by $rules, run after them in the given order. + * + * @throws InvalidArgumentException when a rule of the same class is already registered + */ + public function with(Rule ...$rules): self + { + $registered = []; + + foreach ($this->rules as $rule) { + $registered[] = $rule::class; + } + + foreach ($rules as $rule) { + if (in_array($rule::class, $registered, true)) { + throw new InvalidArgumentException(sprintf('%s is already a registered optimizer rule', $rule::class)); + } + + $registered[] = $rule::class; + } + + return new self(...$this->rules, ...$rules); + } + + /** + * This optimizer's rules, minus the named ones - so a caller drops one rule without freezing the list + * and silently missing every rule added later. + * + * @param class-string ...$rules + * + * @throws InvalidArgumentException when a name is not a registered rule + */ + public function without(string ...$rules): self + { + $kept = []; + $registered = []; + + foreach ($this->rules as $rule) { + $registered[] = $rule::class; + + if (!in_array($rule::class, $rules, true)) { + $kept[] = $rule; + } + } + + foreach (array_diff($rules, $registered) as $name) { + throw new InvalidArgumentException(sprintf('%s is not a registered optimizer rule', $name)); + } + + return new self(...$kept); + } +} diff --git a/src/core/etl/src/Flow/ETL/Optimizer/FilterWalk.php b/src/core/etl/src/Flow/ETL/Optimizer/FilterWalk.php new file mode 100644 index 0000000000..098733d12f --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Optimizer/FilterWalk.php @@ -0,0 +1,78 @@ +children()[0] ?? null) { + if ($node === null) { + return false; + } + } + } + + return true; + } + + /** + * $predicate as $leaf sees it, or null when it may not be evaluated there instead of above $filter. + * Another Filter is TRANSPARENT here: it only removes rows, and the pushed Filter node stays, so pruning a + * file drops rows that filter would have dropped anyway. Limit/Offset/Until/Distinct/Discard are not: they + * make WHICH rows arrive depend on what the source read. + * + * A node that redefines a column the predicate reads blocks it, unless the column is a plain alias of a + * column below (Rename, a WithColumn of a bare reference): the predicate is rewritten to read that column. + */ + public function predicateAtLeaf(Node\Filter $filter, Read $leaf, ScalarFunction $predicate): ?ScalarFunction + { + $columns = new ReferencedColumns(); + + for ($node = $filter->children()[0]; $node !== $leaf; $node = $node->children()[0]) { + if ($node->children() === [] || $node->transparency() !== Transparency::transparent) { + return null; + } + + if ($node->rowCount() === RowCount::reducing && !$node instanceof Node\Filter) { + return null; + } + + $redefined = $node->redefines(); + + foreach ($columns->in($predicate)->names() as $name) { + if (!$redefined->defines($name)) { + continue; + } + + $below = $redefined->aliasOf($name); + $renamed = $below === null ? null : (new ReferenceRename($name, $below))->in($predicate); + + if (!$renamed instanceof ScalarFunction) { + return null; + } + + $predicate = $renamed; + } + } + + return $predicate; + } +} diff --git a/src/core/etl/src/Flow/ETL/Optimizer/JoinSides.php b/src/core/etl/src/Flow/ETL/Optimizer/JoinSides.php new file mode 100644 index 0000000000..2eea368fbb --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Optimizer/JoinSides.php @@ -0,0 +1,35 @@ +withChildren([ + $node->children()[0], + $this->optimizer->optimize(new LogicalPlan($node->right()), $this->context)->root, + ]); + } +} diff --git a/src/core/etl/src/Flow/ETL/Optimizer/LimitWalk.php b/src/core/etl/src/Flow/ETL/Optimizer/LimitWalk.php new file mode 100644 index 0000000000..a33f49f789 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Optimizer/LimitWalk.php @@ -0,0 +1,50 @@ +limit(5)->sort()->limit(3) still yields 5. An Offset grows the limit by the rows it skips, so + * read->offset(100)->limit(10) yields 110. + * + * @return null|int null when no limit survives, and when this chain does not reach $leaf at all + */ + public function of(Node $from, Read $leaf): ?int + { + $limit = null; + + for ($node = $from; $node !== $leaf; $node = $node->children()[0]) { + if ($node instanceof Limit) { + $limit = $limit === null ? $node->limit : min($limit, $node->limit); + } elseif ($node instanceof Offset) { + // the source must read the skipped rows too; the Offset and Limit nodes above still cut them + $limit = $limit === null ? null : $limit + $node->offset; + } elseif ( + $node->rowCount() !== RowCount::preserving + || $node->transparency() !== Transparency::transparent + ) { + $limit = null; + } + + if ($node->children() === []) { + return null; + } + } + + return $limit; + } +} diff --git a/src/core/etl/src/Flow/ETL/Optimizer/Rule.php b/src/core/etl/src/Flow/ETL/Optimizer/Rule.php new file mode 100644 index 0000000000..71728d0554 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Optimizer/Rule.php @@ -0,0 +1,19 @@ + Limit(x, min(n, m)). + */ +final readonly class CombineLimits implements Rewrite, Rule +{ + public function apply(LogicalPlan $plan, FlowContext $context): LogicalPlan + { + return $plan->transformUp($this); + } + + public function of(Node $node): Node + { + if (!$node instanceof Limit) { + return $node; + } + + $child = $node->children()[0]; + + return $child instanceof Limit ? new Limit($child->children()[0], min($node->limit, $child->limit)) : $node; + } +} diff --git a/src/core/etl/src/Flow/ETL/Optimizer/Rule/CombineSortAndLimit.php b/src/core/etl/src/Flow/ETL/Optimizer/Rule/CombineSortAndLimit.php new file mode 100644 index 0000000000..63c8530cc3 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Optimizer/Rule/CombineSortAndLimit.php @@ -0,0 +1,25 @@ + TopN(x, n): the sort keeps n rows instead of the whole input. A shared Sort stays for its + * other consumers. An external sort bounds memory by its run size, so a larger n keeps the external sort. + */ +final readonly class CombineSortAndLimit implements Rule +{ + public function apply(LogicalPlan $plan, FlowContext $context): LogicalPlan + { + return $plan->transformUp(new TopNRewrite($context)); + } +} diff --git a/src/core/etl/src/Flow/ETL/Optimizer/Rule/PushFilterIntoSource.php b/src/core/etl/src/Flow/ETL/Optimizer/Rule/PushFilterIntoSource.php new file mode 100644 index 0000000000..945f176528 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Optimizer/Rule/PushFilterIntoSource.php @@ -0,0 +1,76 @@ +source(); + $extractor = $leaf->extractor(); + + if (!$extractor instanceof FileExtractor) { + return $plan; + } + + $partitions = $extractor->partitionSchema(); + + if ($partitions->count() === 0) { + return $plan; + } + + $consumerInputs = $plan->consumerInputs(); + $walk = new FilterWalk(); + $columns = new ReferencedColumns(); + $names = $partitions->references()->names(); + $read = $leaf; + + for ($node = $plan->root; $node->children() !== []; $node = $node->children()[0]) { + if (!$node instanceof Node\Filter || !$walk->reachedByEveryConsumer($node, ...$consumerInputs)) { + continue; + } + + foreach ($node->function instanceof All ? $node->function->children() : [$node->function] as $conjunct) { + if (!$conjunct->deterministic()) { + continue; + } + + $atLeaf = $walk->predicateAtLeaf($node, $leaf, $conjunct); + + if ($atLeaf === null) { + continue; + } + + $refs = $columns->in($atLeaf); + + if ($refs->all() === [] || array_diff($refs->names(), $names) !== []) { + continue; + } + + $read = $read->withPathFilter(new ScalarFunctionFilter($atLeaf, $partitions, $context)); + } + } + + return $read === $leaf ? $plan : $plan->transformUp(new ReplaceLeaf($leaf, $read)); + } +} diff --git a/src/core/etl/src/Flow/ETL/Optimizer/Rule/PushLimitIntoSource.php b/src/core/etl/src/Flow/ETL/Optimizer/Rule/PushLimitIntoSource.php new file mode 100644 index 0000000000..36beb317b9 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Optimizer/Rule/PushLimitIntoSource.php @@ -0,0 +1,39 @@ +source(); + $walk = new LimitWalk(); + $limits = []; + + foreach ($plan->consumerInputs() as $input) { + $limit = $walk->of($input, $leaf); + + if ($limit === null) { + return $plan; + } + + $limits[] = $limit; + } + + return $plan->transformUp(new ReplaceLeaf($leaf, $leaf->withLimit(max($limits)))); + } +} diff --git a/src/core/etl/src/Flow/ETL/Optimizer/TopNRewrite.php b/src/core/etl/src/Flow/ETL/Optimizer/TopNRewrite.php new file mode 100644 index 0000000000..b276930834 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Optimizer/TopNRewrite.php @@ -0,0 +1,45 @@ +children()[0]; + + if (!$sort instanceof Sort) { + return $node; + } + + $config = $this->context->config; + $algorithm = $sort->algorithm?->build($config->cache->localFilesystemCacheDir) ?? $config->sort; + + if ($algorithm instanceof ExternalSortConfig && $node->limit > $algorithm->runSize) { + return $node; + } + + return new TopN($sort->children()[0], $sort->refs, $node->limit); + } +} diff --git a/src/core/etl/src/Flow/ETL/Pipeline.php b/src/core/etl/src/Flow/ETL/Pipeline.php deleted file mode 100644 index 18ad6caf67..0000000000 --- a/src/core/etl/src/Flow/ETL/Pipeline.php +++ /dev/null @@ -1,168 +0,0 @@ -segments = new Segments($extractor); - } - - public function add(Transformer|Loader|Processor $step): self - { - $this->invalidateBind(); - $this->segments->add($step); - - return $this; - } - - /** - * Walk the plan once and memoise the result, refusal included. - * - * @throws InvalidLogicException - * @throws SchemaNotDerivableException - */ - public function bind(): BoundPlan - { - if ($this->bindRefusal !== null) { - throw $this->bindRefusal; - } - - if ($this->bound !== null) { - return $this->bound; - } - - if ($this->binding) { - throw InvalidLogicException::cyclicPlanOnDescribe(); - } - - $this->binding = true; - - try { - return $this->bound = (new PlanBinder())->bind($this->extractor, $this->segments); - } catch (SchemaNotDerivableException $refusal) { - $this->bindRefusal = $refusal; - - throw $refusal; - } finally { - $this->binding = false; - } - } - - public function boundOrNull(): ?BoundPlan - { - try { - return $this->bind(); - } catch (SchemaNotDerivableException) { - return null; - } - } - - /** - * Get the pipeline extractor. - */ - public function extractor(): Extractor - { - return $this->extractor; - } - - /** - * Check if pipeline contains a step of the given class. - * - * @param class-string $class - */ - public function has(string $class): bool - { - return $this->segments->has($class); - } - - /** - * Drop the memo. Call after any mutation of the plan or of its extractor - both change what the - * walk would compute. - */ - public function invalidateBind(): void - { - $this->bound = null; - $this->bindRefusal = null; - } - - /** - * Process the pipeline and yield Rows batches. - * - * @return \Generator - */ - public function process(FlowContext $context): Generator - { - if ($this->running) { - throw InvalidLogicException::cyclicPlanOnRun(); - } - - $this->running = true; - - try { - $generator = $this->extractor->extract($context); - - foreach (($this->boundOrNull()?->segments() ?? $this->segments)->all() as $segment) { - $generator = $segment->execute($generator, $context); - - $processor = $segment->processor(); - - if ($processor !== null) { - $generator = $processor->process($generator, $context); - } - } - - // disarmed across our own yield: while parked we are not advancing, so a second read - // arriving here is another reader of the same plan, not recursion. Only a re-entry during - // the advance is a cycle - every step is pulled from inside this foreach. - foreach ($generator as $rows) { - $this->running = false; - - yield $rows; - - $this->running = true; - } - } finally { - $this->running = false; - } - } - - public function replaceExtractor(Extractor $extractor): void - { - $this->extractor = $extractor; - $this->segments->replaceExtractor($extractor); - $this->invalidateBind(); - } - - /** - * Get the pipeline stages. - */ - public function segments(): Segments - { - return $this->segments; - } -} diff --git a/src/core/etl/src/Flow/ETL/Pipeline/BoundPlan.php b/src/core/etl/src/Flow/ETL/Pipeline/BoundPlan.php deleted file mode 100644 index 9e4192962e..0000000000 --- a/src/core/etl/src/Flow/ETL/Pipeline/BoundPlan.php +++ /dev/null @@ -1,20 +0,0 @@ -segments; - } -} diff --git a/src/core/etl/src/Flow/ETL/Pipeline/Optimizer.php b/src/core/etl/src/Flow/ETL/Pipeline/Optimizer.php deleted file mode 100644 index f3cf5c7346..0000000000 --- a/src/core/etl/src/Flow/ETL/Pipeline/Optimizer.php +++ /dev/null @@ -1,56 +0,0 @@ - - */ - private array $optimizations; - - public function __construct(Optimization ...$optimizations) - { - $this->optimizations = $optimizations; - } - - public function disabled(): self - { - return new self(); - } - - /** - * @return array - */ - public function optimizations(): array - { - return $this->optimizations; - } - - public function optimize(Loader|Transformer $element, Pipeline $pipeline): Pipeline - { - if (!count($this->optimizations)) { - return $pipeline->add($element); - } - - $optimized = false; - - foreach ($this->optimizations as $optimization) { - if ($optimization->isFor($element, $pipeline)) { - $pipeline = $optimization->optimize($element, $pipeline); - $optimized = true; - } - } - - return $optimized ? $pipeline : $pipeline->add($element); - } -} diff --git a/src/core/etl/src/Flow/ETL/Pipeline/Optimizer/LimitOptimization.php b/src/core/etl/src/Flow/ETL/Pipeline/Optimizer/LimitOptimization.php deleted file mode 100644 index ad5e79f1b7..0000000000 --- a/src/core/etl/src/Flow/ETL/Pipeline/Optimizer/LimitOptimization.php +++ /dev/null @@ -1,109 +0,0 @@ -> - */ - private array $nonExpandingProcessors = [ - CollectingProcessor::class, - BatchingProcessor::class, - VoidProcessor::class, - ]; - - /** - * @var array - */ - private array $nonExpandingTransformers = [ - ScalarFunctionTransformer::class, - SelectEntriesTransformer::class, - PruneEntriesTransformer::class, - DropEntriesTransformer::class, - RenameEachEntryTransformer::class, - RenameEntryTransformer::class, - LimitTransformer::class, - ]; - - public function isFor(Loader|Transformer $element, Pipeline $pipeline): bool - { - return $element instanceof LimitTransformer; - } - - public function optimize(Loader|Transformer $element, Pipeline $pipeline): Pipeline - { - $extractor = $pipeline->extractor(); - - if ( - $element instanceof LimitTransformer - && $extractor instanceof LimitPushDown - && $this->hasOnlyNonExpandingSteps($pipeline) - ) { - // a hint only: the source may read less. The operator below still enforces the count. - // Pushed into a copy the plan owns - the caller may read the same extractor again without a limit. - $pushed = clone $extractor; - $pushed->pushLimit($element->limit); - $pipeline->replaceExtractor($pushed); - } - - return $pipeline->add($element); - } - - private function isNonExpandingStep(Loader|Processor|Transformer $step): bool - { - if (in_array($step::class, $this->nonExpandingTransformers, true)) { - return true; - } - - foreach ($this->nonExpandingProcessors as $nonExpandingProcessor) { - if ($step instanceof $nonExpandingProcessor) { - return true; - } - } - - return false; - } - - private function hasOnlyNonExpandingSteps(Pipeline $pipeline): bool - { - foreach ($pipeline->segments()->steps() as $step) { - if ($step instanceof ScalarFunctionTransformer && (new ExpandingFunctions())->in($step->function) !== []) { - return false; - } - - if (!$this->isNonExpandingStep($step)) { - return false; - } - } - - return true; - } -} diff --git a/src/core/etl/src/Flow/ETL/Pipeline/Optimizer/Optimization.php b/src/core/etl/src/Flow/ETL/Pipeline/Optimizer/Optimization.php deleted file mode 100644 index c0c1fec649..0000000000 --- a/src/core/etl/src/Flow/ETL/Pipeline/Optimizer/Optimization.php +++ /dev/null @@ -1,16 +0,0 @@ -schema(); - $bound = new Segments($extractor); - - foreach ($segments->steps() as $step) { - if ($step instanceof Loader) { - $bound->add($step); - - continue; - } - - $boundStep = $step->bind($schema); - $schema = $boundStep->output; - $bound->add($boundStep->step); - } - - return new BoundPlan($bound, $schema); - } -} diff --git a/src/core/etl/src/Flow/ETL/Pipeline/Segments.php b/src/core/etl/src/Flow/ETL/Pipeline/Segments.php deleted file mode 100644 index 83e1c9ee64..0000000000 --- a/src/core/etl/src/Flow/ETL/Pipeline/Segments.php +++ /dev/null @@ -1,134 +0,0 @@ - */ - private array $segments = []; - - public function __construct(?Extractor $extractor = null) - { - $this->currentSegment = new Segment(extractor: $extractor); - } - - public function add(Transformer|Loader|Processor $step): void - { - if ($step instanceof Processor) { - $this->segments[] = $this->currentSegment->withProcessor($step); - $this->currentSegment = new Segment(); - } else { - $this->currentSegment->add($step); - } - } - - public function replaceExtractor(Extractor $extractor): void - { - if ($this->segments === []) { - $this->currentSegment = $this->currentSegment->withExtractor($extractor); - - return; - } - - $this->segments[0] = $this->segments[0]->withExtractor($extractor); - } - - /** - * Get all segments including the current one. - * - * @return array - */ - public function all(): array - { - return [...$this->segments, $this->currentSegment]; - } - - /** - * Get the current (most recent) segment. - * - * Returns the last completed segment if any exist, otherwise the current segment being built. - */ - public function current(): Segment - { - if ($this->segments === []) { - return $this->currentSegment; - } - - return $this->segments[count($this->segments) - 1]; - } - - /** - * Check if any segment contains a step of the given class. - * - * @param class-string $class - */ - public function has(string $class): bool - { - foreach ($this->segments as $segment) { - if ($segment->has($class)) { - return true; - } - } - - return $this->currentSegment->has($class); - } - - public function segmentFor(Transformer|Loader|Processor $step): ?Segment - { - foreach ($this->segments as $segment) { - if ($segment->contains($step)) { - return $segment; - } - } - - if ($this->currentSegment->contains($step)) { - return $this->currentSegment; - } - - return null; - } - - /** - * Get all steps (Transformers, Loaders, Processors) flattened. - * - * @return array - */ - public function steps(): array - { - $steps = []; - - foreach ($this->segments as $segment) { - foreach ($segment->steps() as $step) { - $steps[] = $step; - } - - $processor = $segment->processor(); - - if ($processor !== null) { - $steps[] = $processor; - } - } - - foreach ($this->currentSegment->steps() as $step) { - $steps[] = $step; - } - - return $steps; - } -} diff --git a/src/core/etl/src/Flow/ETL/Pipeline/TransformationStream.php b/src/core/etl/src/Flow/ETL/Pipeline/TransformationStream.php deleted file mode 100644 index 850e598ef9..0000000000 --- a/src/core/etl/src/Flow/ETL/Pipeline/TransformationStream.php +++ /dev/null @@ -1,79 +0,0 @@ -source = new FeedExtractor($schema); - - try { - $frame = $transformation->transform(df($context->config)->from($this->source)); - - // @mago-ignore analysis:avoid-catching-error - } catch (FiberError $error) { - throw new InvalidLogicException( - 'A Transformation given to to_transformation() or to_branch()->withTransformation() must only ' - . 'build the DataFrame, not trigger it - count(), fetch() and the other trigger methods read ' - . 'from a source that only exists while the nested pipeline runs.', - previous: $error, - ); - } - - $this->fiber = new Fiber(function () use ($frame): void { - foreach ($frame->get() as $transformedRows) { - $this->sink->load($transformedRows, $this->context); - } - }); - } - - public function drain(): void - { - if ($this->fiber->isSuspended()) { - $this->source->finish(); - $this->fiber->resume(); - } - } - - public function drivenBy(FlowContext $context): bool - { - return $this->context === $context; - } - - public function feed(Rows $rows): void - { - if ($this->fiber->isTerminated()) { - return; - } - - $this->source->feed($rows); - - $this->fiber->isStarted() ? $this->fiber->resume() : $this->fiber->start(); - } -} diff --git a/src/core/etl/src/Flow/ETL/Plan.php b/src/core/etl/src/Flow/ETL/Plan.php new file mode 100644 index 0000000000..0b6f05b71f --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan.php @@ -0,0 +1,49 @@ +config))->setErrorHandler($context->errorHandler())); + } + + /** + * A subtree several consumers share is printed once and referenced by its number afterwards. The optimized stage + * is the plan the configured optimizer hands to the planner; a joined or read frame is part of the tree. + */ + public function toString(Stage $stage = Stage::optimized, Format $format = Format::tree): string + { + if ($stage === Stage::physical) { + return (new Explain())->physical( + $this->context->config->planner()->plan($this->logical, $this->context), + $format, + ); + } + + return (new Explain())->of(match ($stage) { + Stage::unoptimized => $this->logical, + Stage::optimized => $this->context->config->optimizer()->optimize($this->logical, $this->context), + }, $format); + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Explain.php b/src/core/etl/src/Flow/ETL/Plan/Explain.php new file mode 100644 index 0000000000..5731f7756c --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Explain.php @@ -0,0 +1,38 @@ +render((new Outline(declarations: $format === Format::declarations))->of($plan->root), $format); + } + + /** + * The physical plan carries no declarations of its own, so every format but the boxes renders as a tree. + */ + public function physical(PhysicalPlan $plan, Format $format = Format::tree): string + { + return $this->render((new PhysicalOutline())->of($plan), $format); + } + + public function render(Entry $root, Format $format): string + { + return (match ($format) { + Format::tree, Format::declarations => new TreeLayout(), + Format::boxes => new BoxLayout(), + Format::flow => new FlowLayout(), + })->render($root); + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Explain/BoxLayout.php b/src/core/etl/src/Flow/ETL/Plan/Explain/BoxLayout.php new file mode 100644 index 0000000000..53259affc4 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Explain/BoxLayout.php @@ -0,0 +1,222 @@ + $boxes */ + $boxes = []; + $this->place($root, 0, 0, null, $boxes); + + /** @var array $heights */ + $heights = []; + + foreach ($boxes as $box) { + $heights[$box['depth']] = max($heights[$box['depth']] ?? 0, count($this->content($box['entry'])) + 2); + } + + /** @var array $tops */ + $tops = []; + $top = 0; + + for ($depth = 0; $depth < count($heights); $depth++) { + $tops[$depth] = $top; + $top += $heights[$depth]; + } + + $canvas = array_fill(0, max(0, $top), array_fill(0, max(0, $this->span($root) * self::WIDTH), ' ')); + + foreach ($boxes as $box) { + $this->box( + $canvas, + $box['entry'], + $box['column'] * self::WIDTH, + $tops[$box['depth']], + $heights[$box['depth']], + $box['parent'] !== null, + ); + } + + foreach ($boxes as $box) { + $this->links($canvas, $box, $boxes, $tops[$box['depth']], $heights[$box['depth']]); + } + + return implode("\n", array_map(static fn(array $row): string => rtrim(implode('', $row)), $canvas)); + } + + /** + * @param list $boxes + */ + public function place(Entry $entry, int $column, int $depth, ?int $parent, array &$boxes): void + { + $boxes[] = ['entry' => $entry, 'column' => $column, 'depth' => $depth, 'parent' => $parent]; + $index = count($boxes) - 1; + + foreach ($entry->children as $child) { + $this->place($child, $column, $depth + 1, $index, $boxes); + $column += $this->span($child); + } + } + + public function span(Entry $entry): int + { + return $entry->children === [] ? 1 : array_sum(array_map($this->span(...), $entry->children)); + } + + /** + * @return list + */ + public function content(Entry $entry): array + { + $title = $entry->title(); + + if ($entry->shared) { + return [...$this->wrap($title), '(shared)']; + } + + $details = $entry->lines; + + if ($details === []) { + return $this->wrap($title); + } + + return array_merge($this->wrap($title), [str_repeat('─', 20)], ...array_map($this->wrap(...), $details)); + } + + /** + * @return list + */ + public function wrap(string $text): array + { + $lines = []; + $line = ''; + + foreach (explode(' ', $text) as $word) { + foreach (mb_str_split($word, self::TEXT) as $piece) { + if ($line !== '' && (mb_strlen($line) + 1 + mb_strlen($piece)) > self::TEXT) { + $lines[] = $line; + $line = ''; + } + + $line = $line === '' ? $piece : $line . ' ' . $piece; + } + } + + $lines[] = $line; + + return $lines; + } + + /** + * @param list> $canvas + */ + public function box(array &$canvas, Entry $entry, int $x, int $y, int $height, bool $hasParent): void + { + $inner = self::WIDTH - 2; + $center = $x + intdiv(self::WIDTH, 2); + + $this->write($canvas, $x, $y, '┌' . str_repeat('─', $inner) . '┐'); + $this->write($canvas, $x, $y + $height - 1, '└' . str_repeat('─', $inner) . '┘'); + + $content = $this->content($entry); + + for ($row = 1; $row < ($height - 1); $row++) { + $text = $content[$row - 1] ?? ''; + $left = max(0, intdiv($inner - mb_strlen($text), 2)); + $this->write( + $canvas, + $x, + $y + $row, + '│' . str_repeat(' ', $left) . $text . str_repeat(' ', max(0, $inner - $left - mb_strlen($text))) . '│', + ); + } + + if ($hasParent) { + $canvas[$y][$center] = '┴'; + } + + if ($entry->children !== []) { + $canvas[$y + $height - 1][$center] = '┬'; + } + } + + /** + * Draws the line from a box's right edge to each child after the first; the first child sits right below it. + * + * @param list> $canvas + * @param array{entry: Entry, column: int, depth: int, parent: ?int} $box + * @param list $boxes + */ + public function links(array &$canvas, array $box, array $boxes, int $top, int $height): void + { + $children = $box['entry']->children; + + if (count($children) < 2) { + return; + } + + $row = $top + intdiv($height, 2); + $edge = (($box['column'] + 1) * self::WIDTH) - 1; + $canvas[$row][$edge] = '├'; + $column = $box['column']; + $centers = []; + + foreach ($children as $index => $child) { + if ($index > 0) { + $centers[] = ($column * self::WIDTH) + intdiv(self::WIDTH, 2); + } + + $column += $this->span($child); + } + + $last = $centers[count($centers) - 1]; + + for ($x = $edge + 1; $x < $last; $x++) { + $canvas[$row][$x] = '─'; + } + + foreach ($centers as $center) { + $canvas[$row][$center] = $center === $last ? '┐' : '┬'; + + for ($y = $row + 1; $y < ($top + $height); $y++) { + $canvas[$y][$center] = '│'; + } + } + } + + /** + * @param list> $canvas + */ + public function write(array &$canvas, int $x, int $y, string $text): void + { + foreach (mb_str_split($text) as $offset => $character) { + $canvas[$y][$x + $offset] = $character; + } + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Explain/Branches.php b/src/core/etl/src/Flow/ETL/Plan/Explain/Branches.php new file mode 100644 index 0000000000..ff1ccca17d --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Explain/Branches.php @@ -0,0 +1,29 @@ + + */ + public function of(Entry $entry, string $indent): array + { + $last = array_key_last($entry->children); + $branches = []; + + foreach ($entry->children as $index => $child) { + $branches[] = $index === $last + ? [$child, $indent . '└─ ', $indent . ' '] + : [$child, $indent . '├─ ', $indent . '│ ']; + } + + return $branches; + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Explain/Condition.php b/src/core/etl/src/Flow/ETL/Plan/Explain/Condition.php new file mode 100644 index 0000000000..2968265df6 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Explain/Condition.php @@ -0,0 +1,66 @@ + $this->composite($comparison->comparisons(), ' AND '), + $comparison instanceof Any => $this->composite($comparison->comparisons(), ' OR '), + $comparison instanceof Equal => $this->pair($comparison, '='), + $comparison instanceof Identical => $this->pair($comparison, '==='), + default => (new ReflectionClass($comparison))->getShortName(), + }; + } + + /** + * The conditions an AND joins, each on its own line; anything else stays one line. + * + * @return list + */ + public function lines(Comparison $comparison): array + { + return ( + $comparison instanceof All + ? array_values(array_map(fn(Comparison $each): string => $this->of($each), $comparison->comparisons())) + : [$this->of($comparison)] + ); + } + + /** + * A comparison that joins others is parenthesized, so the operators it sits between stay unambiguous. + * + * @param array $comparisons + */ + public function composite(array $comparisons, string $operator): string + { + return implode($operator, array_map(fn(Comparison $each): string => $each instanceof All || $each instanceof Any + ? '(' . $this->of($each) . ')' + : $this->of($each), $comparisons)); + } + + public function pair(Comparison $comparison, string $operator): string + { + $left = $comparison->left(); + $right = $comparison->right(); + + return isset($left[0], $right[0]) + ? $left[0]->name() . ' ' . $operator . ' ' . $right[0]->name() + : (new ReflectionClass($comparison))->getShortName(); + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Explain/Details.php b/src/core/etl/src/Flow/ETL/Plan/Explain/Details.php new file mode 100644 index 0000000000..d282c27e2d --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Explain/Details.php @@ -0,0 +1,249 @@ +getShortName(); + } + + /** + * What the node does, one "Label: value" per line, followed by what it means for the rows in plain words. + * + * @return list + */ + public function lines(Node $node): array + { + return [...$this->labelled($node), ...$this->notes($node)]; + } + + /** + * @return list + */ + public function labelled(Node $node): array + { + return match (true) { + $node instanceof Read => $this->read($node), + $node instanceof Join => $this->join($node), + $node instanceof CrossJoin => $this->crossJoin($node), + $node instanceof Result => ['Rows this plan hands out: to the trigger, or to the node reading it'], + $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 Write => ['Loader: ' . $this->name($node->loader)], + $node instanceof Limit => ['Limit: ' . $node->limit], + $node instanceof Offset => ['Skip: ' . $node->offset], + $node instanceof TopN => ['Top: ' . $node->limit], + $node instanceof Rename => [sprintf('Rename: %s → %s', $node->from, $node->to)], + $node instanceof Select => ['Columns: ' . $this->columns($node->entries)], + $node instanceof Drop => ['Drops: ' . $this->columns($node->entries)], + $node instanceof Distinct => [ + 'Distinct on: ' . ($node->entries === [] ? 'every column' : $this->columns($node->entries)), + ], + $node instanceof Batch => ['Batch size: ' . $node->size], + $node instanceof Repartition => ['Partition by: ' . implode(', ', $node->by->names())], + $node instanceof Sort => $node->algorithm === null + ? ['Sort by: ' . implode(', ', $node->refs->names())] + : [ + 'Sort by: ' . implode(', ', $node->refs->names()), + 'Algorithm: ' . $this->algorithm($node->algorithm), + ], + $node instanceof Aggregate => $this->aggregate($node), + $node instanceof Cache => $node->id === null ? [] : ['Cache: ' . $node->id], + $node instanceof Validate => ['Against: ' . $this->name($node->validator)], + default => [], + }; + } + + /** + * @return list + */ + public function join(Join $join): array + { + $comparison = $join->on->comparison(); + $lines = ['Type: ' . $join->type->value]; + + if ($comparison instanceof Any) { + foreach ($this->condition->lines($comparison) as $condition) { + $lines[] = 'On: ' . $condition; + } + } else { + $lines[] = 'Left on: ' . $this->references($comparison->left()); + $lines[] = 'Right on: ' . $this->references($comparison->right()); + } + + if ($join->on->prefix() !== '') { + $lines[] = 'Prefix: ' . $join->on->prefix(); + } + + if ($join->algorithm !== null) { + $lines[] = 'Algorithm: ' . $this->algorithm($join->algorithm); + } + + return $lines; + } + + /** + * @return list + */ + public function crossJoin(CrossJoin $join): array + { + return $join->prefix === '' ? ['Type: cross'] : ['Type: cross', 'Prefix: ' . $join->prefix]; + } + + /** + * @param array $references + */ + public function references(array $references): string + { + return implode(', ', array_map(static fn(Reference $ref): string => $ref->name(), $references)); + } + + // every algorithm is configured through a *Builder, the algorithm is what the reader is after + public function algorithm(object $builder): string + { + $algorithm = $this->name($builder); + + return str_ends_with($algorithm, 'Builder') ? substr($algorithm, 0, -7) : $algorithm; + } + + /** + * @param list $entries + */ + public function columns(array $entries): string + { + return implode(', ', array_map(static fn(Reference|string $entry): string => $entry instanceof Reference + ? $entry->name() + : $entry, $entries)); + } + + /** + * @return list + */ + public function aggregate(Aggregate $node): array + { + $lines = $node->groupBy->isGlobal() + ? ['Group by: every row'] + : ['Group by: ' . implode(', ', $node->groupBy->refs()->names())]; + + if ($node->algorithm !== null) { + $lines[] = 'Algorithm: ' . $this->algorithm($node->algorithm); + } + + return $lines; + } + + /** + * @return list + */ + public function read(Read $read): array + { + $extractor = $read->extractor(); + $lines = ['Extractor: ' . $this->name($extractor)]; + + // the path is metadata the source already holds; asking for its schema would read it, which a logical stage never does + if ($extractor instanceof FileExtractor) { + $lines[] = 'Source: ' . $extractor->source()->uri(); + } + + $limit = $read->limit(); + + if ($limit !== null) { + $lines[] = 'Limit: ' . $limit; + } + + // every file source reads only files unless a filter was pushed into it + if (!$read->pathFilter() instanceof OnlyFiles) { + $lines[] = 'Files: ' . $this->name($read->pathFilter()); + } + + return $lines; + } + + /** + * The declarations below in plain words, for the ones that change how the rows flow. + * + * @return list + */ + public function notes(Node $node): array + { + $notes = []; + $redefines = $node->redefines(); + + if ($node->materialization() === Materialization::blocking) { + $notes[] = 'Buffers all rows before passing them on'; + } + + if ($redefines->unknown) { + $notes[] = 'Defines columns known only at run time'; + } elseif ($redefines->names !== []) { + $notes[] = 'Defines columns: ' . implode(', ', $redefines->names); + } + + return $notes; + } + + /** + * The declarations optimizer rules read, on one line. + */ + public function declarations(Node $node): string + { + $redefines = $node->redefines(); + $declarations = [ + $node->rowCount()->name, + $node->transparency()->name, + $node->materialization()->name, + ]; + + if ($redefines->unknown) { + $declarations[] = 'redefines unknown'; + } elseif ($redefines->names !== []) { + $declarations[] = 'redefines ' . implode(', ', $redefines->names); + } + + return implode(' · ', $declarations); + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Explain/Entry.php b/src/core/etl/src/Flow/ETL/Plan/Explain/Entry.php new file mode 100644 index 0000000000..71d12df1bf --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Explain/Entry.php @@ -0,0 +1,55 @@ + $lines the details under the title + * @param list $children + * @param string $suffix what goes on the title line, after the name + */ + public function __construct( + public object $source, + public string $name, + public array $lines, + public ?int $number, + public bool $shared, + public array $children, + public string $suffix = '', + ) {} + + /** + * The name with the number in front; an entry without a number - Outputs, which only groups the consumers - has + * none. + */ + public function title(): string + { + return $this->number === null ? $this->name : '#' . $this->number . ' ' . $this->name; + } + + /** + * The same entry read from somewhere else in the plan: shared drops what the first visit already printed. + * + * @param list $children + */ + public function with(array $children, bool $shared = false): self + { + return new self( + $this->source, + $this->name, + $shared ? [] : $this->lines, + $this->number, + $shared, + $children, + $shared ? '' : $this->suffix, + ); + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Explain/FlowLayout.php b/src/core/etl/src/Flow/ETL/Plan/Explain/FlowLayout.php new file mode 100644 index 0000000000..3552e69975 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Explain/FlowLayout.php @@ -0,0 +1,85 @@ +> $readers */ + $readers = new SplObjectStorage(); + $sources = []; + $this->collect($root, $readers, $sources); + + /** @var SplObjectStorage $placed */ + $placed = new SplObjectStorage(); + + return implode("\n", array_map(fn(Entry $source): string => $this->tree->render($this->reversed( + $source, + $readers, + $placed, + )), $sources)); + } + + /** + * @param SplObjectStorage> $readers every node's readers, in the order the tree visits them + * @param list $sources the entries without inputs, in the order the tree visits them + */ + public function collect(Entry $entry, SplObjectStorage $readers, array &$sources): void + { + if ($entry->shared) { + return; + } + + if ($entry->children === []) { + $sources[] = $entry; + } + + foreach ($entry->children as $child) { + $readers[$child->source] = [ + ...($readers->offsetExists($child->source) ? $readers[$child->source] : []), + $entry, + ]; + $this->collect($child, $readers, $sources); + } + } + + /** + * @param SplObjectStorage> $readers + * @param SplObjectStorage $placed the nodes already printed, any later reach is a shared reference + */ + public function reversed(Entry $entry, SplObjectStorage $readers, SplObjectStorage $placed): Entry + { + $placed[$entry->source] = true; + $children = []; + + foreach ($readers->offsetExists($entry->source) ? $readers[$entry->source] : [] as $reader) { + if ($reader->source instanceof Outputs) { + continue; + } + + $children[] = $placed->offsetExists($reader->source) + ? $reader->with([], shared: true) + : $this->reversed($reader, $readers, $placed); + } + + return $entry->with($children); + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Explain/Layout.php b/src/core/etl/src/Flow/ETL/Plan/Explain/Layout.php new file mode 100644 index 0000000000..e1634aa8d6 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Explain/Layout.php @@ -0,0 +1,10 @@ + $numbers */ + $numbers = new SplObjectStorage(); + + return $this->entry($root, $numbers); + } + + /** + * A node is numbered once everything it reads is, so the numbers follow the order rows move: the source is #1. + * + * @param SplObjectStorage $numbers the nodes numbered so far + */ + public function entry(Node $node, SplObjectStorage $numbers): Entry + { + if ($numbers->offsetExists($node)) { + return $this->describe($node, $numbers[$node], [])->with([], shared: true); + } + + $children = []; + + foreach ($node->children() as $child) { + $children[] = $this->entry($this->read($node, $child), $numbers); + } + + if ($node instanceof Outputs) { + return $this->describe($node, null, $children); + } + + $numbers[$node] = $number = count($numbers) + 1; + + return $this->describe($node, $number, $children); + } + + /** + * @param list $children + */ + public function describe(Node $node, ?int $number, array $children): Entry + { + return new Entry( + $node, + $this->details->name($node), + $this->declarations ? $this->details->labelled($node) : $this->details->lines($node), + $number, + false, + $children, + $this->declarations ? $this->details->declarations($node) : '', + ); + } + + /** + * A join's right side has to be a plan root, and a Result there hands its rows to the join and to nothing else, + * so the join is drawn reading what that Result reads. An Outputs stays: it means the side has other consumers. + */ + public function read(Node $node, Node $child): Node + { + return $node instanceof JoinsFrame && $child instanceof Result ? $child->children()[0] : $child; + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Explain/PhysicalOutline.php b/src/core/etl/src/Flow/ETL/Plan/Explain/PhysicalOutline.php new file mode 100644 index 0000000000..cea5a9af82 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Explain/PhysicalOutline.php @@ -0,0 +1,122 @@ +schema($plan), null, false, [$this->pipeline($plan->root())]); + } + + public function pipeline(Pipeline $pipeline): Entry + { + $lines = []; + $children = []; + + foreach ($pipeline->segments()->all() as $segment) { + $extractor = $segment->extractor(); + + if ($extractor !== null) { + foreach ($this->steps->lines($extractor) as $line) { + $lines[] = $line; + } + + foreach ($this->source($pipeline) as $line) { + $lines[] = $line; + } + } + + $processor = $segment->processor(); + + foreach ([...$segment->steps(), ...($processor === null ? [] : [$processor])] as $step) { + foreach ($this->steps->lines($step) as $line) { + $lines[] = $line; + } + + $joined = match (true) { + $step instanceof HashJoinProcessor, $step instanceof CrossJoinRowsTransformer => $step->right, + default => null, + }; + + if ($joined !== null) { + $children[] = $this->joined($joined); + } + } + } + + $input = $pipeline->input(); + + return new Entry( + $pipeline, + 'Pipeline #' . $pipeline->id, + $lines, + null, + false, + $input === null ? $children : [$this->pipeline($input), ...$children], + ); + } + + /** + * A joined frame is planned apart, so its pipelines are numbered apart too - the name says which side they are. + */ + public function joined(PhysicalPlan $right): Entry + { + $root = $this->pipeline($right->root()); + + return new Entry($right, 'Right side: ' . $root->name, $root->lines, null, false, $root->children); + } + + /** + * What the source was handed, when the pipeline reads it directly. + * + * @return list + */ + public function source(Pipeline $pipeline): array + { + $lines = []; + $limit = $pipeline->limit(); + + if ($limit !== null) { + $lines[] = ' Limit: ' . $limit; + } + + if (!$pipeline->pathFilter() instanceof OnlyFiles) { + $lines[] = ' Files: ' . $this->details->name($pipeline->pathFilter()); + } + + return $lines; + } + + /** + * @return list + */ + public function schema(PhysicalPlan $plan): array + { + if (!$plan instanceof Described) { + return ['Schema: not derivable - ' . $plan->why->getMessage()]; + } + + return ['Columns: ' . implode(', ', $plan->schema->references()->names())]; + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Explain/StepDetails.php b/src/core/etl/src/Flow/ETL/Plan/Explain/StepDetails.php new file mode 100644 index 0000000000..7738770a65 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Explain/StepDetails.php @@ -0,0 +1,215 @@ + + */ + public function lines(Extractor|Loader|Processor|Transformer $step): array + { + $label = match (true) { + $step instanceof Extractor => 'Extractor: ', + $step instanceof Processor => 'Processor: ', + $step instanceof Transformer => 'Transformer: ', + default => 'Loader: ', + }; + + $lines = [$label . $this->details->name($step)]; + + foreach ($this->settings($step) as $setting) { + $lines[] = self::INDENT . $setting; + } + + return $lines; + } + + /** + * @return list + */ + public function settings(Extractor|Loader|Processor|Transformer $step): array + { + return match (true) { + $step instanceof HashJoinProcessor => $this->hashJoin($step), + $step instanceof CrossJoinRowsTransformer => $step->prefix === '' + ? ['Join: cross'] + : ['Join: cross', 'Prefix: ' . $step->prefix], + $step instanceof MergeSortProcessor => [ + 'Sort: ' . $this->sort($step->refs), + 'Spill: ' . $this->details->name($step->spill->storage()), + 'Merge: ' . $step->mergeFanIn . ' ways', + 'Batch: ' . $step->batchSize, + ], + $step instanceof MemorySortProcessor => ['Sort: ' . $this->sort($step->refs)], + $step instanceof TopNProcessor => ['Top: ' . $step->limit, 'Sort: ' . $this->sort($step->refs)], + $step instanceof GroupByAggregationProcessor => [ + 'Group by: ' . $this->columns($step->groupBy->refs()), + 'Aggregations: ' . $this->aggregations($step), + 'Storage: ' . $this->details->name($step->buckets->storage()), + 'Batch: ' . $step->batchSize, + ], + $step instanceof PivotProcessor => $this->pivot($step), + $step instanceof WindowProcessor => $this->window($step), + $step instanceof RepartitionProcessor => [ + 'By: ' . $this->columns($step->by), + 'Hasher: ' . $this->details->name($step->hasher), + 'Storage: ' . $this->details->name($step->buckets->storage()), + ], + $step instanceof BucketingProcessor => [ + 'Strategy: ' . $this->details->name($step->strategy), + 'Storage: ' . $this->details->name($step->buckets->storage()), + ], + $step instanceof BatchingProcessor => ['Batch: ' . $step->size], + $step instanceof BatchingByProcessor => $this->batchingBy($step), + $step instanceof CachingProcessor => $this->caching($step), + $step instanceof ConstrainedProcessor => $step->constraints === [] + ? [] + : ['Constraints: ' . implode(', ', array_map($this->details->name(...), $step->constraints))], + $step instanceof CollectingProcessor => $step->declared === null ? [] : ['Schema: declared'], + $step instanceof OffsetProcessor => ['Skip: ' . $step->offset], + default => [], + }; + } + + /** + * @return list + */ + public function hashJoin(HashJoinProcessor $join): array + { + $lines = ['Join: ' . $join->type->value]; + + foreach ($this->condition->lines($join->expression->comparison()) as $condition) { + $lines[] = 'On: ' . $condition; + } + + if ($join->expression->prefix() !== '') { + $lines[] = 'Prefix: ' . $join->expression->prefix(); + } + + return [ + ...$lines, + 'Storage: ' . $this->details->name($join->rightBuckets->storage()), + 'Buckets: ' . $join->bucketsCount, + 'Batch: ' . $join->batchSize, + ]; + } + + /** + * @return list + */ + public function pivot(PivotProcessor $pivot): array + { + $lines = ['Group by: ' . $this->columns($pivot->groupBy->refs())]; + $pivoted = $pivot->groupBy->pivotedBy(); + + if ($pivoted !== null) { + $lines[] = 'Pivot: ' . $pivoted->column->name(); + } + + $lines[] = 'Batch: ' . $pivot->batchSize; + + return $lines; + } + + /** + * @return list + */ + public function window(WindowProcessor $window): array + { + return [ + 'Column: ' . ($window->entry instanceof Definition ? $window->entry->entry()->name() : $window->entry), + 'Function: ' . $this->details->name($window->function), + ...($window->bound === null ? [] : ['Frame: bound']), + ]; + } + + /** + * @return list + */ + public function batchingBy(BatchingByProcessor $batching): array + { + return ( + $batching->minSize === null + ? ['Batch by: ' . $batching->column->name()] + : ['Batch by: ' . $batching->column->name(), 'Min size: ' . $batching->minSize] + ); + } + + /** + * @return list + */ + public function caching(CachingProcessor $caching): array + { + $lines = $caching->cache === null ? [] : ['Cache: ' . $this->details->name($caching->cache)]; + + if ($caching->id !== null) { + $lines[] = 'Id: ' . $caching->id; + } + + return $lines; + } + + public function aggregations(GroupByAggregationProcessor $groupBy): string + { + $names = []; + + foreach ($groupBy->groupBy->aggregations() as $aggregation) { + $names[] = $this->details->name($aggregation); + } + + return $names === [] ? 'none' : implode(', ', $names); + } + + public function columns(References $refs): string + { + return implode(', ', array_map(static fn(Reference $ref): string => $ref->name(), $refs->all())); + } + + public function sort(References $refs): string + { + return implode(', ', array_map( + static fn(Reference $ref): string => ( + $ref->name() . ' ' . ($ref->sort() === SortOrder::ASC ? 'asc' : 'desc') + ), + $refs->all(), + )); + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Explain/TreeLayout.php b/src/core/etl/src/Flow/ETL/Plan/Explain/TreeLayout.php new file mode 100644 index 0000000000..b9b91ed2c1 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Explain/TreeLayout.php @@ -0,0 +1,45 @@ +lines($root, '', '')); + } + + /** + * @param string $connector drawn before this entry's line + * @param string $indent drawn before every line under this entry + * + * @return list + */ + public function lines(Entry $entry, string $connector, string $indent): array + { + if ($entry->shared) { + return [$connector . $entry->title() . ' (shared)']; + } + + $title = $connector . $entry->title(); + $lines = [$entry->suffix === '' ? $title : $title . ' ' . $entry->suffix]; + // the children's connector runs through the details, so the details sit inside the node's branch + $rail = $entry->children === [] ? ' ' : '│ '; + + foreach ($entry->lines as $detail) { + $lines[] = $indent . $rail . $detail; + } + + foreach ((new Branches())->of($entry, $indent) as [$child, $childConnector, $childIndent]) { + foreach ($this->lines($child, $childConnector, $childIndent) as $line) { + $lines[] = $line; + } + } + + return $lines; + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Format.php b/src/core/etl/src/Flow/ETL/Plan/Format.php new file mode 100644 index 0000000000..95fb37c9e9 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Format.php @@ -0,0 +1,28 @@ +root instanceof Node\Outputs => $this->root->sinks(), + $this->root instanceof Node\Write, $this->root instanceof Node\Transaction => new Sinks($this->root), + default => new Sinks(), + }; + } + + /** + * The root's sinks, then the sinks of every Outputs further down the chain - a frame this plan read keeps its + * own sinks, and they read the rows that pass through it. + */ + public function sinksOnSpine(): Sinks + { + $sinks = $this->sinks(); + + for ($node = $this->root; $node->children() !== []; $node = $node->children()[0]) { + if ($node !== $this->root && $node instanceof Node\Outputs) { + $sinks = $sinks->merge($node->sinks()); + } + } + + return $sinks; + } + + /** + * The node the first consumer reads: the chain a verb built, under the consumer the trigger put on top. + * + * @throws InvalidLogicException when that consumer is a Transaction, whose children are sibling sinks, or when + * the root carries no consumer at all + */ + public function spine(): Node + { + $consumer = $this->root instanceof Node\Outputs ? $this->root->children()[0] : $this->root; + + if ($consumer instanceof Node\Transaction) { + throw InvalidLogicException::firstConsumerIsATransaction(); + } + + return $consumer->children()[0] ?? throw InvalidLogicException::because( + 'A logical plan must have a consumer root, %s found', + $consumer::class, + ); + } + + /** + * The node each consumer reads - the root's consumers, each Write of a Transaction expanded, and the sinks of + * every Outputs further down the spine. A consumer takes rows out of the plan, so a walk from it starts at its + * input. + * + * @return list + */ + public function consumerInputs(): array + { + $first = $this->root instanceof Node\Outputs ? $this->root->children()[0] : $this->root; + $consumers = $first instanceof Node\Result + ? [$first, ...$this->sinksOnSpine()->all()] + : $this->sinksOnSpine()->all(); + + $inputs = []; + + foreach ($consumers as $consumer) { + foreach ($consumer instanceof Node\Transaction ? $consumer->children() : [$consumer] as $write) { + $inputs[] = $write->children()[0]; + } + } + + return $inputs; + } + + /** + * ONE memo for the whole DAG, so a prefix shared by several consumers is rewritten once. A join's right side + * is handed back as it is. + */ + public function transformUp(Rewrite $rewrite): self + { + $root = (new TransformUp())->of($this->root, $rewrite); + + return $root === $this->root ? $this : new self($root); + } + + /** + * This frame's own source: follow children()[0] to the leaf. Read is the only leaf kind a DataFrame + * can build, so the walk stops there and never descends into a join's right side. + * + * @throws InvalidLogicException when the row-input chain does not end in a Read + */ + public function source(): Read + { + $node = $this->root; + + while (!$node instanceof Read) { + $children = $node->children(); + + if ($children === []) { + throw InvalidLogicException::because('A logical plan must end in a Read, %s found', $node::class); + } + + $node = $children[0]; + } + + return $node; + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Materialization.php b/src/core/etl/src/Flow/ETL/Plan/Materialization.php new file mode 100644 index 0000000000..9d31d0601f --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Materialization.php @@ -0,0 +1,11 @@ + + */ + public function children(): array; + + /** + * The same node over new children. Returns $this when the children are the ones it already holds, so + * an untouched subtree keeps its identity and its planned steps (PlannedNodes remembers them by identity). + * + * @param list $children exactly as many as children() returns + */ + public function withChildren(array $children): self; + + /** + * What this node does to the row count. Answered from what the node holds, never from a class list. + */ + public function rowCount(): RowCount; + + /** + * Whether the node's output is a function of the rows it is handed, one at a time, with no effect + * outside the stream. + */ + public function transparency(): Transparency; + + /** + * Whether the node's steps must drain their input before they can emit. This is the pipeline cut + * point and it is NOT derivable from the other two: Sort is preserving+opaque+blocking, Write is + * preserving+opaque+streaming, Collect is preserving+transparent+blocking. + * + * A node NodeTranslator turns into Transformers only is streaming by construction: Segment::execute() + * calls transform() inside the per-batch loop, so a Transformer cannot buffer the stream. Only a + * Processor - handed the Generator - can be blocking. + */ + public function materialization(): Materialization; + + /** + * Columns this node introduces or renames on its output. A predicate that references one of them means a + * different column below this node, so it cannot be pushed past it. Answered from what the node holds, + * never from a class list. + */ + public function redefines(): Redefined; +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Node/Aggregate.php b/src/core/etl/src/Flow/ETL/Plan/Node/Aggregate.php new file mode 100644 index 0000000000..014f1616b7 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Node/Aggregate.php @@ -0,0 +1,58 @@ + + */ + public function children(): array + { + return [$this->input]; + } + + public function withChildren(array $children): self + { + return $children[0] === $this->input ? $this : new self($children[0], $this->groupBy, $this->algorithm); + } + + public function rowCount(): RowCount + { + return RowCount::reducing; + } + + public function transparency(): Transparency + { + return Transparency::opaque; + } + + public function materialization(): Materialization + { + return Materialization::blocking; + } + + public function redefines(): Redefined + { + return Redefined::unknown(); + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Node/Batch.php b/src/core/etl/src/Flow/ETL/Plan/Node/Batch.php new file mode 100644 index 0000000000..c6c7a386d4 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Node/Batch.php @@ -0,0 +1,63 @@ + $size + * + * @throws InvalidArgumentException + */ + public function __construct( + private Node $input, + public int $size, + ) { + // @mago-ignore analysis:invalid-operand,impossible-condition,redundant-comparison + if ($this->size <= 0) { + throw new InvalidArgumentException('Batch size must be greater than 0, given: ' . $this->size); + } + } + + /** + * @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->size); + } + + public function rowCount(): RowCount + { + return RowCount::preserving; + } + + public function transparency(): Transparency + { + return Transparency::transparent; + } + + public function materialization(): Materialization + { + return Materialization::streaming; + } + + public function redefines(): Redefined + { + return Redefined::none(); + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Node/BatchBy.php b/src/core/etl/src/Flow/ETL/Plan/Node/BatchBy.php new file mode 100644 index 0000000000..b680bacd9e --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Node/BatchBy.php @@ -0,0 +1,65 @@ + $minSize + * + * @throws InvalidArgumentException + */ + public function __construct( + private Node $input, + public Reference $column, + public ?int $minSize = null, + ) { + // @mago-ignore analysis:invalid-operand,impossible-condition,redundant-comparison,redundant-logical-operation + if ($this->minSize !== null && $this->minSize <= 0) { + throw new InvalidArgumentException('Minimum batch size must be greater than 0, given: ' . $this->minSize); + } + } + + /** + * @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->column, $this->minSize); + } + + public function rowCount(): RowCount + { + return RowCount::preserving; + } + + public function transparency(): Transparency + { + return Transparency::transparent; + } + + public function materialization(): Materialization + { + return Materialization::streaming; + } + + public function redefines(): Redefined + { + return Redefined::none(); + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Node/Cache.php b/src/core/etl/src/Flow/ETL/Plan/Node/Cache.php new file mode 100644 index 0000000000..05f389a804 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Node/Cache.php @@ -0,0 +1,63 @@ + $batchSize + */ + public function __construct( + private Node $input, + public ?string $id, + public ?int $batchSize, + public ?CacheStore $cache, + ) {} + + /** + * @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->id, $this->batchSize, $this->cache); + } + + public function rowCount(): RowCount + { + return RowCount::preserving; + } + + public function transparency(): Transparency + { + return Transparency::opaque; + } + + public function materialization(): Materialization + { + return Materialization::streaming; + } + + public function redefines(): Redefined + { + return Redefined::none(); + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Node/Collect.php b/src/core/etl/src/Flow/ETL/Plan/Node/Collect.php new file mode 100644 index 0000000000..9f678159ed --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Node/Collect.php @@ -0,0 +1,51 @@ + + */ + public function children(): array + { + return [$this->input]; + } + + public function withChildren(array $children): self + { + return $children[0] === $this->input ? $this : new self($children[0]); + } + + public function rowCount(): RowCount + { + return RowCount::preserving; + } + + public function transparency(): Transparency + { + return Transparency::transparent; + } + + public function materialization(): Materialization + { + return Materialization::blocking; + } + + public function redefines(): Redefined + { + return Redefined::none(); + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Node/CollectRefs.php b/src/core/etl/src/Flow/ETL/Plan/Node/CollectRefs.php new file mode 100644 index 0000000000..1b91db886b --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Node/CollectRefs.php @@ -0,0 +1,56 @@ + + */ + public function children(): array + { + return [$this->input]; + } + + public function withChildren(array $children): self + { + return $children[0] === $this->input ? $this : new self($children[0], $this->references); + } + + public function rowCount(): RowCount + { + return RowCount::preserving; + } + + public function transparency(): Transparency + { + return Transparency::opaque; + } + + public function materialization(): Materialization + { + return Materialization::streaming; + } + + public function redefines(): Redefined + { + return Redefined::none(); + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Node/Constrain.php b/src/core/etl/src/Flow/ETL/Plan/Node/Constrain.php new file mode 100644 index 0000000000..8bd2fb50c9 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Node/Constrain.php @@ -0,0 +1,59 @@ + $constraints + */ + public function __construct( + private Node $input, + public array $constraints, + ) {} + + /** + * @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->constraints); + } + + public function rowCount(): RowCount + { + return RowCount::preserving; + } + + public function transparency(): Transparency + { + return Transparency::opaque; + } + + public function materialization(): Materialization + { + return Materialization::streaming; + } + + public function redefines(): Redefined + { + return Redefined::none(); + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Node/CrossJoin.php b/src/core/etl/src/Flow/ETL/Plan/Node/CrossJoin.php new file mode 100644 index 0000000000..b9da33d2aa --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Node/CrossJoin.php @@ -0,0 +1,73 @@ +right = + $right instanceof Result || $right instanceof Outputs + ? $right + : throw InvalidLogicException::joinSideIsNotAPlanRoot($right::class); + } + + /** + * @return list + */ + public function children(): array + { + return [$this->input, $this->right]; + } + + public function withChildren(array $children): self + { + if ($children[0] === $this->input && $children[1] === $this->right) { + return $this; + } + + return new self($children[0], $children[1], $this->prefix); + } + + public function right(): Result|Outputs + { + return $this->right; + } + + public function rowCount(): RowCount + { + return RowCount::expanding; + } + + public function transparency(): Transparency + { + return Transparency::opaque; + } + + public function materialization(): Materialization + { + return Materialization::streaming; + } + + public function redefines(): Redefined + { + return Redefined::unknown(); + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Node/Discard.php b/src/core/etl/src/Flow/ETL/Plan/Node/Discard.php new file mode 100644 index 0000000000..ccf778cf01 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Node/Discard.php @@ -0,0 +1,51 @@ + + */ + public function children(): array + { + return [$this->input]; + } + + public function withChildren(array $children): self + { + return $children[0] === $this->input ? $this : new self($children[0]); + } + + public function rowCount(): RowCount + { + return RowCount::reducing; + } + + public function transparency(): Transparency + { + return Transparency::transparent; + } + + public function materialization(): Materialization + { + return Materialization::blocking; + } + + public function redefines(): Redefined + { + return Redefined::none(); + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Node/Distinct.php b/src/core/etl/src/Flow/ETL/Plan/Node/Distinct.php new file mode 100644 index 0000000000..390972f3db --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Node/Distinct.php @@ -0,0 +1,66 @@ + $entries + * + * @throws InvalidArgumentException + */ + public function __construct( + private Node $input, + public array $entries, + ) { + if ($this->entries === []) { + throw new InvalidArgumentException('DropDuplicatesTransformer requires at least one entry'); + } + } + + /** + * @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->entries); + } + + public function rowCount(): RowCount + { + return RowCount::reducing; + } + + public function transparency(): Transparency + { + return Transparency::transparent; + } + + public function materialization(): Materialization + { + return Materialization::streaming; + } + + public function redefines(): Redefined + { + return Redefined::none(); + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Node/Drop.php b/src/core/etl/src/Flow/ETL/Plan/Node/Drop.php new file mode 100644 index 0000000000..0b3360c587 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Node/Drop.php @@ -0,0 +1,56 @@ + $entries + */ + public function __construct( + private Node $input, + public array $entries, + ) {} + + /** + * @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->entries); + } + + public function rowCount(): RowCount + { + return RowCount::preserving; + } + + public function transparency(): Transparency + { + return Transparency::transparent; + } + + public function materialization(): Materialization + { + return Materialization::streaming; + } + + public function redefines(): Redefined + { + return Redefined::none(); + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Node/DuplicateRow.php b/src/core/etl/src/Flow/ETL/Plan/Node/DuplicateRow.php new file mode 100644 index 0000000000..1dec4c5fbd --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Node/DuplicateRow.php @@ -0,0 +1,59 @@ + $entries + */ + public function __construct( + private Node $input, + public mixed $condition, + public array $entries, + ) {} + + /** + * @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->condition, $this->entries); + } + + 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(...array_map(static fn(WithEntry $entry): string => $entry->name, $this->entries)); + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Node/Filter.php b/src/core/etl/src/Flow/ETL/Plan/Node/Filter.php new file mode 100644 index 0000000000..ccea492d99 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Node/Filter.php @@ -0,0 +1,53 @@ + + */ + public function children(): array + { + return [$this->input]; + } + + public function withChildren(array $children): self + { + return $children[0] === $this->input ? $this : new self($children[0], $this->function); + } + + public function rowCount(): RowCount + { + return RowCount::reducing; + } + + public function transparency(): Transparency + { + return Transparency::transparent; + } + + public function materialization(): Materialization + { + return Materialization::streaming; + } + + public function redefines(): Redefined + { + return Redefined::none(); + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Node/Join.php b/src/core/etl/src/Flow/ETL/Plan/Node/Join.php new file mode 100644 index 0000000000..f2bf6fc7f1 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Node/Join.php @@ -0,0 +1,80 @@ +right = + $right instanceof Result || $right instanceof Outputs + ? $right + : throw InvalidLogicException::joinSideIsNotAPlanRoot($right::class); + } + + /** + * @return list + */ + public function children(): array + { + return [$this->input, $this->right]; + } + + public function withChildren(array $children): self + { + if ($children[0] === $this->input && $children[1] === $this->right) { + return $this; + } + + return new self($children[0], $children[1], $this->on, $this->type, $this->algorithm); + } + + public function right(): Result|Outputs + { + return $this->right; + } + + public function rowCount(): RowCount + { + return RowCount::unknown; + } + + public function transparency(): Transparency + { + return Transparency::opaque; + } + + public function materialization(): Materialization + { + return Materialization::blocking; + } + + public function redefines(): Redefined + { + return Redefined::unknown(); + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Node/JoinEach.php b/src/core/etl/src/Flow/ETL/Plan/Node/JoinEach.php new file mode 100644 index 0000000000..1c25b08627 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Node/JoinEach.php @@ -0,0 +1,60 @@ + + */ + public function children(): array + { + return [$this->input]; + } + + public function withChildren(array $children): self + { + return $children[0] === $this->input ? $this : new self($children[0], $this->factory, $this->on, $this->type); + } + + public function rowCount(): RowCount + { + return RowCount::unknown; + } + + public function transparency(): Transparency + { + return Transparency::opaque; + } + + public function materialization(): Materialization + { + return Materialization::streaming; + } + + public function redefines(): Redefined + { + return Redefined::unknown(); + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Node/JoinsFrame.php b/src/core/etl/src/Flow/ETL/Plan/Node/JoinsFrame.php new file mode 100644 index 0000000000..5be18f0b96 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Node/JoinsFrame.php @@ -0,0 +1,15 @@ +limit <= 0) { + throw new InvalidArgumentException("Limit can't be lower or equal zero, given: " . $this->limit); + } + } + + /** + * @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->limit); + } + + public function rowCount(): RowCount + { + return RowCount::reducing; + } + + public function transparency(): Transparency + { + return Transparency::transparent; + } + + public function materialization(): Materialization + { + return Materialization::streaming; + } + + public function redefines(): Redefined + { + return Redefined::none(); + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Node/Offset.php b/src/core/etl/src/Flow/ETL/Plan/Node/Offset.php new file mode 100644 index 0000000000..5aa6d091d5 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Node/Offset.php @@ -0,0 +1,64 @@ + $offset + * + * @throws InvalidArgumentException + */ + public function __construct( + private Node $input, + public int $offset, + ) { + // @mago-ignore analysis:invalid-operand + // @mago-ignore analysis:impossible-condition,redundant-comparison + if ($this->offset < 0) { + throw new InvalidArgumentException('Offset must be greater than or equal to 0, given: ' . $this->offset); + } + } + + /** + * @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->offset); + } + + public function rowCount(): RowCount + { + return RowCount::reducing; + } + + public function transparency(): Transparency + { + return Transparency::transparent; + } + + public function materialization(): Materialization + { + return Materialization::streaming; + } + + public function redefines(): Redefined + { + return Redefined::none(); + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Node/Outputs.php b/src/core/etl/src/Flow/ETL/Plan/Node/Outputs.php new file mode 100644 index 0000000000..d979769da6 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Node/Outputs.php @@ -0,0 +1,99 @@ + + */ + private array $consumers; + + public function __construct(Result|Transaction|Write ...$consumers) + { + if (count($consumers) < 2) { + throw InvalidLogicException::because('Outputs needs two or more consumers'); + } + + if ($consumers[0] instanceof Transaction) { + throw InvalidLogicException::firstConsumerIsATransaction(); + } + + $this->consumers = array_values($consumers); + } + + /** + * @return non-empty-list + */ + public function children(): array + { + return $this->consumers; + } + + public function sinks(): Sinks + { + $sinks = []; + + foreach ($this->consumers as $consumer) { + if ($consumer instanceof Write || $consumer instanceof Transaction) { + $sinks[] = $consumer; + } + } + + return new Sinks(...$sinks); + } + + public function withChildren(array $children): self + { + if ($children === $this->consumers) { + return $this; + } + + $consumers = []; + + foreach ($children as $child) { + $consumers[] = + $child instanceof Result || $child instanceof Write || $child instanceof Transaction + ? $child + : throw InvalidLogicException::consumerRewritten($child::class); + } + + return new self(...$consumers); + } + + public function rowCount(): RowCount + { + return RowCount::preserving; + } + + public function transparency(): Transparency + { + return Transparency::opaque; + } + + public function materialization(): Materialization + { + return Materialization::streaming; + } + + public function redefines(): Redefined + { + return Redefined::none(); + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Node/Read.php b/src/core/etl/src/Flow/ETL/Plan/Node/Read.php new file mode 100644 index 0000000000..f94adb446e --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Node/Read.php @@ -0,0 +1,122 @@ + $limit the pushed limit, handed to Extractor::extract() when the plan runs + * @param Filter $pathFilter the pushed partition filter, handed to FileExtractor::extract() when the plan runs + */ + public function __construct( + private Extractor $extractor, + private ?int $limit = null, + private Filter $pathFilter = new OnlyFiles(), + ) {} + + public function extractor(): Extractor + { + return $this->extractor; + } + + /** + * @return null|int<1, max> + */ + public function limit(): ?int + { + return $this->limit; + } + + public function pathFilter(): Filter + { + return $this->pathFilter; + } + + public function withPathFilter(Filter $filter): self + { + return new self( + $this->extractor, + $this->limit, + $this->pathFilter instanceof Filters + ? $this->pathFilter->add($filter) + : new Filters($this->pathFilter, $filter), + ); + } + + /** + * Narrowing only: a second push may lower the limit, never raise it. + * + * @throws InvalidArgumentException when $limit is not greater than 0 + */ + public function withLimit(int $limit): self + { + if ($limit <= 0) { + throw new InvalidArgumentException('Limit must be greater than 0'); + } + + return new self( + $this->extractor, + $this->limit === null ? $limit : min($this->limit, $limit), + $this->pathFilter, + ); + } + + /** + * @return list + */ + public function children(): array + { + return []; + } + + public function withChildren(array $children): self + { + return $this; + } + + /** + * @throws SchemaNotDerivableException + */ + public function schema(): Schema + { + return $this->extractor->schema(); + } + + public function rowCount(): RowCount + { + return RowCount::source; + } + + public function transparency(): Transparency + { + return Transparency::transparent; + } + + public function materialization(): Materialization + { + return Materialization::streaming; + } + + public function redefines(): Redefined + { + return Redefined::none(); + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Node/Rename.php b/src/core/etl/src/Flow/ETL/Plan/Node/Rename.php new file mode 100644 index 0000000000..c3f29e3ee8 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Node/Rename.php @@ -0,0 +1,53 @@ + + */ + public function children(): array + { + return [$this->input]; + } + + public function withChildren(array $children): self + { + return $children[0] === $this->input ? $this : new self($children[0], $this->from, $this->to); + } + + public function rowCount(): RowCount + { + return RowCount::preserving; + } + + public function transparency(): Transparency + { + return Transparency::transparent; + } + + public function materialization(): Materialization + { + return Materialization::streaming; + } + + public function redefines(): Redefined + { + return Redefined::alias($this->to, $this->from); + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Node/RenameEach.php b/src/core/etl/src/Flow/ETL/Plan/Node/RenameEach.php new file mode 100644 index 0000000000..431dc66018 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Node/RenameEach.php @@ -0,0 +1,63 @@ + $strategies + * + * @throws InvalidArgumentException + */ + public function __construct( + private Node $input, + public array $strategies, + ) { + if ($this->strategies === []) { + throw new InvalidArgumentException('At least one strategy must be provided.'); + } + } + + /** + * @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->strategies); + } + + public function rowCount(): RowCount + { + return RowCount::preserving; + } + + public function transparency(): Transparency + { + return Transparency::transparent; + } + + public function materialization(): Materialization + { + return Materialization::streaming; + } + + public function redefines(): Redefined + { + return Redefined::unknown(); + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Node/Repartition.php b/src/core/etl/src/Flow/ETL/Plan/Node/Repartition.php new file mode 100644 index 0000000000..caf6100353 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Node/Repartition.php @@ -0,0 +1,56 @@ + + */ + public function children(): array + { + return [$this->input]; + } + + public function withChildren(array $children): self + { + return $children[0] === $this->input ? $this : new self($children[0], $this->by); + } + + public function rowCount(): RowCount + { + return RowCount::preserving; + } + + public function transparency(): Transparency + { + return Transparency::opaque; + } + + public function materialization(): Materialization + { + return Materialization::blocking; + } + + public function redefines(): Redefined + { + return Redefined::none(); + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Node/Result.php b/src/core/etl/src/Flow/ETL/Plan/Node/Result.php new file mode 100644 index 0000000000..80f7d5250b --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Node/Result.php @@ -0,0 +1,55 @@ + + */ + public function children(): array + { + return [$this->input]; + } + + public function withChildren(array $children): self + { + return $children[0] === $this->input ? $this : new self($children[0]); + } + + public function rowCount(): RowCount + { + return RowCount::preserving; + } + + public function transparency(): Transparency + { + return Transparency::transparent; + } + + public function materialization(): Materialization + { + return Materialization::streaming; + } + + public function redefines(): Redefined + { + return Redefined::none(); + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Node/Select.php b/src/core/etl/src/Flow/ETL/Plan/Node/Select.php new file mode 100644 index 0000000000..0221ceca07 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Node/Select.php @@ -0,0 +1,56 @@ + $entries + */ + public function __construct( + private Node $input, + public array $entries, + ) {} + + /** + * @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->entries); + } + + public function rowCount(): RowCount + { + return RowCount::preserving; + } + + public function transparency(): Transparency + { + return Transparency::transparent; + } + + public function materialization(): Materialization + { + return Materialization::streaming; + } + + public function redefines(): Redefined + { + return Redefined::none(); + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Node/Sort.php b/src/core/etl/src/Flow/ETL/Plan/Node/Sort.php new file mode 100644 index 0000000000..e06da668cf --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Node/Sort.php @@ -0,0 +1,58 @@ + + */ + public function children(): array + { + return [$this->input]; + } + + public function withChildren(array $children): self + { + return $children[0] === $this->input ? $this : new self($children[0], $this->refs, $this->algorithm); + } + + public function rowCount(): RowCount + { + return RowCount::preserving; + } + + public function transparency(): Transparency + { + return Transparency::opaque; + } + + public function materialization(): Materialization + { + return Materialization::blocking; + } + + public function redefines(): Redefined + { + return Redefined::none(); + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Node/TopN.php b/src/core/etl/src/Flow/ETL/Plan/Node/TopN.php new file mode 100644 index 0000000000..f54dee43a5 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Node/TopN.php @@ -0,0 +1,66 @@ +limit < 1) { + throw new InvalidArgumentException('TopN limit must be greater than 0, given: ' . $this->limit); + } + } + + /** + * @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->refs, $this->limit); + } + + public function rowCount(): RowCount + { + return RowCount::reducing; + } + + public function transparency(): Transparency + { + return Transparency::opaque; + } + + public function materialization(): Materialization + { + return Materialization::blocking; + } + + public function redefines(): Redefined + { + return Redefined::none(); + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Node/Transaction.php b/src/core/etl/src/Flow/ETL/Plan/Node/Transaction.php new file mode 100644 index 0000000000..50ad78a6c9 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Node/Transaction.php @@ -0,0 +1,79 @@ + + */ + private array $sinks; + + public function __construct( + public FlowTransaction $transaction, + Write ...$sinks, + ) { + if ($sinks === []) { + throw new InvalidArgumentException('At least one loader must be provided'); + } + + $this->sinks = array_values($sinks); + } + + /** + * @return list the sibling ROOTS this transaction commits together - never a row input + */ + public function children(): array + { + return $this->sinks; + } + + public function withChildren(array $children): self + { + $writes = []; + + foreach ($children as $child) { + $writes[] = $child instanceof Write + ? $child + : throw InvalidLogicException::sinkRootRewritten($child::class); + } + + return $writes === $this->sinks ? $this : new self($this->transaction, ...$writes); + } + + public function rowCount(): RowCount + { + return RowCount::preserving; + } + + public function transparency(): Transparency + { + return Transparency::opaque; + } + + public function materialization(): Materialization + { + return Materialization::streaming; + } + + public function redefines(): Redefined + { + return Redefined::none(); + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Node/Transform.php b/src/core/etl/src/Flow/ETL/Plan/Node/Transform.php new file mode 100644 index 0000000000..d3ef8e7537 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Node/Transform.php @@ -0,0 +1,57 @@ + + */ + public function children(): array + { + return [$this->input]; + } + + public function withChildren(array $children): self + { + return $children[0] === $this->input ? $this : new self($children[0], $this->transformer); + } + + public function rowCount(): RowCount + { + return RowCount::unknown; + } + + public function transparency(): Transparency + { + return Transparency::opaque; + } + + public function materialization(): Materialization + { + return Materialization::streaming; + } + + public function redefines(): Redefined + { + return Redefined::unknown(); + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Node/Until.php b/src/core/etl/src/Flow/ETL/Plan/Node/Until.php new file mode 100644 index 0000000000..dc95c39e04 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Node/Until.php @@ -0,0 +1,53 @@ + + */ + public function children(): array + { + return [$this->input]; + } + + public function withChildren(array $children): self + { + return $children[0] === $this->input ? $this : new self($children[0], $this->function); + } + + public function rowCount(): RowCount + { + return RowCount::reducing; + } + + public function transparency(): Transparency + { + return Transparency::transparent; + } + + public function materialization(): Materialization + { + return Materialization::streaming; + } + + public function redefines(): Redefined + { + return Redefined::none(); + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Node/Validate.php b/src/core/etl/src/Flow/ETL/Plan/Node/Validate.php new file mode 100644 index 0000000000..6727fa654e --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Node/Validate.php @@ -0,0 +1,58 @@ + + */ + public function children(): array + { + return [$this->input]; + } + + public function withChildren(array $children): self + { + return $children[0] === $this->input ? $this : new self($children[0], $this->schema, $this->validator); + } + + public function rowCount(): RowCount + { + return RowCount::preserving; + } + + public function transparency(): Transparency + { + return Transparency::opaque; + } + + public function materialization(): Materialization + { + return Materialization::streaming; + } + + public function redefines(): Redefined + { + return Redefined::none(); + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Node/WindowColumn.php b/src/core/etl/src/Flow/ETL/Plan/Node/WindowColumn.php new file mode 100644 index 0000000000..7da21329e2 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Node/WindowColumn.php @@ -0,0 +1,66 @@ +|string $entry + */ + public function __construct( + private Node $input, + public string|Definition $entry, + public WindowFunction $function, + ) {} + + /** + * @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); + } + + public function rowCount(): RowCount + { + return RowCount::preserving; + } + + public function transparency(): Transparency + { + return Transparency::opaque; + } + + public function materialization(): Materialization + { + return Materialization::blocking; + } + + 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 new file mode 100644 index 0000000000..45714d3dbb --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Node/WithColumn.php @@ -0,0 +1,73 @@ +|string $entry + */ + 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 + */ + 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); + } + + public function rowCount(): RowCount + { + return $this->rowCount; + } + + public function transparency(): Transparency + { + return Transparency::transparent; + } + + public function materialization(): Materialization + { + return Materialization::streaming; + } + + public function redefines(): Redefined + { + // only a bare column reference under a plain name: a Definition entry may cast the value + return is_string($this->entry) && $this->function instanceof UnresolvedReference + ? Redefined::alias($this->name(), $this->function->to()) + : 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/Write.php b/src/core/etl/src/Flow/ETL/Plan/Node/Write.php new file mode 100644 index 0000000000..d01faf6fbf --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Node/Write.php @@ -0,0 +1,56 @@ + + */ + public function children(): array + { + return [$this->input]; + } + + public function withChildren(array $children): self + { + return $children[0] === $this->input ? $this : new self($children[0], $this->loader); + } + + public function rowCount(): RowCount + { + return RowCount::preserving; + } + + public function transparency(): Transparency + { + return Transparency::opaque; + } + + public function materialization(): Materialization + { + return Materialization::streaming; + } + + public function redefines(): Redefined + { + return Redefined::none(); + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Redefined.php b/src/core/etl/src/Flow/ETL/Plan/Redefined.php new file mode 100644 index 0000000000..b64220a352 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Redefined.php @@ -0,0 +1,62 @@ + $names + * @param array $aliases a redefined name => the column below the node it only renames + */ + private function __construct( + public bool $unknown, + public array $names, + private array $aliases, + ) {} + + public static function none(): self + { + return new self(false, [], []); + } + + public static function names(string ...$names): self + { + return new self(false, array_values($names), []); + } + + /** + * $name holds exactly the values of $below: a reference to $name above the node is a reference to $below + * under it. + */ + public static function alias(string $name, string $below): self + { + return new self(false, [$name], [$name => $below]); + } + + /** + * The node cannot name its columns before a schema is bound (RenameEach): every name is redefined. + */ + public static function unknown(): self + { + return new self(true, [], []); + } + + public function defines(string $name): bool + { + return $this->unknown || in_array($name, $this->names, true); + } + + /** + * The column under the node that $name above it renames, or null when $name is not a plain alias. + */ + public function aliasOf(string $name): ?string + { + return array_key_exists($name, $this->aliases) ? $this->aliases[$name] : null; + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/ReplaceLeaf.php b/src/core/etl/src/Flow/ETL/Plan/ReplaceLeaf.php new file mode 100644 index 0000000000..36f49a146d --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/ReplaceLeaf.php @@ -0,0 +1,18 @@ +target ? $this->replacement : $node; + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Rewrite.php b/src/core/etl/src/Flow/ETL/Plan/Rewrite.php new file mode 100644 index 0000000000..5b60893224 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Rewrite.php @@ -0,0 +1,16 @@ + + */ +final readonly class Sinks implements IteratorAggregate +{ + /** + * @var list + */ + private array $sinks; + + public function __construct(Node\Transaction|Node\Write ...$sinks) + { + $this->sinks = array_values($sinks); + } + + /** + * @return list + */ + public function all(): array + { + return $this->sinks; + } + + /** + * @return ArrayIterator + */ + public function getIterator(): ArrayIterator + { + return new ArrayIterator($this->sinks); + } + + public function merge(self $sinks): self + { + return new self(...$this->sinks, ...$sinks->sinks); + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Stage.php b/src/core/etl/src/Flow/ETL/Plan/Stage.php new file mode 100644 index 0000000000..de4ff0c503 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Stage.php @@ -0,0 +1,18 @@ + + */ + private SplObjectStorage $memo; + + public function __construct() + { + /** @var SplObjectStorage $memo */ + $memo = new SplObjectStorage(); + $this->memo = $memo; + } + + public function of(Node $node, Rewrite $rewrite): Node + { + if ($this->memo->offsetExists($node)) { + return $this->memo[$node]; + } + + $children = $node->children(); + + // a joined frame may share nodes with this plan, and a rewrite of this plan must not change what that frame reads + foreach ($node instanceof Node\JoinsFrame ? [0] : array_keys($children) as $i) { + $children[$i] = $this->of($children[$i], $rewrite); + } + + return $this->memo[$node] = $rewrite->of($node->withChildren($children)); + } +} diff --git a/src/core/etl/src/Flow/ETL/Plan/Transparency.php b/src/core/etl/src/Flow/ETL/Plan/Transparency.php new file mode 100644 index 0000000000..f6ee015772 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Plan/Transparency.php @@ -0,0 +1,11 @@ +all(); + + $consumers = match ($this) { + self::rows => [new Node\Result($root), ...$all], + self::run => ($all[0] ?? null) instanceof Node\Write && $all[0]->children()[0] === $root + ? $all + : [new Node\Result($root), ...$all], + }; + + return new LogicalPlan(count($consumers) === 1 ? $consumers[0] : new Node\Outputs(...$consumers)); + } +} diff --git a/src/core/etl/src/Flow/ETL/Planner.php b/src/core/etl/src/Flow/ETL/Planner.php new file mode 100644 index 0000000000..29141168ef --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Planner.php @@ -0,0 +1,103 @@ +optimizer->optimize($logical, $context); + + $this->node($logical->root, $context, $planned); + + return (new PipelineSplit())->of($logical, $planned, $context); + } catch (Throwable $e) { + // a failure is never reported without a start + $context->telemetry()->dataFrameStarted($context); + $context->telemetry()->dataFrameFailed($context, $e); + + throw $e; + } + } + + /** + * Plans $node and everything under it, each node once by identity: translated to steps, then bound to the + * schema of its input. A prefix several consumers share is planned once; a joined frame is planned apart. + */ + public function node(Node $node, FlowContext $context, PlannedNodes $planned): PlannedNode + { + if ($planned->has($node)) { + return $planned->of($node); + } + + $inputs = []; + + foreach ($node instanceof Node\JoinsFrame ? [$node->children()[0]] : $node->children() as $child) { + $inputs[] = $this->node($child, $context, $planned); + } + + $frames = []; + + if ($node instanceof Node\JoinsFrame) { + // the joined frame runs as a pipeline of its own, so a node it shares with this plan needs its own steps + $right = new PlannedNodes(); + $this->node($node->right(), $context, $right); + $frames[] = (new PipelineSplit())->of(new LogicalPlan($node->right()), $right, $context); + } + + $steps = NodeTranslator::toSteps($node, $context, $frames); + $bound = []; + $schema = null; + + try { + $schema = match (true) { + $node instanceof Node\Read => $node->schema(), + default => $inputs[0]->schema ?? null, + }; + + if ($schema !== null) { + foreach ($steps as $step) { + if ($step instanceof Loader) { + $bound[] = $step; + + continue; + } + + $boundStep = $step->bind($schema); + $schema = $boundStep->output; + $bound[] = $boundStep->step; + } + } + } catch (SchemaNotDerivableException $refusal) { + $planned->refuse($refusal); + $schema = null; + $bound = $steps; + } + + return $planned->add($node, new PlannedNode($steps, $bound, $schema)); + } +} diff --git a/src/core/etl/src/Flow/ETL/Planner/NodeTranslator.php b/src/core/etl/src/Flow/ETL/Planner/NodeTranslator.php new file mode 100644 index 0000000000..be3d32668e --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Planner/NodeTranslator.php @@ -0,0 +1,121 @@ + $frames the physical plan of a join's right side; [] for any other node + * + * @throws InvalidLogicException when no translation exists for the node + * + * @return list in execution order; [] for a node that adds no step of its own + */ + public static function toSteps(Node $node, FlowContext $context, array $frames): array + { + return match (true) { + $node instanceof Node\Read, + $node instanceof Node\Result, + $node instanceof Node\Outputs, + $node instanceof Node\Transaction, + => [], + $node instanceof Node\Aggregate => GroupBySteps::of($node->groupBy, $context->config, $node->algorithm), + $node instanceof Node\BatchBy => [new BatchingByProcessor($node->column, $node->minSize)], + $node instanceof Node\Batch => [new BatchingProcessor($node->size)], + $node instanceof Node\Cache => $node->batchSize + ? [new BatchingProcessor($node->batchSize), new CachingProcessor($node->id, $node->cache)] + : [new CachingProcessor($node->id, $node->cache)], + $node instanceof Node\Collect => [new CollectingProcessor()], + $node instanceof Node\CollectRefs => [new CollectReferencesTransformer($node->references)], + $node instanceof Node\Constrain => [new ConstrainedProcessor($node->constraints)], + $node instanceof Node\CrossJoin => [new CrossJoinRowsTransformer( + $frames[0], + $context->config->executor(), + $node->prefix, + )], + $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\DuplicateRow => [new DuplicateRowTransformer($node->condition, ...$node->entries)], + $node instanceof Node\Filter => [new ScalarFunctionFilterTransformer($node->function)], + $node instanceof Node\JoinEach => match ($node->type) { + JoinType::left => [JoinEachRowsTransformer::left($node->factory, $node->on)], + JoinType::left_anti => [JoinEachRowsTransformer::leftAnti($node->factory, $node->on)], + JoinType::right => [JoinEachRowsTransformer::right($node->factory, $node->on)], + JoinType::inner => [JoinEachRowsTransformer::inner($node->factory, $node->on)], + }, + $node instanceof Node\Join => JoinSteps::of( + $frames[0], + $node->on, + $node->type, + $context->config, + $node->algorithm, + ), + $node instanceof Node\Limit => [new LimitTransformer($node->limit)], + $node instanceof Node\Offset => [new OffsetProcessor($node->offset)], + $node instanceof Node\RenameEach => [new RenameEachEntryTransformer(...$node->strategies)], + $node instanceof Node\Rename => [new RenameEntryTransformer($node->from, $node->to)], + $node instanceof Node\Repartition => RepartitionSteps::of($node->by, $context->config), + $node instanceof Node\Select => [new SelectEntriesTransformer(...$node->entries)], + $node instanceof Node\Sort => SortSteps::of($node->refs, $context->config, $node->algorithm), + $node instanceof Node\TopN => [new TopNProcessor($node->refs, $node->limit)], + $node instanceof Node\Transform => [ + $node->transformer instanceof Stateful ? $node->transformer->fresh() : $node->transformer, + ], + $node instanceof Node\Until => [new UntilTransformer($node->function)], + $node instanceof Node\Validate => [new SchemaValidationLoader($node->schema, $node->validator)], + $node instanceof Node\WindowColumn => $node->function->window()->partitions()->count() + ? [ + ...RepartitionSteps::of($node->function->window()->partitions(), $context->config), + new WindowProcessor($node->entry, $node->function), + ] + : [new CollectingProcessor(), new WindowProcessor($node->entry, $node->function)], + $node instanceof Node\WithColumn => [new ScalarFunctionTransformer($node->entry, $node->function)], + $node instanceof Node\Write => [$node->loader], + default => throw InvalidLogicException::nodeNotTranslatable($node::class), + }; + } +} diff --git a/src/core/etl/src/Flow/ETL/Planner/PipelineSplit.php b/src/core/etl/src/Flow/ETL/Planner/PipelineSplit.php new file mode 100644 index 0000000000..55f761b675 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Planner/PipelineSplit.php @@ -0,0 +1,92 @@ +root; + $top = $logical->spine(); + $spine = []; + /** @var SplObjectStorage $onSpine */ + $onSpine = new SplObjectStorage(); + + for ($node = $top;; $node = $node->children()[0]) { + $spine[] = $node; + $onSpine[$node] = $node; + + if ($node->children() === []) { + break; + } + + if ($node instanceof Node\Outputs) { + $node = $node->children()[0]; + } + } + + $spine = array_reverse($spine); + $read = $logical->source(); + $input = null; + $segments = new Segments($read->extractor()); + $limit = $read->limit(); + $pathFilter = $read->pathFilter(); + + $attachment = new SinkAttachment($planned, $context); + $remembered = $attachment->attach($logical->sinksOnSpine(), $onSpine); + $id = $attachment->next(); + + foreach ($spine as $node) { + foreach ($planned->steps($node) as $step) { + $segments->add($step); + } + + foreach ($remembered->offsetExists($node) ? $remembered[$node] : [] as $step) { + $segments->add($step); + } + + if ($node->materialization() === Materialization::blocking && $node !== $top) { + $input = new Pipeline($id++, $segments, $context, $input, $limit, $pathFilter); + $segments = new Segments(); + $limit = null; + $pathFilter = new OnlyFiles(); + } + } + + $pipeline = new Pipeline($id, $segments, $context, $input, $limit, $pathFilter); + $refusal = $planned->refusal(); + + return $refusal === null + ? new Described( + $pipeline, + $planned->of($root)->schema ?? throw InvalidLogicException::because( + 'A node without a schema requires a plan-wide refusal', + ), + ) + : new Raw($pipeline, $refusal, $planned->of($root)->schema); + } +} diff --git a/src/core/etl/src/Flow/ETL/Planner/PlannedNode.php b/src/core/etl/src/Flow/ETL/Planner/PlannedNode.php new file mode 100644 index 0000000000..59ea2d29fe --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Planner/PlannedNode.php @@ -0,0 +1,26 @@ + $steps as translated + * @param list $bound the same steps after bind(); identical to $steps when this node + * refused, empty when its input already had no schema - nothing reads + * it once the plan refused + * @param null|Schema $schema this node's output schema; null when the plan refused at or below it + */ + public function __construct( + public array $steps, + public array $bound, + public ?Schema $schema, + ) {} +} diff --git a/src/core/etl/src/Flow/ETL/Planner/PlannedNodes.php b/src/core/etl/src/Flow/ETL/Planner/PlannedNodes.php new file mode 100644 index 0000000000..6a65558f2c --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Planner/PlannedNodes.php @@ -0,0 +1,87 @@ + + */ + private SplObjectStorage $nodes; + + private ?SchemaNotDerivableException $refusal = null; + + public function __construct() + { + /** @var SplObjectStorage $nodes */ + $nodes = new SplObjectStorage(); + $this->nodes = $nodes; + } + + public function add(Node $node, PlannedNode $planned): PlannedNode + { + $this->nodes[$node] = $planned; + + return $planned; + } + + public function has(Node $node): bool + { + return $this->nodes->offsetExists($node); + } + + /** + * @throws InvalidLogicException when $node was never planned + */ + public function of(Node $node): PlannedNode + { + return $this->nodes->offsetExists($node) + ? $this->nodes[$node] + : throw InvalidLogicException::because('Node %s was never planned', $node::class); + } + + /** + * Keeps the first refusal. + */ + public function refuse(SchemaNotDerivableException $refusal): void + { + $this->refusal ??= $refusal; + } + + /** + * Non-null means the WHOLE plan runs raw - all or nothing. + */ + public function refusal(): ?SchemaNotDerivableException + { + return $this->refusal; + } + + /** + * The steps a pipeline runs for $node: the bound ones, or the raw ones when any node of the plan refused a + * schema - a refusal is plan-wide, so every node answers the same way. + * + * @throws InvalidLogicException when $node was never planned + * + * @return list + */ + public function steps(Node $node): array + { + $planned = $this->of($node); + + return $this->refusal === null ? $planned->bound : $planned->steps; + } +} diff --git a/src/core/etl/src/Flow/ETL/Planner/SinkAttachment.php b/src/core/etl/src/Flow/ETL/Planner/SinkAttachment.php new file mode 100644 index 0000000000..a1c09387f0 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Planner/SinkAttachment.php @@ -0,0 +1,295 @@ +, transaction: null|Transaction} + */ +final class SinkAttachment +{ + private int $next = 0; + + private readonly SinkFeedFactory $feed; + + public function __construct( + private readonly PlannedNodes $planned, + private readonly FlowContext $context, + ) { + $this->feed = new SinkFeedFactory($planned, $context); + } + + /** + * Every sink root attached at the spine node its chain meets, as the Loader steps that node's segment gains. + * Side pipelines take the ids first; next() is where the spine's own cuts continue. + * + * @param SplObjectStorage $onSpine + * + * @throws InvalidLogicException when a sink shares no node with the spine, a Write does not translate to a Loader, + * or the sinks of one transaction attach to different nodes + * + * @return SplObjectStorage> + */ + public function attach(Sinks $sinks, SplObjectStorage $onSpine): SplObjectStorage + { + /** @var SplObjectStorage> $attached */ + $attached = new SplObjectStorage(); + + foreach ($sinks as $sink) { + $at = null; + + foreach ($sink instanceof Transaction ? $sink->children() : [$sink] as $write) { + $chain = $this->chain($write, $onSpine); + $bottom = $chain[array_key_last($chain)]->children()[0]; + + if ($at !== null && $bottom !== $at) { + throw InvalidLogicException::because('Every sink of one transaction must attach to the same node'); + } + + $at = $bottom; + $loader = $this->planned->steps($write)[0] ?? null; + + if (!$loader instanceof Loader) { + throw InvalidLogicException::because( + 'A Write must translate to a Loader, %s given', + get_debug_type($loader), + ); + } + + $attached[$bottom] = [ + ...($attached->offsetExists($bottom) ? $attached[$bottom] : []), + [ + 'write' => $write, + 'loader' => $loader, + 'path' => array_reverse(array_slice($chain, 1)), + 'transaction' => $sink instanceof Transaction ? $sink : null, + ], + ]; + } + } + + /** @var SplObjectStorage> $remembered */ + $remembered = new SplObjectStorage(); + + foreach ($attached as $at) { + $remembered[$at] = $this->consumers($attached[$at], $at, $this->context->errorHandler()); + } + + return $remembered; + } + + public function next(): int + { + return $this->next; + } + + /** + * $write first, then every node below it, stopping BEFORE the first node on the spine - so a bare Write sitting + * directly on a spine node is exactly [$write], and the node it attaches to is never part of its chain. + * + * @param SplObjectStorage $onSpine + * + * @throws InvalidLogicException when the chain ends without reaching the spine + * + * @return non-empty-list + */ + public function chain(Write $write, SplObjectStorage $onSpine): array + { + $chain = [$write]; + + for ($node = $write->children()[0]; !$onSpine->offsetExists($node); $node = $node->children()[0]) { + $chain[] = $node; + + if ($node->children() === []) { + throw InvalidLogicException::sinkNotOnSpine($write->loader::class); + } + } + + return $chain; + } + + /** + * A node several sinks share feeds them ONCE - it is the point their rows fan out - and a transaction attaches + * where its children part, so a node they all share runs before it opens. + * + * @param non-empty-list $leaves the sinks hanging off $host, each with the nodes between $host and its Write + * + * @throws InvalidLogicException when a sink outside a transaction shares a node with one of its children + * + * @return list + */ + public function consumers(array $leaves, Node $host, ErrorHandler $handler): array + { + /** @var SplObjectStorage $position */ + $position = new SplObjectStorage(); + /** @var list> $groups */ + $groups = []; + /** @var SplObjectStorage $members */ + $members = new SplObjectStorage(); + + foreach ($leaves as $leaf) { + $first = $leaf['path'][0] ?? $leaf['write']; + + if ($position->offsetExists($first)) { + $groups[$position[$first]][] = $leaf; + } else { + $position[$first] = count($groups); + $groups[] = [$leaf]; + } + + $transaction = $leaf['transaction']; + + if ($transaction !== null) { + $members[$transaction] = ($members->offsetExists($transaction) ? $members[$transaction] : 0) + 1; + } + } + + /** @var SplObjectStorage $opensHere */ + $opensHere = new SplObjectStorage(); + + foreach ($groups as $group) { + /** @var SplObjectStorage $inGroup */ + $inGroup = new SplObjectStorage(); + + foreach ($group as $leaf) { + $transaction = $leaf['transaction']; + + if ($transaction !== null) { + $inGroup[$transaction] = ($inGroup->offsetExists($transaction) ? $inGroup[$transaction] : 0) + 1; + } + } + + foreach ($inGroup as $transaction) { + if (count($group) === 1 || $inGroup[$transaction] !== $members[$transaction]) { + $opensHere[$transaction] = $transaction; + } + } + } + + $steps = []; + /** @var SplObjectStorage $placed */ + $placed = new SplObjectStorage(); + + foreach ($groups as $group) { + $opening = null; + + foreach ($group as $leaf) { + if ($leaf['transaction'] !== null && $opensHere->offsetExists($leaf['transaction'])) { + $opening = $leaf['transaction']; + + break; + } + } + + if ($opening === null) { + $steps[] = $this->consumer($group, $host, $handler); + + continue; + } + + if ($placed->offsetExists($opening)) { + continue; + } + + $placed[$opening] = $opening; + $children = []; + + foreach ($groups as $candidate) { + $mine = []; + + foreach ($candidate as $leaf) { + if ($leaf['transaction'] === $opening) { + $mine[] = [...$leaf, 'transaction' => null]; + } + } + + if ($mine === []) { + continue; + } + + if (count($mine) !== count($candidate)) { + throw InvalidLogicException::because( + 'A sink outside a transaction cannot share a node with one of its children', + ); + } + + $children[] = $this->consumer($mine, $host, new ThrowError()); + } + + $steps[] = new TransactionalSinks($opening->transaction, $children); + } + + return $steps; + } + + /** + * @param non-empty-list $group sinks whose nodes above $host start with the same node + */ + public function consumer(array $group, Node $host, ErrorHandler $handler): Loader + { + if (count($group) === 1) { + $leaf = $group[0]; + + return ( + $leaf['path'] === [] + ? $leaf['loader'] + : $this->feed->of($leaf['path'], [$leaf['loader']], $host, new SinkOffers($handler), $this->next++) + ); + } + + $shared = [$group[0]['path'][0] ?? $group[0]['write']]; + + for ($depth = 1; array_key_exists($depth, $group[0]['path']); $depth++) { + $node = $group[0]['path'][$depth]; + + foreach ($group as $leaf) { + if (($leaf['path'][$depth] ?? null) !== $node) { + break 2; + } + } + + $shared[] = $node; + } + + $rest = []; + + foreach ($group as $leaf) { + $rest[] = [...$leaf, 'path' => array_slice($leaf['path'], count($shared))]; + } + + $sharedId = $this->next++; + $offers = new SinkOffers($handler); + + return $this->feed->of( + $shared, + $this->consumers($rest, $shared[array_key_last($shared)], $offers), + $host, + $offers, + $sharedId, + ); + } +} diff --git a/src/core/etl/src/Flow/ETL/Planner/SinkFeedFactory.php b/src/core/etl/src/Flow/ETL/Planner/SinkFeedFactory.php new file mode 100644 index 0000000000..1f0df0df46 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Planner/SinkFeedFactory.php @@ -0,0 +1,61 @@ + $nodes what runs before $tail, bottom-up + * @param list $tail + * @param SinkOffers $offers the feed's handler; nested feeds report through it, so a failure they offered is not + * offered again when it escapes this feed + */ + public function of(array $nodes, array $tail, Node $host, SinkOffers $offers, int $id): SinkFeed + { + $feed = new FeedExtractor($this->planned->of($host)->schema ?? new Schema()); + $segments = new Segments($feed); + + foreach ($nodes as $node) { + foreach ($this->planned->steps($node) as $step) { + $segments->add($step); + } + } + + foreach ($tail as $step) { + $segments->add($step); + } + + return new SinkFeed( + $feed, + new SinkRun( + new Pipeline($id, $segments, $this->context->withErrorHandler($offers)), + $this->context->config->executor(), + ), + $offers, + ...$tail, + ); + } +} diff --git a/src/core/etl/src/Flow/ETL/Processor.php b/src/core/etl/src/Flow/ETL/Processor.php index 3eb62126a4..45defcad02 100644 --- a/src/core/etl/src/Flow/ETL/Processor.php +++ b/src/core/etl/src/Flow/ETL/Processor.php @@ -5,7 +5,6 @@ namespace Flow\ETL; use Flow\ETL\Exception\DataDependentSchemaException; -use Flow\ETL\Pipeline\BoundStep; use Generator; /** @@ -14,8 +13,6 @@ * Unlike Transformer which operates on a single batch of Rows, a Processor receives * the entire upstream generator and produces a new generator. This allows operations * like sorting, grouping, and batching that need to accumulate data across batches. - * - * @internal */ interface Processor { diff --git a/src/core/etl/src/Flow/ETL/Processor/BatchingByProcessor.php b/src/core/etl/src/Flow/ETL/Processor/BatchingByProcessor.php index ea4ee9a9d1..3900d9a64c 100644 --- a/src/core/etl/src/Flow/ETL/Processor/BatchingByProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/BatchingByProcessor.php @@ -4,10 +4,10 @@ namespace Flow\ETL\Processor; +use Flow\ETL\BoundStep; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Extractor\Signal; use Flow\ETL\FlowContext; -use Flow\ETL\Pipeline\BoundStep; use Flow\ETL\Processor; use Flow\ETL\Row; use Flow\ETL\Row\Reference; @@ -22,8 +22,6 @@ * * Assumes data is pre-sorted by the batching column. When the column value changes, * a new batch is started. - * - * @internal */ final readonly class BatchingByProcessor implements Processor { @@ -33,8 +31,8 @@ * @throws InvalidArgumentException */ public function __construct( - private Reference $column, - private ?int $minSize = null, + public Reference $column, + public ?int $minSize = null, ) { // @mago-ignore analysis:invalid-operand,impossible-condition,redundant-comparison,redundant-logical-operation if ($this->minSize !== null && $this->minSize <= 0) { diff --git a/src/core/etl/src/Flow/ETL/Processor/BatchingProcessor.php b/src/core/etl/src/Flow/ETL/Processor/BatchingProcessor.php index cc96186e75..e9608210f7 100644 --- a/src/core/etl/src/Flow/ETL/Processor/BatchingProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/BatchingProcessor.php @@ -4,10 +4,10 @@ namespace Flow\ETL\Processor; +use Flow\ETL\BoundStep; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Extractor\Signal; use Flow\ETL\FlowContext; -use Flow\ETL\Pipeline\BoundStep; use Flow\ETL\Processor; use Flow\ETL\Row; use Flow\ETL\Rows; @@ -19,8 +19,6 @@ /** * Re-batches rows into fixed-size batches. - * - * @internal */ final readonly class BatchingProcessor implements Processor { @@ -30,7 +28,7 @@ * @throws InvalidArgumentException */ public function __construct( - private int $size, + public int $size, ) { // @mago-ignore analysis:invalid-operand,impossible-condition,redundant-comparison if ($this->size <= 0) { diff --git a/src/core/etl/src/Flow/ETL/Processor/BucketingProcessor.php b/src/core/etl/src/Flow/ETL/Processor/BucketingProcessor.php index c7257e6a94..0771eb56f5 100644 --- a/src/core/etl/src/Flow/ETL/Processor/BucketingProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/BucketingProcessor.php @@ -4,24 +4,21 @@ namespace Flow\ETL\Processor; +use Flow\ETL\BoundStep; use Flow\ETL\Bucketing\Bucket; use Flow\ETL\Bucketing\BucketingStrategy; use Flow\ETL\Bucketing\Buckets; use Flow\ETL\FlowContext; -use Flow\ETL\Pipeline\BoundStep; use Flow\ETL\Processor; use Flow\ETL\Rows; use Flow\ETL\Schema; use Generator; -/** - * @internal - */ final class BucketingProcessor implements Processor { public function __construct( - private readonly BucketingStrategy $strategy, - private readonly Buckets $buckets, + public readonly BucketingStrategy $strategy, + public readonly Buckets $buckets, ) {} /** diff --git a/src/core/etl/src/Flow/ETL/Processor/CachingProcessor.php b/src/core/etl/src/Flow/ETL/Processor/CachingProcessor.php index f32e5d6088..2b80da2cbe 100644 --- a/src/core/etl/src/Flow/ETL/Processor/CachingProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/CachingProcessor.php @@ -4,11 +4,11 @@ namespace Flow\ETL\Processor; +use Flow\ETL\BoundStep; use Flow\ETL\Cache; use Flow\ETL\Cache\CacheIndex; use Flow\ETL\Extractor\Signal; use Flow\ETL\FlowContext; -use Flow\ETL\Pipeline\BoundStep; use Flow\ETL\Processor; use Flow\ETL\Rows; use Flow\ETL\Schema; @@ -22,14 +22,12 @@ * * If a cache with the given id already exists, data passes through unchanged. * Otherwise, each batch is cached before being yielded. - * - * @internal */ final readonly class CachingProcessor implements Processor { public function __construct( - private ?string $id = null, - private ?Cache $cache = null, + public ?string $id = null, + public ?Cache $cache = null, ) {} /** diff --git a/src/core/etl/src/Flow/ETL/Processor/CollectingProcessor.php b/src/core/etl/src/Flow/ETL/Processor/CollectingProcessor.php index c84d486a5f..4c988fd0d9 100644 --- a/src/core/etl/src/Flow/ETL/Processor/CollectingProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/CollectingProcessor.php @@ -4,8 +4,8 @@ namespace Flow\ETL\Processor; +use Flow\ETL\BoundStep; use Flow\ETL\FlowContext; -use Flow\ETL\Pipeline\BoundStep; use Flow\ETL\Processor; use Flow\ETL\Rows; use Flow\ETL\Schema; @@ -17,13 +17,11 @@ * This processor consumes the entire input generator and yields * all rows as a single Rows batch. Use with caution on large datasets * as it loads everything into memory. - * - * @internal */ final readonly class CollectingProcessor implements Processor { public function __construct( - private ?Schema $declared = null, + public ?Schema $declared = null, ) {} public function bind(Schema $input): BoundStep diff --git a/src/core/etl/src/Flow/ETL/Processor/ConstrainedProcessor.php b/src/core/etl/src/Flow/ETL/Processor/ConstrainedProcessor.php index 9ee5fb2465..b820ec1bcb 100644 --- a/src/core/etl/src/Flow/ETL/Processor/ConstrainedProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/ConstrainedProcessor.php @@ -4,12 +4,12 @@ namespace Flow\ETL\Processor; +use Flow\ETL\BoundStep; use Flow\ETL\Constraint; use Flow\ETL\Exception\ConstraintViolationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Extractor\Signal; use Flow\ETL\FlowContext; -use Flow\ETL\Pipeline\BoundStep; use Flow\ETL\Processor; use Flow\ETL\Rows; use Flow\ETL\Schema; @@ -17,8 +17,6 @@ /** * Validates constraints on each row. - * - * @internal */ final class ConstrainedProcessor implements Processor { @@ -30,7 +28,7 @@ final class ConstrainedProcessor implements Processor * @throws InvalidArgumentException */ public function __construct( - private readonly array $constraints = [], + public readonly array $constraints = [], ) { foreach ($constraints as $constraint) { // @mago-ignore analysis:impossible-condition diff --git a/src/core/etl/src/Flow/ETL/Processor/GroupByAggregationProcessor.php b/src/core/etl/src/Flow/ETL/Processor/GroupByAggregationProcessor.php index e341894c7a..77d8b765f1 100644 --- a/src/core/etl/src/Flow/ETL/Processor/GroupByAggregationProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/GroupByAggregationProcessor.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Processor; +use Flow\ETL\BoundStep; use Flow\ETL\Bucketing\Buckets; use Flow\ETL\Bucketing\BucketShape; use Flow\ETL\Exception\InvalidArgumentException; @@ -13,7 +14,6 @@ use Flow\ETL\GroupBy\BucketAggregation; use Flow\ETL\GroupBy\GroupByShape; use Flow\ETL\GroupBy\GroupKey; -use Flow\ETL\Pipeline\BoundStep; use Flow\ETL\Processor; use Flow\ETL\Rows; use Flow\ETL\Schema; @@ -21,8 +21,6 @@ /** * Aggregates buckets spilled by BucketingProcessor, one bucket per incoming metadata Row. - * - * @internal */ final class GroupByAggregationProcessor implements Processor { @@ -36,9 +34,9 @@ final class GroupByAggregationProcessor implements Processor * @param int<1, max> $batchSize */ public function __construct( - private readonly GroupBy $groupBy, - private readonly Buckets $buckets, - private readonly int $batchSize = 1000, + public readonly GroupBy $groupBy, + public readonly Buckets $buckets, + public readonly int $batchSize = 1000, ) { // @mago-ignore analysis:invalid-operand // @mago-ignore analysis:impossible-condition,redundant-comparison diff --git a/src/core/etl/src/Flow/ETL/Processor/HashJoinProcessor.php b/src/core/etl/src/Flow/ETL/Processor/HashJoinProcessor.php index ae9b7789bd..8453c718f6 100644 --- a/src/core/etl/src/Flow/ETL/Processor/HashJoinProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/HashJoinProcessor.php @@ -4,18 +4,20 @@ namespace Flow\ETL\Processor; +use Flow\ETL\BoundStep; use Flow\ETL\Bucketing\Bucket; use Flow\ETL\Bucketing\Buckets; use Flow\ETL\Bucketing\HashBucketing; use Flow\ETL\Bucketing\NativeHasher; use Flow\ETL\Bucketing\ResidentBucketsStorage; use Flow\ETL\Bucketing\SingleBucketHasher; -use Flow\ETL\DataFrame; use Flow\ETL\Exception\DuplicatedEntriesException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\JoinException; use Flow\ETL\Exception\SchemaDefinitionNotUniqueException; use Flow\ETL\Exception\SchemaNotDerivableException; +use Flow\ETL\Executor; +use Flow\ETL\Executor\PhysicalPlan; use Flow\ETL\Extractor\Signal; use Flow\ETL\FlowContext; use Flow\ETL\Join\Expression; @@ -24,7 +26,6 @@ use Flow\ETL\Join\HashJoin\NullRowBuilder; use Flow\ETL\Join\Join; use Flow\ETL\Join\JoinShape; -use Flow\ETL\Pipeline\BoundStep; use Flow\ETL\Processor; use Flow\ETL\RandomValueGenerator; use Flow\ETL\Row\Reference; @@ -35,9 +36,6 @@ use function array_intersect_key; use function array_keys; -/** - * @internal - */ final class HashJoinProcessor implements Processor { /** @@ -53,14 +51,15 @@ final class HashJoinProcessor implements Processor * @param int<1, max> $batchSize */ public function __construct( - private readonly DataFrame $right, - private readonly Expression $expression, - private readonly Join $type, - private readonly Buckets $leftBuckets, - private readonly Buckets $rightBuckets, + public readonly PhysicalPlan $right, + private readonly Executor $executor, + public readonly Expression $expression, + public readonly Join $type, + public readonly Buckets $leftBuckets, + public readonly Buckets $rightBuckets, private readonly RandomValueGenerator $random, - private readonly int $bucketsCount = 64, - private readonly int $batchSize = 1000, + public readonly int $bucketsCount = 64, + public readonly int $batchSize = 1000, ) { // @mago-ignore analysis:invalid-operand // @mago-ignore analysis:impossible-condition,redundant-comparison @@ -81,6 +80,7 @@ public function bind(Schema $input): BoundStep $bound = new self( $this->right, + $this->executor, $this->expression, $this->type, $this->leftBuckets, @@ -125,7 +125,7 @@ public function process(Generator $rows, FlowContext $context): Generator try { $rightRows = $this->tap( - $this->right->get(), + $this->executor->executePipeline($this->right->root()), $rightSchema, // right rows with a null join key can never match, they only surface in right join output $equalityKeys !== null && $this->type !== Join::right ? $equalityKeys->rightRefs() : null, diff --git a/src/core/etl/src/Flow/ETL/Processor/MemorySortProcessor.php b/src/core/etl/src/Flow/ETL/Processor/MemorySortProcessor.php index 1bad2364da..ffbb7a23ae 100644 --- a/src/core/etl/src/Flow/ETL/Processor/MemorySortProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/MemorySortProcessor.php @@ -4,8 +4,8 @@ namespace Flow\ETL\Processor; +use Flow\ETL\BoundStep; use Flow\ETL\FlowContext; -use Flow\ETL\Pipeline\BoundStep; use Flow\ETL\Processor; use Flow\ETL\Row; use Flow\ETL\Row\References; @@ -18,13 +18,11 @@ /** * Buffers all rows and sorts them in memory. Registered by SortSteps when the sort algorithm is * memory_sort(). - * - * @internal */ final readonly class MemorySortProcessor implements Processor { public function __construct( - private References $refs, + public References $refs, private ?Schema $declared = null, ) {} diff --git a/src/core/etl/src/Flow/ETL/Processor/MergeSortProcessor.php b/src/core/etl/src/Flow/ETL/Processor/MergeSortProcessor.php index b723e1e88a..13931e45ae 100644 --- a/src/core/etl/src/Flow/ETL/Processor/MergeSortProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/MergeSortProcessor.php @@ -4,13 +4,13 @@ namespace Flow\ETL\Processor; +use Flow\ETL\BoundStep; use Flow\ETL\Bucketing\Bucket; use Flow\ETL\Bucketing\BucketRun; use Flow\ETL\Bucketing\Buckets; use Flow\ETL\Bucketing\BucketShape; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Pipeline\BoundStep; use Flow\ETL\Processor; use Flow\ETL\RandomValueGenerator; use Flow\ETL\Row\References; @@ -29,12 +29,12 @@ final class MergeSortProcessor implements Processor * @param int<1, max> $batchSize */ public function __construct( - private readonly References $refs, - private readonly Buckets $spill, - private readonly Buckets $merge, + public readonly References $refs, + public readonly Buckets $spill, + public readonly Buckets $merge, private readonly RandomValueGenerator $random, - private readonly int $mergeFanIn = 10, - private readonly int $batchSize = 1000, + public readonly int $mergeFanIn = 10, + public readonly int $batchSize = 1000, ) { // @mago-ignore analysis:invalid-operand // @mago-ignore analysis:impossible-condition,redundant-comparison diff --git a/src/core/etl/src/Flow/ETL/Processor/OffsetProcessor.php b/src/core/etl/src/Flow/ETL/Processor/OffsetProcessor.php index 8b0aa1e4fc..16cb36f6d0 100644 --- a/src/core/etl/src/Flow/ETL/Processor/OffsetProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/OffsetProcessor.php @@ -4,10 +4,10 @@ namespace Flow\ETL\Processor; +use Flow\ETL\BoundStep; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Extractor\Signal; use Flow\ETL\FlowContext; -use Flow\ETL\Pipeline\BoundStep; use Flow\ETL\Processor; use Flow\ETL\Rows; use Flow\ETL\Schema; @@ -15,8 +15,6 @@ /** * Skips the first N rows. - * - * @internal */ final readonly class OffsetProcessor implements Processor { @@ -26,7 +24,7 @@ * @throws InvalidArgumentException */ public function __construct( - private int $offset, + public int $offset, ) { // @mago-ignore analysis:invalid-operand // @mago-ignore analysis:impossible-condition,redundant-comparison diff --git a/src/core/etl/src/Flow/ETL/Processor/PivotProcessor.php b/src/core/etl/src/Flow/ETL/Processor/PivotProcessor.php index 736a274e78..53d09fbc7d 100644 --- a/src/core/etl/src/Flow/ETL/Processor/PivotProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/PivotProcessor.php @@ -4,21 +4,18 @@ namespace Flow\ETL\Processor; +use Flow\ETL\BoundStep; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\SchemaDefinitionNotFoundException; use Flow\ETL\FlowContext; use Flow\ETL\GroupBy; use Flow\ETL\GroupBy\PivotAggregation; use Flow\ETL\GroupBy\PivotShape; -use Flow\ETL\Pipeline\BoundStep; use Flow\ETL\Processor; use Flow\ETL\Rows; use Flow\ETL\Schema; use Generator; -/** - * @internal - */ final class PivotProcessor implements Processor { /** @@ -31,8 +28,8 @@ final class PivotProcessor implements Processor * @param int<1, max> $batchSize */ public function __construct( - private readonly GroupBy $groupBy, - private readonly int $batchSize = 1000, + public readonly GroupBy $groupBy, + public readonly int $batchSize = 1000, ) { // @mago-ignore analysis:invalid-operand // @mago-ignore analysis:impossible-condition,redundant-comparison diff --git a/src/core/etl/src/Flow/ETL/Processor/RepartitionProcessor.php b/src/core/etl/src/Flow/ETL/Processor/RepartitionProcessor.php index b49f8af68c..660eb92d13 100644 --- a/src/core/etl/src/Flow/ETL/Processor/RepartitionProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/RepartitionProcessor.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Processor; +use Flow\ETL\BoundStep; use Flow\ETL\Bucketing\Buckets; use Flow\ETL\Bucketing\BucketShape; use Flow\ETL\Bucketing\Hasher; @@ -11,7 +12,6 @@ use Flow\ETL\Bucketing\KeyValues; use Flow\ETL\Bucketing\NativeHasher; use Flow\ETL\FlowContext; -use Flow\ETL\Pipeline\BoundStep; use Flow\ETL\Processor; use Flow\ETL\Row\References; use Flow\ETL\Rows; @@ -22,15 +22,13 @@ /** * Regroups buckets spilled by BucketingProcessor so every row sharing a key arrives in one batch. - * - * @internal */ final readonly class RepartitionProcessor implements Processor { public function __construct( - private References $by, - private Buckets $buckets, - private Hasher $hasher = new NativeHasher(), + public References $by, + public Buckets $buckets, + public Hasher $hasher = new NativeHasher(), ) {} /** diff --git a/src/core/etl/src/Flow/ETL/Processor/TopNProcessor.php b/src/core/etl/src/Flow/ETL/Processor/TopNProcessor.php new file mode 100644 index 0000000000..92e2a4860f --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Processor/TopNProcessor.php @@ -0,0 +1,88 @@ +limit < 1) { + throw new InvalidArgumentException('TopN limit must be greater than 0, given: ' . $this->limit); + } + } + + public function bind(Schema $input): BoundStep + { + return new BoundStep(new self($this->refs, $this->limit, $input), $input); + } + + public function process(Generator $rows, FlowContext $context): Generator + { + /** @var array $kept */ + $kept = []; + $maxSize = 1; + $schema = null; + + foreach ($rows as $batch) { + $schema ??= $batch->schema(); + + if ($batch->empty()) { + continue; + } + + $maxSize = max($batch->count(), $maxSize); + + foreach ($batch->all() as $row) { + $kept[] = $row; + } + + // trimming only past twice the limit keeps the re-sorts amortised + if (count($kept) > (2 * $this->limit)) { + $kept = $this->top($kept, $schema); + } + } + + yield from (new Rows($this->declared ?? $schema ?? new Schema(), ...$this->top($kept, $schema)))->chunks( + $maxSize, + ); + } + + /** + * @param array $rows + * + * @return array + */ + public function top(array $rows, ?Schema $schema): array + { + return (new Rows($this->declared ?? $schema ?? new Schema(), ...$rows)) + ->sortBy(...$this->refs->all()) + ->take($this->limit) + ->all(); + } +} diff --git a/src/core/etl/src/Flow/ETL/Processor/VoidProcessor.php b/src/core/etl/src/Flow/ETL/Processor/VoidProcessor.php index 828289f85e..33077907ba 100644 --- a/src/core/etl/src/Flow/ETL/Processor/VoidProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/VoidProcessor.php @@ -4,8 +4,8 @@ namespace Flow\ETL\Processor; +use Flow\ETL\BoundStep; use Flow\ETL\FlowContext; -use Flow\ETL\Pipeline\BoundStep; use Flow\ETL\Processor; use Flow\ETL\Rows; use Flow\ETL\Schema; @@ -13,8 +13,6 @@ /** * Discards all rows and yields an empty batch. - * - * @internal */ final readonly class VoidProcessor implements Processor { diff --git a/src/core/etl/src/Flow/ETL/Processor/WindowProcessor.php b/src/core/etl/src/Flow/ETL/Processor/WindowProcessor.php index 9cac332727..7cc8772789 100644 --- a/src/core/etl/src/Flow/ETL/Processor/WindowProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/WindowProcessor.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Processor; +use Flow\ETL\BoundStep; use Flow\ETL\Exception\SchemaDefinitionNotFoundException; use Flow\ETL\FlowContext; use Flow\ETL\Function\ExpandingFunctions; @@ -11,7 +12,6 @@ use Flow\ETL\Function\PartitionRanking; use Flow\ETL\Function\ReferenceResolver; use Flow\ETL\Function\WindowFunction; -use Flow\ETL\Pipeline\BoundStep; use Flow\ETL\Processor; use Flow\ETL\Row; use Flow\ETL\Rows; @@ -29,8 +29,6 @@ /** * Applies window functions over partitioned and ordered data. - * - * @internal */ final class WindowProcessor implements Processor { @@ -38,9 +36,9 @@ final class WindowProcessor implements Processor * @param Definition|string $entry */ public function __construct( - private readonly string|Definition $entry, - private readonly WindowFunction $function, - private readonly ?BoundWindow $bound = null, + public readonly string|Definition $entry, + public readonly WindowFunction $function, + public readonly ?BoundWindow $bound = null, ) {} public function bind(Schema $input): BoundStep diff --git a/src/core/etl/src/Flow/ETL/Repartition/RepartitionSteps.php b/src/core/etl/src/Flow/ETL/Repartition/RepartitionSteps.php index ae8f97e2e2..1458a6ab3c 100644 --- a/src/core/etl/src/Flow/ETL/Repartition/RepartitionSteps.php +++ b/src/core/etl/src/Flow/ETL/Repartition/RepartitionSteps.php @@ -14,9 +14,6 @@ use Flow\ETL\Processor\RepartitionProcessor; use Flow\ETL\Row\References; -/** - * @internal - */ final readonly class RepartitionSteps { /** diff --git a/src/core/etl/src/Flow/ETL/Retry/DelayFactory.php b/src/core/etl/src/Flow/ETL/Retry/DelayFactory.php deleted file mode 100644 index 5c39852a11..0000000000 --- a/src/core/etl/src/Flow/ETL/Retry/DelayFactory.php +++ /dev/null @@ -1,12 +0,0 @@ -baseDuration->microseconds() * ($this->multiplier ** ($attempt - 1))), - ); - - if ($this->maxDelay !== null && $calculatedDelay->microseconds() > $this->maxDelay->microseconds()) { - return $this->maxDelay; - } - - return $calculatedDelay; - } -} diff --git a/src/core/etl/src/Flow/ETL/Retry/DelayFactory/Fixed.php b/src/core/etl/src/Flow/ETL/Retry/DelayFactory/Fixed.php deleted file mode 100644 index c20deae999..0000000000 --- a/src/core/etl/src/Flow/ETL/Retry/DelayFactory/Fixed.php +++ /dev/null @@ -1,20 +0,0 @@ -duration; - } -} diff --git a/src/core/etl/src/Flow/ETL/Retry/DelayFactory/Fixed/FixedMilliseconds.php b/src/core/etl/src/Flow/ETL/Retry/DelayFactory/Fixed/FixedMilliseconds.php deleted file mode 100644 index 7e7251d076..0000000000 --- a/src/core/etl/src/Flow/ETL/Retry/DelayFactory/Fixed/FixedMilliseconds.php +++ /dev/null @@ -1,20 +0,0 @@ -milliseconds); - } -} diff --git a/src/core/etl/src/Flow/ETL/Retry/DelayFactory/Jitter.php b/src/core/etl/src/Flow/ETL/Retry/DelayFactory/Jitter.php deleted file mode 100644 index d78d54b591..0000000000 --- a/src/core/etl/src/Flow/ETL/Retry/DelayFactory/Jitter.php +++ /dev/null @@ -1,40 +0,0 @@ - 1.0) { - throw new InvalidArgumentException('Jitter percentage must be between 0.0 and 1.0'); - } - } - - public function delay(int $attempt): Duration - { - $baseDelay = $this->delayFactory->delay($attempt); - - if ($this->jitterPercentage === 0.0) { - return $baseDelay; - } - - $jitterRange = (int) ($baseDelay->microseconds() * $this->jitterPercentage); - $jitter = mt_rand(-$jitterRange, $jitterRange); - - $jitteredDelay = $baseDelay->microseconds() + $jitter; - - return Duration::fromMicroseconds(max(0, $jitteredDelay)); - } -} diff --git a/src/core/etl/src/Flow/ETL/Retry/DelayFactory/Linear.php b/src/core/etl/src/Flow/ETL/Retry/DelayFactory/Linear.php deleted file mode 100644 index f620b6448c..0000000000 --- a/src/core/etl/src/Flow/ETL/Retry/DelayFactory/Linear.php +++ /dev/null @@ -1,23 +0,0 @@ -baseDuration->microseconds() + ($this->increment->microseconds() * ($attempt - 1)), - ); - } -} diff --git a/src/core/etl/src/Flow/ETL/Retry/FailedRetry.php b/src/core/etl/src/Flow/ETL/Retry/FailedRetry.php deleted file mode 100644 index f6b837c809..0000000000 --- a/src/core/etl/src/Flow/ETL/Retry/FailedRetry.php +++ /dev/null @@ -1,23 +0,0 @@ -now(), $exception, $attemptNumber); - } -} diff --git a/src/core/etl/src/Flow/ETL/Retry/RetriesRecord.php b/src/core/etl/src/Flow/ETL/Retry/RetriesRecord.php deleted file mode 100644 index 8edd816fac..0000000000 --- a/src/core/etl/src/Flow/ETL/Retry/RetriesRecord.php +++ /dev/null @@ -1,45 +0,0 @@ - - */ - private array $attempts = []; - - public function add(FailedRetry $attempt): void - { - $this->attempts[] = $attempt; - } - - /** - * @return array - */ - public function attempts(): array - { - return $this->attempts; - } - - public function count(): int - { - return count($this->attempts); - } - - public function last(): ?FailedRetry - { - if ($this->attempts === []) { - return null; - } - - return end($this->attempts); - } -} diff --git a/src/core/etl/src/Flow/ETL/Retry/RetryStrategy.php b/src/core/etl/src/Flow/ETL/Retry/RetryStrategy.php deleted file mode 100644 index 10e601eedf..0000000000 --- a/src/core/etl/src/Flow/ETL/Retry/RetryStrategy.php +++ /dev/null @@ -1,12 +0,0 @@ -limit; - } -} diff --git a/src/core/etl/src/Flow/ETL/Retry/RetryStrategy/AnyThrowableExcept.php b/src/core/etl/src/Flow/ETL/Retry/RetryStrategy/AnyThrowableExcept.php deleted file mode 100644 index 8ff321e00a..0000000000 --- a/src/core/etl/src/Flow/ETL/Retry/RetryStrategy/AnyThrowableExcept.php +++ /dev/null @@ -1,67 +0,0 @@ -> - */ - private array $exceptionTypes; - - /** - * @param array> $exceptionTypes - */ - public function __construct( - array $exceptionTypes, - private int $limit, - ) { - if ($exceptionTypes === []) { - throw new InvalidArgumentException( - 'Exception types cannot be empty. Use AnyThrowable strategy to retry on any throwable.', - ); - } - - if ($limit <= 0) { - throw new InvalidArgumentException('Retry limit must be greater than 0'); - } - - foreach ($exceptionTypes as $exceptionType) { - if (!class_exists($exceptionType) && !interface_exists($exceptionType)) { - throw new InvalidArgumentException("Class '{$exceptionType}' does not exist"); - } - - // @mago-ignore analysis:redundant-comparison,redundant-logical-operation - if (!is_subclass_of($exceptionType, Throwable::class) && $exceptionType !== Throwable::class) { - throw new InvalidArgumentException("Class '{$exceptionType}' is not a Throwable"); - } - } - - $this->exceptionTypes = $exceptionTypes; - } - - public function shouldRetry(Throwable $exception, int $attemptNumber): bool - { - if ($attemptNumber > $this->limit) { - return false; - } - - foreach ($this->exceptionTypes as $exceptionType) { - if ($exception instanceof $exceptionType) { - return false; - } - } - - return true; - } -} diff --git a/src/core/etl/src/Flow/ETL/Retry/RetryStrategy/OnExceptionTypes.php b/src/core/etl/src/Flow/ETL/Retry/RetryStrategy/OnExceptionTypes.php deleted file mode 100644 index fb16e7c52b..0000000000 --- a/src/core/etl/src/Flow/ETL/Retry/RetryStrategy/OnExceptionTypes.php +++ /dev/null @@ -1,67 +0,0 @@ -> - */ - private array $exceptionTypes; - - /** - * @param array> $exceptionTypes - */ - public function __construct( - array $exceptionTypes, - private int $limit, - ) { - if ($exceptionTypes === []) { - throw new InvalidArgumentException( - 'Exception types cannot be empty. Use AnyThrowable strategy to retry on any throwable.', - ); - } - - if ($limit <= 0) { - throw new InvalidArgumentException('Retry limit must be greater than 0'); - } - - foreach ($exceptionTypes as $exceptionType) { - if (!class_exists($exceptionType) && !interface_exists($exceptionType)) { - throw new InvalidArgumentException("Class '{$exceptionType}' does not exist"); - } - - // @mago-ignore analysis:redundant-comparison,redundant-logical-operation - if (!is_subclass_of($exceptionType, Throwable::class) && $exceptionType !== Throwable::class) { - throw new InvalidArgumentException("Class '{$exceptionType}' is not a Throwable"); - } - } - - $this->exceptionTypes = $exceptionTypes; - } - - public function shouldRetry(Throwable $exception, int $attemptNumber): bool - { - if ($attemptNumber > $this->limit) { - return false; - } - - foreach ($this->exceptionTypes as $exceptionType) { - if ($exception instanceof $exceptionType) { - return true; - } - } - - return false; - } -} diff --git a/src/core/etl/src/Flow/ETL/Rows.php b/src/core/etl/src/Flow/ETL/Rows.php index d27df9c8d4..3b735c54fc 100644 --- a/src/core/etl/src/Flow/ETL/Rows.php +++ b/src/core/etl/src/Flow/ETL/Rows.php @@ -78,7 +78,7 @@ public function __construct( * operation produced the schema and the rows, or when the rows are a subset or a permutation of * a batch that already passed. * - * @internal engine paths only + * Engine paths only. * * @param array $rows re-indexed here - first(), last(), chunks() and offsetGet() read by position */ @@ -96,7 +96,7 @@ public static function trusted(Schema $schema, array $rows): self * non-null value is not validated against its type, because the caller produced it by casting to, or decoding * from, that type. A value is validated once, where it enters the engine. * - * @internal engine paths only + * Engine paths only. * * @param array $rows * diff --git a/src/core/etl/src/Flow/ETL/Sink.php b/src/core/etl/src/Flow/ETL/Sink.php new file mode 100644 index 0000000000..07d9f22b42 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Sink.php @@ -0,0 +1,14 @@ +filter($this->condition)->write($this->sink); + } + + /** + * BC shim for to_branch($condition, $loader, $transformation) - must precede write(). + */ + public function withTransformation(Transformation $transformation): self + { + return new self($this->condition, new Transformed($transformation, $this->sink)); + } +} diff --git a/src/core/etl/src/Flow/ETL/Sink/Transactional.php b/src/core/etl/src/Flow/ETL/Sink/Transactional.php new file mode 100644 index 0000000000..b08051bcdc --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Sink/Transactional.php @@ -0,0 +1,50 @@ + + */ + private array $sinks; + + public function __construct( + private Transaction $transaction, + Loader|Sink ...$sinks, + ) { + if ($sinks === []) { + throw new InvalidArgumentException('At least one loader must be provided'); + } + + $this->sinks = array_values($sinks); + } + + /** + * @return list + */ + public function sinks(): array + { + return $this->sinks; + } + + public function transaction(): Transaction + { + return $this->transaction; + } + + public function write(DataFrame $prefix): void + { + $prefix->load($this); + } +} diff --git a/src/core/etl/src/Flow/ETL/Sink/Transformed.php b/src/core/etl/src/Flow/ETL/Sink/Transformed.php new file mode 100644 index 0000000000..92a2966762 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Sink/Transformed.php @@ -0,0 +1,29 @@ +with($this->transformer) !== $prefix) { + throw InvalidLogicException::transformationReturnedAnotherFrame($this->transformer::class); + } + + $prefix->write($this->sink); + } +} diff --git a/src/core/etl/src/Flow/ETL/Sort/SortSteps.php b/src/core/etl/src/Flow/ETL/Sort/SortSteps.php index 2f4dd204a3..a9a6b0731c 100644 --- a/src/core/etl/src/Flow/ETL/Sort/SortSteps.php +++ b/src/core/etl/src/Flow/ETL/Sort/SortSteps.php @@ -15,9 +15,6 @@ use Flow\ETL\Processor\MergeSortProcessor; use Flow\ETL\Row\References; -/** - * @internal - */ final readonly class SortSteps { /** diff --git a/src/core/etl/src/Flow/ETL/Time/Duration.php b/src/core/etl/src/Flow/ETL/Time/Duration.php deleted file mode 100644 index 81f7639043..0000000000 --- a/src/core/etl/src/Flow/ETL/Time/Duration.php +++ /dev/null @@ -1,61 +0,0 @@ -microseconds = $microseconds; - } - - public static function fromMicroseconds(int $microseconds): self - { - return new self($microseconds); - } - - public static function fromMilliseconds(int $milliseconds): self - { - return new self($milliseconds * 1000); - } - - public static function fromMinutes(int $minutes): self - { - return new self($minutes * 60 * 1_000_000); - } - - public static function fromSeconds(int $seconds): self - { - return new self($seconds * 1_000_000); - } - - public function microseconds(): int - { - return $this->microseconds; - } - - public function milliseconds(): int - { - return (int) ($this->microseconds / 1000); - } - - public function minutes(): int - { - return (int) ($this->microseconds / 60_000_000); - } - - public function seconds(): int - { - return (int) ($this->microseconds / 1_000_000); - } -} diff --git a/src/core/etl/src/Flow/ETL/Time/FakeSleep.php b/src/core/etl/src/Flow/ETL/Time/FakeSleep.php deleted file mode 100644 index c7e945f9d0..0000000000 --- a/src/core/etl/src/Flow/ETL/Time/FakeSleep.php +++ /dev/null @@ -1,57 +0,0 @@ - - */ - private array $sleepDurations = []; - - private int $totalMicroseconds = 0; - - public function for(Duration $duration): void - { - $this->sleepDurations[] = $duration; - $this->totalMicroseconds += $duration->microseconds(); - } - - public function reset(): void - { - $this->totalMicroseconds = 0; - $this->sleepDurations = []; - } - - public function sleepCount(): int - { - return count($this->sleepDurations); - } - - /** - * @return array - */ - public function sleepDurations(): array - { - return $this->sleepDurations; - } - - public function totalMicroseconds(): int - { - return $this->totalMicroseconds; - } - - public function totalMilliseconds(): int - { - return (int) ($this->totalMicroseconds / 1000); - } - - public function totalSeconds(): int - { - return (int) ($this->totalMicroseconds / 1_000_000); - } -} diff --git a/src/core/etl/src/Flow/ETL/Time/Sleep.php b/src/core/etl/src/Flow/ETL/Time/Sleep.php deleted file mode 100644 index 0b4bef656b..0000000000 --- a/src/core/etl/src/Flow/ETL/Time/Sleep.php +++ /dev/null @@ -1,10 +0,0 @@ -microseconds())); - } -} diff --git a/src/core/etl/src/Flow/ETL/Transaction.php b/src/core/etl/src/Flow/ETL/Transaction.php new file mode 100644 index 0000000000..4ee1a00ed2 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Transaction.php @@ -0,0 +1,19 @@ +rows(new AddRowIndexTransformer($this->indexColumn, $this->startFrom)); + return $dataFrame->transform(new AddRowIndexTransformer($this->indexColumn, $this->startFrom)); } } diff --git a/src/core/etl/src/Flow/ETL/Transformer.php b/src/core/etl/src/Flow/ETL/Transformer.php index 83593cba97..41dabb64bd 100644 --- a/src/core/etl/src/Flow/ETL/Transformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer.php @@ -6,7 +6,6 @@ use Flow\ETL\Exception\DataDependentSchemaException; use Flow\ETL\Exception\LimitReachedException; -use Flow\ETL\Pipeline\BoundStep; interface Transformer { diff --git a/src/core/etl/src/Flow/ETL/Transformer/AddRowIndexTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/AddRowIndexTransformer.php index c5d7bbd9d8..bf24502ee5 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/AddRowIndexTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/AddRowIndexTransformer.php @@ -4,29 +4,33 @@ namespace Flow\ETL\Transformer; +use Flow\ETL\BoundStep; use Flow\ETL\Config\Telemetry\TelemetryAttributes; use Flow\ETL\FlowContext; -use Flow\ETL\Pipeline\BoundStep; use Flow\ETL\Row; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\Transformation\AddRowIndex\StartFrom; -use Flow\ETL\Transformer; use Throwable; use function Flow\ETL\DSL\int_schema; -final class AddRowIndexTransformer implements Transformer +final class AddRowIndexTransformer implements Stateful { private int $index; public function __construct( private readonly string $indexColumn, - StartFrom $startFrom, + private readonly StartFrom $startFrom, ) { $this->index = $startFrom === StartFrom::ZERO ? 0 : 1; } + public function fresh(): self + { + return new self($this->indexColumn, $this->startFrom); + } + public function bind(Schema $input): BoundStep { return new BoundStep($this, $input->add(int_schema($this->indexColumn))); diff --git a/src/core/etl/src/Flow/ETL/Transformer/CollectReferencesTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/CollectReferencesTransformer.php index 8e9b3f095d..ff0d84de6b 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/CollectReferencesTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/CollectReferencesTransformer.php @@ -4,9 +4,9 @@ namespace Flow\ETL\Transformer; +use Flow\ETL\BoundStep; use Flow\ETL\Config\Telemetry\TelemetryAttributes; use Flow\ETL\FlowContext; -use Flow\ETL\Pipeline\BoundStep; use Flow\ETL\Row\References; use Flow\ETL\Rows; use Flow\ETL\Schema; diff --git a/src/core/etl/src/Flow/ETL/Transformer/CrossJoinRowsTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/CrossJoinRowsTransformer.php index a79fe0bd85..f3a65924eb 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/CrossJoinRowsTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/CrossJoinRowsTransformer.php @@ -4,11 +4,12 @@ namespace Flow\ETL\Transformer; +use Flow\ETL\BoundStep; use Flow\ETL\Config\Telemetry\TelemetryAttributes; -use Flow\ETL\DataFrame; +use Flow\ETL\Executor; +use Flow\ETL\Executor\PhysicalPlan; use Flow\ETL\FlowContext; use Flow\ETL\Join\JoinSchema; -use Flow\ETL\Pipeline\BoundStep; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\Transformer; @@ -19,13 +20,14 @@ final class CrossJoinRowsTransformer implements Transformer private ?Rows $rows = null; public function __construct( - private readonly DataFrame $dataFrame, - private readonly string $prefix = '', + public readonly PhysicalPlan $right, + private readonly Executor $executor, + public readonly string $prefix = '', ) {} public function bind(Schema $input): BoundStep { - return new BoundStep($this, (new JoinSchema($this->prefix))->cross($input, $this->dataFrame->schema())); + return new BoundStep($this, (new JoinSchema($this->prefix))->cross($input, $this->right->schema())); } public function transform(Rows $rows, FlowContext $context): Rows @@ -51,7 +53,7 @@ public function transform(Rows $rows, FlowContext $context): Rows private function rows(): Rows { if ($this->rows === null) { - $this->rows = $this->dataFrame->fetch(); + $this->rows = $this->executor->merge($this->executor->executePipeline($this->right->root()), $this->right); } return $this->rows; diff --git a/src/core/etl/src/Flow/ETL/Transformer/DropDuplicatesTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/DropDuplicatesTransformer.php index 91e38155fb..07f4c4fffb 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/DropDuplicatesTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/DropDuplicatesTransformer.php @@ -4,12 +4,12 @@ namespace Flow\ETL\Transformer; +use Flow\ETL\BoundStep; use Flow\ETL\Config\Telemetry\TelemetryAttributes; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; use Flow\ETL\Hash\Algorithm; use Flow\ETL\Hash\NativePHPHash; -use Flow\ETL\Pipeline\BoundStep; use Flow\ETL\Row\Reference; use Flow\ETL\Rows; use Flow\ETL\Schema; diff --git a/src/core/etl/src/Flow/ETL/Transformer/DropEntriesTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/DropEntriesTransformer.php index 9ba33a970f..0b5f892af4 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/DropEntriesTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/DropEntriesTransformer.php @@ -4,10 +4,9 @@ namespace Flow\ETL\Transformer; +use Flow\ETL\BoundStep; use Flow\ETL\Config\Telemetry\TelemetryAttributes; use Flow\ETL\FlowContext; -use Flow\ETL\Pipeline\BoundStep; -use Flow\ETL\Row; use Flow\ETL\Row\Reference; use Flow\ETL\Row\References; use Flow\ETL\Rows; diff --git a/src/core/etl/src/Flow/ETL/Transformer/DuplicateRowTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/DuplicateRowTransformer.php index 633f44c845..3ecddd0409 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/DuplicateRowTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/DuplicateRowTransformer.php @@ -4,13 +4,13 @@ namespace Flow\ETL\Transformer; +use Flow\ETL\BoundStep; use Flow\ETL\Config\Telemetry\TelemetryAttributes; use Flow\ETL\FlowContext; use Flow\ETL\Function\ExpandingFunctions; use Flow\ETL\Function\Parameter; use Flow\ETL\Function\ReferenceResolver; use Flow\ETL\Function\ScalarFunction; -use Flow\ETL\Pipeline\BoundStep; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\Transformer; diff --git a/src/core/etl/src/Flow/ETL/Transformer/JoinEachRowsTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/JoinEachRowsTransformer.php index 4a3e3593c8..f585240fbc 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/JoinEachRowsTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/JoinEachRowsTransformer.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Transformer; +use Flow\ETL\BoundStep; use Flow\ETL\Config\Telemetry\TelemetryAttributes; use Flow\ETL\DataFrameFactory; use Flow\ETL\Exception\DataDependentSchemaException; @@ -11,7 +12,6 @@ use Flow\ETL\FlowContext; use Flow\ETL\Join\Expression; use Flow\ETL\Join\Join; -use Flow\ETL\Pipeline\BoundStep; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\Transformer; diff --git a/src/core/etl/src/Flow/ETL/Transformer/LimitTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/LimitTransformer.php index fbf25f9d07..31b48b18e1 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/LimitTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/LimitTransformer.php @@ -4,11 +4,11 @@ namespace Flow\ETL\Transformer; +use Flow\ETL\BoundStep; use Flow\ETL\Config\Telemetry\TelemetryAttributes; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\LimitReachedException; use Flow\ETL\FlowContext; -use Flow\ETL\Pipeline\BoundStep; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\Transformer; diff --git a/src/core/etl/src/Flow/ETL/Transformer/NestedExpandTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/NestedExpandTransformer.php index a5dd5eaab7..8a9f49819b 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/NestedExpandTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/NestedExpandTransformer.php @@ -4,9 +4,9 @@ namespace Flow\ETL\Transformer; +use Flow\ETL\BoundStep; use Flow\ETL\Config\Telemetry\TelemetryAttributes; use Flow\ETL\FlowContext; -use Flow\ETL\Pipeline\BoundStep; use Flow\ETL\Row; use Flow\ETL\Rows; use Flow\ETL\Schema; diff --git a/src/core/etl/src/Flow/ETL/Transformer/PruneEntriesTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/PruneEntriesTransformer.php index f8d362ff1b..8e2fd241dd 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/PruneEntriesTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/PruneEntriesTransformer.php @@ -4,9 +4,9 @@ namespace Flow\ETL\Transformer; +use Flow\ETL\BoundStep; use Flow\ETL\Config\Telemetry\TelemetryAttributes; use Flow\ETL\FlowContext; -use Flow\ETL\Pipeline\BoundStep; use Flow\ETL\Row\Reference; use Flow\ETL\Row\References; use Flow\ETL\Rows; diff --git a/src/core/etl/src/Flow/ETL/Transformer/RenameEachEntryTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/RenameEachEntryTransformer.php index fef34c9a45..be7ad8b77f 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/RenameEachEntryTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/RenameEachEntryTransformer.php @@ -4,10 +4,10 @@ namespace Flow\ETL\Transformer; +use Flow\ETL\BoundStep; use Flow\ETL\Config\Telemetry\TelemetryAttributes; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Pipeline\BoundStep; use Flow\ETL\Row\RowRenaming; use Flow\ETL\Rows; use Flow\ETL\Schema; diff --git a/src/core/etl/src/Flow/ETL/Transformer/RenameEntryTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/RenameEntryTransformer.php index 6abc1d7e12..1b79ed4af6 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/RenameEntryTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/RenameEntryTransformer.php @@ -4,9 +4,9 @@ namespace Flow\ETL\Transformer; +use Flow\ETL\BoundStep; use Flow\ETL\Config\Telemetry\TelemetryAttributes; use Flow\ETL\FlowContext; -use Flow\ETL\Pipeline\BoundStep; use Flow\ETL\Row\RowRenaming; use Flow\ETL\Rows; use Flow\ETL\Schema; diff --git a/src/core/etl/src/Flow/ETL/Transformer/ScalarFunctionFilterTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/ScalarFunctionFilterTransformer.php index f85a39f69c..0a01576ea9 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/ScalarFunctionFilterTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/ScalarFunctionFilterTransformer.php @@ -4,13 +4,13 @@ namespace Flow\ETL\Transformer; +use Flow\ETL\BoundStep; use Flow\ETL\Config\Telemetry\TelemetryAttributes; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; use Flow\ETL\Function\ExpandingFunctions; use Flow\ETL\Function\ReferenceResolver; use Flow\ETL\Function\ScalarFunction; -use Flow\ETL\Pipeline\BoundStep; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\Transformer; diff --git a/src/core/etl/src/Flow/ETL/Transformer/ScalarFunctionTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/ScalarFunctionTransformer.php index 92ab393e4e..717d7be21d 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/ScalarFunctionTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/ScalarFunctionTransformer.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Transformer; +use Flow\ETL\BoundStep; use Flow\ETL\Config\Telemetry\TelemetryAttributes; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\InvalidLogicException; @@ -14,7 +15,6 @@ use Flow\ETL\Function\ScalarFunction; use Flow\ETL\Function\ScalarFunction\ExpandResults; use Flow\ETL\Function\ScalarFunction\UnpackResults; -use Flow\ETL\Pipeline\BoundStep; use Flow\ETL\Row; use Flow\ETL\Rows; use Flow\ETL\Schema; diff --git a/src/core/etl/src/Flow/ETL/Transformer/SelectEntriesTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/SelectEntriesTransformer.php index a449ed0879..eaadb6a5b1 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/SelectEntriesTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/SelectEntriesTransformer.php @@ -4,10 +4,9 @@ namespace Flow\ETL\Transformer; +use Flow\ETL\BoundStep; use Flow\ETL\Config\Telemetry\TelemetryAttributes; use Flow\ETL\FlowContext; -use Flow\ETL\Pipeline\BoundStep; -use Flow\ETL\Row; use Flow\ETL\Row\Reference; use Flow\ETL\Row\References; use Flow\ETL\Rows; diff --git a/src/core/etl/src/Flow/ETL/Transformer/SerializeTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/SerializeTransformer.php index bd35824d01..aa69a0adc7 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/SerializeTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/SerializeTransformer.php @@ -4,9 +4,9 @@ namespace Flow\ETL\Transformer; +use Flow\ETL\BoundStep; use Flow\ETL\Config\Telemetry\TelemetryAttributes; use Flow\ETL\FlowContext; -use Flow\ETL\Pipeline\BoundStep; use Flow\ETL\Row\Reference; use Flow\ETL\Rows; use Flow\ETL\Schema; diff --git a/src/core/etl/src/Flow/ETL/Transformer/Stateful.php b/src/core/etl/src/Flow/ETL/Transformer/Stateful.php new file mode 100644 index 0000000000..40993d419b --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Transformer/Stateful.php @@ -0,0 +1,19 @@ + */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null, Filter $pathFilter = new OnlyFiles()): Generator { $fileOffset = $this->offset ?? 0; $yielded = 0; @@ -89,7 +87,7 @@ public function extract(FlowContext $context): Generator $fileColumns = $this->fileColumns($this->filesystem, $this->path); - foreach ($this->files($context->hydrator()) as $file) { + foreach ($this->files($context->hydrator(), $pathFilter) as $file) { // finally, not a close() per exit: the offset-skip continue, the STOP/limit return // below and an abandoned generator all have to release the handle (b73) try { @@ -118,8 +116,6 @@ public function extract(FlowContext $context): Generator $constants = $fileColumns->forFile($file->source(), $fileSchema); // a declared schema is always matched: the rows below are only trusted against the footer $matchTo = $promisedSchema ?? (!$fileSchema->isSame($target) ? $target : null); - - $limit = $this->pushedLimit(); $remaining = $limit === null ? null : $limit - $yielded; foreach ($file->reader->rows($this->batchSize(), $fileOffset, $remaining) as $rows) { @@ -181,6 +177,11 @@ public function unionByName(bool $union = true): self return $this; } + public function partitionSchema(): Schema + { + return $this->fileColumns($this->filesystem, $this->path)->partitions($this->schema ?? new Schema()); + } + public function source(): Path { return $this->path; @@ -200,9 +201,9 @@ public function withOffset(int $offset): self /** * @return Generator */ - private function files(?Hydrator $hydrator = null): Generator + private function files(?Hydrator $hydrator = null, Filter $pathFilter = new OnlyFiles()): Generator { - foreach ($this->sourceFiles($this->filesystem, $this->path) as $source) { + foreach ($this->sourceFiles($this->filesystem, $this->path, $pathFilter) as $source) { yield new FloeSourceFile( (new FloeReader( $this->filesystem, diff --git a/src/core/etl/src/Flow/Serializer/Serializer.php b/src/core/etl/src/Flow/Serializer/Serializer.php index ebf662895c..97c8ba25e0 100644 --- a/src/core/etl/src/Flow/Serializer/Serializer.php +++ b/src/core/etl/src/Flow/Serializer/Serializer.php @@ -9,9 +9,6 @@ use Flow\Filesystem\SourceStream; use Flow\Serializer\Exception\SerializationException; -/** - * @internal - */ interface Serializer { /** diff --git a/src/core/etl/tests/Flow/ETL/Tests/Context/ExecutedPlan.php b/src/core/etl/tests/Flow/ETL/Tests/Context/ExecutedPlan.php new file mode 100644 index 0000000000..3c35ccbb5f --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Context/ExecutedPlan.php @@ -0,0 +1,23 @@ + + */ + public static function of(LogicalPlan $plan, FlowContext $context): Generator + { + return $context->config->executor()->execute($context->config->planner()->plan($plan, $context)); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Context/ExecutedSegments.php b/src/core/etl/tests/Flow/ETL/Tests/Context/ExecutedSegments.php new file mode 100644 index 0000000000..4219b4aecc --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Context/ExecutedSegments.php @@ -0,0 +1,29 @@ + + */ + public static function of(Segments $segments, ?FlowContext $context = null): Generator + { + return (new Executor())->executePipeline(new Pipeline(0, $segments, $context ?? flow_context())); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Context/ExtractedRows.php b/src/core/etl/tests/Flow/ETL/Tests/Context/ExtractedRows.php index 4a01dc2cee..3b3fc220d6 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Context/ExtractedRows.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Context/ExtractedRows.php @@ -7,6 +7,9 @@ use Flow\ETL\Extractor; use Flow\ETL\FlowContext; use Flow\ETL\Rows; +use Flow\ETL\Tests\FlowTestCase; +use Flow\Filesystem\Path\Filter; +use Flow\Filesystem\Path\Filter\OnlyFiles; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\rows; @@ -14,11 +17,18 @@ final class ExtractedRows { - public static function of(Extractor $extractor, ?FlowContext $context = null): Rows - { + /** + * @param null|int<1, max> $limit + */ + public static function of( + Extractor $extractor, + ?FlowContext $context = null, + ?int $limit = null, + Filter $pathFilter = new OnlyFiles(), + ): Rows { $extracted = rows(schema()); - foreach ($extractor->extract($context ?? flow_context()) as $batch) { + foreach (FlowTestCase::extracted($extractor, $context ?? flow_context(), $limit, $pathFilter) as $batch) { $extracted = $extracted->merge($batch); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Context/LoaderEndingContext.php b/src/core/etl/tests/Flow/ETL/Tests/Context/LoaderEndingContext.php index 39014d5253..00e68250d6 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Context/LoaderEndingContext.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Context/LoaderEndingContext.php @@ -7,6 +7,7 @@ use Flow\ETL\Config; use Flow\ETL\Exception\RuntimeException; use Flow\ETL\Loader; +use Flow\ETL\Sink; use Flow\ETL\Tests\Double\ThrowWhenRowMatches; use Throwable; @@ -15,26 +16,26 @@ final class LoaderEndingContext { - public static function failedRun(Loader $loader, ?Config $config = null): void + public static function failedRun(Loader|Sink $sink, ?Config $config = null): void { try { data_frame($config) ->read(from_array([['id' => 1, 'v' => 'a'], ['id' => 2, 'v' => 'b']])) ->batchSize(1) ->with(new ThrowWhenRowMatches('id', 2, new RuntimeException('boom'))) - ->write($loader) + ->write($sink) ->run(); } catch (Throwable) { // the run is expected to fail; what matters is which ending the sink was given } } - public static function thrownByRun(Loader $loader, ?Config $config = null): ?Throwable + public static function thrownByRun(Loader|Sink $sink, ?Config $config = null): ?Throwable { try { data_frame($config) ->read(from_array([['id' => 1]])) - ->write($loader) + ->write($sink) ->run(); } catch (Throwable $failure) { return $failure; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Context/PipelineSteps.php b/src/core/etl/tests/Flow/ETL/Tests/Context/PipelineSteps.php new file mode 100644 index 0000000000..53c763eb09 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Context/PipelineSteps.php @@ -0,0 +1,45 @@ + + */ + public static function of(Segments $segments): array + { + $steps = []; + + foreach ($segments->all() as $segment) { + foreach ($segment->steps() as $step) { + $steps[] = $step; + } + + $processor = $segment->processor(); + + if ($processor !== null) { + $steps[] = $processor; + } + } + + return $steps; + } + + /** + * @return list + */ + public static function classes(Segments $segments): array + { + return array_map(static fn(Loader|Processor|Transformer $step): string => $step::class, self::of($segments)); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Context/ScoredRows.php b/src/core/etl/tests/Flow/ETL/Tests/Context/ScoredRows.php new file mode 100644 index 0000000000..5ec471442b --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Context/ScoredRows.php @@ -0,0 +1,55 @@ + ...$batches + * + * @return Generator + */ + public static function batches(array ...$batches): Generator + { + foreach ($batches as $batch) { + $rows = []; + + foreach ($batch as [$score, $name]) { + $rows[] = row(['score' => $score, 'name' => $name]); + } + + yield rows(schema(int_schema('score'), str_schema('name')), ...$rows); + } + } + + /** + * @param Generator $batches + * + * @return array> + */ + public static function merged(Generator $batches): array + { + $all = []; + + foreach ($batches as $batch) { + $all = array_merge($all, $batch->toArray()); + } + + return $all; + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/AddStampToStringEntryTransformer.php b/src/core/etl/tests/Flow/ETL/Tests/Double/AddStampToStringEntryTransformer.php index 6981563337..590373f8d9 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/AddStampToStringEntryTransformer.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/AddStampToStringEntryTransformer.php @@ -4,8 +4,8 @@ namespace Flow\ETL\Tests\Double; +use Flow\ETL\BoundStep; use Flow\ETL\FlowContext; -use Flow\ETL\Pipeline\BoundStep; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\Transformer; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/CallOrderLoader.php b/src/core/etl/tests/Flow/ETL/Tests/Double/CallOrderLoader.php new file mode 100644 index 0000000000..f336ad527f --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/CallOrderLoader.php @@ -0,0 +1,26 @@ + $log shared by every loader whose call order a test compares + */ + public function __construct( + private readonly string $name, + private readonly ArrayObject $log, + ) {} + + public function load(Rows $rows, FlowContext $context): void + { + $this->log[] = "{$this->name}:{$rows->count()}"; + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/ChildlessNode.php b/src/core/etl/tests/Flow/ETL/Tests/Double/ChildlessNode.php new file mode 100644 index 0000000000..de18e140f2 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/ChildlessNode.php @@ -0,0 +1,48 @@ + + */ + public array $contexts = []; + + public function bind(Schema $input): BoundStep + { + return new BoundStep($this, $input); + } + + public function transform(Rows $rows, FlowContext $context): Rows + { + $this->contexts[] = $context; + + return $rows; + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/CountingExtractor.php b/src/core/etl/tests/Flow/ETL/Tests/Double/CountingExtractor.php index 2f4bd9946d..070822d587 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/CountingExtractor.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/CountingExtractor.php @@ -30,6 +30,11 @@ final class CountingExtractor implements BatchableExtractor, Extractor, Rewindab public int $extractCalls = 0; + /** + * @var list + */ + public array $contexts = []; + private readonly Schema $schema; /** @@ -43,9 +48,10 @@ public function __construct(Schema $schema, Rows ...$batches) $this->batches = array_values($batches); } - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { $this->extractCalls++; + $this->contexts[] = $context; $buffer = []; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/EmptyExtractor.php b/src/core/etl/tests/Flow/ETL/Tests/Double/EmptyExtractor.php index cad88cb17e..6292cb2b73 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/EmptyExtractor.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/EmptyExtractor.php @@ -14,7 +14,7 @@ final class EmptyExtractor implements Extractor { - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { yield rows(schema()); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/FakeExtractor.php b/src/core/etl/tests/Flow/ETL/Tests/Double/FakeExtractor.php index 229097cad8..1b1629fca2 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/FakeExtractor.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/FakeExtractor.php @@ -85,7 +85,7 @@ enum_schema('enum', BackedStringEnum::class), * * @return \Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { for ($i = 0; $i < $this->total; $i++) { $id = $i; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/FakeRandomOrdersExtractor.php b/src/core/etl/tests/Flow/ETL/Tests/Double/FakeRandomOrdersExtractor.php index c90db79aa8..2dbc8ecf30 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/FakeRandomOrdersExtractor.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/FakeRandomOrdersExtractor.php @@ -71,7 +71,7 @@ public function schema(): Schema ); } - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { $schema = self::schema(); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/FakeStaticOrdersExtractor.php b/src/core/etl/tests/Flow/ETL/Tests/Double/FakeStaticOrdersExtractor.php index d510c9b58d..25c329f82d 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/FakeStaticOrdersExtractor.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/FakeStaticOrdersExtractor.php @@ -72,7 +72,7 @@ public function schema(): Schema ); } - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { $schema = self::schema(); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/FanOutSink.php b/src/core/etl/tests/Flow/ETL/Tests/Double/FanOutSink.php new file mode 100644 index 0000000000..07e312fd70 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/FanOutSink.php @@ -0,0 +1,32 @@ + + */ + private array $sinks; + + public function __construct(Loader|Sink ...$sinks) + { + $this->sinks = array_values($sinks); + } + + public function write(DataFrame $prefix): void + { + foreach ($this->sinks as $sink) { + $prefix->write($sink); + } + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/FileReadingExtractor.php b/src/core/etl/tests/Flow/ETL/Tests/Double/FileReadingExtractor.php index 74be98cca7..cdd0e75ee4 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/FileReadingExtractor.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/FileReadingExtractor.php @@ -10,6 +10,8 @@ use Flow\ETL\Schema; use Flow\Filesystem\Filesystem; use Flow\Filesystem\Path; +use Flow\Filesystem\Path\Filter; +use Flow\Filesystem\Path\Filter\OnlyFiles; use Generator; /** @@ -30,8 +32,8 @@ public function derive(Generator $files, bool $unionByName = false): Schema /** * @return Generator */ - public function listing(Filesystem $filesystem, Path $path): Generator + public function listing(Filesystem $filesystem, Path $path, Filter $pathFilter = new OnlyFiles()): Generator { - return $this->sourceFiles($filesystem, $path); + return $this->sourceFiles($filesystem, $path, $pathFilter); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/FixedRandomValueGenerator.php b/src/core/etl/tests/Flow/ETL/Tests/Double/FixedRandomValueGenerator.php new file mode 100644 index 0000000000..847f24a014 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/FixedRandomValueGenerator.php @@ -0,0 +1,25 @@ +int; + } + + public function string(int $int): string + { + return $this->string; + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/OneRowBatchesExtractor.php b/src/core/etl/tests/Flow/ETL/Tests/Double/OneRowBatchesExtractor.php index 8e5cef8968..70f6cc5142 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/OneRowBatchesExtractor.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/OneRowBatchesExtractor.php @@ -26,7 +26,7 @@ public function __construct( private readonly Rows $rows, ) {} - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { foreach ($this->rows->all() as $row) { $signal = yield Rows::trusted($this->rows->schema(), [$row]); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/PassThroughProcessor.php b/src/core/etl/tests/Flow/ETL/Tests/Double/PassThroughProcessor.php new file mode 100644 index 0000000000..c365637284 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/PassThroughProcessor.php @@ -0,0 +1,24 @@ + + */ + public array $drained = []; + + public function __construct( + private readonly LogicalPlan $plan, + private readonly FlowContext $context, + ) {} + + public function bind(Schema $input): BoundStep + { + return new BoundStep($this, $input); + } + + public function transform(Rows $rows, FlowContext $context): Rows + { + $this->drained = [ + ...$this->drained, + ...iterator_to_array(ExecutedPlan::of($this->plan, $this->context), false), + ]; + + return $rows; + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/PropagatingTransformationsSkippingLoaders.php b/src/core/etl/tests/Flow/ETL/Tests/Double/PropagatingTransformationsSkippingLoaders.php new file mode 100644 index 0000000000..a58dc3a1f1 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/PropagatingTransformationsSkippingLoaders.php @@ -0,0 +1,31 @@ + + */ + public array $limits = []; + + /** + * @var list + */ + private readonly array $batches; + + public function __construct( + private readonly Schema $schema, + Rows ...$batches, + ) { + $this->batches = array_values($batches); + } + + public function extract(FlowContext $context, ?int $limit = null): Generator + { + $this->limits[] = $limit; + + foreach ($this->batches as $rows) { + yield $rows; + } + } + + public function schema(): Schema + { + return $this->schema; + } + + public function withSchema(Schema $schema): static + { + return $this; + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/RecordingFileExtractor.php b/src/core/etl/tests/Flow/ETL/Tests/Double/RecordingFileExtractor.php new file mode 100644 index 0000000000..a73941f15f --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/RecordingFileExtractor.php @@ -0,0 +1,87 @@ + + */ + public array $limits = []; + + /** + * @var list + */ + public array $pathFilters = []; + + /** + * @var list + */ + private readonly array $batches; + + private Schema $partitions; + + public function __construct( + private readonly Schema $schema, + Rows ...$batches, + ) { + $this->batches = array_values($batches); + $this->partitions = new Schema(); + } + + public function extract(FlowContext $context, ?int $limit = null, Filter $pathFilter = new OnlyFiles()): Generator + { + $this->limits[] = $limit; + $this->pathFilters[] = $pathFilter; + + foreach ($this->batches as $rows) { + yield $rows; + } + } + + public function partitionSchema(): Schema + { + return $this->partitions; + } + + public function schema(): Schema + { + return $this->schema; + } + + public function source(): Path + { + return path('/dev/null'); + } + + public function withPartitionSchema(Schema $partitions): self + { + $self = new self($this->schema, ...$this->batches); + $self->partitions = $partitions; + + return $self; + } + + public function withSchema(Schema $schema): static + { + return $this; + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/RecordingLoader.php b/src/core/etl/tests/Flow/ETL/Tests/Double/RecordingLoader.php new file mode 100644 index 0000000000..dc05af5704 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/RecordingLoader.php @@ -0,0 +1,68 @@ +()`, `load# THROW`, `closure`, `closure THROW`, `discard` - and the + * error handler of every context it loads under. + */ +final class RecordingLoader implements Closure, Discardable, Loader +{ + /** + * @var list + */ + public array $handlers = []; + + /** + * @var list + */ + public array $log = []; + + public int $loadsCount = 0; + + public function __construct( + private readonly ?Throwable $loadFailure = null, + private readonly int $failingLoad = 1, + private readonly ?Throwable $closureFailure = null, + ) {} + + public function closure(FlowContext $context): void + { + if ($this->closureFailure !== null) { + $this->log[] = 'closure THROW'; + + throw $this->closureFailure; + } + + $this->log[] = 'closure'; + } + + public function discard(FlowContext $context): void + { + $this->log[] = 'discard'; + } + + public function load(Rows $rows, FlowContext $context): void + { + $this->loadsCount++; + $this->handlers[] = $context->errorHandler(); + + if ($this->loadFailure !== null && $this->loadsCount === $this->failingLoad) { + $this->log[] = 'load#' . $this->loadsCount . ' THROW'; + + throw $this->loadFailure; + } + + $this->log[] = 'load#' . $this->loadsCount . '(' . $rows->count() . ')'; + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/RecordingRule.php b/src/core/etl/tests/Flow/ETL/Tests/Double/RecordingRule.php new file mode 100644 index 0000000000..31bf4edc2a --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/RecordingRule.php @@ -0,0 +1,31 @@ + $log + */ + public function __construct( + private string $name, + private ArrayObject $log, + ) {} + + public function apply(LogicalPlan $plan, FlowContext $context): LogicalPlan + { + $this->log[] = $this->name; + + return $plan; + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/RecordingTransaction.php b/src/core/etl/tests/Flow/ETL/Tests/Double/RecordingTransaction.php new file mode 100644 index 0000000000..162b491af1 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/RecordingTransaction.php @@ -0,0 +1,59 @@ + + */ + public array $log = []; + + /** + * @var list + */ + public array $rolledBackFor = []; + + public function __construct( + private readonly ?Throwable $beginFailure = null, + private readonly ?Throwable $commitFailure = null, + private readonly ?Throwable $rollbackFailure = null, + ) {} + + public function begin(): void + { + $this->log[] = 'begin'; + + if ($this->beginFailure !== null) { + throw $this->beginFailure; + } + } + + public function commit(): void + { + $this->log[] = 'commit'; + + if ($this->commitFailure !== null) { + throw $this->commitFailure; + } + } + + public function rollback(Throwable $cause): void + { + $this->log[] = 'rollback'; + $this->rolledBackFor[] = $cause; + + if ($this->rollbackFailure !== null) { + throw $this->rollbackFailure; + } + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/RedefiningNode.php b/src/core/etl/tests/Flow/ETL/Tests/Double/RedefiningNode.php new file mode 100644 index 0000000000..328b22c205 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/RedefiningNode.php @@ -0,0 +1,55 @@ + + */ + public function children(): array + { + return [$this->input]; + } + + public function withChildren(array $children): self + { + return $children[0] === $this->input ? $this : new self($children[0], $this->redefined); + } + + public function rowCount(): RowCount + { + return RowCount::preserving; + } + + public function transparency(): Transparency + { + return Transparency::transparent; + } + + public function materialization(): Materialization + { + return Materialization::streaming; + } + + public function redefines(): Redefined + { + return $this->redefined; + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/RenameSelectRewrite.php b/src/core/etl/tests/Flow/ETL/Tests/Double/RenameSelectRewrite.php new file mode 100644 index 0000000000..223e428f12 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/RenameSelectRewrite.php @@ -0,0 +1,18 @@ +children()[0], 'name') : $node; + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/RepeatableExtractor.php b/src/core/etl/tests/Flow/ETL/Tests/Double/RepeatableExtractor.php index 6633f2af90..b01be67adc 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/RepeatableExtractor.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/RepeatableExtractor.php @@ -32,7 +32,7 @@ public function __construct( $this->wrapped = array_values($wrapped); } - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { yield new Rows($this->schema()); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/RowLessExtractor.php b/src/core/etl/tests/Flow/ETL/Tests/Double/RowLessExtractor.php index e4ba6f650d..3d2fed8e0e 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/RowLessExtractor.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/RowLessExtractor.php @@ -23,7 +23,7 @@ public function __construct( private Schema $schema, ) {} - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { $this->extractCalls++; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/SpineCopyingRule.php b/src/core/etl/tests/Flow/ETL/Tests/Double/SpineCopyingRule.php new file mode 100644 index 0000000000..6a243df2cd --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/SpineCopyingRule.php @@ -0,0 +1,31 @@ +of($plan->root, $this)); + } + + public function of(Node $node): Node + { + return $node instanceof Read ? new Read($node->extractor(), $node->limit(), $node->pathFilter()) : $node; + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/SpySink.php b/src/core/etl/tests/Flow/ETL/Tests/Double/SpySink.php new file mode 100644 index 0000000000..d5378c719e --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/SpySink.php @@ -0,0 +1,18 @@ +prefix = $prefix; + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/SpyTransformer.php b/src/core/etl/tests/Flow/ETL/Tests/Double/SpyTransformer.php new file mode 100644 index 0000000000..74953771a6 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/SpyTransformer.php @@ -0,0 +1,28 @@ +seen += $rows->count(); + + return $rows; + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/StopIgnoringExtractor.php b/src/core/etl/tests/Flow/ETL/Tests/Double/StopIgnoringExtractor.php index cf205b7a68..31b9ee48e4 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/StopIgnoringExtractor.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/StopIgnoringExtractor.php @@ -27,7 +27,7 @@ public function __construct( private readonly Rows $rows, ) {} - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { foreach (array_chunk($this->rows->all(), $this->batchSize()) as $chunk) { yield Rows::trusted($this->rows->schema(), $chunk); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/ThrowWhenRowMatches.php b/src/core/etl/tests/Flow/ETL/Tests/Double/ThrowWhenRowMatches.php index ef1a7c06b0..d8093317f4 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/ThrowWhenRowMatches.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/ThrowWhenRowMatches.php @@ -4,8 +4,8 @@ namespace Flow\ETL\Tests\Double; +use Flow\ETL\BoundStep; use Flow\ETL\FlowContext; -use Flow\ETL\Pipeline\BoundStep; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\Transformer; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/ThrowingAfterFirstBatchExtractor.php b/src/core/etl/tests/Flow/ETL/Tests/Double/ThrowingAfterFirstBatchExtractor.php index 01138e166e..ba618b08c6 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/ThrowingAfterFirstBatchExtractor.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/ThrowingAfterFirstBatchExtractor.php @@ -17,7 +17,7 @@ final class ThrowingAfterFirstBatchExtractor implements Extractor { - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { yield rows($this->schema(), row(['id' => 1])); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/ThrowingTransformer.php b/src/core/etl/tests/Flow/ETL/Tests/Double/ThrowingTransformer.php index 1ae2acdc3d..0a58937926 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/ThrowingTransformer.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/ThrowingTransformer.php @@ -4,8 +4,8 @@ namespace Flow\ETL\Tests\Double; +use Flow\ETL\BoundStep; use Flow\ETL\FlowContext; -use Flow\ETL\Pipeline\BoundStep; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\Transformer; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/UndescribableRowLessExtractor.php b/src/core/etl/tests/Flow/ETL/Tests/Double/UndescribableRowLessExtractor.php index a45125bf21..ffcdd0c264 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/UndescribableRowLessExtractor.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/UndescribableRowLessExtractor.php @@ -18,7 +18,7 @@ */ final class UndescribableRowLessExtractor implements Extractor { - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { return from_rows()->extract($context); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/VaryingBatchesExtractor.php b/src/core/etl/tests/Flow/ETL/Tests/Double/VaryingBatchesExtractor.php index 0aa29268f7..90bc7b0f4a 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/VaryingBatchesExtractor.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/VaryingBatchesExtractor.php @@ -26,7 +26,7 @@ public function __construct(Rows ...$batches) $this->batches = $batches; } - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { foreach ($this->batches as $batch) { yield $batch; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/WrappingLoader.php b/src/core/etl/tests/Flow/ETL/Tests/Double/WrappingLoader.php deleted file mode 100644 index 676595a64c..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/WrappingLoader.php +++ /dev/null @@ -1,45 +0,0 @@ - - */ - public array $wrapped; - - public function __construct(Loader ...$wrapped) - { - $this->wrapped = $wrapped; - } - - public function closure(FlowContext $context): void - { - foreach ($this->wrapped as $loader) { - if ($loader instanceof Closure) { - $loader->closure($context); - } - } - } - - public function load(Rows $rows, FlowContext $context): void - { - foreach ($this->wrapped as $loader) { - $loader->load($rows, $context); - } - } - - public function loaders(): array - { - return $this->wrapped; - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Fixtures/Join/AlwaysMeets.php b/src/core/etl/tests/Flow/ETL/Tests/Fixtures/Join/AlwaysMeets.php new file mode 100644 index 0000000000..972611841a --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Fixtures/Join/AlwaysMeets.php @@ -0,0 +1,26 @@ + $expectedArray + * @param null|int<1, max> $limit */ final public static function assertExtractedRowsAsArrayEquals( array $expectedArray, Extractor $extractor, ?FlowContext $flowContext = null, string $message = '', + ?int $limit = null, + Filter $pathFilter = new OnlyFiles(), ): void { $flowContext ??= flow_context(); $extractedRows = rows(schema()); - foreach ($extractor->extract($flowContext) as $nextRows) { + foreach (self::extracted($extractor, $flowContext, $limit, $pathFilter) as $nextRows) { $extractedRows = $extractedRows->merge($nextRows); } static::assertEquals($expectedArray, $extractedRows->toArray(), $message); } + /** + * @param null|int<1, max> $limit + */ final public static function assertExtractedRowsCount( int $expectedCount, Extractor $extractor, ?FlowContext $flowContext = null, string $message = '', + ?int $limit = null, + Filter $pathFilter = new OnlyFiles(), ): void { $flowContext ??= flow_context(); $totalRows = 0; - foreach ($extractor->extract($flowContext) as $rows) { + foreach (self::extracted($extractor, $flowContext, $limit, $pathFilter) as $rows) { $totalRows += $rows->count(); } static::assertSame($expectedCount, $totalRows, $message); } + /** + * @param null|int<1, max> $limit + */ final public static function assertExtractedRowsEquals( Rows $expectedRows, Extractor $extractor, ?FlowContext $flowContext = null, string $message = '', + ?int $limit = null, + Filter $pathFilter = new OnlyFiles(), ): void { $flowContext ??= flow_context(); $extractedRows = rows(schema()); - foreach ($extractor->extract($flowContext) as $nextRows) { + foreach (self::extracted($extractor, $flowContext, $limit, $pathFilter) as $nextRows) { $extractedRows = $extractedRows->merge($nextRows); } static::assertEquals($expectedRows, $extractedRows, $message); } + /** + * @param null|int<1, max> $limit + * + * @return Generator + */ + final public static function extracted( + Extractor $extractor, + FlowContext $context, + ?int $limit, + Filter $pathFilter, + ): Generator { + return $extractor instanceof FileExtractor + ? $extractor->extract($context, $limit, $pathFilter) + : $extractor->extract($context, $limit); + } + public function repositoryRoot(): string { $root = getenv('FLOW_MONOREPO_PROJECT_ROOT'); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/AnalyzeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/AnalyzeTest.php index 55fe42fb9a..742c6c1c55 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/AnalyzeTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/AnalyzeTest.php @@ -11,6 +11,7 @@ use Flow\ETL\Dataset\Statistics\HighResolutionTime; use Flow\ETL\FlowContext; use Flow\ETL\Rows; +use Flow\ETL\Tests\Double\InlineLoader; use Flow\ETL\Tests\FlowIntegrationTestCase; use Flow\ETL\Tests\Mother\MarketRowsMother; @@ -34,13 +35,14 @@ public function test_analyzing_an_inferred_array_source(): void $report = df($config) ->read(from_array(MarketRowsMother::fiveDays())->inferSchema(infer_schema())) ->collect() - ->run(static function (Rows $rows, FlowContext $context): void { + ->write(new InlineLoader(static function (Rows $rows, FlowContext $context): void { $clock = $context->config->clock(); if ($clock instanceof FakeClock) { $clock->modify('+5 minutes'); } - }, analyze()->withSchema()->withColumnStatistics()); + })) + ->run(analyze: analyze()->withSchema()->withColumnStatistics()); static::assertNotNull($report); static::assertSame(5, $report->statistics()->totalRows()); @@ -102,13 +104,14 @@ public function test_analyzing_csv_file_without_column_stats(): void $report = df($config) ->read(from_array(MarketRowsMother::fiveDays())->inferSchema(infer_schema())) ->collect() - ->run(static function (Rows $rows, FlowContext $context): void { + ->write(new InlineLoader(static function (Rows $rows, FlowContext $context): void { $clock = $context->config->clock(); if ($clock instanceof FakeClock) { $clock->modify('+5 minutes'); } - }, analyze()->withSchema()); + })) + ->run(analyze: analyze()->withSchema()); static::assertNotNull($report); static::assertSame(5, $report->statistics()->totalRows()); @@ -136,13 +139,14 @@ public function test_analyzing_csv_file_without_schema(): void $report = df($config) ->read(from_array(MarketRowsMother::fiveDays())) ->collect() - ->run(static function (Rows $rows, FlowContext $context): void { + ->write(new InlineLoader(static function (Rows $rows, FlowContext $context): void { $clock = $context->config->clock(); if ($clock instanceof FakeClock) { $clock->modify('+5 minutes'); } - }, analyze()); + })) + ->run(analyze: analyze()); static::assertNotNull($report); static::assertSame(5, $report->statistics()->totalRows()); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/BatchByTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/BatchByTest.php index 58552f4981..bde79c955a 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/BatchByTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/BatchByTest.php @@ -30,7 +30,7 @@ public function test_batch_by_column_with_min_size(): void ['order_id' => 5, 'item' => 'E'], ])) ->batchBy('order_id', minSize: 3) - ->run(callback: static function ($rows) use (&$batchCount, &$batchSizes): void { + ->forEach(static function ($rows) use (&$batchCount, &$batchSizes): void { $batchCount++; $batchSizes[] = $rows->count(); }); @@ -54,7 +54,7 @@ public function test_batch_by_column_without_min_size(): void ['order_id' => 3, 'item' => 'Widget', 'qty' => 1], ])) ->batchBy('order_id') - ->run(callback: static function ($rows) use (&$results, &$batchCount): void { + ->forEach(static function ($rows) use (&$results, &$batchCount): void { $batchCount++; $results = array_merge($results, $rows->toArray()); }); @@ -77,7 +77,7 @@ public function test_batch_by_preserves_referential_integrity(): void ['order_id' => 2, 'line' => 2], ])) ->batchBy('order_id') - ->run(callback: static function ($rows) use (&$batches): void { + ->forEach(static function ($rows) use (&$batches): void { $orderIds = array_unique(array_column($rows->toArray(), 'order_id')); $batches[] = $orderIds; }); @@ -97,7 +97,7 @@ public function test_batch_by_using_reference_object(): void ['customer_id' => 'B', 'order' => 3], ])) ->batchBy(ref('customer_id')) - ->run(callback: static function ($rows) use (&$batchCount): void { + ->forEach(static function ($rows) use (&$batchCount): void { $batchCount++; }); @@ -120,7 +120,7 @@ public function test_batch_by_with_large_group_exceeding_min_size(): void ['order_id' => 2, 'item' => 'F'], ])) ->batchBy('order_id', minSize: 2) - ->run(callback: static function ($rows) use (&$batchCount, &$batchSizes): void { + ->forEach(static function ($rows) use (&$batchCount, &$batchSizes): void { $batchCount++; $batchSizes[] = $rows->count(); }); @@ -142,7 +142,7 @@ public function test_batch_by_with_transformations(): void ])) ->batchBy('order_id') ->withEntry('total', ref('amount')->multiply(lit(2))) - ->run(callback: static function ($rows) use (&$results): void { + ->forEach(static function ($rows) use (&$results): void { $results = array_merge($results, $rows->toArray()); }); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/BranchingTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/BranchingTest.php index 2ae5ee4817..58f2fb8c74 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/BranchingTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/BranchingTest.php @@ -8,26 +8,25 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Memory\ArrayMemory; use Flow\ETL\Tests\Double\CallbackTransformation; +use Flow\ETL\Tests\Double\SpyLoader; use Flow\ETL\Tests\FlowIntegrationTestCase; +use Flow\ETL\Tests\Mother\RowsMother; use Flow\ETL\Transformation; +use function array_column; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\from_array; -use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\from_rows; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\schema; -use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\sum; use function Flow\ETL\DSL\to_branch; use function Flow\ETL\DSL\to_memory; final class BranchingTest extends FlowIntegrationTestCase { - public function test_a_branch_transformation_is_seeded_with_the_shape_it_is_fed(): void + public function test_a_branch_transformation_builds_on_the_columns_it_is_fed(): void { - $captured = null; - df() ->read(from_array([ ['id' => 1, 'group' => 'A'], @@ -36,19 +35,43 @@ public function test_a_branch_transformation_is_seeded_with_the_shape_it_is_fed( ->write(to_branch( ref('group')->equals(lit('A')), to_memory($memory = new ArrayMemory()), - )->withTransformation(new CallbackTransformation(static function (DataFrame $dataFrame) use ( - &$captured, - ): DataFrame { - $captured = $dataFrame->schema(); - - return $dataFrame->withEntry('group_name', lit('A')); - }))) + )->withTransformation(new CallbackTransformation(static fn(DataFrame $dataFrame): DataFrame => $dataFrame->withEntry( + 'group_name', + lit('A'), + )))) ->run(); - static::assertEquals(schema(int_schema('id', true), str_schema('group', true)), $captured); static::assertSame([['id' => 1, 'group' => 'A', 'group_name' => 'A']], $memory->dump()); } + public function test_a_branch_nothing_matches_never_loads_and_still_closes(): void + { + $spy = new SpyLoader(); + + df() + ->read(from_array([['id' => 1], ['id' => 2]])) + ->write(to_branch(lit(false), $spy)->withTransformation(new CallbackTransformation( + static fn(DataFrame $dataFrame): DataFrame => $dataFrame->select('id'), + ))) + ->run(); + + static::assertSame(0, $spy->loadsCount); + static::assertSame(1, $spy->closureCount); + } + + public function test_only_the_rows_matching_the_condition_reach_the_branch(): void + { + $spy = new SpyLoader(); + + df() + ->read(from_rows(...RowsMother::descendingIdBatches())) + ->write(to_branch(ref('id')->greaterThanEqual(lit(2)), $spy)) + ->run(); + + static::assertSame([2, 2], $spy->loadedRowCounts()); + static::assertSame([5, 4, 3, 2], array_column($spy->loadedRowsToArray(), 'id')); + } + public function test_branching(): void { df() diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/CacheTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/CacheTest.php index 771fee8cd3..d146e90064 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/CacheTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/CacheTest.php @@ -61,7 +61,7 @@ public function __construct(int $rowsets) $this->extractor = new FakeExtractor($rowsets); } - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { $this->extractions++; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/ConfigBuilderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/ConfigBuilderTest.php index 31fd4d402f..0d7e55e024 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/ConfigBuilderTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/ConfigBuilderTest.php @@ -11,6 +11,10 @@ use Flow\ETL\Config\Cache\CacheConfig; use Flow\ETL\Config\Sort\ExternalSortConfig; use Flow\ETL\Config\Sort\MemorySortConfig; +use Flow\ETL\Executor; +use Flow\ETL\Optimizer; +use Flow\ETL\Optimizer\Rule\PushLimitIntoSource; +use Flow\ETL\Planner; use Flow\ETL\Row\AdaptiveRowHydrator; use Flow\ETL\Row\PhpRowHydrator; use Flow\ETL\Tests\Double\SpySerializer; @@ -176,4 +180,35 @@ public function test_external_sort_storage_override(): void static::assertInstanceOf(ExternalSortConfig::class, $config->sort); static::assertSame($storage, $config->sort->bucketing->storage); } + + public function test_optimizer_defaults_to_optimizer_default(): void + { + static::assertEquals(Optimizer::default(), config_builder()->build()->optimizer()); + } + + public function test_optimizer_can_be_overridden(): void + { + $optimizer = Optimizer::default()->without(PushLimitIntoSource::class); + + static::assertSame($optimizer, config_builder()->optimizer($optimizer)->build()->optimizer()); + } + + public function test_the_planner_runs_the_configured_optimizer(): void + { + $optimizer = Optimizer::default()->without(PushLimitIntoSource::class); + + static::assertEquals(new Planner($optimizer), config_builder()->optimizer($optimizer)->build()->planner()); + } + + public function test_executor_defaults_to_an_executor(): void + { + static::assertEquals(new Executor(), config_builder()->build()->executor()); + } + + public function test_executor_can_be_overridden(): void + { + $executor = new Executor(); + + static::assertSame($executor, config_builder()->executor($executor)->build()->executor()); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/DisplayTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/DisplayTest.php index c2b98e210c..336ee7db3c 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/DisplayTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/DisplayTest.php @@ -69,7 +69,7 @@ public function schema(): Schema /** * @return \Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { for ($i = 0; $i < 20; $i++) { yield rows( @@ -145,7 +145,7 @@ public function schema(): Schema /** * @return \Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { for ($i = 0; $i < 5; $i++) { yield rows( diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/GroupByTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/GroupByTest.php index 628cd33578..e125ce1977 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/GroupByTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/GroupByTest.php @@ -704,7 +704,7 @@ public function test_standalone_avg_and_max_aggregation(): void row(['id' => 9, 'country' => 'US', 'age' => 50]), ))) ->aggregate([average(ref('age')), max(ref('age'))]) - ->run(function (Rows $rows): void { + ->forEach(function (Rows $rows): void { $this->assertSame([['age_avg' => 33.75, 'age_max' => 50]], $rows->toArray()); $this->assertEquals( schema(float_schema('age_avg', true), int_schema('age_max', true)), diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/LimitTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/LimitTest.php index 0fbc8af0cf..1336941293 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/LimitTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/LimitTest.php @@ -8,15 +8,23 @@ use Flow\ETL\Extractor; use Flow\ETL\Extractor\Signal; use Flow\ETL\FlowContext; +use Flow\ETL\Optimizer; +use Flow\ETL\Planner; +use Flow\ETL\Processor\TopNProcessor; use Flow\ETL\Rows; use Flow\ETL\Schema; +use Flow\ETL\Tests\Context\PipelineSteps; +use Flow\ETL\Tests\Double\RecordingFileExtractor; use Flow\ETL\Tests\FlowIntegrationTestCase; use Generator; +use PHPUnit\Framework\Attributes\DataProvider; use function array_column; use function array_map; +use function array_slice; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\from_array; +use function Flow\ETL\DSL\from_data_frame; use function Flow\ETL\DSL\from_rows; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\integer_schema; @@ -91,7 +99,7 @@ public function schema(): Schema * * @return \Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { for ($i = 0; $i < 20; $i++) { yield rows(schema(integer_schema('id')), row(['id' => $i])); @@ -121,7 +129,7 @@ public function schema(): Schema * * @return \Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { for ($i = 0; $i < 1000; $i++) { yield rows(schema(integer_schema('id')), row(['id' => $i + 1]), row(['id' => $i + 2])); @@ -177,7 +185,7 @@ public function schema(): Schema * * @return \Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { for ($i = 0; $i < 1000; $i++) { yield rows( @@ -234,7 +242,7 @@ public function schema(): Schema * * @return \Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { for ($i = 0; $i < 1000; $i++) { yield rows(schema(integer_schema('id')), row(['id' => $i + 1]), row(['id' => $i + 2])); @@ -267,7 +275,7 @@ public function schema(): Schema * * @return \Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { for ($i = 0; $i < 100; $i++) { yield rows(schema(integer_schema('id')), row(['id' => $i + 1]), row(['id' => $i + 2])); @@ -300,7 +308,7 @@ public function schema(): Schema * * @return \Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { for ($i = 0; $i < 5; $i++) { yield rows(schema(integer_schema('id')), row(['id' => $i])); @@ -343,4 +351,78 @@ public function test_limit_after_a_filter_returns_exactly_the_limit(): void ), ); } + + public function test_a_limit_over_a_sort_runs_as_a_top_n_with_the_sorts_result(): void + { + $data = []; + + foreach (range(1, 50) as $i) { + $data[] = ['id' => $i, 'group' => $i % 7]; + } + + $sorted = df() + ->read(from_array($data)) + ->batchSize(4) + ->sortBy([ref('group')->desc(), ref('id')]) + ->fetch() + ->toArray(); + $frame = df() + ->read(from_array($data)) + ->batchSize(4) + ->sortBy([ref('group')->desc(), ref('id')]) + ->limit(5); + + static::assertSame(array_slice($sorted, 0, 5), $frame->fetch()->toArray()); + $plan = $frame->explain(); + static::assertContains( + TopNProcessor::class, + PipelineSteps::classes( + (new Planner(Optimizer::default())) + ->plan($plan->logical, $plan->context) + ->root() + ->segments(), + ), + ); + } + + public function test_offset_then_limit_returns_the_page(): void + { + static::assertSame( + [['id' => 101], ['id' => 102], ['id' => 103]], + df() + ->read(from_array(array_map(static fn(int $i): array => ['id' => $i], range(1, 500)))) + ->offset(100) + ->limit(3) + ->fetch() + ->toArray(), + ); + } + + /** + * @return Generator + */ + public static function read_frame_schemas(): Generator + { + yield 'derived schema' => [false]; + yield 'declared schema' => [true]; + } + + #[DataProvider('read_frame_schemas')] + public function test_a_limit_over_a_read_frame_reaches_that_frames_source(bool $declared): void + { + $source = new RecordingFileExtractor( + schema(int_schema('id')), + rows(schema(int_schema('id')), ...array_map(static fn(int $id) => row(['id' => $id]), range(1, 6))), + ); + $nested = from_data_frame(df()->read($source)); + + if ($declared) { + $nested->withSchema(schema(int_schema('id'))); + } + + $rows = df()->read($nested)->offset(1)->limit(2)->fetch(); + + static::assertSame([['id' => 2], ['id' => 3]], $rows->toArray()); + static::assertSame([3], $source->limits); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/MathTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/MathTest.php index 70125e5119..c345d249d8 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/MathTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/MathTest.php @@ -7,7 +7,6 @@ use Flow\ETL\Rows; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\analyze; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\from_rows; @@ -38,9 +37,9 @@ public function test_aggregations_on_floats(): void row(['id' => 10, 'price' => 45.0, 'quantity' => 5, 'weight' => 3.0]), ))) ->aggregate([sum(ref('price')), sum(ref('weight'))]) - ->run(static function (Rows $r) use (&$rows): void { + ->forEach(static function (Rows $r) use (&$rows): void { $rows = $rows->merge($r); - }, analyze: analyze()->withSchema()); + }); static::assertSame( [ @@ -69,9 +68,9 @@ public function test_mathematical_operations_on_floats(): void ))) ->withEntry('discount', ref('price')->multiply(-0.1)) ->withEntry('total_weight', ref('weight')->multiply(ref('quantity'))) - ->run(static function (Rows $r) use (&$rows): void { + ->forEach(static function (Rows $r) use (&$rows): void { $rows = $rows->merge($r); - }, analyze: analyze()->withSchema()); + }); static::assertEquals( [ diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/OffsetTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/OffsetTest.php index 111fa666aa..a33bf10584 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/OffsetTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/OffsetTest.php @@ -135,7 +135,7 @@ public function schema(): Schema * * @return \Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { for ($i = 0; $i < 10; $i++) { yield rows(schema(integer_schema('id')), row(['id' => $i + 1])); @@ -178,7 +178,7 @@ public function schema(): Schema * * @return \Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { for ($i = 0; $i < 5; $i++) { yield rows(schema(integer_schema('id')), row(['id' => $i + 1])); @@ -223,7 +223,7 @@ public function schema(): Schema * * @return \Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { for ($i = 0; $i < 100; $i++) { yield rows( @@ -300,7 +300,7 @@ public function schema(): Schema * * @return \Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { for ($i = 0; $i < 10; $i++) { yield rows(schema(integer_schema('id')), row(['id' => $i + 1])); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/PartitioningTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/PartitioningTest.php index 996deb8823..a563a6cdf9 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/PartitioningTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/PartitioningTest.php @@ -5,12 +5,17 @@ namespace Flow\ETL\Tests\Integration\DataFrame; use DateTimeImmutable; -use Flow\ETL\Function\ScalarFunction; +use Flow\ETL\Extractor; use Flow\ETL\Rows; use Flow\ETL\Tests\FlowIntegrationTestCase; use Flow\Types\Exception\InvalidArgumentException; +use Generator; +use PHPUnit\Framework\Attributes\DataProvider; +use function array_column; use function array_map; +use function array_unique; +use function array_values; use function file_exists; use function Flow\ETL\Adapter\Text\from_text; use function Flow\ETL\Adapter\Text\to_text; @@ -51,14 +56,14 @@ public function test_a_partition_filter_with_a_numeric_literal_binds_over_a_stri 7, df() ->read(from_text($glob)) - ->filterPartitions(ref('year')->between(lit(2020), lit(2025))) + ->filter(ref('year')->between(lit(2020), lit(2025))) ->fetch(), ); static::assertCount( 5, df() ->read(from_text($glob)) - ->filterPartitions(ref('year')->between(lit(2023), lit(2025))) + ->filter(ref('year')->between(lit(2023), lit(2025))) ->fetch(), ); } @@ -70,20 +75,30 @@ public function test_a_partition_filter_binds_when_the_partition_type_is_declare . '/Fixtures/Partitioning/multi_partition_pruning_test/year=*/month=*/day=*/*.txt')->partitionTypes( partition_types(year: type_integer()), )) - ->filterPartitions(ref('year')->equals(lit(2023))) + ->filter(ref('year')->equals(lit(2023))) ->fetch(); static::assertCount(5, $rows); } - public function test_a_partition_filter_on_an_extractor_without_partition_columns_is_not_gated(): void + #[DataProvider('file_listings')] + public function test_a_partition_filter_on_a_file_listing_prunes_it(Extractor $extractor): void + { + $rows = df() + ->read($extractor) + ->filter(ref('year')->equals(lit('2023'))) + ->fetch(); + + static::assertCount(5, $rows); + static::assertSame(['2023'], array_values(array_unique(array_column($rows->toArray(), 'year')))); + } + + public static function file_listings(): Generator { - // The same literal throws at bind on from_text(), which declares its partition columns $glob = __DIR__ . '/Fixtures/Partitioning/multi_partition_pruning_test/**/*.txt'; - $incomparable = static fn(): ScalarFunction => ref('year')->equals(lit(new DateTimeImmutable('2024-01-01'))); - static::assertCount(0, df()->read(from_path_partitions($glob))->filterPartitions($incomparable())->fetch()); - static::assertCount(0, df()->read(files($glob))->filterPartitions($incomparable())->fetch()); + yield 'from_path_partitions' => [from_path_partitions($glob)]; + yield 'files' => [files($glob)]; } public function test_a_partition_filter_with_an_incomparable_literal_is_refused_at_bind(): void @@ -96,20 +111,21 @@ public function test_a_partition_filter_with_an_incomparable_literal_is_refused_ df() ->read(from_text(__DIR__ . '/Fixtures/Partitioning/multi_partition_pruning_test/year=*/month=*/day=*/*.txt')) - ->filterPartitions(ref('year')->equals(lit(new DateTimeImmutable('2024-01-01')))); + ->filter(ref('year')->equals(lit(new DateTimeImmutable('2024-01-01')))) + ->fetch(); } - public function test_filter_partitions_rebinds(): void + public function test_pruning_keeps_the_source_schema(): void { - // "tier" is nullable while both paths are listed - only one of them carries it - and becomes - // NOT NULL once the filter leaves only the path that does + // "tier" is nullable because only one of the two listed paths carries it; pruning the read to + // that path does not change the schema - it is a property of the source, not of the read $df = df()->read(from_text(__DIR__ . '/Fixtures/Partitioning/rebind/**/*.txt')); static::assertTrue($df->schema()->get('tier')->isNullable()); - $df->filterPartitions(ref('region')->equals(lit('eu'))); + $df->filter(ref('region')->equals(lit('eu'))); - static::assertFalse($df->schema()->get('tier')->isNullable()); + static::assertTrue($df->schema()->get('tier')->isNullable()); static::assertEquals($df->schema(), $df->fetch()->schema()); } @@ -151,6 +167,7 @@ public function test_overwrite_save_mode_not_dropping_old_partitions(): void . ltrim(str_replace('\\', '/', __DIR__), '/') . '/Fixtures/Partitioning/overwrite/date=2024-04-01/file.txt', 'partitions' => ['date' => '2024-04-01'], + 'date' => '2024-04-01', ], [ 'path' => @@ -158,6 +175,7 @@ public function test_overwrite_save_mode_not_dropping_old_partitions(): void . ltrim(str_replace('\\', '/', __DIR__), '/') . '/Fixtures/Partitioning/overwrite/date=2024-04-02/file.txt', 'partitions' => ['date' => '2024-04-02'], + 'date' => '2024-04-02', ], [ 'path' => @@ -165,6 +183,7 @@ public function test_overwrite_save_mode_not_dropping_old_partitions(): void . ltrim(str_replace('\\', '/', __DIR__), '/') . '/Fixtures/Partitioning/overwrite/date=2024-04-03/file.txt', 'partitions' => ['date' => '2024-04-03'], + 'date' => '2024-04-03', ], [ 'path' => @@ -172,6 +191,7 @@ public function test_overwrite_save_mode_not_dropping_old_partitions(): void . ltrim(str_replace('\\', '/', __DIR__), '/') . '/Fixtures/Partitioning/overwrite/date=2024-04-04/file.txt', 'partitions' => ['date' => '2024-04-04'], + 'date' => '2024-04-04', ], ], $actualData, @@ -256,22 +276,25 @@ public function test_partitioning_by_path_placeholders_only(): void static::assertFileExists($output . '/2024/03/789-DE.txt'); static::assertFileExists($output . '/2025/01/555-FR.txt'); - df()->read(from_text($output - . '/{order-year}/{order-month}/{order-name}.txt'))->run(function (Rows $rows): void { - // the placeholders put the values in the path, and the read takes them back from it - $this->assertSame( - ['text', 'order-month', 'order-name', 'order-year'], - $rows->schema()->references()->names(), - ); - }); + df() + ->read(from_text($output . '/{order-year}/{order-month}/{order-name}.txt')) + ->forEach(function (Rows $rows): void { + // the placeholders put the values in the path, and the read takes them back from it + $this->assertSame( + ['text', 'order-month', 'order-name', 'order-year'], + $rows->schema()->references()->names(), + ); + }); - df()->read(from_text($output . '/**/*.txt'))->run(function (Rows $rows): void { - $this->assertSame(['text'], $rows->schema()->references()->names()); - }); + df() + ->read(from_text($output . '/**/*.txt')) + ->forEach(function (Rows $rows): void { + $this->assertSame(['text'], $rows->schema()->references()->names()); + }); $prunedRows = df() ->read(from_text($output . '/{order-year}/{order-month}/{order-name}.txt')) - ->filterPartitions(ref('order-month')->equals(lit('01'))) + ->filter(ref('order-month')->equals(lit('01'))) ->fetch(); static::assertCount(1, $prunedRows); @@ -283,9 +306,9 @@ public function test_pruning_multiple_partitions(): void $rows = df() ->read(from_text(__DIR__ . '/Fixtures/Partitioning/multi_partition_pruning_test/year=*/month=*/day=*/*.txt')) - ->filterPartitions(ref('year')->cast('int')->greaterThanEqual(lit(2023))) - ->filterPartitions(ref('month')->cast('int')->greaterThanEqual(lit(1))) - ->filterPartitions(ref('day')->cast('int')->lessThan(lit(3))) + ->filter(ref('year')->cast('int')->greaterThanEqual(lit(2023))) + ->filter(ref('month')->cast('int')->greaterThanEqual(lit(1))) + ->filter(ref('day')->cast('int')->lessThan(lit(3))) ->filter(ref('text')->notEquals(lit('something'))) ->withEntry('day', ref('day')->cast('int')) ->collect() @@ -297,12 +320,36 @@ public function test_pruning_multiple_partitions(): void static::assertSame([1, 2], $days); } + public function test_a_mixed_predicate_prunes_on_its_partition_conjunct_and_still_filters_rows(): void + { + $glob = __DIR__ . '/Fixtures/Partitioning/multi_partition_pruning_test/year=*/month=*/day=*/*.txt'; + + static::assertSame( + df() + ->read(from_text($glob)) + ->filter(ref('year')->cast('int')->greaterThanEqual(lit(2023))) + ->filter(ref('text')->notEquals(lit('something'))) + ->fetch() + ->toArray(), + df() + ->read(from_text($glob)) + ->filter( + ref('year') + ->cast('int') + ->greaterThanEqual(lit(2023)) + ->and(ref('text')->notEquals(lit('something'))), + ) + ->fetch() + ->toArray(), + ); + } + public function test_pruning_single_partition(): void { $rows = df() ->read(from_text(__DIR__ . '/Fixtures/Partitioning/multi_partition_pruning_test/year=*/month=*/day=*/*.txt')) - ->filterPartitions( + ->filter( ref('year') ->cast('string') ->concat( diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/PerRunPlanTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/PerRunPlanTest.php new file mode 100644 index 0000000000..02ded31e9a --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/PerRunPlanTest.php @@ -0,0 +1,64 @@ +read(from_array([['id' => 1], ['id' => 2], ['id' => 3], ['id' => 4], ['id' => 5]])) + ->limit(3); + + static::assertCount(3, $dataFrame->fetch()); + static::assertCount(3, $dataFrame->fetch()); + } + + public function test_a_stateful_transformer_starts_from_its_constructed_state_on_every_run(): void + { + $dataFrame = df() + ->read(from_array([['id' => 1], ['id' => 2], ['id' => 3]])) + ->transform(new AddRowIndexTransformer('idx', StartFrom::ZERO)); + + static::assertSame([0, 1, 2], array_column($dataFrame->fetch()->toArray(), 'idx')); + static::assertSame([0, 1, 2], array_column($dataFrame->fetch()->toArray(), 'idx')); + } + + public function test_the_users_own_transformer_keeps_its_state_across_runs(): void + { + $transformer = new SpyTransformer(); + $dataFrame = df()->read(from_array([['id' => 1], ['id' => 2], ['id' => 3]]))->transform($transformer); + + $dataFrame->run(); + $dataFrame->run(); + + static::assertSame(6, $transformer->seen); + } + + public function test_a_side_root_that_hit_its_limit_hits_its_own_limit_on_the_next_run(): void + { + $loader = new SpyLoader(); + $dataFrame = df() + ->read(from_array([['id' => 1], ['id' => 2], ['id' => 3]])) + ->write(new Transformed(limit(1), $loader)); + + $dataFrame->run(); + $dataFrame->run(); + + static::assertSame([1, 1], $loader->loadedRowCounts()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/PlanBindTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/PlanBindTest.php index f5f253bac6..79dd806e45 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/PlanBindTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/PlanBindTest.php @@ -9,7 +9,9 @@ use Flow\ETL\Exception\SchemaDefinitionNotFoundException; use Flow\ETL\Exception\SchemaNotDerivableException; use Flow\ETL\Join\Join; +use Flow\ETL\Memory\ArrayMemory; use Flow\ETL\Tests\Double\CountingExtractor; +use Flow\ETL\Tests\Double\RepeatableExtractor; use Flow\ETL\Tests\FlowTestCase; use Flow\Types\Exception\InvalidArgumentException; use Generator; @@ -35,6 +37,7 @@ use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\sum; +use function Flow\ETL\DSL\to_memory; use function Flow\ETL\DSL\window; use function Flow\ETL\DSL\with_entry; @@ -271,13 +274,58 @@ public function test_a_discovering_pivot_over_a_non_repeatable_source_is_refused $this->expectExceptionMessage('cannot read its dataset twice'); df() - ->read(from_data_frame(df()->read(from_array([ - ['product' => 'Banana', 'country' => 'USA', 'amount' => 1000], - ])))) + ->read(from_data_frame(df()->read(new RepeatableExtractor(false)))) ->groupBy([ref('product')]) ->pivot(ref('country'), discover_pivot_values()); } + public function test_a_discovering_pivot_over_a_join_with_a_non_repeatable_side_is_refused(): void + { + $this->expectException(SchemaNotDerivableException::class); + $this->expectExceptionMessage('cannot read its dataset twice'); + + df() + ->read(from_array([['k' => 'a', 'v' => 1], ['k' => 'b', 'v' => 2]])) + ->join(df()->read(new RepeatableExtractor(false)), join_on(['k' => 'k'])) + ->groupBy('k') + ->pivot(ref('p'), discover_pivot_values()); + } + + public function test_a_discovering_pivot_over_a_nested_repeatable_frame_is_allowed(): void + { + static::assertSame( + [['product' => 'Banana', 'USA' => 1000.0]], + df() + ->read(from_data_frame(df()->read(from_array([ + ['product' => 'Banana', 'country' => 'USA', 'amount' => 1000], + ])))) + ->groupBy([ref('product')]) + ->pivot(ref('country'), discover_pivot_values()) + ->aggregate(sum(ref('amount'))) + ->fetch() + ->toArray(), + ); + } + + public function test_pivot_discovery_does_not_run_the_frames_sinks(): void + { + $memory = new ArrayMemory(); + + $rows = df() + ->read(from_array([['k' => 'a', 'p' => 'x', 'v' => 1], ['k' => 'b', 'p' => 'y', 'v' => 2]])) + ->write(to_memory($memory)) + ->groupBy('k') + ->pivot(ref('p'), discover_pivot_values()) + ->aggregate(sum(ref('v'))) + ->fetch(); + + static::assertCount(2, $memory->dump()); + static::assertSame( + [['k' => 'a', 'x' => 1.0, 'y' => null], ['k' => 'b', 'x' => null, 'y' => 2.0]], + $rows->toArray(), + ); + } + public function test_discovered_pivot_values_scan_the_source_once_at_build(): void { $extractor = new CountingExtractor( diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/SinglePlanTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/SinglePlanTest.php new file mode 100644 index 0000000000..e67ca3cf52 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/SinglePlanTest.php @@ -0,0 +1,156 @@ +read(from_array([['id' => 1, 'n' => 'a'], ['id' => 2, 'n' => 'b']]))->write(to_memory($memory)); + + $rows = df() + ->read(from_array([['id' => 1]])) + ->join($right, join_on(['id' => 'id'], 'r_')) + ->fetch(); + + static::assertSame(1, $rows->count()); + static::assertCount(2, $memory->dump()); + } + + public function test_a_read_frame_wrapped_in_another_extractor_still_reads(): void + { + $a = df()->read(from_array([['id' => 1]])); + $b = df()->read(from_array([['id' => 2]])); + + static::assertSame( + [['id' => 1], ['id' => 2]], + df() + ->read(from_all(from_data_frame($a), from_data_frame($b))) + ->fetch() + ->toArray(), + ); + } + + public function test_a_declared_schema_re_types_the_read_frames_rows(): void + { + $inner = df()->read(from_array([['id' => '1']])); + + static::assertSame( + [['id' => 1]], + df() + ->read(from_data_frame($inner)->withSchema(schema(int_schema('id')))) + ->fetch() + ->toArray(), + ); + } + + public function test_a_sink_inside_a_read_frame_receives_every_row_under_an_outer_limit(): void + { + $memory = new ArrayMemory(); + $inner = df()->read(from_array([['id' => 1], ['id' => 2], ['id' => 3]]))->write(to_memory($memory)); + + $rows = df()->read(from_data_frame($inner))->limit(1)->fetch(); + + static::assertSame(1, $rows->count()); + static::assertCount(3, $memory->dump()); + } + + public function test_a_joined_frame_is_optimized_with_the_outer_frames_optimizer(): void + { + $source = new RecordingFileExtractor( + schema(int_schema('id')), + rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])), + ); + $right = df(config_builder()->optimizer(new Optimizer()))->read($source)->limit(1); + + df() + ->read(from_array([['id' => 1]])) + ->join($right, join_on(['id' => 'id'], 'r_')) + ->fetch(); + + static::assertSame([1], $source->limits); + } + + public function test_a_joined_frames_own_error_handler_is_ignored(): void + { + $right = df() + ->read(from_array([['id' => 1]])) + ->transform(new ThrowingTransformer(new RuntimeException('right boom'))) + ->onError(new IgnoreError()); + + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('right boom'); + + df() + ->read(from_array([['id' => 1]])) + ->join($right, join_on(['id' => 'id'], 'r_')) + ->fetch(); + } + + public function test_a_stateful_step_both_sides_of_a_self_join_share_runs_once_per_side(): void + { + $frame = df() + ->read(from_array([['id' => 1], ['id' => 2]])) + ->transform(new AddRowIndexTransformer('index', StartFrom::ZERO)); + + static::assertSame( + [ + ['id' => 1, 'index' => 0, 'r_id' => 1, 'r_index' => 0], + ['id' => 2, 'index' => 1, 'r_id' => 2, 'r_index' => 1], + ], + $frame + ->join($frame, join_on(['index' => 'index'], 'r_')) + ->fetch() + ->toArray(), + ); + } + + public function test_a_filter_pushed_into_a_source_both_sides_share_leaves_the_joined_side_unfiltered(): void + { + $source = PartitionedSourceMother::yearMonth(); + $base = df()->read($source); + $joined = df()->read(from_array([['k' => 1]]))->crossJoin($base, 'b_'); + + $base + ->filter(ref('year')->equals(lit(2023))) + ->crossJoin($joined, 'j_') + ->fetch(); + + $accepts2024 = static fn(Filter $filter): bool => $filter->accept(PartitionedSourceMother::file( + 'year=2024/month=08', + )); + + static::assertCount(2, $source->pathFilters); + static::assertCount(1, array_filter($source->pathFilters, $accepts2024)); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/TransformerLoaderBlockingOperationsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/SinkRootBlockingOperationsTest.php similarity index 83% rename from src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/TransformerLoaderBlockingOperationsTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/SinkRootBlockingOperationsTest.php index 425e69c7cc..42c2a85056 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/TransformerLoaderBlockingOperationsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/SinkRootBlockingOperationsTest.php @@ -2,21 +2,24 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Integration\Loader; +namespace Flow\ETL\Tests\Integration\DataFrame; use Flow\ETL\DataFrame; use Flow\ETL\Exception\ConstraintViolationException; use Flow\ETL\Join\Join; use Flow\ETL\Tests\Double\CallbackTransformation; use Flow\ETL\Tests\Double\SpyLoader; +use Flow\ETL\Tests\Double\ThrowWhenRowMatches; use Flow\ETL\Tests\FlowIntegrationTestCase; use Flow\ETL\Tests\Mother\RowsMother; +use RuntimeException; use function array_column; use function Flow\ETL\DSL\average; use function Flow\ETL\DSL\constraint_unique; use function Flow\ETL\DSL\data_frame; use function Flow\ETL\DSL\df; +use function Flow\ETL\DSL\from_array; use function Flow\ETL\DSL\from_cache; use function Flow\ETL\DSL\from_rows; use function Flow\ETL\DSL\join_on; @@ -27,27 +30,47 @@ use function Flow\ETL\DSL\row_number; use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\skip_rows_handler; use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\sum; use function Flow\ETL\DSL\to_transformation; use function Flow\ETL\DSL\window; /** - * A Transformation given to to_transformation() expands into a nested DataFrame that is driven ONCE per outer run, - * over a long-lived source fed batch by batch and drained by closure(). A Processor placed there therefore answers - * exactly as it would on the outer frame, and a blocking operation buffers proportional to the data - the same cost - * it has outside a Transformation. + * A Transformation given to to_transformation() becomes a sink root: one sink pipeline per run, fed batch by batch + * and drained when the run ends. A Processor placed there therefore answers exactly as it would on the outer frame, + * and a blocking operation buffers proportional to the data - the same cost it has outside a Transformation. * * The values below are the outer-frame ground truth: running the same operation on the outer frame produces them - * byte for byte. If one of them starts failing, the nested stream regressed - do not "fix" the assertion. + * byte for byte. If one of them starts failing, the sink root regressed - do not "fix" the assertion. * * See documentation/components/core/transformations.md. */ -final class TransformerLoaderBlockingOperationsTest extends FlowIntegrationTestCase +final class SinkRootBlockingOperationsTest extends FlowIntegrationTestCase { + public function test_a_drain_failure_under_skip_rows_completes_and_drops_the_whole_buffered_batch(): void + { + $spy = new SpyLoader(); + + df() + ->read(from_array([['id' => 1], ['id' => 2], ['id' => 3], ['id' => 4]])) + ->batchSize(2) + ->onError(skip_rows_handler()) + ->write(to_transformation( + new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df->collect()->with( + new ThrowWhenRowMatches('id', 3, new RuntimeException('boom')), + )), + $spy, + )) + ->run(); + + static::assertSame(0, $spy->loadsCount); + static::assertSame(1, $spy->closureCount); + } + public function test_aggregate_inside_a_transformation_aggregates_the_whole_stream(): void { - // A2 - one result row for the stream, not one per batch. + // One result row for the stream, not one per batch. $spy = new SpyLoader(); $sumV = new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df->aggregate([sum(ref('v'))])); @@ -59,7 +82,7 @@ public function test_aggregate_inside_a_transformation_aggregates_the_whole_stre public function test_batch_by_inside_a_transformation_batches_by_group_across_the_stream(): void { - // A7 - chunks are cut at the group boundaries now that the whole stream flows through one stream. + // Chunks are cut at the group boundaries of the whole stream, not of each source batch. $spy = new SpyLoader(); $batchByGroup = new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df->batchBy(ref('g'))); @@ -84,7 +107,7 @@ public function test_batch_by_inside_a_transformation_batches_by_group_across_th public function test_cache_inside_a_transformation_persists_the_whole_stream(): void { - // A9 - counting loads proves nothing here, the run always reported all 6 rows; the cache read-back is what + // Counting loads proves nothing here, the run always reported all 6 rows; the cache read-back is what // shows the whole stream was persisted under the user-chosen id. $spy = new SpyLoader(); $cacheRows = new CallbackTransformation( @@ -99,7 +122,7 @@ public function test_cache_inside_a_transformation_persists_the_whole_stream(): public function test_collect_inside_a_transformation_collects_the_whole_stream(): void { - // A10 - one load of 6 rows. This is the buffering cost the repair accepts: collect() inside a Transformation + // One load of 6 rows. This is the buffering cost a blocking operation has: collect() inside a Transformation // holds the stream in memory exactly as it does on an outer frame. $spy = new SpyLoader(); $collectRows = new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df->collect()); @@ -134,7 +157,7 @@ public function test_constrain_inside_a_transformation_accumulates_across_batche public function test_drop_duplicates_inside_a_transformation_deduplicates_globally(): void { // REGRESSION GUARD - asserts CORRECT behaviour. DropDuplicatesTransformer is a Transformer holding its - // hashes, and the memoized nested frame keeps it alive across batches. + // hashes, and the sink pipeline keeps it alive for the whole run. $spy = new SpyLoader(); $dedupByGroup = new CallbackTransformation(static function (DataFrame $df): DataFrame { return $df->dropDuplicates(ref('g')); @@ -151,7 +174,7 @@ public function test_drop_duplicates_inside_a_transformation_deduplicates_global public function test_group_by_aggregate_inside_a_transformation_merges_groups_across_batches(): void { - // A3 - groups are merged across batches, giving the 2 rows the outer frame gives. + // Groups are merged across batches, giving the 2 rows the outer frame gives. $spy = new SpyLoader(); $sumVByGroup = new CallbackTransformation(static function (DataFrame $df): DataFrame { return $df->groupBy([ref('g')])->aggregate(sum(ref('v'))); @@ -216,14 +239,14 @@ public function test_limit_inside_a_transformation_applies_across_the_whole_stre static::assertSame([5, 4, 3], array_column($spy->loadedRowsToArray(), 'id')); static::assertSame([2, 1], $spy->loadedRowCounts()); - // I9: the terminated fiber skips the drain, but closure() is still forwarded, so a file loader never orphans + // The terminated fiber skips the drain, but closure() is still forwarded, so a file loader never orphans // its temporary file on a limited run. static::assertSame(1, $spy->closureCount); } public function test_offset_inside_a_transformation_skips_across_batches(): void { - // A8 - the offset is consumed once, over the stream, instead of inside every batch. + // The offset is consumed once, over the stream, instead of inside every batch. $spy = new SpyLoader(); $skipTwo = new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df->offset(2)); @@ -263,7 +286,7 @@ public function test_repartition_inside_a_transformation_regroups_the_whole_stre public function test_pivot_inside_a_transformation_pivots_the_whole_stream(): void { - // A6 - one pivoted set for the stream. Every row carries both pivoted columns in Schema order, + // One pivoted set for the stream. Every row carries both pivoted columns in Schema order, // the group's own value and null for the other. $spy = new SpyLoader(); $pivotGroupSums = new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df @@ -285,7 +308,7 @@ public function test_pivot_inside_a_transformation_pivots_the_whole_stream(): vo public function test_row_number_inside_a_transformation_numbers_the_whole_stream(): void { - // A5 - an unpartitioned window covers the stream, so the numbering runs 1..6 over the ordered rows. + // An unpartitioned window covers the stream, so the numbering runs 1..6 over the ordered rows. $spy = new SpyLoader(); $numberByValue = new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df->withEntry( 'rn', @@ -313,7 +336,7 @@ public function test_row_number_inside_a_transformation_numbers_the_whole_stream public function test_sort_by_inside_a_transformation_sorts_the_whole_stream(): void { - // A1 - the stream is sorted, not each batch on its own. + // The stream is sorted, not each batch on its own. $spy = new SpyLoader(); $sortById = new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df->sortBy([ref('id')])); @@ -323,10 +346,9 @@ public function test_sort_by_inside_a_transformation_sorts_the_whole_stream(): v static::assertSame([0, 1, 2, 3, 4, 5], array_column($spy->loadedRowsToArray(), 'id')); } - public function test_the_nested_frame_is_built_once_per_loader(): void + public function test_the_transformation_is_expanded_once_per_run(): void { - // The Transformation is expanded when the first batch arrives and never again, so the fiber drives one - // pipeline for the whole run. + // The Transformation is expanded once, when write() builds the plan, so one sink pipeline serves the run. $expansions = 0; $spy = new SpyLoader(); $reBatch = new CallbackTransformation(static function (DataFrame $df) use (&$expansions): DataFrame { @@ -343,8 +365,8 @@ public function test_the_nested_frame_is_built_once_per_loader(): void public function test_until_inside_a_transformation_applies_across_the_whole_stream(): void { - // REGRESSION GUARD - asserts CORRECT behaviour. UntilTransformer is a Transformer and its STOP propagates out - // of the nested frame. Identical to running until() on the outer frame. + // REGRESSION GUARD - asserts CORRECT behaviour. UntilTransformer is a Transformer and its STOP ends the side + // pipeline. Identical to running until() on the outer frame. $spy = new SpyLoader(); $untilValueReachesThree = new CallbackTransformation(static function (DataFrame $df): DataFrame { return $df->until(ref('v')->lessThan(lit(3))); @@ -361,7 +383,7 @@ public function test_until_inside_a_transformation_applies_across_the_whole_stre public function test_window_partition_by_inside_a_transformation_covers_the_whole_stream(): void { - // A4 - each partition holds every row of its group across the stream, so the averages are the group averages. + // Each partition holds every row of its group across the stream, so the averages are the group averages. $spy = new SpyLoader(); $averageOverGroup = new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df->withEntry( 'avg', diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/SinkRootTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/SinkRootTest.php new file mode 100644 index 0000000000..eca4b01a2c --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/SinkRootTest.php @@ -0,0 +1,821 @@ +read(from_array([ + ['name' => 'Alice', 'age' => 30], + ['name' => 'Bob', 'age' => 25], + ['name' => 'Charlie', 'age' => 35], + ])) + ->collect() + ->write(to_transformation(add_row_index('row_num', StartFrom::ONE), to_memory($memory))) + ->run(); + + static::assertSame( + [ + ['name' => 'Alice', 'age' => 30, 'row_num' => 1], + ['name' => 'Bob', 'age' => 25, 'row_num' => 2], + ['name' => 'Charlie', 'age' => 35, 'row_num' => 3], + ], + $memory->dump(), + ); + } + + public function test_a_transformation_sink_with_batch_size_transformation(): void + { + $loader = new SpyLoader(); + + df() + ->read(new FakeStaticOrdersExtractor(1000)) + ->collect() + ->write(to_transformation(batch_size(500), $loader)) + ->run(); + + static::assertSame(2, $loader->loadsCount); + } + + public function test_a_transformation_sink_with_add_row_index_transformation_across_batches(): void + { + $source = []; + + for ($id = 1; $id <= 6; $id++) { + $source[] = ['id' => $id]; + } + + $memory = new ArrayMemory(); + + df() + ->read(from_array($source)) + ->write(to_transformation(add_row_index('n', StartFrom::ONE), to_memory($memory))) + ->run(); + + static::assertSame([1, 2, 3, 4, 5, 6], array_column($memory->dump(), 'n')); + } + + public function test_a_transformation_sink_with_batch_size_transformation_across_batches(): void + { + $source = []; + + for ($id = 1; $id <= 6; $id++) { + $source[] = ['id' => $id]; + } + + $loader = new SpyLoader(); + + df() + ->read(from_array($source)) + ->write(to_transformation(batch_size(4), $loader)) + ->run(); + + // The sink pipeline is driven once over the whole stream, so batch_size(4) re-batches the stream instead of + // each incoming batch - the same [4, 2] the outer frame's batchSize(4) produces. + static::assertSame(2, $loader->loadsCount); + static::assertSame([4, 2], $loader->loadedRowCounts()); + } + + public function test_a_transformation_sink_with_drop_transformation(): void + { + $memory = new ArrayMemory(); + + df() + ->read(from_array([ + ['id' => 1, 'name' => 'Alice', 'email' => 'alice@example.com', 'password' => 'secret123'], + ['id' => 2, 'name' => 'Bob', 'email' => 'bob@example.com', 'password' => 'secret456'], + ])) + ->write(to_transformation(drop('password', 'email'), to_memory($memory))) + ->run(); + + static::assertSame( + [ + ['id' => 1, 'name' => 'Alice'], + ['id' => 2, 'name' => 'Bob'], + ], + $memory->dump(), + ); + } + + public function test_a_transformation_sink_with_limit_transformer_does_not_stop_sibling_loaders(): void + { + $limited = new ArrayMemory(); + $sibling = new ArrayMemory(); + + $source = []; + + for ($id = 1; $id <= 20; $id++) { + $source[] = ['id' => $id]; + } + + df() + ->read(from_array($source)) + ->load(to_transformation(new LimitTransformer(10), to_memory($limited))) + ->load(to_memory($sibling)) + ->run(); + + static::assertCount(10, $limited->dump()); + static::assertCount(20, $sibling->dump()); + } + + public function test_a_transformation_sink_with_limit_transformation(): void + { + $memory = new ArrayMemory(); + + df() + ->read(from_array([ + ['id' => 1, 'name' => 'Alice'], + ['id' => 2, 'name' => 'Bob'], + ['id' => 3, 'name' => 'Charlie'], + ['id' => 4, 'name' => 'Diana'], + ['id' => 5, 'name' => 'Eve'], + ])) + ->collect() + ->write(to_transformation(limit(3), to_memory($memory))) + ->run(); + + static::assertSame( + [ + ['id' => 1, 'name' => 'Alice'], + ['id' => 2, 'name' => 'Bob'], + ['id' => 3, 'name' => 'Charlie'], + ], + $memory->dump(), + ); + } + + public function test_a_transformation_sink_with_limit_transformation_across_batches(): void + { + $source = []; + + for ($id = 1; $id <= 6; $id++) { + $source[] = ['id' => $id]; + } + + $memory = new ArrayMemory(); + + df() + ->read(from_array($source)) + ->write(to_transformation(limit(3), to_memory($memory))) + ->run(); + + static::assertSame([['id' => 1], ['id' => 2], ['id' => 3]], $memory->dump()); + } + + public function test_a_transformation_sink_with_mask_columns_transformation(): void + { + $memory = new ArrayMemory(); + + df() + ->read(from_array([ + ['id' => 1, 'name' => 'Alice', 'ssn' => '123-45-6789', 'email' => 'alice@example.com'], + ['id' => 2, 'name' => 'Bob', 'ssn' => '987-65-4321', 'email' => 'bob@example.com'], + ])) + ->write(to_transformation(mask_columns(['ssn', 'email'], '***'), to_memory($memory))) + ->run(); + + static::assertSame( + [ + ['id' => 1, 'name' => 'Alice', 'ssn' => '***', 'email' => '***'], + ['id' => 2, 'name' => 'Bob', 'ssn' => '***', 'email' => '***'], + ], + $memory->dump(), + ); + } + + public function test_an_unresolved_column_inside_a_transformation_fails_when_the_plan_binds(): void + { + $sink = new SpyLoader(); + + try { + df() + ->read(from_array([['id' => 1], ['id' => 2]])) + ->write(to_transformation(select('nope'), $sink)) + ->run(); + + static::fail('Expected the plan to refuse to bind the sink root against the prefix shape.'); + } catch (SchemaDefinitionNotFoundException $e) { + static::assertSame('Schema definition for entry "nope" not found.', $e->getMessage()); + } + + static::assertSame(0, $sink->loadsCount); + } + + public function test_a_nested_transformation_sink_applies_the_inner_limit_across_the_stream(): void + { + $memory = new ArrayMemory(); + + df() + ->read(from_sequence_number('id', 1, 12)) + ->batchSize(4) + ->write(to_transformation(select('id'), to_transformation(limit(5), to_memory($memory)))) + ->run(); + + static::assertSame([['id' => 1], ['id' => 2], ['id' => 3], ['id' => 4], ['id' => 5]], $memory->dump()); + } + + public function test_a_nested_transformation_sink_keeps_row_index_continuous_across_batches(): void + { + $memory = new ArrayMemory(); + + df() + ->read(from_sequence_number('id', 1, 12)) + ->batchSize(4) + ->write(to_transformation( + select('id'), + to_transformation(add_row_index('n', StartFrom::ONE), to_memory($memory)), + )) + ->run(); + + static::assertSame([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], array_column($memory->dump(), 'n')); + } + + public function test_a_three_level_nested_transformation_sink_delivers_the_whole_stream_and_closes_once(): void + { + $loader = new SpyLoader(); + + df() + ->read(from_sequence_number('id', 1, 12)) + ->batchSize(4) + ->write(to_transformation( + select('id'), + to_transformation(select('id'), to_transformation(add_row_index('n', StartFrom::ONE), $loader)), + )) + ->run(); + + static::assertSame(1, $loader->closureCount); + static::assertSame([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], array_column($loader->loadedRowsToArray(), 'n')); + } + + public function test_a_transformation_sink_with_select_transformation(): void + { + $memory = new ArrayMemory(); + + df() + ->read(from_array([ + ['id' => 1, 'name' => 'Alice', 'email' => 'alice@example.com', 'age' => 30], + ['id' => 2, 'name' => 'Bob', 'email' => 'bob@example.com', 'age' => 25], + ])) + ->write(to_transformation(select('name', 'email'), to_memory($memory))) + ->run(); + + static::assertSame( + [ + ['name' => 'Alice', 'email' => 'alice@example.com'], + ['name' => 'Bob', 'email' => 'bob@example.com'], + ], + $memory->dump(), + ); + } + + public function test_a_transformation_sink_with_stream_loader_across_batches(): void + { + df() + ->read(from_sequence_number('id', 1, 12)) + ->batchSize(4) + ->write(to_transformation( + select('id'), + to_stream( + $path = $this->cacheDir->suffix('transformation_stream.txt')->path(), + output: Output::rows_count, + ), + )) + ->run(); + + $content = file_get_contents($path); + + if ($content === false) { + static::fail('Failed to read file content'); + } + + static::assertSame("Rows: 4\nRows: 4\nRows: 4\n", $content); + } + + public function test_a_sink_inside_a_joined_frame_runs_once_per_outer_run(): void + { + $inner = new SpyLoader(); + $outer = df() + ->read(from_array([['id' => 1]])) + ->join(df()->read(from_array([['id' => 1, 'v' => 'r']]))->write($inner), join_on(['id' => 'id'], 'r_')); + + $outer->run(); + $outer->run(); + + static::assertSame([1, 1], $inner->loadedRowCounts()); + static::assertSame(2, $inner->closureCount); + } + + public function test_a_sink_inside_a_frame_the_operator_never_pulls_never_runs(): void + { + $inner = new SpyLoader(); + + df() + ->read(from_array([], schema(int_schema('id')))) + ->crossJoin(df()->read(from_array([['v' => 'r']]))->write($inner)) + ->run(); + + static::assertSame(0, $inner->loadsCount); + static::assertSame(0, $inner->closureCount); + } + + public function test_a_later_filter_does_not_narrow_an_earlier_sink(): void + { + $spy = new SpyLoader(); + + df() + ->read(from_text(__DIR__ + . '/Fixtures/Partitioning/multi_partition_pruning_test/year=*/month=*/day=*/*.txt')->partitionTypes( + partition_types(year: type_integer()), + )) + ->write($spy) + ->filter(ref('year')->equals(lit(2023))) + ->run(); + + static::assertSame(7, array_sum($spy->loadedRowCounts())); + } + + public function test_a_later_limit_does_not_narrow_an_earlier_sink(): void + { + $spy = new SpyLoader(); + $extractor = new RecordingFileExtractor( + schema(int_schema('id')), + rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])), + ); + + $rows = df()->read($extractor)->write($spy)->limit(2)->fetch(); + + static::assertCount(2, $rows); + static::assertNull($extractor->limits[0]); + static::assertSame([3], $spy->loadedRowCounts()); + } + + public function test_two_writes_on_one_node_close_independently(): void + { + $failure = new RuntimeException('closure failed'); + $first = new ClosureThrowingLoader($failure); + $second = new RecordingSink(); + + try { + df() + ->read(from_array([['id' => 1]])) + ->write($first) + ->write($second) + ->run(); + + static::fail('Expected the first closure failure to surface'); + } catch (RuntimeException $e) { + static::assertSame($failure, $e); + } + + static::assertSame(1, $first->discarded); + static::assertSame(1, $second->closed); + static::assertSame(0, $second->discarded); + } + + public function test_a_side_loader_failure_is_offered_once_against_the_users_loader(): void + { + $handler = new RecordingErrorHandler(new IgnoreError()); + $failure = new RuntimeException('boom'); + $loader = new ThrowingLoader($failure); + + df() + ->read(from_array([['id' => 1]])) + ->onError($handler) + ->write(to_branch(lit(true), $loader)) + ->run(); + + static::assertCount(1, $handler->errors); + $error = $handler->errors[0]; + static::assertInstanceOf(LoadingError::class, $error); + static::assertSame($loader, $error->loader); + static::assertSame($failure, $error->cause); + } + + public function test_a_failure_under_a_node_two_sinks_share_is_offered_once(): void + { + $handler = new RecordingErrorHandler(new ThrowError()); + $failure = new RuntimeException('boom'); + + try { + df() + ->read(from_array([['id' => 1], ['id' => 2]])) + ->onError($handler) + ->write(to_transformation( + limit(100), + new FanOutSink( + to_transformation(new ThrowingTransformer($failure), to_memory(new ArrayMemory())), + to_memory(new ArrayMemory()), + ), + )) + ->run(); + static::fail('The failure was not thrown'); + } catch (RuntimeException $thrown) { + static::assertSame($failure, $thrown); + } + + static::assertCount(1, $handler->errors); + static::assertInstanceOf(TransformationError::class, $handler->errors[0]); + static::assertSame($failure, $handler->errors[0]->cause); + } + + public function test_a_failure_under_a_shared_node_propagated_by_the_handler_stops_the_run(): void + { + $handler = new RecordingErrorHandler(new PropagatingTransformationsSkippingLoaders()); + $failure = new RuntimeException('boom'); + + try { + df() + ->read(from_array([['id' => 1], ['id' => 2]])) + ->onError($handler) + ->write(to_transformation( + limit(100), + new FanOutSink( + to_transformation(new ThrowingTransformer($failure), to_memory(new ArrayMemory())), + to_memory(new ArrayMemory()), + ), + )) + ->run(); + static::fail('The run completed although the handler propagated the failure'); + } catch (RuntimeException $thrown) { + static::assertSame($failure, $thrown); + } + + static::assertCount(1, $handler->errors); + } + + public function test_a_transaction_child_failure_is_offered_once_against_the_childs_feed(): void + { + $handler = new RecordingErrorHandler(new IgnoreError()); + $failure = new RuntimeException('boom'); + $transaction = new RecordingTransaction(); + + df() + ->read(from_array([['id' => 1]])) + ->onError($handler) + ->write(new Transactional($transaction, to_branch(lit(true), new ThrowingLoader($failure)))) + ->run(); + + static::assertCount(1, $handler->errors); + $error = $handler->errors[0]; + static::assertInstanceOf(LoadingError::class, $error); + static::assertInstanceOf(SinkFeed::class, $error->loader); + static::assertSame($failure, $error->cause); + static::assertSame(['begin', 'rollback', 'begin', 'commit'], $transaction->log); + } + + /** + * @param 'beginFailure'|'commitFailure' $failing + * @param list $log + */ + #[DataProvider('failing_transaction_calls')] + public function test_a_failing_transaction_call_is_offered_once_against_the_transaction_step( + string $failing, + array $log, + ): void { + $handler = new RecordingErrorHandler(new IgnoreError()); + $failure = new RuntimeException('transaction failed'); + $transaction = new RecordingTransaction(...[$failing => $failure]); + + try { + df() + ->read(from_array([['id' => 1]])) + ->onError($handler) + ->write(new Transactional($transaction, new SpyLoader())) + ->run(); + + static::fail('Expected the drain transaction failure to surface'); + } catch (RuntimeException $e) { + static::assertSame($failure, $e); + } + + static::assertCount(1, $handler->errors); + $error = $handler->errors[0]; + static::assertInstanceOf(LoadingError::class, $error); + static::assertInstanceOf(TransactionalSinks::class, $error->loader); + static::assertSame($failure, $error->cause); + static::assertSame($log, $transaction->log); + } + + public static function failing_transaction_calls(): Generator + { + yield 'begin' => ['beginFailure', ['begin', 'begin']]; + yield 'commit' => ['commitFailure', ['begin', 'commit', 'rollback', 'begin', 'commit', 'rollback']]; + } + + public function test_a_later_limit_still_drains_a_transaction_once(): void + { + $spy = new SpyLoader(); + $transaction = new RecordingTransaction(); + + df() + ->read(from_array([['id' => 1], ['id' => 2], ['id' => 3]])) + ->batchSize(1) + ->write(new Transactional($transaction, to_branch(lit(true), $spy))) + ->limit(1) + ->run(); + + static::assertSame(['begin', 'commit', 'begin', 'commit'], $transaction->log); + static::assertSame([1], $spy->loadedRowCounts()); + static::assertSame(1, $spy->closureCount); + } + + public function test_a_node_shared_by_transaction_children_runs_once_per_row(): void + { + $first = new ArrayMemory(); + $second = new ArrayMemory(); + $transaction = new RecordingTransaction(); + + df() + ->read(from_sequence_number('id', 0, 5)) + ->batchSize(3) + ->write(to_transformation( + add_row_index('idx'), + new Transactional($transaction, to_memory($first), to_memory($second)), + )) + ->run(); + + static::assertSame([0, 1, 2, 3, 4, 5], array_column($first->dump(), 'idx')); + static::assertSame([0, 1, 2, 3, 4, 5], array_column($second->dump(), 'idx')); + static::assertSame(['begin', 'commit', 'begin', 'commit', 'begin', 'commit'], $transaction->log); + } + + public function test_a_write_inside_a_transformation_sees_the_rows_its_outer_sink_sees(): void + { + $inner = new ArrayMemory(); + $outer = new ArrayMemory(); + + df() + ->read(from_sequence_number('id', 0, 5)) + ->batchSize(3) + ->write(to_transformation(new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df->limit( + 4, + )->write(to_memory($inner))), to_memory($outer))) + ->run(); + + static::assertSame([0, 1, 2, 3], array_column($inner->dump(), 'id')); + static::assertSame([0, 1, 2, 3], array_column($outer->dump(), 'id')); + } + + public function test_an_ending_failure_during_load_is_offered_once_against_the_feed(): void + { + $handler = new RecordingErrorHandler(new IgnoreError()); + $failure = new RuntimeException('closure failed'); + $loader = new ClosureThrowingLoader($failure); + + df() + ->read(from_array([['id' => 1], ['id' => 2]])) + ->batchSize(1) + ->onError($handler) + ->write(to_transformation(limit(1), $loader)) + ->run(); + + static::assertCount(1, $handler->errors); + $error = $handler->errors[0]; + static::assertInstanceOf(LoadingError::class, $error); + static::assertInstanceOf(SinkFeed::class, $error->loader); + static::assertSame($failure, $error->cause); + static::assertSame(1, $loader->loadsCount); + } + + public function test_a_closure_failure_is_never_offered_and_surfaces_the_users_exception(): void + { + $handler = new RecordingErrorHandler(new IgnoreError()); + $failure = new RuntimeException('closure failed'); + + try { + df() + ->read(from_array([['id' => 1]])) + ->onError($handler) + ->write(to_branch(lit(true), new ClosureThrowingLoader($failure))) + ->run(); + + static::fail('Expected the closure failure to surface'); + } catch (RuntimeException $e) { + static::assertSame($failure, $e); + } + + static::assertSame([], $handler->errors); + } + + public function test_a_declined_failure_inside_a_sink_root_skips_only_that_batch(): void + { + $spy = new SpyLoader(); + + df() + ->read(from_array([['id' => 1], ['id' => 2]])) + ->batchSize(1) + ->onError(ignore_error_handler()) + ->write(to_transformation(new ThrowWhenRowMatches('id', 1, new RuntimeException('boom')), $spy)) + ->run(); + + static::assertSame([['id' => 2]], $spy->loadedRowsToArray()); + static::assertSame(1, $spy->closureCount); + } + + public function test_a_declined_failure_keeps_loading_into_the_next_loader_like_a_plain_loader(): void + { + // skipBatch declines the failure inside the sink root only: the loader after it still receives every batch + $tail = new SpyLoader(); + + df() + ->read(from_array([['id' => 1], ['id' => 2], ['id' => 3]])) + ->batchSize(1) + ->onError(ignore_error_handler()) + ->write(to_transformation(new ThrowWhenRowMatches('id', 2, new RuntimeException('boom')), new SpyLoader())) + ->write($tail) + ->run(); + + static::assertSame([1, 2, 3], array_column($tail->loadedRowsToArray(), 'id')); + } + + public function test_a_failed_run_does_not_close_the_sink(): void + { + $spy = new SpyLoader(); + $boom = new RuntimeException('boom'); + + try { + df() + ->read(from_array([['id' => 1], ['id' => 2]])) + ->write(to_transformation(new ThrowingTransformer($boom), $spy)) + ->run(); + + static::fail('Expected the transformer failure to surface'); + } catch (RuntimeException $e) { + static::assertSame($boom, $e); + } + + static::assertSame(0, $spy->closureCount); + static::assertSame(0, $spy->loadsCount); + } + + /** + * @param Closure(SpyLoader): Sink $sinkOf + */ + #[DataProvider('limited_sink_roots')] + public function test_a_limit_inside_a_sink_root_ignores_later_batches_and_closes_once(Closure $sinkOf): void + { + $spy = new SpyLoader(); + + df() + ->read(from_array([['id' => 1], ['id' => 2], ['id' => 3], ['id' => 4]])) + ->batchSize(1) + ->write($sinkOf($spy)) + ->run(); + + static::assertSame([1, 1], $spy->loadedRowCounts()); + static::assertSame(1, $spy->closureCount); + } + + public static function limited_sink_roots(): Generator + { + yield 'transformation' => [static fn(SpyLoader $spy): Sink => to_transformation(limit(2), $spy)]; + yield 'branch' => [static fn(SpyLoader $spy): Sink => to_branch(lit(true), $spy)->withTransformation(limit(2))]; + } + + /** + * @param Closure(Loader, Transformer): Sink $sinkOf + */ + #[DataProvider('draining_sink_roots')] + public function test_a_declined_drain_failure_skips_the_buffered_batch_and_closes_once(Closure $sinkOf): void + { + $spy = new SpyLoader(); + + df() + ->read(from_array([['id' => 1]])) + ->onError(ignore_error_handler()) + ->write($sinkOf($spy, new ThrowingTransformer(new RuntimeException('boom')))) + ->run(); + + static::assertSame(0, $spy->loadsCount); + static::assertSame(1, $spy->closureCount); + } + + /** + * @param Closure(Loader, Transformer): Sink $sinkOf + */ + #[DataProvider('draining_sink_roots')] + public function test_a_drain_failure_surfaces_the_users_exception(Closure $sinkOf): void + { + $boom = new RuntimeException('boom'); + $loader = new ThrowingLoader($boom); + + try { + df() + ->read(from_array([['id' => 1]])) + ->write($sinkOf($loader, new SpyTransformer())) + ->run(); + + static::fail('Expected the drain failure to surface'); + } catch (RuntimeException $e) { + static::assertSame($boom, $e); + } + + static::assertSame(1, $loader->loadsCount); + } + + /** + * @param Closure(Loader, Transformer): Sink $sinkOf + */ + #[DataProvider('draining_sink_roots')] + public function test_a_drain_failure_is_offered_to_the_handler_once(Closure $sinkOf): void + { + $handler = new RecordingErrorHandler(new IgnoreError()); + + df() + ->read(from_array([['id' => 1]])) + ->onError($handler) + ->write($sinkOf(new SpyLoader(), new ThrowingTransformer(new RuntimeException('boom')))) + ->run(); + + static::assertCount(1, $handler->errors); + static::assertInstanceOf(TransformationError::class, $handler->errors[0]); + static::assertSame('boom', $handler->errors[0]->cause->getMessage()); + } + + public static function draining_sink_roots(): Generator + { + yield 'transformation' => [ + static fn(Loader $sink, Transformer $after): Sink => to_transformation(new CallbackTransformation( + static fn(DataFrame $df): DataFrame => $df->collect()->with($after), + ), $sink), + ]; + yield 'branch' => [ + static fn(Loader $sink, Transformer $after): Sink => to_branch( + lit(true), + $sink, + )->withTransformation(new CallbackTransformation( + static fn(DataFrame $df): DataFrame => $df->collect()->with($after), + )), + ]; + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/TelemetryTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/TelemetryTest.php index 98889af56d..4221e6a2ce 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/TelemetryTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/TelemetryTest.php @@ -4,11 +4,14 @@ namespace Flow\ETL\Tests\Integration\DataFrame; -use DateTimeImmutable; +use Flow\Clock\FakeClock; use Flow\ETL\Bucketing\Storage\FilesystemBuckets; -use Flow\ETL\Loader\RetryLoader; +use Flow\ETL\DataFrame; +use Flow\ETL\Sink\Transactional; use Flow\ETL\Tests\Context\MemoryTelemetryContext; +use Flow\ETL\Tests\Double\RecordingTransaction; use Flow\ETL\Tests\FlowTestCase; +use Flow\ETL\Tests\Mother\RowsMother; use Flow\ETL\Transformer\LimitTransformer; use Flow\Telemetry\Context\MemoryContextStorage; use Flow\Telemetry\Logger\LoggerProvider; @@ -22,23 +25,29 @@ use Flow\Telemetry\Telemetry; use Flow\Telemetry\Tracer\Span; use Flow\Telemetry\Tracer\TracerProvider; -use Psr\Clock\ClockInterface; use function array_filter; use function array_keys; +use function array_map; +use function array_values; use function count; use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\from_array; +use function Flow\ETL\DSL\from_data_frame; +use function Flow\ETL\DSL\from_rows; +use function Flow\ETL\DSL\join_on; use function Flow\ETL\DSL\limit; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\telemetry_options; use function Flow\ETL\DSL\to_array; +use function Flow\ETL\DSL\to_branch; use function Flow\ETL\DSL\to_transformation; use function Flow\ETL\DSL\with_entry; use function Flow\Types\DSL\type_map; use function Flow\Types\DSL\type_string; +use function in_array; use function str_contains; use function str_ends_with; use function str_starts_with; @@ -50,7 +59,7 @@ public function test_dataframe_collects_metrics_when_enabled(): void $spanProcessor = new MemorySpanProcessor(new VoidExporter()); $metricProcessor = new MemoryMetricProcessor(new VoidExporter()); $logProcessor = new MemoryLogProcessor(new VoidExporter()); - $clock = $this->createFrozenClock(); + $clock = new FakeClock(); $contextStorage = new MemoryContextStorage(); $telemetry = new Telemetry( @@ -80,7 +89,7 @@ public function test_dataframe_loading_traced_when_enabled(): void $spanProcessor = new MemorySpanProcessor(new VoidExporter()); $metricProcessor = new MemoryMetricProcessor(new VoidExporter()); $logProcessor = new MemoryLogProcessor(new VoidExporter()); - $clock = $this->createFrozenClock(); + $clock = new FakeClock(); $contextStorage = new MemoryContextStorage(); $telemetry = new Telemetry( @@ -129,7 +138,7 @@ public function test_dataframe_run_creates_telemetry_span(): void $spanProcessor = new MemorySpanProcessor(new VoidExporter()); $metricProcessor = new MemoryMetricProcessor(new VoidExporter()); $logProcessor = new MemoryLogProcessor(new VoidExporter()); - $clock = $this->createFrozenClock(); + $clock = new FakeClock(); $contextStorage = new MemoryContextStorage(); $telemetry = new Telemetry( @@ -181,7 +190,7 @@ public function test_dataframe_run_logs_start_and_completion(): void $spanProcessor = new MemorySpanProcessor(new VoidExporter()); $metricProcessor = new MemoryMetricProcessor(new VoidExporter()); $logProcessor = new MemoryLogProcessor(new VoidExporter()); - $clock = $this->createFrozenClock(); + $clock = new FakeClock(); $contextStorage = new MemoryContextStorage(); $telemetry = new Telemetry( @@ -223,7 +232,7 @@ public function test_dataframe_span_contains_row_statistics(): void $spanProcessor = new MemorySpanProcessor(new VoidExporter()); $metricProcessor = new MemoryMetricProcessor(new VoidExporter()); $logProcessor = new MemoryLogProcessor(new VoidExporter()); - $clock = $this->createFrozenClock(); + $clock = new FakeClock(); $contextStorage = new MemoryContextStorage(); $telemetry = new Telemetry( @@ -260,7 +269,7 @@ public function test_dataframe_transformations_traced_when_enabled(): void $spanProcessor = new MemorySpanProcessor(new VoidExporter()); $metricProcessor = new MemoryMetricProcessor(new VoidExporter()); $logProcessor = new MemoryLogProcessor(new VoidExporter()); - $clock = $this->createFrozenClock(); + $clock = new FakeClock(); $contextStorage = new MemoryContextStorage(); $telemetry = new Telemetry( @@ -330,7 +339,7 @@ public function test_duplicate_row_transformer_exports_nested_spans_once(): void )); } - public function test_limit_reached_inside_transformer_loader_is_not_reported_as_failure(): void + public function test_limit_reached_inside_a_sink_root_is_not_reported_as_failure(): void { $context = new MemoryTelemetryContext(telemetry_options(trace_loading: true)); @@ -395,45 +404,66 @@ public function test_limit_reached_is_logged_without_exception_attribute(): void static::assertSame(5, $entries[0]->record->attributes->get('limit')); } - public function test_retry_loader_exports_nested_spans_once(): void + public function test_telemetry_disabled_by_default_uses_void_providers(): void + { + $config = config_builder()->build(); + + $output = []; + df($config) + ->read(from_array([ + ['id' => 1, 'name' => 'John'], + ])) + ->write(to_array($output)) + ->run(); + + static::assertCount(1, $output); + static::assertSame(1, $output[0]['id']); + } + + public function test_loading_rows_on_a_branch_counts_the_rows_written(): void { $context = new MemoryTelemetryContext(telemetry_options(trace_loading: true)); $output = []; df($context->config) - ->read(from_array([['id' => 1], ['id' => 2]])->withBatchSize(1)) - ->load(new RetryLoader(to_array($output))) + ->read(from_rows(...RowsMother::descendingIdBatches())) + ->write(to_branch(ref('id')->greaterThanEqual(lit(2)), to_array($output))) ->run(); - $endedSpans = $context->spans->endedSpans(); - - static::assertCount(2, array_filter( - $endedSpans, - static fn(Span $span): bool => $span->name() === 'RetryLoader', - )); - static::assertCount(2, array_filter( - $endedSpans, - static fn(Span $span): bool => $span->name() === 'ArrayLoader', - )); + static::assertSame( + [2, 2], + array_values(array_map( + static fn(Span $span): mixed => $span->attributes()['flow.etl.loading.rows'], + array_filter( + $context->spans->endedSpans(), + static fn(Span $span): bool => $span->name() === 'ArrayLoader', + ), + )), + ); } - public function test_telemetry_disabled_by_default_uses_void_providers(): void + public function test_planner_built_sink_steps_emit_no_span(): void { - $config = config_builder()->build(); + $context = new MemoryTelemetryContext(telemetry_options(trace_loading: true)); $output = []; - df($config) - ->read(from_array([ - ['id' => 1, 'name' => 'John'], - ])) - ->write(to_array($output)) + df($context->config) + ->read(from_array([['id' => 1], ['id' => 2]])) + ->write(new Transactional(new RecordingTransaction(), to_transformation(limit(1), to_array($output)))) ->run(); static::assertCount(1, $output); - static::assertSame(1, $output[0]['id']); + static::assertSame( + [], + array_values(array_filter($context->spans->endedSpans(), static fn(Span $span): bool => in_array( + $span->name(), + ['SinkFeed', 'TransactionalSinks'], + true, + ))), + ); } - public function test_transformation_loader_builds_one_nested_dataframe_span_per_run(): void + public function test_a_sink_root_builds_no_dataframe_span_of_its_own(): void { $context = new MemoryTelemetryContext(); @@ -451,8 +481,8 @@ public function test_transformation_loader_builds_one_nested_dataframe_span_per_ $isDataFrameSpan = static fn(Span $span): bool => str_starts_with($span->name(), 'DataFrame '); - static::assertCount(2, array_filter($context->spans->startedSpans(), $isDataFrameSpan)); - static::assertCount(2, array_filter($context->spans->endedSpans(), $isDataFrameSpan)); + static::assertCount(1, array_filter($context->spans->startedSpans(), $isDataFrameSpan)); + static::assertCount(1, array_filter($context->spans->endedSpans(), $isDataFrameSpan)); } public function test_until_condition_is_logged_without_exception_attribute(): void @@ -478,17 +508,105 @@ public function test_until_condition_is_logged_without_exception_attribute(): vo static::assertSame(0, $entries[0]->record->attributes->get('limit')); } - private function createFrozenClock(DateTimeImmutable $now = new DateTimeImmutable()): ClockInterface + public function test_a_join_builds_one_balanced_dataframe_span_per_run(): void { - return new readonly class($now) implements ClockInterface { - public function __construct( - private DateTimeImmutable $now, - ) {} - - public function now(): DateTimeImmutable - { - return $this->now; - } - }; + $context = new MemoryTelemetryContext(); + $right = df($context->config)->read(from_array([['id' => 1, 'name' => 'a']])); + + df($context->config) + ->read(from_array([['id' => 1]])) + ->join($right, join_on(['id' => 'id'], 'r_')) + ->run(); + + $isDataFrameSpan = static fn(Span $span): bool => str_starts_with($span->name(), 'DataFrame '); + + static::assertCount(1, array_filter($context->spans->startedSpans(), $isDataFrameSpan)); + static::assertCount(1, array_filter($context->spans->endedSpans(), $isDataFrameSpan)); + } + + public function test_a_join_over_frames_sharing_one_flow_context_builds_one_balanced_dataframe_span(): void + { + $context = new MemoryTelemetryContext(); + $right = new DataFrame(from_array([['id' => 1, 'x' => 'a']]), $context->flowContext); + + (new DataFrame(from_array([['id' => 1]]), $context->flowContext))->join($right, join_on([ + 'id' => 'id', + ], 'r_'))->run(); + + $isDataFrameSpan = static fn(Span $span): bool => str_starts_with($span->name(), 'DataFrame '); + + static::assertCount(1, array_filter($context->spans->startedSpans(), $isDataFrameSpan)); + static::assertCount(1, array_filter($context->spans->endedSpans(), $isDataFrameSpan)); + } + + public function test_a_cross_join_builds_one_balanced_dataframe_span_per_run(): void + { + $context = new MemoryTelemetryContext(); + $right = df($context->config)->read(from_array([['name' => 'a']])); + + df($context->config) + ->read(from_array([['id' => 1]])) + ->crossJoin($right, 'r_') + ->run(); + + $isDataFrameSpan = static fn(Span $span): bool => str_starts_with($span->name(), 'DataFrame '); + + static::assertCount(1, array_filter($context->spans->startedSpans(), $isDataFrameSpan)); + static::assertCount(1, array_filter($context->spans->endedSpans(), $isDataFrameSpan)); + } + + public function test_a_read_frame_builds_its_own_balanced_dataframe_span_per_run(): void + { + $context = new MemoryTelemetryContext(); + $inner = df($context->config)->read(from_array([['id' => 1]]))->select('id'); + + df($context->config)->read(from_data_frame($inner))->run(); + + $isDataFrameSpan = static fn(Span $span): bool => str_starts_with($span->name(), 'DataFrame '); + + static::assertCount(2, array_filter($context->spans->startedSpans(), $isDataFrameSpan)); + static::assertCount(2, array_filter($context->spans->endedSpans(), $isDataFrameSpan)); + } + + public function test_a_read_frame_sharing_the_outer_flow_context_builds_balanced_dataframe_spans(): void + { + $context = new MemoryTelemetryContext(); + $inner = new DataFrame(from_array([['id' => 1]]), $context->flowContext); + + (new DataFrame(from_data_frame($inner), $context->flowContext))->run(); + + $isDataFrameSpan = static fn(Span $span): bool => str_starts_with($span->name(), 'DataFrame '); + + static::assertCount(2, array_filter($context->spans->startedSpans(), $isDataFrameSpan)); + static::assertCount(2, array_filter($context->spans->endedSpans(), $isDataFrameSpan)); + } + + public function test_an_abandoned_run_over_a_read_frame_closes_both_dataframe_spans(): void + { + $context = new MemoryTelemetryContext(); + $inner = df($context->config)->read(from_array([['id' => 1], ['id' => 2]]))->select('id'); + + foreach (df($context->config)->read(from_data_frame($inner))->batchSize(1)->get() as $_rows) { + break; + } + + $isDataFrameSpan = static fn(Span $span): bool => str_starts_with($span->name(), 'DataFrame '); + + static::assertCount(2, array_filter($context->spans->startedSpans(), $isDataFrameSpan)); + static::assertCount(2, array_filter($context->spans->endedSpans(), $isDataFrameSpan)); + } + + public function test_a_frame_run_twice_builds_two_balanced_dataframe_spans(): void + { + $context = new MemoryTelemetryContext(); + $frame = df($context->config)->read(from_array([['id' => 1]])); + + $frame->count(); + $frame->fetch(); + + $isDataFrameSpan = static fn(Span $span): bool => str_starts_with($span->name(), 'DataFrame '); + + static::assertCount(2, array_filter($context->spans->startedSpans(), $isDataFrameSpan)); + static::assertCount(2, array_filter($context->spans->endedSpans(), $isDataFrameSpan)); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/TriggerPlanTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/TriggerPlanTest.php new file mode 100644 index 0000000000..b50914f74a --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/TriggerPlanTest.php @@ -0,0 +1,94 @@ +read(from_array([['id' => 1], ['id' => 2], ['id' => 3]])) + ->batchSize(1) + ->write($sink) + ->transform($afterWrite) + ->run(); + + static::assertSame(3, $afterWrite->seen); + static::assertSame([1, 1, 1], $sink->loadedRowCounts()); + } + + public function test_run_analyze_counts_the_rows_of_a_frame_with_a_sink(): void + { + $report = df() + ->read(from_array([['id' => 1], ['id' => 2], ['id' => 3]])) + ->write(new SpyLoader()) + ->run(analyze: analyze()->withSchema()); + + static::assertSame(3, $report->statistics()->totalRows()); + } + + public function test_run_analyze_counts_the_rows_of_a_frame_without_a_sink(): void + { + $report = df()->read(from_array([['id' => 1], ['id' => 2]]))->run(analyze: analyze()->withSchema()); + + static::assertSame(2, $report->statistics()->totalRows()); + } + + public function test_one_sink_is_written_exactly_once(): void + { + $sink = new SpyLoader(); + + df() + ->read(from_array([['id' => 1], ['id' => 2]])) + ->batchSize(1) + ->write($sink) + ->run(); + + static::assertSame([1, 1], $sink->loadedRowCounts()); + } + + public function test_two_sinks_are_each_written_exactly_once_in_write_order(): void + { + $first = new SpyLoader(); + $second = new SpyLoader(); + + df() + ->read(from_array([['id' => 1], ['id' => 2]])) + ->batchSize(1) + ->write($first) + ->write($second) + ->run(); + + static::assertSame([1, 1], $first->loadedRowCounts()); + static::assertSame([1, 1], $second->loadedRowCounts()); + } + + public function test_a_transactional_sink_is_written_exactly_once(): void + { + $sink = new SpyLoader(); + $transaction = new RecordingTransaction(); + + df() + ->read(from_array([['id' => 1], ['id' => 2]])) + ->batchSize(1) + ->write(new Transactional($transaction, $sink)) + ->run(); + + static::assertSame([1, 1], $sink->loadedRowCounts()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Extractor/PathPartitionsExtractorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Extractor/PathPartitionsExtractorTest.php index bcdd480395..a0d7edd552 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Extractor/PathPartitionsExtractorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Extractor/PathPartitionsExtractorTest.php @@ -12,9 +12,13 @@ use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\from_path_partitions; +use function Flow\ETL\DSL\map_schema; use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; use function Flow\Filesystem\DSL\path_real; +use function Flow\Types\DSL\type_map; +use function Flow\Types\DSL\type_string; use function iterator_to_array; use function str_replace; use function usort; @@ -23,6 +27,26 @@ final class PathPartitionsExtractorTest extends FlowIntegrationTestCase { use OperatingSystem; + public function test_partition_directories_are_declared_as_string_columns_next_to_the_map(): void + { + $extractor = from_path_partitions(path_real(__DIR__ . '/Fixtures/multi_partitioned/**/*')); + + static::assertEquals( + schema(str_schema('day'), str_schema('month'), str_schema('year')), + $extractor->partitionSchema(), + ); + static::assertEquals( + schema( + str_schema('path'), + map_schema('partitions', type_map(type_string(), type_string())), + str_schema('day'), + str_schema('month'), + str_schema('year'), + ), + $extractor->schema(), + ); + } + public function test_extracting_data_from_path_partitions(): void { $extractor = from_path_partitions(path_real(__DIR__ . '/Fixtures/multi_partitioned/**/*')); @@ -49,6 +73,9 @@ public function test_extracting_data_from_path_partitions(): void . ltrim(str_replace('\\', '/', __DIR__), '/') . '/Fixtures/multi_partitioned/year=2022/month=12/day=30/file.txt', 'partitions' => ['year' => '2022', 'month' => '12', 'day' => '30'], + 'day' => '30', + 'month' => '12', + 'year' => '2022', ], [ 'path' => @@ -56,6 +83,9 @@ public function test_extracting_data_from_path_partitions(): void . ltrim(str_replace('\\', '/', __DIR__), '/') . '/Fixtures/multi_partitioned/year=2022/month=12/day=31/file.txt', 'partitions' => ['year' => '2022', 'month' => '12', 'day' => '31'], + 'day' => '31', + 'month' => '12', + 'year' => '2022', ], [ 'path' => @@ -63,6 +93,9 @@ public function test_extracting_data_from_path_partitions(): void . ltrim(str_replace('\\', '/', __DIR__), '/') . '/Fixtures/multi_partitioned/year=2023/month=1/day=1/file.txt', 'partitions' => ['year' => '2023', 'month' => '1', 'day' => '1'], + 'day' => '1', + 'month' => '1', + 'year' => '2023', ], [ 'path' => @@ -70,6 +103,9 @@ public function test_extracting_data_from_path_partitions(): void . ltrim(str_replace('\\', '/', __DIR__), '/') . '/Fixtures/multi_partitioned/year=2023/month=1/day=2/file.txt', 'partitions' => ['year' => '2023', 'month' => '1', 'day' => '2'], + 'day' => '2', + 'month' => '1', + 'year' => '2023', ], [ 'path' => @@ -77,6 +113,9 @@ public function test_extracting_data_from_path_partitions(): void . ltrim(str_replace('\\', '/', __DIR__), '/') . '/Fixtures/multi_partitioned/year=2023/month=1/day=3/file.txt', 'partitions' => ['year' => '2023', 'month' => '1', 'day' => '3'], + 'day' => '3', + 'month' => '1', + 'year' => '2023', ], [ 'path' => @@ -84,6 +123,9 @@ public function test_extracting_data_from_path_partitions(): void . ltrim(str_replace('\\', '/', __DIR__), '/') . '/Fixtures/multi_partitioned/year=2023/month=1/day=4/file.txt', 'partitions' => ['year' => '2023', 'month' => '1', 'day' => '4'], + 'day' => '4', + 'month' => '1', + 'year' => '2023', ], [ 'path' => @@ -91,6 +133,9 @@ public function test_extracting_data_from_path_partitions(): void . ltrim(str_replace('\\', '/', __DIR__), '/') . '/Fixtures/multi_partitioned/year=2023/month=1/day=5/file.txt', 'partitions' => ['year' => '2023', 'month' => '1', 'day' => '5'], + 'day' => '5', + 'month' => '1', + 'year' => '2023', ], ], $actualData, diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/RetryLoaderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/RetryLoaderTest.php deleted file mode 100644 index 4f46dbd1fa..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/RetryLoaderTest.php +++ /dev/null @@ -1,54 +0,0 @@ -read(from_array([['id' => 1], ['id' => 2], ['id' => 3], ['id' => 4]])) - ->batchSize(2) - ->write(write_with_retries($spy)) - ->run(); - - static::assertSame(2, $spy->loadsCount); - static::assertSame(1, $spy->closureCount); - } - - public function test_retry_loader_does_not_retry_an_invalid_logic_exception(): void - { - // The default strategy declines InvalidLogicException: a pipeline definition error can never succeed on a - // retry, so the attempt is made once instead of four times and no delay is slept. RetryLoader still wraps a - // declined exception in FailedRetryException, so the actionable message arrives as the previous exception - // rather than the top-level one. - $loader = new ThrowingLoader(new InvalidLogicException('pipeline definition error')); - - try { - df() - ->read(from_array([['id' => 2], ['id' => 1]])) - ->write(write_with_retries($loader)) - ->run(); - - static::fail('Expected the InvalidLogicException to be declined by the retry strategy.'); - } catch (FailedRetryException $e) { - static::assertSame(1, $e->record->count()); - static::assertInstanceOf(InvalidLogicException::class, $e->getPrevious()); - static::assertSame(1, $loader->loadsCount); - } - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/TransformerLoaderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/TransformerLoaderTest.php deleted file mode 100644 index d1b6ec0546..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/TransformerLoaderTest.php +++ /dev/null @@ -1,323 +0,0 @@ -read(from_array([ - ['name' => 'Alice', 'age' => 30], - ['name' => 'Bob', 'age' => 25], - ['name' => 'Charlie', 'age' => 35], - ])) - ->collect() - ->write(to_transformation(add_row_index('row_num', StartFrom::ONE), to_memory($memory))) - ->run(); - - static::assertSame( - [ - ['name' => 'Alice', 'age' => 30, 'row_num' => 1], - ['name' => 'Bob', 'age' => 25, 'row_num' => 2], - ['name' => 'Charlie', 'age' => 35, 'row_num' => 3], - ], - $memory->dump(), - ); - } - - public function test_transformer_loader_with_batch_size_transformation(): void - { - $loader = new SpyLoader(); - - df() - ->read(new FakeStaticOrdersExtractor(1000)) - ->collect() - ->write(to_transformation(batch_size(500), $loader)) - ->run(); - - static::assertSame(2, $loader->loadsCount); - } - - public function test_transformer_loader_with_add_row_index_transformation_across_batches(): void - { - $source = []; - - for ($id = 1; $id <= 6; $id++) { - $source[] = ['id' => $id]; - } - - $memory = new ArrayMemory(); - - df() - ->read(from_array($source)) - ->write(to_transformation(add_row_index('n', StartFrom::ONE), to_memory($memory))) - ->run(); - - static::assertSame([1, 2, 3, 4, 5, 6], array_column($memory->dump(), 'n')); - } - - public function test_transformer_loader_with_batch_size_transformation_across_batches(): void - { - $source = []; - - for ($id = 1; $id <= 6; $id++) { - $source[] = ['id' => $id]; - } - - $loader = new SpyLoader(); - - df() - ->read(from_array($source)) - ->write(to_transformation(batch_size(4), $loader)) - ->run(); - - // The nested pipeline is driven once over the whole stream, so batch_size(4) re-batches the stream instead of - // each incoming batch - the same [4, 2] the outer frame's batchSize(4) produces. - static::assertSame(2, $loader->loadsCount); - static::assertSame([4, 2], $loader->loadedRowCounts()); - } - - public function test_transformer_loader_with_drop_transformation(): void - { - $memory = new ArrayMemory(); - - df() - ->read(from_array([ - ['id' => 1, 'name' => 'Alice', 'email' => 'alice@example.com', 'password' => 'secret123'], - ['id' => 2, 'name' => 'Bob', 'email' => 'bob@example.com', 'password' => 'secret456'], - ])) - ->write(to_transformation(drop('password', 'email'), to_memory($memory))) - ->run(); - - static::assertSame( - [ - ['id' => 1, 'name' => 'Alice'], - ['id' => 2, 'name' => 'Bob'], - ], - $memory->dump(), - ); - } - - public function test_transformer_loader_with_limit_transformer_does_not_stop_sibling_loaders(): void - { - $limited = new ArrayMemory(); - $sibling = new ArrayMemory(); - - $source = []; - - for ($id = 1; $id <= 20; $id++) { - $source[] = ['id' => $id]; - } - - df() - ->read(from_array($source)) - ->load(to_transformation(new LimitTransformer(10), to_memory($limited))) - ->load(to_memory($sibling)) - ->run(); - - static::assertCount(10, $limited->dump()); - static::assertCount(20, $sibling->dump()); - } - - public function test_transformer_loader_with_limit_transformation(): void - { - $memory = new ArrayMemory(); - - df() - ->read(from_array([ - ['id' => 1, 'name' => 'Alice'], - ['id' => 2, 'name' => 'Bob'], - ['id' => 3, 'name' => 'Charlie'], - ['id' => 4, 'name' => 'Diana'], - ['id' => 5, 'name' => 'Eve'], - ])) - ->collect() - ->write(to_transformation(limit(3), to_memory($memory))) - ->run(); - - static::assertSame( - [ - ['id' => 1, 'name' => 'Alice'], - ['id' => 2, 'name' => 'Bob'], - ['id' => 3, 'name' => 'Charlie'], - ], - $memory->dump(), - ); - } - - public function test_transformer_loader_with_limit_transformation_across_batches(): void - { - $source = []; - - for ($id = 1; $id <= 6; $id++) { - $source[] = ['id' => $id]; - } - - $memory = new ArrayMemory(); - - df() - ->read(from_array($source)) - ->write(to_transformation(limit(3), to_memory($memory))) - ->run(); - - static::assertSame([['id' => 1], ['id' => 2], ['id' => 3]], $memory->dump()); - } - - public function test_transformer_loader_with_mask_columns_transformation(): void - { - $memory = new ArrayMemory(); - - df() - ->read(from_array([ - ['id' => 1, 'name' => 'Alice', 'ssn' => '123-45-6789', 'email' => 'alice@example.com'], - ['id' => 2, 'name' => 'Bob', 'ssn' => '987-65-4321', 'email' => 'bob@example.com'], - ])) - ->write(to_transformation(mask_columns(['ssn', 'email'], '***'), to_memory($memory))) - ->run(); - - static::assertSame( - [ - ['id' => 1, 'name' => 'Alice', 'ssn' => '***', 'email' => '***'], - ['id' => 2, 'name' => 'Bob', 'ssn' => '***', 'email' => '***'], - ], - $memory->dump(), - ); - } - - public function test_an_unresolved_column_inside_a_transformation_fails_at_the_first_batch(): void - { - $sink = new SpyLoader(); - - try { - df() - ->read(from_array([['id' => 1], ['id' => 2]])) - ->write(to_transformation(select('nope'), $sink)) - ->run(); - - static::fail('Expected the nested plan to refuse to bind against the fed shape.'); - } catch (SchemaDefinitionNotFoundException $e) { - static::assertSame('Schema definition for entry "nope" not found.', $e->getMessage()); - } - - static::assertSame(0, $sink->loadsCount); - } - - public function test_nested_transformer_loader_applies_the_inner_limit_across_the_stream(): void - { - $memory = new ArrayMemory(); - - df() - ->read(from_sequence_number('id', 1, 12)) - ->batchSize(4) - ->write(to_transformation(select('id'), to_transformation(limit(5), to_memory($memory)))) - ->run(); - - static::assertSame([['id' => 1], ['id' => 2], ['id' => 3], ['id' => 4], ['id' => 5]], $memory->dump()); - } - - public function test_nested_transformer_loader_keeps_row_index_continuous_across_batches(): void - { - $memory = new ArrayMemory(); - - df() - ->read(from_sequence_number('id', 1, 12)) - ->batchSize(4) - ->write(to_transformation( - select('id'), - to_transformation(add_row_index('n', StartFrom::ONE), to_memory($memory)), - )) - ->run(); - - static::assertSame([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], array_column($memory->dump(), 'n')); - } - - public function test_three_level_nested_transformer_loader_delivers_the_whole_stream_and_closes_once(): void - { - $loader = new SpyLoader(); - - df() - ->read(from_sequence_number('id', 1, 12)) - ->batchSize(4) - ->write(to_transformation( - select('id'), - to_transformation(select('id'), to_transformation(add_row_index('n', StartFrom::ONE), $loader)), - )) - ->run(); - - static::assertSame(1, $loader->closureCount); - static::assertSame([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], array_column($loader->loadedRowsToArray(), 'n')); - } - - public function test_transformer_loader_with_select_transformation(): void - { - $memory = new ArrayMemory(); - - df() - ->read(from_array([ - ['id' => 1, 'name' => 'Alice', 'email' => 'alice@example.com', 'age' => 30], - ['id' => 2, 'name' => 'Bob', 'email' => 'bob@example.com', 'age' => 25], - ])) - ->write(to_transformation(select('name', 'email'), to_memory($memory))) - ->run(); - - static::assertSame( - [ - ['name' => 'Alice', 'email' => 'alice@example.com'], - ['name' => 'Bob', 'email' => 'bob@example.com'], - ], - $memory->dump(), - ); - } - - public function test_transformer_loader_with_stream_loader_across_batches(): void - { - df() - ->read(from_sequence_number('id', 1, 12)) - ->batchSize(4) - ->write(to_transformation( - select('id'), - to_stream( - $path = $this->cacheDir->suffix('transformation_stream.txt')->path(), - output: Output::rows_count, - ), - )) - ->run(); - - $content = file_get_contents($path); - - if ($content === false) { - static::fail('Failed to read file content'); - } - - static::assertSame("Rows: 4\nRows: 4\nRows: 4\n", $content); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Pipeline/BatchingPipelineTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Pipeline/BatchingPipelineTest.php index 23a2abab5f..0642e4b9cb 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Pipeline/BatchingPipelineTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Pipeline/BatchingPipelineTest.php @@ -4,9 +4,10 @@ namespace Flow\ETL\Tests\Integration\Pipeline; -use Flow\ETL\Pipeline; +use Flow\ETL\Executor\Segments; use Flow\ETL\Processor\BatchingProcessor; use Flow\ETL\Rows; +use Flow\ETL\Tests\Context\ExecutedSegments; use Flow\ETL\Tests\FlowTestCase; use function array_map; @@ -20,7 +21,7 @@ final class BatchingPipelineTest extends FlowTestCase { public function test_batching_rows(): void { - $pipeline = new Pipeline(from_all( + $segments = new Segments(from_all( from_array([ ['id' => 1], ['id' => 2], @@ -36,14 +37,14 @@ public function test_batching_rows(): void ['id' => 10], ]), )); - $pipeline->add(new BatchingProcessor(10)); + $segments->add(new BatchingProcessor(10)); - static::assertCount(1, iterator_to_array($pipeline->process(flow_context(config())))); + static::assertCount(1, iterator_to_array(ExecutedSegments::of($segments, flow_context(config())))); } public function test_that_rows_are_not_lost(): void { - $pipeline = new Pipeline(from_all(from_array([ + $segments = new Segments(from_all(from_array([ ['id' => 1], ['id' => 2], ['id' => 3], @@ -55,7 +56,7 @@ public function test_that_rows_are_not_lost(): void ['id' => 9], ['id' => 10], ]))); - $pipeline->add(new BatchingProcessor(7)); + $segments->add(new BatchingProcessor(7)); static::assertEquals( [ @@ -76,14 +77,14 @@ public function test_that_rows_are_not_lost(): void ], array_map( static fn(Rows $r) => $r->toArray(), - iterator_to_array($pipeline->process(flow_context(config()))), + iterator_to_array(ExecutedSegments::of($segments, flow_context(config()))), ), ); } public function test_using_bigger_batch_size_than_total_number_of_rows(): void { - $pipeline = new Pipeline(from_all( + $segments = new Segments(from_all( from_array([ ['id' => 1], ['id' => 2], @@ -99,14 +100,14 @@ public function test_using_bigger_batch_size_than_total_number_of_rows(): void ['id' => 10], ]), )); - $pipeline->add(new BatchingProcessor(11)); + $segments->add(new BatchingProcessor(11)); - static::assertCount(1, iterator_to_array($pipeline->process(flow_context(config())))); + static::assertCount(1, iterator_to_array(ExecutedSegments::of($segments, flow_context(config())))); } public function test_using_smaller_batch_size_than_total_number_of_rows(): void { - $pipeline = new Pipeline(from_all(from_array([ + $segments = new Segments(from_all(from_array([ ['id' => 1], ['id' => 2], ['id' => 3], @@ -118,8 +119,8 @@ public function test_using_smaller_batch_size_than_total_number_of_rows(): void ['id' => 9], ['id' => 10], ]))); - $pipeline->add(new BatchingProcessor(5)); + $segments->add(new BatchingProcessor(5)); - static::assertCount(2, iterator_to_array($pipeline->process(flow_context(config())))); + static::assertCount(2, iterator_to_array(ExecutedSegments::of($segments, flow_context(config())))); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Pipeline/CollectingPipelineTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Pipeline/CollectingPipelineTest.php index fb9945ef79..83f41f5b32 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Pipeline/CollectingPipelineTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Pipeline/CollectingPipelineTest.php @@ -4,8 +4,9 @@ namespace Flow\ETL\Tests\Integration\Pipeline; -use Flow\ETL\Pipeline; +use Flow\ETL\Executor\Segments; use Flow\ETL\Processor\CollectingProcessor; +use Flow\ETL\Tests\Context\ExecutedSegments; use Flow\ETL\Tests\FlowTestCase; use function Flow\ETL\DSL\config; @@ -18,7 +19,7 @@ final class CollectingPipelineTest extends FlowTestCase { public function test_collecting(): void { - $pipeline = new Pipeline(from_all( + $segments = new Segments(from_all( from_array([ ['id' => 1], ['id' => 2], @@ -39,8 +40,8 @@ public function test_collecting(): void ['id' => 13], ]), )); - $pipeline->add(new CollectingProcessor()); + $segments->add(new CollectingProcessor()); - static::assertCount(1, iterator_to_array($pipeline->process(flow_context(config())))); + static::assertCount(1, iterator_to_array(ExecutedSegments::of($segments, flow_context(config())))); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Pipeline/OptimizerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Pipeline/OptimizerTest.php deleted file mode 100644 index 89a5ee6597..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Pipeline/OptimizerTest.php +++ /dev/null @@ -1,27 +0,0 @@ -optimize(new SelectEntriesTransformer(ref('id')), $pipeline); - - static::assertCount(1, $optimizedPipeline->segments()->steps()); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Pipeline/PipelineTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Pipeline/PipelineTest.php index e9ef407f28..a4620c18ae 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Pipeline/PipelineTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Pipeline/PipelineTest.php @@ -4,19 +4,11 @@ namespace Flow\ETL\Tests\Integration\Pipeline; -use Flow\ETL\Bucketing\Buckets; -use Flow\ETL\Bucketing\Storage\MemoryBuckets; use Flow\ETL\Exception\DataDependentSchemaException; use Flow\ETL\Exception\InvalidLogicException; -use Flow\ETL\GroupBy; -use Flow\ETL\Loader; -use Flow\ETL\Pipeline; -use Flow\ETL\Processor\CollectingProcessor; -use Flow\ETL\Processor\GroupByAggregationProcessor; use Flow\ETL\Tests\Double\ReadsBackOnSecondBatch; use Flow\ETL\Tests\Double\StaticDataFrameFactory; use Flow\ETL\Tests\FlowTestCase; -use Flow\ETL\Transformer; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\from_array; @@ -30,25 +22,17 @@ final class PipelineTest extends FlowTestCase { - public function test_a_join_each_cycle_is_refused_when_run(): void + public function test_a_join_each_plan_refuses_to_describe_its_output(): void { $frame = df()->read(from_array([['id' => 1, 'x' => 'p']])); $frame->joinEach(new StaticDataFrameFactory(df()->read(from_data_frame($frame))), join_on([ 'id' => 'id', ], 'r_')); - try { - $frame->schema(); + $this->expectException(DataDependentSchemaException::class); + $this->expectExceptionMessage('JoinEachRowsTransformer'); - static::fail('Expected joinEach() to refuse to describe its output.'); - } catch (DataDependentSchemaException $e) { - static::assertStringContainsString('JoinEachRowsTransformer', $e->getMessage()); - } - - $this->expectException(InvalidLogicException::class); - $this->expectExceptionMessage('Cannot run this plan: it reads from a DataFrame that reads back from it.'); - - $frame->fetch(); + $frame->schema(); } public function test_a_plan_can_be_run_twice(): void @@ -88,56 +72,13 @@ public function test_a_plan_read_again_while_an_earlier_generator_is_parked_is_n static::assertSame(3, $frame->fetch()->count()); } - public function test_a_plan_that_reads_back_from_itself_is_refused_when_described(): void + public function test_a_plan_that_reads_back_from_itself_is_a_self_join(): void { $frame = df()->read(from_array([['id' => 1, 'x' => 'p']])); $frame->join(df()->read(from_data_frame($frame)), join_on(['id' => 'id'], 'r_')); - $this->expectException(InvalidLogicException::class); - $this->expectExceptionMessage( - 'Cannot describe this plan: it reads from a DataFrame that reads back from it. A DataFrame is ' - . 'mutable, so join(), select() and withEntry() can add that edge after both frames exist. Break ' - . 'the cycle by reading the nested frame from its own source.', - ); - - $frame->schema(); - } - - public function test_fetching_a_plan_that_reads_back_from_itself_is_refused_at_bind(): void - { - $frame = df()->read(from_array([['id' => 1, 'x' => 'p']])); - $frame->join(df()->read(from_data_frame($frame)), join_on(['id' => 'id'], 'r_')); - - // this used to segfault - $this->expectException(InvalidLogicException::class); - $this->expectExceptionMessage( - 'Cannot describe this plan: it reads from a DataFrame that reads back from it. A DataFrame is ' - . 'mutable, so join(), select() and withEntry() can add that edge after both frames exist. Break ' - . 'the cycle by reading the nested frame from its own source.', - ); - - $frame->fetch(); - } - - public function test_getting_steps_from_pipeline(): void - { - $pipeline = new Pipeline(from_rows(rows(schema()))); - $pipeline->add($transformer1 = $this->createStub(Transformer::class)); - $pipeline->add($groupBy = new GroupByAggregationProcessor(new GroupBy(), new Buckets(new MemoryBuckets()))); - $pipeline->add($transformer2 = $this->createStub(Transformer::class)); - $pipeline->add($collecting = new CollectingProcessor()); - $pipeline->add($loader = $this->createStub(Loader::class)); - - static::assertSame( - [ - $transformer1, - $groupBy, - $transformer2, - $collecting, - $loader, - ], - $pipeline->segments()->steps(), - ); + static::assertSame(['id', 'x', 'r_id', 'r_x'], $frame->schema()->references()->names()); + static::assertSame([['id' => 1, 'x' => 'p', 'r_id' => 1, 'r_x' => 'p']], $frame->fetch()->toArray()); } public function test_the_same_frame_read_twice_in_one_plan_is_not_a_cycle(): void diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Sort/MemorySort/MemorySortTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Sort/MemorySort/MemorySortTest.php index 2961eaf14f..007a2faf85 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Sort/MemorySort/MemorySortTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Sort/MemorySort/MemorySortTest.php @@ -4,8 +4,9 @@ namespace Flow\ETL\Tests\Integration\Sort\MemorySort; -use Flow\ETL\Pipeline; +use Flow\ETL\Executor\Segments; use Flow\ETL\Processor\MemorySortProcessor; +use Flow\ETL\Tests\Context\ExecutedSegments; use Flow\ETL\Tests\FlowTestCase; use function array_map; @@ -38,9 +39,9 @@ public function test_memory_implementation_of_external_sort_algorithm(): void $processor = new MemorySortProcessor(refs(ref('id')->desc())); $context = flow_context(); - $pipeline = new Pipeline(from_array($randomizedInput)); + $segments = new Segments(from_array($randomizedInput)); - $sortedOutput = iterator_to_array($processor->process($pipeline->process($context), $context)); + $sortedOutput = iterator_to_array($processor->process(ExecutedSegments::of($segments, $context), $context)); static::assertEquals($input, array_merge(...array_map(static fn($row) => $row->toArray(), $sortedOutput))); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Mother/EntryMother.php b/src/core/etl/tests/Flow/ETL/Tests/Mother/EntryMother.php new file mode 100644 index 0000000000..5cbe037543 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Mother/EntryMother.php @@ -0,0 +1,25 @@ + $children + * @param list $lines + */ + public static function named( + string $name, + ?int $number = 1, + array $children = [], + array $lines = [], + string $suffix = '', + ): Entry { + return new Entry(new stdClass(), $name, $lines, $number, false, $children, $suffix); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Mother/HashJoinProcessorMother.php b/src/core/etl/tests/Flow/ETL/Tests/Mother/HashJoinProcessorMother.php index 5c3e7d9563..8859c806c8 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Mother/HashJoinProcessorMother.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Mother/HashJoinProcessorMother.php @@ -7,7 +7,8 @@ use Flow\ETL\Bucketing\Buckets; use Flow\ETL\Bucketing\BucketsStorage; use Flow\ETL\Bucketing\Storage\MemoryBuckets; -use Flow\ETL\DataFrame; +use Flow\ETL\Executor; +use Flow\ETL\Executor\PhysicalPlan; use Flow\ETL\Join\Expression; use Flow\ETL\Join\Join; use Flow\ETL\NativePHPRandomValueGenerator; @@ -23,7 +24,7 @@ final class HashJoinProcessorMother * @param int<1, max> $batchSize */ public static function grace( - DataFrame $right, + PhysicalPlan $right, Expression $on, Join $type, ?SpyBucketsStorage $storage = null, @@ -46,7 +47,7 @@ public static function grace( * @param int<1, max> $batchSize */ public static function resident( - DataFrame $right, + PhysicalPlan $right, Expression $on, Join $type, int $batchSize = 1000, @@ -59,7 +60,7 @@ public static function resident( * @param int<1, max> $batchSize */ public static function with( - DataFrame $right, + PhysicalPlan $right, Expression $on, Join $type, BucketsStorage $storage, @@ -68,6 +69,7 @@ public static function with( ): HashJoinProcessor { return new HashJoinProcessor( $right, + new Executor(), $on, $type, new Buckets($storage), diff --git a/src/core/etl/tests/Flow/ETL/Tests/Mother/NodeMother.php b/src/core/etl/tests/Flow/ETL/Tests/Mother/NodeMother.php new file mode 100644 index 0000000000..52609e04e7 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Mother/NodeMother.php @@ -0,0 +1,80 @@ + 'id']), Join::left, null); + } + + public static function crossJoin(Node $left, Node $right): Node\CrossJoin + { + return new Node\CrossJoin($left, $right, 'r_'); + } + + public static function nonRepeatableRead(): Read + { + return new Read(new RepeatableExtractor(false)); + } + + public static function joinRight(LogicalPlan $plan): Node + { + return $plan->root; + } + + public static function limit(Node $input, int $limit): Limit + { + return new Limit($input, $limit); + } + + public static function plan(Node $root): LogicalPlan + { + return Trigger::rows->plan($root); + } + + public static function read(?Extractor $extractor = null): Read + { + return new Read($extractor ?? from_array([['id' => 1]])); + } + + public static function select(Node $input, string ...$entries): Select + { + return new Select($input, $entries === [] ? ['id'] : array_values($entries)); + } + + public static function sort(Node $input, ?References $refs = null): Sort + { + return new Sort($input, $refs ?? refs(ref('id'))); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Mother/PartitionedSourceMother.php b/src/core/etl/tests/Flow/ETL/Tests/Mother/PartitionedSourceMother.php new file mode 100644 index 0000000000..0c9a9470be --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Mother/PartitionedSourceMother.php @@ -0,0 +1,45 @@ + 2023, 'month' => '07', 'value' => 'a']), + row(['year' => 2024, 'month' => '08', 'value' => 'b']), + ), + ))->withPartitionSchema(self::partitions()); + } + + public static function file(string $partitions): FileStatus + { + return new FileStatus(path('flow-file://data/' . $partitions . '/file.csv'), true); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Mother/PhysicalPlanMother.php b/src/core/etl/tests/Flow/ETL/Tests/Mother/PhysicalPlanMother.php new file mode 100644 index 0000000000..ecef9a1d15 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Mother/PhysicalPlanMother.php @@ -0,0 +1,32 @@ +explain(); + + return $plan->context->config->planner()->plan($plan->logical, $plan->context); + } + + public static function reading(Extractor $extractor): PhysicalPlan + { + return (new Planner(Optimizer::default()))->plan( + NodeMother::plan(NodeMother::read($extractor)), + NodeMother::context(), + ); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Mother/SinkAttachmentMother.php b/src/core/etl/tests/Flow/ETL/Tests/Mother/SinkAttachmentMother.php new file mode 100644 index 0000000000..4b1547c94c --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Mother/SinkAttachmentMother.php @@ -0,0 +1,39 @@ +} + */ + public static function over(Sinks $sinks, Node ...$spine): array + { + $planned = new PlannedNodes(); + + foreach ($sinks as $sink) { + (new Planner())->node($sink, NodeMother::context(), $planned); + } + + /** @var SplObjectStorage $onSpine */ + $onSpine = new SplObjectStorage(); + + foreach ($spine as $node) { + (new Planner())->node($node, NodeMother::context(), $planned); + $onSpine[$node] = $node; + } + + return [new SinkAttachment($planned, NodeMother::context()), $onSpine]; + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Mother/SinkFeedMother.php b/src/core/etl/tests/Flow/ETL/Tests/Mother/SinkFeedMother.php new file mode 100644 index 0000000000..5ce17b6999 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Mother/SinkFeedMother.php @@ -0,0 +1,69 @@ + $id])); + } + + public static function feed(): FeedExtractor + { + return new FeedExtractor(schema(int_schema('id'))); + } + + public static function pipeline( + FeedExtractor $feed, + FlowContext $context, + Transformer|Loader|Processor ...$steps, + ): Pipeline { + $segments = new Segments($feed); + + foreach ($steps as $step) { + $segments->add($step); + } + + return new Pipeline(0, $segments, $context); + } + + /** + * The wiring the planner builds for one non-bare sink: $before, then the sink's own loader, under a context whose + * handler is $offers. + */ + public static function sinkFeed(SinkOffers $offers, Loader $loader, Transformer|Processor ...$before): SinkFeed + { + $feed = self::feed(); + + return new SinkFeed( + $feed, + new SinkRun( + self::pipeline($feed, NodeMother::context()->withErrorHandler($offers), ...[...$before, $loader]), + new Executor(), + ), + $offers, + $loader, + ); + } +} 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 444b159299..cd5e9c28b8 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 @@ -8,6 +8,10 @@ use Flow\ETL\Config\Telemetry\TelemetryContext; use Flow\ETL\Config\Telemetry\TelemetryOptions; use Flow\ETL\Loader\StreamLoader; +use Flow\ETL\Optimizer\Rule\CombineLimits; +use Flow\ETL\Optimizer\Rule\CombineSortAndLimit; +use Flow\ETL\Optimizer\Rule\PushFilterIntoSource; +use Flow\ETL\Optimizer\Rule\PushLimitIntoSource; use Flow\ETL\Tests\Context\MemoryTelemetryContext; use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Transformer\LimitTransformer; @@ -939,4 +943,35 @@ public function now(): DateTimeImmutable } }; } + + public function test_optimizer_rules_are_logged(): void + { + $logProcessor = new MemoryLogProcessor(new VoidExporter()); + $clock = $this->createFrozenClock(); + $contextStorage = new MemoryContextStorage(); + + $telemetry = new Telemetry( + Resource::create(['service.name' => 'flow-test']), + new TracerProvider(new MemorySpanProcessor(new VoidExporter()), $clock, $contextStorage), + new MeterProvider(new MemoryMetricProcessor(new VoidExporter()), $clock), + new LoggerProvider($logProcessor, $clock, $contextStorage), + ); + + $telemetryContext = new TelemetryContext( + $telemetry->logger('flow-php'), + $telemetry->tracer('flow-php'), + $telemetry->meter('flow-php'), + new TelemetryOptions(), + ); + + $telemetryContext->dataFrameStarted(flow_context(config_builder()->withTelemetry($telemetry)->build())); + + $debugLogs = $logProcessor->entriesWithSeverity(Severity::DEBUG); + + static::assertCount(1, $debugLogs); + static::assertSame( + [CombineLimits::class, CombineSortAndLimit::class, PushLimitIntoSource::class, PushFilterIntoSource::class], + $debugLogs[0]->record->attributes->get('optimizer_rules'), + ); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/DataFrameTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/DataFrameTest.php index 01c51ac5f4..d9457f7952 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/DataFrameTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/DataFrameTest.php @@ -4,41 +4,73 @@ namespace Flow\ETL\Tests\Unit; +use ArrayObject; use DateTimeImmutable; +use Flow\ETL\BoundStep; use Flow\ETL\DataFrame; use Flow\ETL\ErrorHandler\IgnoreError; +use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Exception\InvalidLogicException; use Flow\ETL\Extractor; use Flow\ETL\Extractor\Signal; use Flow\ETL\FlowContext; use Flow\ETL\Loader; -use Flow\ETL\Pipeline\BoundStep; +use Flow\ETL\Memory\ArrayMemory; +use Flow\ETL\Optimizer; +use Flow\ETL\Plan\Format; +use Flow\ETL\Plan\Node\CrossJoin; +use Flow\ETL\Plan\Node\Read; +use Flow\ETL\Plan\Stage; +use Flow\ETL\Plan\Trigger; use Flow\ETL\Row\RowRenaming; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\Schema\Validator\SelectiveValidator; +use Flow\ETL\Sink\Branched; +use Flow\ETL\Sink\Transformed; use Flow\ETL\Tests\Double\AddStampToStringEntryTransformer; +use Flow\ETL\Tests\Double\CallbackTransformation; +use Flow\ETL\Tests\Double\CallOrderLoader; +use Flow\ETL\Tests\Double\RecordingErrorHandler; +use Flow\ETL\Tests\Double\RecordingFileExtractor; +use Flow\ETL\Tests\Double\RecordingRule; use Flow\ETL\Tests\Double\RowLessExtractor; use Flow\ETL\Tests\Double\SpyLoader; +use Flow\ETL\Tests\Double\SpySink; +use Flow\ETL\Tests\Double\StaticDataFrameFactory; +use Flow\ETL\Tests\Double\ThrowingLoader; +use Flow\ETL\Tests\Double\ThrowingTransformer; use Flow\ETL\Tests\Double\UndescribableRowLessExtractor; use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Transformation; +use Flow\ETL\Transformation\AddRowIndex\StartFrom; +use Flow\ETL\Transformations; use Flow\ETL\Transformer; +use Flow\ETL\Transformer\AddRowIndexTransformer; use Generator; use PHPUnit\Framework\Assert; +use PHPUnit\Framework\Attributes\TestWith; use RuntimeException; +use function array_column; use function array_merge; +use function Flow\ETL\DSL\add_row_index; use function Flow\ETL\DSL\average; use function Flow\ETL\DSL\bool_schema; +use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\data_frame; use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\float_schema; +use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\from_all; use function Flow\ETL\DSL\from_array; +use function Flow\ETL\DSL\from_data_frame; use function Flow\ETL\DSL\from_rows; +use function Flow\ETL\DSL\from_sequence_number; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\integer_schema; +use function Flow\ETL\DSL\join_on; use function Flow\ETL\DSL\json_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; @@ -46,8 +78,11 @@ use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\select; use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\string_schema; +use function Flow\ETL\DSL\to_memory; +use function Flow\ETL\DSL\to_transformation; use function Flow\Types\DSL\type_json; use function iterator_to_array; @@ -69,7 +104,7 @@ public function test_batch_size(): void ->load($spy) ->withEntry('element', ref('elements')->expand()) ->batchSize(3) - ->run(function (Rows $rows): void { + ->forEach(function (Rows $rows): void { $this->assertLessThanOrEqual(3, $rows->count()); }); @@ -222,7 +257,7 @@ public function schema(): Schema * * @return \Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { for ($i = 1; $i <= 10; $i++) { yield rows(schema(integer_schema('id')), row(['id' => $i])); @@ -372,7 +407,7 @@ public function schema(): Schema * * @return \Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { for ($i = 1; $i <= 10; $i++) { yield rows(schema(integer_schema('id')), row(['id' => $i])); @@ -423,7 +458,7 @@ public function schema(): Schema * * @return \Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { yield rows( schema( @@ -721,7 +756,7 @@ public function schema(): Schema * * @return \Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { yield rows( schema(integer_schema('id')), @@ -784,7 +819,7 @@ public function schema(): Schema * * @return \Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { yield rows(schema(integer_schema('id')), row(['id' => 1])); yield rows(schema(integer_schema('id')), row(['id' => 2])); @@ -859,4 +894,519 @@ public function test_fetch_does_not_claim_the_source_schema_when_a_step_reshapes static::assertCount(0, $rows); static::assertCount(0, $rows->schema()->definitions()); } + + public function test_a_pushed_limit_reaches_extract_and_leaves_the_users_extractor_alone(): void + { + $extractor = new RecordingFileExtractor( + schema(int_schema('id')), + rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])), + ); + $frame = df() + ->read($extractor) + ->withEntry('doubled', ref('id')->multiply(lit(2))) + ->limit(1); + + $frame->schema(); + + static::assertSame([['id' => 1, 'doubled' => 2]], $frame->fetch()->toArray()); + static::assertSame([['id' => 1, 'doubled' => 2]], $frame->fetch()->toArray()); + static::assertCount(2, $extractor->limits); + static::assertSame(1, $extractor->limits[0]); + static::assertSame(1, $extractor->limits[1]); + static::assertStringEndsWith( + "#1 Read\n Extractor: RecordingFileExtractor\n Source: file://dev/null", + $frame->explain()->toString(Stage::unoptimized), + ); + static::assertStringEndsWith( + "#1 Read\n Extractor: RecordingFileExtractor\n Source: file://dev/null" + . "\n Limit: 1", + $frame->explain()->toString(), + ); + } + + public function test_a_limit_inside_a_joins_right_side_is_pushed_into_that_source(): void + { + $extractor = new RecordingFileExtractor( + schema(int_schema('id')), + rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])), + ); + $right = df()->read($extractor)->limit(1); + + df() + ->read(from_array([['id' => 1]])) + ->join($right, join_on(['id' => 'id'], 'r_')) + ->fetch(); + + static::assertSame(1, $extractor->limits[0]); + } + + public function test_an_empty_fetch_plans_once(): void + { + /** @var ArrayObject $log */ + $log = new ArrayObject(); + + $rows = df(config_builder()->optimizer(new Optimizer(new RecordingRule('plan', $log)))) + ->read(from_array([['id' => 1]])) + ->filter(ref('id')->equals(lit(2))) + ->fetch(); + + static::assertCount(0, $rows); + static::assertCount(1, $log); + } + + public function test_an_abandoned_get_each_leaves_no_consumed_step_for_the_next_run(): void + { + $dataFrame = df() + ->read(from_rows( + rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])), + rows(schema(int_schema('id')), row(['id' => 3]), row(['id' => 4])), + )) + ->limit(3); + + // the reference keeps the generator parked, so its steps stay consumed + $parked = $dataFrame->getEach(); + $parked->current(); + + static::assertCount(3, $dataFrame->fetch()); + } + + public function test_an_error_handler_set_after_schema_reaches_a_sink_root(): void + { + $handler = new RecordingErrorHandler(new IgnoreError()); + $dataFrame = df() + ->read(from_array([['id' => 1]])) + ->write(new Branched(ref('id')->equals(lit(1)), new ThrowingLoader(new RuntimeException('boom')))); + + $dataFrame->schema(); + $dataFrame->onError($handler); + $dataFrame->run(); + + static::assertCount(1, $handler->errors); + } + + public function test_on_error_sets_the_handler(): void + { + $context = flow_context(); + $handler = new IgnoreError(); + + (new DataFrame(from_array([['id' => 1]]), $context))->onError($handler); + + static::assertSame($handler, $context->errorHandler()); + } + + public function test_on_error_inside_a_sinks_transformation_is_refused(): void + { + $this->expectException(InvalidLogicException::class); + $this->expectExceptionMessage( + 'onError() inside a sink cannot apply, because a plan runs under one error handler: call onError() on ' + . 'the frame, not inside ' + . Transformed::class, + ); + + df()->read(from_array([['id' => 1]]))->write(new Transformed( + new CallbackTransformation(static fn(DataFrame $prefix): DataFrame => $prefix->onError(new IgnoreError())), + to_memory(new ArrayMemory()), + )); + } + + public function test_a_sink_without_on_error_is_not_refused(): void + { + $memory = new ArrayMemory(); + + df() + ->read(from_array([['id' => 1]])) + ->write(new Transformed(select('id'), to_memory($memory))) + ->run(); + + static::assertSame([['id' => 1]], $memory->dump()); + } + + public function test_a_sink_that_cannot_describe_its_rows_does_not_hide_the_frames_schema(): void + { + $frame = df() + ->read(from_array([['id' => 1], ['id' => 2]], schema(int_schema('id')))) + ->withEntry('double', ref('id')->multiply(lit(2))) + ->write(to_transformation(new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df->joinEach( + new StaticDataFrameFactory(df()->read(from_array([['id' => 1, 'name' => 'a']]))), + join_on(['id' => 'id'], 'joined_'), + )), to_memory(new ArrayMemory()))); + + static::assertEquals(schema(int_schema('id'), int_schema('double')), $frame->schema()); + } + + public function test_a_row_index_starts_again_on_every_run(): void + { + $frame = df()->read(from_array([['id' => 1], ['id' => 2], ['id' => 3]]))->with(add_row_index('idx')); + + static::assertSame([0, 1, 2], array_column($frame->fetch()->toArray(), 'idx')); + static::assertSame([0, 1, 2], array_column($frame->fetch()->toArray(), 'idx')); + } + + public function test_schema_then_a_run_plans_twice(): void + { + /** @var ArrayObject $log */ + $log = new ArrayObject(); + $dataFrame = df(config_builder()->optimizer(new Optimizer(new RecordingRule('plan', $log)))) + ->read(from_array([['id' => 1]])); + + $dataFrame->schema(); + $dataFrame->run(); + + static::assertCount(2, $log); + } + + public function test_a_limit_inside_a_read_frame_is_pushed_into_its_source(): void + { + $extractor = new RecordingFileExtractor( + schema(int_schema('id')), + rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])), + ); + $inner = df()->read($extractor)->limit(1); + + static::assertSame([['id' => 1]], df()->read(from_data_frame($inner))->fetch()->toArray()); + static::assertSame(1, $extractor->limits[0]); + } + + public function test_explain_without_sinks_prints_one_result_over_the_chain(): void + { + $dataFrame = df()->read(from_array([['id' => 1]]))->select('id'); + + static::assertSame(<<<'PLAN' + #3 Result preserving · transparent · streaming + │ Rows this plan hands out: to the trigger, or to the node reading it + └─ #2 Select preserving · transparent · streaming + │ Columns: id + └─ #1 Read source · transparent · streaming + Extractor: ArrayExtractor + PLAN, $dataFrame->explain()->toString(format: Format::declarations)); + } + + public function test_explain_with_a_sink_prints_the_outputs_sharing_the_chain(): void + { + $dataFrame = df() + ->read(from_array([['id' => 1]])) + ->write(to_memory(new ArrayMemory())) + ->select('id'); + + static::assertSame(<<<'PLAN' + Outputs preserving · opaque · streaming + ├─ #3 Result preserving · transparent · streaming + │ │ Rows this plan hands out: to the trigger, or to the node reading it + │ └─ #2 Select preserving · transparent · streaming + │ │ Columns: id + │ └─ #1 Read source · transparent · streaming + │ Extractor: ArrayExtractor + └─ #4 Write preserving · opaque · streaming + │ Loader: MemoryLoader + └─ #1 Read (shared) + PLAN, $dataFrame->explain()->toString(format: Format::declarations)); + } + + public function test_explain_of_the_run_trigger_makes_the_write_the_root(): void + { + $dataFrame = df()->read(from_array([['id' => 1]]))->write(to_memory(new ArrayMemory())); + + static::assertSame(<<<'PLAN' + #2 Write preserving · opaque · streaming + │ Loader: MemoryLoader + └─ #1 Read source · transparent · streaming + Extractor: ArrayExtractor + PLAN, $dataFrame->explain(Trigger::run)->toString(format: Format::declarations)); + } + + public function test_explain_of_the_run_trigger_keeps_a_result_over_a_chain_end_no_sink_reads(): void + { + $dataFrame = df() + ->read(from_array([['id' => 1]])) + ->write(to_memory(new ArrayMemory())) + ->select('id'); + + static::assertSame(<<<'PLAN' + Outputs preserving · opaque · streaming + ├─ #3 Result preserving · transparent · streaming + │ │ Rows this plan hands out: to the trigger, or to the node reading it + │ └─ #2 Select preserving · transparent · streaming + │ │ Columns: id + │ └─ #1 Read source · transparent · streaming + │ Extractor: ArrayExtractor + └─ #4 Write preserving · opaque · streaming + │ Loader: MemoryLoader + └─ #1 Read (shared) + PLAN, $dataFrame->explain(Trigger::run)->toString(format: Format::declarations)); + } + + public function test_for_each_receives_every_batch(): void + { + $batches = []; + + df() + ->read(from_array([['id' => 1], ['id' => 2], ['id' => 3]])) + ->batchSize(2) + ->forEach(static function (Rows $rows) use (&$batches): void { + $batches[] = $rows->count(); + }); + + static::assertSame([2, 1], $batches); + } + + public function test_explain_prints_the_logical_plan_without_reading_a_row(): void + { + $extractor = new RecordingFileExtractor(schema(int_schema('id'))); + $dataFrame = df()->read($extractor)->filter(ref('id')->isNotNull())->write(to_memory(new ArrayMemory())); + + static::assertSame(<<<'PLAN' + #3 Write preserving · opaque · streaming + │ Loader: MemoryLoader + └─ #2 Filter reducing · transparent · streaming + │ Condition: IsNotNull + └─ #1 Read source · transparent · streaming + Extractor: RecordingFileExtractor + Source: file://dev/null + PLAN, $dataFrame->explain()->toString(format: Format::declarations)); + static::assertSame([], $extractor->limits); + } + + public function test_from_data_frame_reads_the_frame_as_a_source(): void + { + $frame = df()->read(from_array([['id' => 1], ['id' => 2]]))->filter(ref('id')->greaterThan(lit(1))); + + static::assertSame([['id' => 2]], df()->read(from_data_frame($frame))->fetch()->toArray()); + } + + public function test_from_data_frame_freezes_the_frame(): void + { + $frame = df()->read(from_array([['id' => 1, 'name' => 'a']])); + $extractor = from_data_frame($frame); + + $frame->select('id'); + + static::assertSame([['id' => 1, 'name' => 'a']], df()->read($extractor)->fetch()->toArray()); + } + + /** + * @param int<-1, 0> $size + */ + #[TestWith([-1])] + #[TestWith([0])] + public function test_batch_size_below_one_collects_every_row_into_one_batch(int $size): void + { + $batches = iterator_to_array( + df() + ->read(from_array([['id' => 1], ['id' => 2], ['id' => 3]])) + ->batchSize(1) + ->batchSize($size) + ->get(), + false, + ); + + static::assertCount(1, $batches); + static::assertSame(3, $batches[0]->count()); + } + + public function test_cache_refuses_a_batch_size_below_one(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Cache batch size must be greater than 0'); + + df()->read(from_array([['id' => 1]]))->cache(cacheBatchSize: 0); + } + + public function test_join_takes_the_join_type_as_a_string(): void + { + static::assertSame( + [['id' => 1, 'r_id' => 1, 'r_x' => 'a']], + df() + ->read(from_array([['id' => 1], ['id' => 2]])) + ->join(df()->read(from_array([['id' => 1, 'x' => 'a']])), join_on(['id' => 'id'], 'r_'), 'inner') + ->fetch() + ->toArray(), + ); + } + + public function test_join_each_refuses_an_unsupported_join_type(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Unsupported join type'); + + df() + ->read(from_array([['id' => 1]])) + ->joinEach( + new StaticDataFrameFactory(df()->read(from_array([['id' => 1]]))), + join_on(['id' => 'id']), + 'nope', + ); + } + + public function test_with_applies_every_transformation_of_a_transformations_group(): void + { + static::assertSame( + [['id' => 1]], + df() + ->read(from_array([['id' => 1, 'name' => 'a']])) + ->with(new Transformations(select('id'))) + ->fetch() + ->toArray(), + ); + } + + public function test_an_error_handler_set_after_join_does_not_reach_the_joined_frame(): void + { + $left = df()->read(from_array([['id' => 1], ['id' => 2]])); + $right = df() + ->read(from_array([['id' => 1, 'x' => 'a']])) + ->with(new ThrowingTransformer(new RuntimeException('right boom'))); + $left->join($right, join_on(['id' => 'id'], 'r_')); + $right->onError(new IgnoreError()); + + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('right boom'); + + $left->fetch(); + } + + public function test_an_error_handler_set_after_cross_join_does_not_reach_the_joined_frame(): void + { + $left = df()->read(from_array([['id' => 1], ['id' => 2]])); + $right = df() + ->read(from_array([['x' => 'a']])) + ->with(new ThrowingTransformer(new RuntimeException('right boom'))); + $left->crossJoin($right, 'r_'); + $right->onError(new IgnoreError()); + + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('right boom'); + + $left->fetch(); + } + + public function test_a_sink_is_handed_a_frame_without_the_callers_sinks(): void + { + $spy = new SpySink(); + + df() + ->read(from_array([['id' => 1]])) + ->write(to_memory(new ArrayMemory())) + ->write(to_memory(new ArrayMemory())) + ->write($spy); + + static::assertInstanceOf(DataFrame::class, $spy->prefix); + static::assertStringStartsWith('#2 Result', $spy->prefix->explain()->toString()); + } + + public function test_a_sink_is_handed_a_frame_other_than_the_caller(): void + { + $frame = df()->read(from_array([['id' => 1]])); + $spy = new SpySink(); + + $frame->write($spy); + + static::assertInstanceOf(DataFrame::class, $spy->prefix); + static::assertNotSame($frame, $spy->prefix); + } + + public function test_two_sinks_share_the_chain_and_do_not_alias(): void + { + $dataFrame = df() + ->read(from_array([['id' => 1]])) + ->write(new Transformed(new AddRowIndexTransformer('idx', StartFrom::ZERO), to_memory(new ArrayMemory()))) + ->write(new Branched(ref('id')->equals(lit(1)), to_memory(new ArrayMemory()))); + + static::assertSame(<<<'PLAN' + Outputs preserving · opaque · streaming + ├─ #2 Result preserving · transparent · streaming + │ │ Rows this plan hands out: to the trigger, or to the node reading it + │ └─ #1 Read source · transparent · streaming + │ Extractor: ArrayExtractor + ├─ #4 Write preserving · opaque · streaming + │ │ Loader: MemoryLoader + │ └─ #3 Transform unknown · opaque · streaming · redefines unknown + │ └─ #1 Read (shared) + └─ #6 Write preserving · opaque · streaming + │ Loader: MemoryLoader + └─ #5 Filter reducing · transparent · streaming + │ Condition: Equals + └─ #1 Read (shared) + PLAN, $dataFrame->explain()->toString(format: Format::declarations)); + } + + public function test_a_write_inside_a_sinks_transformation_runs_before_the_sinks_own_write(): void + { + /** @var ArrayObject $log */ + $log = new ArrayObject(); + + df() + ->read(from_sequence_number('id', 0, 3)) + ->batchSize(2) + ->write( + new Transformed( + new CallbackTransformation(static fn(DataFrame $prefix): DataFrame => $prefix->write(new CallOrderLoader( + 'inner', + $log, + ))), + new CallOrderLoader('outer', $log), + ), + ) + ->run(); + + static::assertSame(['inner:2', 'outer:2', 'inner:2', 'outer:2'], $log->getArrayCopy()); + } + + public function test_a_joined_frame_is_part_of_the_outer_plan(): void + { + $right = df()->read(from_array([['id' => 1]])); + + $spine = df() + ->read(from_array([['id' => 1]])) + ->crossJoin($right, 'r_') + ->explain() + ->logical->spine(); + + static::assertInstanceOf(CrossJoin::class, $spine); + static::assertEquals($right->explain()->logical->root, $spine->children()[1]); + } + + public function test_the_same_frame_cross_joined_twice_is_read_by_both_joins(): void + { + $right = df()->read(from_array([['n' => 1]])); + + $frame = df() + ->read(from_array([['id' => 1]])) + ->crossJoin($right, 'a_') + ->crossJoin($right, 'b_'); + + static::assertSame([['id' => 1, 'a_n' => 1, 'b_n' => 1]], $frame->fetch()->toArray()); + } + + public function test_for_each_without_a_callback_still_executes_the_plan(): void + { + $sink = new SpyLoader(); + + df() + ->read(from_array([['id' => 1], ['id' => 2]])) + ->batchSize(1) + ->write($sink) + ->forEach(); + + static::assertSame([1, 1], $sink->loadedRowCounts()); + } + + public function test_a_read_frame_is_a_source_of_the_outer_plan(): void + { + $extractor = from_data_frame(df()->read(from_array([['id' => 1]]))->select('id')); + + $spine = df()->read($extractor)->explain()->logical->spine(); + + static::assertInstanceOf(Read::class, $spine); + static::assertSame($extractor, $spine->extractor()); + } + + public function test_a_verb_on_the_joined_frame_after_the_join_does_not_reach_the_outer_plan(): void + { + $right = df()->read(from_array([['id' => 1, 'n' => 'a']])); + $outer = df()->read(from_array([['id' => 1]]))->join($right, join_on(['id' => 'id'], 'r_')); + + $right->filter(ref('id')->equals(lit(2))); + + static::assertSame([['id' => 1, 'r_id' => 1, 'r_n' => 'a']], $outer->fetch()->toArray()); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/ETLErrorHandlingTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/ETLErrorHandlingTest.php index a29eb83ca5..e53d89341a 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/ETLErrorHandlingTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/ETLErrorHandlingTest.php @@ -5,11 +5,11 @@ namespace Flow\ETL\Tests\Unit; use DateTimeImmutable; +use Flow\ETL\BoundStep; use Flow\ETL\Extractor; use Flow\ETL\Extractor\Signal; use Flow\ETL\FlowContext; use Flow\ETL\Loader; -use Flow\ETL\Pipeline\BoundStep; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\Tests\Double\ThrowingAfterFirstBatchExtractor; @@ -65,7 +65,7 @@ public function schema(): Schema * * @return \Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { $schema = schema( int_schema('id'), @@ -141,7 +141,7 @@ public function schema(): Schema * * @return \Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { $schema = schema( int_schema('id'), @@ -239,7 +239,7 @@ public function schema(): Schema * * @return \Generator */ - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { $schema = schema( int_schema('id'), diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Exception/InvalidLogicExceptionTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Exception/InvalidLogicExceptionTest.php index eb5e64dcc6..de8f463ffa 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Exception/InvalidLogicExceptionTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Exception/InvalidLogicExceptionTest.php @@ -11,12 +11,6 @@ final class InvalidLogicExceptionTest extends FlowTestCase { public function test_cyclic_plan_names_the_operation_and_the_way_out(): void { - static::assertSame( - 'Cannot describe this plan: it reads from a DataFrame that reads back from it. A DataFrame is ' - . 'mutable, so join(), select() and withEntry() can add that edge after both frames exist. Break ' - . 'the cycle by reading the nested frame from its own source.', - InvalidLogicException::cyclicPlanOnDescribe()->getMessage(), - ); static::assertSame( 'Cannot run this plan: it reads from a DataFrame that reads back from it. A DataFrame is ' . 'mutable, so join(), select() and withEntry() can add that edge after both frames exist. Break ' diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Exception/SchemaNotDerivableExceptionTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Exception/SchemaNotDerivableExceptionTest.php index 13f94069c0..c47ee1eb63 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Exception/SchemaNotDerivableExceptionTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Exception/SchemaNotDerivableExceptionTest.php @@ -66,12 +66,12 @@ public function test_probe_refused_names_the_refusal_and_the_conditional_way_out ); } - public function test_non_rewindable_names_the_extractor_and_the_way_out(): void + public function test_non_rewindable_names_the_way_out(): void { static::assertSame( - 'ChainExtractor cannot read its dataset twice, so discover_pivot_values() cannot scan it before the ' - . 'pivot runs. Declare the values with pivot_values(...).', - SchemaNotDerivableException::nonRewindable('ChainExtractor')->getMessage(), + 'The frame reads a source that cannot read its dataset twice, so discover_pivot_values() cannot scan it ' + . 'before the pivot runs. Declare the values with pivot_values(...).', + SchemaNotDerivableException::nonRewindable()->getMessage(), ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Pipeline/ClosureTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/ClosureTest.php similarity index 96% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Pipeline/ClosureTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/ClosureTest.php index 3474e731cf..d95cdc4956 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Pipeline/ClosureTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/ClosureTest.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Pipeline; +namespace Flow\ETL\Tests\Unit\Executor; use Flow\ETL\FlowContext; use Flow\ETL\Loader; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/DescribedTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/DescribedTest.php new file mode 100644 index 0000000000..a3264da2eb --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/DescribedTest.php @@ -0,0 +1,30 @@ + 1]])), NodeMother::context()); + $schema = schema(int_schema('id')); + + $plan = new Described($root, $schema); + + static::assertSame($root, $plan->root()); + static::assertSame($schema, $plan->schema); + static::assertSame($schema, $plan->schema()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Pipeline/DiscardableTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/DiscardableTest.php similarity index 78% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Pipeline/DiscardableTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/DiscardableTest.php index cdf9e598c5..28d95463a1 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Pipeline/DiscardableTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/DiscardableTest.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Pipeline; +namespace Flow\ETL\Tests\Unit\Executor; use Flow\ETL\DataFrame; use Flow\ETL\Exception\RuntimeException; @@ -18,7 +18,6 @@ use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\to_branch; use function Flow\ETL\DSL\to_transformation; -use function Flow\ETL\DSL\write_with_retries; final class DiscardableTest extends FlowTestCase { @@ -91,15 +90,6 @@ public function test_a_discard_that_throws_after_a_failed_run_is_logged(): void static::assertCount(1, $telemetry->logs->entriesContaining('Loader failed to end after a failed run.')); } - public function test_a_sink_wrapped_in_a_retrying_loader_is_discarded_when_its_closure_throws(): void - { - $closureFailure = new RuntimeException('closure failed'); - $sink = new ClosureThrowingLoader($closureFailure); - - static::assertSame($closureFailure, LoaderEndingContext::thrownByRun(write_with_retries($sink))); - static::assertSame(1, $sink->discarded); - } - public function test_a_sink_whose_closure_throws_is_discarded_and_the_failure_rethrown(): void { $closureFailure = new RuntimeException('closure failed'); @@ -109,7 +99,7 @@ public function test_a_sink_whose_closure_throws_is_discarded_and_the_failure_re static::assertSame(1, $sink->discarded); } - public function test_a_sink_wrapped_in_a_branching_loader_is_discarded_when_its_closure_throws(): void + public function test_a_branch_sinks_loader_is_discarded_when_its_closure_throws(): void { $closureFailure = new RuntimeException('closure failed'); $sink = new ClosureThrowingLoader($closureFailure); @@ -118,7 +108,7 @@ public function test_a_sink_wrapped_in_a_branching_loader_is_discarded_when_its_ static::assertSame(1, $sink->discarded); } - public function test_a_sink_wrapped_in_a_branching_loader_is_discarded(): void + public function test_a_branch_sinks_loader_is_discarded(): void { $sink = new RecordingSink(); @@ -128,17 +118,7 @@ public function test_a_sink_wrapped_in_a_branching_loader_is_discarded(): void static::assertSame(0, $sink->closed); } - public function test_a_sink_wrapped_in_a_retry_loader_is_discarded(): void - { - $sink = new RecordingSink(); - - LoaderEndingContext::failedRun(write_with_retries($sink)); - - static::assertSame(1, $sink->discarded); - static::assertSame(0, $sink->closed); - } - - public function test_a_sink_wrapped_in_a_transformation_loader_is_discarded(): void + public function test_a_transformation_sinks_loader_is_discarded(): void { $sink = new RecordingSink(); @@ -155,7 +135,10 @@ public function test_a_sink_wrapped_twice_is_discarded_once(): void { $sink = new RecordingSink(); - LoaderEndingContext::failedRun(write_with_retries(to_branch(ref('id')->isNotNull(), $sink))); + LoaderEndingContext::failedRun(to_branch( + ref('id')->isNotNull(), + to_transformation(new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df), $sink), + )); static::assertSame(1, $sink->discarded); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Pipeline/OffsetPipelineTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/OffsetPipelineTest.php similarity index 73% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Pipeline/OffsetPipelineTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/OffsetPipelineTest.php index a12536a5b5..55911d589f 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Pipeline/OffsetPipelineTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/OffsetPipelineTest.php @@ -2,14 +2,15 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Pipeline; +namespace Flow\ETL\Tests\Unit\Executor; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Executor\Segments; use Flow\ETL\Extractor; use Flow\ETL\FlowContext; -use Flow\ETL\Pipeline; use Flow\ETL\Processor\OffsetProcessor; use Flow\ETL\Schema; +use Flow\ETL\Tests\Context\ExecutedSegments; use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Transformer\ScalarFunctionTransformer; use Generator; @@ -50,15 +51,15 @@ public function test_constructor_with_negative_offset_throws_exception(): void public function test_process_maintains_row_structure_with_mixed_entry_types(): void { - $pipeline = new Pipeline(from_rows(rows( + $segments = new Segments(from_rows(rows( schema(int_schema('id'), bool_schema('active')), row(['id' => 1, 'active' => true]), row(['id' => 2, 'active' => false]), row(['id' => 3, 'active' => true]), row(['id' => 4, 'active' => false]), ))); - $pipeline->add(new OffsetProcessor(1)); - $result = iterator_to_array($pipeline->process(flow_context(config()))); + $segments->add(new OffsetProcessor(1)); + $result = iterator_to_array(ExecutedSegments::of($segments, flow_context(config()))); static::assertCount(1, $result); static::assertCount(3, $result[0]); static::assertEquals( @@ -74,15 +75,15 @@ public function test_process_maintains_row_structure_with_mixed_entry_types(): v public function test_process_with_empty_pipeline(): void { - $pipeline = new Pipeline(from_rows(rows(schema()))); - $pipeline->add(new OffsetProcessor(5)); - $result = iterator_to_array($pipeline->process(flow_context(config()))); + $segments = new Segments(from_rows(rows(schema()))); + $segments->add(new OffsetProcessor(5)); + $result = iterator_to_array(ExecutedSegments::of($segments, flow_context(config()))); static::assertCount(0, $result); } public function test_process_with_multiple_batches_offset_skips_entire_batches(): void { - $pipeline = new Pipeline(new class implements Extractor { + $segments = new Segments(new class implements Extractor { public function withSchema(Schema $schema): static { return $this; @@ -93,22 +94,22 @@ public function schema(): Schema return new Schema(); } - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { yield rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])); yield rows(schema(int_schema('id')), row(['id' => 3]), row(['id' => 4])); yield rows(schema(int_schema('id')), row(['id' => 5]), row(['id' => 6])); } }); - $pipeline->add(new OffsetProcessor(4)); - $result = iterator_to_array($pipeline->process(flow_context(config()))); + $segments->add(new OffsetProcessor(4)); + $result = iterator_to_array(ExecutedSegments::of($segments, flow_context(config()))); static::assertCount(1, $result); static::assertEquals(rows(schema(int_schema('id')), row(['id' => 5]), row(['id' => 6])), $result[0]); } public function test_process_with_multiple_batches_offset_spanning_batches(): void { - $pipeline = new Pipeline(new class implements Extractor { + $segments = new Segments(new class implements Extractor { public function withSchema(Schema $schema): static { return $this; @@ -119,15 +120,15 @@ public function schema(): Schema return new Schema(); } - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { yield rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])); yield rows(schema(int_schema('id')), row(['id' => 3]), row(['id' => 4]), row(['id' => 5])); yield rows(schema(int_schema('id')), row(['id' => 6])); } }); - $pipeline->add(new OffsetProcessor(3)); - $result = iterator_to_array($pipeline->process(flow_context(config()))); + $segments->add(new OffsetProcessor(3)); + $result = iterator_to_array(ExecutedSegments::of($segments, flow_context(config()))); static::assertCount(2, $result); static::assertEquals(rows(schema(int_schema('id')), row(['id' => 4]), row(['id' => 5])), $result[0]); static::assertEquals(rows(schema(int_schema('id')), row(['id' => 6])), $result[1]); @@ -135,7 +136,7 @@ public function extract(FlowContext $context): Generator public function test_process_with_multiple_batches_offset_within_first_batch(): void { - $pipeline = new Pipeline(new class implements Extractor { + $segments = new Segments(new class implements Extractor { public function withSchema(Schema $schema): static { return $this; @@ -146,14 +147,14 @@ public function schema(): Schema return new Schema(); } - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { yield rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])); yield rows(schema(int_schema('id')), row(['id' => 4]), row(['id' => 5])); } }); - $pipeline->add(new OffsetProcessor(1)); - $result = iterator_to_array($pipeline->process(flow_context(config()))); + $segments->add(new OffsetProcessor(1)); + $result = iterator_to_array(ExecutedSegments::of($segments, flow_context(config()))); static::assertCount(2, $result); static::assertEquals(rows(schema(int_schema('id')), row(['id' => 2]), row(['id' => 3])), $result[0]); static::assertEquals(rows(schema(int_schema('id')), row(['id' => 4]), row(['id' => 5])), $result[1]); @@ -161,28 +162,28 @@ public function extract(FlowContext $context): Generator public function test_process_with_offset_equal_to_batch_size(): void { - $pipeline = new Pipeline(from_rows(rows( + $segments = new Segments(from_rows(rows( schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3]), ))); - $pipeline->add(new OffsetProcessor(3)); - $result = iterator_to_array($pipeline->process(flow_context(config()))); + $segments->add(new OffsetProcessor(3)); + $result = iterator_to_array(ExecutedSegments::of($segments, flow_context(config()))); static::assertCount(0, $result); } public function test_process_with_offset_larger_than_batch_size(): void { - $pipeline = new Pipeline(from_rows(rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])))); - $pipeline->add(new OffsetProcessor(5)); - $result = iterator_to_array($pipeline->process(flow_context(config()))); + $segments = new Segments(from_rows(rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])))); + $segments->add(new OffsetProcessor(5)); + $result = iterator_to_array(ExecutedSegments::of($segments, flow_context(config()))); static::assertCount(0, $result); } public function test_process_with_offset_resulting_in_empty_batch(): void { - $pipeline = new Pipeline(new class implements Extractor { + $segments = new Segments(new class implements Extractor { public function withSchema(Schema $schema): static { return $this; @@ -193,22 +194,22 @@ public function schema(): Schema return new Schema(); } - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { yield rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])); yield rows(schema()); yield rows(schema(int_schema('id')), row(['id' => 3])); } }); - $pipeline->add(new OffsetProcessor(2)); - $result = iterator_to_array($pipeline->process(flow_context(config()))); + $segments->add(new OffsetProcessor(2)); + $result = iterator_to_array(ExecutedSegments::of($segments, flow_context(config()))); static::assertCount(1, $result); static::assertEquals(rows(schema(int_schema('id')), row(['id' => 3])), $result[0]); } public function test_process_with_offset_smaller_than_batch_size(): void { - $pipeline = new Pipeline(from_rows(rows( + $segments = new Segments(from_rows(rows( schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), @@ -216,8 +217,8 @@ public function test_process_with_offset_smaller_than_batch_size(): void row(['id' => 4]), row(['id' => 5]), ))); - $pipeline->add(new OffsetProcessor(2)); - $result = iterator_to_array($pipeline->process(flow_context(config()))); + $segments->add(new OffsetProcessor(2)); + $result = iterator_to_array(ExecutedSegments::of($segments, flow_context(config()))); static::assertCount(1, $result); static::assertCount(3, $result[0]); static::assertEquals( @@ -228,16 +229,16 @@ public function test_process_with_offset_smaller_than_batch_size(): void public function test_process_with_transformer_before_offset(): void { - $pipeline = new Pipeline(from_rows(rows( + $segments = new Segments(from_rows(rows( schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3]), row(['id' => 4]), ))); - $pipeline->add(new ScalarFunctionTransformer('doubled', ref('id')->multiply(lit(2)))); - $pipeline->add(new OffsetProcessor(1)); - $result = iterator_to_array($pipeline->process(flow_context(config()))); + $segments->add(new ScalarFunctionTransformer('doubled', ref('id')->multiply(lit(2)))); + $segments->add(new OffsetProcessor(1)); + $result = iterator_to_array(ExecutedSegments::of($segments, flow_context(config()))); static::assertCount(1, $result); static::assertCount(3, $result[0]); $rows = $result[0]; @@ -254,9 +255,9 @@ public function test_process_with_various_offset_values(int $offset): void for ($i = 1; $i <= 20; $i++) { $rowsData[] = row(['id' => $i]); } - $pipeline = new Pipeline(from_rows(rows(schema(int_schema('id')), ...$rowsData))); - $pipeline->add(new OffsetProcessor($offset >= 0 ? $offset : 0)); - $result = iterator_to_array($pipeline->process(flow_context(config()))); + $segments = new Segments(from_rows(rows(schema(int_schema('id')), ...$rowsData))); + $segments->add(new OffsetProcessor($offset >= 0 ? $offset : 0)); + $result = iterator_to_array(ExecutedSegments::of($segments, flow_context(config()))); $expectedCount = max(0, 20 - $offset); $totalRows = array_sum(array_map(static fn($batch) => $batch->count(), $result)); static::assertEquals($expectedCount, $totalRows); @@ -268,14 +269,14 @@ public function test_process_with_various_offset_values(int $offset): void public function test_process_with_zero_offset_returns_all_data(): void { - $pipeline = new Pipeline(from_rows(rows( + $segments = new Segments(from_rows(rows( schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3]), ))); - $pipeline->add(new OffsetProcessor(0)); - $result = iterator_to_array($pipeline->process(flow_context(config()))); + $segments->add(new OffsetProcessor(0)); + $result = iterator_to_array(ExecutedSegments::of($segments, flow_context(config()))); static::assertCount(1, $result); static::assertCount(3, $result[0]); static::assertEquals( diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/PipelineTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/PipelineTest.php new file mode 100644 index 0000000000..2a913c2d1a --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/PipelineTest.php @@ -0,0 +1,43 @@ + 1]])), $context); + $filter = new RejectingFilter(); + + $pipeline = new Pipeline(1, $segments, $context, $input, 3, $filter); + + static::assertSame(1, $pipeline->id); + static::assertSame($segments, $pipeline->segments()); + static::assertSame($context, $pipeline->context()); + static::assertSame($input, $pipeline->input()); + static::assertSame(3, $pipeline->limit()); + static::assertSame($filter, $pipeline->pathFilter()); + } + + public function test_a_leaf_pipeline_defaults_to_no_input_no_limit_and_only_files(): void + { + $pipeline = new Pipeline(0, new Segments(from_array([['id' => 1]])), NodeMother::context()); + + static::assertNull($pipeline->input()); + static::assertNull($pipeline->limit()); + static::assertInstanceOf(OnlyFiles::class, $pipeline->pathFilter()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/RawTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/RawTest.php new file mode 100644 index 0000000000..a85bc96863 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/RawTest.php @@ -0,0 +1,55 @@ + 1]])), NodeMother::context()); + $why = DataDependentSchemaException::step('JoinEachRowsTransformer', 'x'); + + $plan = new Raw($root, $why); + + static::assertSame($root, $plan->root()); + static::assertSame($why, $plan->why); + } + + public function test_schema_throws_the_refusal_when_the_returned_rows_are_not_described(): void + { + $why = DataDependentSchemaException::step('JoinEachRowsTransformer', 'x'); + $plan = new Raw(new Pipeline(0, new Segments(from_array([['id' => 1]])), NodeMother::context()), $why); + + try { + $plan->schema(); + + static::fail('Expected the refusal to be thrown.'); + } catch (DataDependentSchemaException $e) { + static::assertSame($why, $e); + } + } + + public function test_schema_is_the_returned_rows_schema_when_the_refusal_came_from_elsewhere(): void + { + $plan = new Raw( + new Pipeline(0, new Segments(from_array([['id' => 1]])), NodeMother::context()), + DataDependentSchemaException::step('JoinEachRowsTransformer', 'x'), + schema(int_schema('id')), + ); + + static::assertEquals(schema(int_schema('id')), $plan->schema()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Pipeline/SegmentTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/SegmentTest.php similarity index 93% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Pipeline/SegmentTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/SegmentTest.php index 8bce71bd99..92769acf09 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Pipeline/SegmentTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/SegmentTest.php @@ -2,14 +2,15 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Pipeline; +namespace Flow\ETL\Tests\Unit\Executor; use Flow\ETL\ErrorHandler\ExtractionError; use Flow\ETL\ErrorHandler\LoadingError; use Flow\ETL\ErrorHandler\SkipRows; use Flow\ETL\ErrorHandler\ThrowError; use Flow\ETL\ErrorHandler\TransformationError; -use Flow\ETL\Pipeline\Segment; +use Flow\ETL\Executor\Segment; +use Flow\ETL\Processor\BatchingProcessor; use Flow\ETL\Rows; use Flow\ETL\Tests\Context\MemoryTelemetryContext; use Flow\ETL\Tests\Double\CountingExtractor; @@ -230,4 +231,16 @@ public function test_a_propagated_extraction_error_is_logged(): void static::assertInstanceOf(RuntimeException::class, $thrown); static::assertCount(1, $telemetry->logs->entriesContaining('Error during extraction.')); } + + public function test_extractor_returns_the_extractor_it_was_constructed_with(): void + { + $extractor = new CountingExtractor(schema(int_schema('id'))); + + static::assertSame($extractor, (new Segment(extractor: $extractor))->extractor()); + } + + public function test_extractor_is_null_behind_a_processor(): void + { + static::assertNull((new Segment(new BatchingProcessor(10)))->extractor()); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/SegmentsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/SegmentsTest.php new file mode 100644 index 0000000000..7d2b574126 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/SegmentsTest.php @@ -0,0 +1,199 @@ +add($loader); + + static::assertCount(1, $segments->all()); + static::assertSame([$loader], $segments->all()[0]->steps()); + } + + public function test_add_multiple_transformers_and_loaders_go_into_the_only_segment(): void + { + $segments = new Segments(); + $transformer1 = new SpyTransformer(); + $transformer2 = new SpyTransformer(); + $loader = new SpyLoader(); + + $segments->add($transformer1); + $segments->add($transformer2); + $segments->add($loader); + + static::assertCount(1, $segments->all()); + static::assertSame([$transformer1, $transformer2, $loader], $segments->all()[0]->steps()); + } + + public function test_add_processor_creates_new_segment(): void + { + $segments = new Segments(); + $transformer = new SpyTransformer(); + $processor = new PassThroughProcessor(); + + $segments->add($transformer); + $segments->add($processor); + + $allSegments = $segments->all(); + + static::assertCount(2, $allSegments); + static::assertSame([$transformer], $allSegments[0]->steps()); + static::assertSame($processor, $allSegments[0]->processor()); + static::assertSame([], $allSegments[1]->steps()); + static::assertNull($allSegments[1]->processor()); + } + + public function test_add_processor_with_empty_steps_creates_segment_with_processor(): void + { + $segments = new Segments(); + $processor = new PassThroughProcessor(); + + $segments->add($processor); + + $allSegments = $segments->all(); + + static::assertCount(2, $allSegments); + static::assertSame([], $allSegments[0]->steps()); + static::assertSame($processor, $allSegments[0]->processor()); + } + + public function test_add_transformer_goes_into_the_only_segment(): void + { + $segments = new Segments(); + $transformer = new SpyTransformer(); + + $segments->add($transformer); + + static::assertCount(1, $segments->all()); + static::assertSame([$transformer], $segments->all()[0]->steps()); + } + + public function test_all_returns_all_segments_including_current(): void + { + $segments = new Segments(); + $transformer1 = new SpyTransformer(); + $processor = new PassThroughProcessor(); + $transformer2 = new SpyTransformer(); + + $segments->add($transformer1); + $segments->add($processor); + $segments->add($transformer2); + + $allSegments = $segments->all(); + + static::assertCount(2, $allSegments); + static::assertSame([$transformer1], $allSegments[0]->steps()); + static::assertSame($processor, $allSegments[0]->processor()); + static::assertSame([$transformer2], $allSegments[1]->steps()); + static::assertNull($allSegments[1]->processor()); + } + + public function test_multiple_processors_create_multiple_segments(): void + { + $segments = new Segments(); + $transformer1 = new SpyTransformer(); + $processor1 = new PassThroughProcessor(); + $transformer2 = new SpyTransformer(); + $processor2 = new PassThroughProcessor(); + $loader = new SpyLoader(); + + $segments->add($transformer1); + $segments->add($processor1); + $segments->add($transformer2); + $segments->add($processor2); + $segments->add($loader); + + $allSegments = $segments->all(); + + static::assertCount(3, $allSegments); + static::assertSame([$transformer1], $allSegments[0]->steps()); + static::assertSame($processor1, $allSegments[0]->processor()); + static::assertSame([$transformer2], $allSegments[1]->steps()); + static::assertSame($processor2, $allSegments[1]->processor()); + static::assertSame([$loader], $allSegments[2]->steps()); + static::assertNull($allSegments[2]->processor()); + } + + public function test_new_segments_has_one_empty_segment(): void + { + $segments = new Segments(); + + static::assertCount(1, $segments->all()); + static::assertSame([], $segments->all()[0]->steps()); + } + + public function test_extractor_returns_the_extractor_of_the_first_segment(): void + { + $extractor = from_rows(rows(schema())); + $segments = new Segments($extractor); + + $segments->add(new BatchingProcessor(10)); + $segments->add(new SpyTransformer()); + + static::assertSame($extractor, $segments->extractor()); + } + + public function test_extractor_is_null_when_the_segments_were_built_without_one(): void + { + static::assertNull((new Segments())->extractor()); + } + + public function test_steps_are_flattened_with_each_processor_after_its_segment(): void + { + $segments = new Segments(); + $transformer1 = new SpyTransformer(); + $loader1 = new SpyLoader(); + $processor = new PassThroughProcessor(); + $transformer2 = new SpyTransformer(); + $loader2 = new SpyLoader(); + + $segments->add($transformer1); + $segments->add($loader1); + $segments->add($processor); + $segments->add($transformer2); + $segments->add($loader2); + + static::assertSame( + [$transformer1, $loader1, $processor, $transformer2, $loader2], + PipelineSteps::of($segments), + ); + } + + public function test_a_new_segments_has_no_steps(): void + { + $segments = new Segments(); + + static::assertSame([], PipelineSteps::of($segments)); + } + + public function test_without_a_processor_every_step_stays_in_one_segment(): void + { + $segments = new Segments(); + $transformer = new SpyTransformer(); + $loader = new SpyLoader(); + + $segments->add($transformer); + $segments->add($loader); + + static::assertSame([$transformer, $loader], PipelineSteps::of($segments)); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/SinkFeedTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/SinkFeedTest.php new file mode 100644 index 0000000000..d3aea79d81 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/SinkFeedTest.php @@ -0,0 +1,230 @@ +withErrorHandler($offers), $first, $second), + new Executor(), + ), + $offers, + $first, + $second, + ); + + $sinkFeed->closure(NodeMother::context()); + $sinkFeed->discard(NodeMother::context()); + + static::assertSame(['closure', 'discard'], $first->log); + static::assertSame(['closure', 'discard'], $second->log); + } + + public function test_a_feed_without_consumers_is_refused(): void + { + $feed = SinkFeedMother::feed(); + $offers = new SinkOffers(new ThrowError()); + + $this->expectExceptionObject(new InvalidArgumentException('At least one consumer must be provided')); + + new SinkFeed( + $feed, + new SinkRun(SinkFeedMother::pipeline($feed, NodeMother::context()), new Executor()), + $offers, + ); + } + + public function test_a_batch_is_loaded_in_the_same_resume_that_fed_it(): void + { + $loader = new RecordingLoader(); + + SinkFeedMother::sinkFeed(new SinkOffers(new ThrowError()), $loader)->load( + SinkFeedMother::batch(), + NodeMother::context(), + ); + + static::assertSame(['load#1(1)'], $loader->log); + } + + public function test_closure_drains_and_closes_the_side_loader(): void + { + $loader = new RecordingLoader(); + $sinkFeed = SinkFeedMother::sinkFeed(new SinkOffers(new ThrowError()), $loader); + + $sinkFeed->load(SinkFeedMother::batch(), NodeMother::context()); + $sinkFeed->closure(NodeMother::context()); + + static::assertSame(['load#1(1)', 'closure'], $loader->log); + } + + public function test_closure_on_a_never_started_run_still_closes(): void + { + $loader = new RecordingLoader(); + + SinkFeedMother::sinkFeed(new SinkOffers(new ThrowError()), $loader)->closure(NodeMother::context()); + + static::assertSame(['closure'], $loader->log); + } + + public function test_discard_never_drains(): void + { + $loader = new RecordingLoader(); + + SinkFeedMother::sinkFeed(new SinkOffers(new ThrowError()), $loader)->discard(NodeMother::context()); + + static::assertSame(['discard'], $loader->log); + static::assertSame(0, $loader->loadsCount); + } + + public function test_a_failure_the_side_pipeline_offered_arrives_as_side_root_failure(): void + { + $boom = new RuntimeException('boom'); + + try { + SinkFeedMother::sinkFeed(new SinkOffers(new ThrowError()), new RecordingLoader($boom))->load( + SinkFeedMother::batch(), + NodeMother::context(), + ); + static::fail('load() must surface the offered failure'); + } catch (SinkFailure $failure) { + static::assertSame($boom, $failure->cause); + } + } + + public function test_an_ending_failure_during_load_arrives_raw(): void + { + $drain = new DomainException('drain-boom'); + $loader = new RecordingLoader(closureFailure: $drain); + $sinkFeed = SinkFeedMother::sinkFeed(new SinkOffers(new ThrowError()), $loader, new LimitTransformer(2)); + $sinkFeed->load(SinkFeedMother::batch(1), NodeMother::context()); + + try { + $sinkFeed->load(SinkFeedMother::batch(2), NodeMother::context()); + static::fail('the second load() completes the side root and must surface its closure failure'); + } catch (DomainException $failure) { + static::assertSame($drain, $failure); + } + + static::assertSame(['load#1(1)', 'load#2(1)', 'closure THROW', 'discard'], $loader->log); + } + + public function test_closure_rethrows_the_users_class(): void + { + $drain = new RuntimeException('drain-boom'); + $sinkFeed = SinkFeedMother::sinkFeed( + new SinkOffers(new ThrowError()), + new RecordingLoader(closureFailure: $drain), + ); + $sinkFeed->load(SinkFeedMother::batch(), NodeMother::context()); + + $this->expectExceptionObject($drain); + + $sinkFeed->closure(NodeMother::context()); + } + + public function test_discard_after_a_terminated_and_dropped_failed_run_does_not_discard_again(): void + { + $loader = new RecordingLoader(new RuntimeException('boom'), 2); + $sinkFeed = SinkFeedMother::sinkFeed(new SinkOffers(new ThrowError()), $loader); + $sinkFeed->load(SinkFeedMother::batch(1), NodeMother::context()); + + try { + $sinkFeed->load(SinkFeedMother::batch(2), NodeMother::context()); + } catch (SinkFailure) { + $sinkFeed->restart(); + } + + $sinkFeed->discard(NodeMother::context()); + + static::assertSame(['load#1(1)', 'load#2 THROW', 'discard'], $loader->log); + } + + public function test_discard_after_a_completed_run_reaches_the_loader(): void + { + $loader = new RecordingLoader(); + $sinkFeed = SinkFeedMother::sinkFeed(new SinkOffers(new ThrowError()), $loader); + + $sinkFeed->closure(NodeMother::context()); + $sinkFeed->discard(NodeMother::context()); + + static::assertSame(['closure', 'discard'], $loader->log); + } + + public function test_discard_after_a_completed_run_skips_a_loader_that_cannot_discard(): void + { + $loader = new SpyLoader(); + $sinkFeed = SinkFeedMother::sinkFeed(new SinkOffers(new ThrowError()), $loader); + + $sinkFeed->closure(NodeMother::context()); + $sinkFeed->discard(NodeMother::context()); + + static::assertSame(1, $loader->closureCount); + } + + public function test_drop_runs_even_when_advance_throws(): void + { + $feed = SinkFeedMother::feed(); + $offers = new SinkOffers(new ThrowError()); + $drain = new RuntimeException('drain-boom'); + $loader = new RecordingLoader(closureFailure: $drain); + $run = new SinkRun( + SinkFeedMother::pipeline($feed, NodeMother::context()->withErrorHandler($offers), $loader), + new Executor(), + ); + $sinkFeed = new SinkFeed($feed, $run, $offers, $loader); + + try { + $sinkFeed->closure(NodeMother::context()); + } catch (RuntimeException $failure) { + static::assertSame($drain, $failure); + } + + static::assertTrue($run->terminated()); + static::assertFalse($run->completed()); + + // the failed fiber was dropped, so the next advance() runs a fresh one over the same pipeline + try { + $run->advance(); + } catch (RuntimeException $failure) { + static::assertSame($drain, $failure); + } + + static::assertSame(['closure THROW', 'discard', 'closure THROW', 'discard'], $loader->log); + } + + public function test_the_loader_sees_the_context_the_plan_gave_the_side_pipeline(): void + { + $offers = new SinkOffers(new ThrowError()); + $loader = new RecordingLoader(); + + SinkFeedMother::sinkFeed($offers, $loader)->load(SinkFeedMother::batch(), NodeMother::context()); + + static::assertSame([$offers], $loader->handlers); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/SinkOffersTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/SinkOffersTest.php new file mode 100644 index 0000000000..2560d7f346 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/SinkOffersTest.php @@ -0,0 +1,87 @@ +offered(new RuntimeException('boom'))); + } + + public function test_an_extraction_failure_is_recorded_and_the_handler_decides(): void + { + $offers = new SinkOffers(new IgnoreError()); + $cause = new RuntimeException('boom'); + + static::assertSame( + ExtractionAction::endSource, + $offers->onExtraction(new ExtractionError($cause, from_array([['id' => 1]]))), + ); + static::assertTrue($offers->offered($cause)); + } + + public function test_a_transformation_failure_is_recorded_and_the_handler_decides(): void + { + $offers = new SinkOffers(new IgnoreError()); + $cause = new RuntimeException('boom'); + + static::assertSame( + TransformationAction::skipBatch, + $offers->onTransformation(new TransformationError($cause, new SpyTransformer(), SinkFeedMother::batch())), + ); + static::assertTrue($offers->offered($cause)); + } + + public function test_a_loading_failure_is_recorded_and_the_handler_decides(): void + { + $offers = new SinkOffers(new IgnoreError()); + $cause = new RuntimeException('boom'); + + static::assertSame( + LoadingAction::skipLoader, + $offers->onLoading(new LoadingError($cause, to_memory(new ArrayMemory()), SinkFeedMother::batch())), + ); + static::assertTrue($offers->offered($cause)); + } + + public function test_offered_compares_by_identity(): void + { + $offers = new SinkOffers(new IgnoreError()); + $offers->onLoading( + new LoadingError(new RuntimeException('boom'), to_memory(new ArrayMemory()), SinkFeedMother::batch()), + ); + + static::assertFalse($offers->offered(new RuntimeException('boom'))); + } + + public function test_forget_clears_the_last_offer(): void + { + $offers = new SinkOffers(new IgnoreError()); + $cause = new RuntimeException('boom'); + $offers->onLoading(new LoadingError($cause, to_memory(new ArrayMemory()), SinkFeedMother::batch())); + + $offers->forget(); + + static::assertFalse($offers->offered($cause)); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/SinkRunTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/SinkRunTest.php new file mode 100644 index 0000000000..99ef7786d4 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/SinkRunTest.php @@ -0,0 +1,142 @@ +terminated()); + static::assertFalse($run->completed()); + } + + public function test_advance_starts_a_never_started_run(): void + { + $feed = SinkFeedMother::feed(); + $loader = new RecordingLoader(); + $run = new SinkRun(SinkFeedMother::pipeline($feed, NodeMother::context(), $loader), new Executor()); + + $feed->feed(SinkFeedMother::batch()); + $run->advance(); + + static::assertSame(['load#1(1)'], $loader->log); + static::assertFalse($run->terminated()); + } + + public function test_advance_on_a_terminated_run_is_a_no_op(): void + { + $feed = SinkFeedMother::feed(); + $loader = new RecordingLoader(); + $run = new SinkRun(SinkFeedMother::pipeline($feed, NodeMother::context(), $loader), new Executor()); + + $feed->finish(); + $run->advance(); + $run->advance(); + + static::assertSame(['closure'], $loader->log); + static::assertTrue($run->terminated()); + static::assertTrue($run->completed()); + } + + public function test_drop_unwinds_a_suspended_fiber_promptly(): void + { + $feed = SinkFeedMother::feed(); + $loader = new RecordingLoader(); + $run = new SinkRun(SinkFeedMother::pipeline($feed, NodeMother::context(), $loader), new Executor()); + $feed->feed(SinkFeedMother::batch()); + $run->advance(); + + $run->drop(); + + static::assertSame(['load#1(1)', 'discard'], $loader->log); + } + + public function test_a_dropped_terminated_run_stays_terminated_and_completed(): void + { + $feed = SinkFeedMother::feed(); + $run = new SinkRun( + SinkFeedMother::pipeline($feed, NodeMother::context(), new RecordingLoader()), + new Executor(), + ); + $feed->finish(); + $run->advance(); + + $run->drop(); + + static::assertTrue($run->terminated()); + static::assertTrue($run->completed()); + } + + public function test_a_run_whose_advance_threw_is_terminated_but_not_completed(): void + { + $feed = SinkFeedMother::feed(); + $boom = new RuntimeException('boom'); + $run = new SinkRun( + SinkFeedMother::pipeline($feed, NodeMother::context(), new RecordingLoader($boom)), + new Executor(), + ); + $feed->feed(SinkFeedMother::batch()); + + try { + $run->advance(); + static::fail('advance() must rethrow the sink pipeline failure'); + } catch (RuntimeException $failure) { + static::assertSame($boom, $failure); + } + + static::assertTrue($run->terminated()); + static::assertFalse($run->completed()); + + $run->drop(); + + static::assertTrue($run->terminated()); + static::assertFalse($run->completed()); + } + + public function test_the_next_advance_after_drop_runs_a_fresh_fiber_over_the_same_pipeline(): void + { + $feed = SinkFeedMother::feed(); + $transformer = new SpyTransformer(); + $loader = new RecordingLoader(new RuntimeException('boom'), 2); + $run = new SinkRun( + SinkFeedMother::pipeline($feed, NodeMother::context(), $transformer, $loader), + new Executor(), + ); + + $feed->feed(SinkFeedMother::batch(1)); + $run->advance(); + $feed->feed(SinkFeedMother::batch(2)); + + try { + $run->advance(); + } catch (RuntimeException) { + $run->drop(); + } + + $feed->feed(SinkFeedMother::batch(3)); + $run->advance(); + $feed->feed(SinkFeedMother::batch(4)); + $run->advance(); + $feed->finish(); + $run->advance(); + + static::assertSame(['load#1(1)', 'load#2 THROW', 'discard', 'load#3(1)', 'load#4(1)', 'closure'], $loader->log); + static::assertSame(4, $transformer->seen); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Execution/StatisticsCollectorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/StatisticsCollectorTest.php similarity index 77% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Execution/StatisticsCollectorTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/StatisticsCollectorTest.php index 6766a7a4f2..684fdc62a3 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Execution/StatisticsCollectorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/StatisticsCollectorTest.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Execution; +namespace Flow\ETL\Tests\Unit\Executor; use DateTimeImmutable; use Flow\Clock\FakeClock; @@ -10,7 +10,7 @@ use Flow\ETL\Dataset\Report; use Flow\ETL\Dataset\Statistics\Columns; use Flow\ETL\Dataset\Statistics\HighResolutionTime; -use Flow\ETL\Execution\StatisticsCollector; +use Flow\ETL\Executor\StatisticsCollector; use Flow\ETL\Tests\FlowTestCase; use function Flow\ETL\DSL\analyze; @@ -25,8 +25,7 @@ final class StatisticsCollectorTest extends FlowTestCase { public function test_capture_collects_column_statistics_when_enabled(): void { - $context = flow_context(); - $collector = new StatisticsCollector(analyze()->withColumnStatistics(), $context); + $collector = new StatisticsCollector(analyze()->withColumnStatistics(), flow_context()); $collector->capture(rows( schema(int_schema('id'), str_schema('name')), @@ -34,7 +33,6 @@ public function test_capture_collects_column_statistics_when_enabled(): void row(['id' => 2, 'name' => 'Bob']), )); - $collector->end(); $report = $collector->report(); static::assertNotNull($report); @@ -46,12 +44,10 @@ public function test_capture_collects_column_statistics_when_enabled(): void public function test_capture_collects_schema_when_enabled(): void { - $context = flow_context(); - $collector = new StatisticsCollector(analyze()->withSchema(), $context); + $collector = new StatisticsCollector(analyze()->withSchema(), flow_context()); $collector->capture(rows(schema(int_schema('id'), str_schema('name')), row(['id' => 1, 'name' => 'Alice']))); - $collector->end(); $report = $collector->report(); static::assertNotNull($report); @@ -64,13 +60,11 @@ public function test_capture_collects_schema_when_enabled(): void public function test_capture_increments_row_count_correctly(): void { - $context = flow_context(); - $collector = new StatisticsCollector(true, $context); + $collector = new StatisticsCollector(true, flow_context()); $collector->capture(rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]))); $collector->capture(rows(schema(int_schema('id')), row(['id' => 3]))); - $collector->end(); $report = $collector->report(); static::assertNotNull($report); @@ -79,23 +73,19 @@ public function test_capture_increments_row_count_correctly(): void public function test_capture_is_noop_when_analyze_is_false(): void { - $context = flow_context(); - $collector = new StatisticsCollector(false, $context); + $collector = new StatisticsCollector(false, flow_context()); $collector->capture(rows(schema(int_schema('id')), row(['id' => 1]))); - $collector->end(); static::assertNull($collector->report()); } public function test_column_statistics_is_null_when_not_enabled(): void { - $context = flow_context(); - $collector = new StatisticsCollector(analyze(), $context); + $collector = new StatisticsCollector(analyze(), flow_context()); $collector->capture(rows(schema(int_schema('id')), row(['id' => 1]))); - $collector->end(); $report = $collector->report(); static::assertNotNull($report); @@ -104,36 +94,28 @@ public function test_column_statistics_is_null_when_not_enabled(): void public function test_report_returns_null_when_analyze_is_false(): void { - $context = flow_context(); - $collector = new StatisticsCollector(false, $context); - $collector->end(); + $collector = new StatisticsCollector(false, flow_context()); static::assertNull($collector->report()); } public function test_report_returns_null_when_analyze_is_null(): void { - $context = flow_context(); - $collector = new StatisticsCollector(null, $context); - $collector->end(); + $collector = new StatisticsCollector(null, flow_context()); static::assertNull($collector->report()); } public function test_report_returns_report_when_analyze_is_true(): void { - $context = flow_context(); - $collector = new StatisticsCollector(true, $context); - $collector->end(); + $collector = new StatisticsCollector(true, flow_context()); static::assertInstanceOf(Report::class, $collector->report()); } public function test_report_returns_report_when_using_analyze_instance(): void { - $context = flow_context(); - $collector = new StatisticsCollector(analyze(), $context); - $collector->end(); + $collector = new StatisticsCollector(analyze(), flow_context()); static::assertInstanceOf(Report::class, $collector->report()); } @@ -151,7 +133,6 @@ public function test_report_returns_report_with_correct_execution_time(): void $collector->capture(rows(schema(int_schema('id')), row(['id' => 1]))); $clock->modify('+5 minutes'); - $collector->end(); $report = $collector->report(); static::assertNotNull($report); @@ -168,12 +149,10 @@ public function test_report_returns_report_with_correct_execution_time(): void public function test_report_returns_report_with_high_resolution_time(): void { - $context = flow_context(); - $collector = new StatisticsCollector(true, $context); + $collector = new StatisticsCollector(true, flow_context()); $collector->capture(rows(schema(int_schema('id')), row(['id' => 1]))); - $collector->end(); $report = $collector->report(); static::assertNotNull($report); @@ -182,12 +161,10 @@ public function test_report_returns_report_with_high_resolution_time(): void public function test_report_returns_report_with_memory_consumption(): void { - $context = flow_context(); - $collector = new StatisticsCollector(true, $context); + $collector = new StatisticsCollector(true, flow_context()); $collector->capture(rows(schema(int_schema('id')), row(['id' => 1]))); - $collector->end(); $report = $collector->report(); static::assertNotNull($report); @@ -196,12 +173,10 @@ public function test_report_returns_report_with_memory_consumption(): void public function test_schema_is_null_when_not_enabled(): void { - $context = flow_context(); - $collector = new StatisticsCollector(analyze(), $context); + $collector = new StatisticsCollector(analyze(), flow_context()); $collector->capture(rows(schema(int_schema('id')), row(['id' => 1]))); - $collector->end(); $report = $collector->report(); static::assertNotNull($report); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/TransactionRollbackTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/TransactionRollbackTest.php new file mode 100644 index 0000000000..88f3451ccf --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/TransactionRollbackTest.php @@ -0,0 +1,38 @@ +rollback($cause, $telemetry->flowContext); + + static::assertSame(['rollback'], $transaction->log); + static::assertSame([$cause], $transaction->rolledBackFor); + static::assertCount(0, $telemetry->logs->entriesContaining('Transaction failed to roll back.')); + } + + public function test_a_rollback_failure_is_logged_not_thrown(): void + { + $telemetry = new MemoryTelemetryContext(); + $transaction = new RecordingTransaction(rollbackFailure: new RuntimeException('rollback failed')); + + (new TransactionRollback($transaction))->rollback(new RuntimeException('boom'), $telemetry->flowContext); + + static::assertSame(['rollback'], $transaction->log); + static::assertCount(1, $telemetry->logs->entriesContaining('Transaction failed to roll back.')); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/TransactionalSinksTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/TransactionalSinksTest.php new file mode 100644 index 0000000000..9937511ddf --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/TransactionalSinksTest.php @@ -0,0 +1,294 @@ +load(SinkFeedMother::batch(1), NodeMother::context()); + $sinks->load(SinkFeedMother::batch(2), NodeMother::context()); + + static::assertSame(['begin', 'commit', 'begin', 'commit'], $transaction->log); + static::assertSame(['load#1(1)', 'load#2(1)'], $bare->log); + static::assertSame(['load#1(1)', 'load#2(1)'], $side->log); + } + + public function test_closure_wraps_every_child_drain_in_one_transaction(): void + { + $transaction = new RecordingTransaction(); + $bare = new RecordingLoader(); + $side = new RecordingLoader(); + $sinks = new TransactionalSinks($transaction, [ + $bare, + SinkFeedMother::sinkFeed(new SinkOffers(new ThrowError()), $side), + ]); + $sinks->load(SinkFeedMother::batch(), NodeMother::context()); + + $sinks->closure(NodeMother::context()); + + static::assertSame(['begin', 'commit', 'begin', 'commit'], $transaction->log); + static::assertSame(['load#1(1)', 'closure'], $bare->log); + static::assertSame(['load#1(1)', 'closure'], $side->log); + } + + public function test_a_child_failure_rolls_back_and_throws_transaction_rolled_back(): void + { + $boom = new RuntimeException('boom'); + $transaction = new RecordingTransaction(); + $failing = SinkFeedMother::sinkFeed(new SinkOffers(new ThrowError()), new RecordingLoader($boom)); + $sinks = new TransactionalSinks($transaction, [new RecordingLoader(), $failing]); + + try { + $sinks->load(SinkFeedMother::batch(), NodeMother::context()); + static::fail('load() must surface the rolled back child failure'); + } catch (TransactionRolledBack $rolledBack) { + static::assertSame($failing, $rolledBack->loader); + static::assertSame($boom, $rolledBack->cause); + } + + static::assertSame(['begin', 'rollback'], $transaction->log); + } + + public function test_a_bare_child_failure_is_reported_against_that_child(): void + { + $boom = new RuntimeException('boom'); + $failing = new RecordingLoader($boom); + + try { + (new TransactionalSinks(new RecordingTransaction(), [$failing]))->load( + SinkFeedMother::batch(), + NodeMother::context(), + ); + static::fail('load() must surface the rolled back child failure'); + } catch (TransactionRolledBack $rolledBack) { + static::assertSame($failing, $rolledBack->loader); + static::assertSame($boom, $rolledBack->cause); + } + } + + public function test_a_rolled_back_child_writes_the_next_batch(): void + { + $transaction = new RecordingTransaction(); + $side = new RecordingLoader(new RuntimeException('boom')); + $sinks = new TransactionalSinks($transaction, [SinkFeedMother::sinkFeed( + new SinkOffers(new ThrowError()), + $side, + )]); + + try { + $sinks->load(SinkFeedMother::batch(1), NodeMother::context()); + } catch (TransactionRolledBack) { + $sinks->load(SinkFeedMother::batch(2), NodeMother::context()); + } + + static::assertSame(['load#1 THROW', 'discard', 'load#2(1)'], $side->log); + static::assertSame(['begin', 'rollback', 'begin', 'commit'], $transaction->log); + } + + public function test_a_restart_keeps_the_child_s_limit_counter(): void + { + $side = new RecordingLoader(new RuntimeException('boom'), 2); + $sinks = new TransactionalSinks(new RecordingTransaction(), [ + SinkFeedMother::sinkFeed(new SinkOffers(new ThrowError()), $side, new LimitTransformer(3)), + ]); + $sinks->load(SinkFeedMother::batch(1), NodeMother::context()); + + try { + $sinks->load(SinkFeedMother::batch(2), NodeMother::context()); + } catch (TransactionRolledBack) { + $sinks->load(SinkFeedMother::batch(3), NodeMother::context()); + $sinks->load(SinkFeedMother::batch(4), NodeMother::context()); + } + + static::assertSame(['load#1(1)', 'load#2 THROW', 'discard', 'load#3(1)', 'closure'], $side->log); + } + + public function test_a_live_sibling_is_not_restarted(): void + { + $live = new RecordingLoader(); + $sinks = new TransactionalSinks(new RecordingTransaction(), [ + SinkFeedMother::sinkFeed(new SinkOffers(new ThrowError()), $live), + SinkFeedMother::sinkFeed( + new SinkOffers(new ThrowError()), + new RecordingLoader(new RuntimeException('boom')), + ), + ]); + + try { + $sinks->load(SinkFeedMother::batch(1), NodeMother::context()); + } catch (TransactionRolledBack) { + $sinks->load(SinkFeedMother::batch(2), NodeMother::context()); + } + + static::assertSame(['load#1(1)', 'load#2(1)'], $live->log); + } + + public function test_a_failing_commit_rolls_the_batch_back(): void + { + $failure = new RuntimeException('commit failed'); + $transaction = new RecordingTransaction(commitFailure: $failure); + + try { + (new TransactionalSinks($transaction, [new RecordingLoader()]))->load( + SinkFeedMother::batch(), + NodeMother::context(), + ); + static::fail('load() must rethrow the commit failure'); + } catch (RuntimeException $thrown) { + static::assertSame($failure, $thrown); + } + + static::assertSame(['begin', 'commit', 'rollback'], $transaction->log); + static::assertSame([$failure], $transaction->rolledBackFor); + } + + public function test_a_failing_commit_rolls_the_drain_back(): void + { + $failure = new RuntimeException('commit failed'); + $transaction = new RecordingTransaction(commitFailure: $failure); + + try { + (new TransactionalSinks($transaction, [new RecordingLoader()]))->closure(NodeMother::context()); + static::fail('closure() must rethrow the commit failure'); + } catch (RuntimeException $thrown) { + static::assertSame($failure, $thrown); + } + + static::assertSame(['begin', 'commit', 'rollback'], $transaction->log); + } + + public function test_a_failing_begin_does_not_roll_back(): void + { + $failure = new RuntimeException('begin failed'); + $transaction = new RecordingTransaction(beginFailure: $failure); + $loader = new RecordingLoader(); + + try { + (new TransactionalSinks($transaction, [$loader]))->load(SinkFeedMother::batch(), NodeMother::context()); + static::fail('load() must rethrow the begin failure'); + } catch (RuntimeException $thrown) { + static::assertSame($failure, $thrown); + } + + static::assertSame(['begin'], $transaction->log); + static::assertSame([], $loader->log); + } + + public function test_a_rollback_failure_is_logged_and_does_not_mask_the_cause(): void + { + $telemetry = new MemoryTelemetryContext(); + $boom = new RuntimeException('boom'); + + try { + (new TransactionalSinks( + new RecordingTransaction(rollbackFailure: new RuntimeException('rollback failed')), + [new RecordingLoader($boom)], + ))->load(SinkFeedMother::batch(), $telemetry->flowContext); + static::fail('load() must surface the child failure'); + } catch (TransactionRolledBack $rolledBack) { + static::assertSame($boom, $rolledBack->cause); + } + + static::assertCount(1, $telemetry->logs->entriesContaining('Transaction failed to roll back.')); + } + + public function test_a_rollback_failure_on_a_failing_batch_commit_is_logged(): void + { + $telemetry = new MemoryTelemetryContext(); + $failure = new RuntimeException('commit failed'); + + try { + (new TransactionalSinks( + new RecordingTransaction( + commitFailure: $failure, + rollbackFailure: new RuntimeException('rollback failed'), + ), + [new RecordingLoader()], + ))->load(SinkFeedMother::batch(), $telemetry->flowContext); + static::fail('load() must rethrow the commit failure'); + } catch (RuntimeException $thrown) { + static::assertSame($failure, $thrown); + } + + static::assertCount(1, $telemetry->logs->entriesContaining('Transaction failed to roll back.')); + } + + public function test_a_rollback_failure_on_a_failing_drain_commit_is_logged(): void + { + $telemetry = new MemoryTelemetryContext(); + $failure = new RuntimeException('commit failed'); + + try { + (new TransactionalSinks( + new RecordingTransaction( + commitFailure: $failure, + rollbackFailure: new RuntimeException('rollback failed'), + ), + [new RecordingLoader()], + ))->closure($telemetry->flowContext); + static::fail('closure() must rethrow the commit failure'); + } catch (RuntimeException $thrown) { + static::assertSame($failure, $thrown); + } + + static::assertCount(1, $telemetry->logs->entriesContaining('Transaction failed to roll back.')); + } + + public function test_a_closure_failure_rethrows_the_users_class(): void + { + $drain = new DomainException('drain-boom'); + $transaction = new RecordingTransaction(); + + try { + (new TransactionalSinks($transaction, [ + SinkFeedMother::sinkFeed(new SinkOffers(new ThrowError()), new RecordingLoader(closureFailure: $drain)), + ]))->closure(NodeMother::context()); + static::fail('closure() must rethrow the drain failure'); + } catch (DomainException $thrown) { + static::assertSame($drain, $thrown); + } + + static::assertSame(['begin', 'rollback'], $transaction->log); + } + + public function test_discard_forwards_to_every_child_without_a_transaction(): void + { + $transaction = new RecordingTransaction(); + $bare = new RecordingLoader(); + $side = new RecordingLoader(); + + (new TransactionalSinks($transaction, [ + $bare, + SinkFeedMother::sinkFeed(new SinkOffers(new ThrowError()), $side), + ]))->discard(NodeMother::context()); + + static::assertSame(['discard'], $bare->log); + static::assertSame(['discard'], $side->log); + static::assertSame([], $transaction->log); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Pipeline/WindowFunctionPipelineTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/WindowFunctionPipelineTest.php similarity index 77% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Pipeline/WindowFunctionPipelineTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/WindowFunctionPipelineTest.php index 97a0c41589..eef87678f6 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Pipeline/WindowFunctionPipelineTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/WindowFunctionPipelineTest.php @@ -2,10 +2,11 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Pipeline; +namespace Flow\ETL\Tests\Unit\Executor; -use Flow\ETL\Pipeline; +use Flow\ETL\Executor\Segments; use Flow\ETL\Processor\WindowProcessor; +use Flow\ETL\Tests\Context\ExecutedSegments; use PHPUnit\Framework\TestCase; use function Flow\ETL\DSL\config; @@ -26,19 +27,19 @@ final class WindowFunctionPipelineTest extends TestCase { public function test_handles_empty_input(): void { - $pipeline = new Pipeline(from_rows(rows(schema(int_schema('id'))))); + $segments = new Segments(from_rows(rows(schema(int_schema('id'))))); $window = window()->orderBy(ref('id')); - $pipeline->add(new WindowProcessor('row_num', row_number()->over($window))); + $segments->add(new WindowProcessor('row_num', row_number()->over($window))); - $result = iterator_to_array($pipeline->process(flow_context(config()))); + $result = iterator_to_array(ExecutedSegments::of($segments, flow_context(config()))); static::assertCount(0, $result); } public function test_handles_no_order_by(): void { - $pipeline = new Pipeline(from_rows(rows( + $segments = new Segments(from_rows(rows( schema(str_schema('dept'), int_schema('value')), row(['dept' => 'IT', 'value' => 100]), row(['dept' => 'IT', 'value' => 150]), @@ -46,10 +47,10 @@ public function test_handles_no_order_by(): void $window = window()->partitionBy(ref('dept')); - $pipeline->add(new WindowProcessor('total', sum(ref('value'))->over($window))); + $segments->add(new WindowProcessor('total', sum(ref('value'))->over($window))); $context = flow_context(config()); - $result = iterator_to_array($pipeline->process($context)); + $result = iterator_to_array(ExecutedSegments::of($segments, $context)); static::assertCount(1, $result); static::assertCount(2, $result[0]); @@ -63,17 +64,17 @@ public function test_handles_single_row_partition(): void // the shuffle is upstream of this processor now, so the test hands it what a shuffle produces: // one Rows per partition key $schema = schema(str_schema('dept'), int_schema('salary')); - $pipeline = new Pipeline(from_rows( + $segments = new Segments(from_rows( rows($schema, row(['dept' => 'IT', 'salary' => 5000])), rows($schema, row(['dept' => 'HR', 'salary' => 4000])), )); $window = window()->partitionBy(ref('dept'))->orderBy(ref('salary')); - $pipeline->add(new WindowProcessor('row_num', row_number()->over($window))); + $segments->add(new WindowProcessor('row_num', row_number()->over($window))); $context = flow_context(config()); - $result = iterator_to_array($pipeline->process($context)); + $result = iterator_to_array(ExecutedSegments::of($segments, $context)); static::assertCount(2, $result); static::assertCount(1, $result[0]); @@ -83,17 +84,17 @@ public function test_handles_single_row_partition(): void public function test_processes_multiple_partitions_separately(): void { $schema = schema(str_schema('dept'), int_schema('salary')); - $pipeline = new Pipeline(from_rows( + $segments = new Segments(from_rows( rows($schema, row(['dept' => 'IT', 'salary' => 5000]), row(['dept' => 'IT', 'salary' => 6000])), rows($schema, row(['dept' => 'HR', 'salary' => 4000]), row(['dept' => 'HR', 'salary' => 4500])), )); $window = window()->partitionBy(ref('dept'))->orderBy(ref('salary')); - $pipeline->add(new WindowProcessor('row_num', row_number()->over($window))); + $segments->add(new WindowProcessor('row_num', row_number()->over($window))); $context = flow_context(config()); - $result = iterator_to_array($pipeline->process($context)); + $result = iterator_to_array(ExecutedSegments::of($segments, $context)); static::assertCount(2, $result); @@ -108,7 +109,7 @@ public function test_processes_multiple_partitions_separately(): void public function test_processes_single_partition_without_partition_by(): void { - $pipeline = new Pipeline(from_rows(rows( + $segments = new Segments(from_rows(rows( schema(int_schema('id'), int_schema('value')), row(['id' => 1, 'value' => 100]), row(['id' => 2, 'value' => 150]), @@ -116,10 +117,10 @@ public function test_processes_single_partition_without_partition_by(): void ))); $window = window()->orderBy(ref('id')); - $pipeline->add(new WindowProcessor('row_num', row_number()->over($window))); + $segments->add(new WindowProcessor('row_num', row_number()->over($window))); $context = flow_context(config()); - $result = iterator_to_array($pipeline->process($context)); + $result = iterator_to_array(ExecutedSegments::of($segments, $context)); static::assertCount(1, $result); static::assertCount(3, $result[0]); @@ -131,7 +132,7 @@ public function test_processes_single_partition_without_partition_by(): void public function test_sorts_partition_by_order_by(): void { - $pipeline = new Pipeline(from_rows(rows( + $segments = new Segments(from_rows(rows( schema(str_schema('dept'), int_schema('salary')), row(['dept' => 'IT', 'salary' => 6000]), row(['dept' => 'IT', 'salary' => 5000]), @@ -140,10 +141,10 @@ public function test_sorts_partition_by_order_by(): void $window = window()->partitionBy(ref('dept'))->orderBy(ref('salary')); - $pipeline->add(new WindowProcessor('row_num', row_number()->over($window))); + $segments->add(new WindowProcessor('row_num', row_number()->over($window))); $context = flow_context(config()); - $result = iterator_to_array($pipeline->process($context)); + $result = iterator_to_array(ExecutedSegments::of($segments, $context)); static::assertEquals(5000, $result[0][0]->get('salary')); static::assertEquals(6000, $result[0][1]->get('salary')); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/ExecutorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/ExecutorTest.php new file mode 100644 index 0000000000..ccdab6b92e --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/ExecutorTest.php @@ -0,0 +1,478 @@ +add(new RenameEntryTransformer('id', 'a')); + $segments->add(new BatchingProcessor(2)); + $segments->add(new RenameEntryTransformer('a', 'b')); + $segments->add($loader = new SpyLoader()); + + $batches = iterator_to_array((new Executor())->executePipeline( + new Pipeline(0, $segments, NodeMother::context()), + )); + + static::assertSame([[['b' => 1], ['b' => 2]], [['b' => 3]]], [$batches[0]->toArray(), $batches[1]->toArray()]); + static::assertSame([2, 1], $loader->loadedRowCounts()); + } + + public function test_an_input_chain_is_flattened_into_one_generator_chain(): void + { + $upstream = new Segments(from_rows(RowsMother::sequentialIds(5))); + $upstream->add(new RenameEntryTransformer('id', 'a')); + $upstream->add(new BatchingProcessor(2)); + $downstream = new Segments(); + $downstream->add(new RenameEntryTransformer('a', 'b')); + $downstream->add(new LimitTransformer(3)); + $context = NodeMother::context(); + + $batches = iterator_to_array((new Executor())->executePipeline( + new Pipeline(1, $downstream, $context, new Pipeline(0, $upstream, $context)), + )); + + static::assertCount(2, $batches); + static::assertSame([['b' => 1], ['b' => 2]], $batches[0]->toArray()); + static::assertSame([['b' => 3]], $batches[1]->toArray()); + } + + public function test_stop_reaches_the_source_across_a_cut(): void + { + $extractor = new CountingExtractor(schema(int_schema('id')), RowsMother::sequentialIds(10)); + $extractor->withBatchSize(1); + $upstream = new Segments($extractor); + $upstream->add($seenUpstream = new SpyLoader()); + $upstream->add(new BatchingProcessor(1)); + $downstream = new Segments(); + $downstream->add(new LimitTransformer(1)); + $context = NodeMother::context(); + + $batches = iterator_to_array((new Executor())->executePipeline( + new Pipeline(1, $downstream, $context, new Pipeline(0, $upstream, $context)), + )); + + static::assertCount(1, $batches); + static::assertSame(1, $extractor->batchesYielded); + static::assertSame(1, $seenUpstream->loadsCount); + } + + public function test_each_stage_runs_under_its_own_flow_context(): void + { + $upstreamContext = NodeMother::context(config()); + $downstreamContext = NodeMother::context(config()); + $upstream = new Segments(from_rows(RowsMother::sequentialIds(1))); + $upstream->add($upstreamLoader = new SpyLoader()); + $upstream->add(new BatchingProcessor(1)); + $downstream = new Segments(); + $downstream->add($downstreamLoader = new SpyLoader()); + + iterator_to_array((new Executor())->executePipeline( + new Pipeline(1, $downstream, $downstreamContext, new Pipeline(0, $upstream, $upstreamContext)), + )); + + static::assertSame([$upstreamContext], $upstreamLoader->contexts); + static::assertSame([$downstreamContext], $downstreamLoader->contexts); + } + + public function test_the_source_is_extracted_under_the_leaf_pipelines_context(): void + { + $leafContext = NodeMother::context(config()); + $extractor = new CountingExtractor(schema(int_schema('id')), RowsMother::sequentialIds(1)); + $upstream = new Segments($extractor); + $upstream->add(new BatchingProcessor(1)); + + iterator_to_array((new Executor())->executePipeline( + new Pipeline(1, new Segments(), NodeMother::context(config()), new Pipeline(0, $upstream, $leafContext)), + )); + + static::assertSame([$leafContext], $extractor->contexts); + } + + public function test_a_pipeline_without_a_source_throws(): void + { + $this->expectException(InvalidLogicException::class); + $this->expectExceptionMessage('pipeline #7 has no source extractor'); + + iterator_to_array((new Executor())->executePipeline(new Pipeline(7, new Segments(), NodeMother::context()))); + } + + public function test_a_file_source_receives_the_pipelines_limit_and_path_filter(): void + { + $extractor = new RecordingFileExtractor(schema(int_schema('id')), RowsMother::sequentialIds(1)); + $filter = new RejectingFilter(); + + iterator_to_array((new Executor())->executePipeline( + new Pipeline(0, new Segments($extractor), NodeMother::context(), limit: 7, pathFilter: $filter), + )); + + static::assertSame([7], $extractor->limits); + static::assertSame([$filter], $extractor->pathFilters); + } + + public function test_a_source_that_lists_no_files_receives_the_pipelines_limit(): void + { + $extractor = new RecordingExtractor(schema(int_schema('id')), RowsMother::sequentialIds(1)); + + iterator_to_array((new Executor())->executePipeline( + new Pipeline(0, new Segments($extractor), NodeMother::context(), limit: 7), + )); + + static::assertSame([7], $extractor->limits); + } + + public function test_a_pipeline_run_opens_no_dataframe_span_for_any_stage(): void + { + $upstream = new MemoryTelemetryContext(); + $own = new MemoryTelemetryContext(); + $segments = new Segments(from_rows(RowsMother::sequentialIds(1))); + $segments->add(new BatchingProcessor(1)); + + iterator_to_array((new Executor())->executePipeline( + new Pipeline(1, new Segments(), $own->flowContext, new Pipeline(0, $segments, $upstream->flowContext)), + )); + + static::assertSame([], $upstream->spans->startedSpans()); + static::assertSame([], $own->spans->startedSpans()); + } + + public function test_execute_runs_the_plans_root_pipeline(): void + { + $segments = new Segments(from_rows(RowsMother::sequentialIds(3))); + $segments->add(new BatchingProcessor(2)); + $segments->add(new RenameEntryTransformer('id', 'b')); + + $batches = iterator_to_array((new Executor())->execute( + new Described(new Pipeline(0, $segments, NodeMother::context()), schema(int_schema('b'))), + )); + + static::assertCount(2, $batches); + static::assertSame([['b' => 1], ['b' => 2]], $batches[0]->toArray()); + } + + public function test_fetch_merges_every_batch_into_one_rows(): void + { + $segments = new Segments(from_rows(RowsMother::sequentialIds(3))); + $segments->add(new BatchingProcessor(1)); + + $rows = (new Executor())->fetch( + new Described(new Pipeline(0, $segments, NodeMother::context()), schema(int_schema('id'))), + ); + + static::assertSame([['id' => 1], ['id' => 2], ['id' => 3]], $rows->toArray()); + } + + public function test_fetch_of_an_empty_pipeline_returns_rows_with_the_output_schema(): void + { + $rows = (new Executor())->fetch( + new Described( + new Pipeline(0, new Segments(from_rows(rows(schema(int_schema('id'))))), NodeMother::context()), + schema(int_schema('id')), + ), + ); + + static::assertSame(0, $rows->count()); + static::assertEquals(schema(int_schema('id')), $rows->schema()); + } + + public function test_fetch_of_an_empty_refused_pipeline_returns_rows_with_an_empty_schema(): void + { + $rows = (new Executor())->fetch( + new Raw( + new Pipeline(0, new Segments(from_rows(rows(schema(int_schema('id'))))), NodeMother::context()), + SchemaNotDerivableException::extractor('x'), + ), + ); + + static::assertSame(0, $rows->count()); + static::assertEquals(schema(), $rows->schema()); + } + + public function test_merge_merges_every_batch_into_one_rows(): void + { + $plan = new Described( + new Pipeline(0, new Segments(from_rows(rows(schema(int_schema('id'))))), NodeMother::context()), + schema(int_schema('id')), + ); + $batches = (static function () { + yield RowsMother::sequentialIds(1); + yield rows(schema(int_schema('id')), row(['id' => 2])); + })(); + + static::assertSame( + [['id' => 1], ['id' => 2]], + (new Executor()) + ->merge($batches, $plan) + ->toArray(), + ); + } + + public function test_merge_of_no_batches_returns_rows_with_the_plans_schema(): void + { + $plan = new Described( + new Pipeline(0, new Segments(from_rows(rows(schema(int_schema('id'))))), NodeMother::context()), + schema(int_schema('id')), + ); + + $rows = (new Executor())->merge((static fn() => yield from [])(), $plan); + + static::assertSame(0, $rows->count()); + static::assertEquals(schema(int_schema('id')), $rows->schema()); + } + + public function test_merge_of_no_batches_from_a_refused_plan_returns_rows_with_an_empty_schema(): void + { + $plan = new Raw( + new Pipeline(0, new Segments(from_rows(rows(schema(int_schema('id'))))), NodeMother::context()), + SchemaNotDerivableException::extractor('x'), + ); + + $rows = (new Executor())->merge((static fn() => yield from [])(), $plan); + + static::assertSame(0, $rows->count()); + static::assertEquals(schema(), $rows->schema()); + } + + public function test_execute_opens_and_closes_the_plans_dataframe_span(): void + { + $telemetry = new MemoryTelemetryContext(); + $segments = new Segments(from_rows(RowsMother::sequentialIds(1))); + + iterator_to_array((new Executor())->execute( + new Described(new Pipeline(0, $segments, $telemetry->flowContext), schema(int_schema('id'))), + )); + + static::assertCount(1, $telemetry->spans->startedSpans()); + static::assertCount(1, $telemetry->spans->endedSpans()); + } + + public function test_a_failing_frame_closes_its_span_as_failed_and_rethrows(): void + { + $telemetry = new MemoryTelemetryContext(); + $failure = new RuntimeException('right side exploded'); + $segments = new Segments(from_rows(RowsMother::sequentialIds(1))); + $segments->add(new ThrowingTransformer($failure)); + $plan = new Described(new Pipeline(0, $segments, $telemetry->flowContext), schema(int_schema('id'))); + + try { + (new Executor())->fetch($plan); + + static::fail('Expected the frame failure to be rethrown.'); + } catch (RuntimeException $e) { + static::assertSame($failure, $e); + } + + static::assertCount(1, $telemetry->spans->endedSpans()); + static::assertTrue($telemetry->spans->endedSpans()[0]->status()?->isError()); + } + + public function test_execute_yields_the_batches_of_the_planned_pipeline(): void + { + $batches = iterator_to_array(ExecutedPlan::of( + NodeMother::plan(NodeMother::limit(NodeMother::read(from_array([['id' => 1], ['id' => 2]])), 1)), + NodeMother::context(), + )); + + static::assertCount(1, $batches); + static::assertSame([['id' => 1]], $batches[0]->toArray()); + } + + public function test_a_second_run_of_the_same_logical_plan_gets_fresh_steps(): void + { + $plan = NodeMother::plan(NodeMother::limit(NodeMother::read(from_array([['id' => 1], ['id' => 2]])), 1)); + $context = NodeMother::context(); + + iterator_to_array(ExecutedPlan::of($plan, $context)); + + static::assertSame([['id' => 1]], iterator_to_array(ExecutedPlan::of($plan, $context))[0]->toArray()); + } + + public function test_every_execution_plans_its_own(): void + { + /** @var ArrayObject $log */ + $log = new ArrayObject(); + $context = NodeMother::context( + config_builder()->optimizer(new Optimizer(new RecordingRule('plan', $log)))->build(), + ); + $plan = NodeMother::plan(NodeMother::read()); + + iterator_to_array(ExecutedPlan::of($plan, $context)); + iterator_to_array(ExecutedPlan::of($plan, $context)); + + static::assertCount(2, $log); + } + + public function test_an_abandoned_run_leaves_no_consumed_step_for_the_next_run(): void + { + $plan = NodeMother::plan(NodeMother::limit( + NodeMother::read(from_rows( + rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])), + rows(schema(int_schema('id')), row(['id' => 3]), row(['id' => 4])), + )), + 3, + )); + $context = NodeMother::context(); + + // the reference keeps the generator parked, so its steps stay consumed + $parked = ExecutedPlan::of($plan, $context); + $parked->current(); + + static::assertSame( + 3, + array_sum(array_map( + static fn(Rows $rows): int => $rows->count(), + iterator_to_array(ExecutedPlan::of($plan, $context), false), + )), + ); + } + + public function test_a_plan_reading_back_from_itself_throws_cyclic_plan_on_run(): void + { + $context = NodeMother::context(); + $read = NodeMother::read(); + + $this->expectException(InvalidLogicException::class); + $this->expectExceptionMessage('Cannot run this plan: it reads from a DataFrame that reads back from it.'); + + iterator_to_array(ExecutedPlan::of( + NodeMother::plan(new Transform($read, new PlanDrainingTransformer(NodeMother::plan($read), $context))), + $context, + )); + } + + public function test_the_reentrancy_guard_is_disarmed_across_the_yield(): void + { + $plan = NodeMother::plan(NodeMother::read(from_array([['id' => 1], ['id' => 2], ['id' => 3]]))); + $context = NodeMother::context(); + + // the reference keeps the generator parked across the read below - inlining it lets PHP + // destroy the generator, which clears the flag and makes this test vacuous + $parked = ExecutedPlan::of($plan, $context); + $parked->current(); + + static::assertCount(1, iterator_to_array(ExecutedPlan::of($plan, $context))); + } + + public function test_a_plan_is_planned_with_the_planner_of_the_contexts_config(): void + { + /** @var ArrayObject $log */ + $log = new ArrayObject(); + $context = NodeMother::context( + config_builder()->optimizer(new Optimizer(new RecordingRule('plan', $log)))->build(), + ); + + $batches = iterator_to_array(ExecutedPlan::of(NodeMother::plan(NodeMother::read()), $context)); + + static::assertSame([['id' => 1]], $batches[0]->toArray()); + static::assertSame(['plan'], $log->getArrayCopy()); + } + + public function test_a_drained_run_reports_one_balanced_dataframe_span(): void + { + $telemetry = new MemoryTelemetryContext(); + + iterator_to_array(ExecutedPlan::of(NodeMother::plan(NodeMother::read()), $telemetry->flowContext)); + + static::assertCount(1, $telemetry->spans->startedSpans()); + static::assertCount(1, $telemetry->spans->endedSpans()); + static::assertNotTrue($telemetry->spans->endedSpans()[0]->status()?->isError()); + } + + public function test_an_executor_failure_reports_the_span_as_failed_and_rethrows(): void + { + $telemetry = new MemoryTelemetryContext(); + $failure = new RuntimeException('source exploded'); + + try { + iterator_to_array(ExecutedPlan::of( + NodeMother::plan(new Transform(NodeMother::read(), new ThrowingTransformer($failure))), + $telemetry->flowContext, + )); + + static::fail('Expected the executor failure to be rethrown.'); + } catch (RuntimeException $e) { + static::assertSame($failure, $e); + } + + static::assertCount(1, $telemetry->spans->startedSpans()); + static::assertCount(1, $telemetry->spans->endedSpans()); + static::assertTrue($telemetry->spans->endedSpans()[0]->status()?->isError()); + } + + public function test_an_abandoned_run_closes_its_span(): void + { + $telemetry = new MemoryTelemetryContext(); + $generator = ExecutedPlan::of( + NodeMother::plan(NodeMother::read(from_rows( + rows(schema(int_schema('id')), row(['id' => 1])), + rows(schema(int_schema('id')), row(['id' => 2])), + ))), + $telemetry->flowContext, + ); + + $generator->current(); + unset($generator); + + static::assertCount(1, $telemetry->spans->startedSpans()); + static::assertCount(1, $telemetry->spans->endedSpans()); + static::assertNotTrue($telemetry->spans->endedSpans()[0]->status()?->isError()); + } + + public function test_another_plan_run_during_an_armed_outer_run_does_not_trip_the_guard(): void + { + $other = new PlanDrainingTransformer(NodeMother::plan(NodeMother::read()), NodeMother::context()); + + iterator_to_array(ExecutedPlan::of( + NodeMother::plan(new Transform(NodeMother::read(), $other)), + NodeMother::context(), + )); + + static::assertCount(1, $other->drained); + static::assertSame([['id' => 1]], $other->drained[0]->toArray()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/ChainExtractorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/ChainExtractorTest.php index 2f2e3b2044..57fd54dff3 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/ChainExtractorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/ChainExtractorTest.php @@ -55,7 +55,7 @@ public function schema(): Schema return schema(int_schema('id')); } - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { yield rows(schema(int_schema('id')), row(['id' => 1])); yield rows(schema(int_schema('id')), row(['id' => 2])); @@ -71,7 +71,7 @@ public function schema(): Schema return schema(int_schema('id')); } - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { yield rows(schema(int_schema('id')), row(['id' => 3])); yield rows(schema(int_schema('id')), row(['id' => 4])); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/DataFrameExtractorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/DataFrameExtractorTest.php index 9f410f6ab7..dcb1388227 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/DataFrameExtractorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/DataFrameExtractorTest.php @@ -4,16 +4,32 @@ namespace Flow\ETL\Tests\Unit\Extractor; +use Flow\ETL\ErrorHandler\ExtractionError; +use Flow\ETL\ErrorHandler\IgnoreError; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\SchemaDefinitionNotFoundException; use Flow\ETL\Exception\SchemaNotDerivableException; +use Flow\ETL\Extractor\DataFrameExtractor; +use Flow\ETL\Extractor\Signal; +use Flow\ETL\Tests\Context\MemoryTelemetryContext; use Flow\ETL\Tests\Double\CountingExtractor; +use Flow\ETL\Tests\Double\RecordingErrorHandler; +use Flow\ETL\Tests\Double\RecordingFileExtractor; +use Flow\ETL\Tests\Double\RepeatableExtractor; +use Flow\ETL\Tests\Double\ThrowingTransformer; use Flow\ETL\Tests\Double\UndescribableRowLessExtractor; use Flow\ETL\Tests\FlowTestCase; +use Generator; +use PHPUnit\Framework\Attributes\DataProvider; +use RuntimeException; +use function array_map; +use function array_merge; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\from_all; +use function Flow\ETL\DSL\from_array; use function Flow\ETL\DSL\from_data_frame; use function Flow\ETL\DSL\from_rows; use function Flow\ETL\DSL\int_schema; @@ -59,6 +75,89 @@ public function test_a_declared_schema_wins_over_the_wrapped_frame(): void static::assertSame([['id' => '1'], ['id' => '2']], $batches[0]->toArray()); } + public function test_a_declared_schema_describes_a_frame_that_cannot_describe_itself(): void + { + $declared = schema(int_schema('id')); + + static::assertEquals( + $declared, + from_data_frame(df()->read(new UndescribableRowLessExtractor()))->withSchema($declared)->schema(), + ); + } + + /** + * @return Generator + */ + public static function declared_schemas(): Generator + { + yield 'derived schema' => [false]; + yield 'declared schema' => [true]; + } + + #[DataProvider('declared_schemas')] + public function test_a_failure_inside_the_frame_is_offered_to_the_outer_handler_as_an_extraction_error(bool $declared): void + { + $failure = new RuntimeException('boom'); + $extractor = from_data_frame( + df()->read(from_array([['id' => 1], ['id' => 2]]))->transform(new ThrowingTransformer($failure)), + ); + + if ($declared) { + $extractor->withSchema(schema(int_schema('id'))); + } + + $handler = new RecordingErrorHandler(new IgnoreError()); + + $rows = df()->read($extractor)->onError($handler)->fetch(); + + static::assertSame(0, $rows->count()); + static::assertCount(1, $handler->errors); + $error = $handler->errors[0]; + static::assertInstanceOf(ExtractionError::class, $error); + static::assertSame($failure, $error->cause); + static::assertSame($extractor, $error->extractor); + } + + public function test_a_failure_inside_a_wrapped_frame_is_offered_to_the_outer_handler_as_an_extraction_error(): void + { + $failure = new RuntimeException('boom'); + $chain = from_all(from_data_frame( + df()->read(from_array([['id' => 1], ['id' => 2]]))->transform(new ThrowingTransformer($failure)), + )); + $handler = new RecordingErrorHandler(new IgnoreError()); + + $rows = df()->read($chain)->onError($handler)->fetch(); + + static::assertSame(0, $rows->count()); + static::assertCount(1, $handler->errors); + $error = $handler->errors[0]; + static::assertInstanceOf(ExtractionError::class, $error); + static::assertSame($failure, $error->cause); + static::assertSame($chain, $error->extractor); + } + + public function test_it_repeats_when_every_source_of_its_frame_repeats(): void + { + static::assertTrue(from_data_frame(df()->read(from_array([['id' => 1]])))->isRepeatable()); + static::assertFalse(from_data_frame(df()->read(new RepeatableExtractor(false)))->isRepeatable()); + } + + public function test_a_limit_given_to_extract_reaches_the_frames_source(): void + { + $source = new RecordingFileExtractor( + schema(int_schema('id')), + rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])), + ); + + $batches = iterator_to_array(from_data_frame(df()->read($source))->extract(flow_context(config()), 2), false); + + static::assertSame([2], $source->limits); + static::assertSame( + [['id' => 1], ['id' => 2]], + array_merge(...array_map(static fn($rows) => $rows->toArray(), $batches)), + ); + } + public function test_a_refusal_from_the_wrapped_frame_is_re_raised_unchanged(): void { $extractor = from_data_frame(df()->read(new UndescribableRowLessExtractor())); @@ -73,15 +172,96 @@ public function test_a_refusal_from_the_wrapped_frame_is_re_raised_unchanged(): $extractor->schema(); } - public function test_a_step_added_to_the_wrapped_frame_after_it_was_described_changes_the_answer(): void + public function test_the_frame_is_frozen_at_construction(): void { - $extractor = from_data_frame($inner = df()->read(from_rows(rows(schema(int_schema('id')), row(['id' => 1]))))); - - static::assertEquals(schema(int_schema('id')), $extractor->schema()); + $inner = df()->read(from_rows(rows(schema(int_schema('id')), row(['id' => 1])))); + $extractor = from_data_frame($inner); $inner->withEntry('doubled', ref('id')->multiply(lit(2))); - static::assertEquals(schema(int_schema('id'), int_schema('doubled')), $extractor->schema()); + static::assertSame([['id' => 1]], iterator_to_array($extractor->extract(flow_context(config())))[0]->toArray()); + } + + public function test_it_is_constructed_from_a_frame(): void + { + static::assertSame( + [['id' => 1]], + df() + ->read(new DataFrameExtractor(df()->read(from_rows(rows(schema(int_schema('id')), row(['id' => 1])))))) + ->fetch() + ->toArray(), + ); + } + + public function test_an_error_handler_set_after_embedding_does_not_reach_the_frame(): void + { + $inner = df() + ->read(from_array([['id' => 1]])) + ->with(new ThrowingTransformer(new RuntimeException('inner boom'))); + $outer = df()->read(from_data_frame($inner)); + $inner->onError(new IgnoreError()); + + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('inner boom'); + + $outer->fetch(); + } + + public function test_extract_runs_the_snapshot_plan_when_reached_through_a_chain_wrapper(): void + { + $inner = df()->read(from_rows(rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]))))->limit(1); + + static::assertSame( + [['id' => 1], ['id' => 3]], + df() + ->read(from_all(from_data_frame($inner), from_array([['id' => 3]]))) + ->fetch() + ->toArray(), + ); + } + + public function test_extract_stops_on_signal_stop(): void + { + $counting = new CountingExtractor( + schema(int_schema('id')), + rows(schema(int_schema('id')), row(['id' => 1])), + rows(schema(int_schema('id')), row(['id' => 2])), + ); + $counting->withBatchSize(1); + $generator = from_data_frame(df()->read($counting))->extract(flow_context(config())); + + $generator->current(); + $generator->send(Signal::STOP); + + static::assertFalse($generator->valid()); + static::assertSame(1, $counting->batchesYielded); + } + + public function test_the_snapshot_source_is_read_once_across_schema_and_extract(): void + { + $counting = new CountingExtractor(schema(int_schema('id')), rows(schema(int_schema('id')), row(['id' => 1]))); + $extractor = from_data_frame(df()->read($counting)->limit(1)); + + $extractor->schema(); + $batches = iterator_to_array($extractor->extract(flow_context(config()))); + + static::assertCount(1, $batches); + static::assertSame(1, $counting->extractCalls); + static::assertSame([['id' => 1]], $batches[0]->toArray()); + } + + public function test_extract_opens_and_closes_one_dataframe_span_for_the_wrapped_frame(): void + { + $telemetry = new MemoryTelemetryContext(); + $extractor = from_data_frame( + df($telemetry->config)->read(from_rows(rows(schema(int_schema('id')), row(['id' => 1])))), + ) + ->withSchema(schema(int_schema('id'))); + + iterator_to_array($extractor->extract(flow_context(config()))); + + static::assertCount(1, $telemetry->spans->startedSpans()); + static::assertCount(1, $telemetry->spans->endedSpans()); } public function test_extracting_from_another_data_frame(): void @@ -103,6 +283,29 @@ public function test_extracting_from_another_data_frame(): void ); } + public function test_a_limited_wrapped_frame_extracted_twice_is_planned_per_run(): void + { + $extractor = from_all( + from_data_frame(df()->read(from_array([['id' => 1], ['id' => 2]]))->limit(1)), + from_array([['id' => 3]]), + ); + + $first = []; + + foreach ($extractor->extract(flow_context(config())) as $rows) { + $first = [...$first, ...$rows->toArray()]; + } + + $second = []; + + foreach ($extractor->extract(flow_context(config())) as $rows) { + $second = [...$second, ...$rows->toArray()]; + } + + static::assertSame([['id' => 1], ['id' => 3]], $first); + static::assertSame([['id' => 1], ['id' => 3]], $second); + } + public function test_it_describes_the_wrapped_frame_without_reading_it(): void { $counting = new CountingExtractor(schema(int_schema('id'), str_schema('name'))); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/FileColumnsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/FileColumnsTest.php index ff25d0ef7f..88366141bc 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/FileColumnsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/FileColumnsTest.php @@ -139,6 +139,33 @@ public function test_the_declared_schema_types_the_value_forFile_produces(): voi ); } + public function test_partitions_is_empty_without_partition_names(): void + { + static::assertEquals( + schema(), + FileColumnsContext::discovering(names: [], metadataColumns: true)->partitions(schema(str_schema('name'))), + ); + } + + public function test_partitions_is_only_the_partition_block_typed_as_declared(): void + { + static::assertEquals( + schema(int_schema('year'), str_schema('month', nullable: true)), + FileColumnsContext::discovering(names: [ + 'year' => false, + 'month' => true, + ], metadataColumns: true)->partitions(schema(str_schema('name'), int_schema('year'))), + ); + } + + public function test_partitions_uses_the_declared_partition_type_when_the_schema_has_none(): void + { + static::assertEquals( + schema(int_schema('year')), + FileColumnsContext::discovering(types: partition_types(year: type_integer()))->partitions(schema()), + ); + } + public function test_without_tail_ignores_names_the_schema_does_not_carry(): void { static::assertTrue(schema(int_schema('id'), str_schema('name'))->isSame(FileColumnsContext::discovering(names: [ diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/FileReadingTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/FileReadingTest.php index 16a4c2c769..ee21c126c1 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/FileReadingTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/FileReadingTest.php @@ -9,7 +9,7 @@ use Flow\ETL\Tests\Context\SelfDescribingFilesContext; use Flow\ETL\Tests\Double\FileReadingExtractor; use Flow\ETL\Tests\FlowTestCase; -use Flow\Filesystem\Path\Filter\OnlyFiles; +use Flow\Filesystem\Tests\Double\RejectingFilter; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\schema; @@ -71,18 +71,6 @@ public function test_the_memo_never_starts_the_generator_again(): void static::assertSame(0, $second->advanced); } - public function test_the_path_filter_forgets_the_memo(): void - { - $extractor = new FileReadingExtractor(); - $extractor->derive(SelfDescribingFilesContext::describing(schema(int_schema('id')))->generator()); - $extractor->withPathFilter(new OnlyFiles()); - - static::assertEquals( - schema(str_schema('name')), - $extractor->derive(SelfDescribingFilesContext::describing(schema(str_schema('name')))->generator()), - ); - } - public function test_union_by_name_folds_every_file(): void { $files = SelfDescribingFilesContext::describing(schema(int_schema('id')), schema(str_schema('name'))); @@ -111,4 +99,23 @@ public function test_source_files_yields_one_source_per_listed_path(): void ), ); } + + public function test_source_files_lists_only_what_the_path_filter_admits(): void + { + $filesystem = memory_filesystem(); + $filesystem->writeTo(path('memory://orders/year=2024/a.csv'))->close(); + $filesystem->writeTo(path('memory://orders/year=2025/b.csv'))->close(); + + static::assertSame( + [], + iterator_to_array( + (new FileReadingExtractor())->listing( + $filesystem, + path('memory://orders/*/*.csv'), + new RejectingFilter(), + ), + false, + ), + ); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/FilesExtractorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/FilesExtractorTest.php index 03f61d7dcf..6ab02bd371 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/FilesExtractorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/FilesExtractorTest.php @@ -6,11 +6,14 @@ use Flow\ETL\Extractor\FilesExtractor; use Flow\ETL\Extractor\Signal; +use Flow\ETL\Schema; use Flow\ETL\Tests\Context\ExtractedRows; use Flow\ETL\Tests\FlowTestCase; use function Flow\ETL\DSL\files; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; use function iterator_to_array; final class FilesExtractorTest extends FlowTestCase @@ -22,6 +25,41 @@ public function test_a_zero_string_extension_is_not_null(): void static::assertSame('0', $batches[0]->first()->get('extension')); } + public function test_partition_directories_become_string_columns(): void + { + $extractor = files(__DIR__ + . '/../../Integration/DataFrame/Fixtures/Partitioning/multi_partition_pruning_test/**/*.txt'); + $partitions = schema(str_schema('day'), str_schema('month'), str_schema('year')); + + $first = iterator_to_array($extractor->extract(flow_context()), false)[0]->first(); + + static::assertEquals($partitions, $extractor->partitionSchema()); + static::assertEquals($partitions, $extractor->schema()->keep('day', 'month', 'year')); + static::assertSame(['day' => '30', 'month' => '12', 'year' => '2022'], [ + 'day' => $first->get('day'), + 'month' => $first->get('month'), + 'year' => $first->get('year'), + ]); + } + + public function test_a_listing_without_partition_directories_declares_no_partition_columns(): void + { + static::assertEquals(new Schema(), files(__DIR__ . '/Fixtures/FileListExtractor/*')->partitionSchema()); + } + + public function test_a_declared_schema_still_gets_the_partition_columns(): void + { + $extractor = files(__DIR__ + . '/../../Integration/DataFrame/Fixtures/Partitioning/multi_partition_pruning_test/**/*.txt')->withSchema(schema(str_schema( + 'path', + ))); + + static::assertEquals( + schema(str_schema('path'), str_schema('day'), str_schema('month'), str_schema('year')), + $extractor->schema(), + ); + } + public function test_extracting_files_from_directory(): void { $extractor = files(__DIR__ . '/Fixtures/FileListExtractor/*'); @@ -54,9 +92,8 @@ public function test_extracting_files_from_directory_recursive(): void public function test_extracting_files_from_directory_with_limit(): void { $extractor = files(__DIR__ . '/Fixtures/FileListExtractor/**/*')->withBatchSize(1); - $extractor->pushLimit(2); - self::assertExtractedRowsCount(2, $extractor); + self::assertExtractedRowsCount(2, $extractor, limit: 2); } public function test_is_repeatable(): void diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/PushesLimitTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/PushesLimitTest.php deleted file mode 100644 index 7edb012aac..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/PushesLimitTest.php +++ /dev/null @@ -1,43 +0,0 @@ -pushLimit(10); - $widened->pushLimit(100); - - $narrowed = files(__DIR__ . '/Fixtures/FileListExtractor/*'); - $narrowed->pushLimit(100); - $narrowed->pushLimit(10); - - static::assertSame(10, $widened->pushedLimit()); - static::assertSame(10, $narrowed->pushedLimit()); - } - - public function test_nothing_is_pushed_by_default(): void - { - static::assertNull(files(__DIR__ . '/Fixtures/FileListExtractor/*')->pushedLimit()); - } - - #[TestWith([0])] - #[TestWith([-1])] - public function test_push_rejects_zero_and_negative(int $limit): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Limit must be greater than 0'); - - files(__DIR__ . '/Fixtures/FileListExtractor/*')->pushLimit($limit); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/RepeatabilityTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/RepeatabilityTest.php index 15acd10b96..4a06ea53d1 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/RepeatabilityTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/RepeatabilityTest.php @@ -5,9 +5,25 @@ namespace Flow\ETL\Tests\Unit\Extractor; use Flow\ETL\Extractor\Repeatability; +use Flow\ETL\Memory\ArrayMemory; +use Flow\ETL\Plan\LogicalPlan; +use Flow\ETL\Plan\Node\Outputs; +use Flow\ETL\Plan\Node\Result; +use Flow\ETL\Plan\Node\Write; +use Flow\ETL\Plan\Sinks; +use Flow\ETL\Plan\Trigger; use Flow\ETL\Tests\Double\EmptyExtractor; use Flow\ETL\Tests\Double\RepeatableExtractor; use Flow\ETL\Tests\FlowTestCase; +use Flow\ETL\Tests\Mother\NodeMother; + +use function Flow\ETL\DSL\df; +use function Flow\ETL\DSL\from_array; +use function Flow\ETL\DSL\from_data_frame; +use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\join_on; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\to_memory; final class RepeatabilityTest extends FlowTestCase { @@ -40,4 +56,85 @@ public function test_it_answers_the_extractors_own_verdict(): void static::assertTrue((new Repeatability())->of(new RepeatableExtractor(true))); static::assertFalse((new Repeatability())->of(new RepeatableExtractor(false))); } + + public function test_a_plan_whose_every_source_repeats_repeats(): void + { + static::assertTrue((new Repeatability())->ofPlan(NodeMother::plan(NodeMother::read()))); + } + + public function test_a_plan_is_refused_when_a_joins_right_side_cannot_repeat(): void + { + static::assertFalse((new Repeatability())->ofPlan(NodeMother::plan(NodeMother::join( + NodeMother::read(), + NodeMother::joinRight(NodeMother::plan(NodeMother::nonRepeatableRead())), + )))); + } + + public function test_a_plan_is_refused_when_a_cross_joins_right_side_cannot_repeat(): void + { + static::assertFalse((new Repeatability())->ofPlan(NodeMother::plan(NodeMother::crossJoin( + NodeMother::read(), + NodeMother::joinRight(NodeMother::plan(NodeMother::nonRepeatableRead())), + )))); + } + + public function test_a_plan_whose_joins_right_side_repeats_repeats(): void + { + static::assertTrue((new Repeatability())->ofPlan(NodeMother::plan(NodeMother::join( + NodeMother::read(), + NodeMother::joinRight(NodeMother::plan(NodeMother::read())), + )))); + } + + public function test_a_plan_whose_consumers_share_a_source_repeats(): void + { + $read = NodeMother::read(); + + static::assertTrue((new Repeatability())->ofPlan(Trigger::rows->plan( + $read, + new Sinks(new Write($read, to_memory(new ArrayMemory()))), + ))); + } + + public function test_a_plan_is_refused_when_a_sink_reads_a_join_whose_right_side_cannot_repeat(): void + { + static::assertFalse((new Repeatability())->ofPlan(new LogicalPlan( + new Outputs( + new Result(NodeMother::read()), + new Write( + NodeMother::join( + NodeMother::read(), + NodeMother::joinRight(NodeMother::plan(NodeMother::nonRepeatableRead())), + ), + to_memory(new ArrayMemory()), + ), + ), + ))); + } + + public function test_a_frame_with_a_declared_schema_answers_for_its_frame(): void + { + static::assertFalse((new Repeatability())->of( + from_data_frame(df()->read(new RepeatableExtractor(false)))->withSchema(schema(int_schema('id'))), + )); + } + + public function test_a_frame_repeats_when_every_source_it_reads_repeats(): void + { + static::assertTrue((new Repeatability())->of(from_data_frame(df()->read(from_array([['id' => 1]]))))); + } + + public function test_a_frame_over_a_source_that_cannot_repeat_is_refused(): void + { + static::assertFalse((new Repeatability())->of(from_data_frame(df()->read(new RepeatableExtractor(false))))); + } + + public function test_a_frame_joining_a_frame_that_cannot_repeat_is_refused(): void + { + static::assertFalse((new Repeatability())->of(from_data_frame( + df() + ->read(from_array([['id' => 1]])) + ->join(df()->read(new RepeatableExtractor(false)), join_on(['id' => 'id'], 'r_')), + ))); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/FlowContextTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/FlowContextTest.php index cefa04cb87..880deb6336 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/FlowContextTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/FlowContextTest.php @@ -6,6 +6,8 @@ use Flow\Calculator\Calculator; use Flow\ETL\Config; +use Flow\ETL\ErrorHandler\IgnoreError; +use Flow\ETL\ErrorHandler\ThrowError; use Flow\ETL\FlowContext; use Flow\ETL\Tests\FlowTestCase; use Flow\Filesystem\FilesystemTable; @@ -20,12 +22,43 @@ final class FlowContextTest extends FlowTestCase { + public function test_with_error_handler_shares_the_telemetry_built_before(): void + { + $outer = flow_context(config()); + $telemetry = $outer->telemetry(); + + static::assertSame($telemetry, $outer->withErrorHandler(new ThrowError())->telemetry()); + } + + public function test_with_error_handler_builds_the_telemetry_it_shares(): void + { + $outer = flow_context(config()); + + $derived = $outer->withErrorHandler(new ThrowError()); + + static::assertSame($outer->telemetry(), $derived->telemetry()); + } + + public function test_with_error_handler_returns_a_new_context_and_leaves_this_one_alone(): void + { + $outer = flow_context(config()); + $original = $outer->errorHandler(); + $handler = new IgnoreError(); + + $derived = $outer->withErrorHandler($handler); + + static::assertNotSame($outer, $derived); + static::assertSame($handler, $derived->errorHandler()); + static::assertSame($outer->config, $derived->config); + static::assertSame($original, $outer->errorHandler()); + } + public function test_config_constructor_takes_no_filesystem_table(): void { $constructor = (new ReflectionClass(Config::class))->getConstructor(); static::assertNotNull($constructor); - static::assertCount(16, $constructor->getParameters()); + static::assertCount(17, $constructor->getParameters()); static::assertSame( [], array_filter( @@ -46,6 +79,7 @@ public function test_flow_context_exposes_no_filesystem_and_no_streams(): void 'errorHandler', 'hydrator', 'setErrorHandler', + 'withErrorHandler', 'telemetry', ], array_map( diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AllFunctionsDeclareTheirDeterminismTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AllFunctionsDeclareTheirDeterminismTest.php new file mode 100644 index 0000000000..a28f8c2af1 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AllFunctionsDeclareTheirDeterminismTest.php @@ -0,0 +1,85 @@ + [$class]; + } + } + + /** + * @param class-string $class + */ + #[DataProvider('scalar_functions_provider')] + public function test_every_scalar_function_is_deterministic_except_the_declared_generators(string $class): void + { + try { + $function = ScalarFunctionFixtures::instance($class); + } catch (RequiredPHPVersionException $e) { + static::markTestSkipped($e->getMessage()); + } + + // the fixtures build Uuid through uuid4() and Ulid without a ref - both generate; a user callable is never + // trusted, and ToDateTime's fixture parses 'Y-m-d', leaving the time of day to the clock + static::assertSame( + !in_array( + $class, + [ + Function\Now::class, + Function\RandomString::class, + Function\Uuid::class, + Function\Ulid::class, + Function\CallUserFunc::class, + Function\ToDateTime::class, + ], + true, + ), + $function->deterministic(), + ); + } + + public function test_a_composite_is_not_deterministic_when_any_child_is_not(): void + { + static::assertFalse(ref('a')->equals(now())->deterministic()); + static::assertFalse(now()->and(lit(true))->deterministic()); + static::assertFalse(lit(1)->plus(random_string(3))->deterministic()); + static::assertTrue(ref('a')->equals(lit(1))->and(ref('b')->isNotNull())->deterministic()); + } + + public function test_a_ulid_over_a_reference_is_deterministic(): void + { + static::assertTrue(ulid(ref('id'))->deterministic()); + static::assertFalse(ulid()->deterministic()); + } + + public function test_both_uuid_constructors_generate(): void + { + static::assertFalse(uuid_v4()->deterministic()); + static::assertFalse(uuid_v7(new DateTimeImmutable('2024-01-01 00:00:00'))->deterministic()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CallUserFuncTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CallUserFuncTest.php index fdf6b37723..16f5711bc1 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CallUserFuncTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CallUserFuncTest.php @@ -25,6 +25,11 @@ final class CallUserFuncTest extends FlowTestCase { + public function test_it_is_never_deterministic(): void + { + static::assertFalse(call(lit('strtoupper'), type_string(), ['a'])->deterministic()); + } + public function test_named_parameters_survive_a_rebuild(): void { $function = new CallUserFunc(lit('explode'), type_list(type_string()), [ diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ReferenceRenameTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ReferenceRenameTest.php new file mode 100644 index 0000000000..424dd6161b --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ReferenceRenameTest.php @@ -0,0 +1,45 @@ +in(ref('y'))); + } + + public function test_every_reference_inside_the_tree_is_renamed_and_the_rest_kept(): void + { + static::assertEquals( + ref('year')->equals(lit(2023))->and(ref('month')->equals(lit('07'))), + (new ReferenceRename('y', 'year'))->in(ref('y')->equals(lit(2023))->and(ref('month')->equals(lit('07')))), + ); + } + + public function test_a_tree_without_the_column_is_returned_as_is(): void + { + $tree = ref('month')->equals(lit('07')); + + static::assertSame($tree, (new ReferenceRename('y', 'year'))->in($tree)); + } + + public function test_an_alias_on_the_reference_is_kept(): void + { + static::assertEquals(ref('year')->as('label'), (new ReferenceRename('y', 'year'))->in(ref('y')->as('label'))); + } + + public function test_a_resolved_reference_to_the_column_cannot_be_renamed(): void + { + static::assertNull((new ReferenceRename('y', 'year'))->in(ref('y')->resolve(int_schema('y')))); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ReferencedColumnsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ReferencedColumnsTest.php new file mode 100644 index 0000000000..771c281d1e --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ReferencedColumnsTest.php @@ -0,0 +1,37 @@ +in(ref('a'))->names()); + } + + public function test_an_alias_reports_the_source_column(): void + { + static::assertSame(['year'], (new ReferencedColumns())->in(ref('year')->as('y'))->names()); + } + + public function test_a_nested_tree_reports_every_column_once(): void + { + static::assertSame( + ['a', 'b'], + (new ReferencedColumns())->in(ref('a')->equals(ref('b'))->and(ref('a')->isNotNull()))->names(), + ); + } + + public function test_a_literal_only_predicate_references_nothing(): void + { + static::assertSame([], (new ReferencedColumns())->in(lit(true))->names()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ToDateTime/PatternCoverageTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ToDateTime/PatternCoverageTest.php new file mode 100644 index 0000000000..3457303860 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ToDateTime/PatternCoverageTest.php @@ -0,0 +1,44 @@ +fillsFromClock()); + } + + #[TestWith(['Y-m-d'])] + #[TestWith(['H:i:s'])] + #[TestWith(['Y-m H:i'])] + #[TestWith(['m-d H:i'])] + #[TestWith(['Y-m-d \H'])] + #[TestWith(['\U Y-m-d'])] + public function test_a_pattern_leaving_a_field_out_reads_the_clock(string $pattern): void + { + static::assertTrue((new PatternCoverage($pattern))->fillsFromClock()); + } + + public function test_any_finds_one_of_the_characters(): void + { + $coverage = new PatternCoverage(''); + + static::assertTrue($coverage->any('Y-m-d', 'xm')); + static::assertFalse($coverage->any('Y-m-d', 'HG')); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ToDateTimeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ToDateTimeTest.php index beaae0861b..955814ddd0 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ToDateTimeTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ToDateTimeTest.php @@ -8,13 +8,58 @@ use DateTimeZone; use Flow\ETL\Tests\FlowTestCase; +use function array_slice; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\lit; +use function Flow\ETL\DSL\random_string; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\to_date_time; final class ToDateTimeTest extends FlowTestCase { + public function test_the_default_format_is_deterministic(): void + { + static::assertTrue(to_date_time(ref('value'))->deterministic()); + } + + public function test_a_format_that_leaves_the_time_out_is_not_deterministic(): void + { + static::assertFalse(to_date_time(ref('value'), 'Y-m-d')->deterministic()); + } + + public function test_a_format_that_resets_unparsed_fields_is_deterministic(): void + { + static::assertTrue(to_date_time(ref('value'), '!Y-m-d')->deterministic()); + } + + public function test_a_format_known_only_at_run_time_is_not_deterministic(): void + { + static::assertFalse(to_date_time(ref('value'), ref('format'))->deterministic()); + } + + public function test_a_non_deterministic_child_makes_it_non_deterministic(): void + { + static::assertFalse(to_date_time(random_string(10))->deterministic()); + } + + public function test_a_rebuild_keeping_the_format_child_keeps_the_answer(): void + { + $function = to_date_time(ref('value')); + + static::assertTrue( + $function->withChildren([ref('renamed'), ...array_slice($function->children(), 1)])->deterministic(), + ); + } + + public function test_a_rebuild_with_another_format_child_does_not_know_the_format(): void + { + $function = to_date_time(ref('value')); + $children = $function->children(); + + static::assertFalse($function->withChildren([$children[0], lit('Y-m-d H:i:s'), $children[2]])->deterministic()); + } + public function test_date_time_to_date_time(): void { static::assertEquals( diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/JoinStepsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/JoinStepsTest.php index 2e1cdf6154..8cf0433d2d 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/JoinStepsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/JoinStepsTest.php @@ -9,10 +9,12 @@ use Flow\ETL\Join\JoinSteps; use Flow\ETL\Processor\HashJoinProcessor; use Flow\ETL\Tests\FlowTestCase; +use Flow\ETL\Tests\Mother\PhysicalPlanMother; use function Flow\ETL\DSL\config_builder; -use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\from_rows; +use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; @@ -21,7 +23,7 @@ final class JoinStepsTest extends FlowTestCase public function test_builds_a_hash_join_processor(): void { $steps = JoinSteps::of( - df()->read(from_rows(rows(schema()))), + PhysicalPlanMother::reading(from_rows(rows(schema()))), Expression::on(['id' => 'user_id']), Join::left, config_builder()->build(), @@ -30,4 +32,22 @@ public function test_builds_a_hash_join_processor(): void static::assertCount(1, $steps); static::assertInstanceOf(HashJoinProcessor::class, $steps[0]); } + + public function test_of_takes_a_frame_output_as_its_right_side(): void + { + $right = PhysicalPlanMother::reading(from_rows(rows(schema(int_schema('id')), row(['id' => 1])))); + + $steps = JoinSteps::of($right, Expression::on(['id' => 'id'], 'r_'), Join::inner, config_builder()->build()); + + static::assertCount(1, $steps); + static::assertInstanceOf(HashJoinProcessor::class, $steps[0]); + static::assertSame( + ['id', 'r_id'], + $steps[0] + ->bind(schema(int_schema('id'))) + ->output + ->references() + ->names(), + ); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/BranchingLoaderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/BranchingLoaderTest.php deleted file mode 100644 index b2f31d2f39..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/BranchingLoaderTest.php +++ /dev/null @@ -1,498 +0,0 @@ -withTransformation(add_row_index('n', StartFrom::ONE)); - - $loader->load(rows(schema(int_schema('id')), row(['id' => 1])), $first); - $loader->load(rows(schema(int_schema('id')), row(['id' => 2])), $second); - - static::assertSame( - [[['id' => 1, 'n' => 1]], [['id' => 2, 'n' => 1]]], - array_map(static fn(Rows $rows): array => $rows->toArray(), $spy->loadedRows), - ); - static::assertSame([$first, $second], $spy->contexts); - } - - public function test_a_constructor_transformation_spans_the_whole_stream(): void - { - $spy = new SpyLoader(); - $context = flow_context(config()); - $sortById = new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df->sortBy([ref('id')])); - $loader = to_branch(lit(true), $spy, $sortById); - - foreach (RowsMother::descendingIdBatches() as $batch) { - $loader->load($batch, $context); - } - - $loader->closure($context); - - static::assertSame([6], $spy->loadedRowCounts()); - static::assertSame([0, 1, 2, 3, 4, 5], array_column($spy->loadedRowsToArray(), 'id')); - } - - public function test_a_drain_time_failure_rethrows_from_closure(): void - { - $failure = new RuntimeException('sink exploded'); - $sink = new ThrowingLoader($failure); - $context = flow_context(config()); - $loader = to_branch(lit(true), $sink)->withTransformation(new CallbackTransformation( - static fn(DataFrame $df): DataFrame => $df->collect(), - )); - - $loader->load(rows(schema(int_schema('id')), row(['id' => 1])), $context); - - static::assertSame(0, $sink->loadsCount); - - $thrown = null; - - try { - $loader->closure($context); - } catch (RuntimeException $e) { - $thrown = $e; - } - - static::assertSame($failure, $thrown); - - static::assertSame(1, $sink->loadsCount); - - // The throwing closure() must still have reset the stream - the next round on the same context starts fresh. - $loader->load(rows(schema(int_schema('id')), row(['id' => 2])), $context); - - $thrown = null; - - try { - $loader->closure($context); - } catch (RuntimeException $e) { - $thrown = $e; - } - - static::assertSame($failure, $thrown); - - static::assertSame(2, $sink->loadsCount); - } - - public function test_a_failed_drive_is_rebuilt_for_the_next_batch(): void - { - $failure = new RuntimeException('sink exploded'); - $sink = new ThrowingLoader($failure); - $context = flow_context(config()); - $loader = to_branch(lit(true), $sink)->withTransformation(select('id')); - - foreach ([1, 2] as $id) { - $thrown = null; - - try { - $loader->load(rows(schema(int_schema('id')), row(['id' => $id])), $context); - } catch (RuntimeException $e) { - $thrown = $e; - } - - static::assertSame($failure, $thrown); - } - - static::assertSame(2, $sink->loadsCount); - } - - public function test_a_fully_filtered_batch_produces_no_sink_calls(): void - { - $spy = new SpyLoader(); - $context = flow_context(config()); - $loader = to_branch(lit(false), $spy)->withTransformation(select('id')); - - $loader->load(rows(schema(int_schema('id')), row(['id' => 1])), $context); - $loader->load(rows(schema(int_schema('id')), row(['id' => 2])), $context); - $loader->closure($context); - - static::assertSame(0, $spy->loadsCount); - static::assertSame(1, $spy->closureCount); - } - - public function test_a_rebuilt_drive_does_not_re_report_the_same_runs_limit(): void - { - $telemetry = new MemoryTelemetryContext(telemetry_options(trace_loading: true)); - $sink = new ThrowingLoader(new LimitReachedException(1)); - $loader = to_branch(lit(true), $sink)->withTransformation(select('id')); - - $loader->load(rows(schema(int_schema('id')), row(['id' => 1])), $telemetry->flowContext); - $loader->load(rows(schema(int_schema('id')), row(['id' => 2])), $telemetry->flowContext); - - static::assertCount(1, $telemetry->logs->entriesContaining('Limit reached')); - static::assertEmpty($telemetry->logs->entriesContaining('Loading failed')); - } - - public function test_a_second_run_reports_its_own_limit(): void - { - $first = new MemoryTelemetryContext(telemetry_options(trace_loading: true)); - $second = new MemoryTelemetryContext(telemetry_options(trace_loading: true)); - $sink = new ThrowingLoader(new LimitReachedException(1)); - $loader = to_branch(lit(true), $sink)->withTransformation(select('id')); - - $loader->load(rows(schema(int_schema('id')), row(['id' => 1])), $first->flowContext); - $loader->load(rows(schema(int_schema('id')), row(['id' => 2])), $second->flowContext); - - static::assertCount(1, $first->logs->entriesContaining('Limit reached')); - static::assertCount(1, $second->logs->entriesContaining('Limit reached')); - static::assertEmpty($second->logs->entriesContaining('Loading failed')); - } - - public function test_a_streaming_transformation_delivers_per_batch(): void - { - $spy = new SpyLoader(); - $context = flow_context(config()); - $loader = to_branch(lit(true), $spy)->withTransformation(select('id')); - - $expected = 0; - - foreach (RowsMother::descendingIdBatches() as $batch) { - $loader->load($batch, $context); - - static::assertSame(++$expected, $spy->loadsCount); - } - } - - public function test_a_terminated_drive_skips_later_batches_and_still_closes_the_wrapped_loader(): void - { - $spy = new SpyLoader(); - $context = flow_context(config()); - $loader = to_branch(lit(true), $spy)->withTransformation(new CallbackTransformation( - static fn(DataFrame $df): DataFrame => $df->limit(2), - )); - - foreach ([1, 2, 3, 4] as $id) { - $loader->load(rows(schema(int_schema('id')), row(['id' => $id])), $context); - } - - $loader->closure($context); - - static::assertSame(2, $spy->loadsCount); - static::assertSame(1, $spy->closureCount); - } - - public function test_a_transformation_spans_the_whole_stream(): void - { - $spy = new SpyLoader(); - $context = flow_context(config()); - $sortById = new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df->sortBy([ref('id')])); - $loader = to_branch(lit(true), $spy)->withTransformation($sortById); - - foreach (RowsMother::descendingIdBatches() as $batch) { - $loader->load($batch, $context); - } - - $loader->closure($context); - - static::assertSame([6], $spy->loadedRowCounts()); - static::assertSame([0, 1, 2, 3, 4, 5], array_column($spy->loadedRowsToArray(), 'id')); - } - - public function test_a_triggering_transformation_is_refused(): void - { - $trigger = new CallbackTransformation(static function (DataFrame $df): DataFrame { - $df->count(); - - return $df; - }); - $loader = to_branch(lit(true), new SpyLoader())->withTransformation($trigger); - - try { - $loader->load(rows(schema(int_schema('id')), row(['id' => 1])), flow_context(config())); - - static::fail('Expected a Transformation triggering the nested frame to be refused.'); - } catch (InvalidLogicException $e) { - static::assertStringContainsString('must only build the DataFrame', $e->getMessage()); - } - } - - public function test_arming_a_transformation_mid_run_spans_only_the_remaining_batches(): void - { - $spy = new SpyLoader(); - $context = flow_context(config()); - $loader = to_branch(lit(true), $spy); - $batches = RowsMother::descendingIdBatches(); - $sortById = new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df->sortBy([ref('id')])); - - $loader->load($batches[0], $context); - $loader->withTransformation($sortById); - $loader->load($batches[1], $context); - $loader->load($batches[2], $context); - $loader->closure($context); - - static::assertSame([2, 4], $spy->loadedRowCounts()); - static::assertSame([5, 4, 0, 1, 2, 3], array_column($spy->loadedRowsToArray(), 'id')); - } - - public function test_closure_after_a_declined_drain_failure_closes_the_wrapped_loader(): void - { - $spy = new SpyLoader(); - $context = flow_context(config())->setErrorHandler(ignore_error_handler()); - $throwOnDrain = - new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df->collect()->with(new ThrowingTransformer( - new RuntimeException('boom'), - ))); - $loader = to_branch(lit(true), $spy)->withTransformation($throwOnDrain); - - $loader->load(rows(schema(int_schema('id')), row(['id' => 1])), $context); - $loader->closure($context); - - static::assertSame(0, $spy->loadsCount); - static::assertSame(1, $spy->closureCount); - } - - public function test_closure_reports_a_drain_failure_as_a_loading_error(): void - { - $handler = new RecordingErrorHandler(); - $context = flow_context(config())->setErrorHandler($handler); - $loader = to_branch( - lit(true), - new SpyLoader(), - )->withTransformation(new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df->collect()->with(new ThrowingTransformer( - new RuntimeException('boom'), - )))); - - $loader->load(rows(schema(int_schema('id')), row(['id' => 1])), $context); - $loader->closure($context); - - static::assertCount(1, $handler->errors); - static::assertInstanceOf(LoadingError::class, $handler->errors[0]); - static::assertSame($loader, $handler->errors[0]->loader); - static::assertSame('boom', $handler->errors[0]->cause->getMessage()); - } - - public function test_closure_rethrows_a_drain_failure_under_skip_rows(): void - { - $context = flow_context(config())->setErrorHandler(skip_rows_handler()); - $loader = to_branch( - lit(true), - new SpyLoader(), - )->withTransformation(new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df->collect()->with(new ThrowingTransformer( - new RuntimeException('boom'), - )))); - - $loader->load(rows(schema(int_schema('id')), row(['id' => 1])), $context); - - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('boom'); - - $loader->closure($context); - } - - public function test_closure_for_a_new_run_does_not_drain_a_dead_runs_drive(): void - { - $dead = flow_context(config()); - $next = flow_context(config()); - $spy = new SpyLoader(); - $loader = to_branch(lit(true), $spy)->withTransformation(new CallbackTransformation( - static fn(DataFrame $df): DataFrame => $df->collect(), - )); - - // Run 1 buffers a batch in the stream and dies without closure(); run 2 routes no batches to this loader. - $loader->load(rows(schema(int_schema('id')), row(['id' => 1])), $dead); - $loader->closure($next); - - static::assertSame(0, $spy->loadsCount); - static::assertSame(1, $spy->closureCount); - } - - public function test_closure_is_forwarded_to_the_wrapped_loader(): void - { - $spy = new SpyLoader(); - $context = flow_context(config()); - - to_branch(lit(true), $spy)->closure($context); - - static::assertSame(1, $spy->closureCount); - static::assertSame([$context], $spy->closureContexts); - } - - public function test_closure_resets_the_drive_for_the_next_run_on_the_same_context(): void - { - $spy = new SpyLoader(); - $context = flow_context(config()); - $loader = to_branch(lit(true), $spy)->withTransformation(add_row_index('n', StartFrom::ONE)); - - $loader->load(rows(schema(int_schema('id')), row(['id' => 1])), $context); - $loader->load(rows(schema(int_schema('id')), row(['id' => 2])), $context); - $loader->closure($context); - $loader->load(rows(schema(int_schema('id')), row(['id' => 3])), $context); - - static::assertSame( - [[['id' => 1, 'n' => 1]], [['id' => 2, 'n' => 2]], [['id' => 3, 'n' => 1]]], - array_map(static fn(Rows $rows): array => $rows->toArray(), $spy->loadedRows), - ); - } - - public function test_limit_reached_is_reported_once_per_loader(): void - { - $telemetry = new MemoryTelemetryContext(telemetry_options(trace_loading: true)); - $loader = to_branch(lit(true), new ThrowingLoader(new LimitReachedException(1))); - $batch = rows(schema(int_schema('id')), row(['id' => 1])); - - $loader->load($batch, $telemetry->flowContext); - $loader->load($batch, $telemetry->flowContext); - $loader->load($batch, $telemetry->flowContext); - - static::assertCount(1, $telemetry->logs->entriesContaining('Limit reached')); - static::assertEmpty($telemetry->logs->entriesContaining('Loading failed')); - } - - public function test_loading_rows_counts_the_rows_offered_to_the_branch(): void - { - $telemetry = new MemoryTelemetryContext(telemetry_options(trace_loading: true)); - $loader = to_branch(ref('id')->greaterThanEqual(lit(2)), new SpyLoader()); - - // Input 2 rows, 0 after the filter - the attribute counts the offer, not the post-filter delivery. - $loader->load(RowsMother::descendingIdBatches()[2], $telemetry->flowContext); - - $spans = $telemetry->spans->endedSpans(); - - static::assertCount(1, $spans); - static::assertSame('BranchingLoader', $spans[0]->name()); - static::assertSame(2, $spans[0]->attributes()['flow.etl.loading.rows']); - } - - public function test_replacing_the_transformation_mid_run_keeps_the_drive_built_first(): void - { - $spy = new SpyLoader(); - $context = flow_context(config()); - $batches = RowsMother::descendingIdBatches(); - $sortById = new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df->sortBy([ref('id')])); - $loader = to_branch(lit(true), $spy)->withTransformation($sortById); - - $loader->load($batches[0], $context); - $loader->withTransformation(select('id')); - $loader->load($batches[1], $context); - $loader->load($batches[2], $context); - $loader->closure($context); - - static::assertSame([6], $spy->loadedRowCounts()); - static::assertSame([0, 1, 2, 3, 4, 5], array_column($spy->loadedRowsToArray(), 'id')); - } - - public function test_replay_safe_is_false_with_a_constructor_transformation(): void - { - static::assertFalse(to_branch(lit(true), new SpyLoader(), select('id'))->replaySafe()); - } - - public function test_replay_safe_only_without_a_transformation(): void - { - $loader = to_branch(lit(true), new SpyLoader()); - - static::assertTrue($loader->replaySafe()); - - $loader->withTransformation(select('id')); - - static::assertFalse($loader->replaySafe()); - } - - public function test_rows_matching_the_condition_reach_the_wrapped_loader(): void - { - $spy = new SpyLoader(); - $context = flow_context(config()); - $loader = to_branch(ref('id')->greaterThanEqual(lit(2)), $spy); - - foreach (RowsMother::descendingIdBatches() as $batch) { - $loader->load($batch, $context); - } - - static::assertSame(3, $spy->loadsCount); - static::assertSame([2, 2, 0], $spy->loadedRowCounts()); - static::assertSame([5, 4, 3, 2], array_column($spy->loadedRowsToArray(), 'id')); - } - - public function test_the_condition_filters_before_the_transformation(): void - { - $spy = new SpyLoader(); - $context = flow_context(config()); - $loader = to_branch(ref('id')->greaterThanEqual(lit(2)), $spy); - $loader->withTransformation(add_row_index('n', StartFrom::ONE)); - - foreach (RowsMother::descendingIdBatches() as $batch) { - $loader->load($batch, $context); - } - - $loader->closure($context); - - static::assertSame( - [['id' => 5, 'n' => 1], ['id' => 4, 'n' => 2], ['id' => 3, 'n' => 3], ['id' => 2, 'n' => 4]], - $spy->loadedRowsToArray(), - ); - } - - public function test_the_nested_frame_is_built_once_per_loader(): void - { - $transformCalls = 0; - $context = flow_context(config()); - $counting = new CallbackTransformation(static function (DataFrame $df) use (&$transformCalls): DataFrame { - ++$transformCalls; - - return $df->select('id'); - }); - $loader = to_branch(lit(true), new SpyLoader())->withTransformation($counting); - - foreach (RowsMother::descendingIdBatches() as $batch) { - $loader->load($batch, $context); - } - - static::assertSame(1, $transformCalls); - } - - public function test_with_transformation_overrides_the_constructor_transformation(): void - { - $spy = new SpyLoader(); - $context = flow_context(config()); - $sortById = new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df->sortBy([ref('id')])); - $loader = to_branch(lit(true), $spy, $sortById)->withTransformation(select('id')); - - foreach (RowsMother::descendingIdBatches() as $batch) { - $loader->load($batch, $context); - } - - $loader->closure($context); - - static::assertSame([2, 2, 2], $spy->loadedRowCounts()); - static::assertSame([5, 4, 3, 2, 1, 0], array_column($spy->loadedRowsToArray(), 'id')); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/LoaderTreeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/LoaderTreeTest.php deleted file mode 100644 index f294fd757c..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/LoaderTreeTest.php +++ /dev/null @@ -1,72 +0,0 @@ -flatten($root)); - } - - public function test_flattening_a_loader_that_overrides_itself(): void - { - $loader = new WrappingLoader(); - $loader->wrapped = [$loader]; - - static::assertSame([$loader], (new LoaderTree())->flatten($loader)); - } - - public function test_flattening_a_loader_wrapping_many_loaders(): void - { - $first = new SpyLoader(); - $second = new SpyLoader(); - $root = new WrappingLoader($first, $second); - - static::assertSame([$root, $first, $second], (new LoaderTree())->flatten($root)); - } - - public function test_flattening_a_plain_loader(): void - { - $loader = new SpyLoader(); - - static::assertSame([$loader], (new LoaderTree())->flatten($loader)); - } - - public function test_flattening_a_wrapper_that_overrides_nobody(): void - { - $root = new WrappingLoader(); - - static::assertSame([$root], (new LoaderTree())->flatten($root)); - } - - public function test_flattening_nested_wrappers(): void - { - $innermost = new SpyLoader(); - $middle = new WrappingLoader($innermost); - $root = new WrappingLoader($middle); - - static::assertSame([$root, $middle, $innermost], (new LoaderTree())->flatten($root)); - } - - public function test_flattening_two_loaders_pointing_at_each_other(): void - { - $first = new WrappingLoader(); - $second = new WrappingLoader($first); - $first->wrapped = [$second]; - - static::assertSame([$first, $second], (new LoaderTree())->flatten($first)); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/RetryLoaderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/RetryLoaderTest.php deleted file mode 100644 index 9a09b17ef7..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/RetryLoaderTest.php +++ /dev/null @@ -1,350 +0,0 @@ -> */ - public array $loadedRows = []; - - public int $loads = 0; - - public function load(Rows $rows, FlowContext $context): void - { - if (++$this->loads === 1) { - throw new RuntimeException('Simulated transient failure on the first attempt'); - } - - $this->loadedRows[] = $rows->toArray(); - } - }; - $sleep = new FakeSleep(); - - write_with_retries(loader: to_branch(lit(true), $flaky), sleep: $sleep)->load( - rows(schema(int_schema('id')), row(['id' => 1])), - flow_context(config()), - ); - - static::assertSame([[['id' => 1]]], $flaky->loadedRows); - static::assertSame(1, $sleep->sleepCount()); - } - - public function test_a_raw_transformer_wrap_is_still_refused(): void - { - $spy = new SpyLoader(); - $sleep = new FakeSleep(); - $retry = write_with_retries( - loader: to_transformation(new ScalarFunctionFilterTransformer(lit(true)), $spy), - sleep: $sleep, - ); - - try { - $retry->load(rows(schema(int_schema('id')), row(['id' => 1])), flow_context(config())); - - static::fail('Expected the raw-Transformer wrap to be refused.'); - } catch (InvalidLogicException $e) { - static::assertStringContainsString('RetryLoader cannot wrap this loader', $e->getMessage()); - } - - static::assertSame(0, $sleep->sleepCount()); - static::assertSame(0, $spy->loadsCount); - } - - public function test_a_transformation_armed_after_construction_is_refused_at_load(): void - { - $spy = new SpyLoader(); - $branch = to_branch(lit(true), $spy); - $sleep = new FakeSleep(); - $retry = write_with_retries(loader: $branch, sleep: $sleep); - - $retry->load(rows(schema(int_schema('id')), row(['id' => 1])), $context = flow_context(config())); - $branch->withTransformation(new CallbackTransformation( - static fn(DataFrame $dataFrame): DataFrame => $dataFrame->collect(), - )); - - try { - $retry->load(rows(schema(int_schema('id')), row(['id' => 2])), $context); - - static::fail('Expected the armed transformation to be refused.'); - } catch (InvalidLogicException $e) { - static::assertStringContainsString('RetryLoader cannot wrap this loader', $e->getMessage()); - } - - // Never entered the retry loop, so this is not a FailedRetryException path. - static::assertSame(0, $sleep->sleepCount()); - static::assertSame(1, $spy->loadsCount); - } - - public function test_a_transformation_wrapped_loader_is_refused_at_load(): void - { - $spy = new SpyLoader(); - $sleep = new FakeSleep(); - $retry = write_with_retries(loader: to_transformation(select('id'), $spy), sleep: $sleep); - - try { - $retry->load(rows(schema(int_schema('id')), row(['id' => 1])), flow_context(config())); - - static::fail('Expected the transformation-wrapped loader to be refused.'); - } catch (InvalidLogicException $e) { - static::assertStringContainsString('RetryLoader cannot wrap this loader', $e->getMessage()); - } - - static::assertSame(0, $sleep->sleepCount()); - static::assertSame(0, $spy->loadsCount); - } - - public function test_a_transformation_wrapped_loader_nested_below_a_replay_safe_wrapper_is_refused(): void - { - $spy = new SpyLoader(); - $sleep = new FakeSleep(); - $retry = write_with_retries(loader: to_branch(lit(true), to_transformation(select('id'), $spy)), sleep: $sleep); - - try { - $retry->load(rows(schema(int_schema('id')), row(['id' => 1])), flow_context(config())); - - static::fail('Expected the nested transformation-wrapped loader to be refused.'); - } catch (InvalidLogicException $e) { - static::assertStringContainsString('RetryLoader cannot wrap this loader', $e->getMessage()); - } - - static::assertSame(0, $sleep->sleepCount()); - static::assertSame(0, $spy->loadsCount); - } - - public function test_closure_is_a_no_op_for_a_loader_that_is_not_closure_aware(): void - { - $output = []; - - write_with_retries(new ArrayLoader($output))->closure(flow_context(config())); - - static::assertSame([], $output); - } - - public function test_closure_is_forwarded_to_the_wrapped_loader(): void - { - $context = flow_context(config()); - $spy = new SpyLoader(); - $loader = write_with_retries($spy); - - $loader->load(rows(schema(int_schema('id')), row(['id' => 1])), $context); - $loader->closure($context); - - static::assertSame(1, $spy->loadsCount); - static::assertSame(1, $spy->closureCount); - static::assertSame([$context], $spy->closureContexts); - } - - public function test_closure_is_not_covered_by_the_retry_strategy(): void - { - $failingLoader = new class() implements Closure, Loader { - public int $closureCount = 0; - - public function closure(FlowContext $context): void - { - $this->closureCount++; - - throw new RuntimeException('Commit failed'); - } - - public function load(Rows $rows, FlowContext $context): void {} - }; - - $sleep = new FakeSleep(); - - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('Commit failed'); - - try { - write_with_retries(loader: $failingLoader, sleep: $sleep)->closure(flow_context(config())); - } finally { - static::assertSame(1, $failingLoader->closureCount); - static::assertSame(0, $sleep->sleepCount()); - } - } - - public function test_exposing_the_wrapped_loader(): void - { - $spy = new SpyLoader(); - - static::assertSame([$spy], write_with_retries($spy)->loaders()); - } - - public function test_exhausting_all_retries(): void - { - $mockLoader = $this->createMock(Loader::class); - $rows = rows(schema()); - $context = flow_context(config()); - $sleep = new FakeSleep(); - - $exception = new RuntimeException('Persistent error'); - $mockLoader - ->expects(self::exactly(4)) // 1 initial + 3 retries - ->method('load') - ->with($rows, $context) - ->willThrowException($exception); - - $retryLoader = write_with_retries( - $mockLoader, - retry_any_throwable(3), - delay_fixed(duration_milliseconds(100)), - $sleep, - ); - - $this->expectException(FailedRetryException::class); - $this->expectExceptionMessage('Retry failed after 4 attempts.'); - - $retryLoader->load($rows, $context); - - static::assertSame(3, $sleep->sleepCount()); - static::assertSame(300, $sleep->totalMilliseconds()); - } - - public function test_retry_loader_does_not_create_duplicates_retries_same_rows(): void - { - $mockLoader = new class() implements Loader { - /** @var array> */ - public array $loadedRows = []; - - public int $loads = 0; - - public function load(Rows $rows, FlowContext $context): void - { - $this->loads++; - - if ($this->loads === 2) { - throw new RuntimeException('Simulated transient failure on attempt 2'); - } - - $this->loadedRows[] = $rows->toArray(); - } - }; - - $context = flow_context(config()); - $sleep = new FakeSleep(); - - $retryLoader = write_with_retries(loader: $mockLoader, sleep: $sleep); - - $retryLoader->load(rows(schema(int_schema('id')), row(['id' => 1])), $context); - $retryLoader->load(rows(schema(int_schema('id')), row(['id' => 2])), $context); - $retryLoader->load(rows(schema(int_schema('id')), row(['id' => 3])), $context); - - static::assertCount(3, $mockLoader->loadedRows); - static::assertEquals( - [ - [['id' => 1]], - [['id' => 2]], - [['id' => 3]], - ], - $mockLoader->loadedRows, - ); - static::assertSame(4, $mockLoader->loads); - } - - public function test_retry_on_transient_failure_that_succeeds(): void - { - $mockLoader = $this->createMock(Loader::class); - $rows = rows(schema()); - $context = flow_context(config()); - $sleep = new FakeSleep(); - - $callCount = 0; - $mockLoader - ->expects(self::exactly(2)) - ->method('load') - ->with($rows, $context) - ->willReturnCallback(function () use (&$callCount): void { - $callCount++; - - if ($callCount === 1) { - throw new RuntimeException('Transient error'); - } - }); - - $retryLoader = write_with_retries( - $mockLoader, - retry_any_throwable(3), - delay_fixed(duration_milliseconds(100)), - $sleep, - ); - - $retryLoader->load($rows, $context); - - static::assertSame(1, $sleep->sleepCount()); - static::assertSame(100, $sleep->totalMilliseconds()); - } - - public function test_retry_strategy_determining_not_to_retry(): void - { - $mockLoader = $this->createMock(Loader::class); - $rows = rows(schema()); - $context = flow_context(config()); - $sleep = new FakeSleep(); - - $exception = new LogicException('Logic error'); - $mockLoader->expects(self::once())->method('load')->with($rows, $context)->willThrowException($exception); - - $retryLoader = write_with_retries( - $mockLoader, - new OnExceptionTypes([RuntimeException::class], 3), - delay_fixed(duration_milliseconds(100)), - $sleep, - ); - - $this->expectException(FailedRetryException::class); - $this->expectExceptionMessage('Retry failed after 1 attempts.'); - - $retryLoader->load($rows, $context); - - static::assertSame(0, $sleep->sleepCount()); - } - - public function test_successful_load_without_retries(): void - { - $mockLoader = $this->createMock(Loader::class); - $rows = rows(schema()); - $context = flow_context(config()); - - $mockLoader->expects(self::once())->method('load')->with($rows, $context); - - $retryLoader = write_with_retries($mockLoader, retry_any_throwable(3), delay_fixed(duration_milliseconds(100))); - - $retryLoader->load($rows, $context); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/TransformerLoaderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/TransformerLoaderTest.php deleted file mode 100644 index 67b714f10a..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/TransformerLoaderTest.php +++ /dev/null @@ -1,555 +0,0 @@ -setErrorHandler(ignore_error_handler()); - $spy = new SpyLoader(); - $loader = to_transformation(new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df->with( - new ThrowWhenRowMatches('id', 1, new RuntimeException('boom')), - )), $spy); - - $thrown = null; - - try { - $loader->load(rows(schema(int_schema('id')), row(['id' => 1])), $context); - } catch (RuntimeException $e) { - $thrown = $e; - } - - static::assertInstanceOf(RuntimeException::class, $thrown); - static::assertSame('boom', $thrown->getMessage()); - - $loader->load(rows(schema(int_schema('id')), row(['id' => 2])), $context); - $loader->closure($context); - - static::assertSame( - [[['id' => 2]]], - array_map(static fn(Rows $rows): array => $rows->toArray(), $spy->loadedRows), - ); - static::assertSame(1, $spy->closureCount); - } - - public function test_a_new_flow_context_starts_a_fresh_drive_after_a_failed_run(): void - { - $failed = flow_context(config()); - $next = flow_context(config()); - $spy = new SpyLoader(); - $loader = to_transformation(new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df->with( - new ThrowWhenRowMatches('id', 1, new RuntimeException('boom')), - )), $spy); - - $thrown = null; - - try { - $loader->load(rows(schema(int_schema('id')), row(['id' => 1])), $failed); - } catch (RuntimeException $e) { - $thrown = $e; - } - - static::assertInstanceOf(RuntimeException::class, $thrown); - static::assertSame('boom', $thrown->getMessage()); - - $loader->load(rows(schema(int_schema('id')), row(['id' => 2])), $next); - $loader->closure($next); - - static::assertSame( - [[['id' => 2]]], - array_map(static fn(Rows $rows): array => $rows->toArray(), $spy->loadedRows), - ); - static::assertSame([$next], $spy->contexts); - } - - public function test_a_batch_from_a_new_run_does_not_reuse_a_suspended_drive(): void - { - $first = flow_context(config()); - $second = flow_context(config()); - $spy = new SpyLoader(); - $loader = to_transformation(add_row_index('n', StartFrom::ONE), $spy); - - // Run 1 dies via a sibling step, so closure() never runs and the stream is left suspended, not dropped. - $loader->load(rows(schema(int_schema('id')), row(['id' => 1])), $first); - $loader->load(rows(schema(int_schema('id')), row(['id' => 2])), $second); - - static::assertSame( - [[['id' => 1, 'n' => 1]], [['id' => 2, 'n' => 1]]], - array_map(static fn(Rows $rows): array => $rows->toArray(), $spy->loadedRows), - ); - static::assertSame([$first, $second], $spy->contexts); - } - - public function test_a_terminated_drive_skips_later_batches_and_still_closes_the_wrapped_loader(): void - { - $context = flow_context(config()); - $spy = new SpyLoader(); - $loader = to_transformation(new CallbackTransformation( - static fn(DataFrame $df): DataFrame => $df->limit(2), - ), $spy); - - for ($id = 1; $id <= 4; $id++) { - $loader->load(rows(schema(int_schema('id')), row(['id' => $id])), $context); - } - - $loader->closure($context); - - static::assertSame(2, $spy->loadsCount); - static::assertSame([1, 1], $spy->loadedRowCounts()); - static::assertSame(1, $spy->closureCount); - } - - public function test_closure_for_a_new_run_does_not_drain_a_dead_runs_drive(): void - { - $dead = flow_context(config()); - $next = flow_context(config()); - $spy = new SpyLoader(); - $loader = to_transformation(new CallbackTransformation( - static fn(DataFrame $df): DataFrame => $df->collect(), - ), $spy); - - // Run 1 buffers a batch in the stream and dies without closure(); run 2 routes no batches to this loader. - $loader->load(rows(schema(int_schema('id')), row(['id' => 1])), $dead); - $loader->closure($next); - - static::assertSame(0, $spy->loadsCount); - static::assertSame(1, $spy->closureCount); - } - - public function test_closure_after_a_declined_drain_failure_closes_the_wrapped_loader(): void - { - $context = flow_context(config())->setErrorHandler(ignore_error_handler()); - $spy = new SpyLoader(); - $loader = to_transformation( - new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df->collect()->with(new ThrowingTransformer( - new RuntimeException('boom'), - ))), - $spy, - ); - - $loader->load(rows(schema(int_schema('id')), row(['id' => 1])), $context); - $loader->closure($context); - - static::assertSame(0, $spy->loadsCount); - static::assertSame(1, $spy->closureCount); - } - - public function test_a_drain_time_failure_rethrows_from_closure(): void - { - $context = flow_context(config()); - $throwing = new ThrowingLoader($failure = new RuntimeException('boom')); - $loader = to_transformation(new CallbackTransformation( - static fn(DataFrame $df): DataFrame => $df->collect(), - ), $throwing); - - $loader->load(rows(schema(int_schema('id')), row(['id' => 1])), $context); - $loader->load(rows(schema(int_schema('id')), row(['id' => 2])), $context); - - static::assertSame(0, $throwing->loadsCount); - - $thrown = null; - - try { - $loader->closure($context); - } catch (RuntimeException $e) { - $thrown = $e; - } - - static::assertSame($failure, $thrown); - - static::assertSame(1, $throwing->loadsCount); - - $loader->load(rows(schema(int_schema('id')), row(['id' => 3])), $context); - - $thrown = null; - - try { - $loader->closure($context); - } catch (RuntimeException $e) { - $thrown = $e; - } - - static::assertSame($failure, $thrown); - - static::assertSame(2, $throwing->loadsCount); - } - - public function test_a_failed_drive_is_rebuilt_for_the_next_batch(): void - { - // The dead fiber is dropped, so the loader stays usable: the batch offered after a failure reaches a fresh - // stream and the destination again. Without this a RetryLoader could never re-offer a batch. - $context = flow_context(config()); - $throwing = new ThrowingLoader($failure = new RuntimeException('boom')); - $loader = to_transformation(select('id'), $throwing); - - foreach ([1, 2] as $id) { - $thrown = null; - - try { - $loader->load(rows(schema(int_schema('id')), row(['id' => $id])), $context); - } catch (RuntimeException $e) { - $thrown = $e; - } - - static::assertSame($failure, $thrown); - } - - static::assertSame(2, $throwing->loadsCount); - } - - public function test_a_declined_failure_keeps_loading_into_the_next_loader_like_a_plain_loader(): void - { - // skipLoader declines one sink's failure, not the batch: the loader after this one still receives it - - // exactly what a plain loader's declined failure does. - $tail = new SpyLoader(); - - df() - ->read(from_array([['id' => 1], ['id' => 2], ['id' => 3]])) - ->batchSize(1) - ->onError(ignore_error_handler()) - ->write(to_transformation(new ThrowWhenRowMatches('id', 2, new RuntimeException('boom')), new SpyLoader())) - ->write($tail) - ->run(); - - static::assertSame([1, 2, 3], array_column($tail->loadedRowsToArray(), 'id')); - } - - public function test_closure_reports_a_drain_failure_as_a_loading_error(): void - { - $handler = new RecordingErrorHandler(); - $context = flow_context(config())->setErrorHandler($handler); - $loader = to_transformation( - new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df->collect()->with(new ThrowingTransformer( - new RuntimeException('boom'), - ))), - new SpyLoader(), - ); - - $loader->load(rows(schema(int_schema('id')), row(['id' => 1])), $context); - $loader->closure($context); - - static::assertCount(1, $handler->errors); - static::assertInstanceOf(LoadingError::class, $handler->errors[0]); - static::assertSame($loader, $handler->errors[0]->loader); - static::assertSame('boom', $handler->errors[0]->cause->getMessage()); - } - - public function test_closure_rethrows_a_drain_failure_under_skip_rows(): void - { - $context = flow_context(config())->setErrorHandler(skip_rows_handler()); - $loader = to_transformation( - new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df->collect()->with(new ThrowingTransformer( - new RuntimeException('boom'), - ))), - new SpyLoader(), - ); - - $loader->load(rows(schema(int_schema('id')), row(['id' => 1])), $context); - - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('boom'); - - $loader->closure($context); - } - - public function test_a_failed_run_does_not_close_the_wrapped_loader(): void - { - // Req 3, pinned where it actually holds: Segment propagates the failure before reaching its closure loop - // (Segment.php:98 vs :119), so no loader in the segment is closed. - $spy = new SpyLoader(); - - $thrown = null; - - try { - df() - ->read(from_array([['id' => 1], ['id' => 2]])) - ->write(to_transformation(new ThrowingTransformer(new RuntimeException('boom')), $spy)) - ->run(); - } catch (RuntimeException $e) { - $thrown = $e; - } - - static::assertInstanceOf(RuntimeException::class, $thrown); - static::assertSame('boom', $thrown->getMessage()); - - static::assertSame(0, $spy->closureCount); - static::assertSame(0, $spy->loadsCount); - } - - public function test_closure_drains_the_output_a_blocking_operation_buffered(): void - { - $context = flow_context(config()); - $spy = new SpyLoader(); - $loader = to_transformation(new CallbackTransformation( - static fn(DataFrame $df): DataFrame => $df->collect(), - ), $spy); - - for ($id = 1; $id <= 3; $id++) { - $loader->load(rows(schema(int_schema('id')), row(['id' => $id])), $context); - } - - static::assertSame(0, $spy->loadsCount); - - $loader->closure($context); - - static::assertSame(1, $spy->loadsCount); - static::assertSame(1, $spy->closureCount); - static::assertSame( - [[['id' => 1], ['id' => 2], ['id' => 3]]], - array_map(static fn(Rows $rows): array => $rows->toArray(), $spy->loadedRows), - ); - } - - public function test_a_rebuilt_drive_does_not_re_report_the_same_runs_limit(): void - { - $telemetry = new MemoryTelemetryContext(telemetry_options(trace_loading: true)); - $loader = to_transformation(select('id'), new ThrowingLoader(new LimitReachedException(1))); - - // The first load drops the stream; the second arrives on the SAME run, rebuilds it, and the sink throws again. - // One logical limit event, so exactly one report. - $loader->load(rows(schema(int_schema('id')), row(['id' => 1])), $telemetry->flowContext); - $loader->load(rows(schema(int_schema('id')), row(['id' => 2])), $telemetry->flowContext); - - static::assertCount(1, $telemetry->logs->entriesContaining('Limit reached')); - static::assertEmpty($telemetry->logs->entriesContaining('Loading failed')); - } - - public function test_a_second_run_reports_its_own_limit(): void - { - $first = new MemoryTelemetryContext(telemetry_options(trace_loading: true)); - $second = new MemoryTelemetryContext(telemetry_options(trace_loading: true)); - $loader = to_transformation(select('id'), new ThrowingLoader(new LimitReachedException(1))); - - // Run 1 dies without closure(), so only the run-change check can re-arm reporting for run 2. - $loader->load(rows(schema(int_schema('id')), row(['id' => 1])), $first->flowContext); - $loader->load(rows(schema(int_schema('id')), row(['id' => 2])), $second->flowContext); - - static::assertCount(1, $first->logs->entriesContaining('Limit reached')); - static::assertCount(1, $second->logs->entriesContaining('Limit reached')); - static::assertEmpty($second->logs->entriesContaining('Loading failed')); - } - - public function test_a_transformer_loader_is_never_replay_safe(): void - { - static::assertFalse(to_transformation(select('id'), new SpyLoader())->replaySafe()); - static::assertFalse(to_transformation(new LimitTransformer(1), new SpyLoader())->replaySafe()); - } - - public function test_limit_reached_is_reported_once_per_loader(): void - { - $context = new MemoryTelemetryContext(telemetry_options(trace_loading: true)); - - $loader = to_transformation(new LimitTransformer(1), to_memory(new ArrayMemory())); - $batch = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])); - - $loader->load($batch, $context->flowContext); - $loader->load($batch, $context->flowContext); - $loader->load($batch, $context->flowContext); - - static::assertCount(1, $context->logs->entriesContaining('Limit reached')); - static::assertEmpty($context->logs->entriesContaining('Loading failed')); - - $endedSpans = $context->spans->endedSpans(); - - // MemoryLoader runs only on the first call; the other two throw before reaching it. - static::assertSame( - ['MemoryLoader', 'TransformerLoader', 'TransformerLoader', 'TransformerLoader'], - array_map(static fn(Span $span): string => $span->name(), $endedSpans), - ); - - foreach ($endedSpans as $span) { - static::assertNull($span->status()); - } - } - - public function test_closure_rebuilds_the_transformation_against_the_next_context(): void - { - $first = new MemoryTelemetryContext(telemetry_options(trace_loading: true)); - $second = new MemoryTelemetryContext(telemetry_options(trace_loading: true)); - - $loader = to_transformation(select('id'), to_memory(new ArrayMemory())); - - $loader->load(rows(schema(int_schema('id')), row(['id' => 1])), $first->flowContext); - $loader->closure($first->flowContext); - $loader->load(rows(schema(int_schema('id')), row(['id' => 2])), $second->flowContext); - - $memoryLoaderSpans = static fn(MemoryTelemetryContext $context): int => count(array_filter( - $context->spans->endedSpans(), - static fn(Span $span): bool => $span->name() === 'MemoryLoader', - )); - - static::assertSame(1, $memoryLoaderSpans($first)); - static::assertSame(1, $memoryLoaderSpans($second)); - } - - public function test_closure_resets_stateful_transformation_state(): void - { - $context = flow_context(config()); - $spy = new SpyLoader(); - $loader = to_transformation(add_row_index('n', StartFrom::ONE), $spy); - - $loader->load(rows(schema(int_schema('id')), row(['id' => 1])), $context); - $loader->load(rows(schema(int_schema('id')), row(['id' => 2])), $context); - $loader->closure($context); - $loader->load(rows(schema(int_schema('id')), row(['id' => 3])), $context); - - static::assertSame( - [[['id' => 1, 'n' => 1]], [['id' => 2, 'n' => 2]], [['id' => 3, 'n' => 1]]], - array_map(static fn(Rows $rows): array => $rows->toArray(), $spy->loadedRows), - ); - } - - public function test_stateful_loader_is_closed_once_across_batches(): void - { - $context = flow_context(config()); - $spy = new SpyLoader(); - $loader = to_transformation(select('id'), $spy); - - for ($id = 1; $id <= 3; $id++) { - $loader->load(rows(schema(int_schema('id')), row(['id' => $id])), $context); - } - - $loader->closure($context); - - static::assertSame(3, $spy->loadsCount); - static::assertSame(1, $spy->closureCount); - static::assertSame( - [[['id' => 1]], [['id' => 2]], [['id' => 3]]], - array_map(static fn(Rows $rows): array => $rows->toArray(), $spy->loadedRows), - ); - } - - public function test_stateful_transformation_keeps_state_across_batches(): void - { - $context = flow_context(config()); - $spy = new SpyLoader(); - $loader = to_transformation(add_row_index('n', StartFrom::ONE), $spy); - - for ($id = 1; $id <= 3; $id++) { - $loader->load(rows(schema(int_schema('id')), row(['id' => $id])), $context); - } - - static::assertSame(3, $spy->loadsCount); - static::assertSame( - [[['id' => 1, 'n' => 1]], [['id' => 2, 'n' => 2]], [['id' => 3, 'n' => 3]]], - array_map(static fn(Rows $rows): array => $rows->toArray(), $spy->loadedRows), - ); - } - - public function test_stateless_transformation_applies_to_every_batch(): void - { - $context = flow_context(config()); - $spy = new SpyLoader(); - $loader = to_transformation(select('id'), $spy); - - for ($id = 1; $id <= 3; $id++) { - $loader->load( - rows(schema(int_schema('id'), str_schema('name')), row(['id' => $id, 'name' => 'name-' . $id])), - $context, - ); - } - - static::assertSame(3, $spy->loadsCount); - static::assertSame( - [[['id' => 1]], [['id' => 2]], [['id' => 3]]], - array_map(static fn(Rows $rows): array => $rows->toArray(), $spy->loadedRows), - ); - } - - public function test_transformer_loader(): void - { - $transformerMock = $this->createMock(Transformer::class); - $transformerMock->expects(self::once())->method('transform')->willReturn(rows(schema())); - - $loaderMock = $this->createMock(Loader::class); - $loaderMock->expects(self::once())->method('load'); - - $transformer = to_transformation($transformerMock, $loaderMock); - - $transformer->load(rows(schema()), flow_context(config())); - } - - public function test_transformer_loader_with_transformation(): void - { - df() - ->read(from_array([ - ['id' => 1], - ['id' => 2], - ['id' => 3], - ])) - ->write(to_transformation(new class implements Transformation { - public function transform(DataFrame $dataFrame): DataFrame - { - return $dataFrame->withEntry('id_string', ref('id')->cast(type_string())); - } - }, to_memory($memory = new ArrayMemory()))) - ->run(); - - static::assertEquals( - [ - ['id' => 1, 'id_string' => '1'], - ['id' => 2, 'id_string' => '2'], - ['id' => 3, 'id_string' => '3'], - ], - $memory->dump(), - ); - } - - public function test_wrapped_loader_receives_the_outer_flow_context(): void - { - $context = flow_context(config()); - $spy = new SpyLoader(); - $loader = to_transformation(select('id'), $spy); - - $loader->load(rows(schema(int_schema('id')), row(['id' => 1])), $context); - - static::assertSame([$context], $spy->contexts); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/FilterWalkTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/FilterWalkTest.php new file mode 100644 index 0000000000..b1f9030bbf --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/FilterWalkTest.php @@ -0,0 +1,330 @@ +reachedByEveryConsumer($filter, NodeMother::select($filter), $filter)); + } + + public function test_a_consumer_bypassing_the_filter_is_not_reached(): void + { + $read = NodeMother::read(); + $filter = new Filter($read, lit(true)); + + static::assertFalse((new FilterWalk())->reachedByEveryConsumer( + $filter, + NodeMother::select($filter), + NodeMother::limit($read, 5), + )); + } + + public function test_a_chain_that_never_reaches_the_filter_is_not_reached(): void + { + $filter = new Filter(NodeMother::read(), lit(true)); + + static::assertFalse((new FilterWalk())->reachedByEveryConsumer( + $filter, + NodeMother::select(NodeMother::read()), + )); + } + + public function test_a_transparent_preserving_chain_reaches_the_leaf(): void + { + $read = NodeMother::read(); + + static::assertNotNull((new FilterWalk())->predicateAtLeaf( + new Filter(NodeMother::select($read), lit(true)), + $read, + ref('year')->isNotNull(), + )); + } + + public function test_another_filter_below_is_transparent(): void + { + $read = NodeMother::read(); + + static::assertNotNull((new FilterWalk())->predicateAtLeaf( + new Filter(new Filter($read, lit(true)), lit(true)), + $read, + ref('year')->isNotNull(), + )); + } + + public function test_a_limit_below_blocks(): void + { + $read = NodeMother::read(); + + static::assertNull((new FilterWalk())->predicateAtLeaf( + new Filter(NodeMother::limit($read, 5), lit(true)), + $read, + ref('year')->isNotNull(), + )); + } + + public function test_an_offset_below_blocks(): void + { + $read = NodeMother::read(); + + static::assertNull((new FilterWalk())->predicateAtLeaf( + new Filter(new Offset($read, 5), lit(true)), + $read, + ref('year')->isNotNull(), + )); + } + + public function test_an_until_below_blocks(): void + { + $read = NodeMother::read(); + + static::assertNull((new FilterWalk())->predicateAtLeaf( + new Filter(new Until($read, lit(true)), lit(true)), + $read, + ref('year')->isNotNull(), + )); + } + + public function test_a_distinct_below_blocks(): void + { + $read = NodeMother::read(); + + static::assertNull((new FilterWalk())->predicateAtLeaf( + new Filter(new Distinct($read, ['id']), lit(true)), + $read, + ref('year')->isNotNull(), + )); + } + + public function test_a_discard_below_blocks(): void + { + $read = NodeMother::read(); + + static::assertNull((new FilterWalk())->predicateAtLeaf( + new Filter(new Discard($read), lit(true)), + $read, + ref('year')->isNotNull(), + )); + } + + public function test_an_opaque_node_below_blocks(): void + { + $read = NodeMother::read(); + + static::assertNull((new FilterWalk())->predicateAtLeaf( + new Filter(NodeMother::sort($read), lit(true)), + $read, + ref('year')->isNotNull(), + )); + } + + public function test_a_with_column_redefining_a_referenced_name_blocks(): void + { + $read = NodeMother::read(); + + static::assertNull((new FilterWalk())->predicateAtLeaf( + new Filter(new WithColumn($read, 'year', lit(1)), lit(true)), + $read, + ref('year')->isNotNull(), + )); + } + + public function test_a_with_column_over_a_definition_redefining_a_referenced_name_blocks(): void + { + $read = NodeMother::read(); + + static::assertNull((new FilterWalk())->predicateAtLeaf( + new Filter(new WithColumn($read, int_schema('year'), lit(1)), lit(true)), + $read, + ref('year')->isNotNull(), + )); + } + + public function test_a_with_column_over_another_name_does_not_block(): void + { + $read = NodeMother::read(); + + static::assertNotNull((new FilterWalk())->predicateAtLeaf( + new Filter(new WithColumn($read, 'other', lit(1)), lit(true)), + $read, + ref('year')->isNotNull(), + )); + } + + public function test_a_rename_to_a_referenced_name_rewrites_the_predicate_to_the_column_below(): void + { + $read = NodeMother::read(); + + static::assertEquals( + ref('id')->isNotNull(), + (new FilterWalk())->predicateAtLeaf( + new Filter(new Rename($read, 'id', 'year'), lit(true)), + $read, + ref('year')->isNotNull(), + ), + ); + } + + public function test_a_rename_to_another_name_does_not_block(): void + { + $read = NodeMother::read(); + + static::assertNotNull((new FilterWalk())->predicateAtLeaf( + new Filter(new Rename($read, 'id', 'other'), lit(true)), + $read, + ref('year')->isNotNull(), + )); + } + + public function test_a_rename_each_always_blocks(): void + { + $read = NodeMother::read(); + + static::assertNull((new FilterWalk())->predicateAtLeaf( + new Filter(new RenameEach($read, [rename_replace('_', '-')]), lit(true)), + $read, + ref('year')->isNotNull(), + )); + } + + public function test_a_chain_that_does_not_end_in_the_leaf_does_not_reach(): void + { + static::assertNull((new FilterWalk())->predicateAtLeaf( + new Filter(NodeMother::read(), lit(true)), + NodeMother::read(), + ref('year')->isNotNull(), + )); + } + + public function test_a_duplicate_row_defining_a_referenced_name_blocks(): void + { + $read = NodeMother::read(); + + static::assertNull((new FilterWalk())->predicateAtLeaf(new Filter(new DuplicateRow( + $read, + lit(true), + [new WithEntry('year', lit(2023))], + ), lit(true)), $read, ref('year')->isNotNull())); + } + + public function test_a_duplicate_row_defining_another_name_does_not_block(): void + { + $read = NodeMother::read(); + + static::assertNotNull((new FilterWalk())->predicateAtLeaf(new Filter(new DuplicateRow( + $read, + lit(true), + [new WithEntry('copy', lit(1))], + ), lit(true)), $read, ref('year')->isNotNull())); + } + + public function test_a_node_redefining_a_referenced_column_blocks(): void + { + $read = NodeMother::read(); + + static::assertNull((new FilterWalk())->predicateAtLeaf( + new Filter(new RedefiningNode($read, Redefined::names('year')), lit(true)), + $read, + ref('year')->isNotNull(), + )); + } + + public function test_a_node_redefining_another_column_does_not_block(): void + { + $read = NodeMother::read(); + + static::assertNotNull((new FilterWalk())->predicateAtLeaf( + new Filter(new RedefiningNode($read, Redefined::names('other')), lit(true)), + $read, + ref('year')->isNotNull(), + )); + } + + public function test_an_unknown_redefinition_blocks(): void + { + $read = NodeMother::read(); + + static::assertNull((new FilterWalk())->predicateAtLeaf( + new Filter(new RedefiningNode($read, Redefined::unknown()), lit(true)), + $read, + ref('year')->isNotNull(), + )); + } + + public function test_a_with_column_aliasing_a_column_rewrites_the_predicate_to_that_column(): void + { + $read = NodeMother::read(); + + static::assertEquals( + ref('id')->isNotNull(), + (new FilterWalk())->predicateAtLeaf( + new Filter(new WithColumn($read, 'year', ref('id')), lit(true)), + $read, + ref('year')->isNotNull(), + ), + ); + } + + public function test_a_with_column_aliasing_a_column_under_a_definition_blocks(): void + { + $read = NodeMother::read(); + + static::assertNull((new FilterWalk())->predicateAtLeaf( + new Filter(new WithColumn($read, int_schema('year'), ref('id')), lit(true)), + $read, + ref('year')->isNotNull(), + )); + } + + public function test_stacked_aliases_rewrite_the_predicate_through_every_one(): void + { + $read = NodeMother::read(); + + static::assertEquals( + ref('id')->equals(ref('month')), + (new FilterWalk())->predicateAtLeaf( + new Filter(new Rename(new WithColumn($read, 'copy', ref('id')), 'copy', 'year'), lit(true)), + $read, + ref('year')->equals(ref('month')), + ), + ); + } + + public function test_a_predicate_reading_no_redefined_name_arrives_unchanged(): void + { + $read = NodeMother::read(); + $predicate = ref('month')->isNotNull(); + + static::assertSame($predicate, (new FilterWalk())->predicateAtLeaf( + new Filter(new Rename($read, 'id', 'year'), lit(true)), + $read, + $predicate, + )); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/JoinSidesTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/JoinSidesTest.php new file mode 100644 index 0000000000..3da06e64ad --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/JoinSidesTest.php @@ -0,0 +1,54 @@ +of($limit)); + } + + public function test_a_joins_right_side_is_optimized_as_its_own_plan(): void + { + $join = NodeMother::join(NodeMother::read(), NodeMother::plan(NodeMother::limit(NodeMother::read(), 3))->root); + + $rewritten = (new JoinSides(Optimizer::default(), NodeMother::context()))->of($join); + + static::assertInstanceOf(Join::class, $rewritten); + static::assertSame(3, (new LogicalPlan($rewritten->right()))->source()->limit()); + static::assertSame($join->children()[0], $rewritten->children()[0]); + } + + public function test_a_cross_joins_right_side_is_optimized_as_its_own_plan(): void + { + $join = NodeMother::crossJoin( + NodeMother::read(), + NodeMother::plan(NodeMother::limit(NodeMother::read(), 3))->root, + ); + + $rewritten = (new JoinSides(Optimizer::default(), NodeMother::context()))->of($join); + + static::assertInstanceOf(CrossJoin::class, $rewritten); + static::assertSame(3, (new LogicalPlan($rewritten->right()))->source()->limit()); + } + + public function test_a_join_whose_right_side_does_not_change_keeps_its_identity(): void + { + $join = NodeMother::crossJoin(NodeMother::read(), NodeMother::plan(NodeMother::read())->root); + + static::assertSame($join, (new JoinSides(new Optimizer(), NodeMother::context()))->of($join)); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/LimitWalkTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/LimitWalkTest.php new file mode 100644 index 0000000000..a04f39732a --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/LimitWalkTest.php @@ -0,0 +1,72 @@ +of($from, $leaf)); + } + + public static function walks(): Generator + { + $read = NodeMother::read(); + + yield 'a limit above the read' => [NodeMother::limit($read, 3), $read, 3]; + yield 'two limits fold with min' => [NodeMother::limit(NodeMother::limit($read, 5), 3), $read, 3]; + yield 'a blocker discards the limit above it' => [ + NodeMother::limit(NodeMother::sort(NodeMother::limit($read, 5)), 3), + $read, + 5, + ]; + yield 'an opaque transform discards the limit above it' => [ + NodeMother::limit(new Node\Transform($read, new AddRowIndexTransformer('idx', StartFrom::ZERO)), 3), + $read, + null, + ]; + yield 'a chain ending at a childless node that is not the leaf' => [ + NodeMother::limit(new ChildlessNode(), 3), + $read, + null, + ]; + yield 'a limit below an opaque transform passes' => [ + new Node\Transform(NodeMother::limit($read, 3), new AddRowIndexTransformer('idx', StartFrom::ZERO)), + $read, + 3, + ]; + yield 'a limit above an offset grows by the skipped rows' => [ + NodeMother::limit(new Node\Offset($read, 100), 10), + $read, + 110, + ]; + yield 'an offset above a limit leaves the limit' => [new Node\Offset(NodeMother::limit($read, 5), 2), $read, 5]; + yield 'an offset without a limit pushes nothing' => [new Node\Offset($read, 100), $read, null]; + yield 'a top-n discards the limit above it' => [ + NodeMother::limit(new Node\TopN($read, refs(ref('id')), 5), 3), + $read, + null, + ]; + yield 'the leaf alone' => [$read, $read, null]; + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/Rule/CombineLimitsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/Rule/CombineLimitsTest.php new file mode 100644 index 0000000000..642bd893a4 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/Rule/CombineLimitsTest.php @@ -0,0 +1,51 @@ +apply($plan, NodeMother::context())->root->children()[0]; + + static::assertInstanceOf(Limit::class, $root); + static::assertSame(3, $root->limit); + static::assertSame([$read], $root->children()); + } + + public function test_three_adjacent_limits_fold_to_the_minimum(): void + { + $read = NodeMother::read(); + $plan = NodeMother::plan(NodeMother::limit(NodeMother::limit(NodeMother::limit($read, 10), 2), 7)); + + $root = (new CombineLimits())->apply($plan, NodeMother::context())->root->children()[0]; + + static::assertInstanceOf(Limit::class, $root); + static::assertSame(2, $root->limit); + static::assertSame([$read], $root->children()); + } + + public function test_non_adjacent_limits_are_left_alone(): void + { + $plan = NodeMother::plan(NodeMother::limit(NodeMother::select(NodeMother::limit(NodeMother::read(), 10)), 3)); + + $root = (new CombineLimits())->apply($plan, NodeMother::context())->root->children()[0]; + + static::assertSame($plan->root->children()[0], $root); + static::assertInstanceOf(Limit::class, $root); + static::assertSame(3, $root->limit); + static::assertInstanceOf(Select::class, $root->children()[0]); + static::assertInstanceOf(Limit::class, $root->children()[0]->children()[0]); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/Rule/CombineSortAndLimitTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/Rule/CombineSortAndLimitTest.php new file mode 100644 index 0000000000..89c76c22f8 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/Rule/CombineSortAndLimitTest.php @@ -0,0 +1,78 @@ +apply( + NodeMother::plan(NodeMother::limit(new Sort($read, $refs), 5)), + NodeMother::context(), + ); + + $topN = $plan->spine(); + static::assertInstanceOf(TopN::class, $topN); + static::assertSame([$read], $topN->children()); + static::assertSame($refs, $topN->refs); + static::assertSame(5, $topN->limit); + } + + public function test_a_limit_over_anything_else_is_left_alone(): void + { + $plan = NodeMother::plan(NodeMother::limit(NodeMother::select(NodeMother::sort(NodeMother::read())), 5)); + + static::assertSame($plan->root, (new CombineSortAndLimit())->apply($plan, NodeMother::context())->root); + } + + public function test_the_rule_uses_the_context_it_is_given(): void + { + $context = NodeMother::context(config_builder()->sort(external_sort()->runSize(2))->build()); + $plan = NodeMother::plan(NodeMother::limit(NodeMother::sort(NodeMother::read()), 3)); + + static::assertInstanceOf( + Limit::class, + (new CombineSortAndLimit()) + ->apply($plan, $context) + ->spine(), + ); + } + + public function test_a_sort_another_consumer_reads_stays_for_that_consumer(): void + { + $sort = NodeMother::sort(NodeMother::read()); + $write = new Write($sort, to_memory(new ArrayMemory())); + + $plan = (new CombineSortAndLimit())->apply( + new LogicalPlan(new Outputs(new Result(NodeMother::limit($sort, 5)), $write)), + NodeMother::context(), + ); + + static::assertInstanceOf(TopN::class, $plan->spine()); + static::assertSame([$write], $plan->sinks()->all()); + static::assertSame($sort, $write->children()[0]); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/Rule/PushFilterIntoSourceTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/Rule/PushFilterIntoSourceTest.php new file mode 100644 index 0000000000..193b22f18d --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/Rule/PushFilterIntoSourceTest.php @@ -0,0 +1,442 @@ +read($extractor) + ->filter(ref('year')->equals(lit(2023))) + ->fetch(); + + $pathFilter = $extractor->pathFilters[0]; + static::assertInstanceOf(Filters::class, $pathFilter); + static::assertTrue($pathFilter->accept(PartitionedSourceMother::file('year=2023/month=07'))); + static::assertFalse($pathFilter->accept(PartitionedSourceMother::file('year=2024/month=07'))); + // the double reads every partition anyway, so only the Filter node the rule kept drops 2024 + static::assertSame([2023], $rows->reduceToArray('year')); + } + + public function test_two_stacked_partition_filters_are_both_pushed(): void + { + $extractor = PartitionedSourceMother::yearMonth(); + + df() + ->read($extractor) + ->filter(ref('year')->equals(lit(2023))) + ->filter(ref('month')->equals(lit('07'))) + ->fetch(); + + $pathFilter = $extractor->pathFilters[0]; + static::assertTrue($pathFilter->accept(PartitionedSourceMother::file('year=2023/month=07'))); + static::assertFalse($pathFilter->accept(PartitionedSourceMother::file('year=2024/month=07'))); + static::assertFalse($pathFilter->accept(PartitionedSourceMother::file('year=2023/month=08'))); + } + + public function test_three_stacked_partition_filters_all_reach_the_source(): void + { + $extractor = PartitionedSourceMother::yearMonth(); + + df() + ->read($extractor) + ->filter(ref('year')->greaterThanEqual(lit(2023))) + ->filter(ref('year')->lessThanEqual(lit(2023))) + ->filter(ref('month')->equals(lit('07'))) + ->fetch(); + + $pathFilter = $extractor->pathFilters[0]; + static::assertTrue($pathFilter->accept(PartitionedSourceMother::file('year=2023/month=07'))); + static::assertFalse($pathFilter->accept(PartitionedSourceMother::file('year=2022/month=07'))); + static::assertFalse($pathFilter->accept(PartitionedSourceMother::file('year=2024/month=07'))); + static::assertFalse($pathFilter->accept(PartitionedSourceMother::file('year=2023/month=08'))); + } + + public function test_a_body_predicate_below_a_partition_filter_does_not_block_it(): void + { + $extractor = PartitionedSourceMother::yearMonth(); + + $rows = df() + ->read($extractor) + ->filter(ref('value')->notEquals(lit(''))) + ->filter(ref('year')->equals(lit(2023))) + ->fetch(); + + $pathFilter = $extractor->pathFilters[0]; + static::assertTrue($pathFilter->accept(PartitionedSourceMother::file('year=2023/month=07'))); + static::assertFalse($pathFilter->accept(PartitionedSourceMother::file('year=2024/month=07'))); + static::assertSame(['a'], $rows->reduceToArray('value')); + } + + public function test_a_body_column_predicate_is_not_pushed(): void + { + $extractor = PartitionedSourceMother::yearMonth(); + + df() + ->read($extractor) + ->filter(ref('value')->equals(lit('a'))) + ->fetch(); + + static::assertEquals(new OnlyFiles(), $extractor->pathFilters[0]); + } + + public function test_a_mixed_predicate_pushes_only_its_partition_conjunct(): void + { + $extractor = PartitionedSourceMother::yearMonth(); + + $rows = df() + ->read($extractor) + ->filter(ref('year')->equals(lit(2023))->and(ref('value')->notEquals(lit('a')))) + ->fetch(); + + $pathFilter = $extractor->pathFilters[0]; + static::assertInstanceOf(Filters::class, $pathFilter); + static::assertTrue($pathFilter->accept(PartitionedSourceMother::file('year=2023/month=07'))); + static::assertFalse($pathFilter->accept(PartitionedSourceMother::file('year=2024/month=07'))); + // the body conjunct still runs in the Filter node: the only 2023 row has value "a" + static::assertCount(0, $rows); + } + + public function test_a_mixed_predicate_with_two_partition_conjuncts_pushes_both(): void + { + $extractor = PartitionedSourceMother::yearMonth(); + + df() + ->read($extractor) + ->filter( + ref('year') + ->equals(lit(2023)) + ->and(ref('month')->equals(lit('07'))) + ->and(ref('value')->notEquals(lit(''))), + ) + ->fetch(); + + $pathFilter = $extractor->pathFilters[0]; + static::assertTrue($pathFilter->accept(PartitionedSourceMother::file('year=2023/month=07'))); + static::assertFalse($pathFilter->accept(PartitionedSourceMother::file('year=2024/month=07'))); + static::assertFalse($pathFilter->accept(PartitionedSourceMother::file('year=2023/month=08'))); + } + + public function test_a_conjunct_that_is_not_deterministic_is_skipped_and_the_rest_pushed(): void + { + $extractor = PartitionedSourceMother::yearMonth(); + + df() + ->read($extractor) + ->filter( + ref('year') + ->equals(lit(2023)) + ->and(ref('month')->equals(random_string(2, new FixedRandomValueGenerator('xx')))), + ) + ->fetch(); + + $pathFilter = $extractor->pathFilters[0]; + static::assertTrue($pathFilter->accept(PartitionedSourceMother::file('year=2023/month=07'))); + static::assertFalse($pathFilter->accept(PartitionedSourceMother::file('year=2024/month=07'))); + } + + public function test_an_or_over_partition_columns_is_pushed_whole(): void + { + $extractor = PartitionedSourceMother::yearMonth(); + + df() + ->read($extractor) + ->filter(ref('year')->equals(lit(2023))->or(ref('year')->equals(lit(2024)))) + ->fetch(); + + $pathFilter = $extractor->pathFilters[0]; + static::assertTrue($pathFilter->accept(PartitionedSourceMother::file('year=2023/month=07'))); + static::assertTrue($pathFilter->accept(PartitionedSourceMother::file('year=2024/month=07'))); + static::assertFalse($pathFilter->accept(PartitionedSourceMother::file('year=2025/month=07'))); + } + + public function test_an_or_mixing_a_body_column_is_not_pushed(): void + { + $extractor = PartitionedSourceMother::yearMonth(); + + df() + ->read($extractor) + ->filter(ref('year')->equals(lit(2023))->or(ref('value')->equals(lit('x')))) + ->fetch(); + + static::assertEquals(new OnlyFiles(), $extractor->pathFilters[0]); + } + + public function test_a_nested_and_inside_an_and_pushes_the_partition_conjuncts(): void + { + $extractor = PartitionedSourceMother::yearMonth(); + + // and() on a plain function wraps its argument, so the partition pair stays one nested All + $rows = df() + ->read($extractor) + ->filter( + ref('value') + ->notEquals(lit('')) + ->and(ref('year')->equals(lit(2023))->and(ref('month')->equals(lit('07')))), + ) + ->fetch(); + + $pathFilter = $extractor->pathFilters[0]; + static::assertTrue($pathFilter->accept(PartitionedSourceMother::file('year=2023/month=07'))); + static::assertFalse($pathFilter->accept(PartitionedSourceMother::file('year=2024/month=07'))); + static::assertFalse($pathFilter->accept(PartitionedSourceMother::file('year=2023/month=08'))); + static::assertSame(['a'], $rows->reduceToArray('value')); + } + + public function test_a_limit_below_the_filter_blocks_the_push(): void + { + $extractor = PartitionedSourceMother::yearMonth(); + + df() + ->read($extractor) + ->limit(5) + ->filter(ref('year')->equals(lit(2023))) + ->fetch(); + + static::assertEquals(new OnlyFiles(), $extractor->pathFilters[0]); + } + + public function test_a_with_entry_redefining_the_partition_column_blocks_the_push(): void + { + $extractor = PartitionedSourceMother::yearMonth(); + + df() + ->read($extractor) + ->withEntry('year', lit(2023)) + ->filter(ref('year')->equals(lit(2023))) + ->fetch(); + + static::assertEquals(new OnlyFiles(), $extractor->pathFilters[0]); + } + + public function test_a_duplicate_row_defining_the_partition_column_blocks_the_push(): void + { + $extractor = PartitionedSourceMother::yearMonth(); + + $rows = df() + ->read($extractor) + ->duplicateRow(lit(true), new WithEntry('year', lit(2023))) + ->filter(ref('year')->equals(lit(2023))) + ->fetch(); + + static::assertEquals(new OnlyFiles(), $extractor->pathFilters[0]); + // the 2024 row's duplicate carries year=2023: pruning its partition would lose it + static::assertCount(3, $rows); + } + + public function test_a_duplicate_row_defining_another_column_does_not_block_the_push(): void + { + $extractor = PartitionedSourceMother::yearMonth(); + + df() + ->read($extractor) + ->duplicateRow(lit(true), new WithEntry('copy', lit(1))) + ->filter(ref('year')->equals(lit(2023))) + ->fetch(); + + static::assertInstanceOf(Filters::class, $extractor->pathFilters[0]); + } + + public function test_a_filter_a_sink_root_does_not_consume_through_is_not_pushed(): void + { + $extractor = PartitionedSourceMother::yearMonth(); + + df() + ->read($extractor) + ->write(to_memory(new ArrayMemory())) + ->filter(ref('year')->equals(lit(2023))) + ->fetch(); + + static::assertEquals(new OnlyFiles(), $extractor->pathFilters[0]); + } + + public function test_a_non_file_extractor_is_never_pushed_into(): void + { + $plan = NodeMother::plan( + new Filter(new Read(new RecordingExtractor(schema(int_schema('year')))), ref('year')->equals(lit(2023))), + ); + + static::assertSame($plan, (new PushFilterIntoSource())->apply($plan, NodeMother::context())); + } + + public function test_a_source_without_partition_columns_is_never_pushed_into(): void + { + $extractor = new RecordingFileExtractor( + schema(int_schema('year')), + rows(schema(int_schema('year')), row(['year' => 2023])), + ); + + df() + ->read($extractor) + ->filter(ref('year')->equals(lit(2023))) + ->fetch(); + + static::assertEquals(new OnlyFiles(), $extractor->pathFilters[0]); + } + + public function test_a_non_deterministic_predicate_is_not_pushed(): void + { + $extractor = PartitionedSourceMother::yearMonth(); + + df() + ->read($extractor) + ->filter(ref('month')->equals(random_string(2))) + ->fetch(); + + static::assertEquals(new OnlyFiles(), $extractor->pathFilters[0]); + } + + public function test_a_predicate_calling_a_user_callable_is_not_pushed(): void + { + $extractor = PartitionedSourceMother::yearMonth(); + + df() + ->read($extractor) + ->filter(ref('year')->call(lit('is_string'), type_boolean())) + ->fetch(); + + static::assertEquals(new OnlyFiles(), $extractor->pathFilters[0]); + } + + public function test_a_literal_only_predicate_is_not_pushed(): void + { + $extractor = PartitionedSourceMother::yearMonth(); + + df()->read($extractor)->filter(lit(true))->fetch(); + + static::assertEquals(new OnlyFiles(), $extractor->pathFilters[0]); + } + + public function test_a_filter_inside_a_joined_frame_is_pushed_with_that_frames_context(): void + { + $right = PartitionedSourceMother::yearMonth(); + + df() + ->read(from_array([['id' => 2023]])) + ->join(df()->read($right)->filter(ref('year')->equals(lit(2023))), join_on(['id' => 'year'], 'r_')) + ->fetch(); + + $pathFilter = $right->pathFilters[0]; + static::assertTrue($pathFilter->accept(PartitionedSourceMother::file('year=2023/month=07'))); + static::assertFalse($pathFilter->accept(PartitionedSourceMother::file('year=2024/month=07'))); + } + + public function test_an_incomparable_partition_predicate_fails_the_plan(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage( + "Can't compare '(string == date)' due to data type mismatch - an explicit cast is required.", + ); + + (new Planner(Optimizer::default()))->plan( + NodeMother::plan( + new Filter( + new Read(PartitionedSourceMother::yearMonth()), + ref('month')->equals(lit(new DateTimeImmutable('2024-01-01'))), + ), + ), + NodeMother::context(), + ); + } + + public function test_the_extractor_instance_is_never_mutated(): void + { + $extractor = PartitionedSourceMother::yearMonth(); + $frame = df()->read($extractor)->filter(ref('year')->equals(lit(2023))); + + $frame->fetch(); + + static::assertStringEndsWith( + "Extractor: RecordingFileExtractor\n Source: file://dev/null", + $frame->explain()->toString(Stage::unoptimized), + ); + static::assertStringEndsWith( + "Extractor: RecordingFileExtractor\n Source: file://dev/null\n Files: Filters", + $frame->explain()->toString(), + ); + } + + public function test_a_filter_on_a_renamed_partition_column_is_pushed_as_the_original_column(): void + { + $extractor = PartitionedSourceMother::yearMonth(); + + $rows = df() + ->read($extractor) + ->rename('year', 'y') + ->filter(ref('y')->equals(lit(2023))) + ->fetch(); + + $pathFilter = $extractor->pathFilters[0]; + static::assertInstanceOf(Filters::class, $pathFilter); + static::assertTrue($pathFilter->accept(PartitionedSourceMother::file('year=2023/month=07'))); + static::assertFalse($pathFilter->accept(PartitionedSourceMother::file('year=2024/month=07'))); + static::assertSame([2023], $rows->reduceToArray('y')); + } + + public function test_a_filter_on_an_alias_of_a_partition_column_is_pushed_as_the_original_column(): void + { + $extractor = PartitionedSourceMother::yearMonth(); + + $rows = df() + ->read($extractor) + ->withEntry('y', ref('year')) + ->filter(ref('y')->equals(lit(2023))) + ->fetch(); + + $pathFilter = $extractor->pathFilters[0]; + static::assertInstanceOf(Filters::class, $pathFilter); + static::assertTrue($pathFilter->accept(PartitionedSourceMother::file('year=2023/month=07'))); + static::assertFalse($pathFilter->accept(PartitionedSourceMother::file('year=2024/month=07'))); + static::assertSame([2023], $rows->reduceToArray('y')); + } + + public function test_a_filter_on_an_alias_of_a_body_column_is_not_pushed(): void + { + $extractor = PartitionedSourceMother::yearMonth(); + + df() + ->read($extractor) + ->withEntry('v', ref('value')) + ->filter(ref('v')->equals(lit('a'))) + ->fetch(); + + static::assertEquals(new OnlyFiles(), $extractor->pathFilters[0]); + } +} 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 new file mode 100644 index 0000000000..3f88de5bcc --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/Rule/PushLimitIntoSourceTest.php @@ -0,0 +1,294 @@ +apply( + NodeMother::plan(NodeMother::limit(NodeMother::read(), 10)), + NodeMother::context(), + ); + + static::assertSame(10, $plan->source()->limit()); + } + + public function test_a_limit_passes_a_select(): void + { + $plan = (new PushLimitIntoSource())->apply( + NodeMother::plan(NodeMother::limit(NodeMother::select(NodeMother::read()), 10)), + NodeMother::context(), + ); + + static::assertSame(10, $plan->source()->limit()); + } + + #[DataProvider('expanding_expressions')] + public function test_a_limit_does_not_pass_a_with_column_that_expands(ScalarFunction $function): void + { + $plan = (new PushLimitIntoSource())->apply( + NodeMother::plan(NodeMother::limit(new Node\WithColumn(NodeMother::read(), 'expanded', $function), 10)), + NodeMother::context(), + ); + + static::assertNull($plan->source()->limit()); + } + + public static function expanding_expressions(): Generator + { + yield 'root expand' => [ref('data')->expand()]; + yield 'nested expand' => [structure(['tag' => ref('data')->expand()])]; + } + + public function test_a_limit_does_not_pass_a_filter(): void + { + $plan = (new PushLimitIntoSource())->apply( + NodeMother::plan(NodeMother::limit( + new Node\Filter(NodeMother::select(NodeMother::read()), ref('id')->equals(lit(1))), + 10, + )), + NodeMother::context(), + ); + + static::assertNull($plan->source()->limit()); + } + + public function test_a_limit_does_not_pass_a_write(): void + { + $plan = (new PushLimitIntoSource())->apply( + NodeMother::plan(NodeMother::limit(new Node\Write(NodeMother::read(), to_memory(new ArrayMemory())), 10)), + NodeMother::context(), + ); + + static::assertNull($plan->source()->limit()); + } + + public function test_a_blocker_discards_the_limit_collected_above_it_and_the_walk_continues(): void + { + $plan = (new PushLimitIntoSource())->apply( + NodeMother::plan(NodeMother::limit( + new Node\Sort(NodeMother::limit(NodeMother::read(), 5), refs(ref('id')), memory_sort()), + 3, + )), + NodeMother::context(), + ); + + static::assertSame(5, $plan->source()->limit()); + } + + public function test_the_push_rewrites_the_leaf_and_keeps_the_spine(): void + { + $extractor = new RecordingFileExtractor(schema(int_schema('id'))); + $plan = NodeMother::plan(NodeMother::limit(NodeMother::select(new Read($extractor)), 10)); + + $pushed = (new PushLimitIntoSource())->apply($plan, NodeMother::context()); + + static::assertNotSame($plan, $pushed); + $limit = $pushed->root->children()[0]; + static::assertInstanceOf(Node\Limit::class, $limit); + static::assertSame(10, $limit->limit); + static::assertInstanceOf(Node\Select::class, $limit->children()[0]); + static::assertSame(10, $pushed->source()->limit()); + static::assertSame($extractor, $pushed->source()->extractor()); + static::assertNull($plan->source()->limit()); + static::assertSame([], $extractor->limits); + } + + public function test_the_minimum_of_two_limits_is_pushed(): void + { + $plan = (new PushLimitIntoSource())->apply( + NodeMother::plan(NodeMother::limit(NodeMother::select(NodeMother::limit(NodeMother::read(), 10)), 3)), + NodeMother::context(), + ); + + static::assertSame(3, $plan->source()->limit()); + } + + public function test_a_limit_narrows_an_already_pushed_limit(): void + { + $plan = (new PushLimitIntoSource())->apply( + NodeMother::plan(NodeMother::limit(new Node\Rename(NodeMother::read()->withLimit(4), 'id', 'new_id'), 10)), + NodeMother::context(), + ); + + static::assertSame(4, $plan->source()->limit()); + } + + public function test_a_plan_without_a_limit_pushes_nothing(): void + { + $plan = (new PushLimitIntoSource())->apply( + NodeMother::plan(NodeMother::select(NodeMother::read())), + NodeMother::context(), + ); + + static::assertNull($plan->source()->limit()); + } + + public function test_a_row_input_chain_that_does_not_end_in_a_read_throws(): void + { + $this->expectException(InvalidLogicException::class); + $this->expectExceptionMessage('A logical plan must end in a Read, ' . ChildlessNode::class . ' found'); + + (new PushLimitIntoSource())->apply( + NodeMother::plan(NodeMother::limit(NodeMother::select(new ChildlessNode()), 10)), + NodeMother::context(), + ); + } + + public function test_a_transaction_contributes_one_walk_per_child(): void + { + $limit = NodeMother::limit(NodeMother::read(), 3); + + $plan = (new PushLimitIntoSource())->apply( + new LogicalPlan( + new Outputs( + new Result($limit), + new Node\Transaction( + new RecordingTransaction(), + new Write($limit, to_memory(new ArrayMemory())), + new Write($limit, to_memory(new ArrayMemory())), + ), + ), + ), + NodeMother::context(), + ); + + static::assertSame(3, $plan->source()->limit()); + } + + public function test_one_transaction_child_whose_walk_yields_no_limit_blocks_the_push(): void + { + $read = NodeMother::read(); + $limit = NodeMother::limit($read, 3); + + $plan = (new PushLimitIntoSource())->apply( + new LogicalPlan( + new Outputs( + new Result($limit), + new Node\Transaction( + new RecordingTransaction(), + new Write($limit, to_memory(new ArrayMemory())), + new Write($read, to_memory(new ArrayMemory())), + ), + ), + ), + NodeMother::context(), + ); + + static::assertNull($plan->source()->limit()); + } + + public function test_a_limit_below_a_sink_is_pushed(): void + { + $limit = NodeMother::limit(NodeMother::read(), 3); + + $plan = (new PushLimitIntoSource())->apply( + new LogicalPlan(new Outputs(new Result($limit), new Write($limit, to_memory(new ArrayMemory())))), + NodeMother::context(), + ); + + static::assertSame(3, $plan->source()->limit()); + } + + public function test_a_limit_above_a_sink_does_not_narrow_the_sink(): void + { + $read = NodeMother::read(); + + $plan = (new PushLimitIntoSource())->apply( + new LogicalPlan( + new Outputs(new Result(NodeMother::limit($read, 3)), new Write($read, to_memory(new ArrayMemory()))), + ), + NodeMother::context(), + ); + + static::assertNull($plan->source()->limit()); + } + + public function test_the_widest_limit_of_every_root_is_pushed(): void + { + $limit = NodeMother::limit(NodeMother::read(), 5); + + $plan = (new PushLimitIntoSource())->apply( + new LogicalPlan( + new Outputs(new Result(NodeMother::limit($limit, 3)), new Write($limit, to_memory(new ArrayMemory()))), + ), + NodeMother::context(), + ); + + static::assertSame(5, $plan->source()->limit()); + } + + public function test_a_sink_whose_walk_yields_no_limit_blocks_the_push(): void + { + $read = NodeMother::read(); + + $plan = (new PushLimitIntoSource())->apply( + new LogicalPlan( + new Outputs( + new Result(NodeMother::limit($read, 3)), + new Write( + new Node\Transform($read, new AddRowIndexTransformer('idx', StartFrom::ZERO)), + to_memory(new ArrayMemory()), + ), + ), + ), + NodeMother::context(), + ); + + static::assertNull($plan->source()->limit()); + } + + public function test_the_push_reaches_the_sinks_through_the_shared_leaf(): void + { + $limit = NodeMother::limit(NodeMother::read(), 3); + + $plan = (new PushLimitIntoSource())->apply( + new LogicalPlan(new Outputs(new Result($limit), new Write($limit, to_memory(new ArrayMemory())))), + NodeMother::context(), + ); + + static::assertSame($plan->root->children()[0]->children()[0], $plan->sinks()->all()[0]->children()[0]); + } + + public function test_a_limit_above_an_offset_pushes_the_limit_plus_the_offset(): void + { + $plan = (new PushLimitIntoSource())->apply( + NodeMother::plan(NodeMother::limit(new Node\Offset(NodeMother::read(), 100), 10)), + NodeMother::context(), + ); + + static::assertSame(110, $plan->source()->limit()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/TopNRewriteTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/TopNRewriteTest.php new file mode 100644 index 0000000000..6e1232c096 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/TopNRewriteTest.php @@ -0,0 +1,76 @@ +of($sort)); + } + + public function test_a_limit_over_anything_but_a_sort_is_returned_as_is(): void + { + $limit = NodeMother::limit(NodeMother::select(NodeMother::sort(NodeMother::read())), 5); + + static::assertSame($limit, (new TopNRewrite(NodeMother::context()))->of($limit)); + } + + public function test_a_limit_over_a_sort_becomes_a_top_n_over_the_sorts_input_refs_and_limit(): void + { + $read = NodeMother::read(); + $refs = refs(ref('id')); + + $topN = (new TopNRewrite(NodeMother::context()))->of(NodeMother::limit(new Sort($read, $refs), 5)); + + static::assertInstanceOf(TopN::class, $topN); + static::assertSame([$read], $topN->children()); + static::assertSame($refs, $topN->refs); + static::assertSame(5, $topN->limit); + } + + public function test_an_external_sort_is_rewritten_up_to_its_run_size_and_kept_beyond_it(): void + { + $rewrite = new TopNRewrite(NodeMother::context()); + $sort = new Sort(NodeMother::read(), refs(ref('id')), external_sort()->runSize(10)); + + static::assertInstanceOf(TopN::class, $rewrite->of(NodeMother::limit($sort, 10))); + static::assertInstanceOf(Limit::class, $rewrite->of(NodeMother::limit($sort, 11))); + } + + public function test_the_configured_sort_decides_when_the_sort_pins_none(): void + { + $rewrite = new TopNRewrite(NodeMother::context(config_builder()->sort(external_sort()->runSize(2))->build())); + $sort = NodeMother::sort(NodeMother::read()); + + static::assertInstanceOf(TopN::class, $rewrite->of(NodeMother::limit($sort, 2))); + static::assertInstanceOf(Limit::class, $rewrite->of(NodeMother::limit($sort, 3))); + } + + public function test_a_sort_that_pins_its_algorithm_wins_over_the_configured_one(): void + { + $rewrite = new TopNRewrite(NodeMother::context(config_builder()->sort(external_sort()->runSize(2))->build())); + + static::assertInstanceOf( + TopN::class, + $rewrite->of(NodeMother::limit(new Sort(NodeMother::read(), refs(ref('id')), memory_sort()), 1_000_000)), + ); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/OptimizerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/OptimizerTest.php new file mode 100644 index 0000000000..a85b192b93 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/OptimizerTest.php @@ -0,0 +1,130 @@ + $log */ + $log = new ArrayObject(); + $plan = NodeMother::plan(NodeMother::read()); + + $optimized = (new Optimizer(new RecordingRule('first', $log), new RecordingRule('second', $log)))->optimize( + $plan, + NodeMother::context(), + ); + + static::assertSame(['first', 'second'], $log->getArrayCopy()); + static::assertSame($plan, $optimized); + } + + public function test_optimize_applies_the_rules_to_a_joins_right_side_first(): void + { + /** @var ArrayObject $log */ + $log = new ArrayObject(); + $plan = NodeMother::plan(NodeMother::crossJoin(NodeMother::read(), NodeMother::plan(NodeMother::read())->root)); + + (new Optimizer(new RecordingRule('first', $log), new RecordingRule('second', $log)))->optimize( + $plan, + NodeMother::context(), + ); + + static::assertSame(['first', 'second', 'first', 'second'], $log->getArrayCopy()); + } + + public function test_an_optimizer_without_rules_returns_the_plan_it_was_given(): void + { + $plan = NodeMother::plan(NodeMother::read()); + + static::assertSame($plan, (new Optimizer())->optimize($plan, NodeMother::context())); + } + + public function test_default_registers_combine_limits_combine_sort_and_limit_push_limit_then_push_filter_into_source(): void + { + static::assertSame( + [CombineLimits::class, CombineSortAndLimit::class, PushLimitIntoSource::class, PushFilterIntoSource::class], + array_map(static fn($rule) => $rule::class, Optimizer::default()->rules()), + ); + } + + public function test_without_drops_the_named_rule_and_keeps_the_rest(): void + { + static::assertSame( + [CombineLimits::class, CombineSortAndLimit::class, PushFilterIntoSource::class], + array_map( + static fn($rule) => $rule::class, + Optimizer::default()->without(PushLimitIntoSource::class)->rules(), + ), + ); + } + + public function test_without_returns_a_new_optimizer(): void + { + $optimizer = Optimizer::default(); + + static::assertNotSame($optimizer, $optimizer->without(CombineLimits::class)); + } + + public function test_without_throws_on_an_unregistered_rule_name(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage(RecordingRule::class . ' is not a registered optimizer rule'); + + Optimizer::default()->without(RecordingRule::class); + } + + public function test_with_appends_the_rules_after_the_registered_ones(): void + { + /** @var ArrayObject $log */ + $log = new ArrayObject(); + + static::assertSame( + [CombineLimits::class, RecordingRule::class], + array_map( + static fn($rule) => $rule::class, + (new Optimizer(new CombineLimits())) + ->with(new RecordingRule('first', $log)) + ->rules(), + ), + ); + } + + public function test_with_returns_a_new_optimizer(): void + { + $optimizer = new Optimizer(); + + static::assertNotSame($optimizer, $optimizer->with(new CombineLimits())); + } + + public function test_with_throws_on_a_rule_class_already_registered(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage(CombineLimits::class . ' is already a registered optimizer rule'); + + Optimizer::default()->with(new CombineLimits()); + } + + public function test_with_throws_on_the_same_rule_class_given_twice(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage(CombineLimits::class . ' is already a registered optimizer rule'); + + (new Optimizer())->with(new CombineLimits(), new CombineLimits()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Pipeline/Optimizer/LimitOptimizationTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Pipeline/Optimizer/LimitOptimizationTest.php deleted file mode 100644 index 69227473fe..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Pipeline/Optimizer/LimitOptimizationTest.php +++ /dev/null @@ -1,194 +0,0 @@ -add(new ScalarFunctionFilterTransformer(ref('id')->equals(lit(1)))); - - (new Optimizer(new LimitOptimization()))->optimize(new LimitTransformer(10), $filteredPipeline); - - $selectedThenFiltered = from_csv(path_real('file.csv')); - $selectedThenFilteredPipeline = new Pipeline($selectedThenFiltered); - $selectedThenFilteredPipeline->add(new SelectEntriesTransformer(ref('id'))); - $selectedThenFilteredPipeline->add(new ScalarFunctionFilterTransformer(ref('id')->equals(lit(1)))); - - (new Optimizer(new LimitOptimization()))->optimize(new LimitTransformer(10), $selectedThenFilteredPipeline); - - static::assertNull($filtered->pushedLimit()); - static::assertNull($selectedThenFiltered->pushedLimit()); - } - - public function test_limit_transformer_stays_in_the_pipeline_after_push_down(): void - { - $accepted = new Pipeline(from_csv(path_real('file.csv'))); - $accepted->add(new SelectEntriesTransformer(ref('id'))); - - $refused = new Pipeline(from_csv(path_real('file.csv'))); - $refused->add(new DropDuplicatesTransformer(ref('id'))); - - $expanding = new Pipeline(from_csv(path_real('file.csv'))); - $expanding->add(new ScalarFunctionTransformer('expanded', ref('data')->expand())); - - $notPushing = new Pipeline(from_rows(rows(schema()))); - - foreach ([$accepted, $refused, $expanding, $notPushing] as $pipeline) { - $steps = (new Optimizer(new LimitOptimization())) - ->optimize(new LimitTransformer(10), $pipeline) - ->segments() - ->steps(); - - static::assertInstanceOf(LimitTransformer::class, $steps[count($steps) - 1]); - } - } - - public function test_push_down_leaves_the_callers_extractor_untouched(): void - { - $extractor = from_csv(path_real('file.csv')); - $pipeline = new Pipeline($extractor); - - (new Optimizer(new LimitOptimization()))->optimize(new LimitTransformer(10), $pipeline); - - $pushed = $pipeline->extractor(); - - static::assertInstanceOf(CSVExtractor::class, $pushed); - static::assertNotSame($extractor, $pushed); - static::assertSame(10, $pushed->pushedLimit()); - static::assertNull($extractor->pushedLimit()); - } - - public function test_optimization_against_pipelines_with_expanding_processors(): void - { - $groupedExtractor = from_csv(path_real('file.csv')); - $pipelineWithGroupBy = new Pipeline($groupedExtractor); - $pipelineWithGroupBy->add(new GroupByAggregationProcessor(new GroupBy(), new Buckets(new MemoryBuckets()))); - - (new Optimizer(new LimitOptimization()))->optimize(new LimitTransformer(10), $pipelineWithGroupBy); - - static::assertNull($groupedExtractor->pushedLimit()); - - $partitionedExtractor = from_csv(path_real('file.csv')); - $pipelineWithPartitioning = new Pipeline($partitionedExtractor); - $pipelineWithPartitioning->add( - new RepartitionProcessor(References::init(ref('group')), new Buckets(new MemoryBuckets())), - ); - - (new Optimizer(new LimitOptimization()))->optimize(new LimitTransformer(10), $pipelineWithPartitioning); - - static::assertNull($partitionedExtractor->pushedLimit()); - } - - #[DataProvider('expanding_expressions')] - public function test_optimization_for_a_pipeline_with_expanding_expression_transformations(ScalarFunction $function): void - { - $pipeline = new Pipeline(from_csv(path_real('file.csv'))); - $pipeline->add(new ScalarFunctionTransformer('expanded', $function)); - - $optimizedPipeline = (new Optimizer(new LimitOptimization()))->optimize(new LimitTransformer(10), $pipeline); - - $extractor = $pipeline->extractor(); - static::assertInstanceOf(CSVExtractor::class, $extractor); - static::assertNull($extractor->pushedLimit()); - static::assertCount(2, $optimizedPipeline->segments()->steps()); - } - - /** - * @return Generator - */ - public static function expanding_expressions(): Generator - { - yield 'root expand' => [ref('data')->expand()]; - yield 'nested expand' => [structure(['tag' => ref('data')->expand()])]; - } - - public function test_optimization_for_a_pipeline_with_expanding_transformations(): void - { - $pipeline = new Pipeline(from_csv(path_real('file.csv'))); - $pipeline->add(new DropDuplicatesTransformer(ref('id'))); - - $optimizedPipeline = (new Optimizer(new LimitOptimization()))->optimize(new LimitTransformer(10), $pipeline); - - $extractor = $pipeline->extractor(); - static::assertInstanceOf(CSVExtractor::class, $extractor); - static::assertNull($extractor->pushedLimit()); - static::assertCount(2, $optimizedPipeline->segments()->steps()); - } - - public function test_optimization_for_a_pipeline_with_limited_extractor(): void - { - $extractor = from_csv(path_real('file.csv')); - $extractor->pushLimit(10); - $pipeline = new Pipeline($extractor); - $pipeline->add(new RenameEntryTransformer('id', 'new_id')); - - $optimizedPipeline = (new Optimizer(new LimitOptimization()))->optimize(new LimitTransformer(10), $pipeline); - - $extractor = $pipeline->extractor(); - static::assertInstanceOf(CSVExtractor::class, $extractor); - static::assertNotNull($extractor->pushedLimit()); - static::assertCount(2, $optimizedPipeline->segments()->steps()); - static::assertInstanceOf(LimitTransformer::class, $optimizedPipeline->segments()->steps()[1]); - } - - public function test_optimization_for_a_pipeline_without_expanding_transformations(): void - { - $pipeline = new Pipeline(from_csv(path_real('file.csv'))); - $pipeline->add(new SelectEntriesTransformer(ref('id'), ref('name'))); - - $optimizedPipeline = (new Optimizer(new LimitOptimization()))->optimize(new LimitTransformer(10), $pipeline); - - $extractor = $pipeline->extractor(); - static::assertInstanceOf(CSVExtractor::class, $extractor); - static::assertNotNull($extractor->pushedLimit()); - static::assertCount(2, $optimizedPipeline->segments()->steps()); - } - - public function test_optimization_of_limit_on_empty_pipeline(): void - { - $pipeline = new Pipeline(from_csv(path_real('file.csv'))); - - $optimizedPipeline = (new Optimizer(new LimitOptimization()))->optimize(new LimitTransformer(10), $pipeline); - - $extractor = $pipeline->extractor(); - static::assertInstanceOf(CSVExtractor::class, $extractor); - static::assertNotNull($extractor->pushedLimit()); - static::assertCount(1, $optimizedPipeline->segments()->steps()); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Pipeline/PlanBinderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Pipeline/PlanBinderTest.php deleted file mode 100644 index c8f3eafb6a..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Pipeline/PlanBinderTest.php +++ /dev/null @@ -1,97 +0,0 @@ -add($loader = to_array($output)); - - $bound = (new PlanBinder())->bind(new CountingExtractor(schema(int_schema('id'))), $segments); - - static::assertSame([$loader], $bound->segments()->steps()); - static::assertEquals(schema(int_schema('id')), $bound->schema); - } - - public function test_a_step_that_cannot_describe_its_output_refuses_the_walk(): void - { - $segments = new Segments(); - $segments->add(JoinEachRowsTransformer::inner( - new class implements DataFrameFactory { - public function from(Rows $rows): DataFrame - { - return data_frame()->process(rows(schema(str_schema('code')), row(['code' => 'PL']))); - } - }, - Expression::on(['country' => 'code'], 'joined_'), - )); - - $this->expectException(DataDependentSchemaException::class); - $this->expectExceptionMessage("its right side is built from each left batch's row values"); - - (new PlanBinder())->bind(new CountingExtractor(schema(str_schema('country'))), $segments); - } - - public function test_the_extractor_schema_seeds_the_walk(): void - { - static::assertEquals( - schema(int_schema('id'), str_schema('name')), - (new PlanBinder())->bind( - new CountingExtractor(schema(int_schema('id'), str_schema('name'))), - new Segments(), - )->schema, - ); - } - - public function test_the_output_of_a_two_step_chain_is_the_second_steps(): void - { - $segments = new Segments(); - $segments->add(new AddRowIndexTransformer('index', StartFrom::ZERO)); - $segments->add(new SelectEntriesTransformer('index')); - - static::assertEquals( - schema(int_schema('index')), - (new PlanBinder())->bind( - new CountingExtractor(schema(int_schema('id'), str_schema('name'))), - $segments, - )->schema, - ); - } - - public function test_the_walk_reads_no_row(): void - { - $segments = new Segments(); - $segments->add(new SelectEntriesTransformer('id')); - - (new PlanBinder())->bind($extractor = new CountingExtractor(schema(int_schema('id'))), $segments); - - static::assertSame(0, $extractor->extractCalls); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Pipeline/SegmentsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Pipeline/SegmentsTest.php deleted file mode 100644 index 298681aec6..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Pipeline/SegmentsTest.php +++ /dev/null @@ -1,347 +0,0 @@ -add(new BatchingProcessor(10)); - } - - $replacement = from_rows(rows(schema())); - $segments->replaceExtractor($replacement); - - $handler = new RecordingErrorHandler(); - - iterator_to_array($segments->all()[0]->execute( - (static function (): Generator { - yield RowsMother::sequentialIds(1); - - throw new RuntimeException('source failed'); - })(), - flow_context(config())->setErrorHandler($handler), - )); - - $error = $handler->errors[0]; - - static::assertInstanceOf(ExtractionError::class, $error); - static::assertSame($replacement, $error->extractor); - } - - public function test_add_loader_to_current_segment(): void - { - $segments = new Segments(); - $loader = $this->createStubLoader(); - - $segments->add($loader); - - static::assertCount(1, $segments->all()); - static::assertSame([$loader], $segments->current()->steps()); - } - - public function test_add_multiple_transformers_and_loaders_to_current_segment(): void - { - $segments = new Segments(); - $transformer1 = $this->createStubTransformer(); - $transformer2 = $this->createStubTransformer(); - $loader = $this->createStubLoader(); - - $segments->add($transformer1); - $segments->add($transformer2); - $segments->add($loader); - - static::assertCount(1, $segments->all()); - static::assertSame([$transformer1, $transformer2, $loader], $segments->current()->steps()); - } - - public function test_add_processor_creates_new_segment(): void - { - $segments = new Segments(); - $transformer = $this->createStubTransformer(); - $processor = $this->createStubProcessor(); - - $segments->add($transformer); - $segments->add($processor); - - $allSegments = $segments->all(); - - static::assertCount(2, $allSegments); - static::assertSame([$transformer], $allSegments[0]->steps()); - static::assertSame($processor, $allSegments[0]->processor()); - static::assertSame([], $allSegments[1]->steps()); - static::assertNull($allSegments[1]->processor()); - } - - public function test_add_processor_with_empty_steps_creates_segment_with_processor(): void - { - $segments = new Segments(); - $processor = $this->createStubProcessor(); - - $segments->add($processor); - - $allSegments = $segments->all(); - - static::assertCount(2, $allSegments); - static::assertSame([], $allSegments[0]->steps()); - static::assertSame($processor, $allSegments[0]->processor()); - } - - public function test_add_transformer_to_current_segment(): void - { - $segments = new Segments(); - $transformer = $this->createStubTransformer(); - - $segments->add($transformer); - - static::assertCount(1, $segments->all()); - static::assertSame([$transformer], $segments->current()->steps()); - } - - public function test_all_returns_all_segments_including_current(): void - { - $segments = new Segments(); - $transformer1 = $this->createStubTransformer(); - $processor = $this->createStubProcessor(); - $transformer2 = $this->createStubTransformer(); - - $segments->add($transformer1); - $segments->add($processor); - $segments->add($transformer2); - - $allSegments = $segments->all(); - - static::assertCount(2, $allSegments); - static::assertSame([$transformer1], $allSegments[0]->steps()); - static::assertSame($processor, $allSegments[0]->processor()); - static::assertSame([$transformer2], $allSegments[1]->steps()); - static::assertNull($allSegments[1]->processor()); - } - - public function test_current_returns_current_segment_when_no_processors(): void - { - $segments = new Segments(); - $transformer = $this->createStubTransformer(); - - $segments->add($transformer); - - static::assertSame([$transformer], $segments->current()->steps()); - static::assertNull($segments->current()->processor()); - } - - public function test_current_returns_last_completed_segment_when_processors_exist(): void - { - $segments = new Segments(); - $transformer = $this->createStubTransformer(); - $processor = $this->createStubProcessor(); - - $segments->add($transformer); - $segments->add($processor); - - static::assertSame([$transformer], $segments->current()->steps()); - static::assertSame($processor, $segments->current()->processor()); - } - - public function test_has_finds_loader_in_completed_segment(): void - { - $segments = new Segments(); - $loader = $this->createStubLoader(); - $processor = $this->createStubProcessor(); - - $segments->add($loader); - $segments->add($processor); - - static::assertTrue($segments->has($loader::class)); - } - - public function test_has_finds_loader_in_current_segment(): void - { - $segments = new Segments(); - $loader = $this->createStubLoader(); - - $segments->add($loader); - - static::assertTrue($segments->has($loader::class)); - } - - public function test_has_finds_processor_in_completed_segment(): void - { - $segments = new Segments(); - $processor = $this->createStubProcessor(); - - $segments->add($processor); - - static::assertTrue($segments->has($processor::class)); - } - - public function test_has_finds_transformer_in_completed_segment(): void - { - $segments = new Segments(); - $transformer = $this->createStubTransformer(); - $processor = $this->createStubProcessor(); - - $segments->add($transformer); - $segments->add($processor); - - static::assertTrue($segments->has($transformer::class)); - } - - public function test_has_finds_transformer_in_current_segment(): void - { - $segments = new Segments(); - $transformer = $this->createStubTransformer(); - - $segments->add($transformer); - - static::assertTrue($segments->has($transformer::class)); - } - - public function test_has_returns_false_when_class_not_present(): void - { - $segments = new Segments(); - $transformer = $this->createStubTransformer(); - - $segments->add($transformer); - - static::assertFalse($segments->has(Loader::class)); - } - - public function test_multiple_processors_create_multiple_segments(): void - { - $segments = new Segments(); - $transformer1 = $this->createStubTransformer(); - $processor1 = $this->createStubProcessor(); - $transformer2 = $this->createStubTransformer(); - $processor2 = $this->createStubProcessor(); - $loader = $this->createStubLoader(); - - $segments->add($transformer1); - $segments->add($processor1); - $segments->add($transformer2); - $segments->add($processor2); - $segments->add($loader); - - $allSegments = $segments->all(); - - static::assertCount(3, $allSegments); - static::assertSame([$transformer1], $allSegments[0]->steps()); - static::assertSame($processor1, $allSegments[0]->processor()); - static::assertSame([$transformer2], $allSegments[1]->steps()); - static::assertSame($processor2, $allSegments[1]->processor()); - static::assertSame([$loader], $allSegments[2]->steps()); - static::assertNull($allSegments[2]->processor()); - } - - public function test_new_segments_has_one_empty_segment(): void - { - $segments = new Segments(); - - static::assertCount(1, $segments->all()); - static::assertSame([], $segments->current()->steps()); - } - - public function test_steps_returns_all_steps_flattened_including_processors(): void - { - $segments = new Segments(); - $transformer1 = $this->createStubTransformer(); - $loader1 = $this->createStubLoader(); - $processor = $this->createStubProcessor(); - $transformer2 = $this->createStubTransformer(); - $loader2 = $this->createStubLoader(); - - $segments->add($transformer1); - $segments->add($loader1); - $segments->add($processor); - $segments->add($transformer2); - $segments->add($loader2); - - static::assertSame([$transformer1, $loader1, $processor, $transformer2, $loader2], $segments->steps()); - } - - public function test_steps_returns_empty_array_for_new_segments(): void - { - $segments = new Segments(); - - static::assertSame([], $segments->steps()); - } - - public function test_steps_returns_steps_from_current_segment_only_when_no_processors(): void - { - $segments = new Segments(); - $transformer = $this->createStubTransformer(); - $loader = $this->createStubLoader(); - - $segments->add($transformer); - $segments->add($loader); - - static::assertSame([$transformer, $loader], $segments->steps()); - } - - private function createStubLoader(): Loader - { - return new class implements Loader { - public function load(Rows $rows, FlowContext $context): void {} - }; - } - - private function createStubProcessor(): Processor - { - return new class implements Processor { - public function bind(Schema $input): BoundStep - { - return new BoundStep($this, $input); - } - - public function process(Generator $rows, FlowContext $context): Generator - { - yield from $rows; - } - }; - } - - private function createStubTransformer(): Transformer - { - return new class implements Transformer { - public function bind(Schema $input): BoundStep - { - return new BoundStep($this, $input); - } - - public function transform(Rows $rows, FlowContext $context): Rows - { - return $rows; - } - }; - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Pipeline/TransformationStreamTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Pipeline/TransformationStreamTest.php deleted file mode 100644 index 2627d05d84..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Pipeline/TransformationStreamTest.php +++ /dev/null @@ -1,197 +0,0 @@ - $df->collect()), - schema(int_schema('id')), - $sink, - flow_context(config()), - ); - - $stream->feed(rows(schema(int_schema('id')), row(['id' => 1]))); - - $loadsBeforeDrain = $sink->loadsCount; - - try { - $stream->drain(); - - static::fail('Expected the sink failure to propagate out of drain().'); - } catch (RuntimeException $e) { - static::assertSame($failure, $e); - } - - static::assertSame(0, $loadsBeforeDrain); - static::assertSame(1, $sink->loadsCount); - } - - public function test_a_sink_failure_propagates_from_feed(): void - { - $failure = new RuntimeException('sink exploded'); - $stream = new TransformationStream( - select('id'), - schema(int_schema('id')), - new ThrowingLoader($failure), - flow_context(config()), - ); - - try { - $stream->feed(rows(schema(int_schema('id')), row(['id' => 1]))); - - static::fail('Expected the sink failure to propagate out of feed().'); - } catch (RuntimeException $e) { - static::assertSame($failure, $e); - } - } - - public function test_a_terminated_drive_ignores_later_feeds(): void - { - $sink = new SpyLoader(); - $stream = new TransformationStream( - new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df->limit(1)), - schema(int_schema('id')), - $sink, - flow_context(config()), - ); - - $stream->feed(rows(schema(int_schema('id')), row(['id' => 1]))); - $stream->feed(rows(schema(int_schema('id')), row(['id' => 2]))); - - static::assertSame(1, $sink->loadsCount); - - $stream->drain(); - - static::assertSame(1, $sink->loadsCount); - } - - public function test_a_triggering_transformation_is_refused(): void - { - try { - new TransformationStream( - new CallbackTransformation(static function (DataFrame $df): DataFrame { - $df->count(); - - return $df; - }), - schema(int_schema('id')), - new SpyLoader(), - flow_context(config()), - ); - - static::fail('Expected a Transformation triggering the nested frame to be refused.'); - } catch (InvalidLogicException $e) { - static::assertStringContainsString('to_branch()->withTransformation()', $e->getMessage()); - static::assertInstanceOf(FiberError::class, $e->getPrevious()); - } - } - - public function test_drain_before_any_feed_is_a_no_op(): void - { - $sink = new SpyLoader(); - - (new TransformationStream(select('id'), schema(int_schema('id')), $sink, flow_context(config())))->drain(); - - static::assertSame(0, $sink->loadsCount); - } - - public function test_drain_flushes_a_blocking_transformation(): void - { - $sink = new SpyLoader(); - $stream = new TransformationStream( - new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df->collect()), - schema(int_schema('id')), - $sink, - flow_context(config()), - ); - - $stream->feed(rows(schema(int_schema('id')), row(['id' => 1]))); - $stream->feed(rows(schema(int_schema('id')), row(['id' => 2]))); - $stream->feed(rows(schema(int_schema('id')), row(['id' => 3]))); - - $loadsBeforeDrain = $sink->loadsCount; - - $stream->drain(); - - static::assertSame(0, $loadsBeforeDrain); - static::assertSame(1, $sink->loadsCount); - static::assertSame([3], $sink->loadedRowCounts()); - } - - public function test_feed_delivers_transformed_rows_to_the_sink(): void - { - $sink = new SpyLoader(); - $context = flow_context(config()); - $stream = new TransformationStream( - select('id'), - schema(int_schema('id'), int_schema('other')), - $sink, - $context, - ); - - $stream->feed(rows(schema(int_schema('id'), int_schema('other')), row(['id' => 1, 'other' => 10]))); - $stream->feed(rows(schema(int_schema('id'), int_schema('other')), row(['id' => 2, 'other' => 20]))); - - static::assertSame(2, $sink->loadsCount); - static::assertSame([1, 1], $sink->loadedRowCounts()); - static::assertSame([$context, $context], $sink->contexts); - static::assertSame( - [[['id' => 1]], [['id' => 2]]], - array_map(static fn(Rows $rows): array => $rows->toArray(), $sink->loadedRows), - ); - } - - public function test_the_drive_knows_the_context_it_was_built_for(): void - { - $context = flow_context(config()); - $stream = new TransformationStream(select('id'), schema(int_schema('id')), new SpyLoader(), $context); - - static::assertTrue($stream->drivenBy($context)); - static::assertFalse($stream->drivenBy(flow_context(config()))); - } - - public function test_the_nested_frame_is_seeded_with_the_fed_shape(): void - { - $captured = null; - - new TransformationStream( - new CallbackTransformation(static function (DataFrame $df) use (&$captured): DataFrame { - $captured = $df->schema(); - - return $df; - }), - schema(int_schema('id'), int_schema('other')), - new SpyLoader(), - flow_context(config()), - ); - - static::assertEquals(schema(int_schema('id'), int_schema('other')), $captured); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Explain/BoxLayoutTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Explain/BoxLayoutTest.php new file mode 100644 index 0000000000..ce9a262b2c --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Explain/BoxLayoutTest.php @@ -0,0 +1,170 @@ +render((new Outline())->of($plan))); + } + + public function test_a_chain_stacks_boxes_joined_at_their_centers(): void + { + $plan = new Result(NodeMother::limit(new Collect(NodeMother::read()->withLimit(5)), 5)); + + static::assertSame(<<<'PLAN' + ┌───────────────────────────┐ + │ #4 Result │ + │ ──────────────────── │ + │ Rows this plan hands out: │ + │ to the trigger, or to the │ + │ node reading it │ + └─────────────┬─────────────┘ + ┌─────────────┴─────────────┐ + │ #3 Limit │ + │ ──────────────────── │ + │ Limit: 5 │ + └─────────────┬─────────────┘ + ┌─────────────┴─────────────┐ + │ #2 Collect │ + │ ──────────────────── │ + │ Buffers all rows before │ + │ passing them on │ + └─────────────┬─────────────┘ + ┌─────────────┴─────────────┐ + │ #1 Read │ + │ ──────────────────── │ + │ Extractor: ArrayExtractor │ + │ Limit: 5 │ + └───────────────────────────┘ + PLAN, (new BoxLayout())->render((new Outline())->of($plan))); + } + + public function test_a_later_child_hangs_off_the_right_edge_and_a_shared_node_is_a_leaf(): void + { + $filter = new Filter(NodeMother::read(), ref('id')->isNotNull()); + $plan = new Outputs(new Result($filter), new Write($filter, to_memory(new ArrayMemory()))); + + static::assertSame(<<<'PLAN' + ┌───────────────────────────┐ + │ Outputs ├──────────────┐ + └─────────────┬─────────────┘ │ + ┌─────────────┴─────────────┐┌─────────────┴─────────────┐ + │ #3 Result ││ #4 Write │ + │ ──────────────────── ││ ──────────────────── │ + │ Rows this plan hands out: ││ Loader: MemoryLoader │ + │ to the trigger, or to the ││ │ + │ node reading it ││ │ + └─────────────┬─────────────┘└─────────────┬─────────────┘ + ┌─────────────┴─────────────┐┌─────────────┴─────────────┐ + │ #2 Filter ││ #2 Filter │ + │ ──────────────────── ││ (shared) │ + │ Condition: IsNotNull ││ │ + └─────────────┬─────────────┘└───────────────────────────┘ + ┌─────────────┴─────────────┐ + │ #1 Read │ + │ ──────────────────── │ + │ Extractor: ArrayExtractor │ + └───────────────────────────┘ + PLAN, (new BoxLayout())->render((new Outline())->of($plan))); + } + + public function test_a_middle_child_branches_off_the_same_line(): void + { + $read = NodeMother::read(); + $plan = new Outputs( + new Result($read), + new Write($read, to_memory(new ArrayMemory())), + new Write(NodeMother::select($read), to_memory(new ArrayMemory())), + ); + + static::assertSame(<<<'PLAN' + ┌───────────────────────────┐ + │ Outputs ├──────────────┬────────────────────────────┐ + └─────────────┬─────────────┘ │ │ + ┌─────────────┴─────────────┐┌─────────────┴─────────────┐┌─────────────┴─────────────┐ + │ #2 Result ││ #3 Write ││ #5 Write │ + │ ──────────────────── ││ ──────────────────── ││ ──────────────────── │ + │ Rows this plan hands out: ││ Loader: MemoryLoader ││ Loader: MemoryLoader │ + │ to the trigger, or to the ││ ││ │ + │ node reading it ││ ││ │ + └─────────────┬─────────────┘└─────────────┬─────────────┘└─────────────┬─────────────┘ + ┌─────────────┴─────────────┐┌─────────────┴─────────────┐┌─────────────┴─────────────┐ + │ #1 Read ││ #1 Read ││ #4 Select │ + │ ──────────────────── ││ (shared) ││ ──────────────────── │ + │ Extractor: ArrayExtractor ││ ││ Columns: id │ + └───────────────────────────┘└───────────────────────────┘└─────────────┬─────────────┘ + ┌─────────────┴─────────────┐ + │ #1 Read │ + │ (shared) │ + └───────────────────────────┘ + PLAN, (new BoxLayout())->render((new Outline())->of($plan))); + } + + public function test_long_text_wraps_and_a_word_longer_than_the_box_is_split(): void + { + $plan = new Rename(NodeMother::read(), 'id', 'identifier_of_the_customer_order'); + + static::assertSame(<<<'PLAN' + ┌───────────────────────────┐ + │ #2 Rename │ + │ ──────────────────── │ + │ Rename: id → │ + │ identifier_of_the_custome │ + │ r_order │ + │ Defines columns: │ + │ identifier_of_the_custome │ + │ r_order │ + └─────────────┬─────────────┘ + ┌─────────────┴─────────────┐ + │ #1 Read │ + │ ──────────────────── │ + │ Extractor: ArrayExtractor │ + └───────────────────────────┘ + PLAN, (new BoxLayout())->render((new Outline())->of($plan))); + } + + public function test_span_counts_the_leaves_under_an_entry(): void + { + $read = NodeMother::read(); + $plan = new Outputs( + new Result($read), + new Write($read, to_memory(new ArrayMemory())), + new Write($read, to_memory(new ArrayMemory())), + ); + + static::assertSame(3, (new BoxLayout())->span((new Outline())->of($plan))); + static::assertSame(1, (new BoxLayout())->span((new Outline())->of($read))); + } + + public function test_wrap_keeps_short_text_on_one_line(): void + { + static::assertSame(['Limit: 5'], (new BoxLayout())->wrap('Limit: 5')); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Explain/BranchesTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Explain/BranchesTest.php new file mode 100644 index 0000000000..a345928f23 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Explain/BranchesTest.php @@ -0,0 +1,33 @@ +of(EntryMother::named('Read', 1), '│ ')); + } + + public function test_every_child_but_the_last_keeps_the_rail_open(): void + { + $first = EntryMother::named('Read', 2); + $second = EntryMother::named('Read', 3); + $third = EntryMother::named('Read', 4); + + static::assertSame( + [ + [$first, '│ ├─ ', '│ │ '], + [$second, '│ ├─ ', '│ │ '], + [$third, '│ └─ ', '│ '], + ], + (new Branches())->of(EntryMother::named('Read', 1, [$first, $second, $third]), '│ '), + ); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Explain/ConditionTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Explain/ConditionTest.php new file mode 100644 index 0000000000..ee4fff16bc --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Explain/ConditionTest.php @@ -0,0 +1,52 @@ +of(new Equal('id', 'user_id'))); + static::assertSame('id === user_id', (new Condition())->of(new Identical('id', 'user_id'))); + } + + public function test_an_and_is_one_line_per_comparison_and_anything_else_stays_one_line(): void + { + $condition = new Condition(); + + static::assertSame( + ['id = id', 'tag = tag'], + $condition->lines(new All(new Equal('id', 'id'), new Equal('tag', 'tag'))), + ); + static::assertSame( + ['id = id OR tag = tag'], + $condition->lines(new Any(new Equal('id', 'id'), new Equal('tag', 'tag'))), + ); + static::assertSame(['id = id'], $condition->lines(new Equal('id', 'id'))); + } + + public function test_nested_comparisons_keep_their_operators(): void + { + static::assertSame( + 'id = id AND (name = name OR tag === tag)', + (new Condition())->of( + new All(new Equal('id', 'id'), new Any(new Equal('name', 'name'), new Identical('tag', 'tag'))), + ), + ); + } + + public function test_a_comparison_the_explain_does_not_know_reads_as_its_name(): void + { + static::assertSame('AlwaysMeets', (new Condition())->of(new AlwaysMeets())); + } +} 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 new file mode 100644 index 0000000000..840ec84f82 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Explain/DetailsTest.php @@ -0,0 +1,193 @@ +name(NodeMother::select(NodeMother::read()))); + } + + public function test_a_read_lists_its_extractor_only_when_nothing_was_pushed_into_it(): void + { + static::assertSame(['Extractor: ArrayExtractor'], (new Details())->lines(NodeMother::read())); + } + + public function test_a_read_lists_a_pushed_limit_and_file_filter(): void + { + static::assertSame( + ['Extractor: ArrayExtractor', 'Limit: 3', 'Files: Filters'], + (new Details())->lines(NodeMother::read()->withLimit(3)->withPathFilter(new KeepAll())), + ); + } + + public function test_nodes_with_arguments_label_them(): void + { + $read = NodeMother::read(); + $details = new Details(); + + static::assertSame(['Condition: IsNotNull'], $details->lines(new Filter($read, ref('id')->isNotNull()))); + static::assertSame(['Until: Literal'], $details->lines(new Until($read, lit(true)))); + static::assertSame(['Loader: MemoryLoader'], $details->lines(new Write($read, to_memory(new ArrayMemory())))); + static::assertSame(['Limit: 5'], $details->lines(NodeMother::limit($read, 5))); + static::assertSame(['Skip: 2'], $details->lines(new Offset($read, 2))); + static::assertSame( + ['Top: 4', 'Buffers all rows before passing them on'], + $details->lines(new TopN($read, refs(ref('id')), 4)), + ); + } + + public function test_a_join_labels_its_type_and_condition(): void + { + static::assertSame( + [ + 'Type: left', + 'Left on: id', + 'Right on: id', + 'Buffers all rows before passing them on', + 'Defines columns known only at run time', + ], + (new Details())->lines(NodeMother::join( + NodeMother::read(), + NodeMother::joinRight(NodeMother::plan(NodeMother::read())), + )), + ); + } + + public function test_a_join_labels_a_prefix_and_an_algorithm_only_when_they_were_given(): void + { + static::assertSame( + [ + 'Type: right', + 'Left on: id, tag', + 'Right on: user_id, tag', + 'Prefix: joined_', + 'Algorithm: HashJoin', + ], + (new Details())->labelled( + new JoinNode( + NodeMother::read(), + NodeMother::joinRight(NodeMother::plan(NodeMother::read())), + Expression::on([new Equal('id', 'user_id'), new Equal('tag', 'tag')], 'joined_'), + Join::right, + hash_join(), + ), + ), + ); + } + + public function test_a_cross_join_labels_its_prefix_only_when_it_was_given(): void + { + $details = new Details(); + $right = NodeMother::joinRight(NodeMother::plan(NodeMother::read())); + + static::assertSame(['Type: cross'], $details->labelled(new CrossJoin(NodeMother::read(), $right))); + static::assertSame( + ['Type: cross', 'Prefix: r_'], + $details->labelled(new CrossJoin(NodeMother::read(), $right, 'r_')), + ); + } + + public function test_a_result_says_what_it_returns(): void + { + static::assertSame( + ['Rows this plan hands out: to the trigger, or to the node reading it'], + (new Details())->lines(new Result(NodeMother::read())), + ); + } + + public function test_a_node_without_arguments_has_no_details(): void + { + static::assertSame([], (new Details())->lines(new CollectRefs(NodeMother::read(), refs()))); + } + + public function test_a_blocking_node_says_it_buffers_rows(): void + { + static::assertSame( + ['Buffers all rows before passing them on'], + (new Details())->lines(new Collect(NodeMother::read())), + ); + } + + public function test_redefined_columns_follow_the_labelled_details(): void + { + $read = NodeMother::read(); + $details = new Details(); + + static::assertSame( + ['Column: n = Literal', 'Defines columns: n'], + $details->lines(new WithColumn($read, int_schema('n'), lit(1))), + ); + static::assertSame(['Rename: n → m', 'Defines columns: m'], $details->lines(new Rename($read, 'n', 'm'))); + static::assertSame( + ['Defines columns known only at run time'], + $details->lines(new RenameEach($read, [rename_replace('_', '-')])), + ); + } + + public function test_declarations_are_the_row_count_transparency_materialization_and_redefinitions(): void + { + $read = NodeMother::read(); + $details = new Details(); + + static::assertSame('preserving · transparent · blocking', $details->declarations(new Collect($read))); + static::assertSame( + 'preserving · transparent · streaming · redefines m', + $details->declarations(new Rename($read, 'n', 'm')), + ); + static::assertSame('preserving · transparent · streaming · redefines unknown', $details->declarations( + new RenameEach($read, [rename_replace('_', '-')]), + )); + } + + public function test_notes_leave_out_the_labelled_details(): void + { + $read = NodeMother::read(); + $details = new Details(); + + static::assertSame([], $details->notes(NodeMother::limit($read, 5))); + static::assertSame( + ['Buffers all rows before passing them on'], + $details->notes(new TopN($read, refs(ref('id')), 4)), + ); + static::assertSame(['Top: 4'], $details->labelled(new TopN($read, refs(ref('id')), 4))); + } + + public function test_name_of_any_object_drops_the_namespace(): void + { + static::assertSame('KeepAll', (new Details())->name(new KeepAll())); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Explain/EntryTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Explain/EntryTest.php new file mode 100644 index 0000000000..9d7d02cc35 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Explain/EntryTest.php @@ -0,0 +1,36 @@ +title()); + } + + public function test_title_of_an_entry_without_a_number_is_the_name(): void + { + static::assertSame('Outputs', EntryMother::named('Outputs', null)->title()); + } + + public function test_a_shared_entry_drops_the_details_the_first_visit_printed(): void + { + $shared = EntryMother::named( + 'Collect', + 2, + lines: ['Buffers all rows before passing them on'], + suffix: 'blocking', + )->with([], shared: true); + + static::assertSame([], $shared->lines); + static::assertSame('', $shared->suffix); + static::assertTrue($shared->shared); + static::assertSame('#2 Collect', $shared->title()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Explain/FlowLayoutTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Explain/FlowLayoutTest.php new file mode 100644 index 0000000000..b6650dea73 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Explain/FlowLayoutTest.php @@ -0,0 +1,100 @@ +withLimit(5)), 5)); + + static::assertSame(<<<'PLAN' + #1 Read + │ Extractor: ArrayExtractor + │ Limit: 5 + └─ #2 Collect + │ Buffers all rows before passing them on + └─ #3 Limit + │ Limit: 5 + └─ #4 Result + Rows this plan hands out: to the trigger, or to the node reading it + PLAN, (new FlowLayout())->render((new Outline())->of($plan))); + } + + public function test_a_node_read_by_several_consumers_branches_and_outputs_is_left_out(): void + { + $filter = new Filter(NodeMother::read(), ref('id')->isNotNull()); + $plan = new Outputs(new Result($filter), new Write($filter, to_memory(new ArrayMemory()))); + + static::assertSame(<<<'PLAN' + #1 Read + │ Extractor: ArrayExtractor + └─ #2 Filter + │ Condition: IsNotNull + ├─ #3 Result + │ Rows this plan hands out: to the trigger, or to the node reading it + └─ #4 Write + Loader: MemoryLoader + PLAN, (new FlowLayout())->render((new Outline())->of($plan))); + } + + public function test_every_reader_of_a_node_hangs_under_it(): void + { + $read = NodeMother::read(); + $plan = new Outputs( + new Result($read), + new Write($read, to_memory(new ArrayMemory())), + new Write(NodeMother::select($read), to_memory(new ArrayMemory())), + ); + + static::assertSame(<<<'PLAN' + #1 Read + │ Extractor: ArrayExtractor + ├─ #2 Result + │ Rows this plan hands out: to the trigger, or to the node reading it + ├─ #3 Write + │ Loader: MemoryLoader + └─ #4 Select + │ Columns: id + └─ #5 Write + Loader: MemoryLoader + PLAN, (new FlowLayout())->render((new Outline())->of($plan))); + } + + public function test_every_source_starts_its_own_tree_and_a_node_reached_again_is_shared(): void + { + $plan = new Result( + new CrossJoin(NodeMother::read(), NodeMother::joinRight(NodeMother::plan(NodeMother::read()))), + ); + + static::assertSame(<<<'PLAN' + #1 Read + │ Extractor: ArrayExtractor + └─ #3 CrossJoin + │ Type: cross + │ Defines columns known only at run time + └─ #4 Result + Rows this plan hands out: to the trigger, or to the node reading it + #2 Read + │ Extractor: ArrayExtractor + └─ #3 CrossJoin (shared) + PLAN, (new FlowLayout())->render((new Outline())->of($plan))); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Explain/OutlineTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Explain/OutlineTest.php new file mode 100644 index 0000000000..cd344b3dc3 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Explain/OutlineTest.php @@ -0,0 +1,95 @@ +of($select); + + static::assertSame($select, $root->source); + static::assertSame(2, $root->number); + static::assertFalse($root->shared); + static::assertCount(1, $root->children); + static::assertSame($read, $root->children[0]->source); + static::assertSame(1, $root->children[0]->number); + static::assertSame([], $root->children[0]->children); + } + + public function test_outputs_has_no_number_and_a_node_reached_again_is_a_shared_entry_with_its_number(): void + { + $select = NodeMother::select(NodeMother::read()); + $write = new Write($select, to_memory(new ArrayMemory())); + + $root = (new Outline())->of(new Outputs(new Result($select), $write)); + + [$result, $sink] = $root->children; + $shared = $sink->children[0]; + + static::assertNull($root->number); + static::assertSame(3, $result->number); + static::assertSame(2, $result->children[0]->number); + static::assertFalse($result->children[0]->shared); + static::assertSame(4, $sink->number); + static::assertSame($select, $shared->source); + static::assertSame(2, $shared->number); + static::assertTrue($shared->shared); + static::assertSame([], $shared->children); + } + + public function test_a_join_is_drawn_reading_what_its_right_sides_result_reads(): void + { + $limit = NodeMother::limit(NodeMother::read(), 5); + $frame = NodeMother::joinRight(NodeMother::plan($limit)); + + $join = (new Outline())->of(new Result(new CrossJoin(NodeMother::read(), $frame)))->children[0]; + $side = $join->children[1]; + + static::assertSame($limit, $side->source); + static::assertSame(3, $side->number); + static::assertSame(2, $side->children[0]->number); + static::assertSame(4, $join->number); + } + + public function test_a_node_both_sides_read_is_a_shared_entry_as_the_right_side(): void + { + $select = NodeMother::select(NodeMother::read()); + $frame = NodeMother::joinRight(NodeMother::plan($select)); + + $root = (new Outline())->of(new Result(new CrossJoin($select, $frame))); + + $shared = $root->children[0]->children[1]; + + static::assertSame($select, $shared->source); + static::assertTrue($shared->shared); + static::assertSame(2, $shared->number); + } + + public function test_an_outputs_right_side_stays_in_the_tree(): void + { + $read = NodeMother::read(); + $frame = new Outputs(new Result($read), new Write($read, to_memory(new ArrayMemory()))); + + $side = (new Outline())->of(new Result(new CrossJoin(NodeMother::read(), $frame)))->children[0]->children[1]; + + static::assertSame($frame, $side->source); + static::assertNull($side->number); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Explain/PhysicalOutlineTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Explain/PhysicalOutlineTest.php new file mode 100644 index 0000000000..bab0cb46aa --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Explain/PhysicalOutlineTest.php @@ -0,0 +1,106 @@ +of(PhysicalPlanMother::reading(from_array([['id' => 1]]))); + + static::assertSame('Physical plan', $root->name); + static::assertSame(['Columns: id'], $root->lines); + static::assertCount(1, $root->children); + static::assertSame('Pipeline #0', $root->children[0]->name); + static::assertSame(['Extractor: ArrayExtractor'], $root->children[0]->lines); + static::assertSame([], $root->children[0]->children); + } + + public function test_every_step_is_listed_in_the_order_the_rows_reach_it(): void + { + static::assertSame( + <<<'PLAN' + Physical plan + │ Columns: id + └─ Pipeline #0 + Extractor: ArrayExtractor + Processor: CollectingProcessor + Schema: declared + Loader: StreamLoader + PLAN, + (new TreeLayout())->render((new PhysicalOutline())->of(PhysicalPlanMother::of( + data_frame() + ->read(from_array([['id' => 1]])) + ->collect() + ->write(to_output(truncate: false)), + ))), + ); + } + + public function test_a_joined_frame_is_a_plan_of_its_own_under_the_step_that_reads_it(): void + { + static::assertSame( + <<<'PLAN' + Physical plan + │ Columns: id, joined_id + └─ Pipeline #1 + │ Processor: CollectingProcessor + │ Schema: declared + │ Loader: StreamLoader + └─ Pipeline #0 + │ Extractor: ArrayExtractor + │ Processor: HashJoinProcessor + │ Join: left + │ On: id = id + │ Prefix: joined_ + │ Storage: FilesystemBuckets + │ Buckets: 64 + │ Batch: 1000 + └─ Right side: Pipeline #0 + Extractor: ArrayExtractor + PLAN, + (new TreeLayout())->render((new PhysicalOutline())->of(PhysicalPlanMother::of( + data_frame() + ->read(from_array([['id' => 1]])) + ->join( + data_frame()->read(from_array([['id' => 1]])), + join_on(['id' => 'id'], join_prefix: 'joined_'), + ) + ->collect() + ->write(to_output(truncate: false)), + ))), + ); + } + + public function test_a_pushed_limit_is_listed_under_the_source_that_was_handed_it(): void + { + $root = (new PhysicalOutline())->of(PhysicalPlanMother::of( + data_frame()->read(from_array([['id' => 1], ['id' => 2]]))->limit(1), + )); + + static::assertSame( + ['Extractor: ArrayExtractor', ' Limit: 1', 'Transformer: LimitTransformer'], + $root->children[0]->lines, + ); + } + + public function test_a_plan_that_could_not_derive_its_schema_says_why(): void + { + $root = (new PhysicalOutline())->of(PhysicalPlanMother::reading(new UndescribableRowLessExtractor())); + + static::assertStringStartsWith('Schema: not derivable - ', $root->lines[0]); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Explain/StepDetailsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Explain/StepDetailsTest.php new file mode 100644 index 0000000000..cfdc09ae52 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Explain/StepDetailsTest.php @@ -0,0 +1,230 @@ +lines(from_array([['id' => 1]]))); + static::assertSame(['Processor: VoidProcessor'], $details->lines(new VoidProcessor())); + static::assertSame( + ['Processor: BatchingProcessor', ' Batch: 100'], + $details->lines(new BatchingProcessor(100)), + ); + } + + public function test_a_hash_join_lists_its_condition_and_the_storage_it_was_given(): void + { + static::assertSame( + [ + 'Processor: HashJoinProcessor', + ' Join: left', + ' On: id = id', + ' Prefix: joined_', + ' Storage: MemoryBuckets', + ' Buckets: 8', + ' Batch: 500', + ], + (new StepDetails())->lines(HashJoinProcessorMother::with( + PhysicalPlanMother::reading(from_array([['id' => 1]])), + Expression::on([new Equal('id', 'id')], 'joined_'), + Join::left, + new MemoryBuckets(), + 8, + 500, + )), + ); + } + + public function test_a_cross_join_lists_its_prefix_only_when_it_was_given(): void + { + $details = new StepDetails(); + $right = PhysicalPlanMother::reading(from_array([['id' => 1]])); + + static::assertSame(['Join: cross'], $details->settings(new CrossJoinRowsTransformer($right, new Executor()))); + static::assertSame( + ['Join: cross', 'Prefix: r_'], + $details->settings(new CrossJoinRowsTransformer($right, new Executor(), 'r_')), + ); + } + + public function test_sorting_steps_list_their_columns_with_the_direction(): void + { + $details = new StepDetails(); + + static::assertSame( + ['Sort: id asc, name desc'], + $details->settings(new MemorySortProcessor(refs(ref('id'), ref('name')->desc()))), + ); + static::assertSame( + ['Sort: id desc', 'Spill: MemoryBuckets', 'Merge: 4 ways', 'Batch: 50'], + $details->settings( + new MergeSortProcessor( + refs(ref('id')->desc()), + new Buckets(new MemoryBuckets()), + new Buckets(new MemoryBuckets()), + new NativePHPRandomValueGenerator(), + 4, + 50, + ), + ), + ); + static::assertSame(['Top: 3', 'Sort: id asc'], $details->settings(new TopNProcessor(refs(ref('id')), 3))); + } + + public function test_a_group_by_lists_its_columns_and_aggregations(): void + { + $groupBy = new GroupBy(ref('name')); + $groupBy->aggregate(sum(ref('id'))); + + static::assertSame( + ['Group by: name', 'Aggregations: Sum', 'Storage: MemoryBuckets', 'Batch: 25'], + (new StepDetails())->settings( + new GroupByAggregationProcessor($groupBy, new Buckets(new MemoryBuckets()), 25), + ), + ); + } + + public function test_a_pivot_lists_the_column_it_pivots_on(): void + { + $grouped = new GroupBy(ref('name')); + $grouped->aggregate(sum(ref('id'))); + + $pivoted = new GroupBy(ref('name')); + $pivoted->aggregate(sum(ref('id'))); + $pivoted->pivot(ref('country'), new DeclaredPivotValues('USA', 'China')); + + $details = new StepDetails(); + + static::assertSame(['Group by: name', 'Batch: 1000'], $details->settings(new PivotProcessor($grouped))); + static::assertSame( + ['Group by: name', 'Pivot: country', 'Batch: 500'], + $details->settings(new PivotProcessor($pivoted, 500)), + ); + } + + public function test_a_repartition_lists_its_columns_hasher_and_storage(): void + { + static::assertSame( + ['By: id', 'Hasher: NativeHasher', 'Storage: MemoryBuckets'], + (new StepDetails())->settings( + new RepartitionProcessor(refs(ref('id')), new Buckets(new MemoryBuckets()), new NativeHasher()), + ), + ); + } + + public function test_batching_by_a_column_lists_the_minimum_size_only_when_it_was_given(): void + { + $details = new StepDetails(); + + static::assertSame(['Batch by: id'], $details->settings(new BatchingByProcessor(ref('id')))); + static::assertSame( + ['Batch by: id', 'Min size: 10'], + $details->settings(new BatchingByProcessor(ref('id'), 10)), + ); + } + + public function test_a_caching_step_lists_its_id_only_when_it_was_given(): void + { + $details = new StepDetails(); + + static::assertSame([], $details->settings(new CachingProcessor())); + static::assertSame(['Id: orders'], $details->settings(new CachingProcessor('orders'))); + } + + public function test_a_collecting_step_says_when_a_schema_was_declared(): void + { + $details = new StepDetails(); + + static::assertSame([], $details->settings(new CollectingProcessor())); + static::assertSame(['Schema: declared'], $details->settings(new CollectingProcessor(schema(int_schema('id'))))); + } + + public function test_the_remaining_steps_list_what_they_were_given(): void + { + $details = new StepDetails(); + + static::assertSame(['Skip: 7'], $details->settings(new OffsetProcessor(7))); + static::assertSame([], $details->settings(new VoidProcessor())); + static::assertSame([], $details->settings(new ConstrainedProcessor())); + static::assertSame( + ['Constraints: UniqueConstraint'], + $details->settings(new ConstrainedProcessor([new UniqueConstraint(ref('id'))])), + ); + } + + public function test_a_window_lists_the_column_it_writes_and_its_function(): void + { + static::assertSame( + ['Column: rn', 'Function: RowNumber'], + (new StepDetails())->settings( + new WindowProcessor('rn', row_number()->over(window()->partitionBy(ref('id')))), + ), + ); + } + + public function test_a_step_the_explain_does_not_know_lists_nothing(): void + { + static::assertSame([], (new StepDetails())->settings(from_array([['id' => 1]]))); + } + + public function test_bucketing_lists_its_strategy_and_storage(): void + { + static::assertSame( + ['Strategy: HashBucketing', 'Storage: MemoryBuckets'], + (new StepDetails())->settings( + new BucketingProcessor( + new HashBucketing([ref('id')], 4, new NativeHasher(), new NativePHPRandomValueGenerator(), 'test'), + new Buckets(new MemoryBuckets()), + ), + ), + ); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Explain/TreeLayoutTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Explain/TreeLayoutTest.php new file mode 100644 index 0000000000..3f51fdfc36 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Explain/TreeLayoutTest.php @@ -0,0 +1,249 @@ +withLimit(5)), 5)); + + static::assertSame(<<<'PLAN' + #4 Result + │ Rows this plan hands out: to the trigger, or to the node reading it + └─ #3 Limit + │ Limit: 5 + └─ #2 Collect + │ Buffers all rows before passing them on + └─ #1 Read + Extractor: ArrayExtractor + Limit: 5 + PLAN, (new TreeLayout())->render((new Outline())->of($plan))); + } + + public function test_a_shared_node_is_referenced_by_number_and_name(): void + { + $filter = new Filter(NodeMother::read(), ref('id')->isNotNull()); + $plan = new Outputs(new Result($filter), new Write($filter, to_memory(new ArrayMemory()))); + + static::assertSame(<<<'PLAN' + Outputs + ├─ #3 Result + │ │ Rows this plan hands out: to the trigger, or to the node reading it + │ └─ #2 Filter + │ │ Condition: IsNotNull + │ └─ #1 Read + │ Extractor: ArrayExtractor + └─ #4 Write + │ Loader: MemoryLoader + └─ #2 Filter (shared) + PLAN, (new TreeLayout())->render((new Outline())->of($plan))); + } + + public function test_every_child_but_the_last_keeps_the_rail_open(): void + { + $read = NodeMother::read(); + $plan = new Outputs( + new Result($read), + new Write($read, to_memory(new ArrayMemory())), + new Write(NodeMother::select($read), to_memory(new ArrayMemory())), + ); + + static::assertSame(<<<'PLAN' + Outputs + ├─ #2 Result + │ │ Rows this plan hands out: to the trigger, or to the node reading it + │ └─ #1 Read + │ Extractor: ArrayExtractor + ├─ #3 Write + │ │ Loader: MemoryLoader + │ └─ #1 Read (shared) + └─ #5 Write + │ Loader: MemoryLoader + └─ #4 Select + │ Columns: id + └─ #1 Read (shared) + PLAN, (new TreeLayout())->render((new Outline())->of($plan))); + } + + public function test_with_declarations_a_single_chain_prints_one_line_per_node_with_its_declarations(): void + { + $plan = new LogicalPlan(new Result(NodeMother::limit(NodeMother::select(NodeMother::read()), 5))); + + static::assertSame(<<<'PLAN' + #4 Result preserving · transparent · streaming + │ Rows this plan hands out: to the trigger, or to the node reading it + └─ #3 Limit reducing · transparent · streaming + │ Limit: 5 + └─ #2 Select preserving · transparent · streaming + │ Columns: id + └─ #1 Read source · transparent · streaming + Extractor: ArrayExtractor + PLAN, (new TreeLayout())->render((new Outline(declarations: true))->of($plan->root))); + } + + public function test_with_declarations_a_subtree_two_consumers_share_is_printed_once(): void + { + $filter = new Filter(NodeMother::read(), ref('id')->isNotNull()); + $plan = new LogicalPlan(new Outputs(new Result($filter), new Write($filter, to_memory(new ArrayMemory())))); + + static::assertSame(<<<'PLAN' + Outputs preserving · opaque · streaming + ├─ #3 Result preserving · transparent · streaming + │ │ Rows this plan hands out: to the trigger, or to the node reading it + │ └─ #2 Filter reducing · transparent · streaming + │ │ Condition: IsNotNull + │ └─ #1 Read source · transparent · streaming + │ Extractor: ArrayExtractor + └─ #4 Write preserving · opaque · streaming + │ Loader: MemoryLoader + └─ #2 Filter (shared) + PLAN, (new TreeLayout())->render((new Outline(declarations: true))->of($plan->root))); + } + + public function test_with_declarations_payloads_and_redefinitions(): void + { + $read = NodeMother::read(); + $plan = new LogicalPlan(new Result( + new Until( + new Offset( + new Rename( + new WithColumn(new RenameEach($read, [rename_replace('_', '-')]), int_schema('n'), lit(1)), + 'n', + 'm', + ), + 2, + ), + lit(true), + ), + )); + + static::assertSame(<<<'PLAN' + #7 Result preserving · transparent · streaming + │ Rows this plan hands out: to the trigger, or to the node reading it + └─ #6 Until reducing · transparent · streaming + │ Until: Literal + └─ #5 Offset reducing · transparent · streaming + │ Skip: 2 + └─ #4 Rename preserving · transparent · streaming · redefines m + │ Rename: n → m + └─ #3 WithColumn preserving · transparent · streaming · redefines n + │ Column: n = Literal + └─ #2 RenameEach preserving · transparent · streaming · redefines unknown + └─ #1 Read source · transparent · streaming + Extractor: ArrayExtractor + PLAN, (new TreeLayout())->render((new Outline(declarations: true))->of($plan->root))); + } + + public function test_with_declarations_a_joined_frame_is_part_of_the_tree(): void + { + $plan = new LogicalPlan(new Result( + new CrossJoin(NodeMother::read(), NodeMother::joinRight(NodeMother::plan(NodeMother::read()))), + )); + + static::assertSame(<<<'PLAN' + #4 Result preserving · transparent · streaming + │ Rows this plan hands out: to the trigger, or to the node reading it + └─ #3 CrossJoin expanding · opaque · streaming · redefines unknown + │ Type: cross + ├─ #1 Read source · transparent · streaming + │ Extractor: ArrayExtractor + └─ #2 Read source · transparent · streaming + Extractor: ArrayExtractor + PLAN, (new TreeLayout())->render((new Outline(declarations: true))->of($plan->root))); + } + + public function test_with_declarations_a_pushed_limit_shows_on_the_read_line(): void + { + $plan = new LogicalPlan(new Result(NodeMother::read()->withLimit(3))); + + static::assertStringContainsString( + "Read source · transparent · streaming\n Extractor: ArrayExtractor\n Limit: 3", + (new TreeLayout())->render((new Outline(declarations: true))->of($plan->root)), + ); + } + + public function test_with_declarations_a_run_trigger_keeps_a_result_beside_the_write(): void + { + $read = NodeMother::read(); + $select = NodeMother::select($read); + + static::assertSame(<<<'PLAN' + Outputs preserving · opaque · streaming + ├─ #3 Result preserving · transparent · streaming + │ │ Rows this plan hands out: to the trigger, or to the node reading it + │ └─ #2 Select preserving · transparent · streaming + │ │ Columns: id + │ └─ #1 Read source · transparent · streaming + │ Extractor: ArrayExtractor + └─ #4 Write preserving · opaque · streaming + │ Loader: MemoryLoader + └─ #1 Read (shared) + PLAN, (new TreeLayout())->render((new Outline(declarations: true))->of(Trigger::run->plan( + $select, + new Sinks(new Write($read, to_memory(new ArrayMemory()))), + )->root))); + } + + public function test_with_declarations_a_transaction_root_child_lists_its_writes(): void + { + $read = NodeMother::read(); + $plan = new LogicalPlan( + new Outputs( + new Result($read), + new Transaction( + new RecordingTransaction(), + new Write($read, to_memory(new ArrayMemory())), + new Write(NodeMother::select($read), to_memory(new ArrayMemory())), + ), + ), + ); + + static::assertSame(<<<'PLAN' + Outputs preserving · opaque · streaming + ├─ #2 Result preserving · transparent · streaming + │ │ Rows this plan hands out: to the trigger, or to the node reading it + │ └─ #1 Read source · transparent · streaming + │ Extractor: ArrayExtractor + └─ #6 Transaction preserving · opaque · streaming + ├─ #3 Write preserving · opaque · streaming + │ │ Loader: MemoryLoader + │ └─ #1 Read (shared) + └─ #5 Write preserving · opaque · streaming + │ Loader: MemoryLoader + └─ #4 Select preserving · transparent · streaming + │ Columns: id + └─ #1 Read (shared) + PLAN, (new TreeLayout())->render((new Outline(declarations: true))->of($plan->root))); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/ExplainTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/ExplainTest.php new file mode 100644 index 0000000000..1991f497d2 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/ExplainTest.php @@ -0,0 +1,39 @@ +render((new Outline())->of($plan->root)), (new Explain())->of($plan)); + } + + public function test_each_format_renders_with_its_layout(): void + { + $plan = NodeMother::plan(new Result(NodeMother::limit(NodeMother::read(), 5))); + $outline = (new Outline())->of($plan->root); + + static::assertSame((new TreeLayout())->render($outline), (new Explain())->of($plan, Format::tree)); + static::assertSame((new BoxLayout())->render($outline), (new Explain())->of($plan, Format::boxes)); + static::assertSame((new FlowLayout())->render($outline), (new Explain())->of($plan, Format::flow)); + static::assertSame( + (new TreeLayout())->render((new Outline(declarations: true))->of($plan->root)), + (new Explain())->of($plan, Format::declarations), + ); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/LogicalPlanTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/LogicalPlanTest.php new file mode 100644 index 0000000000..f3ba70577c --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/LogicalPlanTest.php @@ -0,0 +1,298 @@ +sinks()->all(), + ); + } + + public function test_sink_roots_is_empty_for_a_result_root(): void + { + static::assertSame([], (new LogicalPlan(new Result(NodeMother::read())))->sinks()->all()); + } + + public function test_consumer_inputs_are_the_nodes_the_result_and_every_write_read(): void + { + $read = NodeMother::read(); + $select = NodeMother::select($read); + $limit = NodeMother::limit($read, 5); + + $consumers = (new LogicalPlan( + new Outputs( + new Result($select), + new Write($read, to_memory(new ArrayMemory())), + new Node\Transaction( + new RecordingTransaction(), + new Write($limit, to_memory(new ArrayMemory())), + new Write($select, to_memory(new ArrayMemory())), + ), + ), + ))->consumerInputs(); + + static::assertSame([$select, $read, $limit, $select], $consumers); + } + + public function test_sinks_on_spine_are_the_root_sinks_then_the_sinks_of_every_outputs_below(): void + { + $read = NodeMother::read(); + $inner = new Write($read, to_memory(new ArrayMemory())); + $innerRoot = new Outputs(new Result($read), $inner); + $select = NodeMother::select($innerRoot); + $outer = new Write($select, to_memory(new ArrayMemory())); + + static::assertSame( + [$outer, $inner], + (new LogicalPlan(new Outputs(new Result($select), $outer)))->sinksOnSpine()->all(), + ); + } + + public function test_sinks_on_spine_skip_the_sinks_of_a_joined_frame(): void + { + $right = NodeMother::read(); + $joined = new Outputs(new Result($right), new Write($right, to_memory(new ArrayMemory()))); + + static::assertSame( + [], + NodeMother::plan(NodeMother::crossJoin(NodeMother::read(), $joined))->sinksOnSpine()->all(), + ); + } + + public function test_sinks_stay_the_root_sinks_only(): void + { + $read = NodeMother::read(); + $innerRoot = new Outputs(new Result($read), new Write($read, to_memory(new ArrayMemory()))); + + static::assertSame([], NodeMother::plan($innerRoot)->sinks()->all()); + } + + public function test_consumer_inputs_include_the_inputs_of_sinks_below_the_root(): void + { + $read = NodeMother::read(); + $limit = NodeMother::limit($read, 5); + $innerRoot = new Outputs(new Result($read), new Write($limit, to_memory(new ArrayMemory()))); + $select = NodeMother::select($innerRoot); + + static::assertSame([$select, $limit], NodeMother::plan($select)->consumerInputs()); + } + + public function test_transform_up_with_replace_leaf_rewrites_the_leaf_and_keeps_the_spine(): void + { + $replacement = NodeMother::read(from_array([['id' => 2]])); + $plan = NodeMother::plan(NodeMother::select(NodeMother::read())); + + $rewritten = $plan->transformUp(new ReplaceLeaf($plan->source(), $replacement)); + + static::assertSame($replacement, $rewritten->source()); + $select = $rewritten->root->children()[0]; + static::assertInstanceOf(Node\Select::class, $select); + static::assertSame([$replacement], $select->children()); + } + + public function test_transform_up_rewrites_a_node_shared_by_the_spine_and_a_sink_once(): void + { + $select = NodeMother::select(NodeMother::read()); + $plan = new LogicalPlan( + new Outputs(new Result(NodeMother::limit($select, 5)), new Write($select, to_memory(new ArrayMemory()))), + ); + + $rewritten = $plan->transformUp(new RenameSelectRewrite()); + + $spineSelect = $rewritten->root->children()[0]->children()[0]->children()[0]; + static::assertInstanceOf(Node\Select::class, $spineSelect); + static::assertSame(['name'], $spineSelect->entries); + static::assertSame($spineSelect, $rewritten->sinks()->all()[0]->children()[0]); + } + + public function test_transform_up_refuses_an_outputs_consumer_rewritten_to_a_non_consumer(): void + { + $read = NodeMother::read(); + $plan = new LogicalPlan(new Outputs(new Result($read), new Write($read, to_memory(new ArrayMemory())))); + + $this->expectException(InvalidLogicException::class); + $this->expectExceptionMessage( + 'An Outputs consumer rewrite must return a Result, a Write or a Transaction, ' + . Node\Read::class + . ' given', + ); + + $plan->transformUp(new class implements Rewrite { + public function of(Node $node): Node + { + return $node instanceof Write ? $node->children()[0] : $node; + } + }); + } + + public function test_source_returns_the_read_leaf(): void + { + $read = NodeMother::read(); + + static::assertSame($read, NodeMother::plan(NodeMother::limit(NodeMother::select($read), 5))->source()); + } + + public function test_source_stops_at_this_frames_read_and_does_not_descend_into_a_joined_frame(): void + { + $read = NodeMother::read(); + $frame = NodeMother::joinRight(NodeMother::plan(NodeMother::read())); + + static::assertSame($read, NodeMother::plan(new Node\CrossJoin($read, $frame))->source()); + } + + public function test_source_throws_when_the_row_input_chain_does_not_end_in_a_read(): void + { + $leaf = new ChildlessNode(); + + $this->expectException(InvalidLogicException::class); + $this->expectExceptionMessage('A logical plan must end in a Read, ' . $leaf::class . ' found'); + + NodeMother::plan(NodeMother::select($leaf))->source(); + } + + public function test_transform_up_rebuilds_bottom_up(): void + { + $read = NodeMother::read(); + $plan = NodeMother::plan(NodeMother::limit(NodeMother::select($read), 5)); + + $rewritten = $plan->transformUp(new class implements Rewrite { + public function of(Node $node): Node + { + return $node instanceof Limit ? new Limit($node->children()[0], 1) : $node; + } + }); + + static::assertNotSame($plan, $rewritten); + $limit = $rewritten->root->children()[0]; + static::assertInstanceOf(Limit::class, $limit); + static::assertSame(1, $limit->limit); + static::assertSame($plan->root->children()[0]->children()[0], $limit->children()[0]); + static::assertSame($read, $rewritten->source()); + } + + public function test_transform_up_that_changes_nothing_returns_the_same_plan(): void + { + $plan = NodeMother::plan(NodeMother::limit(NodeMother::select(NodeMother::read()), 5)); + + $rewritten = $plan->transformUp(new class implements Rewrite { + public function of(Node $node): Node + { + return $node; + } + }); + + static::assertSame($plan, $rewritten); + } + + public function test_spine_is_the_chain_under_the_first_consumer(): void + { + $select = NodeMother::select(NodeMother::read()); + + static::assertSame($select, (new LogicalPlan(new Result($select)))->spine()); + static::assertSame( + $select, + (new LogicalPlan( + new Outputs(new Result($select), new Write($select, to_memory(new ArrayMemory()))), + ))->spine(), + ); + } + + public function test_spine_of_a_write_root_is_the_chain_that_write_reads(): void + { + $select = NodeMother::select(NodeMother::read()); + + static::assertSame($select, (new LogicalPlan(new Write($select, to_memory(new ArrayMemory()))))->spine()); + } + + public function test_spine_throws_when_the_root_carries_no_consumer(): void + { + $read = NodeMother::read(); + + $this->expectException(InvalidLogicException::class); + $this->expectExceptionMessage('A logical plan must have a consumer root, ' . $read::class . ' found'); + + (new LogicalPlan($read))->spine(); + } + + public function test_spine_throws_when_the_first_consumer_is_a_transaction(): void + { + $this->expectException(InvalidLogicException::class); + $this->expectExceptionMessage('The first consumer of a plan cannot be a Transaction'); + + $read = NodeMother::read(); + + (new LogicalPlan( + new Transaction(new RecordingTransaction(), new Write($read, to_memory(new ArrayMemory()))), + ))->spine(); + } + + public function test_sink_roots_of_a_write_root_are_that_write(): void + { + $write = new Write(NodeMother::read(), to_memory(new ArrayMemory())); + + static::assertSame([$write], (new LogicalPlan($write))->sinks()->all()); + } + + public function test_sink_roots_of_a_transaction_root_are_that_transaction(): void + { + $transaction = new Transaction( + new RecordingTransaction(), + new Write(NodeMother::read(), to_memory(new ArrayMemory())), + ); + + static::assertSame([$transaction], (new LogicalPlan($transaction))->sinks()->all()); + } + + public function test_consumer_inputs_of_a_write_root_are_the_chain_it_reads(): void + { + $select = NodeMother::select(NodeMother::read()); + + static::assertSame( + [$select], + (new LogicalPlan(new Write($select, to_memory(new ArrayMemory()))))->consumerInputs(), + ); + } + + public function test_consumer_inputs_of_a_result_and_a_write_are_the_chains_both_read(): void + { + $read = NodeMother::read(); + $select = NodeMother::select($read); + + static::assertSame( + [$read, $select], + (new LogicalPlan( + new Outputs(new Result($read), new Write($select, to_memory(new ArrayMemory()))), + ))->consumerInputs(), + ); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/AggregateTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/AggregateTest.php new file mode 100644 index 0000000000..388dce4c3a --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/AggregateTest.php @@ -0,0 +1,55 @@ +withChildren([$input])); + } + + public function test_with_children_returns_a_new_instance_when_a_child_changes(): void + { + $input = NodeMother::read(); + $other = NodeMother::read(); + $groupBy = new GroupBy('id'); + $algorithm = hash_group_by(); + $node = new Aggregate($input, $groupBy, $algorithm); + + $rebuilt = $node->withChildren([$other]); + + static::assertNotSame($node, $rebuilt); + static::assertInstanceOf(Aggregate::class, $rebuilt); + static::assertSame([$other], $rebuilt->children()); + static::assertSame($groupBy, $rebuilt->groupBy); + static::assertSame($algorithm, $rebuilt->algorithm); + } + + public function test_declarations(): void + { + $input = NodeMother::read(); + $node = new Aggregate($input, new GroupBy('id'), hash_group_by()); + + static::assertSame(RowCount::reducing, $node->rowCount()); + static::assertSame(Transparency::opaque, $node->transparency()); + static::assertSame(Materialization::blocking, $node->materialization()); + static::assertEquals(Redefined::unknown(), $node->redefines()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/BatchByTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/BatchByTest.php new file mode 100644 index 0000000000..66bcf7f3e4 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/BatchByTest.php @@ -0,0 +1,64 @@ +withChildren([$input])); + } + + public function test_with_children_returns_a_new_instance_when_a_child_changes(): void + { + $input = NodeMother::read(); + $other = NodeMother::read(); + $column = ref('id'); + $node = new BatchBy($input, $column, 5); + + $rebuilt = $node->withChildren([$other]); + + static::assertNotSame($node, $rebuilt); + static::assertInstanceOf(BatchBy::class, $rebuilt); + static::assertSame([$other], $rebuilt->children()); + static::assertSame($column, $rebuilt->column); + static::assertSame(5, $rebuilt->minSize); + } + + public function test_declarations(): void + { + $input = NodeMother::read(); + $node = new BatchBy($input, ref('id'), 5); + + static::assertSame(RowCount::preserving, $node->rowCount()); + static::assertSame(Transparency::transparent, $node->transparency()); + static::assertSame(Materialization::streaming, $node->materialization()); + static::assertEquals(Redefined::none(), $node->redefines()); + } + + public function test_a_min_size_of_zero_or_less_is_refused(): void + { + $column = ref('id'); + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Minimum batch size must be greater than 0, given: 0'); + + // @mago-ignore analysis:invalid-argument + new BatchBy(NodeMother::read(), $column, 0); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/BatchTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/BatchTest.php new file mode 100644 index 0000000000..f7fab15c5a --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/BatchTest.php @@ -0,0 +1,59 @@ +withChildren([$input])); + } + + public function test_with_children_returns_a_new_instance_when_a_child_changes(): void + { + $input = NodeMother::read(); + $other = NodeMother::read(); + $node = new Batch($input, 10); + + $rebuilt = $node->withChildren([$other]); + + static::assertNotSame($node, $rebuilt); + static::assertInstanceOf(Batch::class, $rebuilt); + static::assertSame([$other], $rebuilt->children()); + static::assertSame(10, $rebuilt->size); + } + + public function test_declarations(): void + { + $input = NodeMother::read(); + $node = new Batch($input, 10); + + static::assertSame(RowCount::preserving, $node->rowCount()); + static::assertSame(Transparency::transparent, $node->transparency()); + static::assertSame(Materialization::streaming, $node->materialization()); + static::assertEquals(Redefined::none(), $node->redefines()); + } + + public function test_a_size_of_zero_or_less_is_refused(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Batch size must be greater than 0, given: 0'); + + // @mago-ignore analysis:invalid-argument + new Batch(NodeMother::read(), 0); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/CacheTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/CacheTest.php new file mode 100644 index 0000000000..50b06b3ac6 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/CacheTest.php @@ -0,0 +1,53 @@ +withChildren([$input])); + } + + public function test_with_children_returns_a_new_instance_when_a_child_changes(): void + { + $input = NodeMother::read(); + $other = NodeMother::read(); + $cache = new InMemoryCache(); + $node = new Cache($input, 'cache-id', 100, $cache); + + $rebuilt = $node->withChildren([$other]); + + static::assertNotSame($node, $rebuilt); + static::assertInstanceOf(Cache::class, $rebuilt); + static::assertSame([$other], $rebuilt->children()); + static::assertSame('cache-id', $rebuilt->id); + static::assertSame(100, $rebuilt->batchSize); + static::assertSame($cache, $rebuilt->cache); + } + + public function test_declarations(): void + { + $input = NodeMother::read(); + $node = new Cache($input, 'cache-id', 100, new InMemoryCache()); + + static::assertSame(RowCount::preserving, $node->rowCount()); + static::assertSame(Transparency::opaque, $node->transparency()); + static::assertSame(Materialization::streaming, $node->materialization()); + static::assertEquals(Redefined::none(), $node->redefines()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/CollectRefsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/CollectRefsTest.php new file mode 100644 index 0000000000..46c434c7ee --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/CollectRefsTest.php @@ -0,0 +1,52 @@ +withChildren([$input])); + } + + public function test_with_children_returns_a_new_instance_when_a_child_changes(): void + { + $input = NodeMother::read(); + $other = NodeMother::read(); + $references = refs('id'); + $node = new CollectRefs($input, $references); + + $rebuilt = $node->withChildren([$other]); + + static::assertNotSame($node, $rebuilt); + static::assertInstanceOf(CollectRefs::class, $rebuilt); + static::assertSame([$other], $rebuilt->children()); + static::assertSame($references, $rebuilt->references); + } + + public function test_declarations(): void + { + $input = NodeMother::read(); + $node = new CollectRefs($input, refs('id')); + + static::assertSame(RowCount::preserving, $node->rowCount()); + static::assertSame(Transparency::opaque, $node->transparency()); + static::assertSame(Materialization::streaming, $node->materialization()); + static::assertEquals(Redefined::none(), $node->redefines()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/CollectTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/CollectTest.php new file mode 100644 index 0000000000..2d30f00744 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/CollectTest.php @@ -0,0 +1,48 @@ +withChildren([$input])); + } + + public function test_with_children_returns_a_new_instance_when_a_child_changes(): void + { + $input = NodeMother::read(); + $other = NodeMother::read(); + $node = new Collect($input); + + $rebuilt = $node->withChildren([$other]); + + static::assertNotSame($node, $rebuilt); + static::assertInstanceOf(Collect::class, $rebuilt); + static::assertSame([$other], $rebuilt->children()); + } + + public function test_declarations(): void + { + $input = NodeMother::read(); + $node = new Collect($input); + + static::assertSame(RowCount::preserving, $node->rowCount()); + static::assertSame(Transparency::transparent, $node->transparency()); + static::assertSame(Materialization::blocking, $node->materialization()); + static::assertEquals(Redefined::none(), $node->redefines()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/ConstrainTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/ConstrainTest.php new file mode 100644 index 0000000000..ad440640e6 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/ConstrainTest.php @@ -0,0 +1,51 @@ +withChildren([$input])); + } + + public function test_with_children_returns_a_new_instance_when_a_child_changes(): void + { + $input = NodeMother::read(); + $other = NodeMother::read(); + $constraints = [new UniqueConstraint('id')]; + $node = new Constrain($input, $constraints); + + $rebuilt = $node->withChildren([$other]); + + static::assertNotSame($node, $rebuilt); + static::assertInstanceOf(Constrain::class, $rebuilt); + static::assertSame([$other], $rebuilt->children()); + static::assertSame($constraints, $rebuilt->constraints); + } + + public function test_declarations(): void + { + $input = NodeMother::read(); + $node = new Constrain($input, [new UniqueConstraint('id')]); + + static::assertSame(RowCount::preserving, $node->rowCount()); + static::assertSame(Transparency::opaque, $node->transparency()); + static::assertSame(Materialization::streaming, $node->materialization()); + static::assertEquals(Redefined::none(), $node->redefines()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/CrossJoinTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/CrossJoinTest.php new file mode 100644 index 0000000000..14d491d655 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/CrossJoinTest.php @@ -0,0 +1,108 @@ +withChildren([$input, $frame])); + } + + public function test_with_children_returns_a_new_instance_when_a_child_changes(): void + { + $input = NodeMother::read(); + $other = NodeMother::read(); + $frame = NodeMother::joinRight(NodeMother::plan(NodeMother::read())); + $node = new CrossJoin($input, $frame, 'r_'); + + $rebuilt = $node->withChildren([$other, $frame]); + + static::assertNotSame($node, $rebuilt); + static::assertInstanceOf(CrossJoin::class, $rebuilt); + static::assertSame([$other, $frame], $rebuilt->children()); + static::assertSame('r_', $rebuilt->prefix); + } + + public function test_with_children_returns_a_new_instance_when_the_right_side_changes(): void + { + $input = NodeMother::read(); + $frame = NodeMother::joinRight(NodeMother::plan(NodeMother::read())); + $otherFrame = NodeMother::joinRight(NodeMother::plan(NodeMother::read())); + $node = new CrossJoin($input, $frame, 'r_'); + + $rebuilt = $node->withChildren([$input, $otherFrame]); + + static::assertNotSame($node, $rebuilt); + static::assertSame([$input, $otherFrame], $rebuilt->children()); + } + + public function test_an_outputs_root_is_accepted_as_the_right_side(): void + { + $input = NodeMother::read(); + $read = NodeMother::read(); + $frame = new Outputs(new Result($read), new Write($read, to_memory(new ArrayMemory()))); + + static::assertSame([$input, $frame], (new CrossJoin($input, $frame, 'r_'))->children()); + } + + public function test_a_right_side_that_is_not_a_plan_root_is_refused(): void + { + $input = NodeMother::read(); + + $this->expectException(InvalidLogicException::class); + $this->expectExceptionMessage( + 'The right side of a join must be a frame\'s plan root (Result or Outputs), ' . Read::class . ' given', + ); + + new CrossJoin($input, NodeMother::read(), 'r_'); + } + + public function test_with_children_refuses_a_right_side_that_is_not_a_plan_root(): void + { + $input = NodeMother::read(); + $frame = NodeMother::joinRight(NodeMother::plan(NodeMother::read())); + $node = new CrossJoin($input, $frame, 'r_'); + + $this->expectException(InvalidLogicException::class); + $this->expectExceptionMessage( + 'The right side of a join must be a frame\'s plan root (Result or Outputs), ' . Read::class . ' given', + ); + + $node->withChildren([$input, NodeMother::read()]); + } + + public function test_declarations(): void + { + $input = NodeMother::read(); + $frame = NodeMother::joinRight(NodeMother::plan(NodeMother::read())); + $node = new CrossJoin($input, $frame, 'r_'); + + static::assertSame(RowCount::expanding, $node->rowCount()); + static::assertSame(Transparency::opaque, $node->transparency()); + static::assertSame(Materialization::streaming, $node->materialization()); + static::assertEquals(Redefined::unknown(), $node->redefines()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/DiscardTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/DiscardTest.php new file mode 100644 index 0000000000..101263fcd5 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/DiscardTest.php @@ -0,0 +1,48 @@ +withChildren([$input])); + } + + public function test_with_children_returns_a_new_instance_when_a_child_changes(): void + { + $input = NodeMother::read(); + $other = NodeMother::read(); + $node = new Discard($input); + + $rebuilt = $node->withChildren([$other]); + + static::assertNotSame($node, $rebuilt); + static::assertInstanceOf(Discard::class, $rebuilt); + static::assertSame([$other], $rebuilt->children()); + } + + public function test_declarations(): void + { + $input = NodeMother::read(); + $node = new Discard($input); + + static::assertSame(RowCount::reducing, $node->rowCount()); + static::assertSame(Transparency::transparent, $node->transparency()); + static::assertSame(Materialization::blocking, $node->materialization()); + static::assertEquals(Redefined::none(), $node->redefines()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/DistinctTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/DistinctTest.php new file mode 100644 index 0000000000..5a85651366 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/DistinctTest.php @@ -0,0 +1,58 @@ +withChildren([$input])); + } + + public function test_with_children_returns_a_new_instance_when_a_child_changes(): void + { + $input = NodeMother::read(); + $other = NodeMother::read(); + $node = new Distinct($input, ['id']); + + $rebuilt = $node->withChildren([$other]); + + static::assertNotSame($node, $rebuilt); + static::assertInstanceOf(Distinct::class, $rebuilt); + static::assertSame([$other], $rebuilt->children()); + static::assertSame(['id'], $rebuilt->entries); + } + + public function test_declarations(): void + { + $input = NodeMother::read(); + $node = new Distinct($input, ['id']); + + static::assertSame(RowCount::reducing, $node->rowCount()); + static::assertSame(Transparency::transparent, $node->transparency()); + static::assertSame(Materialization::streaming, $node->materialization()); + static::assertEquals(Redefined::none(), $node->redefines()); + } + + public function test_no_entries_is_refused(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('DropDuplicatesTransformer requires at least one entry'); + + new Distinct(NodeMother::read(), []); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/DropTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/DropTest.php new file mode 100644 index 0000000000..494bd90af7 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/DropTest.php @@ -0,0 +1,49 @@ +withChildren([$input])); + } + + public function test_with_children_returns_a_new_instance_when_a_child_changes(): void + { + $input = NodeMother::read(); + $other = NodeMother::read(); + $node = new Drop($input, ['id']); + + $rebuilt = $node->withChildren([$other]); + + static::assertNotSame($node, $rebuilt); + static::assertInstanceOf(Drop::class, $rebuilt); + static::assertSame([$other], $rebuilt->children()); + static::assertSame(['id'], $rebuilt->entries); + } + + public function test_declarations(): void + { + $input = NodeMother::read(); + $node = new Drop($input, ['id']); + + static::assertSame(RowCount::preserving, $node->rowCount()); + static::assertSame(Transparency::transparent, $node->transparency()); + static::assertSame(Materialization::streaming, $node->materialization()); + static::assertEquals(Redefined::none(), $node->redefines()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/DuplicateRowTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/DuplicateRowTest.php new file mode 100644 index 0000000000..49d79f91b8 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/DuplicateRowTest.php @@ -0,0 +1,55 @@ +withChildren([$input])); + } + + public function test_with_children_returns_a_new_instance_when_a_child_changes(): void + { + $input = NodeMother::read(); + $other = NodeMother::read(); + $condition = lit(true); + $entries = [new WithEntry('copy', lit(1))]; + $node = new DuplicateRow($input, $condition, $entries); + + $rebuilt = $node->withChildren([$other]); + + static::assertNotSame($node, $rebuilt); + static::assertInstanceOf(DuplicateRow::class, $rebuilt); + static::assertSame([$other], $rebuilt->children()); + static::assertSame($condition, $rebuilt->condition); + static::assertSame($entries, $rebuilt->entries); + } + + public function test_declarations(): void + { + $input = NodeMother::read(); + $node = new DuplicateRow($input, lit(true), [new WithEntry('copy', lit(1))]); + + static::assertSame(RowCount::expanding, $node->rowCount()); + static::assertSame(Transparency::transparent, $node->transparency()); + static::assertSame(Materialization::streaming, $node->materialization()); + static::assertEquals(Redefined::names('copy'), $node->redefines()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/FilterTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/FilterTest.php new file mode 100644 index 0000000000..fc34816ed1 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/FilterTest.php @@ -0,0 +1,53 @@ +equals(lit(1))); + + static::assertSame($node, $node->withChildren([$input])); + } + + public function test_with_children_returns_a_new_instance_when_a_child_changes(): void + { + $input = NodeMother::read(); + $other = NodeMother::read(); + $function = ref('id')->equals(lit(1)); + $node = new Filter($input, $function); + + $rebuilt = $node->withChildren([$other]); + + static::assertNotSame($node, $rebuilt); + static::assertInstanceOf(Filter::class, $rebuilt); + static::assertSame([$other], $rebuilt->children()); + static::assertSame($function, $rebuilt->function); + } + + public function test_declarations(): void + { + $input = NodeMother::read(); + $node = new Filter($input, ref('id')->equals(lit(1))); + + static::assertSame(RowCount::reducing, $node->rowCount()); + static::assertSame(Transparency::transparent, $node->transparency()); + static::assertSame(Materialization::streaming, $node->materialization()); + static::assertEquals(Redefined::none(), $node->redefines()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/JoinEachTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/JoinEachTest.php new file mode 100644 index 0000000000..f43ae34179 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/JoinEachTest.php @@ -0,0 +1,69 @@ +read(from_array([['id' => 1]]))), + join_on(['id' => 'id']), + JoinType::left, + ); + + static::assertSame($node, $node->withChildren([$input])); + } + + public function test_with_children_returns_a_new_instance_when_a_child_changes(): void + { + $input = NodeMother::read(); + $other = NodeMother::read(); + $factory = new StaticDataFrameFactory(df()->read(from_array([['id' => 1]]))); + $on = join_on(['id' => 'id']); + $node = new JoinEach($input, $factory, $on, JoinType::left); + + $rebuilt = $node->withChildren([$other]); + + static::assertNotSame($node, $rebuilt); + static::assertInstanceOf(JoinEach::class, $rebuilt); + static::assertSame([$other], $rebuilt->children()); + static::assertSame($factory, $rebuilt->factory); + static::assertSame($on, $rebuilt->on); + static::assertSame(JoinType::left, $rebuilt->type); + } + + public function test_declarations(): void + { + $input = NodeMother::read(); + $node = new JoinEach( + $input, + new StaticDataFrameFactory(df()->read(from_array([['id' => 1]]))), + join_on(['id' => 'id']), + JoinType::left, + ); + + static::assertSame(RowCount::unknown, $node->rowCount()); + static::assertSame(Transparency::opaque, $node->transparency()); + static::assertSame(Materialization::streaming, $node->materialization()); + static::assertEquals(Redefined::unknown(), $node->redefines()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/JoinTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/JoinTest.php new file mode 100644 index 0000000000..bff95be03b --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/JoinTest.php @@ -0,0 +1,118 @@ + 'id']), JoinType::inner, hash_join()); + + static::assertSame($node, $node->withChildren([$input, $frame])); + } + + public function test_with_children_returns_a_new_instance_when_a_child_changes(): void + { + $input = NodeMother::read(); + $other = NodeMother::read(); + $frame = NodeMother::joinRight(NodeMother::plan(NodeMother::read())); + $on = join_on(['id' => 'id']); + $algorithm = hash_join(); + $node = new Join($input, $frame, $on, JoinType::inner, $algorithm); + + $rebuilt = $node->withChildren([$other, $frame]); + + static::assertNotSame($node, $rebuilt); + static::assertInstanceOf(Join::class, $rebuilt); + static::assertSame([$other, $frame], $rebuilt->children()); + static::assertSame($on, $rebuilt->on); + static::assertSame(JoinType::inner, $rebuilt->type); + static::assertSame($algorithm, $rebuilt->algorithm); + } + + public function test_with_children_returns_a_new_instance_when_the_right_side_changes(): void + { + $input = NodeMother::read(); + $frame = NodeMother::joinRight(NodeMother::plan(NodeMother::read())); + $otherFrame = NodeMother::joinRight(NodeMother::plan(NodeMother::read())); + $node = new Join($input, $frame, join_on(['id' => 'id']), JoinType::inner, hash_join()); + + $rebuilt = $node->withChildren([$input, $otherFrame]); + + static::assertNotSame($node, $rebuilt); + static::assertSame([$input, $otherFrame], $rebuilt->children()); + } + + public function test_an_outputs_root_is_accepted_as_the_right_side(): void + { + $input = NodeMother::read(); + $read = NodeMother::read(); + $frame = new Outputs(new Result($read), new Write($read, to_memory(new ArrayMemory()))); + + static::assertSame( + [$input, $frame], + (new Join($input, $frame, join_on(['id' => 'id']), JoinType::inner, hash_join()))->children(), + ); + } + + public function test_a_right_side_that_is_not_a_plan_root_is_refused(): void + { + $input = NodeMother::read(); + + $this->expectException(InvalidLogicException::class); + $this->expectExceptionMessage( + 'The right side of a join must be a frame\'s plan root (Result or Outputs), ' . Read::class . ' given', + ); + + new Join($input, NodeMother::read(), join_on(['id' => 'id']), JoinType::inner, hash_join()); + } + + public function test_with_children_refuses_a_right_side_that_is_not_a_plan_root(): void + { + $input = NodeMother::read(); + $frame = NodeMother::joinRight(NodeMother::plan(NodeMother::read())); + $node = new Join($input, $frame, join_on(['id' => 'id']), JoinType::inner, hash_join()); + + $this->expectException(InvalidLogicException::class); + $this->expectExceptionMessage( + 'The right side of a join must be a frame\'s plan root (Result or Outputs), ' . Read::class . ' given', + ); + + $node->withChildren([$input, NodeMother::read()]); + } + + public function test_declarations(): void + { + $input = NodeMother::read(); + $frame = NodeMother::joinRight(NodeMother::plan(NodeMother::read())); + $node = new Join($input, $frame, join_on(['id' => 'id']), JoinType::inner, hash_join()); + + static::assertSame(RowCount::unknown, $node->rowCount()); + static::assertSame(Transparency::opaque, $node->transparency()); + static::assertSame(Materialization::blocking, $node->materialization()); + static::assertEquals(Redefined::unknown(), $node->redefines()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/LimitTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/LimitTest.php new file mode 100644 index 0000000000..40f2608f4c --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/LimitTest.php @@ -0,0 +1,58 @@ +withChildren([$input])); + } + + public function test_with_children_returns_a_new_instance_when_a_child_changes(): void + { + $input = NodeMother::read(); + $other = NodeMother::read(); + $node = new Limit($input, 5); + + $rebuilt = $node->withChildren([$other]); + + static::assertNotSame($node, $rebuilt); + static::assertInstanceOf(Limit::class, $rebuilt); + static::assertSame([$other], $rebuilt->children()); + static::assertSame(5, $rebuilt->limit); + } + + public function test_declarations(): void + { + $input = NodeMother::read(); + $node = new Limit($input, 5); + + static::assertSame(RowCount::reducing, $node->rowCount()); + static::assertSame(Transparency::transparent, $node->transparency()); + static::assertSame(Materialization::streaming, $node->materialization()); + static::assertEquals(Redefined::none(), $node->redefines()); + } + + public function test_a_limit_of_zero_or_less_is_refused(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Limit can\'t be lower or equal zero, given: 0'); + + new Limit(NodeMother::read(), 0); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/OffsetTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/OffsetTest.php new file mode 100644 index 0000000000..cce6ac9c29 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/OffsetTest.php @@ -0,0 +1,59 @@ +withChildren([$input])); + } + + public function test_with_children_returns_a_new_instance_when_a_child_changes(): void + { + $input = NodeMother::read(); + $other = NodeMother::read(); + $node = new Offset($input, 3); + + $rebuilt = $node->withChildren([$other]); + + static::assertNotSame($node, $rebuilt); + static::assertInstanceOf(Offset::class, $rebuilt); + static::assertSame([$other], $rebuilt->children()); + static::assertSame(3, $rebuilt->offset); + } + + public function test_declarations(): void + { + $input = NodeMother::read(); + $node = new Offset($input, 3); + + static::assertSame(RowCount::reducing, $node->rowCount()); + static::assertSame(Transparency::transparent, $node->transparency()); + static::assertSame(Materialization::streaming, $node->materialization()); + static::assertEquals(Redefined::none(), $node->redefines()); + } + + public function test_a_negative_offset_is_refused(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Offset must be greater than or equal to 0, given: -1'); + + // @mago-ignore analysis:invalid-argument + new Offset(NodeMother::read(), -1); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/OutputsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/OutputsTest.php new file mode 100644 index 0000000000..c19b13c9eb --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/OutputsTest.php @@ -0,0 +1,132 @@ +children()); + } + + public function test_sinks_are_the_write_and_transaction_consumers(): void + { + $read = NodeMother::read(); + $write = new Write($read, to_memory(new ArrayMemory())); + $transaction = new Transaction(new RecordingTransaction(), new Write($read, to_memory(new ArrayMemory()))); + + static::assertSame( + [$write, $transaction], + (new Outputs(new Result($read), $write, $transaction))->sinks()->all(), + ); + } + + public function test_it_needs_two_or_more_consumers(): void + { + $this->expectException(InvalidLogicException::class); + $this->expectExceptionMessage('Outputs needs two or more consumers'); + + new Outputs(new Result(NodeMother::read())); + } + + public function test_a_write_is_accepted_as_the_spine_consumer(): void + { + $read = NodeMother::read(); + $first = new Write($read, to_memory(new ArrayMemory())); + $second = new Write($read, to_memory(new ArrayMemory())); + + static::assertSame([$first, $second], (new Outputs($first, $second))->children()); + } + + public function test_the_spine_consumer_cannot_be_a_transaction(): void + { + $read = NodeMother::read(); + + $this->expectException(InvalidLogicException::class); + $this->expectExceptionMessage('The first consumer of a plan cannot be a Transaction'); + + new Outputs( + new Transaction(new RecordingTransaction(), new Write($read, to_memory(new ArrayMemory()))), + new Write($read, to_memory(new ArrayMemory())), + ); + } + + public function test_with_children_returns_the_same_instance_when_children_are_identical(): void + { + $read = NodeMother::read(); + $node = new Outputs(new Result($read), new Write($read, to_memory(new ArrayMemory()))); + + static::assertSame($node, $node->withChildren($node->children())); + } + + public function test_with_children_rebuilds_over_new_consumers(): void + { + $read = NodeMother::read(); + $node = new Outputs(new Result($read), new Write($read, to_memory(new ArrayMemory()))); + $result = new Result(NodeMother::select($read)); + $write = new Write($read, to_memory(new ArrayMemory())); + + $rebuilt = $node->withChildren([$result, $write]); + + static::assertNotSame($node, $rebuilt); + static::assertSame([$result, $write], $rebuilt->children()); + } + + public function test_with_children_rebuilds_over_a_transaction_child(): void + { + $read = NodeMother::read(); + $node = new Outputs(new Result($read), new Write($read, to_memory(new ArrayMemory()))); + $transaction = new Transaction(new RecordingTransaction(), new Write($read, to_memory(new ArrayMemory()))); + + $rebuilt = $node->withChildren([$node->children()[0], $transaction]); + + static::assertSame([$node->children()[0], $transaction], $rebuilt->children()); + } + + public function test_with_children_refuses_a_child_that_is_not_a_consumer(): void + { + $read = NodeMother::read(); + $node = new Outputs(new Result($read), new Write($read, to_memory(new ArrayMemory()))); + + $this->expectException(InvalidLogicException::class); + $this->expectExceptionMessage( + 'An Outputs consumer rewrite must return a Result, a Write or a Transaction, ' . $read::class . ' given', + ); + + $node->withChildren([new Result($read), $read]); + } + + public function test_declarations(): void + { + $read = NodeMother::read(); + $node = new Outputs(new Result($read), new Write($read, to_memory(new ArrayMemory()))); + + static::assertSame(RowCount::preserving, $node->rowCount()); + static::assertSame(Transparency::opaque, $node->transparency()); + static::assertSame(Materialization::streaming, $node->materialization()); + static::assertEquals(Redefined::none(), $node->redefines()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/ReadTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/ReadTest.php new file mode 100644 index 0000000000..459547604d --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/ReadTest.php @@ -0,0 +1,115 @@ + 1]])))->children()); + } + + public function test_with_children_is_a_no_op(): void + { + $read = new Read(from_array([['id' => 1]])); + + static::assertSame($read, $read->withChildren([])); + } + + public function test_a_default_read_pushes_no_limit_and_lists_only_files(): void + { + $read = new Read(from_array([['id' => 1]])); + + static::assertNull($read->limit()); + static::assertInstanceOf(OnlyFiles::class, $read->pathFilter()); + } + + public function test_extractor_limit_and_path_filter_are_the_values_it_was_built_with(): void + { + $extractor = from_array([['id' => 1]]); + $filter = new RejectingFilter(); + + $read = new Read($extractor, 5, $filter); + + static::assertSame($extractor, $read->extractor()); + static::assertSame(5, $read->limit()); + static::assertSame($filter, $read->pathFilter()); + } + + public function test_with_path_filter_composes_with_the_filters_already_held(): void + { + $extractor = from_array([['id' => 1]]); + $read = new Read($extractor, 3); + $first = new RejectingFilter(); + $second = new RejectingFilter(); + + $filtered = $read->withPathFilter($first)->withPathFilter($second); + + static::assertInstanceOf(OnlyFiles::class, $read->pathFilter()); + static::assertEquals(new Filters(new OnlyFiles(), $first, $second), $filtered->pathFilter()); + static::assertSame(3, $filtered->limit()); + static::assertSame($extractor, $filtered->extractor()); + } + + public function test_with_limit_returns_a_new_read_and_leaves_the_original_alone(): void + { + $read = (new Read(from_array([['id' => 1]])))->withPathFilter($filter = new OnlyFiles()); + + $limited = $read->withLimit(5); + + static::assertNull($read->limit()); + static::assertSame(5, $limited->limit()); + static::assertEquals(new Filters(new OnlyFiles(), $filter), $limited->pathFilter()); + } + + public function test_with_limit_narrows_and_never_widens(): void + { + $read = new Read(from_array([['id' => 1]])); + + static::assertSame(10, $read->withLimit(10)->withLimit(100)->limit()); + static::assertSame(10, $read->withLimit(100)->withLimit(10)->limit()); + } + + public function test_with_limit_refuses_zero_or_less(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Limit must be greater than 0'); + + (new Read(from_array([['id' => 1]])))->withLimit(0); + } + + public function test_schema_delegates_to_the_extractor(): void + { + static::assertEquals( + schema(int_schema('id')), + (new Read(from_array([['id' => 1]], schema(int_schema('id')))))->schema(), + ); + } + + public function test_declarations(): void + { + $read = new Read(from_array([['id' => 1]])); + + static::assertSame(RowCount::source, $read->rowCount()); + static::assertSame(Transparency::transparent, $read->transparency()); + static::assertSame(Materialization::streaming, $read->materialization()); + static::assertEquals(Redefined::none(), $read->redefines()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/RenameEachTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/RenameEachTest.php new file mode 100644 index 0000000000..22acfa22d2 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/RenameEachTest.php @@ -0,0 +1,60 @@ + 'user_id'])]); + + static::assertSame($node, $node->withChildren([$input])); + } + + public function test_with_children_returns_a_new_instance_when_a_child_changes(): void + { + $input = NodeMother::read(); + $other = NodeMother::read(); + $strategies = [new RenameMapEntryStrategy(['id' => 'user_id'])]; + $node = new RenameEach($input, $strategies); + + $rebuilt = $node->withChildren([$other]); + + static::assertNotSame($node, $rebuilt); + static::assertInstanceOf(RenameEach::class, $rebuilt); + static::assertSame([$other], $rebuilt->children()); + static::assertSame($strategies, $rebuilt->strategies); + } + + public function test_declarations(): void + { + $input = NodeMother::read(); + $node = new RenameEach($input, [new RenameMapEntryStrategy(['id' => 'user_id'])]); + + static::assertSame(RowCount::preserving, $node->rowCount()); + static::assertSame(Transparency::transparent, $node->transparency()); + static::assertSame(Materialization::streaming, $node->materialization()); + static::assertEquals(Redefined::unknown(), $node->redefines()); + } + + public function test_no_strategies_is_refused(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('At least one strategy must be provided.'); + + new RenameEach(NodeMother::read(), []); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/RenameTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/RenameTest.php new file mode 100644 index 0000000000..5776bf92ca --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/RenameTest.php @@ -0,0 +1,50 @@ +withChildren([$input])); + } + + public function test_with_children_returns_a_new_instance_when_a_child_changes(): void + { + $input = NodeMother::read(); + $other = NodeMother::read(); + $node = new Rename($input, 'id', 'user_id'); + + $rebuilt = $node->withChildren([$other]); + + static::assertNotSame($node, $rebuilt); + static::assertInstanceOf(Rename::class, $rebuilt); + static::assertSame([$other], $rebuilt->children()); + static::assertSame('id', $rebuilt->from); + static::assertSame('user_id', $rebuilt->to); + } + + public function test_declarations(): void + { + $input = NodeMother::read(); + $node = new Rename($input, 'id', 'user_id'); + + static::assertSame(RowCount::preserving, $node->rowCount()); + static::assertSame(Transparency::transparent, $node->transparency()); + static::assertSame(Materialization::streaming, $node->materialization()); + static::assertEquals(Redefined::alias('user_id', 'id'), $node->redefines()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/RepartitionTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/RepartitionTest.php new file mode 100644 index 0000000000..9cdf499dd1 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/RepartitionTest.php @@ -0,0 +1,52 @@ +withChildren([$input])); + } + + public function test_with_children_returns_a_new_instance_when_a_child_changes(): void + { + $input = NodeMother::read(); + $other = NodeMother::read(); + $by = refs('id'); + $node = new Repartition($input, $by); + + $rebuilt = $node->withChildren([$other]); + + static::assertNotSame($node, $rebuilt); + static::assertInstanceOf(Repartition::class, $rebuilt); + static::assertSame([$other], $rebuilt->children()); + static::assertSame($by, $rebuilt->by); + } + + public function test_declarations(): void + { + $input = NodeMother::read(); + $node = new Repartition($input, refs('id')); + + static::assertSame(RowCount::preserving, $node->rowCount()); + static::assertSame(Transparency::opaque, $node->transparency()); + static::assertSame(Materialization::blocking, $node->materialization()); + static::assertEquals(Redefined::none(), $node->redefines()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/ResultTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/ResultTest.php new file mode 100644 index 0000000000..6ead2d4cb4 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/ResultTest.php @@ -0,0 +1,45 @@ +withChildren([$input])); + } + + public function test_with_children_returns_a_new_instance_when_the_input_changes(): void + { + $node = new Result(NodeMother::read()); + $other = NodeMother::read(); + + $rebuilt = $node->withChildren([$other]); + + static::assertNotSame($node, $rebuilt); + static::assertSame([$other], $rebuilt->children()); + } + + public function test_declarations(): void + { + $node = new Result(NodeMother::read()); + + static::assertSame(RowCount::preserving, $node->rowCount()); + static::assertSame(Transparency::transparent, $node->transparency()); + static::assertSame(Materialization::streaming, $node->materialization()); + static::assertEquals(Redefined::none(), $node->redefines()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/SelectTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/SelectTest.php new file mode 100644 index 0000000000..f934c68ef9 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/SelectTest.php @@ -0,0 +1,49 @@ +withChildren([$input])); + } + + public function test_with_children_returns_a_new_instance_when_a_child_changes(): void + { + $input = NodeMother::read(); + $other = NodeMother::read(); + $node = new Select($input, ['id']); + + $rebuilt = $node->withChildren([$other]); + + static::assertNotSame($node, $rebuilt); + static::assertInstanceOf(Select::class, $rebuilt); + static::assertSame([$other], $rebuilt->children()); + static::assertSame(['id'], $rebuilt->entries); + } + + public function test_declarations(): void + { + $input = NodeMother::read(); + $node = new Select($input, ['id']); + + static::assertSame(RowCount::preserving, $node->rowCount()); + static::assertSame(Transparency::transparent, $node->transparency()); + static::assertSame(Materialization::streaming, $node->materialization()); + static::assertEquals(Redefined::none(), $node->redefines()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/SortTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/SortTest.php new file mode 100644 index 0000000000..e7026b6191 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/SortTest.php @@ -0,0 +1,56 @@ +withChildren([$input])); + } + + public function test_with_children_returns_a_new_instance_when_a_child_changes(): void + { + $input = NodeMother::read(); + $other = NodeMother::read(); + $refs = refs(ref('id')); + $algorithm = memory_sort(); + $node = new Sort($input, $refs, $algorithm); + + $rebuilt = $node->withChildren([$other]); + + static::assertNotSame($node, $rebuilt); + static::assertInstanceOf(Sort::class, $rebuilt); + static::assertSame([$other], $rebuilt->children()); + static::assertSame($refs, $rebuilt->refs); + static::assertSame($algorithm, $rebuilt->algorithm); + } + + public function test_declarations(): void + { + $input = NodeMother::read(); + $node = new Sort($input, refs(ref('id')), memory_sort()); + + static::assertSame(RowCount::preserving, $node->rowCount()); + static::assertSame(Transparency::opaque, $node->transparency()); + static::assertSame(Materialization::blocking, $node->materialization()); + static::assertEquals(Redefined::none(), $node->redefines()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/TopNTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/TopNTest.php new file mode 100644 index 0000000000..41665ba626 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/TopNTest.php @@ -0,0 +1,65 @@ +children()); + } + + public function test_with_children_returns_the_same_instance_when_children_are_identical(): void + { + $input = NodeMother::read(); + $node = new TopN($input, refs(ref('id')), 3); + + static::assertSame($node, $node->withChildren([$input])); + } + + public function test_with_children_keeps_refs_and_limit_over_a_new_input(): void + { + $refs = refs(ref('id')); + $replacement = NodeMother::read(); + + $rebuilt = (new TopN(NodeMother::read(), $refs, 3))->withChildren([$replacement]); + + static::assertSame([$replacement], $rebuilt->children()); + static::assertSame($refs, $rebuilt->refs); + static::assertSame(3, $rebuilt->limit); + } + + public function test_a_limit_below_one_is_refused(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('TopN limit must be greater than 0, given: 0'); + + new TopN(NodeMother::read(), refs(ref('id')), 0); + } + + public function test_declarations(): void + { + $node = new TopN(NodeMother::read(), refs(ref('id')), 3); + + static::assertSame(RowCount::reducing, $node->rowCount()); + static::assertSame(Transparency::opaque, $node->transparency()); + static::assertSame(Materialization::blocking, $node->materialization()); + static::assertEquals(Redefined::none(), $node->redefines()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/TransactionTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/TransactionTest.php new file mode 100644 index 0000000000..13e5363055 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/TransactionTest.php @@ -0,0 +1,110 @@ +children(), + ); + } + + public function test_a_transaction_without_a_write_is_refused(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('At least one loader must be provided'); + + new Transaction(new RecordingTransaction()); + } + + public function test_with_children_returns_the_same_instance_when_children_are_identical(): void + { + $write = new Write(NodeMother::read(), to_memory(new ArrayMemory())); + $node = new Transaction(new RecordingTransaction(), $write); + + static::assertSame($node, $node->withChildren([$write])); + } + + public function test_with_children_rebuilds_and_keeps_the_transaction(): void + { + $transaction = new RecordingTransaction(); + $node = new Transaction($transaction, new Write(NodeMother::read(), to_memory(new ArrayMemory()))); + $other = new Write(NodeMother::read(), to_memory(new ArrayMemory())); + + $rebuilt = $node->withChildren([$other]); + + static::assertNotSame($node, $rebuilt); + static::assertSame([$other], $rebuilt->children()); + static::assertSame($transaction, $rebuilt->transaction); + } + + public function test_with_children_refuses_a_child_that_is_not_a_write(): void + { + $node = new Transaction( + new RecordingTransaction(), + new Write(NodeMother::read(), to_memory(new ArrayMemory())), + ); + + $this->expectException(InvalidLogicException::class); + $this->expectExceptionMessage( + 'A sink root rewrite must return a Write or a Transaction, ' . Read::class . ' given', + ); + + $node->withChildren([NodeMother::read()]); + } + + public function test_the_source_is_reached_through_a_transaction(): void + { + $read = NodeMother::read(); + + static::assertSame( + $read, + (new LogicalPlan(new Result( + new Transaction( + new RecordingTransaction(), + new Write(NodeMother::select($read), to_memory(new ArrayMemory())), + ), + )))->source(), + ); + } + + public function test_declarations(): void + { + $node = new Transaction( + new RecordingTransaction(), + new Write(NodeMother::read(), to_memory(new ArrayMemory())), + ); + + static::assertSame(RowCount::preserving, $node->rowCount()); + static::assertSame(Transparency::opaque, $node->transparency()); + static::assertSame(Materialization::streaming, $node->materialization()); + static::assertEquals(Redefined::none(), $node->redefines()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/TransformTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/TransformTest.php new file mode 100644 index 0000000000..640c9982e1 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/TransformTest.php @@ -0,0 +1,51 @@ +withChildren([$input])); + } + + public function test_with_children_returns_a_new_instance_when_a_child_changes(): void + { + $input = NodeMother::read(); + $other = NodeMother::read(); + $transformer = new SelectEntriesTransformer('id'); + $node = new Transform($input, $transformer); + + $rebuilt = $node->withChildren([$other]); + + static::assertNotSame($node, $rebuilt); + static::assertInstanceOf(Transform::class, $rebuilt); + static::assertSame([$other], $rebuilt->children()); + static::assertSame($transformer, $rebuilt->transformer); + } + + public function test_declarations(): void + { + $input = NodeMother::read(); + $node = new Transform($input, new SelectEntriesTransformer('id')); + + static::assertSame(RowCount::unknown, $node->rowCount()); + static::assertSame(Transparency::opaque, $node->transparency()); + static::assertSame(Materialization::streaming, $node->materialization()); + static::assertEquals(Redefined::unknown(), $node->redefines()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/UntilTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/UntilTest.php new file mode 100644 index 0000000000..d6a2379885 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/UntilTest.php @@ -0,0 +1,53 @@ +equals(lit(1))); + + static::assertSame($node, $node->withChildren([$input])); + } + + public function test_with_children_returns_a_new_instance_when_a_child_changes(): void + { + $input = NodeMother::read(); + $other = NodeMother::read(); + $function = ref('id')->equals(lit(1)); + $node = new Until($input, $function); + + $rebuilt = $node->withChildren([$other]); + + static::assertNotSame($node, $rebuilt); + static::assertInstanceOf(Until::class, $rebuilt); + static::assertSame([$other], $rebuilt->children()); + static::assertSame($function, $rebuilt->function); + } + + public function test_declarations(): void + { + $input = NodeMother::read(); + $node = new Until($input, ref('id')->equals(lit(1))); + + static::assertSame(RowCount::reducing, $node->rowCount()); + static::assertSame(Transparency::transparent, $node->transparency()); + static::assertSame(Materialization::streaming, $node->materialization()); + static::assertEquals(Redefined::none(), $node->redefines()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/ValidateTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/ValidateTest.php new file mode 100644 index 0000000000..c6e7713965 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/ValidateTest.php @@ -0,0 +1,56 @@ +withChildren([$input])); + } + + public function test_with_children_returns_a_new_instance_when_a_child_changes(): void + { + $input = NodeMother::read(); + $other = NodeMother::read(); + $schema = schema(int_schema('id')); + $validator = new StrictValidator(); + $node = new Validate($input, $schema, $validator); + + $rebuilt = $node->withChildren([$other]); + + static::assertNotSame($node, $rebuilt); + static::assertInstanceOf(Validate::class, $rebuilt); + static::assertSame([$other], $rebuilt->children()); + static::assertSame($schema, $rebuilt->schema); + static::assertSame($validator, $rebuilt->validator); + } + + public function test_declarations(): void + { + $input = NodeMother::read(); + $node = new Validate($input, schema(int_schema('id')), new StrictValidator()); + + static::assertSame(RowCount::preserving, $node->rowCount()); + static::assertSame(Transparency::opaque, $node->transparency()); + static::assertSame(Materialization::streaming, $node->materialization()); + static::assertEquals(Redefined::none(), $node->redefines()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/WindowColumnTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/WindowColumnTest.php new file mode 100644 index 0000000000..3034d4c1f1 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/WindowColumnTest.php @@ -0,0 +1,55 @@ +over(window()->orderBy(ref('id')))); + + static::assertSame($node, $node->withChildren([$input])); + } + + public function test_with_children_returns_a_new_instance_when_a_child_changes(): void + { + $input = NodeMother::read(); + $other = NodeMother::read(); + $function = rank()->over(window()->orderBy(ref('id'))); + $node = new WindowColumn($input, 'rank', $function); + + $rebuilt = $node->withChildren([$other]); + + static::assertNotSame($node, $rebuilt); + static::assertInstanceOf(WindowColumn::class, $rebuilt); + static::assertSame([$other], $rebuilt->children()); + static::assertSame('rank', $rebuilt->entry); + static::assertSame($function, $rebuilt->function); + } + + public function test_declarations(): void + { + $input = NodeMother::read(); + $node = new WindowColumn($input, 'rank', rank()->over(window()->orderBy(ref('id')))); + + static::assertSame(RowCount::preserving, $node->rowCount()); + static::assertSame(Transparency::opaque, $node->transparency()); + static::assertSame(Materialization::blocking, $node->materialization()); + static::assertEquals(Redefined::names('rank'), $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 new file mode 100644 index 0000000000..61557a5b3b --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/WithColumnTest.php @@ -0,0 +1,102 @@ +multiply(lit(2))))->children()); + } + + public function test_with_children_returns_the_same_instance_when_children_are_identical(): void + { + $input = NodeMother::read(); + $node = new WithColumn($input, 'doubled', ref('id')->multiply(lit(2))); + + static::assertSame($node, $node->withChildren([$input])); + } + + public function test_with_children_returns_a_new_instance_when_a_child_changes(): void + { + $other = NodeMother::read(); + $function = ref('id')->multiply(lit(2)); + $node = new WithColumn(NodeMother::read(), 'doubled', $function); + + $rebuilt = $node->withChildren([$other]); + + static::assertNotSame($node, $rebuilt); + static::assertSame([$other], $rebuilt->children()); + static::assertSame('doubled', $rebuilt->entry); + static::assertSame($function, $rebuilt->function); + } + + public function test_entry_and_function_are_the_values_it_was_built_with(): void + { + $function = ref('id')->multiply(lit(2)); + $node = new WithColumn(NodeMother::read(), 'doubled', $function); + + static::assertSame('doubled', $node->entry); + static::assertSame($function, $node->function); + } + + public function test_declarations(): void + { + $node = new WithColumn(NodeMother::read(), 'doubled', ref('id')->multiply(lit(2))); + + static::assertSame(RowCount::preserving, $node->rowCount()); + static::assertSame(Transparency::transparent, $node->transparency()); + static::assertSame(Materialization::streaming, $node->materialization()); + 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))); + + static::assertEquals(Redefined::names('doubled'), $node->redefines()); + } + + public function test_a_bare_reference_under_a_plain_name_is_an_alias(): void + { + $node = new WithColumn(NodeMother::read(), 'copy', ref('id')); + + static::assertEquals(Redefined::alias('copy', 'id'), $node->redefines()); + } + + public function test_a_bare_reference_under_a_definition_is_not_an_alias(): void + { + $node = new WithColumn(NodeMother::read(), int_schema('copy'), ref('id')); + + static::assertEquals(Redefined::names('copy'), $node->redefines()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/WriteTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/WriteTest.php new file mode 100644 index 0000000000..71e4397a2d --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/Node/WriteTest.php @@ -0,0 +1,53 @@ +withChildren([$input])); + } + + public function test_with_children_returns_a_new_instance_when_a_child_changes(): void + { + $input = NodeMother::read(); + $other = NodeMother::read(); + $loader = to_memory(new ArrayMemory()); + $node = new Write($input, $loader); + + $rebuilt = $node->withChildren([$other]); + + static::assertNotSame($node, $rebuilt); + static::assertInstanceOf(Write::class, $rebuilt); + static::assertSame([$other], $rebuilt->children()); + static::assertSame($loader, $rebuilt->loader); + } + + public function test_declarations(): void + { + $input = NodeMother::read(); + $node = new Write($input, to_memory(new ArrayMemory())); + + static::assertSame(RowCount::preserving, $node->rowCount()); + static::assertSame(Transparency::opaque, $node->transparency()); + static::assertSame(Materialization::streaming, $node->materialization()); + static::assertEquals(Redefined::none(), $node->redefines()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/RedefinedTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/RedefinedTest.php new file mode 100644 index 0000000000..21ddb51400 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/RedefinedTest.php @@ -0,0 +1,52 @@ +defines('year')); + static::assertSame([], Redefined::none()->names); + static::assertFalse(Redefined::none()->unknown); + } + + public function test_names_define_exactly_those_names_and_alias_none(): void + { + $redefined = Redefined::names('year', 'month'); + + static::assertTrue($redefined->defines('month')); + static::assertFalse($redefined->defines('day')); + static::assertNull($redefined->aliasOf('month')); + static::assertSame(['year', 'month'], $redefined->names); + } + + public function test_unknown_defines_every_name_and_aliases_none(): void + { + static::assertTrue(Redefined::unknown()->defines('anything')); + static::assertNull(Redefined::unknown()->aliasOf('anything')); + static::assertTrue(Redefined::unknown()->unknown); + } + + public function test_names_with_no_names_defines_nothing(): void + { + static::assertFalse(Redefined::names()->defines('year')); + static::assertSame([], Redefined::names()->names); + } + + public function test_an_alias_defines_its_name_and_points_it_at_the_column_below(): void + { + $redefined = Redefined::alias('y', 'year'); + + static::assertTrue($redefined->defines('y')); + static::assertFalse($redefined->defines('year')); + static::assertSame('year', $redefined->aliasOf('y')); + static::assertNull($redefined->aliasOf('year')); + static::assertSame(['y'], $redefined->names); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/ReplaceLeafTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/ReplaceLeafTest.php new file mode 100644 index 0000000000..720dace269 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/ReplaceLeafTest.php @@ -0,0 +1,27 @@ +of($target)); + } + + public function test_any_other_node_is_returned_unchanged(): void + { + $other = NodeMother::select(NodeMother::read()); + + static::assertSame($other, (new ReplaceLeaf(NodeMother::read(), NodeMother::read()))->of($other)); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/SinksTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/SinksTest.php new file mode 100644 index 0000000000..7bfe5f478e --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/SinksTest.php @@ -0,0 +1,52 @@ +all()); + static::assertSame([], iterator_to_array($sinks)); + } + + public function test_it_keeps_the_sinks_in_the_order_given(): void + { + $read = NodeMother::read(); + $write = new Write($read, to_memory(new ArrayMemory())); + $transaction = new Transaction(new RecordingTransaction(), new Write($read, to_memory(new ArrayMemory()))); + + $sinks = new Sinks($write, $transaction); + + static::assertSame([$write, $transaction], $sinks->all()); + static::assertSame([$write, $transaction], iterator_to_array($sinks)); + } + + public function test_merge_appends_the_given_sinks_after_its_own(): void + { + $read = NodeMother::read(); + $first = new Write($read, to_memory(new ArrayMemory())); + $second = new Write($read, to_memory(new ArrayMemory())); + $sinks = new Sinks($first); + + $merged = $sinks->merge(new Sinks($second)); + + static::assertSame([$first, $second], $merged->all()); + static::assertSame([$first], $sinks->all()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/TransformUpTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/TransformUpTest.php new file mode 100644 index 0000000000..94628a6ba5 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/TransformUpTest.php @@ -0,0 +1,110 @@ +of(NodeMother::limit(NodeMother::select(NodeMother::read()), 5), new class( + $visited, + ) implements Rewrite { + /** + * @param list> $visited + */ + public function __construct( + private array &$visited, + ) {} + + public function of(Node $node): Node + { + $this->visited[] = $node::class; + + return $node; + } + }); + + static::assertSame([Read::class, Select::class, Limit::class], $visited); + } + + public function test_a_rewrite_that_changes_nothing_returns_the_same_root_object(): void + { + $root = NodeMother::limit(NodeMother::select(NodeMother::read()), 5); + + static::assertSame($root, (new TransformUp())->of($root, new class implements Rewrite { + public function of(Node $node): Node + { + return $node; + } + })); + } + + public function test_one_instance_rewrites_a_node_once_however_often_it_is_reached(): void + { + $up = new TransformUp(); + $select = NodeMother::select(NodeMother::read()); + $rewrite = new RenameSelectRewrite(); + + $first = $up->of($select, $rewrite); + + static::assertNotSame($select, $first); + static::assertSame($first, $up->of($select, $rewrite)); + } + + public function test_a_parent_sees_its_rewritten_child(): void + { + $rewritten = (new TransformUp())->of( + NodeMother::limit(NodeMother::select(NodeMother::read()), 5), + new RenameSelectRewrite(), + ); + + static::assertInstanceOf(Limit::class, $rewritten); + $select = $rewritten->children()[0]; + static::assertInstanceOf(Select::class, $select); + static::assertSame(['name'], $select->entries); + } + + /** + * @return Generator + */ + public static function joins_sharing_a_node(): Generator + { + $select = NodeMother::select(NodeMother::read()); + + yield 'join' => [NodeMother::join($select, new Result($select))]; + + $select = NodeMother::select(NodeMother::read()); + + yield 'cross join' => [NodeMother::crossJoin($select, new Result($select))]; + } + + #[DataProvider('joins_sharing_a_node')] + public function test_a_joins_right_side_is_handed_back_untouched_even_when_it_shares_a_node_with_the_left(JoinsFrame $join): void + { + $rewritten = (new TransformUp())->of($join, new RenameSelectRewrite()); + + static::assertInstanceOf(JoinsFrame::class, $rewritten); + $left = $rewritten->children()[0]; + static::assertInstanceOf(Select::class, $left); + static::assertSame(['name'], $left->entries); + static::assertSame($join->right(), $rewritten->right()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/TriggerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/TriggerTest.php new file mode 100644 index 0000000000..85a6b60716 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Plan/TriggerTest.php @@ -0,0 +1,101 @@ +plan($read)->root; + + static::assertInstanceOf(Result::class, $root); + static::assertSame([$read], $root->children()); + } + + public function test_rows_with_sinks_is_the_result_then_every_sink_in_order(): void + { + $read = NodeMother::read(); + $first = new Write($read, to_memory(new ArrayMemory())); + $second = new Write($read, to_memory(new ArrayMemory())); + + $root = Trigger::rows->plan($read, new Sinks($first, $second))->root; + + static::assertInstanceOf(Outputs::class, $root); + static::assertInstanceOf(Result::class, $root->children()[0]); + static::assertSame([$first, $second], [$root->children()[1], $root->children()[2]]); + } + + public function test_run_with_one_write_over_the_root_makes_that_write_the_root(): void + { + $read = NodeMother::read(); + $write = new Write($read, to_memory(new ArrayMemory())); + + static::assertSame($write, Trigger::run->plan($read, new Sinks($write))->root); + } + + public function test_run_with_a_write_that_does_not_read_the_root_keeps_a_result_over_the_chain_end(): void + { + $read = NodeMother::read(); + $select = NodeMother::select($read); + $write = new Write($read, to_memory(new ArrayMemory())); + + $root = Trigger::run->plan($select, new Sinks($write))->root; + + static::assertInstanceOf(Outputs::class, $root); + static::assertEquals(new Result($select), $root->children()[0]); + static::assertSame($write, $root->children()[1]); + } + + public function test_run_with_a_transaction_only_keeps_a_result_over_the_chain_end(): void + { + $read = NodeMother::read(); + $transaction = new Transaction(new RecordingTransaction(), new Write($read, to_memory(new ArrayMemory()))); + + $root = Trigger::run->plan($read, new Sinks($transaction))->root; + + static::assertInstanceOf(Outputs::class, $root); + static::assertEquals(new Result($read), $root->children()[0]); + static::assertSame($transaction, $root->children()[1]); + } + + public function test_run_without_sinks_is_a_result_over_the_root(): void + { + $read = NodeMother::read(); + + $root = Trigger::run->plan($read)->root; + + static::assertInstanceOf(Result::class, $root); + static::assertSame([$read], $root->children()); + } + + public function test_run_keeps_a_result_when_only_a_later_write_reads_the_chain_end(): void + { + $read = NodeMother::read(); + $first = new Write($read, to_memory(new ArrayMemory())); + $select = NodeMother::select($read); + $second = new Write($select, to_memory(new ArrayMemory())); + + $root = Trigger::run->plan($select, new Sinks($first, $second))->root; + + static::assertInstanceOf(Outputs::class, $root); + static::assertEquals(new Result($select), $root->children()[0]); + static::assertSame([$first, $second], [$root->children()[1], $root->children()[2]]); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/PlanTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/PlanTest.php new file mode 100644 index 0000000000..1ca19ff2e0 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/PlanTest.php @@ -0,0 +1,106 @@ +logical); + static::assertSame($context->config, $plan->context->config); + } + + public function test_of_carries_the_current_error_handler_in_a_new_context(): void + { + $context = NodeMother::context(); + $context->setErrorHandler($handler = new IgnoreError()); + + $plan = Plan::of(NodeMother::plan(NodeMother::read()), $context); + + static::assertNotSame($context, $plan->context); + static::assertSame($handler, $plan->context->errorHandler()); + } + + public function test_a_handler_set_afterwards_does_not_reach_the_plans_context(): void + { + $context = NodeMother::context(); + $plan = Plan::of(NodeMother::plan(NodeMother::read()), $context); + + $context->setErrorHandler(new IgnoreError()); + + static::assertInstanceOf(ThrowError::class, $plan->context->errorHandler()); + } + + public function test_its_context_has_its_own_telemetry_context(): void + { + $context = NodeMother::context(); + + static::assertNotSame( + $context->telemetry(), + Plan::of(NodeMother::plan(NodeMother::read()), $context)->context->telemetry(), + ); + } + + public function test_to_string_prints_the_tree_its_optimizer_rewrites_by_default(): void + { + $plan = Plan::of( + NodeMother::plan(new Limit(new Limit(NodeMother::read(), 5), 3)), + new FlowContext(config_builder()->optimizer(new Optimizer(new CombineLimits()))->build()), + ); + + static::assertSame( + (new Explain())->of(NodeMother::plan(new Limit(NodeMother::read(), 3)), Format::tree), + $plan->toString(), + ); + } + + public function test_to_string_prints_the_requested_stage_and_format(): void + { + $plan = Plan::of( + NodeMother::plan(new Limit(new Limit(NodeMother::read(), 5), 3)), + new FlowContext(config_builder()->optimizer(new Optimizer(new CombineLimits()))->build()), + ); + + static::assertSame( + (new Explain())->of($plan->logical, Format::boxes), + $plan->toString(Stage::unoptimized, Format::boxes), + ); + static::assertNotSame($plan->toString(), $plan->toString(Stage::unoptimized)); + } + + public function test_the_physical_stage_prints_the_plan_the_executor_would_run(): void + { + $plan = Plan::of(NodeMother::plan(NodeMother::read()), NodeMother::context()); + + static::assertSame( + (new Explain())->physical( + $plan->context->config->planner()->plan($plan->logical, $plan->context), + Format::tree, + ), + $plan->toString(Stage::physical), + ); + static::assertStringStartsWith('Physical plan', $plan->toString(Stage::physical)); + } +} 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 new file mode 100644 index 0000000000..37365d1768 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Planner/NodeTranslatorTest.php @@ -0,0 +1,548 @@ + $step::class, + NodeTranslator::toSteps( + new Aggregate(NodeMother::read(), new GroupBy('id'), hash_group_by()), + NodeMother::context(), + [], + ), + ), + ); + } + + public function test_batch_by_steps_are_the_exact_list_in_order(): void + { + static::assertSame( + [BatchingByProcessor::class], + array_map( + static fn($step) => $step::class, + NodeTranslator::toSteps(new BatchBy(NodeMother::read(), ref('id'), 5), NodeMother::context(), []), + ), + ); + } + + public function test_batch_steps_are_the_exact_list_in_order(): void + { + static::assertSame( + [BatchingProcessor::class], + array_map( + static fn($step) => $step::class, + NodeTranslator::toSteps(new Batch(NodeMother::read(), 10), NodeMother::context(), []), + ), + ); + } + + public function test_cache_steps_are_the_exact_list_in_order(): void + { + static::assertSame( + [CachingProcessor::class], + array_map( + static fn($step) => $step::class, + NodeTranslator::toSteps(new Cache(NodeMother::read(), 'id', null, null), NodeMother::context(), []), + ), + ); + } + + public function test_cache_a_batch_size_prepends_a_batching_processor(): void + { + static::assertSame( + [BatchingProcessor::class, CachingProcessor::class], + array_map( + static fn($step) => $step::class, + NodeTranslator::toSteps(new Cache(NodeMother::read(), 'id', 100, null), NodeMother::context(), []), + ), + ); + } + + public function test_collect_steps_are_the_exact_list_in_order(): void + { + static::assertSame( + [CollectingProcessor::class], + array_map( + static fn($step) => $step::class, + NodeTranslator::toSteps(new Collect(NodeMother::read()), NodeMother::context(), []), + ), + ); + } + + public function test_collect_refs_steps_are_the_exact_list_in_order(): void + { + static::assertSame( + [CollectReferencesTransformer::class], + array_map( + static fn($step) => $step::class, + NodeTranslator::toSteps(new CollectRefs(NodeMother::read(), refs('id')), NodeMother::context(), []), + ), + ); + } + + public function test_constrain_steps_are_the_exact_list_in_order(): void + { + static::assertSame( + [ConstrainedProcessor::class], + array_map( + static fn($step) => $step::class, + NodeTranslator::toSteps( + new Constrain(NodeMother::read(), [new UniqueConstraint('id')]), + NodeMother::context(), + [], + ), + ), + ); + } + + public function test_cross_join_steps_are_the_exact_list_in_order(): void + { + $frame = NodeMother::joinRight(NodeMother::plan(NodeMother::read())); + $right = PhysicalPlanMother::reading(from_array([['id' => 1]], schema(int_schema('id')))); + $context = NodeMother::context(); + + static::assertEquals( + [new CrossJoinRowsTransformer($right, $context->config->executor(), 'r_')], + NodeTranslator::toSteps(new CrossJoin(NodeMother::read(), $frame, 'r_'), $context, [$right]), + ); + } + + public function test_discard_steps_are_the_exact_list_in_order(): void + { + static::assertSame( + [VoidProcessor::class], + array_map( + static fn($step) => $step::class, + NodeTranslator::toSteps(new Discard(NodeMother::read()), NodeMother::context(), []), + ), + ); + } + + public function test_distinct_steps_are_the_exact_list_in_order(): void + { + static::assertSame( + [DropDuplicatesTransformer::class], + array_map( + static fn($step) => $step::class, + NodeTranslator::toSteps(new Distinct(NodeMother::read(), ['id']), NodeMother::context(), []), + ), + ); + } + + public function test_drop_steps_are_the_exact_list_in_order(): void + { + static::assertSame( + [DropEntriesTransformer::class], + array_map( + static fn($step) => $step::class, + NodeTranslator::toSteps(new Drop(NodeMother::read(), ['id']), NodeMother::context(), []), + ), + ); + } + + public function test_duplicate_row_steps_are_the_exact_list_in_order(): void + { + static::assertSame( + [DuplicateRowTransformer::class], + array_map( + static fn($step) => $step::class, + NodeTranslator::toSteps(new DuplicateRow(NodeMother::read(), lit(true), [new WithEntry( + 'copy', + lit(1), + )]), NodeMother::context(), []), + ), + ); + } + + public function test_filter_steps_are_the_exact_list_in_order(): void + { + static::assertSame( + [ScalarFunctionFilterTransformer::class], + array_map( + static fn($step) => $step::class, + NodeTranslator::toSteps( + new Filter(NodeMother::read(), ref('id')->equals(lit(1))), + NodeMother::context(), + [], + ), + ), + ); + } + + #[TestWith([JoinType::left])] + #[TestWith([JoinType::left_anti])] + #[TestWith([JoinType::right])] + #[TestWith([JoinType::inner])] + public function test_join_each_the_named_constructor_follows_the_join_type(JoinType $type): void + { + $factory = new StaticDataFrameFactory(df()->read(from_array([['id' => 1]]))); + $on = join_on(['id' => 'id']); + + static::assertEquals( + [match ($type) { + JoinType::left => JoinEachRowsTransformer::left($factory, $on), + JoinType::left_anti => JoinEachRowsTransformer::leftAnti($factory, $on), + JoinType::right => JoinEachRowsTransformer::right($factory, $on), + JoinType::inner => JoinEachRowsTransformer::inner($factory, $on), + }], + NodeTranslator::toSteps(new JoinEach(NodeMother::read(), $factory, $on, $type), NodeMother::context(), []), + ); + } + + public function test_join_steps_are_the_exact_list_in_order(): void + { + $frame = NodeMother::joinRight(NodeMother::plan(NodeMother::read())); + + static::assertSame( + [HashJoinProcessor::class], + array_map(static fn($step) => $step::class, NodeTranslator::toSteps( + new Join(NodeMother::read(), $frame, join_on(['id' => 'id']), JoinType::inner, hash_join()), + NodeMother::context(), + [PhysicalPlanMother::reading(from_array([['id' => 1]]))], + )), + ); + } + + public function test_limit_steps_are_the_exact_list_in_order(): void + { + static::assertSame( + [LimitTransformer::class], + array_map( + static fn($step) => $step::class, + NodeTranslator::toSteps(new Limit(NodeMother::read(), 5), NodeMother::context(), []), + ), + ); + } + + public function test_offset_steps_are_the_exact_list_in_order(): void + { + static::assertSame( + [OffsetProcessor::class], + array_map( + static fn($step) => $step::class, + NodeTranslator::toSteps(new Offset(NodeMother::read(), 3), NodeMother::context(), []), + ), + ); + } + + public function test_read_steps_are_the_exact_list_in_order(): void + { + static::assertSame([], NodeTranslator::toSteps(NodeMother::read(), NodeMother::context(), [])); + } + + public function test_rename_each_steps_are_the_exact_list_in_order(): void + { + static::assertSame( + [RenameEachEntryTransformer::class], + array_map( + static fn($step) => $step::class, + NodeTranslator::toSteps( + new RenameEach(NodeMother::read(), [new RenameMapEntryStrategy(['id' => 'user_id'])]), + NodeMother::context(), + [], + ), + ), + ); + } + + public function test_rename_steps_are_the_exact_list_in_order(): void + { + static::assertSame( + [RenameEntryTransformer::class], + array_map( + static fn($step) => $step::class, + NodeTranslator::toSteps(new Rename(NodeMother::read(), 'id', 'user_id'), NodeMother::context(), []), + ), + ); + } + + public function test_repartition_steps_are_the_exact_list_in_order(): void + { + static::assertSame( + [BucketingProcessor::class, RepartitionProcessor::class], + array_map( + static fn($step) => $step::class, + NodeTranslator::toSteps(new Repartition(NodeMother::read(), refs('id')), NodeMother::context(), []), + ), + ); + } + + public function test_select_steps_are_the_exact_list_in_order(): void + { + static::assertSame( + [SelectEntriesTransformer::class], + array_map( + static fn($step) => $step::class, + NodeTranslator::toSteps(new Select(NodeMother::read(), ['id']), NodeMother::context(), []), + ), + ); + } + + public function test_sort_steps_are_the_exact_list_in_order(): void + { + static::assertSame( + [MemorySortProcessor::class], + array_map( + static fn($step) => $step::class, + NodeTranslator::toSteps( + new Sort(NodeMother::read(), refs(ref('id')), memory_sort()), + NodeMother::context(), + [], + ), + ), + ); + } + + public function test_transaction_a_transaction_owns_no_step(): void + { + static::assertSame( + [], + NodeTranslator::toSteps( + new Transaction( + new RecordingTransaction(), + new Write(NodeMother::read(), to_memory(new ArrayMemory())), + ), + NodeMother::context(), + [], + ), + ); + } + + public function test_transform_the_instance_the_node_holds_is_the_step(): void + { + $transformer = new SelectEntriesTransformer('id'); + + static::assertSame( + [$transformer], + NodeTranslator::toSteps(new Transform(NodeMother::read(), $transformer), NodeMother::context(), []), + ); + } + + public function test_transform_a_stateful_transformer_runs_as_its_fresh_instance(): void + { + $transformer = new AddRowIndexTransformer('idx', StartFrom::ZERO); + $transformer->transform(rows(schema(int_schema('id')), row(['id' => 1])), flow_context()); + + $steps = NodeTranslator::toSteps(new Transform(NodeMother::read(), $transformer), NodeMother::context(), []); + + static::assertCount(1, $steps); + static::assertInstanceOf(AddRowIndexTransformer::class, $steps[0]); + static::assertNotSame($transformer, $steps[0]); + static::assertSame( + [['id' => 1, 'idx' => 0]], + $steps[0]->transform(rows(schema(int_schema('id')), row(['id' => 1])), flow_context())->toArray(), + ); + } + + public function test_until_steps_are_the_exact_list_in_order(): void + { + static::assertSame( + [UntilTransformer::class], + array_map( + static fn($step) => $step::class, + NodeTranslator::toSteps( + new Until(NodeMother::read(), ref('id')->equals(lit(1))), + NodeMother::context(), + [], + ), + ), + ); + } + + public function test_validate_steps_are_the_exact_list_in_order(): void + { + static::assertSame( + [SchemaValidationLoader::class], + array_map( + static fn($step) => $step::class, + NodeTranslator::toSteps( + new Validate(NodeMother::read(), schema(int_schema('id')), new StrictValidator()), + NodeMother::context(), + [], + ), + ), + ); + } + + public function test_window_column_steps_are_the_exact_list_in_order(): void + { + static::assertSame( + [CollectingProcessor::class, WindowProcessor::class], + array_map( + static fn($step) => $step::class, + NodeTranslator::toSteps( + new WindowColumn(NodeMother::read(), 'rank', rank()->over(window()->orderBy(ref('id')))), + NodeMother::context(), + [], + ), + ), + ); + } + + public function test_window_column_a_partitioned_window_translates_to_repartition_steps_then_the_window_processor(): void + { + static::assertSame( + [BucketingProcessor::class, RepartitionProcessor::class, WindowProcessor::class], + array_map( + static fn($step) => $step::class, + NodeTranslator::toSteps( + new WindowColumn( + NodeMother::read(), + 'rank', + rank()->over(window()->partitionBy(ref('group'))->orderBy(ref('id'))), + ), + NodeMother::context(), + [], + ), + ), + ); + } + + public function test_with_column_steps_are_the_exact_list_in_order(): void + { + static::assertSame( + [ScalarFunctionTransformer::class], + array_map( + static fn($step) => $step::class, + NodeTranslator::toSteps( + new WithColumn(NodeMother::read(), 'doubled', ref('id')->multiply(lit(2))), + NodeMother::context(), + [], + ), + ), + ); + } + + public function test_write_the_instance_the_node_holds_is_the_step(): void + { + $loader = to_memory(new ArrayMemory()); + + static::assertSame( + [$loader], + NodeTranslator::toSteps(new Write(NodeMother::read(), $loader), NodeMother::context(), []), + ); + } + + public function test_a_node_without_a_translation_throws(): void + { + $this->expectException(InvalidLogicException::class); + $this->expectExceptionMessage('No physical steps are known for node ' . ChildlessNode::class); + + NodeTranslator::toSteps(new ChildlessNode(), NodeMother::context(), []); + } + + public function test_top_n_steps_are_the_exact_list_in_order(): void + { + static::assertSame( + [TopNProcessor::class], + array_map( + static fn($step) => $step::class, + NodeTranslator::toSteps(new TopN(NodeMother::read(), refs(ref('id')), 3), NodeMother::context(), []), + ), + ); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Planner/PipelineSplitTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Planner/PipelineSplitTest.php new file mode 100644 index 0000000000..d7f0e9f2fc --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Planner/PipelineSplitTest.php @@ -0,0 +1,670 @@ + 1]], schema(int_schema('id'))))); + $planned = new PlannedNodes(); + $logical = new LogicalPlan(new Result($root)); + (new Planner())->node($logical->root, NodeMother::context(), $planned); + + $plan = (new PipelineSplit())->of($logical, $planned, NodeMother::context()); + + static::assertSame(0, $plan->root()->id); + static::assertNull($plan->root()->input()); + static::assertSame([CollectingProcessor::class], PipelineSteps::classes($plan->root()->segments())); + } + + public function test_ids_count_up_from_the_leaf_and_the_root_has_the_highest(): void + { + $root = NodeMother::sort( + new Collect(NodeMother::sort(NodeMother::read(from_array([['id' => 1]], schema(int_schema('id')))))), + refs(ref('id')), + ); + $planned = new PlannedNodes(); + $logical = new LogicalPlan(new Result($root)); + (new Planner())->node($logical->root, NodeMother::context(), $planned); + + $plan = (new PipelineSplit())->of($logical, $planned, NodeMother::context()); + + static::assertSame(2, $plan->root()->id); + static::assertSame(1, $plan->root()->input()?->id); + static::assertSame(0, $plan->root()->input()?->input()?->id); + static::assertNull($plan->root()->input()?->input()?->input()); + } + + public function test_the_upstream_pipeline_carries_a_trailing_empty_segment(): void + { + $root = NodeMother::limit( + new Node\Sort( + NodeMother::read(from_array([['id' => 1]], schema(int_schema('id')))), + refs(ref('id')), + memory_sort(), + ), + 5, + ); + $planned = new PlannedNodes(); + $logical = new LogicalPlan(new Result($root)); + (new Planner())->node($logical->root, NodeMother::context(), $planned); + + $segments = (new PipelineSplit()) + ->of($logical, $planned, NodeMother::context()) + ->root() + ->input() + ?->segments() + ->all() ?? []; + + static::assertArrayHasKey(1, $segments); + + $trailing = $segments[1]; + + static::assertSame([], $trailing->steps()); + static::assertNull($trailing->processor()); + static::assertNull($trailing->extractor()); + } + + public function test_steps_go_in_through_segments_add_so_a_processor_opens_a_new_segment(): void + { + $output = []; + $root = new Write( + NodeMother::select( + new Node\Batch( + NodeMother::select(NodeMother::read(from_array([['id' => 1]], schema(int_schema('id'))))), + 10, + ), + ), + to_array($output), + ); + $planned = new PlannedNodes(); + $logical = new LogicalPlan(new Result($root)); + (new Planner())->node($logical->root, NodeMother::context(), $planned); + + $segments = (new PipelineSplit()) + ->of($logical, $planned, NodeMother::context()) + ->root() + ->segments() + ->all(); + + static::assertCount(2, $segments); + static::assertSame( + [SelectEntriesTransformer::class], + array_map(static fn($step) => $step::class, $segments[0]->steps()), + ); + static::assertNotNull($segments[0]->processor()); + static::assertSame( + [SelectEntriesTransformer::class, ArrayLoader::class], + array_map(static fn($step) => $step::class, $segments[1]->steps()), + ); + } + + public function test_a_refused_plan_uses_raw_steps_for_every_node(): void + { + $joinEach = new JoinEach( + NodeMother::read(from_array([['id' => 1]], schema(int_schema('id')))), + new StaticDataFrameFactory(df()->read(from_array([['id' => 1]], schema(int_schema('id'))))), + join_on(['id' => 'id']), + JoinType::inner, + ); + $root = new Collect(NodeMother::select($joinEach)); + $planned = new PlannedNodes(); + $logical = new LogicalPlan(new Result($root)); + (new Planner())->node($logical->root, NodeMother::context(), $planned); + + $plan = (new PipelineSplit())->of($logical, $planned, NodeMother::context()); + + static::assertInstanceOf(Raw::class, $plan); + static::assertNull($plan->schema); + static::assertSame( + [JoinEachRowsTransformer::class, SelectEntriesTransformer::class, CollectingProcessor::class], + PipelineSteps::classes($plan->root()->segments()), + ); + static::assertSame($planned->of($root)->steps[0], PipelineSteps::of($plan->root()->segments())[2]); + static::assertSame($planned->of($joinEach)->steps[0], PipelineSteps::of($plan->root()->segments())[0]); + } + + public function test_a_refusal_inside_a_sink_keeps_the_schema_of_the_returned_rows(): void + { + $read = NodeMother::read(from_array([['id' => 1]], schema(int_schema('id')))); + $joinEach = new JoinEach( + $read, + new StaticDataFrameFactory(df()->read(from_array([['id' => 1]], schema(int_schema('id'))))), + join_on(['id' => 'id']), + JoinType::inner, + ); + $logical = Trigger::rows->plan($read, new Sinks(new Write($joinEach, to_memory(new ArrayMemory())))); + $planned = new PlannedNodes(); + (new Planner())->node($logical->root, NodeMother::context(), $planned); + + $plan = (new PipelineSplit())->of($logical, $planned, NodeMother::context()); + + static::assertInstanceOf(Raw::class, $plan); + static::assertEquals(schema(int_schema('id')), $plan->schema()); + } + + public function test_a_bound_plan_uses_bound_steps_for_every_node(): void + { + $root = new Collect(NodeMother::read(from_array([['id' => 1]], schema(int_schema('id'))))); + $planned = new PlannedNodes(); + $logical = new LogicalPlan(new Result($root)); + (new Planner())->node($logical->root, NodeMother::context(), $planned); + + $plan = (new PipelineSplit())->of($logical, $planned, NodeMother::context()); + + static::assertSame($planned->of($root)->bound[0], PipelineSteps::of($plan->root()->segments())[0]); + static::assertNotSame($planned->of($root)->steps[0], PipelineSteps::of($plan->root()->segments())[0]); + } + + public function test_a_spine_that_does_not_end_in_a_read_is_refused(): void + { + $leaf = new ChildlessNode(); + $planned = new PlannedNodes(); + $planned->add($leaf, new PlannedNode([], [], null)); + + $this->expectException(InvalidLogicException::class); + $this->expectExceptionMessage('A logical plan must end in a Read, ' . $leaf::class . ' found'); + + (new PipelineSplit())->of(new LogicalPlan(new Result($leaf)), $planned, NodeMother::context()); + } + + public function test_a_joins_right_side_stays_off_the_spine(): void + { + $left = NodeMother::read(from_array([['id' => 1]], schema(int_schema('id')))); + $root = new Node\CrossJoin( + $left, + NodeMother::joinRight(NodeMother::plan(NodeMother::read(from_array([[ + 'id' => 1, + ]], schema(int_schema('id')))))), + 'r_', + ); + $planned = new PlannedNodes(); + $logical = new LogicalPlan(new Result($root)); + (new Planner())->node($logical->root, NodeMother::context(), $planned); + + $plan = (new PipelineSplit())->of($logical, $planned, NodeMother::context()); + + static::assertNull($plan->root()->input()); + static::assertSame($left->extractor(), $plan->root()->segments()->extractor()); + static::assertSame([CrossJoinRowsTransformer::class], PipelineSteps::classes($plan->root()->segments())); + } + + public function test_a_sink_of_an_outputs_below_the_root_is_attached_to_the_spine(): void + { + $read = NodeMother::read(from_array([['id' => 1]], schema(int_schema('id')))); + $loader = to_memory(new ArrayMemory()); + $logical = NodeMother::plan(NodeMother::limit(new Outputs(new Result($read), new Write($read, $loader)), 5)); + $planned = new PlannedNodes(); + (new Planner())->node($logical->root, NodeMother::context(), $planned); + + $plan = (new PipelineSplit())->of($logical, $planned, NodeMother::context()); + + static::assertContains($loader, PipelineSteps::of($plan->root()->segments())); + static::assertNull($plan->root()->input()); + } + + public function test_a_bare_sink_at_the_spine_root_is_a_step_of_the_spine(): void + { + $read = NodeMother::read(from_array([['id' => 1]], schema(int_schema('id')))); + $loader = to_memory(new ArrayMemory()); + + $plan = (new Planner())->plan( + new LogicalPlan(new Outputs(new Result($read), new Write($read, $loader))), + NodeMother::context(), + ); + + static::assertSame([$loader], PipelineSteps::of($plan->root()->segments())); + static::assertSame(0, $plan->root()->id); + } + + public function test_a_write_root_puts_its_loader_on_the_spine_exactly_once(): void + { + $read = NodeMother::read(from_array([['id' => 1]], schema(int_schema('id')))); + $loader = to_memory(new ArrayMemory()); + + $plan = (new Planner())->plan( + Trigger::run->plan($read, new Sinks(new Write($read, $loader))), + NodeMother::context(), + ); + + static::assertSame([$loader], PipelineSteps::of($plan->root()->segments())); + } + + public function test_two_writes_under_run_are_attached_in_the_order_the_root_lists_them(): void + { + $read = NodeMother::read(from_array([['id' => 1]], schema(int_schema('id')))); + $first = to_memory(new ArrayMemory()); + $second = to_memory(new ArrayMemory()); + + $plan = (new Planner())->plan( + Trigger::run->plan($read, new Sinks(new Write($read, $first), new Write($read, $second))), + NodeMother::context(), + ); + + static::assertSame([$first, $second], PipelineSteps::of($plan->root()->segments())); + } + + public function test_a_bare_sink_at_a_processor_heads_the_next_segment(): void + { + $batch = new Node\Batch( + NodeMother::select(NodeMother::read(from_array([['id' => 1]], schema(int_schema('id'))))), + 10, + ); + + $segments = (new Planner()) + ->plan( + new LogicalPlan( + new Outputs( + new Result(NodeMother::select($batch)), + new Write($batch, to_memory(new ArrayMemory())), + ), + ), + NodeMother::context(), + ) + ->root() + ->segments() + ->all(); + + static::assertCount(2, $segments); + static::assertInstanceOf(BatchingProcessor::class, $segments[0]->processor()); + static::assertSame( + [MemoryLoader::class, SelectEntriesTransformer::class], + array_map(static fn($step) => $step::class, $segments[1]->steps()), + ); + } + + public function test_a_bare_sink_at_a_blocking_node_below_the_root_lives_in_the_pipeline_the_cut_closes(): void + { + $collect = new Collect(NodeMother::read(from_array([['id' => 1]], schema(int_schema('id'))))); + + $plan = (new Planner())->plan( + new LogicalPlan( + new Outputs( + new Result(NodeMother::limit($collect, 5)), + new Write($collect, to_memory(new ArrayMemory())), + ), + ), + NodeMother::context(), + ); + + $upstream = $plan->root()->input()?->segments()->all() ?? []; + static::assertCount(2, $upstream); + static::assertInstanceOf(CollectingProcessor::class, $upstream[0]->processor()); + static::assertSame([MemoryLoader::class], array_map(static fn($step) => $step::class, $upstream[1]->steps())); + static::assertSame([LimitTransformer::class], PipelineSteps::classes($plan->root()->segments())); + } + + public function test_a_sink_with_its_own_steps_is_fed_through_one_side_pipeline(): void + { + $memory = new ArrayMemory(); + $loader = to_memory($memory); + $read = NodeMother::read(from_array( + [['id' => 1, 'name' => 'a']], + schema(int_schema('id'), str_schema('name')), + )); + + $plan = (new Planner())->plan( + new LogicalPlan(new Outputs(new Result($read), new Write(NodeMother::select($read), $loader))), + NodeMother::context(), + ); + + $steps = PipelineSteps::of($plan->root()->segments()); + static::assertCount(1, $steps); + static::assertInstanceOf(SinkFeed::class, $steps[0]); + static::assertSame(1, $plan->root()->id); + + foreach ((new Executor())->executePipeline($plan->root()) as $_) { + } + + static::assertSame([['id' => 1]], $memory->dump()); + } + + public function test_a_node_two_sinks_share_off_the_spine_runs_once_in_one_side_pipeline(): void + { + $first = new ArrayMemory(); + $second = new ArrayMemory(); + $spy = new SpyTransformer(); + $read = NodeMother::read(from_array([['id' => 1], ['id' => 2]], schema(int_schema('id')))); + $shared = new Node\Transform($read, $spy); + + $plan = (new Planner())->plan( + new LogicalPlan( + new Outputs( + new Result($read), + new Write($shared, to_memory($first)), + new Write($shared, to_memory($second)), + ), + ), + NodeMother::context(), + ); + + static::assertSame([SinkFeed::class], PipelineSteps::classes($plan->root()->segments())); + + foreach ((new Executor())->executePipeline($plan->root()) as $_) { + } + + static::assertSame(2, $spy->seen); + static::assertSame([['id' => 1], ['id' => 2]], $first->dump()); + static::assertSame([['id' => 1], ['id' => 2]], $second->dump()); + } + + public function test_a_transaction_whose_children_share_a_node_opens_inside_the_shared_side_pipeline(): void + { + $spy = new SpyTransformer(); + $transaction = new RecordingTransaction(); + $read = NodeMother::read(from_array([['id' => 1], ['id' => 2]], schema(int_schema('id')))); + $shared = new Node\Transform($read, $spy); + + $plan = (new Planner())->plan( + new LogicalPlan( + new Outputs( + new Result($read), + new Node\Transaction( + $transaction, + new Write($shared, to_memory(new ArrayMemory())), + new Write($shared, to_memory(new ArrayMemory())), + ), + ), + ), + NodeMother::context(), + ); + + static::assertSame([SinkFeed::class], PipelineSteps::classes($plan->root()->segments())); + + foreach ((new Executor())->executePipeline($plan->root()) as $_) { + } + + static::assertSame(2, $spy->seen); + static::assertSame(['begin', 'commit', 'begin', 'commit'], $transaction->log); + } + + public function test_transaction_children_sharing_a_node_among_some_siblings_are_fed_through_one_group_pipeline(): void + { + $shared = new ArrayMemory(); + $bare = new ArrayMemory(); + $spy = new SpyTransformer(); + $read = NodeMother::read(from_array([['id' => 1], ['id' => 2]], schema(int_schema('id')))); + $transform = new Node\Transform($read, $spy); + + $plan = (new Planner())->plan( + new LogicalPlan( + new Outputs( + new Result($read), + new Node\Transaction( + new RecordingTransaction(), + new Write($transform, to_memory($shared)), + new Write($transform, to_memory(new ArrayMemory())), + new Write($read, to_memory($bare)), + ), + ), + ), + NodeMother::context(), + ); + + static::assertSame([TransactionalSinks::class], PipelineSteps::classes($plan->root()->segments())); + + foreach ((new Executor())->executePipeline($plan->root()) as $_) { + } + + static::assertSame(2, $spy->seen); + static::assertSame([['id' => 1], ['id' => 2]], $shared->dump()); + static::assertSame([['id' => 1], ['id' => 2]], $bare->dump()); + } + + public function test_a_sink_outside_a_transaction_sharing_a_node_with_one_of_its_children_is_refused(): void + { + $read = NodeMother::read(from_array([['id' => 1]], schema(int_schema('id')))); + $shared = NodeMother::select($read); + + $this->expectException(InvalidLogicException::class); + $this->expectExceptionMessage('A sink outside a transaction cannot share a node with one of its children'); + + (new Planner())->plan( + new LogicalPlan( + new Outputs( + new Result($read), + new Node\Transaction( + new RecordingTransaction(), + new Write($shared, to_memory(new ArrayMemory())), + new Write($read, to_memory(new ArrayMemory())), + ), + new Write($shared, to_memory(new ArrayMemory())), + ), + ), + NodeMother::context(), + ); + } + + public function test_a_transaction_is_one_step_over_its_children(): void + { + $read = NodeMother::read(from_array([['id' => 1]], schema(int_schema('id')))); + + $plan = (new Planner())->plan( + new LogicalPlan( + new Outputs( + new Result($read), + new Node\Transaction( + new RecordingTransaction(), + new Write($read, to_memory(new ArrayMemory())), + new Write(NodeMother::select($read), to_memory(new ArrayMemory())), + ), + ), + ), + NodeMother::context(), + ); + + static::assertSame([TransactionalSinks::class], PipelineSteps::classes($plan->root()->segments())); + static::assertSame(1, $plan->root()->id); + } + + public function test_two_sinks_at_one_node_are_two_steps(): void + { + $read = NodeMother::read(from_array([['id' => 1]], schema(int_schema('id')))); + $first = to_memory(new ArrayMemory()); + $second = to_memory(new ArrayMemory()); + + $plan = (new Planner())->plan( + new LogicalPlan(new Outputs(new Result($read), new Write($read, $first), new Write($read, $second))), + NodeMother::context(), + ); + + static::assertSame([$first, $second], PipelineSteps::of($plan->root()->segments())); + } + + public function test_a_sink_sharing_no_node_with_the_spine_is_refused(): void + { + $this->expectException(InvalidLogicException::class); + $this->expectExceptionMessage('A sink root shares no node with the plan: ' . MemoryLoader::class); + + (new Planner())->plan( + new LogicalPlan( + new Outputs( + new Result(NodeMother::read(from_array([['id' => 1]], schema(int_schema('id'))))), + new Write( + NodeMother::select(NodeMother::read(from_array([['id' => 1]], schema(int_schema('id'))))), + to_memory(new ArrayMemory()), + ), + ), + ), + NodeMother::context(), + ); + } + + public function test_the_children_of_one_transaction_must_attach_to_the_same_node(): void + { + $read = NodeMother::read(from_array([['id' => 1]], schema(int_schema('id')))); + $select = NodeMother::select($read); + + $this->expectException(InvalidLogicException::class); + $this->expectExceptionMessage('Every sink of one transaction must attach to the same node'); + + (new Planner())->plan( + new LogicalPlan( + new Outputs( + new Result($select), + new Node\Transaction( + new RecordingTransaction(), + new Write($read, to_memory(new ArrayMemory())), + new Write($select, to_memory(new ArrayMemory())), + ), + ), + ), + NodeMother::context(), + ); + } + + public function test_a_plan_with_an_undescribable_op_still_attaches_its_sinks(): void + { + $joinEach = new JoinEach( + NodeMother::read(from_array([['id' => 1]], schema(int_schema('id')))), + new StaticDataFrameFactory(df()->read(from_array([['id' => 1]], schema(int_schema('id'))))), + join_on(['id' => 'id']), + JoinType::inner, + ); + $select = NodeMother::select($joinEach); + + $plan = (new Planner())->plan( + new LogicalPlan( + new Outputs( + new Result(new Collect($select)), + new Write($select, to_memory(new ArrayMemory())), + new Node\Transaction( + new RecordingTransaction(), + new Write(NodeMother::select($select), to_memory(new ArrayMemory())), + ), + ), + ), + NodeMother::context(), + ); + + static::assertInstanceOf(Raw::class, $plan); + static::assertSame( + [ + JoinEachRowsTransformer::class, + SelectEntriesTransformer::class, + MemoryLoader::class, + TransactionalSinks::class, + CollectingProcessor::class, + ], + PipelineSteps::classes($plan->root()->segments()), + ); + } + + public function test_a_write_that_does_not_translate_to_a_loader_is_refused(): void + { + $read = NodeMother::read(from_array([['id' => 1]], schema(int_schema('id')))); + $write = new Write($read, to_memory(new ArrayMemory())); + $logical = new LogicalPlan(new Outputs(new Result($read), $write)); + $planned = new PlannedNodes(); + (new Planner())->node($logical->root, NodeMother::context(), $planned); + $planned->add($write, new PlannedNode([], [], null)); + + $this->expectException(InvalidLogicException::class); + $this->expectExceptionMessage('A Write must translate to a Loader, null given'); + + (new PipelineSplit())->of($logical, $planned, NodeMother::context()); + } + + public function test_a_batched_transaction_sink_is_one_step_behind_the_batch_by_processor(): void + { + $batchBy = new Node\BatchBy( + NodeMother::read(from_array([['transaction_id' => 7]], schema(int_schema('transaction_id')))), + ref('transaction_id'), + 5_000, + ); + + $plan = (new Planner())->plan( + new LogicalPlan( + new Outputs( + new Result($batchBy), + new Node\Transaction( + new RecordingTransaction(), + new Write(NodeMother::select($batchBy, 'transaction_id'), to_memory(new ArrayMemory())), + new Write(new Node\Batch($batchBy, 1_000), to_memory(new ArrayMemory())), + ), + ), + ), + NodeMother::context(), + ); + + $segments = $plan->root()->segments()->all(); + static::assertNull($plan->root()->input()); + static::assertSame(2, $plan->root()->id); + static::assertCount(2, $segments); + static::assertSame([], $segments[0]->steps()); + static::assertInstanceOf(BatchingByProcessor::class, $segments[0]->processor()); + static::assertSame( + [TransactionalSinks::class], + array_map(static fn($step) => $step::class, $segments[1]->steps()), + ); + } + + public function test_the_leaf_pipeline_carries_the_reads_limit_and_path_filter(): void + { + $root = NodeMother::limit( + NodeMother::sort(NodeMother::read(from_array([['id' => 1]], schema(int_schema('id'))))->withLimit(5)), + 5, + ); + $planned = new PlannedNodes(); + $logical = new LogicalPlan(new Result($root)); + (new Planner())->node($logical->root, NodeMother::context(), $planned); + + $plan = (new PipelineSplit())->of($logical, $planned, NodeMother::context()); + + static::assertSame(5, $plan->root()->input()?->limit()); + static::assertNull($plan->root()->limit()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Planner/PlannedNodeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Planner/PlannedNodeTest.php new file mode 100644 index 0000000000..f8b86dab39 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Planner/PlannedNodeTest.php @@ -0,0 +1,28 @@ +steps); + static::assertSame($bound, $planned->bound); + static::assertSame($schema, $planned->schema); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Planner/PlannedNodesTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Planner/PlannedNodesTest.php new file mode 100644 index 0000000000..5f5ffc22fd --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Planner/PlannedNodesTest.php @@ -0,0 +1,64 @@ +add($node, $plannedNode)); + static::assertTrue($planned->has($node)); + static::assertSame($plannedNode, $planned->of($node)); + static::assertFalse($planned->has(NodeMother::read())); + } + + public function test_of_throws_for_a_node_never_planned(): void + { + $this->expectException(InvalidLogicException::class); + $this->expectExceptionMessage('was never planned'); + + (new PlannedNodes())->of(NodeMother::read()); + } + + public function test_it_keeps_the_first_refusal(): void + { + $planned = new PlannedNodes(); + $first = new SchemaNotDerivableException('first'); + + static::assertNull($planned->refusal()); + + $planned->refuse($first); + $planned->refuse(new SchemaNotDerivableException('second')); + + static::assertSame($first, $planned->refusal()); + } + + public function test_steps_are_the_bound_ones_until_the_plan_refuses(): void + { + $planned = new PlannedNodes(); + $node = NodeMother::read(); + $steps = [new LimitTransformer(5)]; + $bound = [new LimitTransformer(5)]; + $planned->add($node, new PlannedNode($steps, $bound, null)); + + static::assertSame($bound, $planned->steps($node)); + + $planned->refuse(new SchemaNotDerivableException('refused')); + + static::assertSame($steps, $planned->steps($node)); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Planner/SinkAttachmentTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Planner/SinkAttachmentTest.php new file mode 100644 index 0000000000..a99e78f218 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Planner/SinkAttachmentTest.php @@ -0,0 +1,156 @@ + 1]], schema(int_schema('id')))); + $loader = to_memory(new ArrayMemory()); + $write = new Write($read, $loader); + $sinks = new Sinks($write); + [$attachment, $onSpine] = SinkAttachmentMother::over($sinks, $read); + + $remembered = $attachment->attach($sinks, $onSpine); + + static::assertSame([$loader], $remembered[$read]); + static::assertSame(0, $attachment->next()); + } + + public function test_two_sinks_sharing_a_two_node_path_off_the_spine_are_fed_through_one_side_pipeline(): void + { + $read = NodeMother::read(from_array([['id' => 1]], schema(int_schema('id')))); + $shared = NodeMother::limit(NodeMother::select($read), 5); + $first = new Write($shared, to_memory(new ArrayMemory())); + $second = new Write($shared, to_memory(new ArrayMemory())); + $sinks = new Sinks($first, $second); + [$attachment, $onSpine] = SinkAttachmentMother::over($sinks, $read); + + $remembered = $attachment->attach($sinks, $onSpine); + + static::assertSame([SinkFeed::class], array_map(static fn($step) => $step::class, $remembered[$read])); + // the shared pipeline and nothing else: both loaders end it directly + static::assertSame(1, $attachment->next()); + } + + public function test_two_sinks_sharing_only_part_of_their_path_nest_a_second_side_pipeline(): void + { + $read = NodeMother::read(from_array([['id' => 1]], schema(int_schema('id')))); + $shared = NodeMother::select($read); + $first = new Write($shared, to_memory(new ArrayMemory())); + $second = new Write(NodeMother::limit($shared, 5), to_memory(new ArrayMemory())); + $sinks = new Sinks($first, $second); + [$attachment, $onSpine] = SinkAttachmentMother::over($sinks, $read); + + $remembered = $attachment->attach($sinks, $onSpine); + + static::assertSame([SinkFeed::class], array_map(static fn($step) => $step::class, $remembered[$read])); + // the shared pipeline over Select, plus the second sink's own pipeline over its Limit + static::assertSame(2, $attachment->next()); + } + + public function test_two_sinks_whose_paths_part_below_the_shared_node_each_get_their_own_pipeline_under_it(): void + { + $read = NodeMother::read(from_array([['id' => 1]], schema(int_schema('id')))); + $shared = NodeMother::select($read); + $first = new Write(NodeMother::limit($shared, 5), to_memory(new ArrayMemory())); + $second = new Write(NodeMother::limit($shared, 3), to_memory(new ArrayMemory())); + $sinks = new Sinks($first, $second); + [$attachment, $onSpine] = SinkAttachmentMother::over($sinks, $read); + + $remembered = $attachment->attach($sinks, $onSpine); + + static::assertSame([SinkFeed::class], array_map(static fn($step) => $step::class, $remembered[$read])); + // Select once, then a pipeline per Limit + static::assertSame(3, $attachment->next()); + } + + public function test_a_transaction_is_one_step_over_its_children(): void + { + $read = NodeMother::read(from_array([['id' => 1]], schema(int_schema('id')))); + $transaction = new Transaction( + new RecordingTransaction(), + new Write($read, to_memory(new ArrayMemory())), + new Write(NodeMother::select($read), to_memory(new ArrayMemory())), + ); + $sinks = new Sinks($transaction); + [$attachment, $onSpine] = SinkAttachmentMother::over($sinks, $read); + + $remembered = $attachment->attach($sinks, $onSpine); + + static::assertSame( + [TransactionalSinks::class], + array_map(static fn($step) => $step::class, $remembered[$read]), + ); + } + + public function test_a_sink_outside_a_transaction_sharing_a_node_with_one_of_its_children_is_refused(): void + { + $read = NodeMother::read(from_array([['id' => 1]], schema(int_schema('id')))); + $shared = NodeMother::select($read); + $transaction = new Transaction( + new RecordingTransaction(), + new Write($shared, to_memory(new ArrayMemory())), + new Write(NodeMother::limit($read, 1), to_memory(new ArrayMemory())), + ); + $sinks = new Sinks($transaction, new Write($shared, to_memory(new ArrayMemory()))); + [$attachment, $onSpine] = SinkAttachmentMother::over($sinks, $read); + + $this->expectException(InvalidLogicException::class); + $this->expectExceptionMessage('A sink outside a transaction cannot share a node with one of its children'); + + $attachment->attach($sinks, $onSpine); + } + + public function test_the_children_of_one_transaction_must_attach_to_the_same_node(): void + { + $read = NodeMother::read(from_array([['id' => 1]], schema(int_schema('id')))); + $select = NodeMother::select($read); + $transaction = new Transaction( + new RecordingTransaction(), + new Write($read, to_memory(new ArrayMemory())), + new Write($select, to_memory(new ArrayMemory())), + ); + $sinks = new Sinks($transaction); + [$attachment, $onSpine] = SinkAttachmentMother::over($sinks, $read, $select); + + $this->expectException(InvalidLogicException::class); + $this->expectExceptionMessage('Every sink of one transaction must attach to the same node'); + + $attachment->attach($sinks, $onSpine); + } + + public function test_a_sink_sharing_no_node_with_the_spine_is_refused(): void + { + $read = NodeMother::read(from_array([['id' => 1]], schema(int_schema('id')))); + $sinks = new Sinks(new Write(NodeMother::read(), to_memory(new ArrayMemory()))); + [$attachment, $onSpine] = SinkAttachmentMother::over($sinks, $read); + + $this->expectException(InvalidLogicException::class); + $this->expectExceptionMessage('A sink root shares no node with the plan: ' . MemoryLoader::class); + + $attachment->attach($sinks, $onSpine); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Planner/SinkFeedFactoryTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Planner/SinkFeedFactoryTest.php new file mode 100644 index 0000000000..a0c2081d13 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Planner/SinkFeedFactoryTest.php @@ -0,0 +1,95 @@ + 1]], schema(int_schema('id')))); + $select = NodeMother::select($read); + $planned = new PlannedNodes(); + (new Planner())->node($select, $context, $planned); + $spy = new SpyLoader(); + + $feed = (new SinkFeedFactory($planned, $context))->of( + [$select], + [$spy], + $read, + new SinkOffers($context->errorHandler()), + 7, + ); + $feed->load(rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])), $context); + $feed->closure($context); + + static::assertSame([2], $spy->loadedRowCounts()); + static::assertSame(1, $spy->closureCount); + } + + public function test_a_host_without_a_schema_feeds_an_empty_schema(): void + { + $context = NodeMother::context(); + $read = NodeMother::read(new UndescribableRowLessExtractor()); + $planned = new PlannedNodes(); + (new Planner())->node($read, $context, $planned); + $spy = new SpyLoader(); + + $feed = (new SinkFeedFactory($planned, $context))->of( + [], + [$spy], + $read, + new SinkOffers($context->errorHandler()), + 0, + ); + $feed->load(rows(schema(int_schema('id')), row(['id' => 1])), $context); + $feed->closure($context); + + static::assertNotNull($planned->refusal()); + static::assertSame([1], $spy->loadedRowCounts()); + } + + public function test_a_throw_only_handler_surfaces_a_failing_step(): void + { + $context = NodeMother::context()->withErrorHandler(new IgnoreError()); + $read = NodeMother::read(from_array([['id' => 1]], schema(int_schema('id')))); + $transform = new Transform($read, new ThrowingTransformer(new RuntimeException('boom'))); + $planned = new PlannedNodes(); + (new Planner())->node($transform, $context, $planned); + + $feed = (new SinkFeedFactory($planned, $context))->of( + [$transform], + [new SpyLoader()], + $read, + new SinkOffers(new ThrowError()), + 0, + ); + + $this->expectException(SinkFailure::class); + + $feed->load(rows(schema(int_schema('id')), row(['id' => 1])), $context); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/PlannerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/PlannerTest.php new file mode 100644 index 0000000000..5948767b8b --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/PlannerTest.php @@ -0,0 +1,553 @@ +plan( + new LogicalPlan( + new Outputs( + new Result(NodeMother::select($three)), + new Write($three, $loader), + new Write(NodeMother::limit($read, 4), to_memory(new ArrayMemory())), + ), + ), + NodeMother::context(), + ); + + $steps = PipelineSteps::of($plan->root()->segments()); + static::assertSame(4, $plan->root()->limit()); + static::assertSame( + [SinkFeed::class, LimitTransformer::class, MemoryLoader::class, SelectEntriesTransformer::class], + array_map(static fn($step) => $step::class, $steps), + ); + static::assertSame($loader, $steps[2]); + } + + public function test_a_rule_that_rebuilds_the_plan_around_transform_up_keeps_its_sinks(): void + { + $select = NodeMother::select(NodeMother::read()); + + $plan = (new Planner(new Optimizer(new SpineCopyingRule())))->plan( + new LogicalPlan( + new Outputs( + new Result($select), + new Write($select, to_memory(new ArrayMemory())), + new Write(NodeMother::limit($select, 1), to_memory(new ArrayMemory())), + ), + ), + NodeMother::context(), + ); + + // both sinks are children of the one root, so a rule copying the root cannot lose them + static::assertSame( + [SelectEntriesTransformer::class, MemoryLoader::class, SinkFeed::class], + PipelineSteps::classes($plan->root()->segments()), + ); + } + + public function test_a_linear_plan_is_one_pipeline_with_the_limit_pushed(): void + { + $csv = from_csv(__DIR__ . '/../Fixtures/orders.csv'); + $node = new Read($csv); + $node = new Select($node, ['id', 'total']); + $node = new Limit($node, 5); + $node = new Write($node, to_csv(__DIR__ . '/var/out.csv')); + + $logical = new LogicalPlan(new Result($node)); + $plan = (new Planner(Optimizer::default()))->plan($logical, NodeMother::context()); + + static::assertSame(0, $plan->root()->id); + static::assertSame( + [SelectEntriesTransformer::class, LimitTransformer::class, CSVLoader::class], + PipelineSteps::classes($plan->root()->segments()), + ); + static::assertNull($plan->root()->input()); + static::assertInstanceOf(Described::class, $plan); + static::assertSame(['id', 'total'], $plan->schema->references()->names()); + + static::assertSame($csv, $plan->root()->segments()->extractor()); + static::assertSame(5, $plan->root()->limit()); + static::assertNull($logical->source()->limit()); + } + + public function test_a_run_plan_over_one_sink_is_described_with_the_sinks_input_schema(): void + { + $plan = (new Planner())->plan( + Trigger::run->plan( + $select = new Select(new Read(from_csv(__DIR__ . '/../Fixtures/orders.csv')), ['id']), + new Sinks(new Write($select, to_csv(__DIR__ . '/var/out.csv'))), + ), + NodeMother::context(), + ); + + static::assertInstanceOf(Described::class, $plan); + static::assertSame(['id'], $plan->schema->references()->names()); + } + + public function test_a_sort_splits_the_plan_into_two_pipelines(): void + { + $csv = from_csv(__DIR__ . '/../Fixtures/orders.csv'); + $node = new Read($csv); + $node = new Sort($node, refs(ref('total')), memory_sort()); + $node = new Limit($node, 5); + $node = new Write($node, to_csv(__DIR__ . '/var/out.csv')); + + $logical = new LogicalPlan(new Result($node)); + $plan = (new Planner(Optimizer::default()->without(CombineSortAndLimit::class)))->plan( + $logical, + NodeMother::context(), + ); + + static::assertSame(1, $plan->root()->id); + static::assertSame( + [LimitTransformer::class, CSVLoader::class], + PipelineSteps::classes($plan->root()->segments()), + ); + static::assertNull($plan->root()->segments()->extractor()); + + $upstream = $plan->root()->input(); + + static::assertNotNull($upstream); + static::assertSame(0, $upstream->id); + static::assertSame([MemorySortProcessor::class], PipelineSteps::classes($upstream->segments())); + static::assertInstanceOf(Described::class, $plan); + static::assertSame(['id', 'total', 'seller_id'], $plan->schema->references()->names()); + + static::assertSame($csv, $upstream->segments()->extractor()); + static::assertNull($upstream->limit()); + static::assertNull($plan->root()->limit()); + } + + public function test_a_join_each_plan_refuses_its_schema_and_has_no_frame_edge(): void + { + $node = new Read(from_csv(__DIR__ . '/../Fixtures/orders.csv')); + $node = new JoinEach( + $node, + new StaticDataFrameFactory(df()->read(from_array([['id' => 1]]))), + join_on(['id' => 'id']), + JoinType::left, + ); + + $logical = new LogicalPlan(new Result($node)); + $plan = (new Planner(Optimizer::default()))->plan($logical, NodeMother::context()); + + static::assertSame(0, $plan->root()->id); + static::assertSame([JoinEachRowsTransformer::class], PipelineSteps::classes($plan->root()->segments())); + static::assertInstanceOf(Raw::class, $plan); + static::assertNull($plan->root()->input()); + } + + public function test_rules_run_once_each_in_registration_order(): void + { + $log = new ArrayObject(); + + (new Planner(new Optimizer(new RecordingRule('first', $log), new RecordingRule('second', $log))))->plan( + NodeMother::plan(NodeMother::read()), + NodeMother::context(), + ); + + static::assertSame(['first', 'second'], $log->getArrayCopy()); + } + + public function test_a_planner_with_no_rules_plans_without_a_push(): void + { + $csv = from_csv(__DIR__ . '/../Fixtures/orders.csv'); + $node = new Read($csv); + $node = new Limit($node, 5); + + $logical = new LogicalPlan(new Result($node)); + $plan = (new Planner())->plan($logical, NodeMother::context()); + + static::assertSame($csv, $plan->root()->segments()->extractor()); + static::assertNull($plan->root()->limit()); + } + + public function test_a_join_plans_its_right_side_as_a_physical_plan_of_its_own(): void + { + $node = new Read(from_csv(__DIR__ . '/../Fixtures/orders.csv')); + $node = new Node\Join( + $node, + df()->read(from_csv(__DIR__ . '/../Fixtures/sellers.csv'))->explain()->logical->root, + join_on(['seller_id' => 'id'], 'r_'), + JoinType::inner, + ); + $node = new Write($node, to_csv(__DIR__ . '/var/out.csv')); + + $plan = (new Planner(Optimizer::default()))->plan(new LogicalPlan(new Result($node)), NodeMother::context()); + + static::assertSame(1, $plan->root()->id); + static::assertSame([CSVLoader::class], PipelineSteps::classes($plan->root()->segments())); + + $upstream = $plan->root()->input(); + + static::assertNotNull($upstream); + static::assertSame(0, $upstream->id); + static::assertNull($upstream->input()); + static::assertSame([HashJoinProcessor::class], PipelineSteps::classes($upstream->segments())); + static::assertInstanceOf(Described::class, $plan); + static::assertSame(['id', 'total', 'seller_id', 'r_id', 'r_name'], $plan->schema->references()->names()); + } + + public function test_a_joins_right_side_runs_with_the_outer_context(): void + { + $recording = new ContextRecordingTransformer(); + $right = df(config())->read(from_array([['id' => 1]], schema(int_schema('id'))))->transform($recording); + $node = new CrossJoin( + NodeMother::read(from_array([['id' => 1]], schema(int_schema('id')))), + $right->explain()->logical->root, + 'r_', + ); + $context = NodeMother::context(config()); + + $plan = (new Planner(Optimizer::default()))->plan(new LogicalPlan(new Result($node)), $context); + iterator_to_array($context->config->executor()->execute($plan)); + + static::assertSame([$context], $recording->contexts); + } + + public function test_a_read_frame_is_a_source_of_this_pipeline(): void + { + $extractor = from_data_frame(df()->read(from_csv(__DIR__ . '/../Fixtures/orders.csv'))->select('id')); + $node = new Write(new Limit(new Read($extractor), 5), to_csv(__DIR__ . '/var/out.csv')); + + $plan = (new Planner(Optimizer::default()))->plan(new LogicalPlan(new Result($node)), NodeMother::context()); + + static::assertNull($plan->root()->input()); + static::assertSame( + [LimitTransformer::class, CSVLoader::class], + PipelineSteps::classes($plan->root()->segments()), + ); + static::assertSame($extractor, $plan->root()->segments()->extractor()); + static::assertSame(5, $plan->root()->limit()); + } + + public function test_a_read_frame_describes_the_rows_without_reading_them(): void + { + $counting = new CountingExtractor(schema(int_schema('id'), str_schema('name'))); + $plan = (new Planner(Optimizer::default()))->plan( + new LogicalPlan(new Result(new Read(from_data_frame(df()->read($counting)->select('id'))))), + NodeMother::context(), + ); + + static::assertInstanceOf(Described::class, $plan); + static::assertEquals(schema(int_schema('id')), $plan->schema); + static::assertSame(0, $counting->extractCalls); + } + + public function test_a_read_frame_with_a_declared_schema_describes_that_schema(): void + { + $declared = schema(int_schema('id')); + $node = new Read(from_data_frame(df()->read(new UndescribableRowLessExtractor()))->withSchema($declared)); + + $plan = (new Planner())->plan(new LogicalPlan(new Result($node)), NodeMother::context()); + + static::assertInstanceOf(Described::class, $plan); + static::assertEquals($declared, $plan->schema); + } + + public function test_a_nodes_schema_is_the_fold_of_its_bound_steps(): void + { + $planned = new PlannedNodes(); + $read = new Read(new CountingExtractor(schema(int_schema('id'), str_schema('name')))); + + static::assertEquals( + schema(int_schema('id'), str_schema('name')), + (new Planner())->node($read, NodeMother::context(), $planned)->schema, + ); + static::assertEquals( + schema(str_schema('name')), + (new Planner())->node( + NodeMother::select(NodeMother::select($read, 'id', 'name'), 'name'), + NodeMother::context(), + $planned, + )->schema, + ); + } + + public function test_a_loader_passes_through_the_fold_unbound(): void + { + $output = []; + $loader = to_array($output); + $planned = new PlannedNodes(); + + $plannedNode = (new Planner())->node( + new Write(NodeMother::read(from_array([['id' => 1]], schema(int_schema('id')))), $loader), + NodeMother::context(), + $planned, + ); + + static::assertSame([$loader], $plannedNode->steps); + static::assertSame([$loader], $plannedNode->bound); + static::assertEquals(schema(int_schema('id')), $plannedNode->schema); + } + + public function test_bound_steps_are_the_result_of_bind_not_the_translated_instances(): void + { + $planned = new PlannedNodes(); + + $plannedNode = (new Planner())->node( + new Node\Collect(NodeMother::read(from_array([['id' => 1]], schema(int_schema('id'))))), + NodeMother::context(), + $planned, + ); + + static::assertInstanceOf(CollectingProcessor::class, $plannedNode->steps[0]); + static::assertInstanceOf(CollectingProcessor::class, $plannedNode->bound[0]); + static::assertNotSame($plannedNode->steps[0], $plannedNode->bound[0]); + } + + public function test_the_same_node_object_is_planned_once(): void + { + $planned = new PlannedNodes(); + $node = NodeMother::select(NodeMother::read()); + + static::assertSame( + (new Planner())->node($node, NodeMother::context(), $planned), + (new Planner())->node($node, NodeMother::context(), $planned), + ); + } + + public function test_a_limit_over_a_read_frame_is_pushed_into_its_extractor(): void + { + $child = df()->read(from_array([['id' => 1], ['id' => 2]], schema(int_schema('id'))))->select('id'); + $logical = new LogicalPlan(new Result(new Limit(new Read(from_data_frame($child)), 1))); + + static::assertSame( + 1, + (new Planner(Optimizer::default())) + ->plan($logical, NodeMother::context()) + ->root() + ->limit(), + ); + } + + public function test_a_joins_right_side_is_planned_apart_from_this_plan(): void + { + $planned = new PlannedNodes(); + $shared = NodeMother::select(NodeMother::read(from_array([['id' => 1]], schema(int_schema('id'))))); + $frame = NodeMother::joinRight(NodeMother::plan($shared)); + + (new Planner())->node(NodeMother::crossJoin($shared, $frame), NodeMother::context(), $planned); + + static::assertTrue($planned->has($shared)); + static::assertFalse($planned->has($frame)); + } + + public function test_a_refusal_anywhere_makes_the_whole_plan_raw(): void + { + $planned = new PlannedNodes(); + $joinEach = new JoinEach( + NodeMother::read(from_array([['id' => 1]], schema(int_schema('id')))), + new StaticDataFrameFactory(df()->read(from_array([['id' => 1]], schema(int_schema('id'))))), + join_on(['id' => 'id']), + JoinType::inner, + ); + $above = NodeMother::select($joinEach); + + (new Planner())->node($above, NodeMother::context(), $planned); + + $refusal = $planned->refusal(); + + static::assertNotNull($refusal); + static::assertSame(DataDependentSchemaException::class, $refusal::class); + static::assertStringContainsString('JoinEachRowsTransformer', $refusal->getMessage()); + static::assertStringContainsString( + "its right side is built from each left batch's row values", + $refusal->getMessage(), + ); + static::assertNull($planned->of($joinEach)->schema); + static::assertSame($planned->of($joinEach)->steps, $planned->of($joinEach)->bound); + $abovePlanned = $planned->of($above); + + static::assertNull($abovePlanned->schema); + static::assertCount(1, $abovePlanned->steps); + } + + public function test_a_frame_whose_sink_refuses_still_describes_its_rows(): void + { + $read = NodeMother::read(from_array([['id' => 1]], schema(int_schema('id')))); + $joinEach = new JoinEach( + $read, + new StaticDataFrameFactory(df()->read(from_array([['id' => 1]], schema(int_schema('id'))))), + join_on(['id' => 'id']), + JoinType::inner, + ); + $frame = NodeMother::joinRight(Trigger::rows->plan( + $read, + new Sinks(new Write($joinEach, to_memory(new ArrayMemory()))), + )); + $planned = new PlannedNodes(); + + static::assertEquals( + schema(int_schema('id')), + (new Planner())->node($frame, NodeMother::context(), $planned)->schema, + ); + static::assertNotNull($planned->refusal()); + } + + public function test_the_first_refusal_is_kept(): void + { + $planned = new PlannedNodes(); + $factory = new StaticDataFrameFactory(df()->read(from_array([['id' => 1]], schema(int_schema('id'))))); + $first = new JoinEach( + NodeMother::read(from_array([['id' => 1]], schema(int_schema('id')))), + $factory, + join_on(['id' => 'id']), + JoinType::inner, + ); + + (new Planner())->node( + new JoinEach($first, $factory, join_on(['id' => 'id']), JoinType::left), + NodeMother::context(), + $planned, + ); + + $refusal = $planned->refusal(); + + static::assertNotNull($refusal); + static::assertSame(DataDependentSchemaException::class, $refusal::class); + static::assertStringContainsString('JoinEachRowsTransformer', $refusal->getMessage()); + static::assertSame($refusal, $planned->refusal()); + } + + public function test_a_node_never_walked_is_not_planned(): void + { + $planned = new PlannedNodes(); + (new Planner())->node(NodeMother::read(), NodeMother::context(), $planned); + + static::assertFalse($planned->has(NodeMother::read())); + } + + public function test_a_planned_node_with_a_null_schema_is_distinct_from_a_node_never_walked(): void + { + $planned = new PlannedNodes(); + $refusing = new JoinEach( + NodeMother::read(from_array([['id' => 1]], schema(int_schema('id')))), + new StaticDataFrameFactory(df()->read(from_array([['id' => 1]], schema(int_schema('id'))))), + join_on(['id' => 'id']), + JoinType::inner, + ); + (new Planner())->node($refusing, NodeMother::context(), $planned); + + static::assertTrue($planned->has($refusing)); + static::assertNull($planned->of($refusing)->schema); + static::assertFalse($planned->has(NodeMother::read())); + } + + public function test_planning_reads_no_row(): void + { + $extractor = new CountingExtractor(schema(int_schema('id')), rows(schema(int_schema('id')), row(['id' => 1]))); + $planned = new PlannedNodes(); + + (new Planner())->node(NodeMother::select(new Read($extractor)), NodeMother::context(), $planned); + + static::assertSame(0, $extractor->extractCalls); + } + + public function test_a_joins_right_side_is_handed_to_the_translation_as_a_physical_plan(): void + { + $planned = new PlannedNodes(); + $frame = NodeMother::joinRight(NodeMother::plan(NodeMother::read(from_array([[ + 'id' => 1, + ]], schema(int_schema('id')))))); + $crossJoin = new CrossJoin(NodeMother::read(from_array([['id' => 1]], schema(int_schema('id')))), $frame, 'r_'); + + $plannedNode = (new Planner())->node($crossJoin, NodeMother::context(), $planned); + + static::assertInstanceOf(CrossJoinRowsTransformer::class, $plannedNode->steps[0]); + } + + public function test_a_planning_failure_reports_a_started_and_a_failed_span_and_rethrows(): void + { + $telemetry = new MemoryTelemetryContext(); + + try { + (new Planner(Optimizer::default()))->plan( + NodeMother::plan(NodeMother::select(NodeMother::read(), 'nope')), + $telemetry->flowContext, + ); + + static::fail('Expected the bind failure to be rethrown.'); + } catch (SchemaDefinitionNotFoundException $e) { + static::assertSame('Schema definition for entry "nope" not found.', $e->getMessage()); + } + + static::assertCount(1, $telemetry->spans->startedSpans()); + static::assertCount(1, $telemetry->spans->endedSpans()); + static::assertTrue($telemetry->spans->endedSpans()[0]->status()?->isError()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/HashJoinProcessorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/HashJoinProcessorTest.php index 9a9f810ad1..216cb51983 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/HashJoinProcessorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/HashJoinProcessorTest.php @@ -15,9 +15,9 @@ use Flow\ETL\Tests\Double\SpyBucketsStorage; use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Tests\Mother\HashJoinProcessorMother; +use Flow\ETL\Tests\Mother\PhysicalPlanMother; use Flow\ETL\Tests\Mother\RowsMother; -use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\from_rows; use function Flow\ETL\DSL\int_schema; @@ -34,7 +34,7 @@ final class HashJoinProcessorTest extends FlowTestCase public function test_bind_derives_the_joined_schema_from_both_sides(): void { $processor = HashJoinProcessorMother::resident( - df()->read(from_rows(rows( + PhysicalPlanMother::reading(from_rows(rows( schema(int_schema('id'), str_schema('name')), row(['id' => 1, 'name' => 'Alice']), ))), @@ -62,7 +62,7 @@ public function test_builds_hash_table_from_the_smaller_side_without_changing_re $leftBiggerJoined = []; $processor = HashJoinProcessorMother::grace( - df()->read(from_rows($smaller)), + PhysicalPlanMother::reading(from_rows($smaller)), Expression::on(['id' => 'user_id']), Join::inner, ); @@ -113,12 +113,12 @@ public function test_grace_and_resident_storages_produce_the_same_rows(): void foreach (['grace', 'resident'] as $mode) { $processor = $mode === 'grace' ? HashJoinProcessorMother::grace( - df()->read(from_rows($rightRows)), + PhysicalPlanMother::reading(from_rows($rightRows)), Expression::on(['id' => 'user_id']), Join::left, ) : HashJoinProcessorMother::resident( - df()->read(from_rows($rightRows)), + PhysicalPlanMother::reading(from_rows($rightRows)), Expression::on(['id' => 'user_id']), Join::left, ); @@ -155,7 +155,7 @@ public function test_grace_and_resident_storages_produce_the_same_rows(): void public function test_handles_empty_left_side(): void { $processor = HashJoinProcessorMother::grace( - df()->read(from_rows(rows( + PhysicalPlanMother::reading(from_rows(rows( schema(int_schema('user_id'), str_schema('name')), row(['user_id' => 1, 'name' => 'Alice']), ))), @@ -173,7 +173,7 @@ public function test_handles_empty_left_side(): void public function test_handles_empty_right_side(): void { $processor = HashJoinProcessorMother::grace( - df()->read(from_rows(rows(schema()))), + PhysicalPlanMother::reading(from_rows(rows(schema()))), Expression::on(['id' => 'user_id']), Join::inner, ); @@ -197,7 +197,7 @@ public function test_handles_empty_right_side(): void public function test_inner_join(): void { $processor = HashJoinProcessorMother::grace( - df()->read(from_rows(rows( + PhysicalPlanMother::reading(from_rows(rows( schema(int_schema('user_id'), str_schema('name')), row(['user_id' => 1, 'name' => 'Alice']), row(['user_id' => 2, 'name' => 'Bob']), @@ -239,7 +239,7 @@ public function test_inner_join_drops_null_key_rows_without_touching_storage(): $storage = new SpyBucketsStorage(new MemoryBuckets()); $processor = HashJoinProcessorMother::grace( - df()->read(from_rows(rows( + PhysicalPlanMother::reading(from_rows(rows( schema(int_schema('user_id'), str_schema('name')), row(['user_id' => 1, 'name' => 'Alice']), ))), @@ -259,7 +259,7 @@ public function test_inner_join_drops_null_key_rows_without_touching_storage(): public function test_inner_join_emits_every_matching_right_row(): void { $processor = HashJoinProcessorMother::grace( - df()->read(from_rows(rows( + PhysicalPlanMother::reading(from_rows(rows( schema(int_schema('user_id'), str_schema('role')), row(['user_id' => 1, 'role' => 'admin']), row(['user_id' => 1, 'role' => 'writer']), @@ -294,7 +294,7 @@ public function test_inner_join_emits_every_matching_right_row(): void public function test_left_anti_join(): void { $processor = HashJoinProcessorMother::grace( - df()->read(from_rows(rows(schema(int_schema('user_id')), row(['user_id' => 1])))), + PhysicalPlanMother::reading(from_rows(rows(schema(int_schema('user_id')), row(['user_id' => 1])))), Expression::on(['id' => 'user_id']), Join::left_anti, ); @@ -319,7 +319,7 @@ public function test_left_anti_join(): void public function test_left_anti_join_keeps_null_key_left_rows(): void { $processor = HashJoinProcessorMother::grace( - df()->read(from_rows(rows(schema(int_schema('user_id')), row(['user_id' => 1])))), + PhysicalPlanMother::reading(from_rows(rows(schema(int_schema('user_id')), row(['user_id' => 1])))), Expression::on(['id' => 'user_id']), Join::left_anti, ); @@ -344,7 +344,7 @@ public function test_left_anti_join_keeps_null_key_left_rows(): void public function test_left_join(): void { $processor = HashJoinProcessorMother::grace( - df()->read(from_rows(rows( + PhysicalPlanMother::reading(from_rows(rows( schema(int_schema('user_id'), str_schema('name')), row(['user_id' => 1, 'name' => 'Alice']), ))), @@ -380,7 +380,7 @@ public function test_left_join(): void public function test_left_join_pads_null_key_left_rows(): void { $processor = HashJoinProcessorMother::grace( - df()->read(from_rows(rows( + PhysicalPlanMother::reading(from_rows(rows( schema(int_schema('user_id'), str_schema('name')), row(['user_id' => 1, 'name' => 'Alice']), ))), @@ -416,7 +416,7 @@ public function test_left_join_pads_null_key_left_rows(): void public function test_non_equality_join_falls_back_to_a_single_bucket(): void { $processor = HashJoinProcessorMother::grace( - df()->read(from_rows(rows( + PhysicalPlanMother::reading(from_rows(rows( schema(int_schema('user_id'), str_schema('name')), row(['user_id' => 1, 'name' => 'Alice']), row(['user_id' => 2, 'name' => 'Bob']), @@ -445,7 +445,7 @@ public function test_non_equality_join_falls_back_to_a_single_bucket(): void public function test_resident_storage_preserves_left_row_order(): void { $processor = HashJoinProcessorMother::resident( - df()->read(from_rows(rows( + PhysicalPlanMother::reading(from_rows(rows( schema(int_schema('user_id'), str_schema('name')), row(['user_id' => 1, 'name' => 'Alice']), row(['user_id' => 2, 'name' => 'Bob']), @@ -483,7 +483,7 @@ public function test_resident_storage_preserves_left_row_order(): void public function test_right_join(): void { $processor = HashJoinProcessorMother::grace( - df()->read(from_rows(rows( + PhysicalPlanMother::reading(from_rows(rows( schema(int_schema('user_id'), str_schema('name')), row(['user_id' => 1, 'name' => 'Alice']), row(['user_id' => 2, 'name' => 'Bob']), @@ -520,7 +520,7 @@ public function test_right_join(): void public function test_right_join_pads_null_key_right_rows(): void { $processor = HashJoinProcessorMother::grace( - df()->read(from_rows(rows( + PhysicalPlanMother::reading(from_rows(rows( schema(int_schema('user_id', nullable: true), str_schema('name')), row(['user_id' => 1, 'name' => 'Alice']), row(['user_id' => null, 'name' => 'Bob']), @@ -559,7 +559,7 @@ public function test_storages_are_cleared_after_the_join(): void $storage = new SpyBucketsStorage(new MemoryBuckets()); $processor = HashJoinProcessorMother::grace( - df()->read(from_rows(rows( + PhysicalPlanMother::reading(from_rows(rows( schema(int_schema('user_id'), str_schema('name')), row(['user_id' => 1, 'name' => 'Alice']), ))), @@ -582,7 +582,7 @@ public function test_pairs_with_a_missing_right_side_read_only_left_buckets(): v $storage = new SpyBucketsStorage(new MemoryBuckets()); $processor = HashJoinProcessorMother::grace( - df()->read(from_rows(rows(schema()))), + PhysicalPlanMother::reading(from_rows(rows(schema()))), Expression::on(['id' => 'user_id']), Join::left, $storage, @@ -604,7 +604,7 @@ public function test_resident_join_forwards_stop_to_its_left_upstream(): void { $upstream = (new CountingExtractor(schema(int_schema('id')), RowsMother::sequentialIds(5)))->withBatchSize(1); $joined = HashJoinProcessorMother::resident( - df()->read(from_rows(RowsMother::sequentialIds(5))), + PhysicalPlanMother::reading(from_rows(RowsMother::sequentialIds(5))), Expression::on(['id' => 'id']), Join::inner, batchSize: 1, @@ -625,7 +625,7 @@ public function test_resident_join_forwards_stop_to_its_left_upstream(): void public function test_duplicated_entries_outside_join_columns_throw_join_exception(): void { $processor = HashJoinProcessorMother::grace( - df()->read(from_rows(rows( + PhysicalPlanMother::reading(from_rows(rows( schema(int_schema('user_id'), str_schema('name')), row(['user_id' => 1, 'name' => 'Alice']), ))), @@ -644,4 +644,21 @@ public function test_duplicated_entries_outside_join_columns_throw_join_exceptio iterator_to_array($processor->process($generator, flow_context()), false); } + + public function test_the_right_side_is_pulled_through_a_frame_output(): void + { + $right = PhysicalPlanMother::reading(from_rows(rows( + schema(int_schema('id'), str_schema('name')), + row(['id' => 1, 'name' => 'Alice']), + ))); + $processor = HashJoinProcessorMother::resident($right, Expression::on(['id' => 'id'], 'r_'), Join::inner); + + $generator = (static function () { + yield rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])); + })(); + + $batches = iterator_to_array($processor->process($generator, flow_context()), false); + + static::assertSame([['id' => 1, 'r_id' => 1, 'r_name' => 'Alice']], $batches[0]->toArray()); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/TopNProcessorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/TopNProcessorTest.php new file mode 100644 index 0000000000..b8f98755d5 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/TopNProcessorTest.php @@ -0,0 +1,100 @@ +desc(), ref('name')); + $batches = static fn(): Generator => ScoredRows::batches( + [[3, 'c'], [9, 'a'], [3, 'b']], + [[7, 'x'], [9, 'z'], [1, 'q']], + [[9, 'b'], [3, 'a'], [7, 'y']], + ); + + $sorted = ScoredRows::merged((new MemorySortProcessor($refs))->process($batches(), flow_context())); + $top = ScoredRows::merged((new TopNProcessor($refs, 4))->process($batches(), flow_context())); + + static::assertSame(array_slice($sorted, 0, 4), $top); + } + + public function test_ties_keep_the_order_they_arrived_in(): void + { + $top = ScoredRows::merged((new TopNProcessor(refs(ref('score')), 3))->process( + ScoredRows::batches([[1, 'first'], [1, 'second']], [[1, 'third'], [1, 'fourth']]), + flow_context(), + )); + + static::assertSame(['first', 'second', 'third'], array_column($top, 'name')); + } + + public function test_it_keeps_every_row_when_the_input_is_shorter_than_the_limit(): void + { + $top = ScoredRows::merged((new TopNProcessor(refs(ref('score')), 10))->process(ScoredRows::batches([ + [2, 'b'], + [1, 'a'], + ]), flow_context())); + + static::assertSame([['score' => 1, 'name' => 'a'], ['score' => 2, 'name' => 'b']], $top); + } + + public function test_it_trims_while_reading_many_batches(): void + { + $input = []; + + for ($i = 100; $i > 0; $i--) { + $input[] = [[$i, 'n' . $i]]; + } + + $top = ScoredRows::merged((new TopNProcessor(refs(ref('score')), 2))->process( + ScoredRows::batches(...$input), + flow_context(), + )); + + static::assertSame([1, 2], array_column($top, 'score')); + } + + public function test_an_empty_input_emits_nothing(): void + { + static::assertSame( + [], + iterator_to_array((new TopNProcessor(refs(ref('score')), 3))->process( + ScoredRows::batches(), + flow_context(), + )), + ); + } + + public function test_bind_keeps_the_input_schema_as_output(): void + { + $schema = schema(int_schema('score'), str_schema('name')); + + static::assertSame($schema, (new TopNProcessor(refs(ref('score')), 3))->bind($schema)->output); + } + + public function test_a_limit_below_one_is_refused(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('TopN limit must be greater than 0, given: 0'); + + new TopNProcessor(refs(ref('score')), 0); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Retry/DelayFactory/ExponentialTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Retry/DelayFactory/ExponentialTest.php deleted file mode 100644 index 00b888c0f9..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Retry/DelayFactory/ExponentialTest.php +++ /dev/null @@ -1,66 +0,0 @@ -delay(1)->microseconds()); - static::assertSame(3_000_000, $delayFactory->delay(2)->microseconds()); - static::assertSame(9_000_000, $delayFactory->delay(3)->microseconds()); - static::assertSame(27_000_000, $delayFactory->delay(4)->microseconds()); - } - - public function test_exponential_backoff_with_default_multiplier(): void - { - $baseDuration = Duration::fromSeconds(1); - $delayFactory = delay_exponential($baseDuration); - - static::assertSame(1_000_000, $delayFactory->delay(1)->microseconds()); - static::assertSame(2_000_000, $delayFactory->delay(2)->microseconds()); - static::assertSame(4_000_000, $delayFactory->delay(3)->microseconds()); - static::assertSame(8_000_000, $delayFactory->delay(4)->microseconds()); - } - - public function test_exponential_backoff_with_large_attempt_numbers(): void - { - $baseDuration = Duration::fromMilliseconds(100); - $maxDelay = Duration::fromSeconds(60); - $delayFactory = delay_exponential($baseDuration, 2, $maxDelay); - - $delay = $delayFactory->delay(20); - static::assertSame(60_000_000, $delay->microseconds()); - } - - public function test_exponential_backoff_with_max_delay(): void - { - $baseDuration = Duration::fromSeconds(1); - $maxDelay = Duration::fromSeconds(5); - $delayFactory = delay_exponential($baseDuration, 2, $maxDelay); - - static::assertSame(1_000_000, $delayFactory->delay(1)->microseconds()); - static::assertSame(2_000_000, $delayFactory->delay(2)->microseconds()); - static::assertSame(4_000_000, $delayFactory->delay(3)->microseconds()); - static::assertSame(5_000_000, $delayFactory->delay(4)->microseconds()); - static::assertSame(5_000_000, $delayFactory->delay(5)->microseconds()); - } - - public function test_first_attempt_equals_base_duration(): void - { - $baseDuration = Duration::fromMilliseconds(250); - $delayFactory = delay_exponential($baseDuration); - - static::assertSame(250_000, $delayFactory->delay(1)->microseconds()); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Retry/DelayFactory/FixedTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Retry/DelayFactory/FixedTest.php deleted file mode 100644 index 6f5cddb39d..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Retry/DelayFactory/FixedTest.php +++ /dev/null @@ -1,34 +0,0 @@ -delay(1)->microseconds()); - static::assertSame(2_000_000, $secondDelay->delay(1)->microseconds()); - } - - public function test_returns_same_duration_for_all_attempts(): void - { - $duration = duration_seconds(1); - $delayFactory = delay_fixed($duration); - - static::assertSame(1_000_000, $delayFactory->delay(1)->microseconds()); - static::assertSame(1_000_000, $delayFactory->delay(2)->microseconds()); - static::assertSame(1_000_000, $delayFactory->delay(10)->microseconds()); - static::assertSame(1_000_000, $delayFactory->delay(100)->microseconds()); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Retry/DelayFactory/JitterTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Retry/DelayFactory/JitterTest.php deleted file mode 100644 index b1f38bd5fd..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Retry/DelayFactory/JitterTest.php +++ /dev/null @@ -1,108 +0,0 @@ -expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Jitter percentage must be between 0.0 and 1.0'); - - delay_jitter(delay_fixed(duration_seconds(1)), 1.1); - } - - public function test_invalid_jitter_percentage_below_zero(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Jitter percentage must be between 0.0 and 1.0'); - - delay_jitter(delay_fixed(duration_seconds(1)), -0.1); - } - - public function test_jitter_adds_variation(): void - { - $jitterFactory = delay_jitter(delay_fixed(duration_seconds(1)), 0.5); - - $delays = []; - - for ($i = 0; $i < 100; $i++) { - $delays[] = $jitterFactory->delay(1)->microseconds(); - } - - $minExpected = 500_000; - $maxExpected = 1_500_000; - - $minActual = min($delays); - $maxActual = max($delays); - - static::assertNotSame($minActual, $maxActual, 'Jitter should create variation in delays'); - - foreach ($delays as $delay) { - static::assertGreaterThanOrEqual($minExpected, $delay); - static::assertLessThanOrEqual($maxExpected, $delay); - } - } - - public function test_jitter_boundaries(): void - { - $jitterFactory = delay_jitter(delay_fixed(duration_seconds(10)), 1.0); - - $delays = []; - - for ($i = 0; $i < 1000; $i++) { - $delays[] = $jitterFactory->delay(1)->microseconds(); - } - - $minDelay = min($delays); - $maxDelay = max($delays); - - static::assertGreaterThanOrEqual(0, $minDelay); - static::assertLessThanOrEqual(20_000_000, $maxDelay); - } - - public function test_jitter_never_goes_negative(): void - { - $jitterFactory = delay_jitter(delay_fixed(duration_microseconds(100)), 1.0); - - for ($i = 0; $i < 100; $i++) { - $delay = $jitterFactory->delay(1); - static::assertGreaterThanOrEqual(0, $delay->microseconds()); - } - } - - public function test_jitter_with_different_delay_factories(): void - { - $jitterFactory = delay_jitter(delay_exponential(duration_seconds(1)), 0.2); - - $attempt1Delay = $jitterFactory->delay(1); - $attempt2Delay = $jitterFactory->delay(2); - - static::assertGreaterThanOrEqual(800_000, $attempt1Delay->microseconds()); - static::assertLessThanOrEqual(1_200_000, $attempt1Delay->microseconds()); - - static::assertGreaterThanOrEqual(1_600_000, $attempt2Delay->microseconds()); - static::assertLessThanOrEqual(2_400_000, $attempt2Delay->microseconds()); - } - - public function test_jitter_with_zero_percentage(): void - { - $jitterFactory = delay_jitter(delay_fixed(duration_seconds(1)), 0.0); - - static::assertSame(1_000_000, $jitterFactory->delay(1)->microseconds()); - static::assertSame(1_000_000, $jitterFactory->delay(2)->microseconds()); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Retry/DelayFactory/LinearTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Retry/DelayFactory/LinearTest.php deleted file mode 100644 index 39a3fd0682..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Retry/DelayFactory/LinearTest.php +++ /dev/null @@ -1,58 +0,0 @@ -delay(1)->microseconds()); - } - - public function test_linear_backoff(): void - { - $delayFactory = delay_linear(duration_seconds(1), duration_milliseconds(500)); - - static::assertSame(1_000_000, $delayFactory->delay(1)->microseconds()); - static::assertSame(1_500_000, $delayFactory->delay(2)->microseconds()); - static::assertSame(2_000_000, $delayFactory->delay(3)->microseconds()); - static::assertSame(2_500_000, $delayFactory->delay(4)->microseconds()); - } - - public function test_linear_backoff_with_different_increments(): void - { - $delayFactory = delay_linear(duration_milliseconds(100), duration_milliseconds(100)); - - static::assertSame(100_000, $delayFactory->delay(1)->microseconds()); - static::assertSame(200_000, $delayFactory->delay(2)->microseconds()); - static::assertSame(300_000, $delayFactory->delay(3)->microseconds()); - static::assertSame(400_000, $delayFactory->delay(4)->microseconds()); - } - - public function test_linear_backoff_with_large_attempt_numbers(): void - { - $delayFactory = delay_linear(duration_milliseconds(10), duration_milliseconds(5)); - - static::assertSame(505_000, $delayFactory->delay(100)->microseconds()); - } - - public function test_linear_backoff_with_zero_increment(): void - { - $delayFactory = delay_linear(duration_seconds(2), duration_microseconds(0)); - - static::assertSame(2_000_000, $delayFactory->delay(1)->microseconds()); - static::assertSame(2_000_000, $delayFactory->delay(2)->microseconds()); - static::assertSame(2_000_000, $delayFactory->delay(10)->microseconds()); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Retry/RetryStrategy/AnyThrowableExceptTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Retry/RetryStrategy/AnyThrowableExceptTest.php deleted file mode 100644 index 965e8678f2..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Retry/RetryStrategy/AnyThrowableExceptTest.php +++ /dev/null @@ -1,90 +0,0 @@ -expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Exception types cannot be empty'); - - new AnyThrowableExcept([], 3); - } - - public function test_error_types_are_supported(): void - { - $strategy = new AnyThrowableExcept([TypeError::class], 3); - - static::assertFalse($strategy->shouldRetry(new TypeError('boom'), 1)); - static::assertTrue($strategy->shouldRetry(new RuntimeException('boom'), 1)); - } - - public function test_excluding_throwable_interface_retries_nothing(): void - { - $strategy = new AnyThrowableExcept([Throwable::class], 3); - - static::assertFalse($strategy->shouldRetry(new RuntimeException('boom'), 1)); - } - - public function test_invalid_class_name_throws_exception(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage("Class 'Flow\\NotAClass' does not exist"); - - // @mago-ignore analysis:possibly-invalid-argument - new AnyThrowableExcept(['Flow\NotAClass'], 3); - } - - public function test_non_throwable_class_throws_exception(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('is not a Throwable'); - - // @mago-ignore analysis:invalid-argument - new AnyThrowableExcept([self::class], 3); - } - - public function test_respects_max_attempts(): void - { - $strategy = new AnyThrowableExcept([InvalidLogicException::class], 2); - - static::assertTrue($strategy->shouldRetry(new RuntimeException('boom'), 1)); - static::assertTrue($strategy->shouldRetry(new RuntimeException('boom'), 2)); - static::assertFalse($strategy->shouldRetry(new RuntimeException('boom'), 3)); - } - - public function test_retries_everything_outside_the_excluded_types(): void - { - $strategy = new AnyThrowableExcept([InvalidLogicException::class], 3); - - static::assertTrue($strategy->shouldRetry(new RuntimeException('boom'), 1)); - static::assertFalse($strategy->shouldRetry(InvalidLogicException::because('nope'), 1)); - } - - public function test_subclasses_of_an_excluded_type_are_also_excluded(): void - { - $strategy = new AnyThrowableExcept([RuntimeException::class], 3); - - static::assertFalse($strategy->shouldRetry(new OutOfBoundsException('boom'), 1)); - } - - public function test_throws_exception_for_zero_limit(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Retry limit must be greater than 0'); - - new AnyThrowableExcept([InvalidLogicException::class], 0); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Retry/RetryStrategy/AnyThrowableTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Retry/RetryStrategy/AnyThrowableTest.php deleted file mode 100644 index c4a02090bb..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Retry/RetryStrategy/AnyThrowableTest.php +++ /dev/null @@ -1,69 +0,0 @@ -shouldRetry($exception, 1)); - static::assertTrue($strategy->shouldRetry($exception, 2)); - static::assertTrue($strategy->shouldRetry($exception, 3)); - static::assertFalse($strategy->shouldRetry($exception, 4)); - static::assertFalse($strategy->shouldRetry($exception, 100)); - } - - public function test_retries_on_any_exception(): void - { - $strategy = new AnyThrowable(5); - - static::assertTrue($strategy->shouldRetry(new Exception('test'), 1)); - static::assertTrue($strategy->shouldRetry(new RuntimeException('test'), 1)); - static::assertTrue($strategy->shouldRetry(new InvalidArgumentException('test'), 1)); - static::assertTrue($strategy->shouldRetry(new LogicException('test'), 2)); - static::assertTrue($strategy->shouldRetry(new Error('test'), 1)); - static::assertTrue($strategy->shouldRetry(new TypeError('test'), 1)); - } - - public function test_throws_exception_for_negative_limit(): void - { - $this->expectException(FlowInvalidArgumentException::class); - $this->expectExceptionMessage('Retry limit must be greater than 0'); - - new AnyThrowable(-1); - } - - public function test_throws_exception_for_zero_limit(): void - { - $this->expectException(FlowInvalidArgumentException::class); - $this->expectExceptionMessage('Retry limit must be greater than 0'); - - new AnyThrowable(0); - } - - public function test_works_with_custom_exceptions(): void - { - $customException = new class('test') extends Exception {}; - $anotherException = new class('test') extends Error {}; - - $strategy = new AnyThrowable(3); - - static::assertTrue($strategy->shouldRetry($customException, 1)); - static::assertTrue($strategy->shouldRetry($anotherException, 1)); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Retry/RetryStrategy/OnExceptionTypesTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Retry/RetryStrategy/OnExceptionTypesTest.php deleted file mode 100644 index 85f077ffc4..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Retry/RetryStrategy/OnExceptionTypesTest.php +++ /dev/null @@ -1,133 +0,0 @@ -shouldRetry($customException, 1)); - static::assertTrue($strategy->shouldRetry($anotherException, 1)); - } - - public function test_empty_array_throws_exception(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage( - 'Exception types cannot be empty. Use AnyThrowable strategy to retry on any throwable.', - ); - new OnExceptionTypes([], 3); - } - - public function test_error_types_are_supported(): void - { - $strategy = new OnExceptionTypes([Error::class], 3); - static::assertTrue($strategy->shouldRetry(new Error('test'), 1)); - static::assertTrue($strategy->shouldRetry(new TypeError('test'), 1)); - static::assertFalse($strategy->shouldRetry(new Exception('test'), 1)); - } - - public function test_inheritance_with_specific_subclass(): void - { - $strategy = new OnExceptionTypes([LogicException::class], 3); - // Should match LogicException and its subclasses - static::assertTrue($strategy->shouldRetry(new LogicException('test'), 1)); - static::assertTrue($strategy->shouldRetry(new BaseInvalidArgumentException('test'), 1)); - // Should not match Exception or RuntimeException - static::assertFalse($strategy->shouldRetry(new Exception('test'), 1)); - static::assertFalse($strategy->shouldRetry(new RuntimeException('test'), 1)); - } - - public function test_invalid_class_name_throws_exception(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage("Class 'NonExistentClass' does not exist"); - // @mago-ignore analysis:possibly-invalid-argument - new OnExceptionTypes(['NonExistentClass'], 3); - } - - public function test_non_throwable_class_throws_exception(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage("Class 'stdClass' is not a Throwable"); - // @mago-ignore analysis:invalid-argument - new OnExceptionTypes([stdClass::class], 3); - } - - public function test_respects_max_attempts(): void - { - $strategy = new OnExceptionTypes([RuntimeException::class], 3); - $exception = new RuntimeException('test'); - static::assertTrue($strategy->shouldRetry($exception, 1)); - static::assertTrue($strategy->shouldRetry($exception, 2)); - static::assertTrue($strategy->shouldRetry($exception, 3)); - static::assertFalse($strategy->shouldRetry($exception, 4)); - static::assertFalse($strategy->shouldRetry($exception, 100)); - } - - public function test_retries_on_multiple_exception_types(): void - { - $strategy = new OnExceptionTypes([RuntimeException::class, UnexpectedValueException::class], 3); - static::assertTrue($strategy->shouldRetry(new RuntimeException('test'), 1)); - static::assertTrue($strategy->shouldRetry(new UnexpectedValueException('test'), 1)); - static::assertFalse($strategy->shouldRetry(new Exception('test'), 1)); - static::assertFalse($strategy->shouldRetry(new LogicException('test'), 1)); - } - - public function test_retries_on_specific_exception_types(): void - { - $strategy = new OnExceptionTypes([RuntimeException::class], 3); - static::assertTrue($strategy->shouldRetry(new RuntimeException('test'), 1)); - static::assertFalse($strategy->shouldRetry(new Exception('test'), 1)); - static::assertFalse($strategy->shouldRetry(new LogicException('test'), 1)); - } - - public function test_supports_exception_inheritance(): void - { - $strategy = new OnExceptionTypes([Exception::class], 3); - // Should match Exception and all its subclasses - static::assertTrue($strategy->shouldRetry(new Exception('test'), 1)); - static::assertTrue($strategy->shouldRetry(new RuntimeException('test'), 1)); - static::assertTrue($strategy->shouldRetry(new LogicException('test'), 1)); - static::assertTrue($strategy->shouldRetry(new BaseInvalidArgumentException('test'), 1)); - } - - public function test_throwable_interface_is_accepted(): void - { - $strategy = new OnExceptionTypes([Throwable::class], 3); - static::assertTrue($strategy->shouldRetry(new Exception('test'), 1)); - static::assertTrue($strategy->shouldRetry(new Error('test'), 1)); - } - - public function test_throws_exception_for_negative_limit(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Retry limit must be greater than 0'); - new OnExceptionTypes([RuntimeException::class], -1); - } - - public function test_throws_exception_for_zero_limit(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Retry limit must be greater than 0'); - new OnExceptionTypes([RuntimeException::class], 0); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Sink/BranchedTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Sink/BranchedTest.php new file mode 100644 index 0000000000..7f141b5f2c --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Sink/BranchedTest.php @@ -0,0 +1,82 @@ +read(from_array([['id' => 1], ['id' => 2]])) + ->write(new Branched(ref('id')->equals(lit(1)), to_memory($memory))); + + static::assertSame(<<<'PLAN' + Outputs preserving · opaque · streaming + ├─ #2 Result preserving · transparent · streaming + │ │ Rows this plan hands out: to the trigger, or to the node reading it + │ └─ #1 Read source · transparent · streaming + │ Extractor: ArrayExtractor + └─ #4 Write preserving · opaque · streaming + │ Loader: MemoryLoader + └─ #3 Filter reducing · transparent · streaming + │ Condition: Equals + └─ #1 Read (shared) + PLAN, $dataFrame->explain()->toString(format: Format::declarations)); + + $dataFrame->run(); + + static::assertSame([['id' => 1]], $memory->dump()); + } + + public function test_with_transformation_nests_a_transformed_sink(): void + { + $condition = ref('id')->equals(lit(1)); + $transformation = select('id'); + $loader = to_memory(new ArrayMemory()); + + static::assertEquals( + new Branched($condition, new Transformed($transformation, $loader)), + (new Branched($condition, $loader))->withTransformation($transformation), + ); + } + + public function test_with_transformation_filters_before_it_transforms(): void + { + $dataFrame = df() + ->read(from_array([['id' => 1]])) + ->write((new Branched(ref('id')->equals(lit(1)), to_memory(new ArrayMemory())))->withTransformation(select( + 'id', + ))); + + static::assertSame(<<<'PLAN' + Outputs preserving · opaque · streaming + ├─ #2 Result preserving · transparent · streaming + │ │ Rows this plan hands out: to the trigger, or to the node reading it + │ └─ #1 Read source · transparent · streaming + │ Extractor: ArrayExtractor + └─ #5 Write preserving · opaque · streaming + │ Loader: MemoryLoader + └─ #4 Select preserving · transparent · streaming + │ Columns: id + └─ #3 Filter reducing · transparent · streaming + │ Condition: Equals + └─ #1 Read (shared) + PLAN, $dataFrame->explain()->toString(format: Format::declarations)); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Sink/TransactionalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Sink/TransactionalTest.php new file mode 100644 index 0000000000..c83b7a9f4b --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Sink/TransactionalTest.php @@ -0,0 +1,226 @@ +read(from_array([['id' => 1]])) + ->write( + new Transactional( + $transaction, + new Transformed(new AddRowIndexTransformer('idx', StartFrom::ZERO), to_memory(new ArrayMemory())), + new Branched(ref('id')->equals(lit(1)), to_memory(new ArrayMemory())), + ), + ); + + static::assertSame(<<<'PLAN' + Outputs preserving · opaque · streaming + ├─ #2 Result preserving · transparent · streaming + │ │ Rows this plan hands out: to the trigger, or to the node reading it + │ └─ #1 Read source · transparent · streaming + │ Extractor: ArrayExtractor + └─ #7 Transaction preserving · opaque · streaming + ├─ #4 Write preserving · opaque · streaming + │ │ Loader: MemoryLoader + │ └─ #3 Transform unknown · opaque · streaming · redefines unknown + │ └─ #1 Read (shared) + └─ #6 Write preserving · opaque · streaming + │ Loader: MemoryLoader + └─ #5 Filter reducing · transparent · streaming + │ Condition: Equals + └─ #1 Read (shared) + PLAN, $dataFrame->explain()->toString(format: Format::declarations)); + + $dataFrame->run(); + + static::assertSame(['begin', 'commit', 'begin', 'commit'], $transaction->log); + } + + public function test_a_childs_own_write_joins_the_same_transaction(): void + { + /** @var ArrayObject $log */ + $log = new ArrayObject(); + $transaction = new RecordingTransaction(); + + $dataFrame = df() + ->read(from_sequence_number('id', 0, 3)) + ->batchSize(2) + ->write( + new Transactional( + $transaction, + new Transformed( + new CallbackTransformation(static fn(DataFrame $prefix): DataFrame => $prefix->write(new CallOrderLoader( + 'inner', + $log, + ))), + new CallOrderLoader('outer', $log), + ), + ), + ); + + static::assertSame(<<<'PLAN' + Outputs preserving · opaque · streaming + ├─ #3 Result preserving · transparent · streaming + │ │ Rows this plan hands out: to the trigger, or to the node reading it + │ └─ #2 Batch preserving · transparent · streaming + │ │ Batch size: 2 + │ └─ #1 Read source · transparent · streaming + │ Extractor: SequenceExtractor + └─ #6 Transaction preserving · opaque · streaming + ├─ #4 Write preserving · opaque · streaming + │ │ Loader: CallOrderLoader + │ └─ #2 Batch (shared) + └─ #5 Write preserving · opaque · streaming + │ Loader: CallOrderLoader + └─ #2 Batch (shared) + PLAN, $dataFrame->explain()->toString(format: Format::declarations)); + + $dataFrame->run(); + + static::assertSame(['inner:2', 'outer:2', 'inner:2', 'outer:2'], $log->getArrayCopy()); + static::assertSame(['begin', 'commit', 'begin', 'commit', 'begin', 'commit'], $transaction->log); + } + + public function test_children_run_in_write_call_order_inside_one_transaction(): void + { + /** @var ArrayObject $log */ + $log = new ArrayObject(); + + df() + ->read(from_sequence_number('id', 0, 3)) + ->batchSize(2) + ->write( + new Transactional( + new RecordingTransaction(), + new CallOrderLoader('a', $log), + new CallOrderLoader('b', $log), + ), + ) + ->run(); + + static::assertSame(['a:2', 'b:2', 'a:2', 'b:2'], $log->getArrayCopy()); + } + + public function test_a_transaction_without_a_sink_is_refused(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('At least one loader must be provided'); + + new Transactional(new RecordingTransaction()); + } + + public function test_a_transaction_inside_a_transaction_is_refused(): void + { + $this->expectException(InvalidLogicException::class); + $this->expectExceptionMessage('A transaction cannot contain another transaction'); + + df() + ->read(from_array([['id' => 1]])) + ->write( + new Transactional( + new RecordingTransaction(), + new Transactional(new RecordingTransaction(), to_memory(new ArrayMemory())), + ), + ); + } + + public function test_a_refused_transaction_leaves_the_frame_untouched(): void + { + $dataFrame = df()->read(from_array([['id' => 1]])); + $before = $dataFrame->explain()->toString(); + + try { + $dataFrame->write( + new Transactional( + new RecordingTransaction(), + new Transactional(new RecordingTransaction(), to_memory(new ArrayMemory())), + ), + ); + + static::fail('Expected the nested transaction to be refused.'); + } catch (InvalidLogicException) { + } + + static::assertSame($before, $dataFrame->explain()->toString()); + } + + public function test_a_transactional_nested_in_a_transformed_sink_commits_its_children(): void + { + $transaction = new RecordingTransaction(); + $memory = new ArrayMemory(); + + df() + ->read(from_array([['id' => 1], ['id' => 2]])) + ->write( + new Transformed( + new AddRowIndexTransformer('idx', StartFrom::ZERO), + new Transactional($transaction, to_memory($memory)), + ), + ) + ->run(); + + static::assertSame(['begin', 'commit', 'begin', 'commit'], $transaction->log); + static::assertSame([0, 1], array_column($memory->dump(), 'idx')); + } + + public function test_getters_return_the_transaction_and_the_sinks_it_was_given(): void + { + $transaction = new RecordingTransaction(); + $first = to_memory(new ArrayMemory()); + $second = new Branched(lit(true), to_memory(new ArrayMemory())); + + $transactional = new Transactional($transaction, $first, $second); + + static::assertSame($transaction, $transactional->transaction()); + static::assertSame([$first, $second], $transactional->sinks()); + } + + public function test_writing_it_on_a_frame_attaches_one_transaction_root(): void + { + $dataFrame = df()->read(from_array([['id' => 1]])); + + (new Transactional(new RecordingTransaction(), to_memory(new ArrayMemory())))->write($dataFrame); + + static::assertSame(<<<'PLAN' + Outputs preserving · opaque · streaming + ├─ #2 Result preserving · transparent · streaming + │ │ Rows this plan hands out: to the trigger, or to the node reading it + │ └─ #1 Read source · transparent · streaming + │ Extractor: ArrayExtractor + └─ #4 Transaction preserving · opaque · streaming + └─ #3 Write preserving · opaque · streaming + │ Loader: MemoryLoader + └─ #1 Read (shared) + PLAN, $dataFrame->explain()->toString(format: Format::declarations)); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Sink/TransformedTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Sink/TransformedTest.php new file mode 100644 index 0000000000..f571549e51 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Sink/TransformedTest.php @@ -0,0 +1,111 @@ +read(from_array([['id' => 1]])) + ->write(new Transformed(new AddRowIndexTransformer('idx', StartFrom::ZERO), to_memory($memory))); + + static::assertSame(<<<'PLAN' + Outputs preserving · opaque · streaming + ├─ #2 Result preserving · transparent · streaming + │ │ Rows this plan hands out: to the trigger, or to the node reading it + │ └─ #1 Read source · transparent · streaming + │ Extractor: ArrayExtractor + └─ #4 Write preserving · opaque · streaming + │ Loader: MemoryLoader + └─ #3 Transform unknown · opaque · streaming · redefines unknown + └─ #1 Read (shared) + PLAN, $dataFrame->explain()->toString(format: Format::declarations)); + + $dataFrame->run(); + + static::assertSame([['id' => 1, 'idx' => 0]], $memory->dump()); + } + + public function test_a_transformation_builds_through_the_frames_verbs(): void + { + $dataFrame = df() + ->read(from_array([['id' => 1]])) + ->write(new Transformed(select('id'), to_memory(new ArrayMemory()))); + + static::assertSame(<<<'PLAN' + Outputs preserving · opaque · streaming + ├─ #2 Result preserving · transparent · streaming + │ │ Rows this plan hands out: to the trigger, or to the node reading it + │ └─ #1 Read source · transparent · streaming + │ Extractor: ArrayExtractor + └─ #4 Write preserving · opaque · streaming + │ Loader: MemoryLoader + └─ #3 Select preserving · transparent · streaming + │ Columns: id + └─ #1 Read (shared) + PLAN, $dataFrame->explain()->toString(format: Format::declarations)); + } + + public function test_a_sink_child_extends_the_chain(): void + { + $dataFrame = df() + ->read(from_array([['id' => 1]])) + ->write( + new Transformed( + new AddRowIndexTransformer('idx', StartFrom::ZERO), + new Branched(ref('id')->equals(lit(1)), to_memory(new ArrayMemory())), + ), + ); + + static::assertSame(<<<'PLAN' + Outputs preserving · opaque · streaming + ├─ #2 Result preserving · transparent · streaming + │ │ Rows this plan hands out: to the trigger, or to the node reading it + │ └─ #1 Read source · transparent · streaming + │ Extractor: ArrayExtractor + └─ #5 Write preserving · opaque · streaming + │ Loader: MemoryLoader + └─ #4 Filter reducing · transparent · streaming + │ Condition: Equals + └─ #3 Transform unknown · opaque · streaming · redefines unknown + └─ #1 Read (shared) + PLAN, $dataFrame->explain()->toString(format: Format::declarations)); + } + + public function test_a_transformation_returning_another_frame_is_refused(): void + { + $this->expectException(InvalidLogicException::class); + $this->expectExceptionMessage( + 'A Transformation inside a sink must return the frame it was given; ' + . CallbackTransformation::class + . ' returned another frame, so its writes would never run', + ); + + df()->read(from_array([['id' => 1]]))->write(new Transformed( + new CallbackTransformation(static fn(DataFrame $prefix): DataFrame => df()->read(from_array([['x' => 1]]))), + to_memory(new ArrayMemory()), + )); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Time/DurationTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Time/DurationTest.php deleted file mode 100644 index 816de4cae2..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Time/DurationTest.php +++ /dev/null @@ -1,111 +0,0 @@ -microseconds()); - static::assertSame(1234, $duration->milliseconds()); - static::assertSame(1, $duration->seconds()); - static::assertSame(0, $duration->minutes()); - } - - public function test_create_from_microseconds(): void - { - $duration = Duration::fromMicroseconds(1000); - - static::assertSame(1000, $duration->microseconds()); - static::assertSame(1, $duration->milliseconds()); - } - - public function test_create_from_milliseconds(): void - { - $duration = Duration::fromMilliseconds(500); - - static::assertSame(500000, $duration->microseconds()); - static::assertSame(500, $duration->milliseconds()); - static::assertSame(0, $duration->seconds()); - } - - public function test_create_from_minutes(): void - { - $duration = Duration::fromMinutes(3); - - static::assertSame(180_000_000, $duration->microseconds()); - static::assertSame(180000, $duration->milliseconds()); - static::assertSame(180, $duration->seconds()); - static::assertSame(3, $duration->minutes()); - } - - public function test_create_from_seconds(): void - { - $duration = Duration::fromSeconds(2); - - static::assertSame(2_000_000, $duration->microseconds()); - static::assertSame(2000, $duration->milliseconds()); - static::assertSame(2, $duration->seconds()); - static::assertSame(0, $duration->minutes()); - } - - public function test_large_values(): void - { - $duration = Duration::fromMinutes(60); - - static::assertSame(3_600_000_000, $duration->microseconds()); - static::assertSame(3_600_000, $duration->milliseconds()); - static::assertSame(3600, $duration->seconds()); - static::assertSame(60, $duration->minutes()); - } - - public function test_negative_duration_throws_exception(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Duration cannot be negative'); - - Duration::fromMicroseconds(-1); - } - - public function test_negative_milliseconds_throws_exception(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Duration cannot be negative'); - - Duration::fromMilliseconds(-100); - } - - public function test_negative_minutes_throws_exception(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Duration cannot be negative'); - - Duration::fromMinutes(-1); - } - - public function test_negative_seconds_throws_exception(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Duration cannot be negative'); - - Duration::fromSeconds(-1); - } - - public function test_zero_duration(): void - { - $duration = Duration::fromMicroseconds(0); - - static::assertSame(0, $duration->microseconds()); - static::assertSame(0, $duration->milliseconds()); - static::assertSame(0, $duration->seconds()); - static::assertSame(0, $duration->minutes()); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Time/FakeSleepTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Time/FakeSleepTest.php deleted file mode 100644 index 52ee21188e..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Time/FakeSleepTest.php +++ /dev/null @@ -1,96 +0,0 @@ -for(Duration::fromSeconds(10)); - $endTime = microtime(true); - - $actualElapsed = $endTime - $startTime; - - static::assertLessThan(0.1, $actualElapsed); - } - - public function test_records_all_sleep_durations(): void - { - $sleep = new FakeSleep(); - - $duration1 = Duration::fromMilliseconds(100); - $duration2 = Duration::fromSeconds(2); - $duration3 = Duration::fromMinutes(1); - - $sleep->for($duration1); - $sleep->for($duration2); - $sleep->for($duration3); - - $sleepDurations = $sleep->sleepDurations(); - - static::assertCount(3, $sleepDurations); - static::assertSame(100, $sleepDurations[0]->milliseconds()); - static::assertSame(2000, $sleepDurations[1]->milliseconds()); - static::assertSame(60000, $sleepDurations[2]->milliseconds()); - } - - public function test_reset(): void - { - $sleep = new FakeSleep(); - - $sleep->for(Duration::fromSeconds(5)); - $sleep->for(Duration::fromSeconds(10)); - - static::assertSame(15_000_000, $sleep->totalMicroseconds()); - static::assertCount(2, $sleep->sleepDurations()); - static::assertSame(2, $sleep->sleepCount()); - - $sleep->reset(); - - static::assertSame(0, $sleep->totalMicroseconds()); - static::assertSame(0, $sleep->totalMilliseconds()); - static::assertSame(0, $sleep->totalSeconds()); - static::assertCount(0, $sleep->sleepDurations()); - static::assertSame(0, $sleep->sleepCount()); - } - - public function test_sleep_count(): void - { - $sleep = new FakeSleep(); - - static::assertSame(0, $sleep->sleepCount()); - - $sleep->for(Duration::fromMilliseconds(100)); - static::assertSame(1, $sleep->sleepCount()); - - $sleep->for(Duration::fromMilliseconds(200)); - static::assertSame(2, $sleep->sleepCount()); - - $sleep->for(Duration::fromMilliseconds(300)); - static::assertSame(3, $sleep->sleepCount()); - } - - public function test_tracks_total_sleep_time(): void - { - $sleep = new FakeSleep(); - - $sleep->for(Duration::fromMilliseconds(100)); - $sleep->for(Duration::fromMilliseconds(200)); - $sleep->for(Duration::fromSeconds(1)); - - static::assertSame(1_300_000, $sleep->totalMicroseconds()); - static::assertSame(1300, $sleep->totalMilliseconds()); - static::assertSame(1, $sleep->totalSeconds()); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/AddRowIndexTransformerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/AddRowIndexTransformerTest.php index 80dac94b8c..c56320d8a3 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/AddRowIndexTransformerTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/AddRowIndexTransformerTest.php @@ -8,6 +8,7 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Transformation\AddRowIndex\StartFrom; use Flow\ETL\Transformer\AddRowIndexTransformer; +use PHPUnit\Framework\Attributes\TestWith; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; @@ -52,6 +53,23 @@ public function test_index_keeps_incrementing_across_batches(): void ); } + #[TestWith([StartFrom::ZERO, 0])] + #[TestWith([StartFrom::ONE, 1])] + public function test_a_fresh_instance_starts_counting_again(StartFrom $startFrom, int $first): void + { + $transformer = new AddRowIndexTransformer('idx', $startFrom); + $schema = schema(int_schema('id')); + $transformer->transform(rows($schema, row(['id' => 1]), row(['id' => 2])), flow_context()); + + $fresh = $transformer->fresh(); + + static::assertNotSame($transformer, $fresh); + static::assertSame( + [['id' => 1, 'idx' => $first]], + $fresh->transform(rows($schema, row(['id' => 1])), flow_context())->toArray(), + ); + } + public function test_index_starting_from_one(): void { static::assertSame( diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/CrossJoinRowsTransformerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/CrossJoinRowsTransformerTest.php index c2dcffd49c..c80bc24eeb 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/CrossJoinRowsTransformerTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/CrossJoinRowsTransformerTest.php @@ -4,10 +4,12 @@ namespace Flow\ETL\Tests\Unit\Transformer; +use Flow\ETL\Executor; use Flow\ETL\Tests\FlowTestCase; +use Flow\ETL\Tests\Mother\PhysicalPlanMother; use Flow\ETL\Transformer\CrossJoinRowsTransformer; -use function Flow\ETL\DSL\df; +use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\from_rows; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\row; @@ -21,10 +23,10 @@ public function test_bind_concatenates_the_left_and_the_right_schema(): void { static::assertEquals( schema(int_schema('id'), str_schema('name')), - (new CrossJoinRowsTransformer(df()->read(from_rows(rows( - schema(str_schema('name')), - row(['name' => 'Alice']), - )))))->bind(schema(int_schema('id')))->output, + (new CrossJoinRowsTransformer( + PhysicalPlanMother::reading(from_rows(rows(schema(str_schema('name')), row(['name' => 'Alice'])))), + new Executor(), + ))->bind(schema(int_schema('id')))->output, ); } @@ -33,9 +35,28 @@ public function test_bind_prefixes_every_right_side_column(): void static::assertEquals( schema(int_schema('id'), str_schema('right_name')), (new CrossJoinRowsTransformer( - df()->read(from_rows(rows(schema(str_schema('name')), row(['name' => 'Alice'])))), + PhysicalPlanMother::reading(from_rows(rows(schema(str_schema('name')), row(['name' => 'Alice'])))), + new Executor(), 'right_', ))->bind(schema(int_schema('id')))->output, ); } + + public function test_the_right_side_is_fetched_through_a_frame_output(): void + { + $transformer = new CrossJoinRowsTransformer( + PhysicalPlanMother::reading(from_rows(rows( + schema(str_schema('name')), + row(['name' => 'Alice']), + row(['name' => 'Bob']), + ))), + new Executor(), + 'r_', + ); + + static::assertSame( + [['id' => 1, 'r_name' => 'Alice'], ['id' => 1, 'r_name' => 'Bob']], + $transformer->transform(rows(schema(int_schema('id')), row(['id' => 1])), flow_context())->toArray(), + ); + } } diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeExtractorTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeExtractorTest.php index 0fe09c24ca..2c598399fc 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeExtractorTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeExtractorTest.php @@ -10,8 +10,7 @@ use Flow\ETL\Tests\Double\CountingFilesystem; use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Tests\Mother\RowsMother; -use Flow\Filesystem\Path\Filter\Filters; -use Flow\Filesystem\Path\Filter\OnlyFiles; +use Flow\Filesystem\Tests\Double\RejectingFilter; use Flow\Floe\FloeExtractor; use Flow\Floe\Tests\Context\FloeEngineContext; @@ -130,21 +129,6 @@ public function test_union_by_name_reads_every_file_under_one_schema(): void ); } - public function test_change_limit_to_zero_throws(): void - { - $this->expectException(InvalidArgumentException::class); - - from_floe(path('memory://x.floe'), filesystem: memory_filesystem())->pushLimit(0); - } - - public function test_default_filter_keeps_only_files(): void - { - static::assertInstanceOf( - OnlyFiles::class, - from_floe(path('memory://x.floe'), filesystem: memory_filesystem())->filter(), - ); - } - public function test_extract_adds_input_file_uri_when_configured(): void { $context = flow_context(config_builder()->build()); @@ -193,11 +177,10 @@ public function test_extract_honors_limit(): void $loader->closure($context); $extractor = from_floe($path, filesystem: $memory); - $extractor->pushLimit(2); $ids = []; - foreach ($extractor->extract($context) as $batch) { + foreach ($extractor->extract($context, limit: 2) as $batch) { foreach ($batch->all() as $extractedRow) { $ids[] = $extractedRow->get('id'); } @@ -310,17 +293,6 @@ public function test_extract_yields_the_metadata_column_schema_promises(): void static::assertSame($path->uri(), $batches[0]->first()->get('_input_file_uri')); } - public function test_is_limited_reflects_change_limit(): void - { - $extractor = from_floe(path('memory://x.floe'), filesystem: memory_filesystem()); - - static::assertNull($extractor->pushedLimit()); - - $extractor->pushLimit(5); - - static::assertNotNull($extractor->pushedLimit()); - } - public function test_negative_offset_throws(): void { $this->expectException(InvalidArgumentException::class); @@ -501,16 +473,19 @@ public function test_extract_closes_the_reader_when_the_pipeline_stops(): void static::assertSame($counting->readFromCalls, $counting->closedStreams()); } - public function test_schema_forgets_the_fold_when_the_path_filter_narrows(): void + public function test_a_path_filter_narrows_the_read_but_not_the_schema(): void { $counting = new CountingFilesystem($memory = memory_filesystem()); FloeEngineContext::writePartitionedFiles($memory); $extractor = from_floe(path('memory://parts/*/*.floe'), filesystem: $counting); - $extractor->schema(); - $extractor->withPathFilter(new OnlyFiles())->schema(); + $schema = $extractor->schema(); - static::assertSame(2, $counting->readFromCalls); + $batches = iterator_to_array($extractor->extract(flow_context(config()), pathFilter: new RejectingFilter())); + + static::assertSame([], $batches); + static::assertSame(1, $counting->readFromCalls); + static::assertEquals($schema, $extractor->schema()); } public function test_source_returns_path(): void @@ -521,15 +496,6 @@ public function test_source_returns_path(): void ); } - public function test_with_path_filter_composes_filters(): void - { - $extractor = from_floe(path('memory://x.floe'), filesystem: memory_filesystem()) - ->withPathFilter(new OnlyFiles()) - ->withPathFilter(new OnlyFiles()); - - static::assertInstanceOf(Filters::class, $extractor->filter()); - } - public function test_is_repeatable(): void { static::assertTrue(from_floe(path('memory://x.floe'), filesystem: memory_filesystem())->isRepeatable()); diff --git a/web/landing/assets/codemirror/completions/dataframe.js b/web/landing/assets/codemirror/completions/dataframe.js index 4810f6b02f..e978b8c89b 100644 --- a/web/landing/assets/codemirror/completions/dataframe.js +++ b/web/landing/assets/codemirror/completions/dataframe.js @@ -1,7 +1,7 @@ /** * CodeMirror Completer for Flow PHP DataFrame Methods * - * DataFrame methods: 49 + * DataFrame methods: 47 * DataFrame-returning methods from classes: 3 * * This completer triggers after DataFrame-returning methods @@ -10,7 +10,7 @@ import { CompletionContext, snippet } from "@codemirror/autocomplete" // Map of DataFrame-returning methods grouped by class -const dataframeReturningMethods = {"flow":["extract","from","process","read"],"groupeddataframe":["aggregate"],"dataframe":["aggregate","batchBy","batchSize","cache","collect","collectRefs","constrain","crossJoin","drop","dropDuplicates","duplicateRow","filter","filterPartitions","filters","join","joinEach","limit","load","match","offset","onError","repartition","rename","renameEach","rows","select","sortBy","transform","until","void","with","withEntries","withEntry","write"]}; +const dataframeReturningMethods = {"flow":["extract","from","process","read"],"groupeddataframe":["aggregate"],"dataframe":["aggregate","batchBy","batchSize","cache","collect","collectRefs","constrain","crossJoin","drop","dropDuplicates","duplicateRow","filter","filters","join","joinEach","limit","load","match","offset","onError","repartition","rename","renameEach","rows","select","sortBy","transform","until","void","with","withEntries","withEntry","write"]}; // DataFrame methods const dataframeMethods = [ @@ -278,42 +278,6 @@ const dataframeMethods = [ }, apply: snippet("filter(" + "$" + "{" + "1:function" + "}" + ")"), boost: 10 - }, { - label: "extractor", - type: "method", - detail: "Flow\\\\ETL\\\\DataFrame", - info: () => { - const div = document.createElement("div") - div.innerHTML = ` -
- extractor() : Extractor -
-
- @internal engine paths only - a build-time scan has to know whether the source can be read twice -
- ` - return div - }, - apply: snippet("extractor()"), - boost: 10 - }, { - label: "filterPartitions", - type: "method", - detail: "Flow\\\\ETL\\\\DataFrame", - info: () => { - const div = document.createElement("div") - div.innerHTML = ` -
- filterPartitions(Filter|ScalarFunction $filter) : self -
-
- @lazy
@throws RuntimeException -
- ` - return div - }, - apply: snippet("filterPartitions(" + "$" + "{" + "1:filter" + "}" + ")"), - boost: 10 }, { label: "filters", type: "method", @@ -502,7 +466,7 @@ const dataframeMethods = [ const div = document.createElement("div") div.innerHTML = `
- load(Loader $loader) : self + load(Loader|Sink $sink) : self
@lazy @@ -510,7 +474,7 @@ const dataframeMethods = [ ` return div }, - apply: snippet("load(" + "$" + "{" + "1:loader" + "}" + ")"), + apply: snippet("load(" + "$" + "{" + "1:sink" + "}" + ")"), boost: 10 }, { label: "match", @@ -603,40 +567,40 @@ const dataframeMethods = [ apply: snippet("printRows(" + "$" + "{" + "1:limit" + "}" + ", " + "$" + "{" + "2:truncate" + "}" + ", " + "$" + "{" + "3:formatter" + "}" + ")"), boost: 10 }, { - label: "printSchema", + label: "explain", type: "method", detail: "Flow\\\\ETL\\\\DataFrame", info: () => { const div = document.createElement("div") div.innerHTML = `
- printSchema(SchemaFormatter $formatter = Flow\\ETL\\Row\\Formatter\\ASCIISchemaFormatter::...) : void + explain() : Plan
- @lazy
@throws SchemaNotDerivableException + This frame\'s plan, frozen: later verbs on this frame do not reach it. toString() prints it as a tree.
Answers from the plan without reading a row.
` return div }, - apply: snippet("printSchema(" + "$" + "{" + "1:formatter" + "}" + ")"), + apply: snippet("explain()"), boost: 10 }, { - label: "registerGroupBy", + label: "printSchema", type: "method", detail: "Flow\\\\ETL\\\\DataFrame", info: () => { const div = document.createElement("div") div.innerHTML = `
- registerGroupBy(GroupBy $groupBy, GroupByAlgorithmBuilder $algorithm = null) : void + printSchema(SchemaFormatter $formatter = Flow\\ETL\\Row\\Formatter\\ASCIISchemaFormatter::...) : void
- @internal engine paths only - GroupedDataFrame builds its steps against this frame\'s plan + @lazy
@throws SchemaNotDerivableException
` return div }, - apply: snippet("registerGroupBy(" + "$" + "{" + "1:groupBy" + "}" + ", " + "$" + "{" + "2:algorithm" + "}" + ")"), + apply: snippet("printSchema(" + "$" + "{" + "1:formatter" + "}" + ")"), boost: 10 }, { label: "rename", @@ -877,7 +841,7 @@ const dataframeMethods = [ const div = document.createElement("div") div.innerHTML = `
- write(Loader $loader) : self + write(Loader|Sink $sink) : self
@lazy
Alias for ETL::load function. @@ -885,7 +849,7 @@ const dataframeMethods = [ ` return div }, - apply: snippet("write(" + "$" + "{" + "1:loader" + "}" + ")"), + apply: snippet("write(" + "$" + "{" + "1:sink" + "}" + ")"), boost: 10 } ] diff --git a/web/landing/assets/codemirror/completions/dsl.js b/web/landing/assets/codemirror/completions/dsl.js index 6b91614c8c..d80171d4e7 100644 --- a/web/landing/assets/codemirror/completions/dsl.js +++ b/web/landing/assets/codemirror/completions/dsl.js @@ -1,7 +1,7 @@ /** * CodeMirror Completer for Flow PHP DSL Functions * - * Total functions: 826 + * Total functions: 814 * * This completer provides autocompletion for all Flow PHP DSL functions: * - Extractors (flow-extractors) @@ -3079,10 +3079,10 @@ const dslFunctions = [ const div = document.createElement("div") div.innerHTML = `
- declare_cursor(string $cursorName, SelectFinalStep|Sql|string $query) : DeclareCursorOptionsStep + declare_cursor(string $cursorName, SelectFinalStep|Sql|ParsedQuery|string $query) : DeclareCursorOptionsStep
- Declare a server-side cursor for a query.
Cursors must be declared within a transaction and provide memory-efficient
iteration over large result sets via FETCH commands.
Example with query builder:
declare_cursor(\'my_cursor\', select(star())->from(table(\'users\')))->noScroll()
Produces: DECLARE my_cursor NO SCROLL CURSOR FOR SELECT * FROM users
Example with raw SQL:
declare_cursor(\'my_cursor\', \'SELECT * FROM users WHERE active = true\')->withHold()
Produces: DECLARE my_cursor NO SCROLL CURSOR WITH HOLD FOR SELECT * FROM users WHERE active = true
@param string $cursorName Unique cursor name
@param SelectFinalStep|Sql|string $query Query to iterate over + Declare a server-side cursor for a query.
Cursors must be declared within a transaction and provide memory-efficient
iteration over large result sets via FETCH commands.
Example with query builder:
declare_cursor(\'my_cursor\', select(star())->from(table(\'users\')))->noScroll()
Produces: DECLARE my_cursor NO SCROLL CURSOR FOR SELECT * FROM users
Example with raw SQL:
declare_cursor(\'my_cursor\', \'SELECT * FROM users WHERE active = true\')->withHold()
Produces: DECLARE my_cursor NO SCROLL CURSOR WITH HOLD FOR SELECT * FROM users WHERE active = true
@param string $cursorName Unique cursor name
@param ParsedQuery|SelectFinalStep|Sql|string $query Query to iterate over
` return div @@ -3125,69 +3125,6 @@ const dslFunctions = [ }, apply: snippet("\\Flow\\ETL\\DSL\\definition_from_type(" + "$" + "{" + "1:ref" + "}" + ", " + "$" + "{" + "2:type" + "}" + ", " + "$" + "{" + "3:nullable" + "}" + ", " + "$" + "{" + "4:metadata" + "}" + ")"), boost: 10 - }, { - label: "delay_exponential", - type: "function", - detail: "flow\u002Ddsl\u002Dhelpers", - info: () => { - const div = document.createElement("div") - div.innerHTML = ` -
- delay_exponential(Duration $base, int $multiplier = 2, Duration $max_delay = null) : Exponential -
- ` - return div - }, - apply: snippet("\\Flow\\ETL\\DSL\\delay_exponential(" + "$" + "{" + "1:base" + "}" + ", " + "$" + "{" + "2:multiplier" + "}" + ", " + "$" + "{" + "3:max_delay" + "}" + ")"), - boost: 10 - }, { - label: "delay_fixed", - type: "function", - detail: "flow\u002Ddsl\u002Dhelpers", - info: () => { - const div = document.createElement("div") - div.innerHTML = ` -
- delay_fixed(Duration $delay) : Fixed -
- ` - return div - }, - apply: snippet("\\Flow\\ETL\\DSL\\delay_fixed(" + "$" + "{" + "1:delay" + "}" + ")"), - boost: 10 - }, { - label: "delay_jitter", - type: "function", - detail: "flow\u002Ddsl\u002Dhelpers", - info: () => { - const div = document.createElement("div") - div.innerHTML = ` -
- delay_jitter(DelayFactory $delay, float $jitter_factor) : Jitter -
-
- @param float $jitter_factor a value between 0 and 1 representing the maximum percentage of jitter to apply -
- ` - return div - }, - apply: snippet("\\Flow\\ETL\\DSL\\delay_jitter(" + "$" + "{" + "1:delay" + "}" + ", " + "$" + "{" + "2:jitter_factor" + "}" + ")"), - boost: 10 - }, { - label: "delay_linear", - type: "function", - detail: "flow\u002Ddsl\u002Dhelpers", - info: () => { - const div = document.createElement("div") - div.innerHTML = ` -
- delay_linear(Duration $delay, Duration $increment) : Linear -
- ` - return div - }, - apply: snippet("\\Flow\\ETL\\DSL\\delay_linear(" + "$" + "{" + "1:delay" + "}" + ", " + "$" + "{" + "2:increment" + "}" + ")"), - boost: 10 }, { label: "delete", type: "function", @@ -3428,66 +3365,6 @@ const dslFunctions = [ }, apply: snippet("\\Flow\\PostgreSql\\DSL\\drop_owned(" + "$" + "{" + "1:roles" + "}" + ")"), boost: 10 - }, { - label: "duration_microseconds", - type: "function", - detail: "flow\u002Ddsl\u002Dhelpers", - info: () => { - const div = document.createElement("div") - div.innerHTML = ` -
- duration_microseconds(int $microseconds) : Duration -
- ` - return div - }, - apply: snippet("\\Flow\\ETL\\DSL\\duration_microseconds(" + "$" + "{" + "1:microseconds" + "}" + ")"), - boost: 10 - }, { - label: "duration_milliseconds", - type: "function", - detail: "flow\u002Ddsl\u002Dhelpers", - info: () => { - const div = document.createElement("div") - div.innerHTML = ` -
- duration_milliseconds(int $milliseconds) : Duration -
- ` - return div - }, - apply: snippet("\\Flow\\ETL\\DSL\\duration_milliseconds(" + "$" + "{" + "1:milliseconds" + "}" + ")"), - boost: 10 - }, { - label: "duration_minutes", - type: "function", - detail: "flow\u002Ddsl\u002Dhelpers", - info: () => { - const div = document.createElement("div") - div.innerHTML = ` -
- duration_minutes(int $minutes) : Duration -
- ` - return div - }, - apply: snippet("\\Flow\\ETL\\DSL\\duration_minutes(" + "$" + "{" + "1:minutes" + "}" + ")"), - boost: 10 - }, { - label: "duration_seconds", - type: "function", - detail: "flow\u002Ddsl\u002Dhelpers", - info: () => { - const div = document.createElement("div") - div.innerHTML = ` -
- duration_seconds(int $seconds) : Duration -
- ` - return div - }, - apply: snippet("\\Flow\\ETL\\DSL\\duration_seconds(" + "$" + "{" + "1:seconds" + "}" + ")"), - boost: 10 }, { label: "empty_generator", type: "function", @@ -8495,57 +8372,6 @@ const dslFunctions = [ }, apply: snippet("\\Flow\\Telemetry\\DSL\\resource_detector(" + "$" + "{" + "1:detectors" + "}" + ")"), boost: 10 - }, { - label: "retry_any_throwable", - type: "function", - detail: "flow\u002Ddsl\u002Dhelpers", - info: () => { - const div = document.createElement("div") - div.innerHTML = ` -
- retry_any_throwable(int $limit) : AnyThrowable -
- ` - return div - }, - apply: snippet("\\Flow\\ETL\\DSL\\retry_any_throwable(" + "$" + "{" + "1:limit" + "}" + ")"), - boost: 10 - }, { - label: "retry_any_throwable_except", - type: "function", - detail: "flow\u002Ddsl\u002Dhelpers", - info: () => { - const div = document.createElement("div") - div.innerHTML = ` -
- retry_any_throwable_except(array $exception_types, int $limit) : AnyThrowableExcept -
-
- @param array> $exception_types -
- ` - return div - }, - apply: snippet("\\Flow\\ETL\\DSL\\retry_any_throwable_except(" + "$" + "{" + "1:exception_types" + "}" + ", " + "$" + "{" + "2:limit" + "}" + ")"), - boost: 10 - }, { - label: "retry_on_exception_types", - type: "function", - detail: "flow\u002Ddsl\u002Dhelpers", - info: () => { - const div = document.createElement("div") - div.innerHTML = ` -
- retry_on_exception_types(array $exception_types, int $limit) : OnExceptionTypes -
-
- @param array> $exception_types -
- ` - return div - }, - apply: snippet("\\Flow\\ETL\\DSL\\retry_on_exception_types(" + "$" + "{" + "1:exception_types" + "}" + ", " + "$" + "{" + "2:limit" + "}" + ")"), - boost: 10 }, { label: "returning", type: "function", @@ -11194,12 +11020,12 @@ const dslFunctions = [ const div = document.createElement("div") div.innerHTML = `
- to_branch(ScalarFunction $condition, Loader $loader, Transformation $transformation = null) : BranchingLoader + to_branch(ScalarFunction $condition, Loader|Sink $sink) : Branched
` return div }, - apply: snippet("\\Flow\\ETL\\DSL\\to_branch(" + "$" + "{" + "1:condition" + "}" + ", " + "$" + "{" + "2:loader" + "}" + ", " + "$" + "{" + "3:transformation" + "}" + ")"), + apply: snippet("\\Flow\\ETL\\DSL\\to_branch(" + "$" + "{" + "1:condition" + "}" + ", " + "$" + "{" + "2:sink" + "}" + ")"), boost: 10 }, { label: "to_chartjs", @@ -11380,15 +11206,15 @@ const dslFunctions = [ const div = document.createElement("div") div.innerHTML = `
- to_dbal_transaction(Connection|array $connection, Loader $loaders) : TransactionalDbalLoader + to_dbal_transaction(Connection|array $connection, Loader|Sink $sinks) : Transactional
- Execute multiple loaders within database transactions.
Each batch of rows is loaded in its own transaction; rows a wrapped Transformation delivers when
the loader is closed (blocking operations drain there) are committed in one final transaction.
If any loader fails, the open transaction is rolled back.
Atomicity requires every wrapped loader to use the same connection as the wrapper: pass one live
Connection to both - a wrapped loader built from array params opens its own connection and
escapes the transaction.
@param array|Connection $connection
@param Loader ...$loaders - Loaders to execute within the transaction
@throws InvalidArgumentException + Write every sink within database transactions.
Each batch of rows is written in its own transaction; rows a sink\'s Transformation delivers when
the run ends (blocking operations drain there) are committed in one final transaction.
If any sink fails, the open transaction is rolled back.
A plain Loader child is a bare sink root; a to_transformation(...) child delivers inside the same
transaction. Every child\'s loader must use the same connection as the transaction: pass one live
Connection to both - a loader built from array params opens its own connection and escapes the
transaction.
@param array|Connection $connection
@param Loader|Sink ...$sinks - sinks written within the transaction
@throws InvalidArgumentException
` return div }, - apply: snippet("\\Flow\\ETL\\Adapter\\Doctrine\\to_dbal_transaction(" + "$" + "{" + "1:connection" + "}" + ", " + "$" + "{" + "2:loaders" + "}" + ")"), + apply: snippet("\\Flow\\ETL\\Adapter\\Doctrine\\to_dbal_transaction(" + "$" + "{" + "1:connection" + "}" + ", " + "$" + "{" + "2:sinks" + "}" + ")"), boost: 10 }, { label: "to_excel", @@ -11548,15 +11374,15 @@ const dslFunctions = [ const div = document.createElement("div") div.innerHTML = `
- to_pgsql_transaction(Client $client, Loader $loaders) : TransactionalPostgreSqlLoader + to_pgsql_transaction(Client $client, Loader|Sink $sinks) : Transactional
- Execute multiple loaders within PostgreSQL transactions.
Each batch of rows is loaded in its own transaction; rows a wrapped Transformation delivers when
the loader is closed (blocking operations drain there) are committed in one final transaction.
If any loader fails, the open transaction is rolled back.
All wrapped loaders must use the same Client instance as the wrapper - a loader holding its own
Client escapes the transaction. + Write every sink within PostgreSQL transactions.
Each batch of rows is written in its own transaction; rows a sink\'s Transformation delivers when
the run ends (blocking operations drain there) are committed in one final transaction.
If any sink fails, the open transaction is rolled back.
Every sink\'s loader must use the same Client instance as the transaction - a loader holding its own
Client escapes it.
` return div }, - apply: snippet("\\Flow\\ETL\\Adapter\\PostgreSql\\to_pgsql_transaction(" + "$" + "{" + "1:client" + "}" + ", " + "$" + "{" + "2:loaders" + "}" + ")"), + apply: snippet("\\Flow\\ETL\\Adapter\\PostgreSql\\to_pgsql_transaction(" + "$" + "{" + "1:client" + "}" + ", " + "$" + "{" + "2:sinks" + "}" + ")"), boost: 10 }, { label: "to_seal_delete", @@ -11689,12 +11515,12 @@ const dslFunctions = [ const div = document.createElement("div") div.innerHTML = `
- to_transformation(Transformer|Transformation $transformer, Loader $loader) : TransformerLoader + to_transformation(Transformer|Transformation $transformer, Loader|Sink $sink) : Transformed
` return div }, - apply: snippet("\\Flow\\ETL\\DSL\\to_transformation(" + "$" + "{" + "1:transformer" + "}" + ", " + "$" + "{" + "2:loader" + "}" + ")"), + apply: snippet("\\Flow\\ETL\\DSL\\to_transformation(" + "$" + "{" + "1:transformer" + "}" + ", " + "$" + "{" + "2:sink" + "}" + ")"), boost: 10 }, { label: "to_xml", @@ -13895,21 +13721,6 @@ const dslFunctions = [ }, apply: snippet("\\Flow\\ETL\\DSL\\with_entry(" + "$" + "{" + "1:name" + "}" + ", " + "$" + "{" + "2:function" + "}" + ")"), boost: 10 - }, { - label: "write_with_retries", - type: "function", - detail: "flow\u002Ddsl\u002Dloaders", - info: () => { - const div = document.createElement("div") - div.innerHTML = ` -
- write_with_retries(Loader $loader, RetryStrategy $retry_strategy = Flow\\ETL\\Retry\\RetryStrategy\\AnyThrowableExcept::..., DelayFactory $delay_factory = Flow\\ETL\\Retry\\DelayFactory\\Fixed\\FixedMilliseconds::..., Sleep $sleep = Flow\\ETL\\Time\\SystemSleep::...) : RetryLoader -
- ` - return div - }, - apply: snippet("\\Flow\\ETL\\DSL\\write_with_retries(" + "$" + "{" + "1:loader" + "}" + ", " + "$" + "{" + "2:retry_strategy" + "}" + ", " + "$" + "{" + "3:delay_factory" + "}" + ", " + "$" + "{" + "4:sleep" + "}" + ")"), - boost: 10 }, { label: "xml_element_schema", type: "function", diff --git a/web/landing/assets/codemirror/completions/scalarfunctionchain.js b/web/landing/assets/codemirror/completions/scalarfunctionchain.js index 3ab47e08ae..53f109219a 100644 --- a/web/landing/assets/codemirror/completions/scalarfunctionchain.js +++ b/web/landing/assets/codemirror/completions/scalarfunctionchain.js @@ -1,8 +1,8 @@ /** * CodeMirror Completer for Flow PHP ScalarFunctionChain Methods * - * ScalarFunctionChain methods: 127 - * ScalarFunctionChain-returning functions: 55 + * ScalarFunctionChain methods: 128 + * ScalarFunctionChain-returning functions: 59 * * This completer triggers after ScalarFunctionChain-returning DSL functions */ @@ -11,7 +11,7 @@ import { CompletionContext, snippet } from "@codemirror/autocomplete" // DSL functions that return ScalarFunctionChain (have scalar_function_chain: true) const scalarFunctionChainFunctions = [ - "col", "entry", "ref", "optional", "lit", "exists", "when", "array_get", "array_get_collection", "array_get_collection_first", "array_exists", "array_merge", "array_merge_collection", "array_key_rename", "array_keys_style_convert", "array_sort", "array_reverse", "now", "between", "to_date_time", "to_date", "date_time_format", "split", "combine", "concat", "concat_ws", "hash", "cast", "coalesce", "enum_name", "enum_value", "call", "array_unpack", "array_expand", "size", "uuid_v4", "uuid_v7", "ulid", "lower", "capitalize", "upper", "not", "to_timezone", "regex_replace", "regex_match_all", "regex_match", "regex", "regex_all", "sprintf", "sanitize", "round", "number_format", "greatest", "least", "match_cases"] + "col", "entry", "ref", "structure", "optional", "lit", "exists", "when", "structure_get", "array_get", "structure_get_collection", "array_get_collection", "structure_get_collection_first", "array_get_collection_first", "array_exists", "array_merge", "array_merge_collection", "array_key_rename", "array_keys_style_convert", "array_sort", "array_reverse", "now", "between", "to_date_time", "to_date", "date_time_format", "split", "combine", "concat", "concat_ws", "hash", "cast", "coalesce", "enum_name", "enum_value", "call", "array_unpack", "array_expand", "size", "uuid_v4", "uuid_v7", "ulid", "lower", "capitalize", "upper", "not", "to_timezone", "regex_replace", "regex_match_all", "regex_match", "regex", "regex_all", "sprintf", "sanitize", "round", "number_format", "greatest", "least", "match_cases"] // ScalarFunctionChain methods const scalarFunctionChainMethods = [ @@ -728,7 +728,7 @@ const scalarFunctionChainMethods = [ expand(ArrayExpand $expand = Flow\\ETL\\Function\\ArrayExpand\\ArrayExpand::...) : ArrayExpand
- Expands each value into entry, if there are more than one value, multiple rows will be created.
Array keys are ignored, only values are used to create new rows.
Before:
+--+-------------------+
|id| array|
+--+-------------------+
| 1|{\"a\":1,\"b\":2,\"c\":3}|
+--+-------------------+
After:
+--+--------+
|id|expanded|
+--+--------+
| 1| 1|
| 1| 2|
| 1| 3|
+--+--------+ + Expands each value into entry, if there are more than one value, multiple rows will be created.
Array keys are ignored, only values are used to create new rows.
Nested in another function (structure(), concat(), ...) it still gives one row per element. Several
expands in one expression are zipped to the longest list; a shorter one gives null, so its element
type becomes nullable. It is refused inside another array_expand() and in filter(), until(),
duplicateRow(), aggregate(), over() and onEach().
Before:
+--+-------------------+
|id| array|
+--+-------------------+
| 1|{\"a\":1,\"b\":2,\"c\":3}|
+--+-------------------+
After:
+--+--------+
|id|expanded|
+--+--------+
| 1| 1|
| 1| 2|
| 1| 3|
+--+--------+
` return div @@ -2007,6 +2007,21 @@ const scalarFunctionChainMethods = [ }, apply: snippet("resolved()"), boost: 10 + }, { + label: "deterministic", + type: "method", + detail: "Flow\\\\ETL\\\\Function\\\\ScalarFunctionChain", + info: () => { + const div = document.createElement("div") + div.innerHTML = ` +
+ deterministic() : bool +
+ ` + return div + }, + apply: snippet("deterministic()"), + boost: 10 } ] /** diff --git a/web/landing/assets/wasm/tools/flow.phar b/web/landing/assets/wasm/tools/flow.phar index d43ccf50156378d5d2aa20152675178053aaeaf5..1db86033b8e4ca8fa3e06d8c7259550be87d0997 100755 GIT binary patch delta 436631 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

=yvlrD2{2G$_p3*s2 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

(bqqrdiOD5U6Ob6#_|ISsa z)KDQHOc^~?Zr|S>we9LS;$am#hKX^-gfq_`i{K)M=dV)29ExWQeDT{yCT@zKi;f;G zc)wD%cI%i=;^rRp3-l%CoEv+)TG8tt1Wkuu#Q+7#N$0DU9;rpU*b>>MRivym64o6X zdIknK0}fv!9`VB#5D#wlR2lB(cB?47H?@zwJRE-4!gZ7S%yY3&E_OxRsn0oj2!jE2 z-PX=qA4@d$QqS*4X7C!%`6ce}$o$!fd$q3Sbh@Sc!?Wdyc5V8P_Q7k2X??oyib%_( zPXMTis_gGiz}jKZ@*$nrGthk%f5_RQN{Ja21!OAQQR%l@?@*Uz7fT;!q~~vb;!~=b zqFM!s$LZQoYz`$KDHX@FJZug^b{E{Vw-%P5^P3XOd1RaUIMKc#F( zBoBEWw=0iV_&@UqZOkby38AFQ=o_ny6vaxee)xH=5&ZEw+YfnMa>%Uj$`X=UgsnPw z7;3qcfZ93igEwwExZ(TAG|Pkjv;#*@35@D>G3_wrHk2>td)r5h?{eVGMbT^w4=@wl zVC_1KIAl8tyg?3^x_s9xe=WI)-4kVIM|!Xl)^a}X#>7zbASCt1K= zj*79jZQ@@VB$)lq{QxChLtvkqttyBY@~D2Q7^L!U#)TpCt+Al!-?z0|iiqMed(bn( zCW|Y)$&di9tEKm2SnHAur*RuN4M3$eR-+5HBfmM@A+ZB%C0S9uTlPqpW8EQQ|G`UzIROVL0WY&s7R8 zsov5KB^7f{MAn2?>f&OS`9a!NM9M7RT-zHnNi{D;Aa=QeAVa-4fjqgwUw{A@Yu6^k zR{i<1>o&F{$qSiy0-32`o-}Q7i!Xu~SEeU}e&^M;+n%(_Mru}R#bvb?+@PAuAc44OO3DDbiyYSR@L9WxR>dX$Jzd zU=+@{T1|J`=G+*_2{MZxzrv>v-#@aPGgHFGFjxTEnY9MwjHm3+)y7SE=dEE#b_zF} zyOyM+2h1p`*hJ0teB^;cHeWqWqS3&Q3mjtY*;qL{A zl;-3Q!Psa5VQJ#n*L;2m#w*Z+`&nMXiF%H6{4|ZuTMe28Is^z#jb9Q_6Lv=9*BnZ+ zBmnVrFYqkJzy5t8;z%d^n_0Cg$`xtz4^}&Y1%;Jcz;pp_KDj>29;WQfX|jS{C*L9B z2l1@o9m!UbY2)gO3=bc!qdfEHSla{;(Bz5h&)Qk;ek_*K^B4EHZlYT*rUI-ouuJc7 zWJS*`D4Wl9Oh0Lm))9U>A_8+H0Jw{Zy?=X>pT*F_jWp2wwv0Os%Z_Ipryn-e{{BYz z$|Y)vS)|Cp4*KoEx3_Ya+tq>Vx#hAeE55(FY4T=#z$-Hp8Fss$(3~pgH}%t%8yr~1 zaI7y;^!?B6?tt~)N|lSbJCzz$T@gvO-Ekbhx~tr2Y~l?d(Z?;6ALPdz-b?uHzoOB7 zdB5HHh_R?PZNJBX+I6q~;?E)nrs7?wY^GuMSL|#Ktzb=9aD=o-B!eUFQYNzPbNiWh zSWX6b{c4L1BXIlr+V`6CUpFcsEN?l|Gm&|;bdEXvL5%>W$_@Z!=f&I0Tm_Bp$Si+< z{P=uhhbKk8z?XuRlA}N^|6r{b;Zf-6=;`(1@bzSmFZ!RH=VDXGlk(MZ_&cJNCD% zV|$!^T}}N)(O$I}N15jm?>VLQJa}Hq%Mu=JwUby|*t$hqr4vddz1yRmfT9^lWNAcI z;z#9+I5kCKc_u2W{+R%}QMoUka*TsWk>v{zz()3gU*=VBsnt`3|Fthy*(vK4S5?)` zk4Wn#w#7pnJXX3lJ?Ih}oyi~rq4%aP;IffdyF!k-QW2^8N-Q`Sl@rKCAz1quCo+J} z!}CPAkog)UV-o{AxuosaFn0OK@=D-UBjL9 z-0QV>ax_||L4kc>d|+KfT~%-u2r9>DTQSK+u$Ea$(jfp6S5;@K$jgp_uB{rH@^%Mo z3QMLC@-@Li=j-|@tAmH5MbT@DWAkTA7{XAD3t(l?$WaiK zNDAN!0^k5lB~>m~o8Y}eLFKs_;+#GkItx=s>{`urTl7y{PLj>^5o}b`-PpxtDg(f<{O((DK0(t%U1)&6ec^PRF@f!$n&!-|v7m&b6iCeK7; z|M!QZ;1^svU zELov&*o+BFaJf^A>}3K+7GvH+x4Ig$N`I#i&-0x{=Y1CYk&v4}uBgIkWj3oPbjGo% zE$qHTZ$6m^&c?!pJi(;oU*U5TQcFHdaAu5t{yhtBY^Ls~3ew9CUy$dD_!#OE7ulm> z0lsoT88sAI2ec(BIBIVL{rzdi9La>9&t~5rd>t6J2*h*Gs^CfV)FP+q-5bAOk%AzE z4illBAws1fCL??b(3TJB24{Z)vfNs6-+n2PGPq}{N)mL3>dc8Xt#Nn#HgtR^;R%i( zPswnx^_wJ!j_bAS`?374J)z~#az%wLmId3J@#ipXfdGLKKzJ>2rmvfky^_jQu()mS zul(>D-7EE`7k`8t`!+n|`_#MYPuS!KBbX*}Tz*yxv76F|U4DJmP*myKmI!kB>`_9t zEp1Y{?M1=;t8*<6Nf85~*wa;|u~d(RR`Mnd1Nx5EUD1}FL_@sGpDhb=5I82h2N99EZ2>>ex zDGpo7^b~vYSP?FlOfHrV znHbdIp~z?{>?VTrl}4~sij0|rtIU#?1W&e(Qi&) zz~BV}*q@30JowdRVoQv~|29-B?99xIL?kAt?35r72}SaTE;3oWyJz{&eLPQ9F;u{* zD0)hCoVWTozYlfG*2ylNieQq<NQ+J^NB%+qY~&@s_s^>&jH^~DHmcaU5t*eI8#z+w zY4+up>KtpMw)xE}F(Mp@@5?oB9}qVr+qq$(AYq)J6jfn{qww z1bJxh>S*}hMeZ__siXVDBl%^y7F3OYGBug3ycpIKLo0Ce$sJfh8=W&=-jgmo1M9*^T zS~Vtg=?2T7tt`i!D|0Weo7VvxvCZ&Sz&~07#`>{|e+do2gAb3oe!?Tonw(V(0Oler zn#3l_-Bi(uy;_2%0h%zXSOIPa(0K?wPRU(r@-4$A`-6Z$!LnncP2{)>1l}A0#!&)zlvCjIT0&R~a5C2L+LI=9Wk>fqw%soaASkzJkJASfG zAd;3Vr>IOXV&iA!tmb_wOlE-d2L)ZU8@cE~lgD$t<&~ck-qE0z z38lPALc_^F!FQLvL1D5}hyUeg^`*R5_HYFkM`r2nNf{Of+-0=PxQ39(h)I90Oz+^; z`U?7Ek?NZw1ymL97vI0SIHr<1Cxe0g_W2J9Cu=mv>71xXtlK2wZXkz}9V)T5s*U{7 z`4^p2!H(K65WVLs=8!`o0aC9}sOWZ)R%)RNS?!@zkuei+mDrIzS&G{I_u5GyA>E=? zeTb47&wFp)Ox}Me4u$9KkY|5PV_--NP6?d~G}CwC#PcM}(G-j$EHZW6+{d3cv1Zbw zO6REUh0=6VA5|%LYr@m8)+Vw3&QnjbJ{z2H^LE)yTLIjLJ!Zj|*Kqu_|^1z-#i)Tg%tz7UmrdDB{F1MNBkd~5@P!f`aD`_WIa;gR=_rEWd zFdB{gYIb2&TNAkB(?OWw%;CbcLp2@?DJW>`CRNGH>)cx*cR_6x_(B#Xg=4r(zelN& zN-aU+vAq&hItESgaJGNfcE{2(i!fKuSjlLGhPTDg*~!4o(|Tr~1L!Oe_`H6xBHfj~ zB~5lXqw`t@q5U|+GRLwerU`eo?ywn&JN9-5tHLw2G1FSga8`di%-d~Fu3tmcm ztEV+gXJ?VzPMCsl@c*!@$M_nzvf&@d-}^2!%hpu2j=lhA#19Z$eqHb}>`(437A}~` zTK_CaPXRds8}D#8+xz1E0i9G$Z`wc*z57?p0V%cwhhCH7h@v2+Y6AjCIg|=5%Ye69 zcCFoU35xRHyX${1i~~|sAFTDv+nG0SX8iR&OS2%@AeYQwXvqjpD>`OqhhL(*AW&?N zHe(!NBK2YUko;IChAF$%W{<`Ja@%r!)4AF#2(!C$`&g^3*ew&3xJNR_(`iI5ig`Ipk5+IdXOgK7#vfcp!dL2ezH6b1*MfhixMv;jTpzkDF5=Dv@SY?! z`oPu_ogQ1Em;@)MwJf31r@uL`X_LevO(7}Ll3J{|7v7E zG-?OE%;0}kygI5kHzhcNxA)78*FtT=Qd{T=mE{!OLNh$YmA59JLCTE+g@+R)>`^Lg zA3|?EHMBGj;*v@f4Px$F5SBUmP`Qih2eB>hM3EbGpXdr%syh^(8q$Z>kU@`^2UmoL zbokfaK}_}3hmKhjmia6TVuo;277$g9_K!oiVikY!4BA|h6S|->i2u0y$7P*Wea;+4 zO}UjCt)QQ#HP(Jo8)ALtO4ntVMBcSasZA|0KnV-`~zz$u`WWZTEC;K;^PFOh+vE z0BnDTJ(+l?7P;Y4+ELwAhPaZ|5gB>n{T060FZL8{lltDr>?w@jy#n;Bvb-AjiMAKLlTK zrfx6mvZPC1a}Sm3*X2WVY|CCIW;iMYoGzY`b7jT${%K zXd4W!S-jOc{rURhwqPqRIIb^NV1O;bm*`a+>i)iS2q{p)g8g075(q~iot6ZuTx;^V zu1cO$!ysQlDhS_HSe3$P5-g8?j|lwUy?JB*lQ-nU168C1XWzH!I&Jpe+5eT|4fWxpcX;HQ zXy`lAbh17qSD@I-Uvg1oW1<U@gu0<^RCuK**3Jj+QlThUB%drlSN57QAMm$zIO%)cBJm8^en?fTBIu zhAP7f7xIuB>!j0ad+{Clu%Y*I%I}3#4El?fTg~;6Ex9S625cZS^tif89OR`SXJ>;{ zId5FgX5%1dR#=>{=Dm~CX7GPyIfaKetd^U*XjjWx<+k>5tG5S%V>DkAuYi^%fChy` zR#G=^p4yy@qwwL6uSk|*4Yh}D*2QNG$)WnAlqI9W%Aa(#fG(~8rddjC+F5jY9p)C1%!ftr|3D&fWg zJ5U`CGz7ld-aWCx;!<;9)sc>)3c_DkMSZZvI$n&TTVNJ>F|0xJ;fPyLj0RY zqj87_SyE#{>tr`!Q?7q$igBvGhEdLC`acp|9PClhP!DaV?<^cE zWhKiJ1B+)r79i9^YlSO7+-YE^kYJ~f@W3htl?u)OxMm2AZZd#cEc6S>|1S^{dlfW$ zk`|jZox40p9upv zOc?#Lz#!(az`kvJ9iN{h&cp2iIw3a$a}w9Mqoecre72a+&M&XOUd{eGpMSf$TztFy z{$swFUH!ba`R|?c!-m>h?A4EXPi}8q=*zu}v8tJR4%|(mi+paYJ8LgI04#C&>=nMR zl$TxXKuDzDpaOqb4|IpKRe0a9q?)8Ie#!Z~9mxE|5Ra?wJ)XXLgM*_DZ2s4{Zqa*q zN6!$L61qho%#TIMVR z6kDg=)}XX3is5N};x&TNVCd(TC9`tka)1A|;dy%w=SA{}i#{6x1YcaFr=MYf zc1(DKpbZJ_b-;mR3h<7OgoKl61I>;C_DoG*O?Wy!5AMMSAqYH=(#Y!XbTP8p`(gyF zSWd6vdq3V4424M^+M^F*aT$5DA^~ZTYV1;eMu>mEYlbss_yMP746dt#FBQXY4ILL; zk(n}$8fZ%|JHfTj!O*b}PJ}_eJgv{z^XMO?R^M;pI1qm4ub78OO)6-0uduMku3BBC z-L`_P?g1)f5<`3!?8tWLqEr9(8{0_;ChS(bk=hu~_?ww;emEaK7Fp5jr8LQjq@mK1 zC3=6Q4+T}@KcZ2u$H|VWf+Q5~bMd;oi@z*mNx0ewxuX&lO4Sm55+zUPniiwe{m+7L z*mfDyobITWhvRCh(d4?+RC!14z9+QMOz`Cc-;Dqv?0;NoM%Q zzZu0~7~h^tecSUSqdVelo`ii#vb08M^}2uK7~xz?qUrYF4#k-iuVkImin>k76B7&& zDam1_D3M8qvJK-T2T4gPczys(k5W*fk|eXpExW*Wg<+Iy1+DGge?7qG_WIhs;Trzj z6X|Sy=;SV@{g-c}-UQIRRlqd~?Q&6?_U5PtuicyI@OKEy@h4o#- zzV(`ApfjchlcNhTK8?Ml?=!GwJPlp-K)`rW>Szc}Q+NRfqSUBi;H~QD=mTbtVwNF1 zcZR6On}biz@mQ@fm`Ixl6;{?F3$TBYVh7_1#wvUa&oj5GVM040_%?D7eG4!;Isewh zsieA;+@`Hz!^PIGO+-H=R@XHhns$W%ivW+dS{{PLEs$`d;&WX|2NPXSo-o26H7qe! z=9)-NQ|DOJN(X9tECtFXdF))l4B6kIM@CSwk9v!j7T|B>_@{Yxp1dp1=DB~p1p*vf z2q!;K)30EFOw+Ty^M!E@19<-H84~O&RcjAiEmY&-UwTlT1}Z1uv~)Z&I(T)frt(e- z?ouQz4wH;9-UlTxyc{>Bod$J2UNfSBaKLe!vr2}8AuSV{j&R6O*pcFrl?*x20*$$_ zX$tFuJ%goir9eowwbR@3D5QTCA^1Pk)pAaFsz7Bz>TV7ifbq$#&`?kX(Z{+h=_NL5 zt;L4qc+c3e+5ms7vNAmGy%^557@dK=dF|a%;HC=3(7IxWL$L{K54w9I{c%sYt|ECJ zx=P01os+5pTUhsNXYgQAo~`29^l^UwH2XS@AD$jp50B5^;??Zw@40Pf$4-KyREJUj*I}Q& z#izKIjSI*xJ`2@UuTHftQ=AjpWU=|!fq?qidl!ZGgyl#6g0o_GUjqScU*zupTkn6J zR!wi?HW0o0SIof&2~dBsC{Xm^R1UJc4Y0sADQqozhy#I^Mln&E6i8~_G|hi6DaxWm z*=evk*z$1Z&F35X*Xw#$&t@eSj7W@>mbB2hey&laKgCzG87F&GH7O8onK*2I%f4#SZr*5RP)_Pu3_YVe}uAn~y}{FF$*M)5>;I9LSbomw46iLQ}y# z@aOf{jl}Betz&WcpJVmbxf}5ZpLv3LUiyt&*hQiALyq`mYNE=90$xOt=j@c<>Q6xvC_rTnnp1!#_}tVT?p3fxj}#Ty^30gmUBlfT0ztS_*~;b zi1v}F8_9v=!Dr&E5;y`oZ*lAcc=cXR0*qWZw6UnI-o?_)N%}av`0EWj3igrsk63cN?1Fh7}Nw6Fv zUq^>w2G$?O!3EpBt{DqAtU=1BnKI^CXd-_aJ;DzuG}5-ub;y*7#sZ>=EKFs} zh9JzI7bl@yAY;HGYt9-i0;8T&WA~n26QoIl27{Ht!((u4n1RGhPtF^Kcw@m-yEMK*ZRLr@+_mwlX%r;ELChL@L@ zHllxv<#)mwRBdJ7!WvKKYfx&5s$se#)~Zc@IKK&4cRtTatKPH0J_&nC_d6_she>`X z{*WyeH(9pIv(?Sr`u2YH`%U)c{x1J=_s6#^U)}$?ZnJa~P?(EDM{)Awu=n4xF>YIy zGsur&6}mgDvl?7;P!Me=wg2M=^T`eRt`dLV63Tr2<`_nxtpg(;Ua{`;b@m^v7~4)8 zIrKeW;Z|vxR0(KbLxHjsq)OeeN`m%*pvcTPVYCxZH1-rw%fIjOb!?9(WKr_~iGA*O zpU-F8hi$Kyk+i@SNf@v4lrQ=7mavmQ2FJY~#T&x5I3?(+C?6M>^Y4p!g(+K=)rNmm z08lgM>d&&K*^HCzv44J1(pA1*%t=8ugjdhaw{s3G?`uw2fO7eik}c0my7)$a;3Ch? zt9890l-rBf5Wbh|JbfK{mOhXT{z_Ik&Bei_M#g;%UdbUa1jG_o6@Cuj*tW_kUx5ff5*Mf31 z9c@v**@{%4oFV79_p^uKbM)zx{Et4NFI!yU4Qed-d6Pep?DUt&S-M7jAW=OB(6la! zUp{ZtuT-dIh(9FfQBx{e0;~jc}jSEHRil1;oJ^+43w=ep*&XN2r!* zZw-uch{y7gY8SF0Vx@BF0|BtKgsy;Ac?EGYLfDB)w1sdN?k`>Hk2!yTxD;ki1}Mdp zmK->-6e>SKn4-x@M@l8jj>XJZDCrCDk4~*(A~rD;%yNaiQZ;b&5g*qJnub0}v^|b} zcx3?>-kc2E<9)*fPt)xguXPuvT5Fwuv6<;kF@i~)(7%5hXtBh66 z<_K~GlhJBSHHgw3OS+DNnNtcCtC;zQj^K_F8)n0{rs~GOaIF5)nD74t(3>1(k(&yj z`RIehA$xX)Vo?}G;8%s{2A~=3Y!qtZZlt^(CHq9ko1(*rvm<{(eou6?_zYvI+#G5n zca&FdBuK;r1Pa05A#z4T)KAqHD7ylrU2)}fAj`C@iHMV;fKp1Oo=A$GAu*P~VO2uK zEGdaq#wJX)W6;NsDjM2jsEml5hDCLN-U06IU06e5{6JrR;L4p$P+tuNTJmiHHy~m6 zfKyg*-Qhjc!mWQ76m6Rbl8H3#=u`~@QUfMm7_ma92#ih}|7h1(cf@mD-vXj}m?Q&- z3KmMuIIg(JN)>Up9{GJAkaxwpQJwYd@VM2_@a!71q@6Jt5 zpc!dx(DE8Hz1kcjx$5<}mX#t&s1Y`J8?mV`-#*s7D8+x^+iB0;Hl0t;C$p>T>0jr< zq|0xUzi;Nt>GeM|X1qxMb zdfCT>S2!;k`vH+a0xlT9xf}B8Z|iZPg>B9A{-CWVQX6ijPx;CJD`r~CRKm){MftSEte>yZyO%^`cbAG91eYs zb1buPgw5nY8BDc7pWS0Zb*R{x)eaRNz8pd&0WG{UnfiRa5!F(#bFOBme+&MGxC1TR zAz(G3mZKa{aKly#c6;Z97}QvTMUmFR;i3TdV&SZ?RLfB;)`7k4TZkn-Fa&nbYo_ zycfy*&VoD1?CqVy)KP<$h@GfbiCzx37cU1NjI9MTUZRP&aBGacsToINS>_8eL~DO| z7{33&-X9)BBGTyEdSHZxfyuI*$<`P~_Mqdz)J#`wN9{D!iC%H*8mfP`hF*uL%*N;l zm#7{-uw+zGA3DDU+|G0nu2PYbh`e_A4t6(f{akwEqu)HIy|kZeM zu~zNR7Oj=$el6KnBf0tt+k5vO)Ce@|vT^pZZ*9?*hF9Z*I?W<`(cJ~VOOH0BEywMv zoh@OXRCGdmDr>(f_#(1{#qvw6#D#Fac<)kDD;l^4SbwDboxq@n;EU@eoPi5zSk9e#>zyvBolFqg zhnAK*l^t{~%WIQf6t?HhZR_t$VR?r5Z1t1G5&)&&G7H=u6s!GD;*Q|()GnfJZ( zajZ{Hz}g4e-e6SYO+HAK1lLy|0VVOf z_wL@E&BbN1OB^Re9x;t>N?LGQ(PM(?=u`jPaU_c|O&CX*MQXpi3T~ExW-{F<9iujY zEUj&QR+$VJgvojH`&7w|*e(N%Fhi7!3aJY+8mIrBf(*lNp9_{VU?F88`-wN6j9! zL<%7-;uu31oobF7(QtXlAk-@H#db%hii4Kmu!w0T`)0?c%AT~!GY`I>@YvOH84ZV% zAn;d#Ke=7Z=KhySaDP3&U0vUPy$e?U{M!OX<5qjUzoVYt1r6@f*Q#Hq^gr4?%txU* zrk$5yo@_rJ72@A-jnajz{Pa6X>z8 z({8hU+HEDW<|;>s6Gr`av|20zE$D&l_nWMXMz6r2q!tadhfM&}K3eLaOWM3aP9!5! z%@iq%pU}8s>VKdfsd!T-b^z_Du+KQ*inRK6G|TVJ4Btd4iWIn_fwMj`Axd8yyUWrA zt5Db=x#fIr+C27zcLN`k{)7r2fxOPaTD5SD>E{M-+6fnb>x$blXo^ayI!DH2I5=y0 z(XY<$Fz)-3D36@1)Jw40{Du^LUWd={1+7$3tJ*LWet++;I1hbjp$dD|>2Q}TT-bEf zUiP3Ov8EcRNl8!VMEvhNX>E3*>n##7rm*`EP9Pg!H6e$Vr=!+mE|#s9C(@d)8XK$-?YJJFO0EopMSl z5t5~#Iol|i9)Zlsb0`V#Wwd|Z6ppg~pRK$=JGDe{!tX8p-Nf!wbVGf*tMPk1m3Z?T*~6>qrB#V52;UIKd}+~{L83T|cjSS|sWW70>iNJbBirfQVDlxx zHS#Dh%hF?s(qcb5Z83R~A_be4Fa@cp^RjJ?U4QR~0J`07EyHi+^Hc#|l)1P~2?CgZ zNb}BDs@EGuQMii2(PTEBhTlig+jO#en}7Uxk5=LI=d7$jl}b#Vj-DUcv~J&$>i_Kg0i9M&Z`(K! zz3W%Z0zOEAono)f+Pm4d0Sa`J!d9?{Brs@c921c#fgCk8TL1T*p=4Q-oorejY=4TJ zk2miPDgE(hu`Yrj#UxV}Lq}F8w4iN)Zt{C{5d=nU&=o2{xXSY9`;YPG``9YuR=M4v zWrNbSw*JmblgFoyGyb393N4xh zU)$@4+7u;4V`$D-KVxChYcqknhq@FQTskUlkgyF&RV7C)e;InkWP!o=pO)_p5_V&=|H{D_UGc(#aVm)G;Fo7q2?@u!>X#i#2pxA9_j^Y0uc(?NZICVc4-Yw+t~Z*Jpm zT+hS{kstaj)c0TQb>Mghi6ZH==CcC^*zb=wQFx{J1>W$-L3#-McLT4ta@Y6hF8B|% zYZw#(f9letKvMChY5seM6!oIL=~fqsoZ&pa`DUnJKNMLp7$g{TrZCb*<+0hC=K}TY zr_uYtK(IaPg2f2eTprfHufD8TiV2-cwMRt?rS6D6%2FgtgT?#){*@GI{fng|pkoHVnLx6ThvS{~0#j5de_}kAg{GHrhIQ6+ji7w%n@JD$gF4%=-k1(_~m6IF^AT)sgQ#;qPR56Z^G%LJeXc+l7 z$MT(&+=mV`7uB)OsRU>6?p>uhf|u99$rN_ENTND`Tok1lO`)NwJMz*vQ)o&hK;WTO ziH0W2^%x?%doQRJzG8AEdAS!l8jU7%f0?$}*vIKl=2bc$yi=Gut5qP;X#D1h&eCT( zZ88ncgpiJ?XYKntXqcKxk!=eY5_c)JPOHH%u09AQs}cZIOUZHFz!5>vm}S<>l7cdr zRKVF8QlBR6jxA@eq6}5i=i}Eov5pb7WZKfKMaC;lsa|Q++wj4->NUV*o=~5N+|rM_5(tQ4yE6({=bU&v zZ){q#uJ&YZ%kOw?FTW_@R4>AZ|8Cv$zN=|(xv{Q0>%Obk!4WQ0Y)h(!e@e++b@)>y znoemN)pNK@#Bm#Qkk7Cbowj%r@v3@^bB{2sPeR+Z_^|OkK+`08IMTJx`T2Pi;z*_^ z^C!kjwB?*qRKd*b9IkP(B(NVY&=cyL(cADU)Fn4GX27T5MN~f6JTY_3h%1%hl)Go9*YDyZhC4ar@^IW^?fMiRtDt;T7}0 z%--Iw`gR>K-?6+2QSg_jKh;A13NbU5N6jx23^C--4?%cM)33#Eh+zcAI-vcIZ+|Ji z4*mtTS6ffxMihR}uQ*+$!bVP@uh4|jEl5Z#REbd^2#O~5Nitezf9!h3TtxZrJu|*! zGIkK{?poRC@~Y zyq<+Q6LOj68_bEIkk-}jX(8gN!t8YS{BtUnd^HO(!40bXW&7(~k;p}%P&zCZ&k<&d zr($*`9$CWU^L$loe^99AVlTrr-*7cS7OgSfN3DO5Rtle$dsB$Wz+60MOvGHQ>JwMR zhH`>S%uz%*L766x+ArON(}sNzNMqd_l4Q2w9pY$ixRI@$Z5q(jk;tf6j$kl9EdQ}P|Eta#rri_fKC5I2MZ@o@^jOt~6L7$7PQ2q%t z^=nvO8=*O>A{QX=X-neiH;Kv8>#H@FgK?uPR0owtUIp(5wV+c2yhkxr2i?;JL3Yvq z0a*14{iysw3TqNa*ZOuaR&|r{e0r&2nU*qDELRwpf2#Xc&gh4zEiC=;CDaz$`Q|%h z9~S*N)d}7R58%Fqqo0lrd2(_dhLd?XIlq}+-cG)phgY{Z^Q)Ub@51@y_OB_7#-+Ok zV^jH_AAB41?OkYNAGhHiY~M9L)cwdLOJ^tcjstV4W9L=+mR05Xew7>b^R|nAbYv>A z5M?c9e@v}m%_N8vvV>9Yq_9qtvYMNEXv#VOnNpbom$1Q2$|YT{sd2-=6;kM?qzhZ6 znKWomgp2e}mAWDIQ$-DcS^`tidWU&8^Qm+vc&1Jf7HORBjkqRJ7&LreqaUsCwQj{O5i3; zdn9xghJL=GI06_Bhg-o;;^^nCEwiD&f1vPb#CI#~dj;_a1@Hd`?LFL9sH$mac(%@Z zgGg69c%5;BKDvceM!Jt35Y5Kc!S$7L2w!POhj8-#k?H=}uu_J9TrhOB0RY@W5)zBSW zX1i&B0Z_ZvvX`{j+Uy5rU>w*{(4(r}t!a{cMXV;t%IvQRtzUXv=~ay_c*4~S41k&U zL6)Z(ZJvrGTT5y6ktS^sXVp#~04YlUe?WKmf~aGIWDT%#bV0(uV!0?ooT3~yU}j)g z%e%MLzP}wHWoc+P1Ymy?=*iug{@RWEQp>Bp2)tIAAJhXlCuKN^C(qd1xmH3ur?LLi z&+=1sF3rmj4qB*mc1Lz=FFj|pbJ8jhQ72Otbx>^Z*6LJNEtICqcUp zH7+?hF`qH-P*_f*Do&@=x5UcrL3T5@I&#yADy({Oe(U`Uw;~D{(*l2uRLgFgKos5c z6;}}pupm~qcEFMPSXJ$!=_-k;Yvy8)JPc?C+Mp``-g#l;Bz4QeSa;5AhNHRJbo(xf z7*zrlCAwF<>VNcON4j{IuA@j|L%PF?;FD;7J$$_T{BWmG>bg}8DFYbvZ0TFIrv}Zm z<`M-cLe@$#f>GBRzDs{2bRhP=6+J#US;Vx+DE zVd>u8uob+5dXSZe)QR7zSIEGgo6!srGMHAUkm)LnoSfgced2$1=)0kZ!V8&$n^w&E z5>|Uijv9H{;DNq`<4MxIWX4Q#n@A@qptgR~B%Qf9CwofP$47+gIXEv#_G+}67M7&5 zATMJ2e|c%B?88wYaq=k?Md3c+8QVUa6VrT_dIu z&2?ZF8dJOTqPgw3n);ac&g&628`rD#8)$t$>$FD~N1=bvNAPsprFm!UJ!eZ_q3#n; zx!fFYI5p=v`U9O)!H(K65WVLs=D;D50I63fRCKjSE45H1S@p0~k#Q!A+h9lbq!hLL z@3oVVgmk;w)(1#tJny}EGkN>2I24|jBF~vd-;frZ5;_-X7H@*N=Sg-%Q!tLO&edsm z8-Livnn{0?DSbq3FO;U2dap{EMuf%uI)0;MCLVV&=6FQX=k94mmU3Sbnn8(suw{fl zXpjlj>Ceb6#0)h`jxXhgBsMt=Mf`wAHV9s|>@x8|s}tMjmd(qAWI1SLsgn5_tdqt- zWE480k7T*~mbb^0jq%pG^>vXx#1&6GZoP?5)BwR^5 zvyxLaI{Emkt%T`xTGa+sX^rpBhz`O`mM#U09@A_lq#(a7n^zT2&ol3ZO#Rv_7ztUF z6wIKV{(w;bvn;1MTk^diw+; zUO#_W&F;$3pe8$6(q&71tEGiyjwK?d3DdfbpqY<5_I3}e!ZWo`i(1NLS-(5Xf9iUE zjjGXQEofizQ*uyh2hRKU+!$SisLYe!__8QZ^MtP_-?yN z?lzz9<0RaEj$pC8h~#$uT@QazO{E3xRZTOk2-DG>L z*zAAg_772@LXlyZ=->Y%{9VJ#9H;S~+NDP5TT7Jt-hPmudB#fGr46G^9}7GE7gI_e zx;?+6K*f&C6^+OYmjW``2;yc@aKTETTxboRl%7-IRb66*!f1HMOtxpc68qH@216I9 z_Ccp`jR!9B5qj};0rc1qoGH}g+s@RAKQe!VaOF2cMC9;C%){#%L{pX%?1WN?_%Rvt zM)jPvW>@m;$jHM(CW%SaWF~fip(TYZm!fO~M-Wx+H+8@SzV;g;v*&ub=_9f}@h}ZJ zrb4&qr}Y z@x#^goUZ)ILLu3wkW?Yr9^!!YW|x1Pys7Fq0j41$RSpYf5cJ)>JsGVJ4BCem5Idd5 z0hqw$fV8PK``AQq(bYuvJdN!}+NGSFwj9g6XKA^SMdvE*NKgChE;su&cX^DHWG2+! zEHUScYPGt#{rG7vPG6d*qnyp?0OWiI(5tnDO+Ede;~gCi+&&YkEeWsfc)owp+he!^ z>44g_;n`FK&l^U!h16gNqcZpC6HW5St_PoNG@XuCp+QYza}1AE@hYfd%Jk4<2Yxwe zbBFjb%cDKB4!R43ScxZ{mu}K{N_QF>!`u~0b&v#TJc{Y=J{`Ts-iE&$TyvRi1J;^m z_EOc);^X>}Yc-q+NvbcKO2C2IjNEBdbo?_qm^5%^ z-GG*jqRQISdXLs;ummP@Xhg~XMlgFEdXn_6z#L@QtbuiR9~rC~cQ--&Rw>r{`PE9Z zN3_kZu2JMVNogz4J;1dKg$ep-qIKw|MdN}97|R#enEy1cmylAMe)=rG!foklax^dc z7bMadnJt>G$VQkKG;`o)KazacO1`7;;~mz?f&U488kT zut0!1MY3YoHgSq=?JmPwpgRT_6orn3%90_`$&4-keU$Bd*zr0Y5=)}U_a2|@*`mmb zC|aY`!eQ*mDM>%6D$vhAj_;$$h#Y+(B*K%nyXE7LZ_CGD$G?lofA_&1vtTLPEcLY3cZ*J;;xPiwl zx(YlJ2LNS)KxV>h(8DfFC__lCUc=6o{OeGxArl_Rg48I&5#>L$$!_ca!l|twghfLR zMr$s;#dSNKgDJIUc;~S}MYB1EJ~^9n;PrJIc82%aAZX<&gnt(d84uEeGM)ss7?0*zxAYjE!db{ArP(^;S$4nWTz$@zX3wr6)iWvtRB`^w=e85r$K^@^5 zHiu(_YNVx+K?LYDIzHBFQ#OLas5Bh=sS1*f?^}9(cMIOgPWJyTlq$ZnxU&(TvkkGCUmXY4PH}mxF?rmkW ztU#%R!?9;al5=h?`sLTjZI)?KqqjmLJSnq(eSiG<{QCIDPDnN`T$iMU0*9h7TD1^Z zyoV=J_+YeWq1k7L48mGWr`--y_-=(0HRwjEzfn+cVAMG34q#uQh8kHEf(1yUnp%4Z zy@4sq3kKnwXzvom4A#b|6^z0a6O+*|vGY$WYI?)syyTZq4F)w82Wo*UglI+g(_2)4 zmwy%30yeY@&~Q`t8jEhX&03L!ve7a!LY~X$gli;^6EK1t?F1wIco%-?=RCF2pUkdm z?$0c{zU>CQG~xfSGI;Bd@7c(deR_nmLCJz40?zK0GK4!LpqqmoZeD@mzw-(z5& zd`m1H_Am^ySb$Z6f`s?9(KTwGL8BFI(|?N%(+x3NW5{qI3t0)zn@%AnynvjvZ8#6g zmDP44%PU=O~>1L#nGTlu_5y3Y#5(W!!-6+bx4>tJ4xM5>_Ih=FugYS7= z)=5$z6I3HHR&!<#_FSXc-DeL;B58%DrVQbSQ0?3E>(966Ppc`jO1tC6tRF1m-R4P2 zi=Q?+*{jw>q2H{;iu&LSO4QUVoqxEb0-Q}_;7JLA%yRiYN&>HHffY(?U<_{H*9U6N zi#c)wdu+KZ=uzMpOfCtyRcro1Ekf>HKx+JV2eJ{ux#&U7QE&#QMmh^h!r{P_bd_tE zB|TuyG#N~BbkL(RxLnr>1CY$>1}XEK4dh(9U%@MGgRg8mRjMbvj5ekOQh!@=bN6UM zc_#$(#l)g(#xm1xos>q(N+5w?%wpVPj3wD-_| z?;a~^S^27lt8O0W;A^t@{V$O?5Og6AGTR8@^iaPe@fl27Go3R>QN+Y~4ia1F_GD3I zk_DD8`pnH9YoxZDMBJ-lQ74VmczKH9fC0{fXQ7_a^U<$QJyI zh)Das&Qt!fyFosh!j%#)fwO5Ftlae5a$9<*Wch?$2F6m$S^Pj2?so(HVcpQ6eNFxW zeN|0w+b|5h`&V#44swwq*fpt}p+mRJfDTP>ZBZz;+z7BGLz0_jU4Q@ks1Mt+=Qfup z6#4l0NGccG=FlWb!SaeKMzm2pH&5o&Fr9r(H%TIB&2&R^20to!e7L^*^>F=a6wQrP zc-`vxi;>+PzDr@)tC`%~%A=l`cKLzT)Ej>?!4w@bm95APmjZIx3dBlEE@%bFU2C|a zCO`BPfY(jMY9>s$p?~{|^|woijyEq%DPC~#92sxfk&9v!l)NQ?A4|j`GNkS-jp8rV zFxYzTu+aWH1JPDh=hW^io)0BFJ>^oM-feD(bBK|KG8U}o)O&GZV6nFpcKi?X_7vXw z`-M4heSUf5=5W<{ks$!vYQ5e)uhrR^4?Kf!ikVi4LG}yGgnv?Cla{dKiZThS6; zBrh&Q*lM=CK$}FphehrWOW3*+DqeFFR7%%FS_e3kvsyvJg0_XHKHs=OVzhT8S703+ipNah?U?Ax+LXPkPWV?c%~Xo+4L z6iNbhiwS8}0e|`(F~CTWf3X%@p>8B&~Nr#CaJOYCZ?jIww#iPid zgt&e(`XlKSPJwDzSeEfz#M!so%sX`XNf?XX(bd>HImPZI3Gr#fYs}5Nqb#H+G35}| zc>fquOz_;8mq6U2li-{}mi4L)<2-}zD|Hi#_$SV=hktgA*Xynyp^jxoWLi*6qDR8) zeht>^-QCUak22ejU!~3L{rh~Xaohh7n*SAnIj#ZZOJ-rF3_no>#Y-G;|cal6{q;2-M=sFN^O z!3pUesDFu+A^l{BXSy?6b~&Gf$|?{hs^- zomWk7<2Dez`&Uc=V=D)Cf?n;7-9@k|iWW$b1n6affR@G)5sGw4Dvpu*zjr875+%z? z8y_s09L@~qz4`Fh)i&RbMj57pX-oiyKzYB6)jYM2cE5i`bM^CNF&ar$pxLq%;YO(4 zkM9qE{P_NAHA}71v|XBL*8E(X^8_ir-8*WPxdtF!K2u9dX-YI{3(YG-;&_oTdF ze(_h7sF`<%{r8UqjPT>xBTxM)7TFKGd2Q&dvHL?Cm8c=dRk~z1%*7V9^R@KpTOI}o4-6i_X^J87mc>mvJLT9 zE-eL(0GYx)f1+UjQ>lO##j|BNb~$(p^p{N{oXLL=|1yOYDTcA&1-HSi$-FgNDST_L z)wn;lIXAPV|G8Q<`odB|bgs`_UcxsBq|YE=nW0HFU!x%aZ4OKq<^ulWHdmzuC2<-A zlL;_scBl<(v?^eib6S5v4MvqZ#n=j6AZ5~pJk4PSmOQKRrgJDkD)0{Pn1P&8ie$hg ziPC>-NBk!PCTCj&!}caNA<0>XHCsDBcR91bASc7Q5*Z=0#+13taLT+XZs?FMNbw$a znp;bLu#Ke)5Gc}Y+@3?pT(m)Mg4M*?gsf|1_y&?QkH&17Gm`{Co=qkZUbSf0J*NNJ zRlvM=$bHDSDwHQr&z3c{YWN8)17l4r9a4W-UCvbGrK{~ZiY&fta0OOg1I+z%wxkH9 z`GZOt*+~?MqpQ{iNS#lV`TYLj_RmuexsOk_#o+$oXtlf2{yG3s_34=zb61J!x@}pW z&mEOrDz~Ujp$78_Z474Dsquz*=84h7jj}K4q+=Aw>M`%KD4F!b*8*KRJ6pamQKElI zJerl#-*G<_K)+e}6T9CWIS%O&{`HL_^n=oQ{T4C6OAq1y8SGEtemJ2%MAYX+f3oy86= z-qX3G`hM-CZsiS^+~i5ry~&0_vFU#|ocQurK{P@?_)v*`X#1vLz>@bygLfSo8YGTY ze8$l_N$23lpPv1Q5uufyD&eukwu20ijQZNG8&OzjS)nsp<=a?20l7)e`0naRF>mII z2^5S@3quFkGrIQen>8JejYRXu)Hm{a45(Ua=;%cchLXTc+ln6 zz+hmSunrUMTi_b~E6{r)3Jp@3LQ~<6ubddLN1CdbsfIQs%7P{&cyMw=LYngYR5+~; zFd3^ZrQdTTg}*8KF0H0v#&b>cxMy1!&tyZ@n4gaPLaAr+Kxe39^*dEk+gg*N=jxO$ zMVR+g;r`^f+3>G}MKNbtxCcWvE^S!S3H6SC&XOPlpRrpGF^)mz^~jihq+q zkJ>O0h41+lQz?f8Wm)wK1XfyYd#Th4IIe_@88((2JF*?JsO7)cj!ia6v#0tJGc$Sb z`7>Ed5NrR;LDZaED>w8wo3&4v!PA8(AWD(z${DXi{c#}H_90g7 zfqbVvaz^1?3u>4Ya5zvYEZ~}&#Oc6%K5ysKcHC!kD>enw4{O)5nS!Ki+<&HpnciZB z#JIC2=>m>Y@{y!MQ!4@190yYUQ-+z2`HBgXwWu@Lu{TTqkK>cUMY7Wf!YC1X;z{q~ zA*Ozl!Nv+h%vs4yU~WTqwqqFG+XY|ml^uMGLg z4?V0)Vra3KN$~5-yT#5{{eS*uo(CX{#cu!e*Vy3$_;OIcMZ?`E*LgqS0{s7T1f)&U zM*&~*Kyj2KT7&SYQ)e{|9h)V}57hqI$z5kiMTUoy>9%-H-bTsD_y$gdKj# z7M(W4FgpEVjq@%4b$5ez?_2a2omXFP+c*q=&!-@U46%zey?bq!bbq_M4mh9~hNauf zIv9#AH$olBkmP1T(eFM|k{!pfbL$xh5{nf7^GD|0b-6A_ql~8o(>yX(i_|7|S8_A| zGrk&)B-?OPvXsNeLT&GF?r!gIep<~^t2B};b3jOWX@!#a|H>y;i0p%Ys5V^MhH!Ow z;fvau&e1Ym^9^eqet#4NH#=kb=KeF&R_w*xt+m>+Rl$QDc_mY#0@Ir9l1IKv_)lSM zP;pG|C!pmO?~)q({#oAMW0Vrpva{hbr54iWXwSvj*$B?yFJ;%DIm@7Ac5T42M-Fz4 zA0`UOwc3D^9E3EMNsO_|kt)m-PaHw%jO!^FMVEGvGAWgXOn(^mpgEtRii=S$BrBW} zB@5&!m@z<6`&$*&Mw-#{2=H+h(Q^jxOQzYzyZeq(E+3|_QmR5!lNL|Ra%gfDtY}FNC)1-l&Y-Rd$83%0J1Wx_zk5ICC(mHK z;g)60vIFfgJb%B8dYxlsS?nSzP#9yGnfMau#qmBjDm1s1mN2HIoiDl`o-e!UQ6Cm6wO3aSLx{+Kr~N?Wz6Kg=Usf1TZI^#=Un6L z3W}La>gnX?N)zrzOI7KV(@(5__j?LG)!;GOLBH(+%Q*N#1#q>`DQe&>T@MuuL$IQO z4Rb{Dq+2+s8)t>D{rTRK^Th+Vk-OI_q`eWy+kYLXo_kt**RtcAGdp%T(NFvC?*2e* zkX2E%d~14PZzkdovluv3=uC;bF112c%bkaVj%0dpTv;KB)INPVWVCwsTT0qi5`aYU z`66Y;)~0rpV4+z`T(h*mnD=>OiSC+vXorf9?$8rfkA5OOlg}OCgEw!@8`?MsvHeRZ z34f1>@D{s$Rat~S;1-YdHLzr}g%6NhH+E<(o-~m-CjnXAZn)A@C%LU6Q`ltGKnT6GT2Lux zVff(Wq8ywaHMG;H%HEOp^=J_ijX$wy)C)n)hro~j<9J>bU-(8naT?emJU*(8<9{!s zUv*GBYXdP1-u){yCPzu=nxt>isZb~x14Z%aVuNEFSyNp2bp`R|kboy46Efg+NRk9^M$Uv#0PC?h7&P-30o%)Pp!CcF5Q z&Z9`;AF>)5!8f4}o7K<9&FbA5WKJ0$F70^W?EQy8xp`E3&QOH=Sopij=%e?|nlP(> zgU?z#?S2t+&%O=rsiBaUk~yvj9IPH@(vs66RrgqYfE`WbdgiK?V742S2C^f|z#btoCB9G>3D7@l#t@6ggg zVK}++^jI-Om@d1kO;SJ$@xh?hlwB5ox7}}IS8zLBdfHv;SZ+9mTxlfaD6C)VW%Lw{ z|2sw9wE-BPcufZ`Gu#R4_jh{>!{NAX6%dr9HH8NLT83baWZ)=>wf`O0;eIlKuWx9s zyz>yebqBH(VhOP&k}$dN%Ib#&NIG0qw*2ZmhwQgce5p80mqsbKo%f456kL#h7qZT~ zS@_KDr3$h1R6Is!-zGgB;B=k}#Db`~CAWI#*4d=0AJvvA>9{N}G(DZeR*)|h$Tp1Z zH!{|^B6+4NWSMQEFzdhDW+Qhno6VXo%x^X`Bz=?le=O-tJN_v; zMgIW3S50r*NDRIESMcD2l-fy`EI=3(eRRj;_qbc&H*)R+?u!ov@kp;fz5kNqs*nY*FIKgxY{E|IQ(hOklZvQyuT^a*L^3Bz zs8QrfmOG$oXbm4kZLE_&RoPThkG_w9KAUD)7Fla!vB;Dp4^3tgt6-Jt;z1b7OiT)l zSMhmb^-}o$II>R{XJ>Bb8T=#Bf5rj30?S;3qW`Xn6VM6-Y(i9!*|5N@g#jD3Ruz)m ztTi+;$C^Y4r7JOHl-gbJLQ7={YoWm?SR(ia%weT!5F}D7-dw>Hgv_BZP-u`%S&C(e zuwA2Uok1zGdrdkMpv^3cUZM&+FHqZn{wf~O+5(M|Lc?-GyNYbhJ_J07f3iWV=+D*)OCu!Om^omWra_l}6e&vxf>tD$2s_sPz!;rP@l^7G|v) z6FjI5O3t7FO+OR@7c%${N`KU7n%Xz;O9ryMn~+;o&O0SzIKylnQ|WhK3^ta0zJ}*1JcAbpLGhrGIYd`A3d&4tn#EiT6#4Uq9s+Q ztJ6-99wAQPcJ}%2RiEJQ5jT!HnCC5SBVV;Q0o)Pp9StoT0}>wyDXhCxdE~u~(pLG> zQ(BFcdSKe4TZE~rf3~~W6?Zrx(y$`4MU7LjAtK00JCaKXbXltGe$vt&QALcN`o!A2p=9p$)^8~nPIl#OJ8%*v@Vi%W<=V$yC)gVT zU!TRCGbUP@zmCf80BKL1*ee+(Azu%=Lyzr^HehI~ijen)?$9GUoy1G*vXjK4<}aZg z!h+E!85ri6fBlZ2xM(ECRa1VnfKJZO&)Z2dbR6AOBF|aY&3}4~iQdT-@qwh#TO+zb zjE;Z|L!tyQ1s{R1&KR~(8JNv1uh;=CY%ST&H2Ao6&2j6vCyp#}USc-8z2@Wu74nuV zl1N1&rWMPJTbgi$pSE2I-ZCdg2(;_uAHePs#pZ=N{Fqif@>cvWHNAV`I*d;#fgIf*Qsw98bbprbNC=xp$7r8WLZ*KVdoC@43Qk^p0pqO0~I-mD11t?HadnEW6L|vWO(BKZ#_|RIgtnxF<5ce1h+i@>cMUp6W5QLg)f#~vTqfDK9!X-l!L zWUP`$%eYj;UKv}@p~L6e()q0bLHRQkaP?M%lgSmJI1#{JDV~P7do@;utE`Z*N}PsL z#zaC)(yiKo>oXx^xRxuy}<)j$$o-e_l6R-grFr{qc2h#@O;w z80viO#f;_$tVhou&2yf~EXtA&JZdzW7o1hWsUF{-*6%NadO1YfMsp|NPL^5tcCIn; zKyykY)`jPXfK{%6O@uj>1y4ccBXw9!Zf*?b27W0qbsM@>!467B(Ss8G6sELL^1DbLNjBW+XccG{H3 zCu{e_XtJeSwf*C?NrqjfIz$wM=b_!!d^=akS8152e?!mGEU=yD0};m7r6jTt?YbZ8 zK1Hw>&m5m9DH%uET8U*=@QCVHi&^Q3pz?rau;#6TOjCh*FoQF)(Y!uJPq~!FU5`&l zSZk;aPrS$T288^sVK(oQg1_x5G(=_jUL-8fJBbm###_=QYTUu|PU;O2{nQA!NX>+9 zZ0EF0f9MEZpxH9sMe>1hij(xzMK_t~Ar*#JtbnBANV$L=NpSY7iB5E-8-Pkpp?mRE zclb!BlWJ0srL>Db-Z}#inMRY1vRmCcvC-!=NmOlMTL4w+u__-mBT^u`!%?+j_=1<$ zbYIFDpIcrlW{kITayBbXSQsIpb?Um}shyxWe_!>z%qvsXhg+-nw5tps?0PJ%8gTWz zv=YDS2tUlg<=?Ilp&PNP4^08i9k3#*3p1#j?r0vLwz_e8ewR@-U*#Or>%(yQ<@0@) zMP_33+vD`Tb7`jcznPit5AWVJ9+=O{(eVAEJCx8;N+nRt<5Qd6fAXIz`@(?EtGng0 zf1C>;m{s?b{`aE@|ElY&=gc5jEcEcKB>TNL38A|@>W4+&t6i?Yf%B{b9*O^fK2v^z2x9hV8}e!i*XQIlV?sGU4cuxAx~dLAeQRf&U488kTa6o|BMVesOG-)>!-7W(O0J?vu^er|IKo${tLM9?@6UH{ z&M@w@q2*4FQY> ze!~TP-ZKNt7_Q;0?OcC?HNafC}f(=JZ;v zg>p1#Qg#lH;+0hU<0m+Wy%y_%Nz-6Nev`r^iSjtQy^>&E<@OVX_?Z$%~*kRuo{r@3=RTiYU_kj5yKFk zs%B_tjVXeWhdPUES?0=uATR1l5m0I9>=0^!6sBUF>~L7Xmxh?%?kJ{|b|H9*mK(7} z4}@|DIs1hT5AMBBY`kh7k9x@kofWMxVBfVwA_J2&PU_9+u!75st`;XF^>%M9)%?eQ zNo!XB?6j$;5}&({*}!&5pu=!qpVDuRJAIQHgE-mo_J&^VB%)VK(j;D9=U&t&9k=X5 zvfU$gRJYr`*|e5itsbB5e@s<6+5YNm?HEn}9p5`yt+^9Y9FJ&tyf)d+cp$^_pi7O+=j|zXT#p?*jd-L z!+>Bd;=ILy!N{~lK$ZlOitBax@8cyUij)QFK{`ze|Z207g^S<-~Tr>xj7Ki=IeKYmq$CaMs6yOP01!b-)9eECQIL^HmA zFSgZ=<;rbLy9b=6U>zqPid?a;s6NWt>N_NqIHBhb zA#3CiyggaylR~&RU~z)7)Qf7Pv%BFr%|LgClz;_s<(3Y(z;|WF5aSYmex)i&>0`#+ zZVcWOOXz*xvOUk&f%xFt0QAuIpQvJRZNUyh8#T-zud+=0g+l1EF^H9G7Hagje%8W` zM#1R1&}f1dX)xS)Ah*)hW5$yQho@y?ItvMS4eLMTa$y~r2Fp;C=WW8)ea19TYY6P_>RZ114G+*l#I6pEnhI5s2tsM)?VqoL#7&fBV zt;sxB`stjq=cQp-5zywbIgVd?1QR#R9E3%=F;{x>#R3{M4L&uayjy}mKqw#2)v zV3^oR4A183Qqt@ZMc(-sVyLK8-k z0wEZ;cVi#B6loY{dXspb#eVW4pwh;=P*hd2O9MkgTNJ5(c^2eETPXzEHcl*xN+isD zddlid#7zdgfW4saA5gWkW8BZk{V}VcvU8Zt;mAa9E7fNj8ZallYaBb?zq^UM`t=J= z)2c>kPTVb^a~7e3W4BBstOf83_|@K2ZqvgyDpzO0l{;oIpnGzyUrfX z)5F?yCyDxka(ZX8nouT_#ogyGeGyq&Ivr2YT*uZd!MvGSih+0U+6>HRHUE6S=^iJH zmD&k3bN|p)_n-0?+J4~{a41{U%R*AJ>La?Kn{owuCEP4Hg8t!a z=%jb0`EPJa*XdaQ2aXSG97Np!s$1(OhJZ|)KaYWm{NlEQfZ8rTue3 ze7=mK`4>REhrVW62tIw9dZn~`uF@I=;j>&9$Z~GCKtV!hjrjC987SD;ejfY-T~JL+ z12GV{TT~cq1AomV0%XaMpG^7#5>n5zv!s zzGoI;<#EBt`1b;2Ap}8iMwb^CchV#4QsL zYTYAS!D+6Wwm1;7o8L~S#H5Dj{ zQ1$v6H?E|KZ(}iy$05*Z7*txDYIvP2Dt`nExO+Giz$hs+b)EgDRgwS8M1k#j;vN^0 zQHphWhb9i6aV^3an1PW?q+8rIz}0Hu4QhySqZ~`al7?VZl6tG+>ioEYtBuW@6LWC@ z(Zx`@-!?OKR@3DcZJnDRJ>4koDf_#Jt*XcSVhs}905Ly1^#Uji4uo?frEz*FYJbl# zs)54uv%j?Bsv^d)Ty!VIfLkwQ*|U_zkt0>HYvkFiuE{xQu~r)4*81J*=KkC2W=}zB@`2q=JnwjAm(6GI z2={d2`RRA@#B`@itkjWz@zz+3Z6vH#KNOX3d*qui{5N3r-Pty|y3jA^FsQDd`E;7W z6h1-pP2i@fR0P&Uim;XpXk38-6x572gRg9l>A+y3Sc9)IPz!#|so0~u2Tn3uEMOgc zl|1XlTB#)1#%(x6xgsGnj^hHV0t(LsohQ(xavKCgGftUjhN%pH>ogNS)4)0~zvzkx zgC+Zw0k71QtSNk~RZtZ;uKvt0%ZnT;wZDRqHI*TVh%ecT1$Nu<(Gz7exG%8}<|)+tquL0@B?@Y*T+S46*MG6y7kqnFK41>qwb?k{GAiXV1g6tk z&^`pz!dJo>&L5C}n&4hWzGM<|5Ek69-Px;yn~*c zBXz?_cbgop8MtTl5<1K?w6P0!FbHxynJixE@m%4KtT9J+_u+KLLORchOp1QAUO#nu z6n0YXyFs-gI#yUI5=0wCs&e@Y?v8u2EvT4gm4=GkOyapwuY^_2THlrEj@5p6Ohmdz z=g{6Zl{;ucM(^Yv#U}v-@{(l=6flNLH!NUbv?A=QX~o?j;8xj&%}19>2nA)m!`VMa zHk_t=WQ4;0x%r*_0k`a77~TVawU<{#R*Xg|COK0WX`^^z9?hXZJ^yX;b~F-fhq_=1 z!tc4&N&dd%d5V2APjRUZ^_|7m{jWaDEl*fZT-q>yV*0YN$Jb0L zxvzLyxVZhM6p7(dKq5;)kc>85upB6ST0;e94LI;!k>d`9(eR#`BxCEmxs9Q7-hK1@O zY2`ZSNrTDbVY2JPYg@GrS$pFVj9Df2P(hskgUrMK}sa|4{v)KPzUToEvDA- z=*(mYIwZnb+!YP;xi=rKjsrRKj)e>iSi`#~reMdPF{M;CxT^rP-$qgnB^g9PR-J71 zlKcgxJ!d}SKsMU_X@_tKR+ z)-GYlmIKE;tudZ1z{! zhZd338HirZEm>dFuejGJY^gmeZktiQA4J0=#=7AaR7Es@APi6XC3M_mDi*3GyXX{& zr#{h~8+1MK$>vm5;Vd+@o^1}{PEoxIMb$^Tt+68he$a-T_&LcPo3u+;nL57*jM}_)Szw`eK?snfOUlREd5anvEQ$?ktU~4Hjy^@OM_9n+g-r51YPhv zpFvBp2U`PwgN;I+wOlRGBN~I2^#qv^FFi^){p4OiVV^Hdq-`}$haI`B)|1vf8}_m! zXZDH=hb`Z-^}$f9HxhDW6!g~=E!?7d{iY?d?*w8>BJC3wkkdp^Gr0NlhFqEcjR)&W z!h{s|jW!M9z@g?@NEfqpZ0M(XiXrCK&9?1FuaXRw2cmbN(7pXo{UER3p)CfHNK-yE#IxVzn%|Gav&5NRH zHz)f9-^=J5m%M2h!GCR1!EVAZ487+od_Y=3FtjU-?J&U!O=#kXG-au~MrxBPcInW> zzt1UM2aFtA%P;ReKevz1RbDBTqA7I1gg98k?|i6`77xR@Qcjmhl{N^g!Z*9+cD-AE zanOc+5V)oeSlI&UK#b*CIlqZ-H0MH{jz$Vb5P>(;sdb-_`F{W!$k##qn%oOH_=X@w zGQoZzaE_2grC61O#U5$ac1h-hN(Z)Vy#wQmx^y%K=b=Q_sb(GBx;|)^MySi3o-y0( zFagvikM5w0AmbgtQg44pz39EDPL(XgGOR7J#Mu05k@{93CoUm|mZ*$DZb>@{4ECC+cumfWrnhSMB6XeAvwu zPe87NYbj?YNsr(37+=DiTbexemtNzql>8@kX)ehZvu@)zNv>{Wx*+^($?)-YR7dp# zjZ;le!axwc_gCzJ!%@YcJ{jB3b}YsE)v|eA73*pE+gg}LH8 zdelt@dAN^kA~LA;Z+vY<`T(2J2{lJEyh4wY84<82>$7LtNgjJ$=19Os3LDZXLId7g zV{{5*!PR&kNKa;4=eN@z3g<}w4cnf?0;v1($P`TLbI+Xgd!_>MKc0<SS(iaYmFUYZnpMO#qIGVuo#Az68O{+(l!|H+U*-*mjS+VUF zRNz|3gAPm{qBs5m0gAShZc33^teugU4=bt^J*|ygD_1SrFhMy%LbWChB@JnW?F$Zj z5Jr;)9GJ*G4V63k8xed8OOF9^?ctDE``;N6CFj_r8>E2dQt%V8lajb_1o?>ag@3cG z#l2ou=-$fA?;RTJA`M6_%&Rmnl) zjM^3>Oc>{?dumy#48B!=YwJxxv45On@vV@W8TJZeOeL{v8%8TIr4p?Wt}t{&77odh zZE?|Ww$zBcN|w*7w97&6!LK;!D4WEYKa9wAi=kR_I%(U6YvFRsG8EaYyP@&CGEdt; zPi`1jb#(`HS7Nab+mNI}@nu%w=rj(R_m=OACjt({y@g2~IG*c*2}sgWHGiNxG(IN& z=p;>B(B~G;MxwT}9b)oGt?nQzk&z^=&(Jz80A$Si9G1GvXmI>AB~+8x2{)M0(cn|6 z7w;oB93!>_($TvJlGu}C`S;Thc(3rVZGZoC9==VOUO)kOC*TE^pj=<1no;!v9$v`Mz79#vp})iOBXGg0DD;=psA6?h9U(H6>pH{-#bG}j;*M{Ru|Lc=*`TV z$7jF4ZtJ!vO4L>boKp-&$GiC0B5i+JTor{=4N|K#!e{Fb-#*>`{_WHE7?h4a@Nq|c zV0Ossw48`J+n2?!-hV~>9!DpC`2&r%Zgh=}%A3ET!=Q4~^~FU27w{ReBv8IqyblQ3{Zl7{U zZ(tlnR3-R|PfI>ZflL;v<_ap~4Al&tAWXc3TR!Ffjg?Sr+JE>6(jKTPG8!tbDOYxn z*plQ)c)knFv()`)(3YU;KIska8+7q!0^NnctNCK>m_p9k1|PllcFC_Z7Zo>@p$*BI zMk49aNd`$oJWmKn9e>1H#qq8 zJMDSyq2sDkz$sFeCd?>(F4Oq}o}M#Q5~w^E@G)TQf`5C_?|b9oGRa}tGyRWLx`YRB z$`Ac(>&c1+4o@x-%yeEX;hKSAW=+G>%-t_GFKH9t)3J|3Z7jl^yTirFwmhbS`7G9k zRv&sQw>{h_a1=byIu#~QCgSSVSkw(%xDL zV+5rk@qb~ylnHYblUNwyn61+rG)2c06{FJEYxvlxye{ckt5>sFDj)OvS-vCl|l`8}n7mwnvEhH-QbdYn+%n92CK>GnOrLujGf}73^3s z4iD+R55;EBm=g8>)zN=xDeGzaTV6d+dtMrJwo#Ee8;H2l$U8=NroRwxq4t`23+=>| z#ebCE#LENq%r7IEXJAb_|xw?26zM4!5mUC6Ih|{}F?rz`Se7Jr4 zpeq(>Sz)>ilDddYSSXTp(LmjO6Y36|*&ecq zC|E||hf?&1`PK!FL|$e*=Y>}En&~KIn~Zm>GxA<7Qp%w=qbt4>Mck8~e4P*;V}w15 zE2uVK%1Ycb&1vm6(-hGGU~%*Ff`5uS%LcL)XR$1@JsrTKY2u;VlO8aDrsBYzaTC;t z?ibIW+yCh~U4Fc2Wv`ims9F*Np@I;&QXw?~VV!akV0o1wxfadV7Xy8z$TA*ZVK0=* zx`K759bOxbK-O%$l2RWV_j}1ImXm;H6M%CY=JQ-U@OZTXx=b_0HL-&1ihr><<|?Yh zhQ~0N$_)0t!unpPqSzA85HbiE6IvZleE0)G52GcZo{@6S&Tw>$)1YV1;$wYME{oP$8kwaA->0r{@d4zHcUI*8# zlO1QAi5lP0Xs!q0VfQe6O@FkVKuBLZ!70F3^HonnkKqGB|3sf11F??zjlqM|2tv2x z`(zY6p{{tzfe4@p!X<5_%&g$S?uzTW0{N?&_m1)j+Q@YE>Kth@quZ_+n{=4bwb-IA zeY5b;y%h24WMH`~G=bM$Xd1bf8Lgp$rkTh^3pvd13>f$@-IxM(Er0$sC^f)!pIV5l zU{@#FDA?aUkxiWdT!?)B(&Vaz;{`FK1)r-FA!~CIS!OzOOi3kk;`hATo4Nuzy5s>W zN|I%0o4#iXQK*X;o0Kg@6k%z@N!Ex#G4KiL*RfbwtSOY=nNf zFk(YZ|Hr+9LQkzkCpA8I2)h_gGmAxreGMYS%1@Z#;z|&{;&}}ru*kF$IJ=b zS%33fR(spRhV}zm+YQx`A?=DS=TG4sTJ?H;F|%X+#S#^!Be+hPHc1R)GM;FcQSLrK zsmx+CJu^yKmdtGexom6aUrSkt_=?czQBi;5NOAH~F+Q%q&3_vNeN)FIl8j5(KY}ff`pSG|7mnrY0_pO4 ze+ksac6rN#vNAjJ?y)-Pv8=0zD1iO^IMlZJ%kcDt&BVSp&9pPvW5df}!f(ZY&@#VI z{sXrGco^dke_M~*I23-*uQ*##O)_GbnO7+6MYOAxs#Qft`%)@ooD*Wnu_N2zqH6y8 z9-9yXB(v2<;^y=DTt9#2!>?stMp24fGJ~;oMsT-shZ61dIhjO}Vg=fgafDA&@0K55 zJ}>_?x+?!Tkg>9@H&;SAY@)u2^fOSKp8!^>=|h9F+FWO2OY-M3 zswoqSe@QUNQmy0xXyn$yTv)ERRCoGCY_80ugw={` zMQK;u#Q_jNeqs)RV#AU?k?hu;5sWh7boLu zbbRmZi$Sa97USk*z`*LtaEjDW4F(~_WDN7;8ElUsc)je&2ZFeD%yt}1p$~MPWK}3A*a6nGW^`I{OksThrU03d0u5M)<&YLq zdbJ~*?3s{`K1kI>N+jClg6GE>Tfn{W90)XM_GX$+1!2zp+n^)9FbjhJW*a?@zMG~XYC>h-id%a%w=?!G?`!Mr2JdL#zmvl_?HR}G=B2yse zSqY|I3;u_U_YUem2BdWNG=`)%Evd=r&=T|ru;BEm_g(#ct6NEr7H&^hUi<$;i`J92 zcKMr|RfN-6Pm;0-`ulF}n6!}GIl!fYvFN)v^HRG}SQj0_S zFH|M%zk^oasAkV-ZBdSlE(MR+*s~Va=&Zkk`6-QsWID+%3YLa@f1%o92GZ|R1gMl4 zTetEK=i83bcTre`;GHD`FNv;nBI6CK`hTn>7Dm zffib1MiD@e2o^LM+xjHxLUKr%(&ueYUVEIboatHhn-`C%iKTQEvL#wX#IXajxc)eS zdT3!*vv30Ie;{yKQRsiDTUVv5dty%=+RUXf>wMPpRYfate~IR+fCdT9SE&eSdd*T) zrP7#PTIpvdeORxdwQWK!+AJ&r(iAaYF;$H#@%?Pe;y`@Yc z@wcXROXy1$1Hau6T+QQVYp2R~Y5LM2244T7ATG1-PdBG-q;f&sdqAc;txUZ%#$Kcm zrv0my3`(#zgC~XT6E)5H0lU3ftnpupg6n-Bo4)^6O~!3j$u&?KitMK)@dmlQj>M$H zQ3YiFSRM^^Bh!ZHPI{QezdS?zZEPaGxtF~ucY9tZtO4x2o%aW~iH{gj2!BvbZ^AGP zz2{f>&_k&vpD zECYL^_>)f#!|U^;7J}q}!AXU%>g}Of?$)Uo!*ALwj|v?dOU**ET%beJNW4`Y4)Uj2 z-y2$+!SDuUg6ltMVTjSUnSXfaC56`d0lhd2NH(pi(L)9A+&XZreBzefL+ehS5l^?d-lfjniV=qI+pjwAp>Bi-4ABn|~XLG(;+ik>uZZ zW=L6gCup~Nuw`<{xtue@pCj|6+4 z=$pm6i@#tnH|5X8yW2=?t<-Aqn@;jneUv8UHrnjRPx|D4SJym|@tbU&r$X7j1s}NC zEZ!t*ok_b%yC%=Mm4Dab(}z#^t0C|izCVkV$b^bSWA00|5h-7Mk*Ngt&(YP2#05ry zKItR=hbOssuQTw@imW9_(~Cb0+D~(A_zkhf^-|Pi@z2zBCou*gx zIROL5ES0w+p0klt&WzO=Uke6vB4*1SL%N(WyAjOAmc;^;f@DP8U^20RBj+R9l z`CUqu`^+IABFJ6|;}}MlT~a|#`sA6izf~fyM4JM##DX^6U^r_K0AkUGt2M}6Ql6Cb%^LGvsLNPb-4|#Q;c9ac>^qS5a(uvfi*Z!}#@|Jhja;^4YPbR5vX6FHOt#gQ zs<9CY>aMrN!^T)xi77tBHX>*r;W`3R3xDV-rf#R1XKd)oFk1}oD2fk@VOi4%!|AYd z>Fg;>*;^U2oz7V*ICM-34zd;1t(8uo-Gn%vv9F6^w}xra?gdA~F&iF@Yi@--YmSEB zj#>dNUMq=ze9T^_e61&Ptu)nbp6rY?Gs>5VOWFz2LSV3a4wa5_<8?F>b;C_NQGch? zX_-p~c!qVLk*j5)EhVYCmPy`GTst!HM|1rtmDxv!PSdAXU+j<`3*M%2UX9uQ9>qp{ z|9VQ9QoBV#^(Yd!Sq4|d709paxEuu)`izP)z>ba%9)(6{7B2(sBe5K56~Uq=mm-rn zFfZHTPB>XLrE1Rf)GwY^JethiYkyGN4;!)|9Cy-}ot@Dk)txT|@Asje%n225ME_~& z7bZZ$S59_*@I+It;?G1-aaA|#Jr|92m4=aT{>vhOH~r2&%YR9p`WK*& zcR6h4cAb~|Se$`2^tjTdd9!B4Ol9yO?@;(>py=C!!+fiS`LVw6Nf#S`&2QdpT1C#0 zt8!K8>C-Ef1_RpJlUE8EnYM50_rv(-fP%qaI;&e%M~!OzMePTg!u|4E0h8w3|0NN0 zuE582Og%8nX8!K%=Br*cSbyChVl#Fnr?F_Bv;_fDxF6@ObFiK(6!MoZ8|%^Ww&n^A zdfK^qu$-lhV(9Je?w@AeCj+*S^zXv+=d2%(de_wf&LhB(&bQD(o@@IN=c?dzpIMI- zq83z#Z;21}+l)_#XW%^j8QDBk8Xi8SD7P-cg|7Z2sbt;vGCo)0c7IEkT2K1&5`#)Q zdEfo((9PKgdw&+niIRQ+k%?Wbux@1iPzK=m{6DrwV6+! zAN@~f4(a?}NycC6&wricBBy%Tg-qYA#>6T;e^MLMW}b<0i3Mnib0x(Vyb5E=y67VU zzY5LYu%%G3LrluAFDy6RQg8yyNn*K@uvqwQZ^03Zs)Aid)lNDg8V(piNRyJOY8Dn} zfEon%WLOfa7<71&BYao~#yaYcmjQ|V02|CcYQxyBxap5ii+^B})orpYrwlt`8-jhu zuNP&HZ5wJ|3el}M{2NA1x=OqtMwoI*ImLbJ?ehBU7;1B#-MQFAx+a*`{1`$L)LjQ zsAan7ebDPw#34Pn6&xF2-f?(USysz$g{C!daMnd>`Cmh8PX5f?_R%Mo^`IDufA*yZ zJ8{!3c8j20ph$}LuvrAOG`5MANP?v7xQqOIhmTKNR8(gn48Be{sVUb}%1b5>%E;@pLb?EaU0VdR^owY(3Fg;68ql z!s1KU;edeF_yZHE%>QCpfxn_a&FnFR-VeA!je<;cCLfax=Bzs?wSD@GdW}!N{mu6N ztAqr5`2STQ5*G(Bt=azBWIU;m-5J$0l~D31(7}oemI0N6G2l0I4%86?f6rBhjy41J z;NbfJ=()bU^l!L?JH<51feU*xjUi_*3mE3k*e53L#W~cH*<|y`|G^4$?cb_clFN;= z&(DbzRIEi}qY~JFG_q8RY!403Fx0p*@kwM=RWLM)XW2V&K9&Hd`IcD>w(h9}a>9?E zHcv!^G{G%QCvTu@x;%JNf5AuayG4R<+P%Q0UIsSy~ZcW=0v@v;rZQlWF~9Sd?L zjp54-$HachT_$3UDK$M4md0|*CpS{mruYh?q1|vZUIby?z%+EwJ$9qz4g~JtRC7ib zz8GP}#Fz`n3u9r4uqHYzYBInCOk!B`Es7ajzz=Y=G0E9szt_S4e~q6ek^hmN56%D> zXW{+i)VsF02^i`&-ja(nDs>8mT&Tj1W>D+CU(&d)(H2^GziUVtZ+uuhKew4G1ttnx zNbYEHAk8pL$`A6R#&!H4VS>9Y(~xmvZ|Xya)J7M=95lu~<-jd``8sbZ#Oi$~A5;RV zW?ayT1BD_TLN8;6f2T-fqhG-d>^97jtbHQ^VvtiQRmc_NS)rX=WXMdp#48V`;2db} zwW1nhl-bC~4$M?d->s20)L9&dqG9DOt=8Qd?f?EEDpJdYSZzdHa#OfR$d3~zt(Rlf1kQCUmuuPSY=FNxWIeqi&{(9z8cBWNwaitU&o5mx&=;Wl zrq3<)ifaeIe+Laq&FJkx)Er|H+Z2)wwVv+;rE$w;(QcUIcJ{RF)>;;-0@c_`JZoG-ix-I)mQGT^${xO~6P}%xbS2@oeUYkeDz(Oj z6rlsPIl-GZGjHDTaTA6hghB08M432R&09VO zOt&}vS_o1jrl2&!cjpg}-+tXc{)k>U7xB-cJ4;5s=2{Aw`w!4et|_P1EF$MfKzR5|k<%-o z+skwM^0m&o=KZH{n1_|kX6PnImvFI2==6Lkk{a(y(%u()^#HP)7m}dc)(!L*q_c+U ztXA+;79e{t(T4;qqH=7!pt&@G5_C@>w?OIE7 z+c*-w`&aZ-sbVTc#m?5&9%Ng}Op@8xY{nI5_u{xx5D7_4C_+PmcC?BA`*t@#5+p%M z*~wuK%Y#G#jaNUvZs>BpU2jiLVi~0(mqDTPB+?)BZYztc=i`f$lT2)6u@#Yof1gwJ z@c#9?U*2EmDw0K^a_lY(r{gD8X7P=d+lx+n8GVvE$yWC5KzA|N{})lL>tBOZZ-h?n zCDF=!km#)}l2~TiE_tI>E>?1o{02W#X?}ZWe*HO;Tb-!v{i|}DCXvuGew`sZWl?tx z4*6?#FVZCbF<+G%+|%I!e^W_zf0*hfTFZ@iC6`H-P{SLg|CuGfmGao3IN+7clY6m9 z_l%KIsa2mJruqH#dRHJj((6?8hw5BJM0As^GLd$=>E)%$wEW!F7&<H z35j3mqbIFC$qj15UZOW;n!Z&JKb1)u`{$#Nq4t}#*mmc4?5NfLR%Ef-fBZ|NrTnwR zy^B6~aU-a~OPR|o>Q0M&T?;bOG>y)b{Cinu5s4K5v7(;g70p#lC^AI-T z^9)7{<8of&{`Foup`-Op@^9JRYq>!8(g@|lhe&1Ux64QehOi;Zf2D{O@z6Cw80EC( zupzcbtEns7g^{#x;o!`T6%uvzK1@$)0wW4A!!*_>8!^})M^N*z`sCfy`OFIkbL;Rb zD4Dk8P~?C5<01M=f=K-Q{QTUIkKs!_?CcC)Y{W`U&;hDkfNMkb2f!jcm|%e5ph&YKA!x~F{zg3f6F17 z0KF5=@D1##R&DXd;ZWBhu)nOlRFZ8=J)S}h&3H(&bz?NBf1Y+V{yCW$ryPtg8X=5~ zzrEr!7BXE1t@FF%Ltjtdm9#qhp2O*Gy9=ko>ma(@*-Owdd#B6QOFuy+nWoo~k>Quw zBJr0c(eLht5hDY3oRN zY>)jo6#i;Ie|t&b1VbAIV@p$$+JiQ<=t4uF0U;QC_?2R82=^+9XM1Df)$D6n*0Wi6$RkAT zb%H&JzPmUJ@eI8tqO4dJQJyS_9*nObbOnsnk~D>nf2e`f8A5`-zaU+NkL29egy|Ie zIN#J2V3Y9>Ks$7H1Gicy^@WbnM~45_ZJAu)fSrWFF z?ToqY_vUjp$Q$dk#$!^rhhW^BYw9Le_1lkcQsZ3~2SXek)gwpHlQ zxfsK+K$UqUr>1bTHB;fCE7pCU6`3&x?Se!E1bachi+dGxS>RKrj^ z43eErZ{GcSJ+urjMVf&qK~gg3ju}{o9)qASy#0^8*2n%tz6l-=L_f!{JV{yGf91?w zpA*_(L@lS?W1%vzLnV!=*Rs{V1qBpR1z0133=Md!q9Rj>1%gY63Ft~L8nRJNdclgo z3I;b+BvNgnGYAnL)=66FI%-xwF#ci=Js20+{*DcdPL}ce;$oxTu9U7tl9LNUCBJn_ zYGKQD-3=uHmi@@sBq!L9HjcTLe;<4YeJmO0TRRahqWR`BF$;>{hj)-^)$yk z#wR-(Te;+>=@^e})nO0SKFC4O|6@@7uzeFpr_h#zR$8PC`_N3z$8ZUqZFdNc4sp4h z5U^VqMGUQX=gjm$mH3M8MT=Y${6h=Sa89NMgaLQ1eSGhDiCe%2vJf+sacF4e9*XG%56DeeXtu7|CE_%xz8A!i7}|6IL`sBECAV)FjAMHmPEw z$tlj7=tW=Sc4^CAUo_?2e>(E^s$2C<$fAnAbH1`O`wS_b5lkA@clzTg7t^{`FQmgI zS3538(g~})q{Vs@sajX^fnCT~L1k+9YMzy$RfTnT)>>-nS?cyKgy&|~{^k7sxg96a z7-)6q7Pc{bt@!B_Z8)0R_O5|6~WQ4jw zZnmhT)K=Y>4p(bg)4t3rY++v>XUAx>MJU6CSmYACxEHy(f;N?5v%su%OIWSLVsP89 z;P%cdc8{asbabD5e;w*uOM@YkM07_cv#@`1Y2UN&?VGN?GoxE4Ee{z(vc{&op_A0DB zsI_)8>d`BLiX+5ue($ou1oYds23c;~;z!sOO1t~+h^W@He@zZ+UPDA!qura63M&qq zqJxcY?}qMuewH$JLm>vjIt!!U3zPbUCex2|wJof7T4S2;l-g9L1*T^v!cLGJyQ@Vy zbvP~);Cz^-lo_{h!WhTo*9;xY$!3H$TOk}rKl$R-EKK^_^LO8f6sr4Ib18#6$K`bCILm+V>cEHdA&>txYxEuI z&jja6-L+DH)o?q4yLP-`Ls?N@?HnyOcwbf>FIb^Q>cXt4)a$zEH#YZ9)>f4|um z8{0T(fA<5Rd3|Q)nPG8N?#m!ZG0B+3P-)2%eXoxts`$hBG6)3AQI#w~_#-PG)}O!s zwf-uL1eGczsVmh|+!U2aR~pO9uKe?3f~Dq#SpO*wEaT}%xvO#%x>1}tXvq>?$n}cv z1j~AA^W#$?G(PH{rUk7d|5iMlOV;0TixNeGf9E>Y6Rnax=FADdpg_rVQ~$OSi75gS zs-F-Avx|!WF5rtSs#1ZZXuyRoV8b+pQLs6ZX;$R|s2ded$=KL`REoNyAZ3~XS5Qiv zP$?Qy1!Hv&xb8MOkJTEge15?llgP#G=v$dLc0oNsyEC*3#*%Q^f_z*$P9+xo6xmfZ4 z(AzcUdT(3v5+}Uf%zl^ECgaJe)%W*FA&9M2qC;nRGHS*OBiELwZ*fKN8dwlp$j)dC zKO5uO46bvwD<;IjLLxBg)=_aa=MM3te<+CuB8{j$g;IQz;e=47+#rl3rnC)AXp-gB z8Lm3Qtl05{WiH04TzY&9;Yjbfnk;LCZ(@fL-oAyNY7xWxHfZx~W9{5u>TUS$Z!UOV z<(?VJgvu+WVS}(EMrf22h6#8d!HyqL%;6nOd&%iO)G40>_c=JM4Hs$XHV8&sf0UIT z&!IUM*5y=yL|sW?(KjZpA5ram*-my&z-B)eH0B7*HWLXA*ZK_fxdt2}aF^%FQUeYJ zPnWL}vUGb9HnCjB2wKO=@X`LD@*BHe`BV;EAD9FtB|9z%3t`_>TcUKG+Pqp6!|mN^ z3ZtZw#C-j)Jp+z2E$yDETC-)Df5MhZx#`p{jpAX?GbBEmS|&?Nrf}Tn+sKh925;t3 zge`uwlU!ZJ-et0MB4gPx-O|1>3K{y)Oxf7|#5U@|mt+hk%N^=^d))H(Lz`z->`l{- zp{PUMbeS%PZCkyit2AKsJPgCbHyhr`_Y$aq>k!x1;pxf!1%;j+V_3%hf0cb9Y!lk^ z%HX-Zd(GNbt?ZIe%}0(|YM0h*Pv}P-!E`#U!3@mdEPEY~vb+78&sX37`T8py7K`Ja zLUU`{zQ4$8p1T9Xlda#t{5t6e7xFyF?@ND|egnWfnAf&U488kT@Q{NXq$zq`nz+cY?Xm$wvRhjO zicHtSY{`)1re2W$KFW6d)#M~RK9Y}*bRMH3ErK9Mk#U2}IwOTUxT-+Aeh61Vpm>h9 z-~!=$rcW>5{``FTZL~mZwV`ln2Z60FRlIjttj4&1eAUX~hnqwOf2BtFPME;Hq{b#_$I9*EioJ`*b~Q3ZQ+!n^5i;=3cYC~T}r9eH)ygCKE}c&A@@Nd6{l{< zW393ZXbINBubStpe|GkO%!>?jR3xSYgL44%E6QUgML*QxAhe=Imcp@`Fd+2~!pvY| z7d^qqckU3P#yFU@ClSLMRGDQBGlcUcxY@O6RI$!$YCt9~V6c3ciRKZ0>333BJ9j#0 z8SwPZ4RB+4^+=oD!0cGB#v68}U7p%5J)sxFH&H$ zX5r+@kvoxw13|+AQM7Iucbf)c;cCQ`2^DJ@m=~^M;k20lc^{-Iah!Y!#$Eeq=+%`K z^p(*8ExLHP8t3&>wHb8LEUc%aF>lFf-F$wfR-QAJbwgk!F^eHFItQlk1pX6bGnYzx zx9LtNiU!t!f2ZwR*A}o`F59+YIBG}M(&=w2<{3>vf2!>mQ?5u$^_M#LUJQgzkMt;2 z%&rG6RZ;p&?EbYTmuS$HM%Ai2Ni)*d!aTRe1{sWCvO>g2b5WVv&=77{t zB?Yb&=*Mnbt+d*$mL8ERlMIQa#I|e)%2xgFJB~vje`#qq2NK3_KK$OyOs`a?dc6eW zoM{Y<)jYP(cBjzH#)HdVPp|@wVll#fF1O3Or=QD5En_rBYC0~>(ZQ`OMY6D{F5C9I zml&1hQY?Rn4a<3QqtmiLVVi@K4vRR$f_=v|7u*?sNqg_Iobq%Z-=whkVml`fT9)c| z_px>Pf5P8=Z|uGHfS%#`dG&^Kc*+n0E>vkl&}d}7!35ahP9ezB(&+$5WeNy3;|2`r z1-1U>0)C5p2P-a;U;qXwA-9(V#C?)dtQ`NKf0)h4P4f*p46L;*91hl88w)FD~tJL!CvOjuOct_Uu*|2S2>SiU5eOU z6`r4CDX5#v*ajYW0BK~2bl0p^g?{Qk!jnj<;3zZIJ06Wj9zKBA#%(x+>w={+;;E1t ze}R#rJHyR{`@WB)BDqEK9}b0*#_&~+5nUvydOy^d5cN!0vK2%PH&QgA_!@$~Q#6_% z3Z26ExIXvTOv^0@+`_4049;#{05C2>Q93mdsEbHEP3}y^y{;x|?etI41FMbw&?t5&*bzW;+kUHrb_M&(+oK`YGU zRG3P$uVRI*LL2?wdj9~8RoiacI1qi;SIh!ND+iL@zS@?PcF`>gEU-o0x26baX=D?X zNP(o1c)R)c9bP0$z7*v{qRb3uf94F&nXGP`eG^3m<`q*IYomB>9?YRZoxPndqe!qC zb;ELmzbg53|KaQ3_n(!_QEREl-Rgnky=+CXG1x4}_7BfFHik=a|4BTuiWl$HuB}m+ z-f?!pD3%+k?l*iVSassIAAd?=@Y$Sr2Ca?kU*yxdMW2{9`5tTLjUQ28ZsRP%okf^$Z(^Qhzm z6BM#Sis}IL8d}498^Oh{M+LlYDzuZ+&>N$l5zui}?YV)whACFtf~&U))a-c;6I(L) z`!KV2ja_?`5I1+fn|4c(e~(}v9&#y&E^TgNA9xI+!oFbQJX84DN6hDNSF@c=>0PBl zUj#0ISqO$ujpM8u*4@m*q1-$ zL#TD(LIPfh|B1G$5_punSpSk9jb~@v=kgU37-$zJx&I*eecTCrf&+JtOnKd{s2A#e z+my)~ zOA0o7A_Y+*1abo@IN>s%!ZO7St5N&JnJzICk}{|+xj-zm%UM#JJ~8bInocQIZL`x~ z&dn7OlG-{VYz22g8ITrn0P$(hDug)%|Ypyr+pCt~Nr-R1rp?k=vu{boywCnJ+{lU|J`yNo7WU|L@ z2DhB!5Ilu-Hd5||ye@aXZ^aKvJly(SlEiL;%km%3&MAkI95`0RaV)n^S&Id|n>JW< zqew#4DJ-1oe{ImwH=E6Z`vT4mYhNpjT)kIV}FjLZX;+R1HthK|C1`x!c}TziM$Ki~Q<(f^%Q zOK;ma5WeeI%)vmVz_B-bjFY(SqAiMjU{Uwh6ag)be=Ncjsgjf(Z;}7LLsIWJIg~JL zdFJEHH&5NHtD=gc3{$~0#>Q%%+6Q~8(A-`nt08;jLyEdTJBVr99K_n+l~37);vyShYaJH_OJd-y|1i;s4q8TcN_zo_GL z$^941e^H~P8_$(f(IzdhWI^}|C2D572=iK|jwYlOVMD2tmF$sV%ZrN$F5pkZ%786M z&$Y2I6TIXWH2H(=31%8|1IL031Sdw8nK>Bc{zyEahC+$VK&dp66(+$RIpuz6rV_OQ zCDFOtGMg3)*eGp-S3~83BRj$0NH$JR(WMMBe}(4Sxk54)@ZKUL2HHZd1SJDAN0dSE zcvQ8><^)ysuJCB*_Q-7k_@ib5_IM(?>0COL6l6;_^e)q4K z0!AYTQjS+AankIzMX|+R>Dy)z(9+l@N|6FdC2@=V_Z=RRB}I0Y54J?jJ>MLc*VU$) zObW~e)0h~md2S!3q0VwJh!| zRu_Z&I{%KA%XNG*Z+ySof3OM%G#{UHtSndZ{)>EMf)^k3x-L=L_QPI=yL^Ks`xRGQ za(D5&vY(u#`#9ahFG^Z`wu3L9wW_Pz?f7jp{=<5$am_~LHgxfS%*!6hZ#dM{iG1(= zZ}l{cX>dARenyF!S)Z`ee<+EO6e`rfWv)u1 zfD$b$m}NjloRH|#3B{QSAV3)d(V&ZMxgJe{ z={h{5dnsdKlJ@YhpOS3t*hrq8pPiir@)`VW*-lU4retfCfAO_c8i5fewuYNI59OOF zLJ@0HaFC&_lrelMFe8@>U&5)zg7U|trMr@X$c>V%D87PZ>hO>)c7|TUdDlL7?1s_^ z5}#mSPf3n$eeR8uP}U9$2!ugOw03}yaF)WFU?b;n1Sc@mN*%OO_A&{-uOQ&9Fz{xV zItT|3@*o1Hf4*8~b7=dqXW98a_274)B-ag!RTHfSCaoV442S#*!m>pJ^e+78b2TD6 zm=}w|9gViu(p%G-oCLXPUw*cTRe!NBnxUZDj(6!=BNdekainQUquK%O!7x{$PbDo+ zkeotiX23KL50rtHZkPeKYltxqucpT<2zP^yCASt`e-2kn80-Yo>g@pLD=H^OAWpok zz^KZbrai2PK6%^P9SiY}QOEeh%_Gy`)(091v59;snlKK}j^N4*CUl@pI>UcHrw*~8 znykBCkBD#rdRWaC&dH?J(8XDgzsZ0PVw4dvd==XDD4#pmz5Hd1R#c-lZ86Z6PK5t# zuh98Ef1$o4-j~XBTyt?h*y!6#jjPCyWdPLhq z&S;Tnw+@_xRN%W8O{c=W_}DwhyNJ^M;g%#fe^b=TuMfVJ(=NpFye?}I7MGzesjL%4 zY;j@nVPrJ#AoS^sv^5(GRDxbM6jov}q2F5tZejNt3tX{U&>(-}c5~8G<)-4hHo))S z_d)+Ig1+-10xMf^^I51R6Ul5WcOet5g}MHjj8|JnRnx=MLzJ!VU4lvaxNvuz`etcP zfByM*HZJ_NDV>cnTjYZBN4w(xWj^G`h>$@i+hOnp{K_nbjeFSHa)C@IBRj>*f&U488kT@DQL*<}}?kU+X$_!+>EemL3BXip?a#Y)O;kq}i7LKFUg5f3>R)ts(M} zkB?88eo$K#1PR6|(-<17d2Ao;L7|zwfA3F%K(GvrVll$!RPL9z58syeTE=LM)D+H5 zC2%8ikt{5#N&WuzDMn?v6w9w-$5Nhr)SEm*Vaq@ZU^R=a)XN3m2$nX&?&Fgb7N2Y* zQlVD6{~`CLakYrIm@$9(1qEtmi-|^qK>!0-{N&1j-6E{HHWt2vrW%(N8U<@kf1E%g zOQc8-K++ilck8u5TM_`CsTAFi2FlCePXKg^7VZq-S~1Ns;KEL?BFNa&9D1^-bjm0b z?bZ>1mlQnZjf(#&U!^>TbuMBTgU82M3fgTR+t4RICsFHj%czL;;ZK<}8o_nOHgZU7 zkQ#x};0MFan0p#SsYp1HyaA9Ye`yR~r8p!m33t3AjR`r12}^ewDZ$No5ITGfVb5;4 z8O}XDn8H<+oI8aoAaMVpFyV#Y3}iX2afPs<#aYw@WddkX_$#MvS_!m(4d0;{!v$PI ztu?)bbH`)g|8@$!;vxyXv!KU?%58rP<+CUt&-^voT#JHync^po&frP4e_7i$rEjOS z#R#0s$v@5~P4}F7bpRspZ|twg(=>ve<6o^r~K?0dcz76HziQz3Ua^YDN=h^a5yiF6ZV^(NpHB` zFB4aUG|fR ziI%E`?sqV44%dMEpJ9D#FA_AxqaudhzaG{hO;PilO#b(eaXel;f85=76|Tr_(EZp{ z^E>Lh(|jY(re$QWVlaLx{7~3lp)^+NpN|RQNsxRwQ zndAUV#*SX--D?%2F-p^MW@-mFDwE0FVmdkXe^HVWGcIl8;PxfP)N&Ce8+Moifcfz_e!jtK;Nn(5ta4 zf-8(&Q&Iz6GcV#sIhSl9cnr%-#_kNBpYz07Y{NY87^IOUN{W3>=Y#^W|MffafIj@G zfJ>$Q*us-oe`e~~dc5y`1lJq3QbSSz!GY1B_lBD>O;j1f7XpWbPWZ8x!uS%xceTtk zU}Kq#Q7w;m)T-yqPYfjPI)@fs-18I#-SLSoHkq-oK%fe46VENu1?^_N)*(3kIs|7g zV!>q+=30dwmuY7EW2n~FLymoDw3(K^fhr{I*)=y&e+iz{i?tP2ZNe2%j==5B%!{+7 zuA!5o{GtX0M7Z%@-rAa^)2xs4cpeiu<7UtGGt{yEPX`B6Hy3%wJ&G zZ|Q14|tq#miG{}T#X`^m(86%m67p#KswrU6iLxhLqqO9tH9~B z*q!ls{_x}e+@%$gH0a)idhDc4H{a3MIp*mkC2dw%n@ss89fE(wSxavlHxRz-S4;t+ zStXL(TxCm6(l|XdXbYDn$`~Mj%dR=P7z=3^h7`d--w%FX3%f<$^1CGiD#?7Dc_1M zj8T9*IO;R=x2o5ZjcuhZG2}PafmS+NApGSi#tdS?Nu?b^QRJEQgAYg`J`5KOw3(OcIe`fH)f|l-> ziT^TNm9@6=N%Rp#D(mSa#5#;A;-(P66^v8+1$7K`|3=41vrUOsPj`?Q@xT;vFrDru zk&H;r2AFmrinQEQ8kl>4e^6#Mj2utdQb?=?DzH`v;TFrfxSBr7K~S%jD*6X-lHpf8&MW%>$D?^l(BD zNIlrfvee|!!kCm{vO2ktbGGpc#5XYc;BPZqxo=57b3G9BR6xTk#ie#v&ypZ|fXg67 zzlXpyptCnvV`BCfR5D&f?1V9kg+0$&BUnxip4(g(%Zza9Mi_-bsx(9Paud~yRuEpc z7+PBk7%G)r5cJm~e+>ycRT~(_)br7`+zlOLf)=5jQ+6u~T~ zqIiG}6FK@ZFY65J;|vf%^gA>c81zOEA*5L>X!$)?DL0Wuf57m#6Nq;<<^4IBMu=mu z5mIS`ZWss6Lcp^*{7S``b{dSUnBHLkY$eO^J_>JD=o}rs<|)HK_D3KTNtWt>TR(HU ztg6=vf7co>Y|M$khzYwFitrLl2+ZL#0VOJxet|vvf~4yb&$Nl+<%KP>^rt^SNWfI^YedC`BCT#{?#DlF6N^;ApFEg{3O&?w9(`7$AT4%KjFz zF|A8`3li~>&)+O(SJdt^iYNvfnh|EEh3quqCeoU6?gBnob&BCtD_7t#F8G5e>yR&q zEp@IjmAEZ2CRgYvTLcwk0vi`BLVJX6A7Y{0I`}fP$py9tQ?QNs>GI0_49R~t<4gm0 zy%BS$qmE`K+@?Rxo@q+PjqZPqk8Nw-! zzp4XN@vt>DKA|N%Vjk6SVqUg}#iTKZ%dWWSo2C^xZ1ZaP<83Pf_iumhqSfHQQo7kC z+Vm0j&c;u7KQuokQrroxM#ipqz8E}!#+Qsg;pPwL;J#ltCH%sxSHu0iGVo-w$oBWj zNt;FiGt}S*c7%_Pc0)+wY<6RX-_faNfKv0K5fEXA z_>B8&Om&{kdv@$wDvqP?960x=zW=@#QzvPyw{Cv88*&&fpJIA_2df^->o&`f&s}Un z|2&lV3SLue!o@N=hgSNLI%FA4+TaYEpcq*%Ic?7e zL=FMKz|CC+9s7s9XuJOa7L^x^^fNaY@_nTb=iy;xg37B$E(rks;w3L@2 z(ik2H9aS>EVbnk4mq*eVCV&4x7-*eBzv(ghdpk7=JL#RW=we%^IJ86W=FUHcVG7># zgt?G+Sc^$C;DTc>D8^vUIL-5g`Ll?)%;OC*rA(prhQ4#k-Q*N1%l>1nP1Tm3;mzZD z^bdtoJx{|h5Z(PNZph$Ntt!^06a)em21FT=D%ZKT7Kv@yj!LQe-+ysp*Mxx749U~o zyN~zm%y0Bg6H+3tm_cft5!|iZL8HCC$_qjytI=x45gseGe}8y;et$8FqqWNTbYpvo zJJrZ?=};Ggc*8%?3Av5vLfWIHGtA-kaDizD`4-$O>F{$nqqp;~_^a9vn=JVbYZih} zDA8}yN!m)E7jpE38pE3n@sB1pK3$btO1#8p)kd5>_j&q_?`^j&_6| z$sjA0tPb$U3&?Cl;|oO=vULD~nZxl!Iy4=PLhT4{H8ZUKQ8;g{SU_g{CvpuSOj_ps6Nw9z*YpAmah#v!C8ww_{ScQC=M10nOY_*ni35?7?IaB#JMjv2$cZ z=`B?mwndufz>+0-uXpn2@?0v%BR8W+01tLh34b)h{?h!&+v1L zRDUAj{jXPRAxj#r9b`i4rZpt}OanvWS+r{;N-$@9E-vD*6Zr;(RZDN%Fbux?SMZR7 z9VE+kZQ5+utA86-3`0}w6d;ggCKf77h9oyLiv0IcmSekavgu-){KUsc(!PFQ=4BLR z$R#rvTW17!TUVE8Z{8)#C{nCITQZLDRqDg$%fsE~m(d)p)rQQK9T-09N@Z(@<#MF2 z_#--@_N`?9V_)a2#EY13%;sn=ntxz@YjjnT{4dOJCVwluoXAh+#1ozk<%LgLIsD^B zmH{y@^!N0<#~m6}{8dacj#X=(W5I&*78M%iIVM4e-ICT-MhW81dfv2EM7osM(I9dvBlwr$(C?R0SR9K7d4 z{eh}c+LWasKlAPo=p-z!B6zn8V!}2~o|$5SvAxI8Y4& zNY6Nr!{ej2Ebg&mhlISE#~lW43HLSCytmbhHA) z3GyW{NnNb1ZboCR1>V9SrNbof@;V6a0f&A@Cpc0DoR}<1!e@QS?t!8YM|9J#bOUHp zk<6NhTor?=nXUiYO+_|@qy(h4cA)YCW(=9!nD&GutG#xjT288$$GW!yn!Eed2d}(W z{XO=bjZP{Wvujclo#H2R)xZNkBz6y%=4>B-eXLoX^Ue_4&x46~VxDRa&4J^&iscJkSjK-MD7qnRzoV?vL#JiAZLN5ogPNTdMPD;zJ|vaUUq{Hs zhsHp7g(Cxmvw>T9Be}chyB8lFBrMf6qjh+u6J<;raeZ5N^Y!BHh)RUboL*!5L`&=M z7uG+C#23~XA_ylDP*T&g7#KGIh9jqpZa{&d(RO>|KAHwk7sP771FeH3p5goJNa8*Euf=rp8!$%Fc|+jnIm>pr@bA+_~l z=Y_(r)|+=v6B92hgxl0)&iuuoQz$ulwM#4}Eq=H+0@;~n9|Ig|*h_$nR|WUNjM)b3 z+9Z)%TksI#9c8xhAHg8DWi(>vx#71UG3%&S)T(8oB|7uArj## zvqE0QUl5^^Or=Ia;R68XO!DeruehJ#8Io*N4s~u{i?rRCP0h^gqFP)w@<=a|tZm4^ zYeutn7PV2NNQb$cuwe?A&*HSDL26R7_A4<{{8S7oeU+9xbRZFT<}|DR@WYkLdmz)8 zcM8*8&1zgm2|ViC61=ElR*9;61v6?qN!B&cOn_ zp(0oqo={1-x+4xvCceaTw`sI(UF=&8)a)01w`7O@YbY-rMIHq*#lu46I1$a)e z7XQo{H=_7xStB#g7Zwrz~QvRImFajDU=djAGI(~IU-P9uwt>?G^cczd$U4X;wweRr)?9^p6@0q|mN|?pT z;q-Cw!(Iir<=?F}I>V zzK0Mjf&gb29rLp(IVh!G3~JCqL`)t|m&!=NOmcEctG=Oxe16a;|6koO!s5gMH)>Jd zXv>1E6gAMZ1?hHE50MNRatz>XN(mc_pkBF2HVos2qGAk!KVA)Ae-CgYw8pcb;oJA* z*QAwoKGfIZRP%omYg zd=Foxyl$Q1OgQ9(!UT$_s#bJw(9!jI zf8ozTLD?lNd*i=*aCHXZe`D!Q^ePMDCRS2 z4)mQc$6c*vi{rB0z92OXW?aW2_5<+|$u!(Yp34&KQVnAl-MNae5Ez5oy8hGu(lnIrm3Pkno5Z)7JN3_%2cXdhJ?i;J6~dJ=LTyuH zbS~c*l7Rs&$uLe`dyIZ?hYNBHq5?SK5^B(_{|_3RhXmLK+XBsR5~dtVAr!4S#TX_u z5%s$<1FJmQ+mncE#@MB+JTGbQM!BRk5n8}xpmTFk+E-L+bivaYRC54 z(?(mSn?bvj1(_l8>ugVjZeZV70fj*(xS%s5Dcy>XB}aHMLy+ zDscIEH;-Kq0z_{lc~8lX_x+a1Wx+4}yoPX^xxvz^Xh7WISMfH^!IdBiJ<6q?hrp$N z4q^vle>1mxIO?qV|}sN6}CZ>zkL}Ue*-lkh+Y+4`2De3I?&@ zVQ>9hMZ=hVtyBb1B--j_6$6NNKAo|ZG7&Ycc!A2Db0J zu7+DY8gI(v?IJg+^UFCqTMI`|RCR)A9eN8JV1kQRdTW}{&nH8m^RClrJ-4yW`-H0| zYu5U!a9K8Df0`}>U85RPH>drUWN}7!B54Y|i6!6Dq z3O+$U41!iQGq=D>875>zQ^lswB$7a|(t50n0Hb|!1j&pmG}iMz8;GCZ+^c$bA|0C$ z+F;2(LCR>WB-eYRO!m{=ZZMq-A+$jlK-&h*)GJnUz@na#iYsAzz1%?-=4a zz)n`*f@V|w++dHPeAuzx(;eTj9U}$36hAWa#r_IeP6g^5UJ&_3%bHf4rX#I8^;1 zaTDCC1yRCY;uNfaM0$jGx2OyJR?=;iUcF?G=A+OnyW0Lc*7mZIFFUh#-ZyM&B5^#D)S^ z`3%$U1T_t7fD)!?X&+b2kP5Qb+eC7L+NyGU>+}8i;eA;HXM&*&pK>KEqnRj** zzM5Gwfb+Nw>#*x})GM*IB~8o)r}3gg8*^q>4T-M~7V*%^Cm6Q$-Y?g1?aCzCFQP^^ zc?a5f;dUN1$|w?Rmtw`CzTjGEgfn#T{34P?{>dXMz!&tzuZh`y=j7ZH z2xkZ43+)&#Er10H7;%i6XdHtpq2jHMvJRm!heXQ_T=-kB)TOgmu4iYiDQWdR!ym4n zf6aZ2MSm1{Bp@Oj!ELq&Nvu79BNASwaq2GQ(#H~UKaBbD*(bpD&nt)>YV7f{kQ?fo z^iA>$!cJ+z9^@As;0L1OBWR3yr&v=oE3%aBRo>c!&a5>c4nIb7r;N0}lVR#vsOA!O zIqAXsn}8sr9XX$*Y))x!je1OmpY_nf{YVumNar42IuO&YM<5%shH%C^o?ZuYcG=?Q zmq&f5)y%@qXn)=vm6p~5apd}%gRT_}j*XdO5NT!Q93+%Dpz}}V{*-l>@EdtFNWay3 zk~+$Al@t|S%6$56N0Kg?FbP+aNU<)2myb+nxK{rinKCOjT>CokBboT0anKbod_L|F zHkvJNoWK_U-RWu&ST3Wy-gV8AD{~R_+_K);Xgu3FfTtoa|4Zrz&!|{kE5pg98PuBj zfDUHjOKn3rKw5d^V)qh33qv8s=1Ahf_I2)Kz1#-r>#d(ZKs1@{kb>dzzUF>S3W-uq z2c|31nN{JS11rvD8U6DEbw9t~ezn+%cs%-_h{w%>zA`GcZ|al-pMZ-)euu(7C24HPyCAkCJf=rUU9o0fI_HfE_pf%~)kt0e^hL9B&_A-w!kO zBsH|7ROsSg?CKAb3|HO4E)QI7(IjK+mNd!4KB(3&yav3yGX_j9>Q?D)q1_MY%01WJ ze_m%Il`HUdpbODc4xGSDUYimiY}cwGnw|tu`W)XdY4r1UQA&b4|H3e&0nJ;$6#`g4 zH^xrcK&+FFbCcp&$>2L*xmt}!g2X28-JXVp++PeL($8|a|jp;xa?#x?*>Y< zzUU2QE}61?H0QSLem&U7F&&mJV;exQEOY?&5w3F~sj4?jD{Y(LegHm;VP+W){-$ey zw@$sZoS~Qz*?Z9FVlm1oC4)6Fbu|YSJyTxXk@slZSn9K_e()aGm0%rS6IaR~j^zVg zReN#|h>(P|Bk6wUG-|01$FwNic7i0#+``oX6&+Hh`#VZP&<^FoAWLs}&H%v5fE6&^ z4s)7Orf#45UFUFTC=jWRvy0OPUcasQQfNnU#6j;Y{T2N~m0}?cEwMcpw~!uUhnyQw zPZQYbhxmkPuNzc>$UMb7hd$V|_TCUZN2KGd6LaC5WmfWvgQVoBFC^M8s5cEOHpcEsK=_KGi6D%Rud$QFL=a05dam+c@>9c6S;o-78QXk16Rvo!@Hx;E8z1hk(XSeRVBf(tmfU~C%%i%aH}e8#3m3gx%@U2c-p2Y4ir(O#!|? z?mSv@HMieDS#<@R$rz~Eg96XXE(Oq=;JniMRellos0`~wk*=^}(29f)kQ75w1Gcv9_acq1dPeM8AQ2mE;sae*I^ynKVKaBpR#;yAa~V7Fi^PrZ!`@ zyKI&#aoZyL-nzzMdIbnEE$eJXI6QG7MJ}hldG; zxXxZNba7yP7eE4Wfr@i>sh0~op1u?rtNB2Qdp%d--aY5hZ+^m;mX=6k)(R2hV-sah zyha>ovF%@;HH;%iq&c3Pxa(EcX2b(=CM!|U-4At*_tFW0+64HTtXEX579#Q3Py{%Y z@xa5(;o^vp&Y9v>NR9Y5aUOYmCk~vbO4N~;58FQvlT`ozUok>F^2QZg z)RpeMzH+Xhiws;)o;o{lI+^6Sz2d(e8RMR_r$&_vXz@Va!R zjyeaJsePSyz6h|j0;OP*kKOy%``gE#3lm^vRP?(glyMq6jc@ z9hlgHv_fVCJagfn8=)~xbr_PHECrkapVZ%`ub5GZ14=w>-T|cKn4LU_uF+%MVPf8X z+3@Iar)eXJ^LGOwyP_;cAZCGBE7_ICv0U2Snm(#)>Wm(bYyu)t6G6%oev+CbFn@Bx zxG*aPAGk?k#zw+Vbh7^SdR3#yFt z2DHS_;m^jKM~CCJS~BthNRCCrn&81yYv+@i*pa{c#)6O<{5iW^P%4_Ud?i3EV9hLi z;F#Ynm+^w3%%_mII_!7oHX~$Y@b$JDUYOMv+5ondiR@N1u?zZ9hcnVVN-4#-!@maS z=y$uC^fi6Kj1sP=tYuiLkxuycdMJTXT2a-1JvR;5du)%^oCzzkudDv@@v|^X8|^RC za{yn(KKX(Fpr*7wCK+Jp8UTpEfp%13^aD-kqB0qhd9nz-aj*{_`?XjKVjr(D@8^ey zC%by7GK{DdY|OzmY`Li$U3F&nrTVK43`?GF_ojEwXhFZ|94_w(x<5Krw z;~GK|2c`~=Esu|*I{j?;0==I`&qawB9IYGWA?YLHbXNBDUn(s<~6oeKmK#2QQ@}U z)DCJNvzNoa&q*snzErW&A_rLk_E6?9>^JqA`a*82BEoX@T&t?a!|Wq*yEzYdg+ngVsk%`1#K!|<+ zqXLjcUsXdjFSy22kNf!eko06)RM17Bpuo@%P3us91nrm}PV>ho6i6PV>xKsIN~ak+ z{fJmveTd_{P2O1Dy?+a(rHC{7NqxG8C?6%u?>w}%l;TI!0(w}amG1F}R7QAg8U8*$ z?(oyRl!7SkZ;E;eZ&=J%lhMOeh$MM&aqt`3Y=wR zpQ+h>oJ7|znWrAEzk|}{gYnf_#cKXOWrhB%D{9qby3(c}5H$PZ*EyjFU zCi+k~0^;9JX8I2=lP-ks8)E4$RT&E|D)otv`QwSyRmM^ngw{e7 zA@w}SPn=ivnxK(9lTE?(8gab`v8(0N>IbQ|TGzzoQztrz%fO+$GRVfTLX^ksc6K>nlNAh&)2dUD*c6v)tNL zv&2bFX=2gZCc+kR~J%VGm|c#$S4H;h7X9Y@v0&(Kv{VDH+$MG!=HwT zfEt@EARhyPcwm(7>eQCad}~L`Mwd6$Z2p)I3Rt7)#^!9I zpt4gG`}e2$E3r~N*~Hq=)_tB^;hxWoqj~8IVT9bTG*dcs)jCn!A(aQqXYhrU?@WC; zig^1p2Fvl$8rva#K6o>z|nzfMn$l z+`p6_r!3{9xgtwYA0^N6M*iJ9o9=}wiKKo|*l+WAYV9$1m9Uu!0ZnWBU1U9P=@#6i z8$6?bFXf5qHe^#W&>->*+ud2QEr*!-YhDwD#BUL)@TB03sk`yOxvYsYx5OxQxr~{% z=|DIPP~=HerqHD<<(-$Z9K;A*ZmaUZ3+0hx8@l+ra1%0i_X z@GD8iiePfg)&60t23l~YW9+)-M1IJFFRr}qN6NR2%kKxIrKs^TY3YN&0C5tZQZ*0t zyq|UV*-NDMgf}cN>28e<{UYO%ej-?gZ?MwZt$=aV(FAm&a{F$m-9D_>bF=v}oOCm( z!2!gPKs{C{~KFP8viH}`$M6X7*{cGY_BKZ5T$8|#k>!xXH5}QzSP|k zsTRogwD5Gv&g^2pDSoG(*+B9(fK&Pa-Kw>&Ngdz%upAc#+Y_~vSEaAPlzVU%CG-4@ zm46qnA#D&Hdg3H9yye^OpMs0MFfpnTH9q;$xI*r~{#t z^4M@pB-X88fDrAk6+(WZj!j03UL2%Nelu-xc%2y{{hX=GXbj6Q>rDc;lGDJ!$ytTS zlwtxzs>xKOd~=gCTy zLXI1PF(`%sz#l>C#HGotuabY8q%?-t6l)8?qjw>3hQ^@KX@T6fLKvaXrhH)dND6I+ zn?-@pi|!K;N{f|TX8BMO*y0M&Xm1=j3^h-+t7kS_+q<)bcFl5O3m%J%R-vz4kiV&Y zkKxqKvhY#mhaW0D;xcs}1ir)k%}trQG$h^Pe&9t6fIF42$)TvlOAAR~ zrt01bExkTrS)EvD0rHt-01;MjAb`}{1`%MRSv`ZT+R?Mwk&CC<)X=~g%*6D~h z1e3RD!b6*8H~)$bSqHA*(vrbM_DU zcUD-NqmzjJ2~3q$-o;v?q|Q}gh>Ai0YCBkK8BY%FBF<(6UzE~NnR*nTu3ydMC3ynk z^nAZAb!$;)+~=xcdf2oL->2B*eK(F_MNlDKUt<2G&V_BgM(m~uLFz)$kgGhHjfD{N zgd}K(;6Fvvcq5xKKE+dqHf53eJEj@OlQmx$avFz8`_bIiWor}Lsa(TYZJ1Vnp78w7MSriB*g6EW(z-bS9kZ7@=eB5H08MI8BLBd&xl=m zq(qxV^0m)6!aW;U1kVl_g`IW+@=ghYG*c?dUdUi!k5mAQEN?dZeXhs9g*uK66G%}b zq7T&-BoMg5uJgT7^>&F`Ux6U2;9Rv|5Y~uO{#u5?UYPw}O)Zd!rT1uXBZ+#*n|xP~ z2F^3ELb^e`E-ovleSi2p`^8F-xW2*B6+q-Kv4N)<4Ah`;%r2G$fe=Ou5b&A19yf&E z42s2m*Gg|P&@>OJ`+7hUzG<`nDv841U30>4=bYbhti%CK0VJ~t~ zc$}aR96v>=sYo2WS9H7cHH>9v&SK(@Oft!Tk}hu7*u#01oO5DC)4m-Fx5{K(ahHFo zeLj{HD3AsjFsr8ML1)SVo-A;xKxv3<^KM0fl94 zidrQ4v*zxG`u&1Hm`o=v-ChwS7q{c{KyaR-=VBRO2t-jDsERw3=E*by@pyc4$t`8A z9biuddapHl@=wA2r&0C}Q^}^hXH^mKAr8NJ2lG{0zC0@dykg%G1gI?I{KCD-M_V$y z{tlEbKLC72Rl4c0g-&=uc)&)fnjhar=7rh}r1@d`my7BweS@BUibhtt-wXgw{teJu zn&!mS!9FhZuB=Asyy0y;gy84q6Azl{u*gV1Uj|4K1Gx-F%K}N0S5*AiLgNr2%Eb*C zM)Bjwp_Kr>iOQYJRY+l4zU>ijZ{L1KhS^}pr89hSyks?8XOVSIW;|tpOqY!EgpeUwM{mfCJPC|W~e;z zR{-?`e?MBO7&9PSZg2l~x*AuYzbVdjO}=#}!-O3y>DG9Dih?uVi;qDhavf`uhLz>A zb7eQqD$z{_T=?M9^%JQs)`CjSLAR5Mv0k>nIOAtPQd1AlyD2t3`7`VORYbP-*6-CnOkNa62n`kQ9%uddvgY9c2fX`X=KlHpqEOT8KPa&$eq}SZyxC{HfC+!}2w*U^E z1j;ekKYrop&-mX5!vj@Sc6OENSeu?Ef`Z`U_*InP`dB$m481kYT3_n%0n3Vo(RSEl z<_;_C=EcisxhhYlD3G4Qe0|^8VtEnUWoNC+A02A>&#|FQXNpE^g<6>068Ov|U4w0c zSDnx}r9U6HizmMz6nEXc!*zKi=R|{%K4CTY+jvJg+mT>Xa=J&|Kx=(GnlXj#@_HuOZM0|6p32gwt~qoh=c3R%aZx z|L#o8{3BrumQ=DjV*=du#lciKQq9f){@w&LIY)NK!t6J>*IOYMgj&~5PBFIIVmbGZoOOaM4;cgo)ggvY6lyo!`dg(0_=p=tFUKD3EJ;V ziz_~fWQb6_nC=}`>Rcryq@K=+saciCW}BlNLI%>VieP3P#s4_oq}?O&ffemAu*f^H z3_g}dY#6+>@(RG1)^62XHRn97cL12m3{!=3vme%; zMq&hMsg84~>^)0rzGxs7k3k2!1H#j<3%JgyNXcV?X$BAqsa(Q%HkhAxWK~(UWFd0e zqA_F4?|`U>$8WF%A<{p{BXc%%wwzYkwmk@_`bmubCoqzVEk1QS8wt(hgV*$b!pe;` zTVJM-$>vXo(E7=X)}psqofsd;BgFXm@8cey^z@dc;)zoxcYlWPt=`TZI9F3kwn=1w z2sKNapWbTWw*56>kHfV=tal0gmKTo)A;M0h^XtC)=TuOvrTel`lNO6c=r_XDABYS> z>Fa&;kg*VB6u5fX1s$U5<$mo&s*rxu93Z}w2hWcXE}ybABXp=E!ynB$xeCk_I9Ir^ z5rnR{u@%N{((6GST-7L&Zg?$&ySgKQV&xFDUnoMkqCap!<`t%=Q89-OODPc{PyzGq z6d5D2Mwu1O7D&HkHx9Wl8zn>+H==m|yLqg_9(Qg8)@MV`h4UiXDU5v!>6GyTV#fgknqFPPM$6MkhKFx8`^|3gQc@|J^`Yo$Ci(lTWK_`MT;grkX9B{zbBeB_OTmC5uGo-ncrbqS5P%Jt(;?*4(a|uI6 z$Hx@o->e)G9%*jY$j zM1L^i`1qdrX}J$1DX`jAy-SW{&$^ye`sU^zG`A50sNSKJsxDd!Y?*rwqTlBFcz@es zBvbr;iRxBn7r!SgVv2S|5HF$wV!ovHr^(Z<9PvY~B9{QS>O>_Jqso{7fIhfkg^;w3 z3MDBEzuc8;W}DoL0AsGwXPf(5?l*q1luxWeic1>$1tuOa#F%b%jtAb? zEc`;1B+4P%ZPr(Qx_Fzny%faPiHuvuB-7d>63F7J{$eFvF@syew3;mE%t3zli-hRK zDV{Wi452*%yO}iNZ7RVa080j=@JXT$1Ux0T1>souq#4E=+3srHc%;FD2e{Ml#br_^ znby3c=m@idp!gT$Yo8jwu zrO!2e!b(%JfIGnqgBS`qe_U60YybsbQWK|(>@;jDI~oy%H*JG@tA0jD1Gq72G00`s@~a}OMP0){ZN2`$Qo`nY zBl&Jj?Vv#K9`|J0&lJXwwOJ%baGkC4kSjlBU|FyPu_$%V-?C2J&3{6M^Ekp26EkkS zH;}P_WH)@e8cy+%)fZvHNl?Ys!2y-~!<2^O0}lE7g{ z2QT>w3R%>LWaQc5u+-zL#npCDVVY;eL;XmnD+$~ort#Rpi=Gr2G8y3H(nT-tNG7Y2 z7HQKIyw=J|2WI_LC0ICs#)-GH4$qpZ!Y5^zZ4?XDplRt36N7@Z9fk$E!?K=yc4d<{ z8x|4QnnvCW=t+|{f!`sYncv;HLa+`{j_%Ywq|p~=KBiu>e@!3*_g81q1ad~Q%S%bo z#^A&usd_N$16mriM~RT(mLOS9*a=Ey&hUP;AhryCdBIEE0%{bRE8MU0( zU#A_e8y!!VOc>yg{fe3E8-LgiwQDMLb;goT-$08GfD5BzO9NUKkikL@i){rqV~CtAzTdVOo=WDQgg)~FX+^tU$x8TUw}UqG|7^!y+q zlyt}k?CBn84vTOHC{Ch=h1ZvPd|!lnd~a;Dh-W%!_9~g3Q?SHnwj(jYg#WFvHAopeJP~YsaBc5hI78 z80%6gLlS8X-EP=(jV<|%8b>3w3<))PHr0Uu%;A)h1Z9EgJcu378_USf0CZWm7F%00 zufm9dLB&7e=$Dg^teyp)fCDwDjk^Y@y2QAX+rMyh#0$Nt|%wTcB9* z7rqc2HyAotWLwLNnOtI?oj-o>*}U_&2kGCIskLR}+g>*7x^x|xc^sWu4RaE4ZzpWP zL&6b+Q)%|AM7*pa7cujCMnJgKoTB=Igm-CTpW&=)B7${E6I*Wfn;jF@m60|coMf@O zk-cMT*LCbTbcc3u_egUOn)LyU?p0ZkYikry98ewXFtC#SKJfj_i~@)@dt(O2{j|_^ zVlisMq>%sFA4Z`VIa}ZKk!J1--sdC$ooQ3El-z)90bGf1avuM}rR0+0BQg@=Zp(xE zkTcyy*CUK6IbA>7debD$Cvzy8MnJh<1=%y(R8ep+a&dBFd;OCfWd^v7OP1+!d}StT zmN+!8?zcIPgwj}n4IT{gAVz>#h0@dcn293Sd;9y^r3=$;Th;lC{~{L2)Q?5jRi_^% z5K3sRI`W^%5GjO*O8*7(AuS{+L`8=<@o3lG>M`GTc(Nb|jFNt(y7b3_%tEu`0EF1J zQ`6iA3`BiHY_axCU&Hm@o|Fvk`83nF|uCsRDavHO_5eK;$>Iuv-f{_ z0fPNv1z&gD6wFa8ctDJ;iI*F^%yFZ$ff+=K+rL_WDryWa`UgqFo<84=r~_#r@i^`*`G7yy%bmj)@QW@PmLX-kwj2MF*%j(?}iA|zhTIkC~x|99NF~S7~{Q=~k zU%pvxhHaJ({vvWVOWKJWqPV~*}5k3W7>erz%=zJv?PPR+3XfHhI$DUfa~-FYNxIdRx{nf28XNbgk@2DOs;X3Uu-Te+CGhxup2><@Xq|4IXu( zYbvLdfD5fFq4AhB-@_~g49YAmN>~-Syede=`75qLyB~}yGpTvdrFoAb?Yp>|pw*V} z?QzTZ+QQ!?iEXUHrZZb(t;#RqzwEil-H>ahoqR4A& z6t=9=$j`XMa`jbAkZ*aCP#gE56k$|PloNM4!OUe& zFb}NDUE#p4ogpDVXV8H=2gUpe&|-_g3V^3F4xUUBj{F8zq}Ffz z_ww>oE~r&wTgm=hK29@t*$&T4yKLvUVy!3=SLdy~qsE0f96Ix>7QX(VPFP1W(-6Rh z#dM)A@n#FD>tEDw+Cj+zzHpqnCiFs}mOCD-6VV8b%S{^mTjs_FfkQZI=*wC-^bYsL z-#&jHfHGvHA!pHhQ|MN~rU-SCljFWW#^9?59w{szYE!?`yttlV%4mJWJ&c1?wZ@g= zcK%Wj&OhuurX5na7vW+dp;*xcrIKVcq7>>GoNYu%6!JxC`;6=aGAGJVribpGsrsv+ zJ_>`w8ahJyvjK#_e`u(>Xu}J~!iGDVYZNB}aENzueZ984ohyLmi>om+AXZCqir!ex z*zp_nQdm#VKGvpd(M}f#cuDh7C-nSfJlxOWeU=Dm1M~B<+rQ|Oy%qjtRsmOEKk6MdJF6yX>+2#R}7s@2_wEol@6c_-uDNXjcdVxVxsd!V`ljbe7r6ln2Lh z@iA7FRkDnbvnu&VtVCGlZm?iyus1rbwd3j0qm~0NG{^;4J&(B*76do7!ce>57$dXWF71L$3n`fYJ~FX%xx_TAy+Vx?`N zV-5F91KKb7Bl zo=_qd@J#14uav)dwC^w->%0oy4n1IO=rdt%j0Jk|MJ*P;)k7|bP&UhXM6_W}Tn zoxKE_d$(u1@i=Z9b#e>#GdU2235OZozF!+D;HNyzPa2l9O_X<0xc3(hd9j@PJo?91 zfrXl=HHl@ZF}9K55}1TzsABHIz&4*J^KhKW`Bh!q;e^X=z!&&J8TliXfalA}Bf}${ zd38E-oA&1|z0KQDdo>LRON>CFnoc@^-;Qkd)rYPp-&}pe@12ug&3MxDx4oGxkj+pH z&*d@1u2*c=X;G9Zo4l0hW?76ZJ3>fb6_O6_UG62$2&P zE1i`!qkX@z!-|$Wp{=@i$~Ey>6+TWu)H}=V(1BalZ$x{vwOl2HyVcUGn`+fb40KKR>n0`Sd(SQFU=#|L~O{z$s zw6&n5sDoV^hyy0BoxJ}9rvhGP#WS6MM2KIfkPfmEr?$Du<|bIbnw_2t|JXILgkFiB z)1&BS^4^>rr%(BrUJ%7z1#iK%Rlrb6Z7#)i{tWcr9vw-AbFdDm;Orv%--wLp1bPu& zVFL?k_LjgV)@4$u1oJ%Y9%hy~XHD~B(R?FzS_944Dm+13I^VItVF7ANQ$PAlxb7Ef zpIsoRfZri<3#@jOg>sf1#By5a&B$e_LkP2S-Y-SK&G91pqhEfuJKO(;F~!2y%l%D~ z4I6zVPvUOuDJt@bmPovdkh80JY;(4kH!vBC*$l9hx$lYQAY-DzV(QzcJGI3&nku5y zn`2Pt3)>Z+1~V+{UI7e5SwpVr2C4lJh<#9jtWf+y=DQ$ZiC9p71A6Q<*_Tdu6rHrSY;SR@LR~THtFfSk=hErsqBU+vFd|wX6 znCDnHg)QsczR7471aC?^O06XDHcaC(Sgj#=Y3Q3}ETdQqQvmc1u?6Ugs>h7D>%T6M ze8sWL6LyQD#Qc0e8pTDDAV`Lhsc!5z2sA_ItbBs5dL?rL7kih~{UQvKRQ}%*Dkl-u zC6QIjMLjpx{Ija7$c7Hze~@<&)BhmvTCo5^@{Z62wm;{FiarWH`z%i;YpU=j;4nk< z6w^8Y>W}ps9M_bcd2o~Tl~WuBB>Tj*Mz?JqGI#|!b^@l$2~6U5>7kN2g5 zCEXCY6a%~j5kdbEjci+#I(Sq_)Vb5PNwvT z*q!MimoDbfb|uY%XM}gO4VK)cMqG06#3~GZ9QcbSrt~jWS|1eXIMXB87d?%xDkfw- zrpQXPXUJzGAr*=~+*Hf=;vHgJ5+{Mg6ml{H5`_51HVn)0=~P!y*ol0Hs_O`Ph{6;A zg3W%QOA5Y8cDQtTf4=;DNeuwwGRyQZnk=X;M+40XB&fKikaTJ~6>D$~FIATh_rALv zlq+nefw(EtA|sh0epWk|NcCHfu7xLHHKfZV31`bTRWc%N)k&U!ohLF#QZp!~> z{ry72QP5vYsNR01C`M$CAk-MQeLI~*(X8D(Pcl@J!zSqCWjuy#I{Dmi_Jg2MGD~08 ztVlI_IV}uZhKv^0vnqC``z%d)n=X#l1i4yIbE@Xr{sET096e(m^_{B=#sPgO$aBXm zsJ#n`G`{Z%=LWIwCjffk0bR;dD}I9X{qn1~%wmT zKxa9liIHf*tA6P@XdW6y==mA3-Nvtg{T$y-Ma~BIr$c^IlNyBBF>HUzR=p+SL~JPO z*hA$6RnEJCz9cP7XuG-py&c!sd=!s>WyQvF)8!ez)5VchR?g=JBb}@%NjLa|12e@3$;pp%_5M%T!*s==}Er+fi9iD=$;_ZGNayy=H$y)-L+^+y= zneWx^g_xT*PICfTuwQD5S}e(|wuo#b^z0NjVXJa27+n`(hR8Hcy{is^Ev-*>iCY<@ z+Ew%c^L_J;`5Y+Ts@p<~%AaNa`{vwow6c5p#Bi)2SdG0+0Ovdj9#9d@)<41guBC>b zZe5?*wBgC_r@ih_40D?xpx9~9LehuX+By~9=OZkq;dO}9LGzC$%jW^RX^`TOdU^i~ zbwG;00Cb!2>E1??G_IS`SIP`xj|3DMgd6p~898p!YQhgG_{BPAj6BqZ^)Mlu)eMTe zh6&G`<`#;|gqOXGF_C|CGqBA4^HtVY(>psCB%_v~aDekGxhhC@IVyR4qWe4@w>p^% z^@x13<4&32UEKh4FcI;iDdb!LqoznbU+K2ag|n=-DOh5NmPp2)B?%2u{tFqyq7Qa7 zYH^i4R` zEXV3t{RM4N!A`?4487+ojMPIjbquZy#$kff1PH;2A`~*0MM|A0Ni_!Azmv3`C}lZV zw%>cUV_#m|jb&_&QVWN<4^GMO7Iqf>)j6LtMxsV43E`(vFk_V>p~0b88`3+7>+>F#rhZq1 zt;mC_t;QNDy8R3Vq@S~I2JzYET`T!Jkg!(o^1%uqv(bMRFxV($vUB(a447@bu4;M? zL*sh+bP=2&Ul~_F+dK;!<>OfsYtN33VX8ds6Ecc6wn@RLzN#QUX>m~GgCL2f>Q==E zwBab!p6-zCTc?-FjnZql>L}Ai8#<(%zns0!*}p$^^l@9b2EuKBt&TG))m^Y}q7$!x z1F;P`hl_vVoO`xsKdn|xZ`(K!z3W#@03YPQa=X`ftsSut0UO%z2!TH*d!N^<7m|QIzvcGQ(r*jL6()*HqkYe_3v#NU@UJ zie(&br9K^YpZ153l@q1-hnvHFEjeOpJF@P+JHvl6r_JG3NZx{JY)=G z-_|N~LMt>l{sN6JH(ELV-OVlSwZpZPubJ-oksGcup5JI$m&(q7Lp>q*pG^M!DkPLV zG2Th04txDoU?KE=&ip~=XRqD!N+P*?&WMRG*$`~H*ouYzXPF=WR`p9jZ_z8RKs=p!U)Z+OTGUa}YIjBX}rrfcQm zC2Y4_c>Dj8KsIe%QnRYs*@3d@`GmR?4mJW6Kfy5R6GSJj0D7@FCRo22ecVw|rn`dJ zB=wNVC9mkVaU*h$*q?Yo6E_rMw03_R@P}AcA!Lq@k*^En>+z|z5PXh!eET$~GibqI z7|DQ^QoHlu#}Byh1W^qP+n4{=>~JwOH!Ytby%nt2>lydUc{F-R>_XLiGqH>s*p^MP z+R~G>AE;51xY*$x%m5QYuHbQIexiw|EdQc|bLj;_Iz*D@97!mJ!ks3v_-ubguUB=Z zGT&_G_U$wWV*4F^?F}8HUJR>IzMGf6{PcAGPyniy^5-OpiuEdPrJtlib&+08gzh9M zld>J($0yRy@PpMMTK%uuVd=E{vl0)ZM4w4|60W#ouHE1*KEH0d-PMZ`&{o zz3W%JLk~`nw%B#uIuylr3c8`|ZUzR$W*T7C*Yvfe-2KW%u-93%jl~c|)Z@FE^N7q?j7i39h7Kq2M{o2e?12Zm_-R?2~e z4)alM__?fF#4D2vO?7FuuHLg&8re_K6%fH~3>(K(tGnU;&;YoQJOyG+R7Yq280bmE z#=8#NfxF@&!=~h?W;P$3CH<~2TM3+X$3S~GV;=mDuJvRpLw7aayFOno8q0rI{5NV+x2C7~E|^?is1j%I$d~8jXy4T?s>Puwhkn&QkPgE-h z9j`T$1Ye^pHXYomm4)R>!iq~0Ra`Ownqn&{Hb8wa20YFmOx!1b5}-BS+3`E@$7~r{AtljxSHIVC_8D%s`=pz`|k)>{dM>5GW=~ij1Td_oSDW%NETp z7!^ahQuhvh3F$$$cW9KhX%;1)GBB140UM5@G;pvF#}dM1;7+Tx@!>-UZa4norF1p- zyctNPymNm#olKsyOea}PFr7~JJNxMNMWb!C1lbDl$fAr#}WCx=n3rr%@L z8b6J|PREpnXdC#X)XYmembroY+Wb2)9k&B3i`F{R)&JD&w>&C7#zIy1+YA@_HbL;x z-DiK3W`36O@5%F*C;Z0s@iBVa-gneR=>Jf8-h1y`Vg5Phz`m_Il41JvY35sW^M-0} z_1@p>xC0qF>i{R%KP6AeU!_*tP9sMUefL)slC`msFUji=LkIya5&{H7JS?lIJyU~Q zw7W-r!SZJL_f%hIJRaM-51AL+(^Yk)c}3Z#Fe zSOZnd7`WoXqJC!Lt@m#a=$RfLhfg?$%Xiddr=)R9)Ub5M26wOvt=#JZ`epE*z@1&7 zUUABxa%REhD{yO|(pd1ESp+VvA}<7^oTffVrnOobSS^^X(U?>|$_CFv85jq@2t+na zs8@%eO1LMa8)~Axrr?hu?k@(==RALIVz5_@xI}3u38qH-gX+ST;A;z$$)sONo0@G8ev#S+;#P7^WE0@L9RJ;5n43u|Dg3fyJNeP`!)fItWdS#jeXXI)pyVV6K!1 z;bT+$Q>qXe2Hjklfj;+Nhb`;mLDtfP%#z6o#NS7=S)E4xY8F4or}=`5f=GWe7=HQn zE1aEybV77v`-hiJcnWvO%0C*d(-KN13{kv$`qA6}>!a6vO#!TS$v>U7*xKLF%~wPq zE5RTdqT&ds5Dh zFWn~dS*>flC3{17{(OD$IpUF4xsQ((QvO77uiCbny->UQI*->1xl(^$kcJPHfswlX zFpX7c`W2Nv7b<^??Q&9}F~KT1aPM3R#w9SpslmQIHCVElBaJ^8#5qjWhG%XUae4=H znEU(cdR`B+P8x)vaizJnL=qZUY1YvVBEaN_!f)c7+Z*EEe#QGS9=SP!?TyglFC})i zeb^ZV{g{s-%}QLs&Z>VJ_^r2p3dBS@BHx+{KDi&ygs#e)IncHXGvUiu`2M|)VO#5n z&OKOrLuJ{Z?J~i__ba8yj<)Foi@oD%YLwE7>&3`{Ml#hQl$m7!*FM1rB(6m!% zG`PLfdFNF>Ds2XBoFL1)GU4pTAzObEYLWcY)_}NTAcMgcouiOrz)^A<4!dPJ+0C!6 zLBwk{c3V|H*;c##Jyed(2$?n4>@s7If5O?g*Q@QL_aBW_!EO{e5WUY=)FBd+Xb8)7 z5)wkl?giKt6F`4Rkx;d}I&I;$Tef?KVd39-w!0@}g4mr)Pus3~^2$7rHUge2*>oH6-%)d3U2U7p#w3!NV}z|F(DRn2(>PysU&U$fqxL&8sQu#9GM~> z1#+7aXr;f({4j%`6fi6#DAl@vG}Sh*${iZAzP|WKYxdg-Y(m(Te(7u&I`M(JAw;q+ z5{I;cVmp6rbvJYwXn}Wyvyp8a7cwF1>|^QrxGgDhs%32xi@_mHf)knD}h=&qo=F+lc%?!{;;n97j^%mS+h<#mNoj6qC8Er&ct9js7K z`BOOO`cp`y)4=Oa_Qk(sV_;=x0p8>6+joC&=Stxh_p!_JzUL@pWE>ZXByDEo5t{_5WKap660@0M!!z%8-O zbMu?47(n-LN5wYjv(s%VWRqOkdsh!ierv0c!RByFfqiI|m*x9X+Ll{BikK~tE{lKc zk$mMPdu-E0|J?McxG;4U-;3g)2}0v8#4M6)(vf^km!M2~k>y*n84!j_fD*D>8oisi zUz6MD*cMvz@}Psl7j$v^My*a}-)BDnl~-AB+c*$@_pg{1Mk5E7vwd|Mrzz4Diw&}i zG`lZJ5zrDX6DyN0N!c;F`R_YJQip$4`KVq5QF9;P3_n~h=gVF%zK}!D;D`o#-dBJy4y7wP^v*WiD(E4|e?|VMun#+Xm`)5M@XTcp{TC>e_A;tG1 zFjl`3jFD}fRZ_3N-ae&OM4x9`EnMPJJ|40h&|7057~T8P1ALZRteEA{h!*r&8Du5N zx+dMF^A-9__qqUCQ!d{Rh%#y zjrv%6T5vOP+}><@`gSf%JR!+wNUdx#uKJj%k9#LR;?KZz; z=21s&I{R5AYcPhD5^2j3F@xxhOKsGo9W+Sjv2(4~&bVED8NIz~dXj%Id17J8fiISJ z^S0r4aHUip!r*iI=E7$c-o1mLjdH)=?>4QC0MQm5Jtw|`H2+=*jitd~SYokSl;qGz z1PBQkl`2d(L&(I6%Q2k5sKch=mX2;WkIQr`TgT-+#deNLgn<6P9PRCFC;S+KM?UDQ z!Y&Jo1%ce{!d^KnLi>Lnzn#}EoSmM+#}(7C5HCCpRB(D$5zG{}UNXmgq7A@MGl4x^ zOag5?YeCPWBm0Kxg2;=q0xtb)Tv{7XGLE4q@DulFoTC)Luc%3yBd*j_B9Ku zWm}D8WZ0Jenk%08A9rX`)NJgd;#J3hR5Yc!!>A>%3fC_E`$K~=PvK$Cu|M)+fz^#2i9y!fcM%3)x)}w!v(ADhAdRRXDwO+usxUC5Ci;4!s$T~el0f;_kz;OIw8=7^!SJV4Lp zOlCYC0|R0g#uuj>*6TT!4IW=bu*NQBIZgCUsexG7H0L9@a#DzA$}IMG(32{}E{OpN zeodCe1Dz$D0>`^N;r02w{Uw(8!6`B)3ial5&Sk%*MQepQJCL?4gj6ABc9+< zT5rdZV{9m(#|`c#b11*I0($&>KDcy`$7^BdS1Tr5hMn4YA|1F5-6|8z(-lMzin%Mr zPw@NN+vR_!d2~ow9~_t(E)U1g3opKF6W%>KhTHh>+k4xmZd49sM6qdDuzz#FuJN~x z2r(UtLapnyzy%mbx-DY;@zBx z>dOtO7(&N2wDhg}zOXfQ{1WSDm6vzCDLnnOp#kSFb%#gXuF3W>&{FC?RPId+yf7p$Uoe zoMij&)SJB^$)+`@)(%Wce)*O&AF4E4QWoa^#ENQ{=4$X^f1a%imh#PZnA8<1H%hWs z;IAUhYi2Qcom0GqS#m>ngz=Q8gbvd$`#(FemD1zCe5QX%#S35SXTsA*dVO_$L-J*@{YtWmexf;Lq|GZ9-lpGM zmJblUfxqWVvJ=W+e6?S8aRo>p(~OpN*etFI-`JF_p!MsPvXo?=ZDw*2q?@z5CdmU? z)3213aCAYIW+bWCB~t-izyHj^8&&`S5b&!M+yVhqlqGUPaP;p8!Lxs>?z1#OjFM%M zXM5C+RTL#M>Lou*9|@;ut^fi>L?eYucP)WMB*?f-9f6LbwInG1lcS^hFFHcMKN5!W zD$9Q8yHS)AcV$gQ(WbdWmm?I{DEbDoK4(u%qKFxyFDIZmU!y2pc2NXW`?SWfQB)Wo zcX@RDpolh+xW3yGsCOII9wl&0WJZwl|d+ zurq@7tq;5cp$+*)gL1~!w-l*@H;`XgojE*xMA(tN-N zTfAbzAV7cX%;NB-bQVI#F=;k1XVc$cw3*lPeP3mj+40cInzXhrqRJ?D| zt(+fswqHcg^jcynNh2`C9J`$ZCna0d?$+F{&a;1CGvT&eufcXo^4h|K&M#eJ)7$lG zl%-J903M`8KnD(Ysl)C^mGXyOj&FrX#n|pwdsV7V%5H2A($=Ij9BPAmRXeqd-#H&- zgwCJ1-DdY%V3$Q+Uw)8&C>@~}2&=M+5<$iN&}u3R9B$`(_v4n0t#1Ga?x{&fxc7U? zFxP)}o4faUxTtS%_&dfhV^mxGJ}aI;u&HWrGqOID93%g$s`PU)kj;Tlhm7B6cc78B z7g0s8ZGhG{EaRy!IVSBiMHzICPU7?IOIJ;Gqq5yhcJQ&qWNk#JMC;!f(`m&MyIFe) zTdah&;V+~A0KHUAZ{jczz2{fVp;7|^0oS(;9T~U=e+*dO+R3&bwT)AEpie=(xf{*LcOT96kQBp@M4=@U?8tl54W)AVli zm=YS{e}Mmx&p()nCnSvNlacfar!xSXH z$Wp?z&H2pknlo(D+`4f>v=rlbwSpPTe_DzOe}V0~`x1d3WFd+8fEjQ-ka)hPakg3~ znSO$jUi{UzPZz%tHwBHM*iBBX1uK*Q0FbNb;Yg z;8NJ&1=kAkdznQpS2~0##ZOL%lMmYGgszCv0^;PeYn{J)*Fx{mKm0HO1Zd#9ctNLbo@= zYv+3O^JwOLoK9}Wqxt9xU7!w^2ijnUBJw~e^a+yycGNrTz&xwmE-My=+HU^k0!3L6 zsHC};aWe7chQ=;ojCkCV41JmwjoKaQf7P>N7Pu92y!*Rx*M zrQ-b)r|!DkQ%h(;8{7@+A)UE(ZS)ZPp5WP7utrDzav{0(2f`3FYmridcATUc0ETX^ z9TgIfVn3=i_)BEvjrlI{0fGR$e?9CbAP!dD55WqTUJOL_Yq^_S=Vsf(`F!SF4d=s8 zv*BdqT*Du9F(}v0hu|QhKj09?>fV2-k09rxb2yj%0rotrE{R@sPF*dpx^*7K<+-~1 z!rSu?c>Dyzw(ER-g-=d=zFT!Z7M|MDX-ZE~N3?5f`|Cj}qF$!)6%| zJG~nDueD!-0iT8F@AzIvuerVlDzmF6S8YRIsr8!P!tNcemQGTrz2sr?3mPWU4>+M8 zIpLz(yKoR8-y>K-G+Ah8e^D^Nk0u8A(Zt}s{u7QTQLfLnqMAY+yrIfM@mXbfg$Q}} zUhlRHz~Tpk61TmKN@q`Ce2<$_6Ry~H6mNuf`OD?*fx3KGa$Z)``BYZW7?ee6EZra%4b^UY85oM*A!hjN*WCezt3&g9GWadx_&FCp;7qCd=(Ua+Dz+A4gnOqW>+q%e#%ms_Z*MZ z(G6z^6VuwEs3C;if8hF6kJ1E;z)*icD2=IQKtD?%>5l5p zJEdf0pf7*+2P*MJ_cYE9{?JA^vY^vk!^c4n@wlVfBcu5QLo~lY+Gbb4Gd*o z*xIIuZCkoWlZWdXP9bk#=nV`tz>pEofUZ$f9%pC9Z!3|4yfQZfiYeSVKV)k%AfgBA zptA!#Ur}FSuD4fB(xn80jx=5U%e(oPck%aiQ{ST}Z3QeAi~G>yckaXqb~%W~%wbvf>~p#*#ok>6}Tu zUc=1H=5;~?)4bB*gtFA3Wmm6;XfTaVFA_fpc8P?=G&QLVG=XD)4USwAFH!TFhL$D& zTpHN*e+P@q{hg#BU3iej6cA6YB1T>|Qm=gMRI1JjAVA_Qo(!uJ&0>7xR1A!Ni~Y#J zls6s4P}!>&Oje&zN85?-6i_C@ZC;9RI)u&=;KmtAgEL+_INO#EG^+U(NS<{Ka}J{b z6@?3kF`##x6)IVw#gm9(C9qIf90&|`%i31afA_9z%kQYA&FV`@V1Z1Wo6U>Rq;pK5 z)R-$c3aP$Enk@jYp3Vr5VxDzW-mIQjl3~6x=InSKpY!WM2#OPK(n2p1KOuo15kv~< zoON^+)mK@j3>@1ks=O8^Z+8%SWXcdAlsExsE)?_!Nt`sx=XsA45{05CxGj#zcH{w@ zf2EwFqo$BkmHF!nJx}1O5`Tfz?RU5jN}@FfES1#iq1jZ_k%E#`@_Qb%?hn}hx~mnF z*JVKt$>LSD<^Lo#Q`x-N(CFd_|1C~LhX$$`S19Qc2aFt}rR>1dzj9gAw%Hm$+%-S> zgTX+la zib@rW(E_hlV9E$b9%5ONP@e1;UvJIu+&^K20*AA@b>{C3G)rfNkZu0XiF^l!clZM@ z^O(z)b#S$H+<8i{KiK%`ddS5o#%Wx&EGZR;*ARxhGPLv60G*o2ezocK5F^3TwskKH z?S5_IRCdp;=hpuKx9Kezu@!%@Zo)7S-Tf7Zl);h6(6uz_P_0LY{M6wD^%{anKsdmff z#p`nJ&L>sXOf##r!!%}Co!w*x_?zOwwcC8KvcZ30@4Uc@b-nUNaw~t71g16HufA|^ zTqPHhmEh(u2Huzz+a4Q;sxGlYX$^!d`6b|@Zq}vXffc_SRvPM*L8R4g3a6XIA3OJ7 ztrUpN>5T7TtyFm;YUzB49B2?nJx!8r{e*_bF-+1F`sI$h2Z?)RJ~Y}!OURutoLwqM za=Au444Z<)9gMk3{Yrn&zvN0I;|0)elqB1rGf{XGoCaV9qL8^(6#19oTJ<1F<_y+* z8Yh`A4w{`^nY3OM%#ZCrF&qvs2@Zt9bweLqNh@U2v*5~x&?fldWVIU|NcC@=##3nZ ze4_2zP9ca1*-sJiHP$}3BJ@k^sZYgbPAT1>cy(Gb`SL0|KY1izo?3gtFy)&zot=OW6Qm76>+MRjx z_1>JlTNcYC$x)WVV(PqA($D;6iEi>bdz&O$ROpsMB782*`u5ZH#qFh8(?#v}kM>X8 z-qDpTuo9iaYYr3M;q?(ce@bs`1YguzdSx^SYsF^vfSVaUD(55Y_Iiu|@#^9>$A!|0 z&u0s3s!$2xog5!0a11|0S)&6^-I(agN91E`HWYse{Hf97vED#r)vq2y2z2W`;)^^Q7X! zG#Y{2U%7^w;0+nA&;rtH6R$?hHqlxX*bNe}39Zv^+T5kl_XHxO#H9}_y5t-=qgXa` z2B_nO$>C>BB+f~DE6o3L8AZ|m*FEGALCmRpybm-eW)dPVhk}#~Yg5x8D&?9cw1e37 zBkrmY?&!_YKa%a1TKDK18TE-Sb}#aNUoI85A6+YBc-Qvu^rc<1utrl}Nv-jp6~Md= znqkV*3Xfi{pXL^QZFOr)`82f+fmOm#(d{{TPJRQo&Q=*H0e>n&T|-E+v{R?3TM{AH zF~lm^mTf{&lz;Ex5SOG~>j9sA@7}$8c(GDP6$A%HYob|Xtmf1fwpYyL&v6z6f;7x1 zLK(c)vfI79zwI`%!$fO-U6ovr8Z;vZDe4}O(ip(hh9L_VRd5afS2~-y9cHjrM3V-H z)}&v!Z}Q3dCw~}ph-wL;W=;UmR%2+3;RN{-1nXQp5~XfenxBYeP_}|vE(H_?l>)h1 zYNIQ1f^zMAhbNbh;d}}HS!DZBbBe{p;^w8wGP)NO&%v;|bTwx$UNhTjF)+Jq0o}4IE_YwXHWS1Q>WB5SKONc^yw*>wtxG00-7ioh%%oT`wlBSk-8nK zu{Qg;PE%Mnq>>4*gw*IhK9$~ZGjI48J0$p0FwvlUzM@1Jp+}U3t&-)HHj0552yYHw zn>|V#C2a5K*}AGdtX42a`H1{;j)~LgRy1;YpD)2Tg^>0TbK^jS?JTZM5tm*?SKM?2`D1GLmN(1}WB2c|KIgVQ0~y0(1`h&5$3? z)UQB^AF7{W@jdGPVb3=tftuP$vL339Us7;rqUJ#u4OPXBPJc%pvXS^l8f@pqt2^kt z1qwKQj-(}AuI$Qw0k;cf8Q2DYZI3-q12GJS_xuVE4A+xN#ma}6$^`9lBNFoEd_Aj) z6D1B6Li~4fN7VtS(MT^o4SOO(JBWq-v(;L(mS>=7Fks2>A=#g?%^|2@K9&3d2H~W z^`B|ewo8T<-bz;3?K{vJ0#F9~O{F$ZW zf6UqHFA2IKe*gz(r6y^>p)4$!9fXkH!+;ICsts01?BU#l*b4}!ZeER6P&TAm6xM5H zDQu}x9Cw6{&2!A|lbK5wQ-~B6aRjLg&Cp($@sKoZhiL;y8+$3dtZt7}0mCzI<;X;ur zg0!Nn=f7`1@Zv+1WIK0Tw^3DMi3A#rM!(SL#*5SCe0gv%kx3dCGSX$ClJaA@UP^uZ zxK^8BhUdD+OZ_<2qeSY;09#-1_yndBuQ#HH(OMj79OO=@~XX}^gEH6|!Uz}Ac zoyg*OXRn`fmC=8@HNVV@lK$J${B>N$Zwf%2v5^z^prfId<@JSJ0@TLK^Dl{9mMYJ# z-)6UQswOXsS+$T^>0WH>@GhUJWP9t&WG)x+&w2S;7V0*>N#*7~GO5bExV|joQt479 z`cz*~+R#`%ryqwJnIRnty%s$)H^fHNoXSTKa zRb`WWwV@TQ{`r?>A+_G{7XNEJf0xIw;y{5y#tZY~eN`^2=K6g|h7TXUzs z$V?UtgMLp92Z*>R;`PTW({nX73)XlCl2ci#xK~MDWzFVZiZ9DrTkKgLBd~Ps-11m zzrY%zDiH%|zc$*UIEg`#=S?6aPhy~1tbh1bb(5;ZlltRF7$2roC1un#)JU+Jzw5$z zNFaHV_!*RQr4LWcTOgQiC=`ql1F`aHZStqS#aLu=6~2tzD9@V%IP7qUfGUkt!>ZSrbPxx>8V$25O@Hq; zm}cl`pHMq7L4MPs%t7pML8^jaJ{PgLFHC1Wi!yC zaB)qG!xN9n(a}*2k2WtfndhbJ8-FwyIpCuJ-=UE;{1mdRij0A7;-&wT#Y{fET&AiN zU}>~iD+wf+h?`LSRR(K+6PI8gG%R^3K1;cTb;?0=u3%W;i^T%yO{yANig$7+i3I{-F(0wrcgdH(`)Zp`9=Ky!1vVTkU6$a8G z14;pmTLn0e9EvLiTzex$0;&w55%3juMLeiu4Ez&kGs2e92K@kU4bn%O2K*L-iM+7G z1^r_DSBg}|x^x&6xJHVaFak{i8Toc5;*ML;;p9ZPumX z$~l49M!YvdD_f`0{~guJ=v8P^Vb zBY_8`Sc2Pv(5V;nLC((5DlgSirV7TCsl=6b_+F}of~|&?vTkI9p^gI)BLvDBC4PJz{~p7ZLX(jBcJ+QxVZ?aeRCXcnyPhO@2iu%*@MM zwm%Lwz&4pg;62)t=6cbgnxOjoljyNmF+{JJ!tugs zH7ew!g7LCyaeo6K0P@@S-dWUjyN%uf&~N0;C65NQDdW%3U|Qr0dYPh;4MfvR#t>+d zrY#xV?1Ph4v{qM5y590C5181v-O}t3*fkT23eZ8#NXU^rc6N30|8~qh#Gn4u8h_!1XsH^SAIbWrDMn9TwYV7R z3BoiZ9}Tw{AY9L$?4?x*XhW+g@B|tr46cBeKQh92ePR`UBi}!jTW01 zV{w>6>V7s0FnEy@Hc}*6O6v+;*Byj*L{^KveAs*eefwl#17BG!zK=s?0+}Jj_oeAo zVDmwUk$*_EiDh~gKE#5i8aNQRs8H||W;|gp8$EvGhcu`C>C-0+mYZLZ4IxBB=OzmQ zXyeBJ4ah5)`+2Og#%qHMc!xR~V9W|AfPb1$s?3={8u`9UKm!G_rGY2HeHMrDu8Bkd zaF^9;+NfpFPl@Ugvzm^jr{HNc9!hiCV2w`W zg^X&C1KOK0EZD=7Wg2Ih1VH>XGC}t77)fEC)!8bDk_|@n%kb{K;E z`+qUNMgT;-PBY-v7yIlIi`%e1MXog-TSUm4Vlc5z#z5rY(VWhHJ#Xt&SqncIG$f}JSXamDLK-$`VG%Jh?a*bgU-Pf{poRGRyCSNQMqQr7Oi$;+D^x3z)r*j(?|;woMd1Nb{KX0ydKF_C#*i^mZ!Nc_mhHMy3b5 zW6Yz(5CfQ{ThO1h-NJ2A?jrfq9QPNDR=3ED1QpH=E|=N`@2@Lc{$On=S&9n`5x z(el^xcfc%}Z+l7p8-`V%hJ&=PLf;%?Bi-?$j`E2gsb6vPgta{rcAdIs>fIFAkj%Q9 zRX0N#s)m!_!jwDiAsdvScp^q9(T|HrF&X!vGiw6m{We#q@S)31oP6%5R9=u;Ikf}$ zeqL@7-bR}J>$!F&#A&FsNq=n-;eUO}PU0C)OzprZ7s`|N;pKF?RX>h;(_kYsW-$cNTXz#)R z-=+J}`Jht`?8Xv3?rtlI_^zGbWzVi$%8AMIg3a)ZiyrV`0W+LSE%H^?7~)?eA=G3{ zde$SE*-TB(D!b>3x(I5s)?|C;=+V)U(jN&Y9}&S!WxKdz@tghrd%$2%pHd8h*mNr8 z#N<=?{MQj3;O14yv40B0=7|<7KpTJ_iWSCAmg*KZa}%W#jB%`mPGY-}LX1_$Fauzj5xXBW|z^3}|GK@}TaMZ%tCuRj>3Ak@4Jr58-)SdHEka zTyjKh9$>i_zGg=Z^2|RsF;OHCtS=@t9Si(19;b3z2Ew(CgntdmB1Gz8B3HK&(LlrY zwmcjj6KG7seNsSvs*$77ux?iNKZL7y56S58Z#;7J@z3{-vEYm-q1XgVU4rg&uoE_r zIzxq!*^_BWToI^f{O^pD{rDloLc;{l{v|eb)x--6cNUB_{*rtnOit= zbJEg&>{S-)H-DbP#OdiySxdiUx>_zd|D8yTz4yye`pJ@{5rMPhAR1V{--}TmJtdnX zwm~GgCu7V+iZ{ek+UV~_taltUu2IScknc^K4U^5|NyN2@cUaxSg;Bk^w$Lc3T;jeP zVvV+TDExVNLRn&wuP1Wz{uRxBD?Jv_sU5!TMp>7-uz#~#aCm~Q$azuZ#a}^lq&{5i z8p!Y^VbvI~+mq<0AQFK~7UP6V6E^$%*w@f8;{8D~2b?lJ?r2J_^@)_Yn_$$l2x^Wml3c27kBi>mlc}a!zuibQwb)=;x?X!K1Iz zre$}l>jf1M@KCUR^mimqd&a&;!H|K|(!^%8066#$#J2S*MSGu>U&1E99^DbkGctNn=zoa8oWJyn zuT#5#SKWKDy&r(AxSUthX(~;<2VG?Wtj6^`6d~60xUgZJu(}pStbpINiNgv#t_l@z zOEJl5OJ=!j`B+kX06?}Y>(ur+Px7jST-^cYw3sGY8g({oczAnlk;7Q~`PF|rjQ5$MJ(K*o#Ui4n4=zu-bKf~$KPdgXZW`2c z8BwUCTBkiz$;hXVvp8LUMLzL`_jFK;D6P00IiVXrf)cu0a7yxuYV2Tdq61GIfk`~E zMeKfXCGL%p-E9=w-CqXJ8oggp6Mw^*t9gZ{EHdprMtWP-vF4f_ZfxwR>1u!XkLcr~ zO)%BQL}|Vct_jS%j2r|o4i+>RFey$=N4#MO&1XMbfbpVg7z4s1cFZL)zze4VA`MIJ z8Xw!{O=IoBZ8~UoMC>-=iM?9R-c!`Rbk5%TR}Co8sJ8jD=BT^0r6Lrl`5rsNT_UyUy#Q^SF7;@f8`9dc1LPJK$R&ycefqc zap{s3@e8%)JB}ob6^qNO_aEpEmpHW%Nq=jSy>d*r+ALo{)ecr}T@=FgajHpZBHy5x zq;@ZaqDro5m5N2K>2`mc43y8UO!FmO?t|p9{ldDiWsC)2!Q~mSj)^Qv+_IZ{fy{2( zt&Uvex7ad)$-xdC*2iC5!|OGZWk>uN?*hQc@yJ4=O+8%_7slD~z8L5Qyt#^tEqf5$ zobGoW$7`h%0Q->ZIJPqniP$$1X7ZAQR^ef0Fyw|9SCbsBN7H{Nsi}t=q^$w+oiH?) zMz*l@-OTZ&NA6J(aU|bBsFi&m)p5!wu2z56CCob^=o<9TdOI67{1Z;0rmH{PJWuZU zDI4*TsH?WS`i<6}BTqs*y_MP~tHo&{>`Y&v#nV z?q!AEZaL|DM~#0QQC>*A$YBSN#%Ue~_%rODB5n;bpIv;yvLR4hgzV=y3&q2#n_3eBUhZS6^tl ziMOjINywfEcBS;qm@eX)5)LZj?tqAM}2SdG?cT5XDm*|28K7V zkpw~db1tBa;9=vcUFH1+0&X-zHSOe|iWWuy(+LAO|DVX9g=RmA@o$ zSUH&$(tn;je_J)`XV%v+KwLl!L#0F8lTTmlVm_K`3uuB;a&+x`bw$Pv`7k1KmTDcB zYV@^N+X>@>yB)#)jNZo+L)> z;?pPe#{n~h8N;W~lEl)juh9I?V%X;teY&VARD!5~e^j$l+tagaQWpX^tbc0;8$xlq zA&ik|(I)Jmx?YDg1t0TJcxAjBVU?*aaTYuOywI#DQ`FxVZ`yXpqDK{Jj{4NR=+rR7 z-mqh-s<3n$rvN0;zY}XP2*8C*R&%AJJw1%g*3vIL7+Sd;Z;x(*sf#%LgG3#s%1Iw9lj7zw)GKs5E9d`nw^@R6_i@9S#F8;{4s z;dtOTR9kTh0!3_{GNb99=Be<8qiM#dpdn3Kf8?b{qiN1!J3$mo!^`sfwdb-=4e}a4 zID(xtWs_eJq%M-K} z$9AYsD$i;IbXY86=1_$amhbfnS}LJA91vA^IPDghtY- zf9^A0muZO9p`M&sR%`~pKy?BUSSvd>q&L;IwW=-hU@MZsovqkNLNrx7)1fed9>SBI zn`{)0Tpek@3aptOO-0d-%LPeZwE(oV??G_2T+Y|`k5|_>^Y!)3 zVtMy)wY+YKe^YY1Qv(wncJ%RMq1ZiOjf6}47JiK*S%t8$ z;eu{4mwYx9&b)9}I;Ppl{CY~$5Mhp~zDrd@09CayOWHiil;z4p$OU>OJ0F+BJa@PB-6ccIgX&C%=d87h*L8Ge^(m@f4~lO z$$IdGMkgO}TDH-)3FF2-=K{PE$izmp*4|8;9?W&UFb9(a2W$eHaRC_t2@%OrfaRR^x7b^7`;ASI6Ind84kfl zGADa_AhN@E&Yy_UEF;l_K>Vj1w7`Cw9doU#&+SeTM4Ym~Vy|M%Jq`5DE-3Wr&q~DZ z{mLSTBp2kCGM)Ao^=lo)?X>M*3|dFg2fg(bMP2;veE-CDwU#h~OR+O~JYPlu3Qgk{0_nR4#`@XUh^aNPiC5OX#eP&3% zy2`itXtWY>%9RMTQAup>%rO`G^1JY2G|Ko+=$yxbU8nM}fG+`~g?8_6KD=GL`4o%X zBr;q4nyrO@Qet%*Z^e$6;}^s9d!8n%f2mEe6PX!aU=)vyR72y7AGwLQe3^}rqw^KWI$)5SY(lD(kk zhZg+C&31SO-;EfMrADxLpQT5ds*^&vFJ4PXkHtGFb9%DVKZ{H_+tK^F$YKm#rgN2K zW(~vZ1U$qbv9v~Rl~Y-=%Ts|7uSX0%-RParc#O!QOJdHln49K|WMzAaE zLN?Za_VXX6~cC&NVKXEu)M2UHOU zR=Ph3Pb?%8#M>hKc$@qO)qDB<_b*`h_?4OQiQNrJUEAaS)EgH3B!fbW=FJi!i?Pao>I}Yc)!U+pc zL9Kpa_R+({0ZW?f5|1krW-;5E&^_A(C{a8JLCaFima1g6_a3U8T^)2?U9snt`NzjZ zq${xkvic}^b(d)0=~O&Cj$T?p*_Hi?n)5-;zvt(y$Xx%mf~egKb)+Z-mk~~X(6n;N zptPaMGZ*K4!la!eSY>j}IP3>MFt)4Y6`yhu8&YFXQa1scK_)uQf_ltBn0lfbh=-t^ z1^X&ax!PFEw(N9u)ip%ZDXx-La@GceP6Cwj5MD!8zhnVj^;b4Wg<3nB)w1OR@s62xo3Ty#MXo zMzPJJHvgr7@MnN;@W=QP9%Kd{+xQqJ&u;l%Fe8CQDmc_*0GkZTEPZ`-y zd?bJSEql@zrUL@*ZM%xubIAh4kX9QDNHU!}Dp74X@y7F^+-EW`=9Ahs(|MwadC)1c z^^YyM14pVTqKN(pG8Iy-TX7p2Ix%ITVu2;8r{Z+hG_c?rviJe|O1)viu#>Lw$y)e z=;}LM0gkXJ1ua)h>Z0^;1f@CiwZSQdWr3#$e$;G7&H2g#kHUm@5TXEwu)Bm(t}!+E zh9@AJtsznZ&~=3;W*=lfXuDR?4q*J=LPiA+=R>L;7V>Q==rfLgf|W@I#|GTN74vSD zv=h^^?DnKo1?^4jLIZfWEm0Y4!Al!k2%6O7uvo87U>C;R57xTi*Ika^VD?;UGqnW- zL1Rk&I$(z2yBm@vib$4_krJ9&TJQsbE`asWZaZ)nRTsc^g*5;I*tW;8%d)TztfCD4 zOu}s`KA>7a>%~)lGzj?qn2Y|6&>ktZ0)PBD09lodQIqK$Do;?_>lA1?-hce*+A+{L zsPcm9a7s)GQ44C*24P{yOcd^9=~7#l3a))Z;OxeH2^LslaoF%Ag>)L)=AaT|1hmeX zt?UXn^!N}m0g2G%HH@NCBxVrdj`ZEYdROe{yj@tfjK~*$+HcZ0JBU}tBadq3rtC-W1fXGICR;AIvhfvDbb#Ft@|SM z_^1(BTt=oVn}|EHlUQshjTD_xVZRu3)c|!C4>5ygCr^;REJw^{PXE#N%a0UQL(nj5 zw>$XCvs2Y9g+piV8w8dZt!u$8O{k{3Q=o%3ggQKbE8@WqaRlpZbz+3daN2xzPt|Ve zAP(_10IaG-x^ADLJK7+w(CbB;s9~4p!tJ{s||e+zGsIyq^vH>Yuyblp~H?waquJ5rP= ziIUx9%lr^a$K(Cu-H%5)uTRreIvC7Z7}1P*LS{UaGr3KfIC8?Z zbMyB4{mt2&rjlhhZ>E0&LoTeLw_ie*N}j|w@8Si^GB%%ve=D}8CH=UY|Bgm{ewHos zHH&5U1ewuLCRrE#=A6oKMQ9BUkW!MK|#ECynw}jDX%GIi1r)?LLb` zRuIbf?_@vEe|a=#O(*+iWi@VGDzO!kt*uA*`1>TJ(ai;w{En&TT@yZ1x#}LlciCl& z#c*>OM_V;yv0h_2s=tLnH&dw7cv*bmzy-~+WMdTk&SI8Pl@98Ck;fqx69F!|oz3}T zaqJrSi*1E-U`r*J;EM z2gHEDr(M&5qBmY^^{PpB;b}@&mFZDONe%v1Bj`d27=}=*eMJS|?xk-22ZtDLVf zg5N0NQlXt7!>oE~aGq+JWGM9a35oM4YB1sS1agQ}`9+2cD|a<_ejD+yT9Vl;1bs5g zL+L37f2T;yQ!-59Z%{J1)u3%`L!9N~`Fgfb{w}5P1@WF)^G6err)iQ&;VFH-&5R$p zf^=6px;754NHecC4?hQ%%|8etSa!z*dH#bKA00g>s7?fA35LgGq&`0c$00%G3Uaub zDOXgI6^-XWAqOobhvY!6I7r8}VgX@?%R{orf0Feq6nEOGz!EnmbR%Zs=UGMa4i67~ z|L`Da$+iMD9;@o<<=&msTwJk~L8U`6d;XZ*CP}0it4zw6%(Iw4 zf8Mj2sG}DzG|vn2OTkk@>T5`!!iuWUBc&+V%m|@BBmk5v$kC_4D~}m zPC+mkMtsd>QQ85~n}S}P;#o(c+$KC9Tq})h_%~c_=ZcPNQz#lu46zpSTZFbL|BA~~ z#J?of7`L3k9y|xOmlhQlzChGUfJO9Lf9Vn!E>+)_D3Rn@$WTmcBQa7mi}t@?aA3#I zhl-<-V74|)vNEcWUk1@x<`tBwQg)eQjC-_M*$R4$7yj{}26Dy$jo{Bt^g=h$4OT-~ z3n7Zus;ol7z>CJ5qa#8|gisrhIFSmjpxjfI$?ceIxLhT7ba-DE+Zs~C4pm@* z*8mpi{@U>0kWu1N8xze(No}=SUQ@tm5<>7eG#6Nwqlrw;RMPssTeR;Nlf5Dfp)_^o z!GJn<1*9Ai6k8(UP^w3;PHm*df6x8EomEy{jwW_yn5cIke%W`_C78pbl3#;yklEsv zDg`Yr_9bPZ)ER^lu#^htL>URsE~G^QQ3+R&N(L*aFcsHKCMXMF$Et?B$6)G>{Nvfx z^}FkLmltHtpbO=yZUeGeageK;9pjZxLYM|iN=8KlxfXGo%p0YkdMFA_e{0KWV?tqM zU}D)=Fpyv%)N1Y8ZkwdI)%~a?w!~~-#U!H})w8-vOx0qku%{LqmX#-h?$Uxz5}GpA zz;suYeS+|+gNauiMZD7fPcJ`@CYlw&6?3Swsv1$V-Q9%+Cc%qfbh7{WBYD;?#5{&1 zI^SMEzV^+ueKlbXsxt7^f3EQ9Gx_$7*qmlODA&Sp`tCS%tR#MP_uO$s11+VN|0_U2 zwq)H=Q<2lD=jbU{YG_~&wYz}-%dGQi3Hcj zk&sp?7a6X~waDjb6U;N$G4n)uzu-Lg7E)3O&kY6-XYPOT@UFhsx>WsM)guezbbk5a zimeko%;EJZE)~2nAR~6OXyHa~Hx@UT>est%qF$*hqtLT-?}O|19WDfyu8F!|4ObNJ zU|A**Jl@6ce|gN{WPiKG6FzDu0AsK%u~gmG1G1r7$?#0eK!`W}IUr|W^Njh&urPPX zoJL$C21X#O_W~FldgCy_>omaL3gUTo!10E}9$T}C2+%mFMS0EYw z=n<2b2fe=t{ELh4jFmf1583Kb#oKi%x7W!97+It^XsaksmE^V&HT@6vDh{JWyvq+l^d-O_2Cb_@989~2v6ljq2AW~P)};zeR&zs z-^^Ec$D-N)eV=ZIV2;0DnPd=#@>G$mOt5tC@aKN;54XUB8gK%)zP%bv1%FMCn=lZ) z^DA5_T0s;P^_ma1Rnqkg`*O&`X z&2De6f55!PUrKVsR6cfZ=YRhY%e>$xxe`?FdbD!q37*8F80^3%lUX0K9IwBl11=zd z449|-ffcoq0;#jbc!E`(hz!-eWiYmtiCY%9N=0c(M zITkS!P-HK7mm~r|4fYv8s63u3U{~Iu3G_4H`Y#9nAvH!_9ev-9YAObh!a%i zbwOAdN$ZUCU1XJ{2!D@`DuUEA^=u}H!zS9w=arKhNSw%5G>kT~zOLywskBO~QaV;n zrX`*DRcyR8*mnzhnc0D{*%PXeE`T*52m)-*5OTQg3$Lx&rK#$l-8?GxH2Ne0x%D zs>viJNscKA7^hjnZ}`3v~HHK0JU^obZwkwJ+Xdo^0?k zCyyj0Y_R`h_82aL>XP6zE7pTF|0Nu!nBxy+UT+KbFw;wNn-%Hf)VRvl15P4Y_3vr1&I;1gFI>a0 z{EZZZse`x}UW+6ZX7lCmy%tAA~a?^-RaqFKRLz;^}8D#j$XZzzvvbE&kj>%s<#3xi}hUh9C;ii1)3&mX@K3AudO*xJf}fZqJF(au(V)T zG%Z&vMtDDk_Dvu%PU>~5l?E)>5z56PF~6ZjPGOBp2o}@?5}K}@AnmM5g(==55o~B$ z!GC{I>SdlKjicV&Bp@QEb;1Kh*f)2>EPt{@{ql$)a}h8Uqc!qCefSbTK!5{cRw@fI8_LLy~HNagwe2?U7HuFTT;XrvJZ zy@9h65TGPqA`L5fw#^KxL`bDdWgPvk*3Bl*AOzK{a4r3&n|&(Vg>Cdiv$<*X7JDhs z{VMxYV4hxi+vE}MGm@ty1+v#~9B&Yozc7$!OsBq2P6TP=Xb=b)GyBkn+JEGoW2HPg zQ9rTY@5*v?gz7?XmQx5b@S(koDX_gnF4;|W^isxU=YbAP9HCP6$y9^N6~Ztd{6O2b zk(b<6B;iuyK}mH7Oa{=QH4EGbfuJ%(PGSo|JC!~fr^j@y*08lsCnw#7@R$FCO>fT3 zx-sa4tCdG$tix+n!qO!huFdOtz`T}I??UX=GNH^@f-YykBb$Eyb=KBA<;eXm*puTXK9XIqn z+{Gh8H!BQCxzGK8IM!)j7$^PlNA#l40|x}$sY8VbjAIl?sP+#V06ep~rXtORky%FL zrF|=A#C+jQGn;2jG7mZl-+ff_A2`d#v2@m7AqXLgy4l~;P>WgCG$F#uJ*lrV#tZY0 z5TFmxH|h-&hFz#|fw&wd})X3*!E ze%CTPiEcVo9W$HC2gWxL)g@3V03vY^KaA2}zUsY)@&Tz`9>}31z#xy~zeYN8pq)pLA(>aps76Q?BQUgR@G^HEwAjcTCIyQArA!N3pT|2Jk^V zJ&0hLn|<29Jb&hDVaHUNGP$V*nIwm1@I&gGaiG207ss*4@DHtm+5kLBM>(zXW;e}Q z)rHf@?q`&t9o_xIAHh&6W0?tkzI+{wu7BLgzuUq8nsW~<_>-LadmZ|z&OGKs1N!_e z4m>{ZBP8+9Zd-ik?Ph1q?leNLTlTs)`~9JqkMG}q z+G#d4o>bl4%@dDxO~Uj`6i!{?5+bum#937xTl0*GVDS#9D1)pije=jV zr(oSZY=2XSvK!bTf7CnFSe8RarK{v6$q298jBji~Jm{;Kj~d9Wt2aabHWPKL$zGM+ z*3w7)PpD`t6Zvk=8lAtvlPekRhq=@`cLssM^dVhT|S{1gJBU+LtE3HbtLHj~w)GSTK zxVe9MhOp=_3~MjCl1L#=xBWL#R!fye{$icCU9w|#_J^P`LY=~%8r=4qDMUWOTfewy z?iWO@Ra8R)J-Ay`6pz||IY;Sck-EoRS#nZ0wSk4VxPyKX(k6~u){l^i$=DB8QM3}$ zUO!1~22R&X)t*yt&$Y=AtzL5p50k;Xx8m9<b2woqBrNXo7;8K3-(&?C2<>VL~{?Lh?A23%Spz zIQy;t;piwO8!9pqQgoHD-F!T|nU5lpNy_JUg#VjU2}HSYmOry}8L#GlGn&v1m3&`~ zMiSUR<&ugI^)2HcAW|cD}Xl!!_LyXVTH&B^5GGiDGvzIVGERvTE4Ae#1hN%qPHS zOZE7r4R=JY53kH`eQdN7%(azMIRpGV#1`oDak`3AYVZ$&*=aM|LT-2>B9NVFNKvO0 zEh{gbVSm+iK=@6@sSpQPedTd!-r1V7odKVIU*>73g%uf(Q@MnH=_QykK@b*1DZc>> ziZ_{Z=u`@1F+M;Jo(HJH?f@0PO*9_;cZA@91Ghv{9d6HPN)A#SuA6vo^;hgM0s@R#X z2FU379KAoSG1EkUsJGLriqpfRcbscK)C=9Wv)W=1+)qY#ci#@_#yBWoc}uxgWmpXT z3zqN-nX+t;+ClA}O=<;3MXZ0@X^jl17pF_gIgRXlE3t(?>aoHP+V7=274g}hA zwo~$_Bn~TxFBYHJtuSK5ShQ*Y>IB*pc|1K!WluK=kc95uBdBMd~;)Kr0YC4b<%0At(@> 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

TEE7yUXTryQJS;@ajqC?mAeA#|iKV;msEr zTQ=+D^u}dF9U!uXVeQKflYizxD(VsWxIvF9B}lXbO^&+;nisqVG&UM$hC+;;Ve8lu z&a)FQ2pbEGpAS^pc%g^yjL#2o?a}=D7qG_vjT;~8!UM+e|LRY=?rLT*f40N^l(Y6# zHTxAVGaSZf<}3K3M3D zS3L*!Nrku3_6yd~jzt?f0e<$ANXNAr3k* z{-R)NdYdZJt1)Z3jR3X>xz0*A=aqPVN-AAW<=MAVytF6tX?~y zR`Z3dbpV@ltZe8CLi|o98n4QZuE=85ST~`!cmCEL&>Cs?9m9Uzu=EKP=juy$_^eA3 zR=Y1S)_?pNf}{REq9;Dqqk_^@XUyBkqE2da>=5`)V^51e#&53U0r zvuoog-knqEs(&sP8-X^HJ9y%DjxC3{$~0#>Q%% z+JCS1P@=i{Ik}1=$qF7&;M8PF)K9!ai{9n|Bt4s%R`;XNuwMuX9 z31A;8lYdlud3B1qt7K}qk_0cA%(&dOC#HwIS1fa0P7d2J`o~(OXp9=b+w;w@%%(Yc zdmZ_k5&|irIoLlH&!$k1nn|-&x)>zUd4IF{s8x9@sRL-{5qxpyK_7G_@lD46K-c

6MR?jqW9$pp}v8Uw!Z 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 z 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

_Z;a84-tAvh!cB3c<>N6=~et(%7 zE`@%Ebo#Ls-RLo7Nh``9rk~Lwc(*|MgHqg zlV-Ye8XBoq5CWs@t6Qj(NwuWLFg3g4DNDFu*DRIF6zes5r>v5!EhL!zT+FisjdG@D zm9QCp+PBhw?&xOX45%$$%ZG9tP=Q`)!!{Dv}rA zBpZ-!48<{U{M`c*F&!#ywZrBxUni6x*&*!Hgj3D*fPCtDrq8|4otVQ1fuX52!E$qq zP8VU1hKWcM_ucukL*PMUYtyb+E=@MSR-IygwKB2%VtqRK^=*@=*x#HweycoT>|(0; z7it)P31P_)$Q1c7Iv?InZtmU>Z_a+Wn~r}QkrVRf?&#>K#`136@?6HcAYp6 z5fDN;-Fq`3HaFSRGEJkX$-{z&3!-iMh+fDn ziO8H`UEx$`(P2$vZ`1HRdpphU$2JcQ)?*x>_385JW_)=uoHY1!ZauNm56LeJCWw%R zXl9&`dH%U3_ZicgMY-2`Dsz$)qhk9=gBz_({F_0TQxh)wntyFd`h=)Zwa7|kT2 zhT_@-PZF$$i0d?=D-Z?Il+fV~9%z=tgTZF6{wuLd_>#Y{ep-iZg0ewUC3qO0yjaYF z`6>P1)rO2?i1+_f7m#TEJ5M36&>oC`XhW5OQowcVH738EuWkb3W2c&Rw}L!@UGE(? z&>_H-{MbbbsMV6vVp&UCK%SPA4)$77H-q6WhB`V{XrDY9NyBg?uaSm5vJeiALG_$Q z_H11pklMkD>`A)-s05%|10^1lz!_AA!;>88$hU9a+%gJo?v^pv?ecvZ@t-VX(H~peT^sw_ZI%ikVCaf2JG^&WGd4?e(ZR@=**P zMe%0wfT=i5N{TB1u~;;Pqyqc;P#$c<%fjYuC{qtcNx|C_a#Z)xr(^fL zX+s#$FuUvcw)9sHPc3ZoIJV6=C#YhbTia${zU^7J7zon>5(bx~lOnaDP2iQ=cu!SO zZfnl~9mm|S5q=E7h{cQkfb55vg6=W{`TxOFDN4JZbfyo)(N4}7ivcqazh>^;DjBgg((L<=7YkWN^aJ&;Qq|@B4`@@ zFoh>vu;BZq%`jnk!4x}oYH#@wD{v9c7sG=Y$tGdc;B#_glqQF7buf@~?VLz}ay1 zY_$KW^VInZw=w2BP#Z`%2ZcFuV2LbuxA@6bL!&{&Ae=Blv&3L=fjX;fGtDW>gXBa3 mnVcu&YQ-elIU7{-%AB3ezBUG}_!>(ft+$N?0000-LQO(#{yQoF diff --git a/web/landing/content/examples/topics/errors/throw/documentation.md b/web/landing/content/examples/topics/errors/throw/documentation.md index 14b6864704..e70dda6e22 100644 --- a/web/landing/content/examples/topics/errors/throw/documentation.md +++ b/web/landing/content/examples/topics/errors/throw/documentation.md @@ -1,4 +1,3 @@ An error handler decides what happens to the rest of the run when one row fails. - [Error Handling](/documentation/components/core/error-handling) -- [Retry](/documentation/components/core/retry) diff --git a/web/landing/content/examples/topics/joins/join_each/code.php b/web/landing/content/examples/topics/joins/join_each/code.php index a166fc3e23..9cd26e543e 100644 --- a/web/landing/content/examples/topics/joins/join_each/code.php +++ b/web/landing/content/examples/topics/joins/join_each/code.php @@ -16,7 +16,7 @@ public function __construct(private Schema $schema) { } - public function extract(FlowContext $context): Generator + public function extract(FlowContext $context, ?int $limit = null): Generator { yield rows($this->schema, row(['id' => 1, 'sku' => 'PRODUCT01']), row(['id' => 2, 'sku' => 'PRODUCT02'])); diff --git a/web/landing/content/examples/topics/partitioning/partition_placeholders/description.md b/web/landing/content/examples/topics/partitioning/partition_placeholders/description.md index 695ca13a9f..5e69eb0f5f 100644 --- a/web/landing/content/examples/topics/partitioning/partition_placeholders/description.md +++ b/web/landing/content/examples/topics/partitioning/partition_placeholders/description.md @@ -11,4 +11,4 @@ output └── PRODUCT02.csv ``` -Reading with the same placeholder pattern recreates the partitions from the path, including support for partition pruning with `filterPartitions()`. Keep in mind that this layout is not self-describing - a plain glob like `output/**/*.csv` will read the data but won't recognize any partitions. +Reading with the same placeholder pattern recreates the partitions from the path, including support for partition pruning through `filter()`. Keep in mind that this layout is not self-describing - a plain glob like `output/**/*.csv` will read the data but won't recognize any partitions. diff --git a/web/landing/content/examples/topics/partitioning/partition_pruning/code.php b/web/landing/content/examples/topics/partitioning/partition_pruning/code.php index b9a6d020fe..a24eb0f888 100644 --- a/web/landing/content/examples/topics/partitioning/partition_pruning/code.php +++ b/web/landing/content/examples/topics/partitioning/partition_pruning/code.php @@ -9,7 +9,7 @@ data_frame() ->read(from_csv(__DIR__ . '/data/partitioned/color=*/sku=*/*.csv')) - ->filterPartitions(ref('color')->notEquals(lit('green'))) + ->filter(ref('color')->notEquals(lit('green'))) ->collect() ->write(to_output(truncate: false)) ->run(); diff --git a/web/landing/content/examples/topics/partitioning/partition_pruning/description.md b/web/landing/content/examples/topics/partitioning/partition_pruning/description.md index 6357074500..73d660de3c 100644 --- a/web/landing/content/examples/topics/partitioning/partition_pruning/description.md +++ b/web/landing/content/examples/topics/partitioning/partition_pruning/description.md @@ -1 +1 @@ -Skip entire partitions without reading their data using filterPartitions(). Unlike filter() which reads all data then filters, partition pruning evaluates metadata first and only reads matching partitions - dramatically improving performance for large datasets. +Skip entire partitions without reading their data: when a filter() predicate touches only partition columns, the planner prunes automatically - partition metadata is evaluated first and only matching partitions are read - dramatically improving performance for large datasets. diff --git a/web/landing/content/examples/topics/writing/postgresql/transaction/code.php b/web/landing/content/examples/topics/writing/postgresql/transaction/code.php index 52a7c5a35f..46c450d702 100644 --- a/web/landing/content/examples/topics/writing/postgresql/transaction/code.php +++ b/web/landing/content/examples/topics/writing/postgresql/transaction/code.php @@ -29,7 +29,7 @@ ->column(column('customer', column_type_text())->notNull()) ); -// both loaders share one Client, so both tables move in the same transaction - if the audit write +// both sinks use the transaction's Client, so both tables move in the same transaction - if the audit write // fails, the orders rows roll back with it. A loader holding its own Client escapes the transaction. data_frame() ->read(from_csv(__DIR__ . '/data/orders.csv')) diff --git a/web/landing/content/examples/topics/writing/postgresql/transaction/description.md b/web/landing/content/examples/topics/writing/postgresql/transaction/description.md index 1028a26a6b..ccf557eb37 100644 --- a/web/landing/content/examples/topics/writing/postgresql/transaction/description.md +++ b/web/landing/content/examples/topics/writing/postgresql/transaction/description.md @@ -1,2 +1,4 @@ -`to_pgsql_transaction()` commits several loaders as one unit - every batch in its own transaction, -rolled back together if any loader fails. All wrapped loaders must share the wrapper's `Client`. +`to_pgsql_transaction()` is a transaction root grouping sinks: every batch is written in its own transaction, +rolled back if any sink fails; rows a sink's `Transformation` delivers when the run ends commit in one final +transaction. Every sink's loader must use the same `Client` instance as the transaction - a loader holding its own +`Client` escapes it. diff --git a/web/landing/resources/api.json b/web/landing/resources/api.json index 2f104ba87b..6ac7d65e0c 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}],"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}],"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}],"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}],"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\/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":94,"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":119,"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":139,"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":171,"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":192,"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":211,"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":218,"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":231,"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":252,"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":269,"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":298,"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":312,"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":319,"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":339,"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":"LyoqCiAgICAgKiBCZSBhd2FyZSB0aGF0IGZldGNoIGlzIG5vdCBtZW1vcnkgc2FmZSBhbmQgd2lsbCBsb2FkIGFsbCByb3dzIGludG8gbWVtb3J5LgogICAgICogSWYgeW91IHdhbnQgdG8gc2FmZWx5IGl0ZXJhdGUgb3ZlciBSb3dzIHVzZSBvZSBvZiB0aGUgZm9sbG93aW5nIG1ldGhvZHM6LgogICAgICoKICAgICAqIERhdGFGcmFtZTo6Z2V0KCkgOiBcR2VuZXJhdG9yCiAgICAgKiBEYXRhRnJhbWU6OmdldEFzQXJyYXkoKSA6IFxHZW5lcmF0b3IKICAgICAqIERhdGFGcmFtZTo6Z2V0RWFjaCgpIDogXEdlbmVyYXRvcgogICAgICogRGF0YUZyYW1lOjpnZXRFYWNoQXNBcnJheSgpIDogXEdlbmVyYXRvcgogICAgICoKICAgICAqIEB0cmlnZ2VyCiAgICAgKgogICAgICogQHRocm93cyBJbnZhbGlkQXJndW1lbnRFeGNlcHRpb24KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":370,"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":380,"slug":"extractor","name":"extractor","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[],"return_type":[{"name":"Extractor","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAaW50ZXJuYWwgZW5naW5lIHBhdGhzIG9ubHkgLSBhIGJ1aWxkLXRpbWUgc2NhbiBoYXMgdG8ga25vdyB3aGV0aGVyIHRoZSBzb3VyY2UgY2FuIGJlIHJlYWQgdHdpY2UKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":390,"slug":"filterpartitions","name":"filterPartitions","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"filter","type":[{"name":"Filter","namespace":"Flow\\Filesystem\\Path","is_nullable":false,"is_variadic":false},{"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":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEB0aHJvd3MgUnVudGltZUV4Y2VwdGlvbgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":418,"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":432,"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":"LyoqCiAgICAgKiBAdHJpZ2dlcgogICAgICoKICAgICAqIEBwYXJhbSBudWxsfGNhbGxhYmxlKFJvd3MgJHJvd3MpIDogdm9pZCAkY2FsbGJhY2sKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":444,"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":465,"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":486,"slug":"geteach","name":"getEach","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":"LyoqCiAgICAgKiBZaWVsZCBlYWNoIHJvdyBhcyBhbiBpbnN0YW5jZSBvZiBSb3cuCiAgICAgKgogICAgICogQHRyaWdnZXIKICAgICAqCiAgICAgKiBAcmV0dXJuIFxHZW5lcmF0b3I8Um93PgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":509,"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":532,"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":547,"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":571,"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":594,"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":608,"slug":"load","name":"load","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"loader","type":[{"name":"Loader","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":620,"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":641,"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":655,"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":667,"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":681,"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":701,"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":709,"slug":"registergroupby","name":"registerGroupBy","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"groupBy","type":[{"name":"GroupBy","namespace":"Flow\\ETL","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":"void","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAaW50ZXJuYWwgZW5naW5lIHBhdGhzIG9ubHkgLSBHcm91cGVkRGF0YUZyYW1lIGJ1aWxkcyBpdHMgc3RlcHMgYWdhaW5zdCB0aGlzIGZyYW1lJ3MgcGxhbgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":719,"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":726,"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":737,"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":755,"slug":"run","name":"run","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"},{"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+d2l0aENvbHVtblN0YXRpc3RpY3MoKQogICAgICogLSBzY2hlbWEgLSBhbmFseXplKCktPndpdGhTY2hlbWEoKQogICAgICoKICAgICAqIEBwYXJhbSBudWxsfGNhbGxhYmxlKFJvd3MgJHJvd3MsIEZsb3dDb250ZXh0ICRjb250ZXh0KTogdm9pZCAkY2FsbGJhY2sKICAgICAqIEBwYXJhbSBBbmFseXplfGJvb2wgJGFuYWx5emUgLSB3aGVuIHNldCBydW4gd2lsbCByZXR1cm4gUmVwb3J0CiAgICAgKgogICAgICogQHJldHVybiAoJGFuYWx5emUgaXMgQW5hbHl6ZXx0cnVlID8gUmVwb3J0IDogbnVsbCkKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":787,"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":796,"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":810,"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":826,"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":837,"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":851,"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":861,"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":889,"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":907,"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":930,"slug":"write","name":"write","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"loader","type":[{"name":"Loader","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":22,"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":30,"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}],"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}],"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}],"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}],"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":73,"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":97,"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":117,"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":149,"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":166,"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":185,"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":192,"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":203,"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":222,"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":239,"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":266,"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":280,"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":287,"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":307,"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":"LyoqCiAgICAgKiBCZSBhd2FyZSB0aGF0IGZldGNoIGlzIG5vdCBtZW1vcnkgc2FmZSBhbmQgd2lsbCBsb2FkIGFsbCByb3dzIGludG8gbWVtb3J5LgogICAgICogSWYgeW91IHdhbnQgdG8gc2FmZWx5IGl0ZXJhdGUgb3ZlciBSb3dzIHVzZSBvZSBvZiB0aGUgZm9sbG93aW5nIG1ldGhvZHM6LgogICAgICoKICAgICAqIERhdGFGcmFtZTo6Z2V0KCkgOiBcR2VuZXJhdG9yCiAgICAgKiBEYXRhRnJhbWU6OmdldEFzQXJyYXkoKSA6IFxHZW5lcmF0b3IKICAgICAqIERhdGFGcmFtZTo6Z2V0RWFjaCgpIDogXEdlbmVyYXRvcgogICAgICogRGF0YUZyYW1lOjpnZXRFYWNoQXNBcnJheSgpIDogXEdlbmVyYXRvcgogICAgICoKICAgICAqIEB0cmlnZ2VyCiAgICAgKgogICAgICogQHRocm93cyBJbnZhbGlkQXJndW1lbnRFeGNlcHRpb24KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":324,"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":336,"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":350,"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":371,"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":390,"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":409,"slug":"geteach","name":"getEach","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":"LyoqCiAgICAgKiBZaWVsZCBlYWNoIHJvdyBhcyBhbiBpbnN0YW5jZSBvZiBSb3cuCiAgICAgKgogICAgICogQHRyaWdnZXIKICAgICAqCiAgICAgKiBAcmV0dXJuIFxHZW5lcmF0b3I8Um93PgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":430,"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":451,"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":470,"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":498,"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":514,"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":528,"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":574,"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":595,"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":609,"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":621,"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":633,"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":653,"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":663,"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":671,"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":678,"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":689,"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":706,"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":731,"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":744,"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":758,"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":772,"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":783,"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":797,"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":807,"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":835,"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":853,"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":866,"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 diff --git a/web/landing/resources/dsl.json b/web/landing/resources/dsl.json index 26d2da2835..ede723b2ff 100644 --- a/web/landing/resources/dsl.json +++ b/web/landing/resources/dsl.json @@ -1 +1 @@ -[{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":294,"slug":"df","name":"df","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"config","type":[{"name":"Config","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"ConfigBuilder","namespace":"Flow\\ETL\\Config","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":"Flow","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"reading","example":"data_frame"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"writing","example":"overwrite"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEFsaWFzIGZvciBkYXRhX2ZyYW1lKCkgOiBGbG93LgogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":302,"slug":"data-frame","name":"data_frame","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"config","type":[{"name":"Config","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"ConfigBuilder","namespace":"Flow\\ETL\\Config","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":"Flow","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"reading","example":"data_frame"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"writing","example":"overwrite"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":308,"slug":"telemetry-options","name":"telemetry_options","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"trace_loading","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"trace_transformations","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"trace_cache","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"collect_metrics","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":"TelemetryOptions","namespace":"Flow\\ETL\\Config\\Telemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":320,"slug":"from-rows","name":"from_rows","namespace":"Flow\\ETL\\DSL","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":"RowsExtractor","namespace":"Flow\\ETL\\Extractor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"EXTRACTOR"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"reading","example":"data_frame"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"writing","example":"overwrite"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":327,"slug":"from-path-partitions","name":"from_path_partitions","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"path","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"PathPartitionsExtractor","namespace":"Flow\\ETL\\Extractor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"EXTRACTOR"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"partitioning","example":"path_partitions"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":343,"slug":"from-array","name":"from_array","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"array","type":[{"name":"iterable","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"schema","type":[{"name":"Schema","namespace":"Flow\\ETL","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."},{"name":"spillRoot","type":[{"name":"Path","namespace":"Flow\\Filesystem","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"ArrayExtractor","namespace":"Flow\\ETL\\Extractor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"EXTRACTOR"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"reading","example":"array"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"reading","example":"data_frame"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBpdGVyYWJsZTxhcnJheTxtaXhlZD4+ICRhcnJheQogKiBAcGFyYW0gbnVsbHxTY2hlbWEgJHNjaGVtYSAtIEBkZXByZWNhdGVkIHVzZSB3aXRoU2NoZW1hKCkgbWV0aG9kIGluc3RlYWQKICogQHBhcmFtIG51bGx8UGF0aCAkc3BpbGxSb290IC0gd2hlcmUgYSBub24tYXJyYXkgJGFycmF5IGlzIHNwaWxsZWQgd2hpbGUgaXQgaXMgZGVzY3JpYmVkOyBudWxsIHJlc29sdmVzIHRvCiAqICAgICAgICAgICAgICAgICAgICAgICAgICAkZmlsZXN5c3RlbS0+Z2V0U3lzdGVtVG1wRGlyKCkgYW5kIG9ubHkgb24gdGhhdCBwYXRoCiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":364,"slug":"from-cache","name":"from_cache","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"id","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":"fallback_extractor","type":[{"name":"Extractor","namespace":"Flow\\ETL","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"clear","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"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":"CacheExtractor","namespace":"Flow\\ETL\\Extractor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBzdHJpbmcgJGlkIC0gY2FjaGUgaWQgZnJvbSB3aGljaCBkYXRhIHdpbGwgYmUgZXh0cmFjdGVkCiAqIEBwYXJhbSBudWxsfEV4dHJhY3RvciAkZmFsbGJhY2tfZXh0cmFjdG9yIC0gZXh0cmFjdG9yIHRoYXQgd2lsbCBiZSB1c2VkIHdoZW4gY2FjaGUgaXMgZW1wdHkgLSBAZGVwcmVjYXRlZCB1c2Ugd2l0aEZhbGxiYWNrRXh0cmFjdG9yKCkgbWV0aG9kIGluc3RlYWQKICogQHBhcmFtIGJvb2wgJGNsZWFyIC0gY2xlYXIgY2FjaGUgYWZ0ZXIgZXh0cmFjdGlvbiAtIEBkZXByZWNhdGVkIHVzZSB3aXRoQ2xlYXJPbkZpbmlzaCgpIG1ldGhvZCBpbnN0ZWFkCiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":384,"slug":"from-all","name":"from_all","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"extractors","type":[{"name":"Extractor","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":"ChainExtractor","namespace":"Flow\\ETL\\Extractor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":390,"slug":"from-memory","name":"from_memory","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"memory","type":[{"name":"Memory","namespace":"Flow\\ETL\\Memory","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"MemoryExtractor","namespace":"Flow\\ETL\\Extractor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":396,"slug":"files","name":"files","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"directory","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"FilesExtractor","namespace":"Flow\\ETL\\Extractor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":402,"slug":"filesystem-cache","name":"filesystem_cache","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"cache_dir","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."},{"name":"serializer","type":[{"name":"Serializer","namespace":"Flow\\Serializer","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Floe\\FloeSerializer::..."}],"return_type":[{"name":"FilesystemCache","namespace":"Flow\\ETL\\Cache\\Implementation","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":414,"slug":"batched-by","name":"batched_by","namespace":"Flow\\ETL\\DSL","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},{"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":"min_size","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":"BatchByExtractor","namespace":"Flow\\ETL\\Extractor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBudWxsfGludDwxLCBtYXg+ICRtaW5fc2l6ZQogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":428,"slug":"batches","name":"batches","namespace":"Flow\\ETL\\DSL","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},{"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":"BatchExtractor","namespace":"Flow\\ETL\\Extractor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBpbnQ8MSwgbWF4PiAkc2l6ZQogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":434,"slug":"from-data-frame","name":"from_data_frame","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"data_frame","type":[{"name":"DataFrame","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":"DataFrameExtractor","namespace":"Flow\\ETL\\Extractor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":440,"slug":"from-sequence-date-period","name":"from_sequence_date_period","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"entry_name","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":"start","type":[{"name":"DateTimeInterface","namespace":"","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"interval","type":[{"name":"DateInterval","namespace":"","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"end","type":[{"name":"DateTimeInterface","namespace":"","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"options","type":[{"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":"SequenceExtractor","namespace":"Flow\\ETL\\Extractor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":454,"slug":"from-sequence-date-period-recurrences","name":"from_sequence_date_period_recurrences","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"entry_name","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":"start","type":[{"name":"DateTimeInterface","namespace":"","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"interval","type":[{"name":"DateInterval","namespace":"","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"recurrences","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":"options","type":[{"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":"SequenceExtractor","namespace":"Flow\\ETL\\Extractor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":468,"slug":"from-sequence-number","name":"from_sequence_number","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"entry_name","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":"start","type":[{"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":"end","type":[{"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":"step","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"float","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"1"}],"return_type":[{"name":"SequenceExtractor","namespace":"Flow\\ETL\\Extractor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":478,"slug":"to-memory","name":"to_memory","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"memory","type":[{"name":"Memory","namespace":"Flow\\ETL\\Memory","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"MemoryLoader","namespace":"Flow\\ETL\\Loader","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":492,"slug":"to-array","name":"to_array","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"array","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":"ArrayLoader","namespace":"Flow\\ETL\\Loader","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"LOADER"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"writing","example":"array"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENvbnZlcnQgcm93cyB0byBhbiBhcnJheSBhbmQgc3RvcmUgdGhlbSBpbiBwYXNzZWQgYXJyYXkgdmFyaWFibGUuCiAqCiAqIEBwYXJhbSBhcnJheTxhcnJheS1rZXksIG1peGVkPiAkYXJyYXkKICoKICogQHBhcmFtLW91dCBhcnJheTxhcnJheTxtaXhlZD4+ICRhcnJheQogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":500,"slug":"to-output","name":"to_output","namespace":"Flow\\ETL\\DSL","parameters":[{"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":"output","type":[{"name":"Output","namespace":"Flow\\ETL\\Loader\\StreamLoader","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Loader\\StreamLoader\\Output::..."},{"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::..."},{"name":"schemaFormatter","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":"StreamLoader","namespace":"Flow\\ETL\\Loader","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":510,"slug":"to-stderr","name":"to_stderr","namespace":"Flow\\ETL\\DSL","parameters":[{"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":"output","type":[{"name":"Output","namespace":"Flow\\ETL\\Loader\\StreamLoader","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Loader\\StreamLoader\\Output::..."},{"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::..."},{"name":"schemaFormatter","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":"StreamLoader","namespace":"Flow\\ETL\\Loader","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":520,"slug":"to-stdout","name":"to_stdout","namespace":"Flow\\ETL\\DSL","parameters":[{"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":"output","type":[{"name":"Output","namespace":"Flow\\ETL\\Loader\\StreamLoader","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Loader\\StreamLoader\\Output::..."},{"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::..."},{"name":"schemaFormatter","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":"StreamLoader","namespace":"Flow\\ETL\\Loader","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":530,"slug":"to-stream","name":"to_stream","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"uri","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":"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":"output","type":[{"name":"Output","namespace":"Flow\\ETL\\Loader\\StreamLoader","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Loader\\StreamLoader\\Output::..."},{"name":"mode","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'w'"},{"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::..."},{"name":"schemaFormatter","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":"StreamLoader","namespace":"Flow\\ETL\\Loader","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":550,"slug":"to-transformation","name":"to_transformation","namespace":"Flow\\ETL\\DSL","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},{"name":"loader","type":[{"name":"Loader","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":"TransformerLoader","namespace":"Flow\\ETL\\Loader","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":556,"slug":"to-branch","name":"to_branch","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"condition","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":"loader","type":[{"name":"Loader","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"transformation","type":[{"name":"Transformation","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":"BranchingLoader","namespace":"Flow\\ETL\\Loader","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":562,"slug":"rename-style","name":"rename_style","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"style","type":[{"name":"StringStyles","namespace":"Flow\\ETL\\String","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"RenameCaseEntryStrategy","namespace":"Flow\\ETL\\Transformer\\Rename","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"TRANSFORMER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":572,"slug":"rename-replace","name":"rename_replace","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"search","type":[{"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":"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":"RenameReplaceEntryStrategy","namespace":"Flow\\ETL\\Transformer\\Rename","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"TRANSFORMER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxzdHJpbmc+fHN0cmluZyAkc2VhcmNoCiAqIEBwYXJhbSBhcnJheTxzdHJpbmc+fHN0cmluZyAkcmVwbGFjZQogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":581,"slug":"rename-map","name":"rename_map","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"renames","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":"RenameMapEntryStrategy","namespace":"Flow\\ETL\\Transformer\\Rename","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"TRANSFORMER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxhcnJheS1rZXksIHN0cmluZz4gJHJlbmFtZXMgTWFwIG9mIG9sZF9uYW1lID0+IG5ld19uYW1lCiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":590,"slug":"row","name":"row","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"values","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":"Row","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxhcnJheS1rZXksIG1peGVkPiAkdmFsdWVzCiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":596,"slug":"rows","name":"rows","namespace":"Flow\\ETL\\DSL","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":"row","type":[{"name":"Row","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":"Rows","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":605,"slug":"col","name":"col","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"entry","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":"UnresolvedReference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIEFuIGFsaWFzIGZvciBgcmVmYC4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":615,"slug":"entry","name":"entry","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"entry","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":"UnresolvedReference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"columns","example":"create"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIEFuIGFsaWFzIGZvciBgcmVmYC4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":622,"slug":"ref","name":"ref","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"entry","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":"UnresolvedReference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"columns","example":"create"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":628,"slug":"structure-ref","name":"structure_ref","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"entry","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":"StructureFunctions","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":640,"slug":"structure","name":"structure","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"elements","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":"Structure","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIEJ1aWxkcyBhIHN0cnVjdHVyZSBmcm9tIHNjYWxhciBmdW5jdGlvbnM6IG9uZSBlbGVtZW50IHBlciBrZXksIGluIGtleSBvcmRlci4KICogQW4gZWxlbWVudCBpcyBudWxsYWJsZSB3aGVuIGl0cyBmdW5jdGlvbiBpczsgdGhlIHN0cnVjdHVyZSBpdHNlbGYgbmV2ZXIgaXMuCiAqCiAqIEBwYXJhbSBhcnJheTxhcnJheS1rZXksIFNjYWxhckZ1bmN0aW9uPiAkZWxlbWVudHMKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":646,"slug":"list-ref","name":"list_ref","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"entry","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":"ListFunctions","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":652,"slug":"refs","name":"refs","namespace":"Flow\\ETL\\DSL","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":"References","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":658,"slug":"select","name":"select","namespace":"Flow\\ETL\\DSL","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":"Select","namespace":"Flow\\ETL\\Transformation","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"TRANSFORMER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":664,"slug":"drop","name":"drop","namespace":"Flow\\ETL\\DSL","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":"Drop","namespace":"Flow\\ETL\\Transformation","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"TRANSFORMER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":670,"slug":"add-row-index","name":"add_row_index","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"column","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'index'"},{"name":"startFrom","type":[{"name":"StartFrom","namespace":"Flow\\ETL\\Transformation\\AddRowIndex","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Transformation\\AddRowIndex\\StartFrom::..."}],"return_type":[{"name":"AddRowIndex","namespace":"Flow\\ETL\\Transformation","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"TRANSFORMER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":679,"slug":"batch-size","name":"batch_size","namespace":"Flow\\ETL\\DSL","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":"BatchSize","namespace":"Flow\\ETL\\Transformation","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"TRANSFORMER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBpbnQ8MSwgbWF4PiAkc2l6ZQogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":685,"slug":"limit","name":"limit","namespace":"Flow\\ETL\\DSL","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":"Limit","namespace":"Flow\\ETL\\Transformation","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"TRANSFORMER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":694,"slug":"mask-columns","name":"mask_columns","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"columns","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"mask","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":"MaskColumns","namespace":"Flow\\ETL\\Transformation","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"TRANSFORMER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxpbnQsIHN0cmluZz4gJGNvbHVtbnMKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":700,"slug":"optional","name":"optional","namespace":"Flow\\ETL\\DSL","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":"Optional","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":707,"slug":"lit","name":"lit","namespace":"Flow\\ETL\\DSL","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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"columns","example":"create"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":713,"slug":"exists","name":"exists","namespace":"Flow\\ETL\\DSL","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":"Exists","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":719,"slug":"when","name":"when","namespace":"Flow\\ETL\\DSL","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":"then","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":"else","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"When","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":728,"slug":"structure-get","name":"structure_get","namespace":"Flow\\ETL\\DSL","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},{"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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIEFsaWFzIGZvciBgYXJyYXlfZ2V0YC4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":734,"slug":"array-get","name":"array_get","namespace":"Flow\\ETL\\DSL","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},{"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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":745,"slug":"structure-get-collection","name":"structure_get_collection","namespace":"Flow\\ETL\\DSL","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},{"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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIEFsaWFzIGZvciBgYXJyYXlfZ2V0X2NvbGxlY3Rpb25gLgogKgogKiBAcGFyYW0gYXJyYXk8YXJyYXkta2V5LCBtaXhlZD58U2NhbGFyRnVuY3Rpb24gJGtleXMKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":754,"slug":"array-get-collection","name":"array_get_collection","namespace":"Flow\\ETL\\DSL","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},{"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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxhcnJheS1rZXksIG1peGVkPnxTY2FsYXJGdW5jdGlvbiAka2V5cwogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":763,"slug":"structure-get-collection-first","name":"structure_get_collection_first","namespace":"Flow\\ETL\\DSL","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},{"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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIEFsaWFzIGZvciBgYXJyYXlfZ2V0X2NvbGxlY3Rpb25fZmlyc3RgLgogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":769,"slug":"array-get-collection-first","name":"array_get_collection_first","namespace":"Flow\\ETL\\DSL","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},{"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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":778,"slug":"array-exists","name":"array_exists","namespace":"Flow\\ETL\\DSL","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},{"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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxhcnJheS1rZXksIG1peGVkPnxTY2FsYXJGdW5jdGlvbiAkcmVmCiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":788,"slug":"array-merge","name":"array_merge","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"left","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},{"name":"right","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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxhcnJheS1rZXksIG1peGVkPnxTY2FsYXJGdW5jdGlvbiAkbGVmdAogKiBAcGFyYW0gYXJyYXk8YXJyYXkta2V5LCBtaXhlZD58U2NhbGFyRnVuY3Rpb24gJHJpZ2h0CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":797,"slug":"array-merge-collection","name":"array_merge_collection","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"array","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":"ArrayMergeCollection","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxhcnJheS1rZXksIG1peGVkPnxTY2FsYXJGdW5jdGlvbiAkYXJyYXkKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":803,"slug":"array-key-rename","name":"array_key_rename","namespace":"Flow\\ETL\\DSL","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},{"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},{"name":"newName","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":"ArrayKeyRename","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":809,"slug":"array-keys-style-convert","name":"array_keys_style_convert","namespace":"Flow\\ETL\\DSL","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},{"name":"style","type":[{"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":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\String\\StringStyles::..."}],"return_type":[{"name":"ArrayKeysStyleConvert","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":817,"slug":"array-sort","name":"array_sort","namespace":"Flow\\ETL\\DSL","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":"sort_function","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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":830,"slug":"array-reverse","name":"array_reverse","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"function","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},{"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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxhcnJheS1rZXksIG1peGVkPnxTY2FsYXJGdW5jdGlvbiAkZnVuY3Rpb24KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":836,"slug":"now","name":"now","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"time_zone","type":[{"name":"DateTimeZone","namespace":"","is_nullable":false,"is_variadic":false},{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"DateTimeZone::..."}],"return_type":[{"name":"Now","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":842,"slug":"between","name":"between","namespace":"Flow\\ETL\\DSL","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},{"name":"lower_bound","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":"upper_bound","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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":852,"slug":"to-date-time","name":"to_date_time","namespace":"Flow\\ETL\\DSL","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},{"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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":861,"slug":"to-date","name":"to_date","namespace":"Flow\\ETL\\DSL","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},{"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'"},{"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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":870,"slug":"date-time-format","name":"date_time_format","namespace":"Flow\\ETL\\DSL","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},{"name":"format","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":"DateTimeFormat","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":876,"slug":"split","name":"split","namespace":"Flow\\ETL\\DSL","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}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":889,"slug":"combine","name":"combine","namespace":"Flow\\ETL\\DSL","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},{"name":"values","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":"Combine","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxhcnJheS1rZXksIG1peGVkPnxTY2FsYXJGdW5jdGlvbiAka2V5cwogKiBAcGFyYW0gYXJyYXk8YXJyYXkta2V5LCBtaXhlZD58U2NhbGFyRnVuY3Rpb24gJHZhbHVlcwogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":898,"slug":"concat","name":"concat","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"functions","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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIENvbmNhdCBhbGwgdmFsdWVzLiBJZiB5b3Ugd2FudCB0byBjb25jYXRlbmF0ZSB2YWx1ZXMgd2l0aCBzZXBhcmF0b3IgdXNlIGNvbmNhdF93cyBmdW5jdGlvbi4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":907,"slug":"concat-ws","name":"concat_ws","namespace":"Flow\\ETL\\DSL","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":"functions","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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIENvbmNhdCBhbGwgdmFsdWVzIHdpdGggc2VwYXJhdG9yLgogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":913,"slug":"hash","name":"hash","namespace":"Flow\\ETL\\DSL","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},{"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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":922,"slug":"cast","name":"cast","namespace":"Flow\\ETL\\DSL","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},{"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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIEBwYXJhbSBcRmxvd1xUeXBlc1xUeXBlPG1peGVkPnxzdHJpbmcgJHR5cGUKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":928,"slug":"coalesce","name":"coalesce","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"values","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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":934,"slug":"enum-name","name":"enum_name","namespace":"Flow\\ETL\\DSL","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":"EnumName","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":940,"slug":"enum-value","name":"enum_value","namespace":"Flow\\ETL\\DSL","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":"EnumValue","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":946,"slug":"count","name":"count","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"function","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Count","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"AGGREGATING_FUNCTION"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":958,"slug":"call","name":"call","namespace":"Flow\\ETL\\DSL","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":"return_type","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":"parameters","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"CallUserFunc","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIENhbGxzIGEgdXNlci1kZWZpbmVkIGZ1bmN0aW9uIHdpdGggdGhlIGdpdmVuIHBhcmFtZXRlcnMuCiAqCiAqIEBwYXJhbSBUeXBlPG1peGVkPiAkcmV0dXJuX3R5cGUKICogQHBhcmFtIGFycmF5PG1peGVkPiAkcGFyYW1ldGVycwogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":985,"slug":"array-unpack","name":"array_unpack","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"array","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},{"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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIFVucGFja3MgZWFjaCBlbGVtZW50IG9mIGFuIGFycmF5IGludG8gYSBuZXcgZW50cnksIHVzaW5nIHRoZSBhcnJheSBrZXkgYXMgdGhlIGVudHJ5IG5hbWUuCiAqCiAqIEJlZm9yZToKICogKy0tKy0tLS0tLS0tLS0tLS0tLS0tLS0rCiAqIHxpZHwgICAgICAgICAgICAgIGFycmF5fAogKiArLS0rLS0tLS0tLS0tLS0tLS0tLS0tLSsKICogfCAxfHsiYSI6MSwiYiI6MiwiYyI6M318CiAqIHwgMnx7ImQiOjQsImUiOjUsImYiOjZ9fAogKiArLS0rLS0tLS0tLS0tLS0tLS0tLS0tLSsKICoKICogQWZ0ZXI6CiAqICstLSstLS0tLSstLS0tLSstLS0tLSstLS0tLSstLS0tLSsKICogfGlkfGFyci5ifGFyci5jfGFyci5kfGFyci5lfGFyci5mfAogKiArLS0rLS0tLS0rLS0tLS0rLS0tLS0rLS0tLS0rLS0tLS0rCiAqIHwgMXwgICAgMnwgICAgM3wgICAgIHwgICAgIHwgICAgIHwKICogfCAyfCAgICAgfCAgICAgfCAgICA0fCAgICA1fCAgICA2fAogKiArLS0rLS0tLS0rLS0tLS0rLS0tLS0rLS0tLS0rLS0tLS0rCiAqCiAqIEBwYXJhbSBhcnJheTxhcnJheS1rZXksIG1peGVkPnxTY2FsYXJGdW5jdGlvbiAkYXJyYXkKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1015,"slug":"array-expand","name":"array_expand","namespace":"Flow\\ETL\\DSL","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":"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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIEV4cGFuZHMgZWFjaCB2YWx1ZSBpbnRvIGVudHJ5LCBpZiB0aGVyZSBhcmUgbW9yZSB0aGFuIG9uZSB2YWx1ZSwgbXVsdGlwbGUgcm93cyB3aWxsIGJlIGNyZWF0ZWQuCiAqIEFycmF5IGtleXMgYXJlIGlnbm9yZWQsIG9ubHkgdmFsdWVzIGFyZSB1c2VkIHRvIGNyZWF0ZSBuZXcgcm93cy4KICogTmVzdGVkIGluIGFub3RoZXIgZnVuY3Rpb24gKHN0cnVjdHVyZSgpLCBjb25jYXQoKSwgLi4uKSBpdCBzdGlsbCBnaXZlcyBvbmUgcm93IHBlciBlbGVtZW50LiBTZXZlcmFsCiAqIGV4cGFuZHMgaW4gb25lIGV4cHJlc3Npb24gYXJlIHppcHBlZCB0byB0aGUgbG9uZ2VzdCBsaXN0OyBhIHNob3J0ZXIgb25lIGdpdmVzIG51bGwsIHNvIGl0cyBlbGVtZW50CiAqIHR5cGUgYmVjb21lcyBudWxsYWJsZS4gSXQgaXMgcmVmdXNlZCBpbnNpZGUgYW5vdGhlciBhcnJheV9leHBhbmQoKSBhbmQgaW4gZmlsdGVyKCksIHVudGlsKCksCiAqIGR1cGxpY2F0ZVJvdygpLCBhZ2dyZWdhdGUoKSwgb3ZlcigpIGFuZCBvbkVhY2goKS4KICoKICogQmVmb3JlOgogKiAgICstLSstLS0tLS0tLS0tLS0tLS0tLS0tKwogKiAgIHxpZHwgICAgICAgICAgICAgIGFycmF5fAogKiAgICstLSstLS0tLS0tLS0tLS0tLS0tLS0tKwogKiAgIHwgMXx7ImEiOjEsImIiOjIsImMiOjN9fAogKiAgICstLSstLS0tLS0tLS0tLS0tLS0tLS0tKwogKgogKiBBZnRlcjoKICogICArLS0rLS0tLS0tLS0rCiAqICAgfGlkfGV4cGFuZGVkfAogKiAgICstLSstLS0tLS0tLSsKICogICB8IDF8ICAgICAgIDF8CiAqICAgfCAxfCAgICAgICAyfAogKiAgIHwgMXwgICAgICAgM3wKICogICArLS0rLS0tLS0tLS0rCiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1021,"slug":"size","name":"size","namespace":"Flow\\ETL\\DSL","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":"Size","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1027,"slug":"uuid-v4","name":"uuid_v4","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"Uuid","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1033,"slug":"uuid-v7","name":"uuid_v7","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"value","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"DateTimeInterface","namespace":"","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Uuid","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1039,"slug":"ulid","name":"ulid","namespace":"Flow\\ETL\\DSL","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":"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":"Ulid","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1045,"slug":"lower","name":"lower","namespace":"Flow\\ETL\\DSL","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}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ToLower","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1051,"slug":"capitalize","name":"capitalize","namespace":"Flow\\ETL\\DSL","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}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Capitalize","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1057,"slug":"upper","name":"upper","namespace":"Flow\\ETL\\DSL","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}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ToUpper","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1063,"slug":"all","name":"all","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"functions","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":"All","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1069,"slug":"any","name":"any","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"values","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":"Any","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1075,"slug":"not","name":"not","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"value","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":"Not","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1081,"slug":"to-timezone","name":"to_timezone","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"value","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"DateTimeInterface","namespace":"","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"timeZone","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"DateTimeZone","namespace":"","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":"ToTimeZone","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1087,"slug":"ignore-error-handler","name":"ignore_error_handler","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"IgnoreError","namespace":"Flow\\ETL\\ErrorHandler","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1093,"slug":"skip-rows-handler","name":"skip_rows_handler","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"SkipRows","namespace":"Flow\\ETL\\ErrorHandler","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1099,"slug":"throw-error-handler","name":"throw_error_handler","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"ThrowError","namespace":"Flow\\ETL\\ErrorHandler","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1105,"slug":"regex-replace","name":"regex_replace","namespace":"Flow\\ETL\\DSL","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":"subject","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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1115,"slug":"regex-match-all","name":"regex_match_all","namespace":"Flow\\ETL\\DSL","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":"subject","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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1125,"slug":"regex-match","name":"regex_match","namespace":"Flow\\ETL\\DSL","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":"subject","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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1135,"slug":"regex","name":"regex","namespace":"Flow\\ETL\\DSL","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":"subject","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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1145,"slug":"regex-all","name":"regex_all","namespace":"Flow\\ETL\\DSL","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":"subject","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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1155,"slug":"sprintf","name":"sprintf","namespace":"Flow\\ETL\\DSL","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":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"args","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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1161,"slug":"sanitize","name":"sanitize","namespace":"Flow\\ETL\\DSL","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}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1170,"slug":"round","name":"round","namespace":"Flow\\ETL\\DSL","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":"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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1179,"slug":"number-format","name":"number_format","namespace":"Flow\\ETL\\DSL","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":"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":"decimal_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":"thousands_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":"','"}],"return_type":[{"name":"NumberFormat","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1193,"slug":"array-to-row","name":"array_to_row","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"data","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":"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":"hydrator","type":[{"name":"Hydrator","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Row\\AdaptiveRowHydrator::..."},{"name":"partitions","type":[{"name":"Partitions","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"Row","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxhcnJheTxtaXhlZD4+fGFycmF5PG1peGVkfHN0cmluZz4gJGRhdGEKICogQHBhcmFtIGFycmF5PFBhcnRpdGlvbj58UGFydGl0aW9ucyAkcGFydGl0aW9ucwogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1219,"slug":"array-to-rows","name":"array_to_rows","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"data","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":"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":"hydrator","type":[{"name":"Hydrator","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Row\\AdaptiveRowHydrator::..."}],"return_type":[{"name":"Rows","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxhcnJheTxtaXhlZD4+fGFycmF5PG1peGVkfHN0cmluZz4gJGRhdGEKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1256,"slug":"rank","name":"rank","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"Rank","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"WINDOW_FUNCTION"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1262,"slug":"dens-rank","name":"dens_rank","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"DenseRank","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"WINDOW_FUNCTION"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1268,"slug":"dense-rank","name":"dense_rank","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"DenseRank","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"WINDOW_FUNCTION"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1274,"slug":"average","name":"average","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"ref","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":"scale","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"2"},{"name":"rounding","type":[{"name":"Rounding","namespace":"Flow\\Calculator","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Calculator\\Rounding::..."}],"return_type":[{"name":"Average","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"AGGREGATING_FUNCTION"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1280,"slug":"greatest","name":"greatest","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"values","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":true,"default_value":null}],"return_type":[{"name":"Greatest","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1286,"slug":"least","name":"least","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"values","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":true,"default_value":null}],"return_type":[{"name":"Least","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1292,"slug":"collect","name":"collect","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"ref","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}],"return_type":[{"name":"Collect","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"AGGREGATING_FUNCTION"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1298,"slug":"string-agg","name":"string_agg","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"ref","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":"separator","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"', '"},{"name":"sort","type":[{"name":"SortOrder","namespace":"Flow\\ETL\\Row","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"StringAggregate","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"AGGREGATING_FUNCTION"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1304,"slug":"collect-unique","name":"collect_unique","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"ref","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}],"return_type":[{"name":"CollectUnique","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"AGGREGATING_FUNCTION"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1310,"slug":"window","name":"window","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"Window","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1316,"slug":"unbounded-preceding","name":"unbounded_preceding","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"FrameBound","namespace":"Flow\\ETL\\Window","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1322,"slug":"preceding","name":"preceding","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"offset","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":"FrameBound","namespace":"Flow\\ETL\\Window","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1328,"slug":"current-row","name":"current_row","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"FrameBound","namespace":"Flow\\ETL\\Window","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1334,"slug":"following","name":"following","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"offset","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":"FrameBound","namespace":"Flow\\ETL\\Window","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1340,"slug":"unbounded-following","name":"unbounded_following","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"FrameBound","namespace":"Flow\\ETL\\Window","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1346,"slug":"sum","name":"sum","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"ref","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":"exact","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":"Sum","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"AGGREGATING_FUNCTION"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1352,"slug":"first","name":"first","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"ref","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}],"return_type":[{"name":"First","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"AGGREGATING_FUNCTION"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1358,"slug":"last","name":"last","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"ref","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}],"return_type":[{"name":"Last","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"AGGREGATING_FUNCTION"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1364,"slug":"max","name":"max","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"ref","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}],"return_type":[{"name":"Max","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"AGGREGATING_FUNCTION"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1370,"slug":"min","name":"min","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"ref","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}],"return_type":[{"name":"Min","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"AGGREGATING_FUNCTION"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1376,"slug":"row-number","name":"row_number","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"RowNumber","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1387,"slug":"schema","name":"schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"definitions","type":[{"name":"Definition","namespace":"Flow\\ETL\\Schema","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"Schema","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBEZWZpbml0aW9uPG1peGVkPiAuLi4kZGVmaW5pdGlvbnMKICoKICogQHJldHVybiBTY2hlbWEKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1396,"slug":"schema-to-json","name":"schema_to_json","namespace":"Flow\\ETL\\DSL","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":"pretty","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":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBTY2hlbWEgJHNjaGVtYQogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1405,"slug":"schema-to-php","name":"schema_to_php","namespace":"Flow\\ETL\\DSL","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":"valueFormatter","type":[{"name":"ValueFormatter","namespace":"Flow\\ETL\\Schema\\Formatter\\PHPFormatter","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Schema\\Formatter\\PHPFormatter\\ValueFormatter::..."},{"name":"typeFormatter","type":[{"name":"TypeFormatter","namespace":"Flow\\ETL\\Schema\\Formatter\\PHPFormatter","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Schema\\Formatter\\PHPFormatter\\TypeFormatter::..."}],"return_type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBTY2hlbWEgJHNjaGVtYQogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1417,"slug":"schema-to-ascii","name":"schema_to_ascii","namespace":"Flow\\ETL\\DSL","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":"formatter","type":[{"name":"SchemaFormatter","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBTY2hlbWEgJHNjaGVtYQogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1427,"slug":"schema-validate","name":"schema_validate","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"expected","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":"given","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":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Schema\\Validator\\StrictValidator::..."}],"return_type":[{"name":"ValidationContext","namespace":"Flow\\ETL\\Schema\\Validator","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBTY2hlbWEgJGV4cGVjdGVkCiAqIEBwYXJhbSBTY2hlbWEgJGdpdmVuCiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1436,"slug":"schema-evolving-validator","name":"schema_evolving_validator","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"EvolvingValidator","namespace":"Flow\\ETL\\Schema\\Validator","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1442,"slug":"schema-strict-validator","name":"schema_strict_validator","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"StrictValidator","namespace":"Flow\\ETL\\Schema\\Validator","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1448,"slug":"schema-selective-validator","name":"schema_selective_validator","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"SelectiveValidator","namespace":"Flow\\ETL\\Schema\\Validator","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1457,"slug":"schema-from-json","name":"schema_from_json","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"schema","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":"Schema","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gU2NoZW1hCiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1470,"slug":"schema-metadata","name":"schema_metadata","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"metadata","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxzdHJpbmcsIGFycmF5PGJvb2x8ZmxvYXR8aW50fHN0cmluZz58Ym9vbHxmbG9hdHxpbnR8c3RyaW5nPiAkbWV0YWRhdGEKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1479,"slug":"int-schema","name":"int_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"IntegerDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEFsaWFzIGZvciBgaW50ZWdlcl9zY2hlbWFgLgogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1485,"slug":"integer-schema","name":"integer_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"IntegerDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1494,"slug":"str-schema","name":"str_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"StringDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEFsaWFzIGZvciBgc3RyaW5nX3NjaGVtYWAuCiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1500,"slug":"string-schema","name":"string_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"StringDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1506,"slug":"bool-schema","name":"bool_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"BooleanDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1512,"slug":"float-schema","name":"float_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"FloatDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1526,"slug":"map-schema","name":"map_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"type","type":[{"name":"MapType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false},{"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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"MapDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUS2V5IG9mIGFycmF5LWtleQogKiBAdGVtcGxhdGUgVFZhbHVlCiAqCiAqIEBwYXJhbSBNYXBUeXBlPGFycmF5PFRLZXksIFRWYWx1ZT4+fFR5cGU8YXJyYXk8VEtleSwgVFZhbHVlPj4gJHR5cGUKICoKICogQHJldHVybiBNYXBEZWZpbml0aW9uPFRLZXksIFRWYWx1ZT4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1540,"slug":"list-schema","name":"list_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"type","type":[{"name":"ListType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false},{"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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"ListDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBMaXN0VHlwZTxsaXN0PFQ+PnxUeXBlPGxpc3Q8VD4+ICR0eXBlCiAqCiAqIEByZXR1cm4gTGlzdERlZmluaXRpb248VD4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1558,"slug":"enum-schema","name":"enum_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"type","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"EnumDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUIG9mIFxVbml0RW51bQogKgogKiBAcGFyYW0gY2xhc3Mtc3RyaW5nPFQ+ICR0eXBlCiAqCiAqIEByZXR1cm4gRW51bURlZmluaXRpb248VD4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1564,"slug":"null-schema","name":"null_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"NullDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1570,"slug":"datetime-schema","name":"datetime_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"DateTimeDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1576,"slug":"time-schema","name":"time_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"TimeDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1582,"slug":"date-schema","name":"date_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"DateDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1588,"slug":"json-schema","name":"json_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"JsonDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1594,"slug":"html-schema","name":"html_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"HTMLDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1600,"slug":"html-element-schema","name":"html_element_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"HTMLElementDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1606,"slug":"xml-schema","name":"xml_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"XMLDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1612,"slug":"xml-element-schema","name":"xml_element_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"XMLElementDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1625,"slug":"structure-schema","name":"structure_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"type","type":[{"name":"StructureType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false},{"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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"StructureDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBTdHJ1Y3R1cmVUeXBlPGFycmF5PGFycmF5LWtleSwgVD4+fFR5cGU8YXJyYXk8YXJyYXkta2V5LCBUPj4gJHR5cGUKICoKICogQHJldHVybiBTdHJ1Y3R1cmVEZWZpbml0aW9uPFQ+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1643,"slug":"union-schema","name":"union_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"type","type":[{"name":"UnionType","namespace":"Flow\\Types\\Type\\Native","is_nullable":false,"is_variadic":false},{"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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Definition","namespace":"Flow\\ETL\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBUeXBlPG1peGVkPnxVbmlvblR5cGU8bWl4ZWQsIG1peGVkPiAkdHlwZQogKgogKiBAZGVwcmVjYXRlZCBhIGNvbHVtbiBob2xkcyBleGFjdGx5IG9uZSB0eXBlIC0gdXNlIGRlZmluaXRpb25fZnJvbV90eXBlKCkgaW5zdGVhZAogKgogKiBAcmV0dXJuIERlZmluaXRpb248bWl4ZWQ+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1653,"slug":"uuid-schema","name":"uuid_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"UuidDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1659,"slug":"time-zone-schema","name":"time_zone_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"TimeZoneDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1672,"slug":"definition-from-array","name":"definition_from_array","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"definition","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":"Definition","namespace":"Flow\\ETL\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIERlZmluaXRpb24gZnJvbSBhbiBhcnJheSByZXByZXNlbnRhdGlvbi4KICoKICogQHBhcmFtIGFycmF5PGFycmF5LWtleSwgbWl4ZWQ+ICRkZWZpbml0aW9uCiAqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxtaXhlZD4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1705,"slug":"definition-from-type","name":"definition_from_type","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"ref","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":"type","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Definition","namespace":"Flow\\ETL\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIERlZmluaXRpb24gZnJvbSBhIFR5cGUuCiAqCiAqIEBwYXJhbSBUeXBlPG1peGVkPiAkdHlwZQogKgogKiBAcmV0dXJuIERlZmluaXRpb248bWl4ZWQ+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1757,"slug":"infer-schema","name":"infer_schema","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"SchemaInferenceBuilder","namespace":"Flow\\ETL\\Schema\\Inference","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1763,"slug":"execution-context","name":"execution_context","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"config","type":[{"name":"Config","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":"FlowContext","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1769,"slug":"flow-context","name":"flow_context","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"config","type":[{"name":"Config","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":"FlowContext","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1775,"slug":"config","name":"config","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"Config","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1781,"slug":"config-builder","name":"config_builder","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"ConfigBuilder","namespace":"Flow\\ETL\\Config","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1787,"slug":"memory-sort","name":"memory_sort","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"MemorySortBuilder","namespace":"Flow\\ETL\\Config\\Sort","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1793,"slug":"external-sort","name":"external_sort","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"ExternalSortBuilder","namespace":"Flow\\ETL\\Config\\Sort","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1799,"slug":"hash-join","name":"hash_join","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"HashJoinBuilder","namespace":"Flow\\ETL\\Config\\Join","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1805,"slug":"hash-group-by","name":"hash_group_by","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"HashGroupByBuilder","namespace":"Flow\\ETL\\Config\\Grouping","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1811,"slug":"hash-repartition","name":"hash_repartition","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"HashRepartitionBuilder","namespace":"Flow\\ETL\\Config\\Repartition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1820,"slug":"pivot-values","name":"pivot_values","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"values","type":[{"name":"string","namespace":null,"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":true,"default_value":null}],"return_type":[{"name":"DeclaredPivotValues","namespace":"Flow\\ETL\\GroupBy","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIERlY2xhcmVzIHRoZSBwaXZvdCBjb2x1bW5zIGEgZ3JvdXBCeSgpLT5waXZvdCgpIHByb2R1Y2VzLCBzbyB0aGUgcGxhbiBjYW4gbmFtZSB0aGVtIGJlZm9yZSBhIHJvdyBmbG93cy4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1830,"slug":"discover-pivot-values","name":"discover_pivot_values","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"maxValues","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"10000"}],"return_type":[{"name":"DiscoveredPivotValues","namespace":"Flow\\ETL\\GroupBy","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFJlYWRzIHRoZSBwaXZvdCBjb2x1bW4gb25jZSBhdCBidWlsZCB0aW1lIGFuZCB0dXJucyB3aGF0IGl0IGZpbmRzIGludG8gZGVjbGFyZWQgdmFsdWVzLiBSZWZ1c2VzIGEKICogc291cmNlIHRoYXQgY2Fubm90IGJlIHJlYWQgdHdpY2UuCiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1836,"slug":"partition-by","name":"partition_by","namespace":"Flow\\ETL\\DSL","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":"Partitioning","namespace":"Flow\\ETL\\Loader","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1845,"slug":"partition-types","name":"partition_types","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"types","type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"PartitionTypes","namespace":"Flow\\ETL\\Extractor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBUeXBlPG1peGVkPiAuLi4kdHlwZXMgcGFydGl0aW9uIGNvbHVtbiBuYW1lID0+IHR5cGUsIHBhc3NlZCBhcyBuYW1lZCBhcmd1bWVudHMKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1855,"slug":"overwrite","name":"overwrite","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"SaveMode","namespace":"Flow\\ETL\\Filesystem","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEFsaWFzIGZvciBzYXZlX21vZGVfb3ZlcndyaXRlKCkuCiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1861,"slug":"save-mode-overwrite","name":"save_mode_overwrite","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"SaveMode","namespace":"Flow\\ETL\\Filesystem","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1870,"slug":"ignore","name":"ignore","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"SaveMode","namespace":"Flow\\ETL\\Filesystem","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEFsaWFzIGZvciBzYXZlX21vZGVfaWdub3JlKCkuCiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1876,"slug":"save-mode-ignore","name":"save_mode_ignore","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"SaveMode","namespace":"Flow\\ETL\\Filesystem","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1885,"slug":"exception-if-exists","name":"exception_if_exists","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"SaveMode","namespace":"Flow\\ETL\\Filesystem","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEFsaWFzIGZvciBzYXZlX21vZGVfZXhjZXB0aW9uX2lmX2V4aXN0cygpLgogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1891,"slug":"save-mode-exception-if-exists","name":"save_mode_exception_if_exists","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"SaveMode","namespace":"Flow\\ETL\\Filesystem","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1900,"slug":"append","name":"append","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"SaveMode","namespace":"Flow\\ETL\\Filesystem","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEFsaWFzIGZvciBzYXZlX21vZGVfYXBwZW5kKCkuCiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1906,"slug":"save-mode-append","name":"save_mode_append","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"SaveMode","namespace":"Flow\\ETL\\Filesystem","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1912,"slug":"print-rows","name":"print_rows","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"rows","type":[{"name":"Rows","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"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":"false"},{"name":"formatter","type":[{"name":"Formatter","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":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1918,"slug":"identical","name":"identical","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"left","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":"right","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}],"return_type":[{"name":"Identical","namespace":"Flow\\ETL\\Join\\Comparison","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"COMPARISON"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1924,"slug":"equal","name":"equal","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"left","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":"right","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}],"return_type":[{"name":"Equal","namespace":"Flow\\ETL\\Join\\Comparison","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"COMPARISON"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1930,"slug":"compare-all","name":"compare_all","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"comparison","type":[{"name":"Comparison","namespace":"Flow\\ETL\\Join","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"comparisons","type":[{"name":"Comparison","namespace":"Flow\\ETL\\Join","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"All","namespace":"Flow\\ETL\\Join\\Comparison","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"COMPARISON"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1936,"slug":"compare-any","name":"compare_any","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"comparison","type":[{"name":"Comparison","namespace":"Flow\\ETL\\Join","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"comparisons","type":[{"name":"Comparison","namespace":"Flow\\ETL\\Join","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"Any","namespace":"Flow\\ETL\\Join\\Comparison","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"COMPARISON"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1947,"slug":"join-on","name":"join_on","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"comparisons","type":[{"name":"Comparison","namespace":"Flow\\ETL\\Join","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},{"name":"join_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":"Expression","namespace":"Flow\\ETL\\Join","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"joins","example":"join"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"joins","example":"join_each"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxDb21wYXJpc29ufHN0cmluZz58Q29tcGFyaXNvbiAkY29tcGFyaXNvbnMKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1953,"slug":"schema-sort-by-name","name":"schema_sort_by_name","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"order","type":[{"name":"SortOrder","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Row\\SortOrder::..."}],"return_type":[{"name":"SortingStrategy","namespace":"Flow\\ETL\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1962,"slug":"schema-sort-by-type","name":"schema_sort_by_type","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"priorities","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[...]"},{"name":"order","type":[{"name":"SortOrder","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Row\\SortOrder::..."}],"return_type":[{"name":"SortingStrategy","namespace":"Flow\\ETL\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxjbGFzcy1zdHJpbmc8VHlwZTxtaXhlZD4+LCBpbnQ+ICRwcmlvcml0aWVzCiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1973,"slug":"schema-sort-by-type-and-name","name":"schema_sort_by_type_and_name","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"priorities","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[...]"},{"name":"order","type":[{"name":"SortOrder","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Row\\SortOrder::..."}],"return_type":[{"name":"SortingStrategy","namespace":"Flow\\ETL\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxjbGFzcy1zdHJpbmc8VHlwZTxtaXhlZD4+LCBpbnQ+ICRwcmlvcml0aWVzCiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1984,"slug":"schema-sort-by-metadata","name":"schema_sort_by_metadata","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"key","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":"order","type":[{"name":"SortOrder","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Row\\SortOrder::..."}],"return_type":[{"name":"SortingStrategy","namespace":"Flow\\ETL\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1994,"slug":"is-type","name":"is_type","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"type","type":[{"name":"Type","namespace":"Flow\\Types","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},{"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":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxzdHJpbmd8VHlwZTxtaXhlZD4+fFR5cGU8bWl4ZWQ+ICR0eXBlCiAqIEBwYXJhbSBtaXhlZCAkdmFsdWUKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2028,"slug":"generate-random-string","name":"generate_random_string","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"length","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"32"},{"name":"generator","type":[{"name":"RandomValueGenerator","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\NativePHPRandomValueGenerator::..."}],"return_type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2036,"slug":"generate-random-int","name":"generate_random_int","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"start","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"-9223372036854775808"},{"name":"end","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"9223372036854775807"},{"name":"generator","type":[{"name":"RandomValueGenerator","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\NativePHPRandomValueGenerator::..."}],"return_type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2045,"slug":"random-string","name":"random_string","namespace":"Flow\\ETL\\DSL","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":"generator","type":[{"name":"RandomValueGenerator","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\NativePHPRandomValueGenerator::..."}],"return_type":[{"name":"RandomString","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2053,"slug":"date-interval-to-milliseconds","name":"date_interval_to_milliseconds","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"interval","type":[{"name":"DateInterval","namespace":"","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2070,"slug":"date-interval-to-seconds","name":"date_interval_to_seconds","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"interval","type":[{"name":"DateInterval","namespace":"","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2087,"slug":"date-interval-to-microseconds","name":"date_interval_to_microseconds","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"interval","type":[{"name":"DateInterval","namespace":"","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2104,"slug":"with-entry","name":"with_entry","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"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":"WithEntry","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2110,"slug":"constraint-unique","name":"constraint_unique","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"reference","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":"references","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":"UniqueConstraint","namespace":"Flow\\ETL\\Constraint","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2116,"slug":"constraint-sorted-by","name":"constraint_sorted_by","namespace":"Flow\\ETL\\DSL","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":"columns","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":"SortedByConstraint","namespace":"Flow\\ETL\\Constraint","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2126,"slug":"analyze","name":"analyze","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"Analyze","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2135,"slug":"match-cases","name":"match_cases","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"cases","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":"default","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"MatchCases","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxNYXRjaENvbmRpdGlvbj4gJGNhc2VzCiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2141,"slug":"match-condition","name":"match_condition","namespace":"Flow\\ETL\\DSL","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":"then","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":"MatchCondition","namespace":"Flow\\ETL\\Function\\MatchCases","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2147,"slug":"retry-any-throwable","name":"retry_any_throwable","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"limit","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":"AnyThrowable","namespace":"Flow\\ETL\\Retry\\RetryStrategy","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2156,"slug":"retry-on-exception-types","name":"retry_on_exception_types","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"exception_types","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":"limit","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":"OnExceptionTypes","namespace":"Flow\\ETL\\Retry\\RetryStrategy","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxjbGFzcy1zdHJpbmc8XFRocm93YWJsZT4+ICRleGNlcHRpb25fdHlwZXMKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2165,"slug":"retry-any-throwable-except","name":"retry_any_throwable_except","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"exception_types","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":"limit","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":"AnyThrowableExcept","namespace":"Flow\\ETL\\Retry\\RetryStrategy","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxjbGFzcy1zdHJpbmc8XFRocm93YWJsZT4+ICRleGNlcHRpb25fdHlwZXMKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2171,"slug":"delay-linear","name":"delay_linear","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"delay","type":[{"name":"Duration","namespace":"Flow\\ETL\\Time","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"increment","type":[{"name":"Duration","namespace":"Flow\\ETL\\Time","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Linear","namespace":"Flow\\ETL\\Retry\\DelayFactory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2177,"slug":"delay-exponential","name":"delay_exponential","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"base","type":[{"name":"Duration","namespace":"Flow\\ETL\\Time","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"multiplier","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"2"},{"name":"max_delay","type":[{"name":"Duration","namespace":"Flow\\ETL\\Time","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Exponential","namespace":"Flow\\ETL\\Retry\\DelayFactory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2186,"slug":"delay-jitter","name":"delay_jitter","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"delay","type":[{"name":"DelayFactory","namespace":"Flow\\ETL\\Retry","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"jitter_factor","type":[{"name":"float","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Jitter","namespace":"Flow\\ETL\\Retry\\DelayFactory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBmbG9hdCAkaml0dGVyX2ZhY3RvciBhIHZhbHVlIGJldHdlZW4gMCBhbmQgMSByZXByZXNlbnRpbmcgdGhlIG1heGltdW0gcGVyY2VudGFnZSBvZiBqaXR0ZXIgdG8gYXBwbHkKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2192,"slug":"delay-fixed","name":"delay_fixed","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"delay","type":[{"name":"Duration","namespace":"Flow\\ETL\\Time","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Fixed","namespace":"Flow\\ETL\\Retry\\DelayFactory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2198,"slug":"duration-seconds","name":"duration_seconds","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"seconds","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":"Duration","namespace":"Flow\\ETL\\Time","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2204,"slug":"duration-milliseconds","name":"duration_milliseconds","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"milliseconds","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":"Duration","namespace":"Flow\\ETL\\Time","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2210,"slug":"duration-microseconds","name":"duration_microseconds","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"microseconds","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":"Duration","namespace":"Flow\\ETL\\Time","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2216,"slug":"duration-minutes","name":"duration_minutes","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"minutes","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":"Duration","namespace":"Flow\\ETL\\Time","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2222,"slug":"write-with-retries","name":"write_with_retries","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"loader","type":[{"name":"Loader","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"retry_strategy","type":[{"name":"RetryStrategy","namespace":"Flow\\ETL\\Retry","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Retry\\RetryStrategy\\AnyThrowableExcept::..."},{"name":"delay_factory","type":[{"name":"DelayFactory","namespace":"Flow\\ETL\\Retry","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Retry\\DelayFactory\\Fixed\\FixedMilliseconds::..."},{"name":"sleep","type":[{"name":"Sleep","namespace":"Flow\\ETL\\Time","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Time\\SystemSleep::..."}],"return_type":[{"name":"RetryLoader","namespace":"Flow\\ETL\\Loader","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2232,"slug":"clock","name":"clock","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"time_zone","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'UTC'"}],"return_type":[{"name":"ClockInterface","namespace":"Psr\\Clock","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/Floe\/DSL\/functions.php","start_line_in_file":31,"slug":"from-floe","name":"from_floe","namespace":"Flow\\Floe\\DSL","parameters":[{"name":"path","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"codec","type":[{"name":"Codec","namespace":"Flow\\Floe","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Floe\\Codec\\NoopCodec::..."},{"name":"chunk_size","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"65536"},{"name":"engine","type":[{"name":"FloeEngine","namespace":"Flow\\Floe","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Floe\\FloeEngine::..."},{"name":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"FloeExtractor","namespace":"Flow\\Floe","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"FLOE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBQYXRofHN0cmluZyAkcGF0aAogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/Floe\/DSL\/functions.php","start_line_in_file":45,"slug":"to-floe","name":"to_floe","namespace":"Flow\\Floe\\DSL","parameters":[{"name":"path","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"options","type":[{"name":"Options","namespace":"Flow\\Floe","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Floe\\Options::..."},{"name":"engine","type":[{"name":"FloeEngine","namespace":"Flow\\Floe","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Floe\\FloeEngine::..."},{"name":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"FloeLoader","namespace":"Flow\\Floe","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"FLOE","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBQYXRofHN0cmluZyAkcGF0aAogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/Floe\/DSL\/functions.php","start_line_in_file":56,"slug":"floe-options","name":"floe_options","namespace":"Flow\\Floe\\DSL","parameters":[{"name":"buffer_size","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"65536"},{"name":"codec","type":[{"name":"Codec","namespace":"Flow\\Floe","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Floe\\Codec\\NoopCodec::..."}],"return_type":[{"name":"Options","namespace":"Flow\\Floe","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"FLOE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/Floe\/DSL\/functions.php","start_line_in_file":68,"slug":"merge-floe","name":"merge_floe","namespace":"Flow\\Floe\\DSL","parameters":[{"name":"sources","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":"dest","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"compact","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"void","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"FLOE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIE1lcmdlcyBzZXZlcmFsIEZsb2UgZmlsZXMgKHNhbWUgb3IgYXBwZW5kLWNvbXBhdGlibGUgZXZvbHZpbmcgc2NoZW1hKSBpbnRvIG9uZS4gQnl0ZS1zcGxpY2VzIGZyYW1lCiAqIHJlZ2lvbnMgYnkgZGVmYXVsdCAoTyhieXRlcyksIG5vIHJlLWVuY29kZSk7IGNvbXBhY3QgcmUtZW5jb2RlcyBhbGwgcm93cyBpbnRvIGZld2VyIHNlY3Rpb25zLgogKgogKiBAcGFyYW0gYXJyYXk8aW50LCBQYXRofHN0cmluZz4gJHNvdXJjZXMKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/Serializer\/DSL\/functions.php","start_line_in_file":18,"slug":"serialize-to-string","name":"serialize_to_string","namespace":"Flow\\Serializer\\DSL","parameters":[{"name":"serializer","type":[{"name":"Serializer","namespace":"Flow\\Serializer","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"rows","type":[{"name":"Rows","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":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/Serializer\/DSL\/functions.php","start_line_in_file":27,"slug":"unserialize-from-string","name":"unserialize_from_string","namespace":"Flow\\Serializer\\DSL","parameters":[{"name":"serializer","type":[{"name":"Serializer","namespace":"Flow\\Serializer","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"payload","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":"Rows","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-avro\/src\/Flow\/ETL\/Adapter\/Avro\/functions.php","start_line_in_file":21,"slug":"from-avro","name":"from_avro","namespace":"Flow\\ETL\\DSL\\Adapter\\Avro","parameters":[{"name":"path","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"AvroExtractor","namespace":"Flow\\ETL\\Adapter\\Avro\\FlixTech","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"AVRO","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-avro\/src\/Flow\/ETL\/Adapter\/Avro\/functions.php","start_line_in_file":27,"slug":"to-avro","name":"to_avro","namespace":"Flow\\ETL\\DSL\\Adapter\\Avro","parameters":[{"name":"path","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"schema","type":[{"name":"Schema","namespace":"Flow\\ETL","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"AvroLoader","namespace":"Flow\\ETL\\Adapter\\Avro\\FlixTech","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"AVRO","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-chartjs\/src\/Flow\/ETL\/Adapter\/ChartJS\/functions.php","start_line_in_file":23,"slug":"bar-chart","name":"bar_chart","namespace":"Flow\\ETL\\Adapter\\ChartJS","parameters":[{"name":"label","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":"datasets","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":"BarChart","namespace":"Flow\\ETL\\Adapter\\ChartJS\\Chart","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CHART_JS","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-chartjs\/src\/Flow\/ETL\/Adapter\/ChartJS\/functions.php","start_line_in_file":29,"slug":"line-chart","name":"line_chart","namespace":"Flow\\ETL\\Adapter\\ChartJS","parameters":[{"name":"label","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":"datasets","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":"LineChart","namespace":"Flow\\ETL\\Adapter\\ChartJS\\Chart","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CHART_JS","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-chartjs\/src\/Flow\/ETL\/Adapter\/ChartJS\/functions.php","start_line_in_file":35,"slug":"pie-chart","name":"pie_chart","namespace":"Flow\\ETL\\Adapter\\ChartJS","parameters":[{"name":"label","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":"datasets","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":"PieChart","namespace":"Flow\\ETL\\Adapter\\ChartJS\\Chart","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CHART_JS","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-chartjs\/src\/Flow\/ETL\/Adapter\/ChartJS\/functions.php","start_line_in_file":41,"slug":"to-chartjs","name":"to_chartjs","namespace":"Flow\\ETL\\Adapter\\ChartJS","parameters":[{"name":"type","type":[{"name":"Chart","namespace":"Flow\\ETL\\Adapter\\ChartJS","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ChartJSLoader","namespace":"Flow\\ETL\\Adapter\\ChartJS","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CHART_JS","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-chartjs\/src\/Flow\/ETL\/Adapter\/ChartJS\/functions.php","start_line_in_file":52,"slug":"to-chartjs-file","name":"to_chartjs_file","namespace":"Flow\\ETL\\Adapter\\ChartJS","parameters":[{"name":"type","type":[{"name":"Chart","namespace":"Flow\\ETL\\Adapter\\ChartJS","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"output","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"template","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"ChartJSLoader","namespace":"Flow\\ETL\\Adapter\\ChartJS","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CHART_JS","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBDaGFydCAkdHlwZQogKiBAcGFyYW0gbnVsbHxQYXRofHN0cmluZyAkb3V0cHV0IC0gQGRlcHJlY2F0ZWQgdXNlICRsb2FkZXItPndpdGhPdXRwdXRQYXRoKCkgaW5zdGVhZAogKiBAcGFyYW0gbnVsbHxQYXRofHN0cmluZyAkdGVtcGxhdGUgLSBAZGVwcmVjYXRlZCB1c2UgJGxvYWRlci0+d2l0aFRlbXBsYXRlKCkgaW5zdGVhZAogKi8="},{"repository_path":"src\/adapter\/etl-adapter-chartjs\/src\/Flow\/ETL\/Adapter\/ChartJS\/functions.php","start_line_in_file":84,"slug":"to-chartjs-var","name":"to_chartjs_var","namespace":"Flow\\ETL\\Adapter\\ChartJS","parameters":[{"name":"type","type":[{"name":"Chart","namespace":"Flow\\ETL\\Adapter\\ChartJS","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"output","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":"ChartJSLoader","namespace":"Flow\\ETL\\Adapter\\ChartJS","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CHART_JS","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBDaGFydCAkdHlwZQogKiBAcGFyYW0gYXJyYXk8YXJyYXkta2V5LCBtaXhlZD4gJG91dHB1dCAtIEBkZXByZWNhdGVkIHVzZSAkbG9hZGVyLT53aXRoT3V0cHV0VmFyKCkgaW5zdGVhZAogKi8="},{"repository_path":"src\/adapter\/etl-adapter-csv\/src\/Flow\/ETL\/Adapter\/CSV\/functions.php","start_line_in_file":35,"slug":"from-csv","name":"from_csv","namespace":"Flow\\ETL\\Adapter\\CSV","parameters":[{"name":"path","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"with_header","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"empty_to_null","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"separator","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":"enclosure","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":"escape","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":"characters_read_in_line","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"10485760"},{"name":"schema","type":[{"name":"Schema","namespace":"Flow\\ETL","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"CSVExtractor","namespace":"Flow\\ETL\\Adapter\\CSV","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CSV","type":"EXTRACTOR"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"reading","example":"csv"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBQYXRofHN0cmluZyAkcGF0aAogKiBAcGFyYW0gYm9vbCAkZW1wdHlfdG9fbnVsbCAtIEBkZXByZWNhdGVkIHVzZSAkbG9hZGVyLT53aXRoRW1wdHlUb051bGwoKSBpbnN0ZWFkCiAqIEBwYXJhbSBib29sICR3aXRoX2hlYWRlciAtIEBkZXByZWNhdGVkIHVzZSAkbG9hZGVyLT53aXRoSGVhZGVyKCkgaW5zdGVhZAogKiBAcGFyYW0gbnVsbHxzdHJpbmcgJHNlcGFyYXRvciAtIEBkZXByZWNhdGVkIHVzZSAkbG9hZGVyLT53aXRoU2VwYXJhdG9yKCkgaW5zdGVhZAogKiBAcGFyYW0gbnVsbHxzdHJpbmcgJGVuY2xvc3VyZSAtIEBkZXByZWNhdGVkIHVzZSAkbG9hZGVyLT53aXRoRW5jbG9zdXJlKCkgaW5zdGVhZAogKiBAcGFyYW0gbnVsbHxzdHJpbmcgJGVzY2FwZSAtIEBkZXByZWNhdGVkIHVzZSAkbG9hZGVyLT53aXRoRXNjYXBlKCkgaW5zdGVhZAogKiBAcGFyYW0gaW50PDEsIG1heD4gJGNoYXJhY3RlcnNfcmVhZF9pbl9saW5lIC0gQGRlcHJlY2F0ZWQgdXNlICRsb2FkZXItPndpdGhDaGFyYWN0ZXJzUmVhZEluTGluZSgpIGluc3RlYWQKICogQHBhcmFtIG51bGx8U2NoZW1hICRzY2hlbWEgLSBAZGVwcmVjYXRlZCB1c2UgJGxvYWRlci0+d2l0aFNjaGVtYSgpIGluc3RlYWQKICov"},{"repository_path":"src\/adapter\/etl-adapter-csv\/src\/Flow\/ETL\/Adapter\/CSV\/functions.php","start_line_in_file":80,"slug":"to-csv","name":"to_csv","namespace":"Flow\\ETL\\Adapter\\CSV","parameters":[{"name":"uri","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"with_header","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"separator","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"','"},{"name":"enclosure","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'\\\"'"},{"name":"escape","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'\\\\'"},{"name":"new_line_separator","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'\\n'"},{"name":"datetime_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\\\\TH:i:sP'"},{"name":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"CSVLoader","namespace":"Flow\\ETL\\Adapter\\CSV","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CSV","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBQYXRofHN0cmluZyAkdXJpCiAqIEBwYXJhbSBib29sICR3aXRoX2hlYWRlciAtIEBkZXByZWNhdGVkIHVzZSAkbG9hZGVyLT53aXRoSGVhZGVyKCkgaW5zdGVhZAogKiBAcGFyYW0gc3RyaW5nICRzZXBhcmF0b3IgLSBAZGVwcmVjYXRlZCB1c2UgJGxvYWRlci0+d2l0aFNlcGFyYXRvcigpIGluc3RlYWQKICogQHBhcmFtIHN0cmluZyAkZW5jbG9zdXJlIC0gQGRlcHJlY2F0ZWQgdXNlICRsb2FkZXItPndpdGhFbmNsb3N1cmUoKSBpbnN0ZWFkCiAqIEBwYXJhbSBzdHJpbmcgJGVzY2FwZSAtIEBkZXByZWNhdGVkIHVzZSAkbG9hZGVyLT53aXRoRXNjYXBlKCkgaW5zdGVhZAogKiBAcGFyYW0gc3RyaW5nICRuZXdfbGluZV9zZXBhcmF0b3IgLSBAZGVwcmVjYXRlZCB1c2UgJGxvYWRlci0+d2l0aE5ld0xpbmVTZXBhcmF0b3IoKSBpbnN0ZWFkCiAqIEBwYXJhbSBzdHJpbmcgJGRhdGV0aW1lX2Zvcm1hdCAtIEBkZXByZWNhdGVkIHVzZSAkbG9hZGVyLT53aXRoRGF0ZVRpbWVGb3JtYXQoKSBpbnN0ZWFkCiAqLw=="},{"repository_path":"src\/adapter\/etl-adapter-csv\/src\/Flow\/ETL\/Adapter\/CSV\/functions.php","start_line_in_file":106,"slug":"csv-detect-separator","name":"csv_detect_separator","namespace":"Flow\\ETL\\Adapter\\CSV","parameters":[{"name":"stream","type":[{"name":"SourceStream","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"lines","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"5"},{"name":"fallback","type":[{"name":"Option","namespace":"Flow\\ETL\\Adapter\\CSV\\Detector","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"Flow\\ETL\\Adapter\\CSV\\Detector\\Option::..."},{"name":"options","type":[{"name":"Options","namespace":"Flow\\ETL\\Adapter\\CSV\\Detector","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Option","namespace":"Flow\\ETL\\Adapter\\CSV\\Detector","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CSV","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBTb3VyY2VTdHJlYW0gJHN0cmVhbSAtIHZhbGlkIHJlc291cmNlIHRvIENTViBmaWxlCiAqIEBwYXJhbSBpbnQ8MSwgbWF4PiAkbGluZXMgLSBudW1iZXIgb2YgbGluZXMgdG8gcmVhZCBmcm9tIENTViBmaWxlLCBkZWZhdWx0IDUsIG1vcmUgbGluZXMgbWVhbnMgbW9yZSBhY2N1cmF0ZSBkZXRlY3Rpb24gYnV0IHNsb3dlciBkZXRlY3Rpb24KICogQHBhcmFtIG51bGx8T3B0aW9uICRmYWxsYmFjayAtIGZhbGxiYWNrIG9wdGlvbiB0byB1c2Ugd2hlbiBubyBiZXN0IG9wdGlvbiBjYW4gYmUgZGV0ZWN0ZWQsIGRlZmF1bHQgaXMgT3B0aW9uKCcsJywgJyInLCAnXFwnKQogKiBAcGFyYW0gbnVsbHxPcHRpb25zICRvcHRpb25zIC0gb3B0aW9ucyB0byB1c2UgZm9yIGRldGVjdGlvbiwgZGVmYXVsdCBpcyBPcHRpb25zOjphbGwoKQogKi8="},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":39,"slug":"dbal-dataframe-factory","name":"dbal_dataframe_factory","namespace":"Flow\\ETL\\Adapter\\Doctrine","parameters":[{"name":"connection","type":[{"name":"Connection","namespace":"Doctrine\\DBAL","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},{"name":"query","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":"parameters","type":[{"name":"QueryParameter","namespace":"Flow\\ETL\\Adapter\\Doctrine","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"DbalDataFrameFactory","namespace":"Flow\\ETL\\Adapter\\Doctrine","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"DOCTRINE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxzdHJpbmcsIG1peGVkPnxDb25uZWN0aW9uICRjb25uZWN0aW9uCiAqIEBwYXJhbSBzdHJpbmcgJHF1ZXJ5CiAqIEBwYXJhbSBRdWVyeVBhcmFtZXRlciAuLi4kcGFyYW1ldGVycwogKi8="},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":59,"slug":"from-dbal-limit-offset","name":"from_dbal_limit_offset","namespace":"Flow\\ETL\\Adapter\\Doctrine","parameters":[{"name":"connection","type":[{"name":"Connection","namespace":"Doctrine\\DBAL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"table","type":[{"name":"Table","namespace":"Flow\\ETL\\Adapter\\Doctrine","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":"order_by","type":[{"name":"OrderBy","namespace":"Flow\\ETL\\Adapter\\Doctrine","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},{"name":"page_size","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"1000"},{"name":"maximum","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":"DbalLimitOffsetExtractor","namespace":"Flow\\ETL\\Adapter\\Doctrine","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"DOCTRINE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBDb25uZWN0aW9uICRjb25uZWN0aW9uCiAqIEBwYXJhbSBzdHJpbmd8VGFibGUgJHRhYmxlCiAqIEBwYXJhbSBhcnJheTxPcmRlckJ5PnxPcmRlckJ5ICRvcmRlcl9ieQogKiBAcGFyYW0gaW50ICRwYWdlX3NpemUgLSBiZWNvbWVzIHRoZSBleHRyYWN0b3IncyBiYXRjaCBzaXplOiByb3dzIHBlciBwYWdlCiAqIEBwYXJhbSBudWxsfGludCAkbWF4aW11bQogKgogKiBAdGhyb3dzIEludmFsaWRBcmd1bWVudEV4Y2VwdGlvbgogKi8="},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":86,"slug":"from-dbal-limit-offset-qb","name":"from_dbal_limit_offset_qb","namespace":"Flow\\ETL\\Adapter\\Doctrine","parameters":[{"name":"connection","type":[{"name":"Connection","namespace":"Doctrine\\DBAL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"queryBuilder","type":[{"name":"QueryBuilder","namespace":"Doctrine\\DBAL\\Query","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"page_size","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"1000"},{"name":"maximum","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":"offset","type":[{"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":"DbalLimitOffsetExtractor","namespace":"Flow\\ETL\\Adapter\\Doctrine","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"DOCTRINE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBDb25uZWN0aW9uICRjb25uZWN0aW9uCiAqIEBwYXJhbSBpbnQgJHBhZ2Vfc2l6ZSAtIGJlY29tZXMgdGhlIGV4dHJhY3RvcidzIGJhdGNoIHNpemU6IHJvd3MgcGVyIHBhZ2UKICogQHBhcmFtIG51bGx8aW50ICRtYXhpbXVtIC0gbWF4aW11bSBjYW4gYWxzbyBiZSB0YWtlbiBmcm9tIGEgcXVlcnkgYnVpbGRlciwgJG1heGltdW0gaG93ZXZlciBpcyB1c2VkIHJlZ2FyZGxlc3Mgb2YgdGhlIHF1ZXJ5IGJ1aWxkZXIgaWYgaXQncyBzZXQKICogQHBhcmFtIGludCAkb2Zmc2V0IC0gb2Zmc2V0IGNhbiBhbHNvIGJlIHRha2VuIGZyb20gYSBxdWVyeSBidWlsZGVyLCAkb2Zmc2V0IGhvd2V2ZXIgaXMgdXNlZCByZWdhcmRsZXNzIG9mIHRoZSBxdWVyeSBidWlsZGVyIGlmIGl0J3Mgc2V0IHRvIG5vbiAwIHZhbHVlCiAqLw=="},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":105,"slug":"from-dbal-key-set-qb","name":"from_dbal_key_set_qb","namespace":"Flow\\ETL\\Adapter\\Doctrine","parameters":[{"name":"connection","type":[{"name":"Connection","namespace":"Doctrine\\DBAL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"queryBuilder","type":[{"name":"QueryBuilder","namespace":"Doctrine\\DBAL\\Query","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"key_set","type":[{"name":"KeySet","namespace":"Flow\\ETL\\Adapter\\Doctrine\\Pagination","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"DbalKeySetExtractor","namespace":"Flow\\ETL\\Adapter\\Doctrine","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"DOCTRINE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":115,"slug":"from-dbal-queries","name":"from_dbal_queries","namespace":"Flow\\ETL\\Adapter\\Doctrine","parameters":[{"name":"connection","type":[{"name":"Connection","namespace":"Doctrine\\DBAL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"query","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":"parameters_set","type":[{"name":"ParametersSet","namespace":"Flow\\ETL\\Adapter\\Doctrine","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"types","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"DbalQueryExtractor","namespace":"Flow\\ETL\\Adapter\\Doctrine","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"DOCTRINE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBudWxsfFBhcmFtZXRlcnNTZXQgJHBhcmFtZXRlcnNfc2V0IC0gZWFjaCBvbmUgcGFyYW1ldGVycyBhcnJheSB3aWxsIGJlIGV2YWx1YXRlZCBhcyBuZXcgcXVlcnkKICogQHBhcmFtIGFycmF5PGludDwwLCBtYXg+fHN0cmluZywgRGJhbEFycmF5VHlwZXxEYmFsUGFyYW1ldGVyVHlwZXxEYmFsVHlwZXxzdHJpbmc+ICR0eXBlcwogKi8="},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":141,"slug":"dbal-from-queries","name":"dbal_from_queries","namespace":"Flow\\ETL\\Adapter\\Doctrine","parameters":[{"name":"connection","type":[{"name":"Connection","namespace":"Doctrine\\DBAL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"query","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":"parameters_set","type":[{"name":"ParametersSet","namespace":"Flow\\ETL\\Adapter\\Doctrine","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"types","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"DbalQueryExtractor","namespace":"Flow\\ETL\\Adapter\\Doctrine","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"DOCTRINE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBkZXByZWNhdGVkIHVzZSBmcm9tX2RiYWxfcXVlcmllcygpIGluc3RlYWQKICoKICogQHBhcmFtIG51bGx8UGFyYW1ldGVyc1NldCAkcGFyYW1ldGVyc19zZXQgLSBlYWNoIG9uZSBwYXJhbWV0ZXJzIGFycmF5IHdpbGwgYmUgZXZhbHVhdGVkIGFzIG5ldyBxdWVyeQogKiBAcGFyYW0gYXJyYXk8aW50PDAsIG1heD58c3RyaW5nLCBEYmFsQXJyYXlUeXBlfERiYWxQYXJhbWV0ZXJUeXBlfERiYWxUeXBlfHN0cmluZz4gJHR5cGVzCiAqLw=="},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":155,"slug":"from-dbal-query","name":"from_dbal_query","namespace":"Flow\\ETL\\Adapter\\Doctrine","parameters":[{"name":"connection","type":[{"name":"Connection","namespace":"Doctrine\\DBAL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"query","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":"parameters","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"types","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"DbalQueryExtractor","namespace":"Flow\\ETL\\Adapter\\Doctrine","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"DOCTRINE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxzdHJpbmcsIG1peGVkPnxsaXN0PG1peGVkPiAkcGFyYW1ldGVycyAtIEBkZXByZWNhdGVkIHVzZSBEYmFsUXVlcnlFeHRyYWN0b3I6OndpdGhQYXJhbWV0ZXJzKCkgaW5zdGVhZAogKiBAcGFyYW0gYXJyYXk8aW50PDAsIG1heD58c3RyaW5nLCBEYmFsQXJyYXlUeXBlfERiYWxQYXJhbWV0ZXJUeXBlfERiYWxUeXBlfHN0cmluZz4gJHR5cGVzIC0gQGRlcHJlY2F0ZWQgdXNlIERiYWxRdWVyeUV4dHJhY3Rvcjo6d2l0aFR5cGVzKCkgaW5zdGVhZAogKi8="},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":171,"slug":"dbal-from-query","name":"dbal_from_query","namespace":"Flow\\ETL\\Adapter\\Doctrine","parameters":[{"name":"connection","type":[{"name":"Connection","namespace":"Doctrine\\DBAL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"query","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":"parameters","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"types","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"DbalQueryExtractor","namespace":"Flow\\ETL\\Adapter\\Doctrine","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"DOCTRINE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBkZXByZWNhdGVkIHVzZSBmcm9tX2RiYWxfcXVlcnkoKSBpbnN0ZWFkCiAqCiAqIEBwYXJhbSBhcnJheTxzdHJpbmcsIG1peGVkPnxsaXN0PG1peGVkPiAkcGFyYW1ldGVycyAtIEBkZXByZWNhdGVkIHVzZSBEYmFsUXVlcnlFeHRyYWN0b3I6OndpdGhQYXJhbWV0ZXJzKCkgaW5zdGVhZAogKiBAcGFyYW0gYXJyYXk8aW50PDAsIG1heD58c3RyaW5nLCBEYmFsQXJyYXlUeXBlfERiYWxQYXJhbWV0ZXJUeXBlfERiYWxUeXBlfHN0cmluZz4gJHR5cGVzIC0gQGRlcHJlY2F0ZWQgdXNlIERiYWxRdWVyeUV4dHJhY3Rvcjo6d2l0aFR5cGVzKCkgaW5zdGVhZAogKi8="},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":197,"slug":"to-dbal-table-insert","name":"to_dbal_table_insert","namespace":"Flow\\ETL\\Adapter\\Doctrine","parameters":[{"name":"connection","type":[{"name":"Connection","namespace":"Doctrine\\DBAL","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},{"name":"table","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":"options","type":[{"name":"InsertOptions","namespace":"Flow\\Doctrine\\Bulk","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"DbalLoader","namespace":"Flow\\ETL\\Adapter\\Doctrine","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"DOCTRINE","type":"LOADER"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"writing","example":"dbal","option":"upsert"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEluc2VydCBuZXcgcm93cyBpbnRvIGEgZGF0YWJhc2UgdGFibGUuCiAqIEluc2VydCBjYW4gYWxzbyBiZSB1c2VkIGFzIGFuIHVwc2VydCB3aXRoIHRoZSBoZWxwIG9mIEluc2VydE9wdGlvbnMuCiAqIEluc2VydE9wdGlvbnMgYXJlIHBsYXRmb3JtIHNwZWNpZmljLCBzbyBwbGVhc2UgY2hvb3NlIHRoZSByaWdodCBvbmUgZm9yIHlvdXIgZGF0YWJhc2UuCiAqCiAqICAtIE15U1FMSW5zZXJ0T3B0aW9ucwogKiAgLSBQb3N0Z3JlU1FMSW5zZXJ0T3B0aW9ucwogKiAgLSBTcWxpdGVJbnNlcnRPcHRpb25zCiAqCiAqIEluIG9yZGVyIHRvIGNvbnRyb2wgdGhlIHNpemUgb2YgdGhlIHNpbmdsZSBpbnNlcnQsIHVzZSBEYXRhRnJhbWU6OmNodW5rU2l6ZSgpIG1ldGhvZCBqdXN0IGJlZm9yZSBjYWxsaW5nIERhdGFGcmFtZTo6bG9hZCgpLgogKgogKiBAcGFyYW0gYXJyYXk8c3RyaW5nLCBtaXhlZD58Q29ubmVjdGlvbiAkY29ubmVjdGlvbgogKgogKiBAdGhyb3dzIEludmFsaWRBcmd1bWVudEV4Y2VwdGlvbgogKi8="},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":214,"slug":"to-dbal-table-update","name":"to_dbal_table_update","namespace":"Flow\\ETL\\Adapter\\Doctrine","parameters":[{"name":"connection","type":[{"name":"Connection","namespace":"Doctrine\\DBAL","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},{"name":"table","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":"options","type":[{"name":"UpdateOptions","namespace":"Flow\\Doctrine\\Bulk","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"DbalLoader","namespace":"Flow\\ETL\\Adapter\\Doctrine","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"DOCTRINE","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqICBVcGRhdGUgZXhpc3Rpbmcgcm93cyBpbiBkYXRhYmFzZS4KICoKICogIEluIG9yZGVyIHRvIGNvbnRyb2wgdGhlIHNpemUgb2YgdGhlIHNpbmdsZSByZXF1ZXN0LCB1c2UgRGF0YUZyYW1lOjpjaHVua1NpemUoKSBtZXRob2QganVzdCBiZWZvcmUgY2FsbGluZyBEYXRhRnJhbWU6OmxvYWQoKS4KICoKICogQHBhcmFtIGFycmF5PHN0cmluZywgbWl4ZWQ+fENvbm5lY3Rpb24gJGNvbm5lY3Rpb24KICoKICogQHRocm93cyBJbnZhbGlkQXJndW1lbnRFeGNlcHRpb24KICov"},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":233,"slug":"to-dbal-table-delete","name":"to_dbal_table_delete","namespace":"Flow\\ETL\\Adapter\\Doctrine","parameters":[{"name":"connection","type":[{"name":"Connection","namespace":"Doctrine\\DBAL","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},{"name":"table","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":"DbalLoader","namespace":"Flow\\ETL\\Adapter\\Doctrine","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"DOCTRINE","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIERlbGV0ZSByb3dzIGZyb20gZGF0YWJhc2UgdGFibGUgYmFzZWQgb24gdGhlIHByb3ZpZGVkIGRhdGEuCiAqCiAqIEluIG9yZGVyIHRvIGNvbnRyb2wgdGhlIHNpemUgb2YgdGhlIHNpbmdsZSByZXF1ZXN0LCB1c2UgRGF0YUZyYW1lOjpjaHVua1NpemUoKSBtZXRob2QganVzdCBiZWZvcmUgY2FsbGluZyBEYXRhRnJhbWU6OmxvYWQoKS4KICoKICogQHBhcmFtIGFycmF5PHN0cmluZywgbWl4ZWQ+fENvbm5lY3Rpb24gJGNvbm5lY3Rpb24KICoKICogQHRocm93cyBJbnZhbGlkQXJndW1lbnRFeGNlcHRpb24KICov"},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":248,"slug":"to-dbal-schema-table","name":"to_dbal_schema_table","namespace":"Flow\\ETL\\Adapter\\Doctrine","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":"table_name","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":"table_options","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"types_map","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"Table","namespace":"Doctrine\\DBAL\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"DOCTRINE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENvbnZlcnRzIGEgRmxvd1xFVExcU2NoZW1hIHRvIGEgRG9jdHJpbmVcREJBTFxTY2hlbWFcVGFibGUuCiAqCiAqIEBwYXJhbSBTY2hlbWEgJHNjaGVtYQogKiBAcGFyYW0gYXJyYXk8c3RyaW5nLCBtaXhlZD4gJHRhYmxlX29wdGlvbnMKICogQHBhcmFtIGFycmF5PGNsYXNzLXN0cmluZzxcRmxvd1xUeXBlc1xUeXBlPG1peGVkPj4sIGNsYXNzLXN0cmluZzxcRG9jdHJpbmVcREJBTFxUeXBlc1xUeXBlPj4gJHR5cGVzX21hcAogKi8="},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":265,"slug":"table-schema-to-flow-schema","name":"table_schema_to_flow_schema","namespace":"Flow\\ETL\\Adapter\\Doctrine","parameters":[{"name":"table","type":[{"name":"Table","namespace":"Doctrine\\DBAL\\Schema","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"types_map","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"Schema","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"DOCTRINE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENvbnZlcnRzIGEgRG9jdHJpbmVcREJBTFxTY2hlbWFcVGFibGUgdG8gYSBGbG93XEVUTFxTY2hlbWEuCiAqCiAqIEBwYXJhbSBhcnJheTxjbGFzcy1zdHJpbmc8XEZsb3dcVHlwZXNcVHlwZTxtaXhlZD4+LCBjbGFzcy1zdHJpbmc8XERvY3RyaW5lXERCQUxcVHlwZXNcVHlwZT4+ICR0eXBlc19tYXAKICoKICogQHJldHVybiBTY2hlbWEKICov"},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":276,"slug":"postgresql-insert-options","name":"postgresql_insert_options","namespace":"Flow\\ETL\\Adapter\\Doctrine","parameters":[{"name":"skip_conflicts","type":[{"name":"bool","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"constraint","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":"conflict_columns","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"update_columns","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"PostgreSQLInsertOptions","namespace":"Flow\\Doctrine\\Bulk\\Dialect","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"DOCTRINE","type":"HELPER"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"writing","example":"dbal","option":"upsert"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxzdHJpbmc+ICRjb25mbGljdF9jb2x1bW5zCiAqIEBwYXJhbSBhcnJheTxzdHJpbmc+ICR1cGRhdGVfY29sdW1ucwogKi8="},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":289,"slug":"mysql-insert-options","name":"mysql_insert_options","namespace":"Flow\\ETL\\Adapter\\Doctrine","parameters":[{"name":"skip_conflicts","type":[{"name":"bool","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"upsert","type":[{"name":"bool","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"update_columns","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"MySQLInsertOptions","namespace":"Flow\\Doctrine\\Bulk\\Dialect","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"DOCTRINE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxzdHJpbmc+ICR1cGRhdGVfY29sdW1ucwogKi8="},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":302,"slug":"sqlite-insert-options","name":"sqlite_insert_options","namespace":"Flow\\ETL\\Adapter\\Doctrine","parameters":[{"name":"skip_conflicts","type":[{"name":"bool","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"conflict_columns","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"update_columns","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"SqliteInsertOptions","namespace":"Flow\\Doctrine\\Bulk\\Dialect","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"DOCTRINE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxzdHJpbmc+ICRjb25mbGljdF9jb2x1bW5zCiAqIEBwYXJhbSBhcnJheTxzdHJpbmc+ICR1cGRhdGVfY29sdW1ucwogKi8="},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":315,"slug":"postgresql-update-options","name":"postgresql_update_options","namespace":"Flow\\ETL\\Adapter\\Doctrine","parameters":[{"name":"primary_key_columns","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"update_columns","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"PostgreSQLUpdateOptions","namespace":"Flow\\Doctrine\\Bulk\\Dialect","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"DOCTRINE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxzdHJpbmc+ICRwcmltYXJ5X2tleV9jb2x1bW5zCiAqIEBwYXJhbSBhcnJheTxzdHJpbmc+ICR1cGRhdGVfY29sdW1ucwogKi8="},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":335,"slug":"to-dbal-transaction","name":"to_dbal_transaction","namespace":"Flow\\ETL\\Adapter\\Doctrine","parameters":[{"name":"connection","type":[{"name":"Connection","namespace":"Doctrine\\DBAL","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},{"name":"loaders","type":[{"name":"Loader","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":"TransactionalDbalLoader","namespace":"Flow\\ETL\\Adapter\\Doctrine","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"DOCTRINE","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEV4ZWN1dGUgbXVsdGlwbGUgbG9hZGVycyB3aXRoaW4gZGF0YWJhc2UgdHJhbnNhY3Rpb25zLgogKiBFYWNoIGJhdGNoIG9mIHJvd3MgaXMgbG9hZGVkIGluIGl0cyBvd24gdHJhbnNhY3Rpb247IHJvd3MgYSB3cmFwcGVkIFRyYW5zZm9ybWF0aW9uIGRlbGl2ZXJzIHdoZW4KICogdGhlIGxvYWRlciBpcyBjbG9zZWQgKGJsb2NraW5nIG9wZXJhdGlvbnMgZHJhaW4gdGhlcmUpIGFyZSBjb21taXR0ZWQgaW4gb25lIGZpbmFsIHRyYW5zYWN0aW9uLgogKiBJZiBhbnkgbG9hZGVyIGZhaWxzLCB0aGUgb3BlbiB0cmFuc2FjdGlvbiBpcyByb2xsZWQgYmFjay4KICogQXRvbWljaXR5IHJlcXVpcmVzIGV2ZXJ5IHdyYXBwZWQgbG9hZGVyIHRvIHVzZSB0aGUgc2FtZSBjb25uZWN0aW9uIGFzIHRoZSB3cmFwcGVyOiBwYXNzIG9uZSBsaXZlCiAqIENvbm5lY3Rpb24gdG8gYm90aCAtIGEgd3JhcHBlZCBsb2FkZXIgYnVpbHQgZnJvbSBhcnJheSBwYXJhbXMgb3BlbnMgaXRzIG93biBjb25uZWN0aW9uIGFuZAogKiBlc2NhcGVzIHRoZSB0cmFuc2FjdGlvbi4KICoKICogQHBhcmFtIGFycmF5PHN0cmluZywgbWl4ZWQ+fENvbm5lY3Rpb24gJGNvbm5lY3Rpb24KICogQHBhcmFtIExvYWRlciAuLi4kbG9hZGVycyAtIExvYWRlcnMgdG8gZXhlY3V0ZSB3aXRoaW4gdGhlIHRyYW5zYWN0aW9uCiAqCiAqIEB0aHJvd3MgSW52YWxpZEFyZ3VtZW50RXhjZXB0aW9uCiAqLw=="},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":343,"slug":"pagination-key-asc","name":"pagination_key_asc","namespace":"Flow\\ETL\\Adapter\\Doctrine","parameters":[{"name":"column","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":"type","type":[{"name":"ParameterType","namespace":"Doctrine\\DBAL","is_nullable":false,"is_variadic":false},{"name":"Type","namespace":"Doctrine\\DBAL\\Types","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":"Doctrine\\DBAL\\ParameterType::..."}],"return_type":[{"name":"Key","namespace":"Flow\\ETL\\Adapter\\Doctrine\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"DOCTRINE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":349,"slug":"pagination-key-desc","name":"pagination_key_desc","namespace":"Flow\\ETL\\Adapter\\Doctrine","parameters":[{"name":"column","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":"type","type":[{"name":"ParameterType","namespace":"Doctrine\\DBAL","is_nullable":false,"is_variadic":false},{"name":"Type","namespace":"Doctrine\\DBAL\\Types","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":"Doctrine\\DBAL\\ParameterType::..."}],"return_type":[{"name":"Key","namespace":"Flow\\ETL\\Adapter\\Doctrine\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"DOCTRINE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":355,"slug":"pagination-key-set","name":"pagination_key_set","namespace":"Flow\\ETL\\Adapter\\Doctrine","parameters":[{"name":"keys","type":[{"name":"Key","namespace":"Flow\\ETL\\Adapter\\Doctrine\\Pagination","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"KeySet","namespace":"Flow\\ETL\\Adapter\\Doctrine\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"DOCTRINE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-excel\/src\/Flow\/ETL\/Adapter\/Excel\/DSL\/functions.php","start_line_in_file":22,"slug":"from-excel","name":"from_excel","namespace":"Flow\\ETL\\Adapter\\Excel\\DSL","parameters":[{"name":"path","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"ExcelExtractor","namespace":"Flow\\ETL\\Adapter\\Excel","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"EXCEL","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-excel\/src\/Flow\/ETL\/Adapter\/Excel\/DSL\/functions.php","start_line_in_file":28,"slug":"to-excel","name":"to_excel","namespace":"Flow\\ETL\\Adapter\\Excel\\DSL","parameters":[{"name":"path","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"ExcelLoader","namespace":"Flow\\ETL\\Adapter\\Excel","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"EXCEL","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-excel\/src\/Flow\/ETL\/Adapter\/Excel\/DSL\/functions.php","start_line_in_file":34,"slug":"is-valid-excel-sheet-name","name":"is_valid_excel_sheet_name","namespace":"Flow\\ETL\\Adapter\\Excel\\DSL","parameters":[{"name":"sheet_name","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":"IsValidExcelSheetName","namespace":"Flow\\ETL\\Adapter\\Excel\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"EXCEL","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-google-sheet\/src\/Flow\/ETL\/Adapter\/GoogleSheet\/functions.php","start_line_in_file":22,"slug":"from-google-sheet","name":"from_google_sheet","namespace":"Flow\\ETL\\Adapter\\GoogleSheet","parameters":[{"name":"auth_config","type":[{"name":"Sheets","namespace":"Google\\Service","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},{"name":"spreadsheet_id","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":"sheet_name","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":"with_header","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"rows_per_page","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"1000"},{"name":"options","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"GoogleSheetExtractor","namespace":"Flow\\ETL\\Adapter\\GoogleSheet","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"GOOGLE_SHEET","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheXt0eXBlOiBzdHJpbmcsIHByb2plY3RfaWQ6IHN0cmluZywgcHJpdmF0ZV9rZXlfaWQ6IHN0cmluZywgcHJpdmF0ZV9rZXk6IHN0cmluZywgY2xpZW50X2VtYWlsOiBzdHJpbmcsIGNsaWVudF9pZDogc3RyaW5nLCBhdXRoX3VyaTogc3RyaW5nLCB0b2tlbl91cmk6IHN0cmluZywgYXV0aF9wcm92aWRlcl94NTA5X2NlcnRfdXJsOiBzdHJpbmcsIGNsaWVudF94NTA5X2NlcnRfdXJsOiBzdHJpbmd9fFNoZWV0cyAkYXV0aF9jb25maWcKICogQHBhcmFtIHN0cmluZyAkc3ByZWFkc2hlZXRfaWQKICogQHBhcmFtIHN0cmluZyAkc2hlZXRfbmFtZQogKiBAcGFyYW0gYm9vbCAkd2l0aF9oZWFkZXIgLSBAZGVwcmVjYXRlZCB1c2Ugd2l0aEhlYWRlciBtZXRob2QgaW5zdGVhZAogKiBAcGFyYW0gaW50ICRyb3dzX3Blcl9wYWdlIC0gaG93IG1hbnkgcm93cyBwZXIgcGFnZSB0byBmZXRjaCBmcm9tIEdvb2dsZSBTaGVldHMgQVBJIC0gQGRlcHJlY2F0ZWQgdXNlIHdpdGhSb3dzUGVyUGFnZSBtZXRob2QgaW5zdGVhZAogKiBAcGFyYW0gYXJyYXl7ZGF0ZVRpbWVSZW5kZXJPcHRpb24\/OiBzdHJpbmcsIG1ham9yRGltZW5zaW9uPzogc3RyaW5nLCB2YWx1ZVJlbmRlck9wdGlvbj86IHN0cmluZ30gJG9wdGlvbnMgLSBAZGVwcmVjYXRlZCB1c2Ugd2l0aE9wdGlvbnMgbWV0aG9kIGluc3RlYWQKICov"},{"repository_path":"src\/adapter\/etl-adapter-google-sheet\/src\/Flow\/ETL\/Adapter\/GoogleSheet\/functions.php","start_line_in_file":56,"slug":"from-google-sheet-columns","name":"from_google_sheet_columns","namespace":"Flow\\ETL\\Adapter\\GoogleSheet","parameters":[{"name":"auth_config","type":[{"name":"Sheets","namespace":"Google\\Service","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},{"name":"spreadsheet_id","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":"sheet_name","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":"start_range_column","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":"end_range_column","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":"with_header","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"rows_per_page","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"1000"},{"name":"options","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"GoogleSheetExtractor","namespace":"Flow\\ETL\\Adapter\\GoogleSheet","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"GOOGLE_SHEET","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheXt0eXBlOiBzdHJpbmcsIHByb2plY3RfaWQ6IHN0cmluZywgcHJpdmF0ZV9rZXlfaWQ6IHN0cmluZywgcHJpdmF0ZV9rZXk6IHN0cmluZywgY2xpZW50X2VtYWlsOiBzdHJpbmcsIGNsaWVudF9pZDogc3RyaW5nLCBhdXRoX3VyaTogc3RyaW5nLCB0b2tlbl91cmk6IHN0cmluZywgYXV0aF9wcm92aWRlcl94NTA5X2NlcnRfdXJsOiBzdHJpbmcsIGNsaWVudF94NTA5X2NlcnRfdXJsOiBzdHJpbmd9fFNoZWV0cyAkYXV0aF9jb25maWcKICogQHBhcmFtIHN0cmluZyAkc3ByZWFkc2hlZXRfaWQKICogQHBhcmFtIHN0cmluZyAkc2hlZXRfbmFtZQogKiBAcGFyYW0gc3RyaW5nICRzdGFydF9yYW5nZV9jb2x1bW4KICogQHBhcmFtIHN0cmluZyAkZW5kX3JhbmdlX2NvbHVtbgogKiBAcGFyYW0gYm9vbCAkd2l0aF9oZWFkZXIgLSBAZGVwcmVjYXRlZCB1c2Ugd2l0aEhlYWRlciBtZXRob2QgaW5zdGVhZAogKiBAcGFyYW0gaW50ICRyb3dzX3Blcl9wYWdlIC0gaG93IG1hbnkgcm93cyBwZXIgcGFnZSB0byBmZXRjaCBmcm9tIEdvb2dsZSBTaGVldHMgQVBJLCBkZWZhdWx0IDEwMDAgLSBAZGVwcmVjYXRlZCB1c2Ugd2l0aFJvd3NQZXJQYWdlIG1ldGhvZCBpbnN0ZWFkCiAqIEBwYXJhbSBhcnJheXtkYXRlVGltZVJlbmRlck9wdGlvbj86IHN0cmluZywgbWFqb3JEaW1lbnNpb24\/OiBzdHJpbmcsIHZhbHVlUmVuZGVyT3B0aW9uPzogc3RyaW5nfSAkb3B0aW9ucyAtIEBkZXByZWNhdGVkIHVzZSB3aXRoT3B0aW9ucyBtZXRob2QgaW5zdGVhZAogKi8="},{"repository_path":"src\/adapter\/etl-adapter-http\/src\/Flow\/ETL\/Adapter\/Http\/DSL\/functions.php","start_line_in_file":35,"slug":"from-dynamic-http-requests","name":"from_dynamic_http_requests","namespace":"Flow\\ETL\\Adapter\\Http","parameters":[{"name":"client","type":[{"name":"ClientInterface","namespace":"Psr\\Http\\Client","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"requestFactory","type":[{"name":"NextRequestFactory","namespace":"Flow\\ETL\\Adapter\\Http\\DynamicExtractor","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"schema","type":[{"name":"Schema","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":"PsrHttpClientDynamicExtractor","namespace":"Flow\\ETL\\Adapter\\Http","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"HTTP","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-http\/src\/Flow\/ETL\/Adapter\/Http\/DSL\/functions.php","start_line_in_file":53,"slug":"from-static-http-requests","name":"from_static_http_requests","namespace":"Flow\\ETL\\Adapter\\Http","parameters":[{"name":"client","type":[{"name":"ClientInterface","namespace":"Psr\\Http\\Client","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"requests","type":[{"name":"iterable","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"schema","type":[{"name":"Schema","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":"PsrHttpClientStaticExtractor","namespace":"Flow\\ETL\\Adapter\\Http","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"HTTP","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBpdGVyYWJsZTxSZXF1ZXN0SW50ZXJmYWNlPiAkcmVxdWVzdHMKICov"},{"repository_path":"src\/adapter\/etl-adapter-http\/src\/Flow\/ETL\/Adapter\/Http\/DSL\/functions.php","start_line_in_file":68,"slug":"from-http-paginated","name":"from_http_paginated","namespace":"Flow\\ETL\\Adapter\\Http","parameters":[{"name":"client","type":[{"name":"ClientInterface","namespace":"Psr\\Http\\Client","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"request","type":[{"name":"RequestInterface","namespace":"Psr\\Http\\Message","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"paginator","type":[{"name":"Paginator","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"schema","type":[{"name":"Schema","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":"PsrHttpClientPaginatedExtractor","namespace":"Flow\\ETL\\Adapter\\Http","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"HTTP","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-http\/src\/Flow\/ETL\/Adapter\/Http\/DSL\/functions.php","start_line_in_file":84,"slug":"http-pagination-page-number","name":"http_pagination_page_number","namespace":"Flow\\ETL\\Adapter\\Http","parameters":[{"name":"inject","type":[{"name":"RequestOption","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"start_page","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"1"},{"name":"page_size","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":"size_option","type":[{"name":"RequestOption","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"inject_on_first_request","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"records_path","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":"stop_on_client_error","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"stop_when","type":[{"name":"StopWhen","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Paginator","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"HTTP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-http\/src\/Flow\/ETL\/Adapter\/Http\/DSL\/functions.php","start_line_in_file":104,"slug":"http-pagination-offset","name":"http_pagination_offset","namespace":"Flow\\ETL\\Adapter\\Http","parameters":[{"name":"offset_option","type":[{"name":"RequestOption","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"limit_option","type":[{"name":"RequestOption","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"limit","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":"start_offset","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":"total_path","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":"inject_on_first_request","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"stop_on_client_error","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"stop_when","type":[{"name":"StopWhen","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Paginator","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"HTTP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-http\/src\/Flow\/ETL\/Adapter\/Http\/DSL\/functions.php","start_line_in_file":124,"slug":"http-pagination-cursor","name":"http_pagination_cursor","namespace":"Flow\\ETL\\Adapter\\Http","parameters":[{"name":"cursor_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},{"name":"inject","type":[{"name":"RequestOption","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"stop_on_client_error","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"stop_when","type":[{"name":"StopWhen","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Paginator","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"HTTP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-http\/src\/Flow\/ETL\/Adapter\/Http\/DSL\/functions.php","start_line_in_file":140,"slug":"http-pagination-next-url","name":"http_pagination_next_url","namespace":"Flow\\ETL\\Adapter\\Http","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},{"name":"stop_on_client_error","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"stop_when","type":[{"name":"StopWhen","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Paginator","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"HTTP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-http\/src\/Flow\/ETL\/Adapter\/Http\/DSL\/functions.php","start_line_in_file":155,"slug":"http-pagination-link-header","name":"http_pagination_link_header","namespace":"Flow\\ETL\\Adapter\\Http","parameters":[{"name":"rel","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'next'"},{"name":"stop_on_client_error","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"stop_when","type":[{"name":"StopWhen","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Paginator","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"HTTP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-http\/src\/Flow\/ETL\/Adapter\/Http\/DSL\/functions.php","start_line_in_file":164,"slug":"http-pagination-last-record-cursor","name":"http_pagination_last_record_cursor","namespace":"Flow\\ETL\\Adapter\\Http","parameters":[{"name":"record_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},{"name":"inject","type":[{"name":"RequestOption","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"stop_on_client_error","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"stop_when","type":[{"name":"StopWhen","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Paginator","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"HTTP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-http\/src\/Flow\/ETL\/Adapter\/Http\/DSL\/functions.php","start_line_in_file":180,"slug":"http-request-option-query","name":"http_request_option_query","namespace":"Flow\\ETL\\Adapter\\Http","parameters":[{"name":"name","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":"RequestOption","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"HTTP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-http\/src\/Flow\/ETL\/Adapter\/Http\/DSL\/functions.php","start_line_in_file":186,"slug":"http-request-option-header","name":"http_request_option_header","namespace":"Flow\\ETL\\Adapter\\Http","parameters":[{"name":"name","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":"RequestOption","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"HTTP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-http\/src\/Flow\/ETL\/Adapter\/Http\/DSL\/functions.php","start_line_in_file":192,"slug":"http-request-option-body","name":"http_request_option_body","namespace":"Flow\\ETL\\Adapter\\Http","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},{"name":"stream_factory","type":[{"name":"StreamFactoryInterface","namespace":"Psr\\Http\\Message","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"RequestOption","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"HTTP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-http\/src\/Flow\/ETL\/Adapter\/Http\/DSL\/functions.php","start_line_in_file":198,"slug":"http-request-option-uri","name":"http_request_option_uri","namespace":"Flow\\ETL\\Adapter\\Http","parameters":[],"return_type":[{"name":"RequestOption","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"HTTP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-http\/src\/Flow\/ETL\/Adapter\/Http\/DSL\/functions.php","start_line_in_file":204,"slug":"http-stop-when-path-missing","name":"http_stop_when_path_missing","namespace":"Flow\\ETL\\Adapter\\Http","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":"StopWhen","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"HTTP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-http\/src\/Flow\/ETL\/Adapter\/Http\/DSL\/functions.php","start_line_in_file":210,"slug":"http-stop-when-empty-path","name":"http_stop_when_empty_path","namespace":"Flow\\ETL\\Adapter\\Http","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":"StopWhen","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"HTTP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-http\/src\/Flow\/ETL\/Adapter\/Http\/DSL\/functions.php","start_line_in_file":216,"slug":"http-stop-when-flag-false","name":"http_stop_when_flag_false","namespace":"Flow\\ETL\\Adapter\\Http","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":"StopWhen","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"HTTP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-http\/src\/Flow\/ETL\/Adapter\/Http\/DSL\/functions.php","start_line_in_file":222,"slug":"http-stop-when-flag-true","name":"http_stop_when_flag_true","namespace":"Flow\\ETL\\Adapter\\Http","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":"StopWhen","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"HTTP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-http\/src\/Flow\/ETL\/Adapter\/Http\/DSL\/functions.php","start_line_in_file":228,"slug":"http-stop-when-total-reached","name":"http_stop_when_total_reached","namespace":"Flow\\ETL\\Adapter\\Http","parameters":[{"name":"total_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":"StopWhen","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"HTTP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-http\/src\/Flow\/ETL\/Adapter\/Http\/DSL\/functions.php","start_line_in_file":234,"slug":"http-stop-when-max-pages","name":"http_stop_when_max_pages","namespace":"Flow\\ETL\\Adapter\\Http","parameters":[{"name":"pages","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":"StopWhen","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"HTTP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-http\/src\/Flow\/ETL\/Adapter\/Http\/DSL\/functions.php","start_line_in_file":240,"slug":"http-stop-when-max-results","name":"http_stop_when_max_results","namespace":"Flow\\ETL\\Adapter\\Http","parameters":[{"name":"count","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":"StopWhen","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"HTTP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-json\/src\/Flow\/ETL\/Adapter\/JSON\/functions.php","start_line_in_file":32,"slug":"from-json","name":"from_json","namespace":"Flow\\ETL\\Adapter\\JSON","parameters":[{"name":"path","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"pointer","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":"schema","type":[{"name":"Schema","namespace":"Flow\\ETL","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"JsonExtractor","namespace":"Flow\\ETL\\Adapter\\JSON\\JSONMachine","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"JSON","type":"EXTRACTOR"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"reading","example":"json"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBQYXRofHN0cmluZyAkcGF0aCAtIHN0cmluZyBpcyBpbnRlcm5hbGx5IHR1cm5lZCBpbnRvIHN0cmVhbQogKiBAcGFyYW0gP3N0cmluZyAkcG9pbnRlciAtIGlmIHlvdSB3YW50IHRvIGl0ZXJhdGUgb25seSByZXN1bHRzIG9mIGEgc3VidHJlZSwgdXNlIGEgcG9pbnRlciwgcmVhZCBtb3JlIGF0IGh0dHBzOi8vZ2l0aHViLmNvbS9oYWxheGEvanNvbi1tYWNoaW5lI3BhcnNpbmctYS1zdWJ0cmVlIC0gQGRlcHJlY2F0ZSB1c2Ugd2l0aFBvaW50ZXIgbWV0aG9kIGluc3RlYWQKICogQHBhcmFtIG51bGx8U2NoZW1hICRzY2hlbWEgLSBlbmZvcmNlIHNjaGVtYSBvbiB0aGUgZXh0cmFjdGVkIGRhdGEgLSBAZGVwcmVjYXRlIHVzZSB3aXRoU2NoZW1hIG1ldGhvZCBpbnN0ZWFkCiAqLw=="},{"repository_path":"src\/adapter\/etl-adapter-json\/src\/Flow\/ETL\/Adapter\/JSON\/functions.php","start_line_in_file":58,"slug":"from-json-lines","name":"from_json_lines","namespace":"Flow\\ETL\\Adapter\\JSON","parameters":[{"name":"path","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"JsonLinesExtractor","namespace":"Flow\\ETL\\Adapter\\JSON\\JSONMachine","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"JSON","type":"EXTRACTOR"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"reading","example":"jsonl"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFVzZWQgdG8gcmVhZCBmcm9tIGEgSlNPTiBsaW5lcyBodHRwczovL2pzb25saW5lcy5vcmcvIGZvcm1hdHRlZCBmaWxlLgogKgogKiBAcGFyYW0gUGF0aHxzdHJpbmcgJHBhdGggLSBzdHJpbmcgaXMgaW50ZXJuYWxseSB0dXJuZWQgaW50byBzdHJlYW0KICov"},{"repository_path":"src\/adapter\/etl-adapter-json\/src\/Flow\/ETL\/Adapter\/JSON\/functions.php","start_line_in_file":72,"slug":"to-json","name":"to_json","namespace":"Flow\\ETL\\Adapter\\JSON","parameters":[{"name":"path","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"4194304"},{"name":"date_time_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\\\\TH:i:sP'"},{"name":"put_rows_in_new_lines","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"JsonLoader","namespace":"Flow\\ETL\\Adapter\\JSON","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"JSON","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBQYXRofHN0cmluZyAkcGF0aAogKiBAcGFyYW0gaW50ICRmbGFncyAtIFBIUCBKU09OIEZsYWdzIC0gQGRlcHJlY2F0ZSB1c2Ugd2l0aEZsYWdzIG1ldGhvZCBpbnN0ZWFkCiAqIEBwYXJhbSBzdHJpbmcgJGRhdGVfdGltZV9mb3JtYXQgLSBmb3JtYXQgZm9yIERhdGVUaW1lSW50ZXJmYWNlOjpmb3JtYXQoKSAtIEBkZXByZWNhdGUgdXNlIHdpdGhEYXRlVGltZUZvcm1hdCBtZXRob2QgaW5zdGVhZAogKiBAcGFyYW0gYm9vbCAkcHV0X3Jvd3NfaW5fbmV3X2xpbmVzIC0gaWYgeW91IHdhbnQgdG8gcHV0IGVhY2ggcm93IGluIGEgbmV3IGxpbmUgLSBAZGVwcmVjYXRlIHVzZSB3aXRoUm93c0luTmV3TGluZXMgbWV0aG9kIGluc3RlYWQKICoKICogQHJldHVybiBKc29uTG9hZGVyCiAqLw=="},{"repository_path":"src\/adapter\/etl-adapter-json\/src\/Flow\/ETL\/Adapter\/JSON\/functions.php","start_line_in_file":93,"slug":"to-json-lines","name":"to_json_lines","namespace":"Flow\\ETL\\Adapter\\JSON","parameters":[{"name":"path","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"JsonLinesLoader","namespace":"Flow\\ETL\\Adapter\\JSON","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"JSON","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFVzZWQgdG8gd3JpdGUgdG8gYSBKU09OIGxpbmVzIGh0dHBzOi8vanNvbmxpbmVzLm9yZy8gZm9ybWF0dGVkIGZpbGUuCiAqCiAqIEBwYXJhbSBQYXRofHN0cmluZyAkcGF0aAogKgogKiBAcmV0dXJuIEpzb25MaW5lc0xvYWRlcgogKi8="},{"repository_path":"src\/adapter\/etl-adapter-json\/src\/Flow\/ETL\/Adapter\/JSON\/functions.php","start_line_in_file":107,"slug":"schema-from-json-schema","name":"schema_from_json_schema","namespace":"Flow\\ETL\\Adapter\\JSON","parameters":[{"name":"json_schema","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"client","type":[{"name":"ClientInterface","namespace":"Psr\\Http\\Client","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"request_factory","type":[{"name":"RequestFactoryInterface","namespace":"Psr\\Http\\Message","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"Schema","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"JSON","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENvbnZlcnQgYSBKU09OIFNjaGVtYSAoaHR0cHM6Ly9qc29uLXNjaGVtYS5vcmcpIGRvY3VtZW50IGludG8gYSBGbG93IFNjaGVtYS4KICoKICogQHBhcmFtIGFycmF5PHN0cmluZywgbWl4ZWQ+fFBhdGh8c3RyaW5nICRqc29uX3NjaGVtYSAtIGRlY29kZWQgZG9jdW1lbnQsIHJhdyBKU09OIGRvY3VtZW50IG9yIGEgcGF0aCB0byBhIHNjaGVtYSBmaWxlCiAqIEBwYXJhbSBudWxsfENsaWVudEludGVyZmFjZSAkY2xpZW50IC0gUFNSLTE4IGh0dHAgY2xpZW50LCByZXF1aXJlZCB0byByZXNvbHZlIHJlbW90ZSBodHRwKHMpIHJlZmVyZW5jZXMKICogQHBhcmFtIG51bGx8UmVxdWVzdEZhY3RvcnlJbnRlcmZhY2UgJHJlcXVlc3RfZmFjdG9yeSAtIFBTUi0xNyByZXF1ZXN0IGZhY3RvcnksIHJlcXVpcmVkIHRvIHJlc29sdmUgcmVtb3RlIGh0dHAocykgcmVmZXJlbmNlcwogKiBAcGFyYW0gRmlsZXN5c3RlbSAkZmlsZXN5c3RlbSAtIGZpbGVzeXN0ZW0gdXNlZCB0byByZWFkIGxvY2FsIHNjaGVtYSByZWZlcmVuY2VzCiAqLw=="},{"repository_path":"src\/adapter\/etl-adapter-json\/src\/Flow\/ETL\/Adapter\/JSON\/functions.php","start_line_in_file":122,"slug":"schema-to-json-schema","name":"schema_to_json_schema","namespace":"Flow\\ETL\\Adapter\\JSON","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":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"JSON","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENvbnZlcnQgYSBGbG93IFNjaGVtYSBpbnRvIGEgSlNPTiBTY2hlbWEgKGh0dHBzOi8vanNvbi1zY2hlbWEub3JnLCBkcmFmdCAyMDIwLTEyKSBkb2N1bWVudC4KICoKICogQHJldHVybiBhcnJheTxzdHJpbmcsIG1peGVkPgogKi8="},{"repository_path":"src\/adapter\/etl-adapter-parquet\/src\/Flow\/ETL\/Adapter\/Parquet\/functions.php","start_line_in_file":36,"slug":"from-parquet","name":"from_parquet","namespace":"Flow\\ETL\\Adapter\\Parquet","parameters":[{"name":"path","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"columns","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"options","type":[{"name":"Options","namespace":"Flow\\Parquet","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Parquet\\Options::..."},{"name":"byte_order","type":[{"name":"ByteOrder","namespace":"Flow\\Parquet\\Binary","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Parquet\\Binary\\ByteOrder::..."},{"name":"offset","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":"engine","type":[{"name":"ParquetEngine","namespace":"Flow\\Parquet","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"ParquetExtractor","namespace":"Flow\\ETL\\Adapter\\Parquet","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PARQUET","type":"EXTRACTOR"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"reading","example":"parquet"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBQYXRofHN0cmluZyAkcGF0aAogKiBAcGFyYW0gYXJyYXk8c3RyaW5nPiAkY29sdW1ucyAtIGxpc3Qgb2YgY29sdW1ucyB0byByZWFkIGZyb20gcGFycXVldCBmaWxlIC0gQGRlcHJlY2F0ZWQgdXNlIGB3aXRoQ29sdW1uc2AgbWV0aG9kIGluc3RlYWQKICogQHBhcmFtIE9wdGlvbnMgJG9wdGlvbnMgLSBAZGVwcmVjYXRlZCB1c2UgYHdpdGhPcHRpb25zYCBtZXRob2QgaW5zdGVhZAogKiBAcGFyYW0gQnl0ZU9yZGVyICRieXRlX29yZGVyIC0gQGRlcHJlY2F0ZWQgdXNlIGB3aXRoQnl0ZU9yZGVyYCBtZXRob2QgaW5zdGVhZAogKiBAcGFyYW0gbnVsbHxpbnQgJG9mZnNldCAtIEBkZXByZWNhdGVkIHVzZSBgd2l0aE9mZnNldGAgbWV0aG9kIGluc3RlYWQKICov"},{"repository_path":"src\/adapter\/etl-adapter-parquet\/src\/Flow\/ETL\/Adapter\/Parquet\/functions.php","start_line_in_file":69,"slug":"to-parquet","name":"to_parquet","namespace":"Flow\\ETL\\Adapter\\Parquet","parameters":[{"name":"path","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"options","type":[{"name":"Options","namespace":"Flow\\Parquet","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"compressions","type":[{"name":"Compressions","namespace":"Flow\\Parquet\\ParquetFile","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Parquet\\ParquetFile\\Compressions::..."},{"name":"schema","type":[{"name":"Schema","namespace":"Flow\\ETL","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"engine","type":[{"name":"ParquetEngine","namespace":"Flow\\Parquet","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"ParquetLoader","namespace":"Flow\\ETL\\Adapter\\Parquet","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PARQUET","type":"LOADER"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"writing","example":"parquet"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBQYXRofHN0cmluZyAkcGF0aAogKiBAcGFyYW0gbnVsbHxPcHRpb25zICRvcHRpb25zIC0gQGRlcHJlY2F0ZWQgdXNlIGB3aXRoT3B0aW9uc2AgbWV0aG9kIGluc3RlYWQKICogQHBhcmFtIENvbXByZXNzaW9ucyAkY29tcHJlc3Npb25zIC0gQGRlcHJlY2F0ZWQgdXNlIGB3aXRoQ29tcHJlc3Npb25zYCBtZXRob2QgaW5zdGVhZAogKiBAcGFyYW0gbnVsbHxTY2hlbWEgJHNjaGVtYSAtIEBkZXByZWNhdGVkIHVzZSBgd2l0aFNjaGVtYWAgbWV0aG9kIGluc3RlYWQKICov"},{"repository_path":"src\/adapter\/etl-adapter-parquet\/src\/Flow\/ETL\/Adapter\/Parquet\/functions.php","start_line_in_file":100,"slug":"array-to-generator","name":"array_to_generator","namespace":"Flow\\ETL\\Adapter\\Parquet","parameters":[{"name":"data","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":"Generator","namespace":"","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PARQUET","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBhcnJheTxUPiAkZGF0YQogKgogKiBAcmV0dXJuIFxHZW5lcmF0b3I8VD4KICov"},{"repository_path":"src\/adapter\/etl-adapter-parquet\/src\/Flow\/ETL\/Adapter\/Parquet\/functions.php","start_line_in_file":111,"slug":"empty-generator","name":"empty_generator","namespace":"Flow\\ETL\\Adapter\\Parquet","parameters":[],"return_type":[{"name":"Generator","namespace":"","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PARQUET","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBkZXByZWNhdGVkIHVzZSBGbG93XFBhcnF1ZXRcZW1wdHlfZ2VuZXJhdG9yKCkgaW5zdGVhZAogKi8="},{"repository_path":"src\/adapter\/etl-adapter-parquet\/src\/Flow\/ETL\/Adapter\/Parquet\/functions.php","start_line_in_file":117,"slug":"schema-to-parquet","name":"schema_to_parquet","namespace":"Flow\\ETL\\Adapter\\Parquet","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":"Schema","namespace":"Flow\\Parquet\\ParquetFile","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PARQUET","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-parquet\/src\/Flow\/ETL\/Adapter\/Parquet\/functions.php","start_line_in_file":123,"slug":"schema-from-parquet","name":"schema_from_parquet","namespace":"Flow\\ETL\\Adapter\\Parquet","parameters":[{"name":"schema","type":[{"name":"Schema","namespace":"Flow\\Parquet\\ParquetFile","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Schema","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PARQUET","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-postgresql\/src\/Flow\/ETL\/Adapter\/PostgreSql\/functions.php","start_line_in_file":37,"slug":"from-pgsql-cursor","name":"from_pgsql_cursor","namespace":"Flow\\ETL\\Adapter\\PostgreSql","parameters":[{"name":"client","type":[{"name":"Client","namespace":"Flow\\PostgreSql\\Client","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"query","type":[{"name":"Sql","namespace":"Flow\\PostgreSql\\QueryBuilder","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":"parameters","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"PostgreSqlCursorExtractor","namespace":"Flow\\ETL\\Adapter\\PostgreSql","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"POSTGRESQL","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBvc3RncmVTUUwgY3Vyc29yIGV4dHJhY3RvciB1c2luZyBzZXJ2ZXItc2lkZSBjdXJzb3JzIGZvciBtZW1vcnktZWZmaWNpZW50IGV4dHJhY3Rpb24uCiAqCiAqIFVzZXMgREVDTEFSRSBDVVJTT1IgKyBGRVRDSCB0byBzdHJlYW0gZGF0YSB3aXRob3V0IGxvYWRpbmcgZW50aXJlIHJlc3VsdCBzZXQgaW50byBtZW1vcnkuCiAqIFRoaXMgaXMgdGhlIG9ubHkgd2F5IHRvIGFjaGlldmUgdHJ1ZSBsb3cgbWVtb3J5IGV4dHJhY3Rpb24gd2l0aCBQSFAncyBleHQtcGdzcWwuCiAqCiAqIE5vdGU6IFJlcXVpcmVzIGEgdHJhbnNhY3Rpb24gY29udGV4dCAoYXV0by1zdGFydGVkIGlmIG5vdCBpbiBvbmUpLgogKgogKiBAcGFyYW0gQ2xpZW50ICRjbGllbnQgUG9zdGdyZVNRTCBjbGllbnQKICogQHBhcmFtIFNxbHxzdHJpbmcgJHF1ZXJ5IFNRTCBxdWVyeSB0byBleGVjdXRlICh3cmFwcGVkIGluIERFQ0xBUkUgQ1VSU09SKQogKiBAcGFyYW0gbGlzdDxtaXhlZD4gJHBhcmFtZXRlcnMgVmFsdWVzIGJvdW5kIGJ5IHBvc2l0aW9uIHRvICQxLCAkMiwgLi4uIHBsYWNlaG9sZGVyczsgd3JhcCB3aXRoIHtAc2VlIFxGbG93XFBvc3RncmVTcWxcRFNMXHR5cGVkKCl9IHRvIGZvcmNlIGEgc3BlY2lmaWMgUG9zdGdyZVNRTCB0eXBlCiAqLw=="},{"repository_path":"src\/adapter\/etl-adapter-postgresql\/src\/Flow\/ETL\/Adapter\/PostgreSql\/functions.php","start_line_in_file":53,"slug":"from-pgsql-limit-offset","name":"from_pgsql_limit_offset","namespace":"Flow\\ETL\\Adapter\\PostgreSql","parameters":[{"name":"client","type":[{"name":"Client","namespace":"Flow\\PostgreSql\\Client","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"query","type":[{"name":"Sql","namespace":"Flow\\PostgreSql\\QueryBuilder","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":"parameters","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"PostgreSqlLimitOffsetExtractor","namespace":"Flow\\ETL\\Adapter\\PostgreSql","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"POSTGRESQL","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBvc3RncmVTUUwgZXh0cmFjdG9yIHVzaW5nIExJTUlUL09GRlNFVCBwYWdpbmF0aW9uLgogKgogKiBTdWl0YWJsZSBmb3Igc21hbGxlciBkYXRhc2V0cy4gRm9yIGxhcmdlIGRhdGFzZXRzLCBjb25zaWRlciB1c2luZyBrZXlzZXQgcGFnaW5hdGlvbgogKiAoZnJvbV9wZ3NxbF9rZXlfc2V0KSB3aGljaCBpcyBtb3JlIGVmZmljaWVudC4KICoKICogQHBhcmFtIENsaWVudCAkY2xpZW50IFBvc3RncmVTUUwgY2xpZW50CiAqIEBwYXJhbSBTcWx8c3RyaW5nICRxdWVyeSBTUUwgcXVlcnkgdG8gZXhlY3V0ZSAobXVzdCBoYXZlIE9SREVSIEJZIGNsYXVzZSkKICogQHBhcmFtIGxpc3Q8bWl4ZWQ+ICRwYXJhbWV0ZXJzIFZhbHVlcyBib3VuZCBieSBwb3NpdGlvbiB0byAkMSwgJDIsIC4uLiBwbGFjZWhvbGRlcnM7IHdyYXAgd2l0aCB7QHNlZSBcRmxvd1xQb3N0Z3JlU3FsXERTTFx0eXBlZCgpfSB0byBmb3JjZSBhIHNwZWNpZmljIFBvc3RncmVTUUwgdHlwZQogKi8="},{"repository_path":"src\/adapter\/etl-adapter-postgresql\/src\/Flow\/ETL\/Adapter\/PostgreSql\/functions.php","start_line_in_file":73,"slug":"from-pgsql-key-set","name":"from_pgsql_key_set","namespace":"Flow\\ETL\\Adapter\\PostgreSql","parameters":[{"name":"client","type":[{"name":"Client","namespace":"Flow\\PostgreSql\\Client","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"query","type":[{"name":"Sql","namespace":"Flow\\PostgreSql\\QueryBuilder","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":"keySet","type":[{"name":"KeySet","namespace":"Flow\\ETL\\Adapter\\PostgreSql\\Pagination","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"parameters","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"PostgreSqlKeySetExtractor","namespace":"Flow\\ETL\\Adapter\\PostgreSql","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"POSTGRESQL","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBvc3RncmVTUUwgZXh0cmFjdG9yIHVzaW5nIGtleXNldCAoY3Vyc29yLWJhc2VkKSBwYWdpbmF0aW9uLgogKgogKiBNb3JlIGVmZmljaWVudCB0aGFuIExJTUlUL09GRlNFVCBmb3IgbGFyZ2UgZGF0YXNldHMgLSB1c2VzIGluZGV4ZWQgV0hFUkUgY29uZGl0aW9ucwogKiBpbnN0ZWFkIG9mIHNraXBwaW5nIHJvd3MuCiAqCiAqIEBwYXJhbSBDbGllbnQgJGNsaWVudCBQb3N0Z3JlU1FMIGNsaWVudAogKiBAcGFyYW0gU3FsfHN0cmluZyAkcXVlcnkgU1FMIHF1ZXJ5IHRvIGV4ZWN1dGUgKG11c3QgaGF2ZSBPUkRFUiBCWSBtYXRjaGluZyBrZXlzZXQgY29sdW1ucykKICogQHBhcmFtIEtleVNldCAka2V5U2V0IENvbHVtbnMgdG8gdXNlIGZvciBrZXlzZXQgcGFnaW5hdGlvbgogKiBAcGFyYW0gbGlzdDxtaXhlZD4gJHBhcmFtZXRlcnMgVmFsdWVzIGJvdW5kIGJ5IHBvc2l0aW9uIHRvICQxLCAkMiwgLi4uIHBsYWNlaG9sZGVyczsgd3JhcCB3aXRoIHtAc2VlIFxGbG93XFBvc3RncmVTcWxcRFNMXHR5cGVkKCl9IHRvIGZvcmNlIGEgc3BlY2lmaWMgUG9zdGdyZVNRTCB0eXBlCiAqLw=="},{"repository_path":"src\/adapter\/etl-adapter-postgresql\/src\/Flow\/ETL\/Adapter\/PostgreSql\/functions.php","start_line_in_file":83,"slug":"pgsql-pagination-key-asc","name":"pgsql_pagination_key_asc","namespace":"Flow\\ETL\\Adapter\\PostgreSql","parameters":[{"name":"column","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":"Key","namespace":"Flow\\ETL\\Adapter\\PostgreSql\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"POSTGRESQL","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-postgresql\/src\/Flow\/ETL\/Adapter\/PostgreSql\/functions.php","start_line_in_file":89,"slug":"pgsql-pagination-key-desc","name":"pgsql_pagination_key_desc","namespace":"Flow\\ETL\\Adapter\\PostgreSql","parameters":[{"name":"column","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":"Key","namespace":"Flow\\ETL\\Adapter\\PostgreSql\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"POSTGRESQL","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-postgresql\/src\/Flow\/ETL\/Adapter\/PostgreSql\/functions.php","start_line_in_file":95,"slug":"pgsql-pagination-key-set","name":"pgsql_pagination_key_set","namespace":"Flow\\ETL\\Adapter\\PostgreSql","parameters":[{"name":"keys","type":[{"name":"Key","namespace":"Flow\\ETL\\Adapter\\PostgreSql\\Pagination","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"KeySet","namespace":"Flow\\ETL\\Adapter\\PostgreSql\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"POSTGRESQL","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-postgresql\/src\/Flow\/ETL\/Adapter\/PostgreSql\/functions.php","start_line_in_file":101,"slug":"to-pgsql-table","name":"to_pgsql_table","namespace":"Flow\\ETL\\Adapter\\PostgreSql","parameters":[{"name":"client","type":[{"name":"Client","namespace":"Flow\\PostgreSql\\Client","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"table","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":"PostgreSqlLoader","namespace":"Flow\\ETL\\Adapter\\PostgreSql","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"POSTGRESQL","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-postgresql\/src\/Flow\/ETL\/Adapter\/PostgreSql\/functions.php","start_line_in_file":116,"slug":"to-pgsql-transaction","name":"to_pgsql_transaction","namespace":"Flow\\ETL\\Adapter\\PostgreSql","parameters":[{"name":"client","type":[{"name":"Client","namespace":"Flow\\PostgreSql\\Client","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"loaders","type":[{"name":"Loader","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":"TransactionalPostgreSqlLoader","namespace":"Flow\\ETL\\Adapter\\PostgreSql","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"POSTGRESQL","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEV4ZWN1dGUgbXVsdGlwbGUgbG9hZGVycyB3aXRoaW4gUG9zdGdyZVNRTCB0cmFuc2FjdGlvbnMuCiAqCiAqIEVhY2ggYmF0Y2ggb2Ygcm93cyBpcyBsb2FkZWQgaW4gaXRzIG93biB0cmFuc2FjdGlvbjsgcm93cyBhIHdyYXBwZWQgVHJhbnNmb3JtYXRpb24gZGVsaXZlcnMgd2hlbgogKiB0aGUgbG9hZGVyIGlzIGNsb3NlZCAoYmxvY2tpbmcgb3BlcmF0aW9ucyBkcmFpbiB0aGVyZSkgYXJlIGNvbW1pdHRlZCBpbiBvbmUgZmluYWwgdHJhbnNhY3Rpb24uCiAqIElmIGFueSBsb2FkZXIgZmFpbHMsIHRoZSBvcGVuIHRyYW5zYWN0aW9uIGlzIHJvbGxlZCBiYWNrLgogKiBBbGwgd3JhcHBlZCBsb2FkZXJzIG11c3QgdXNlIHRoZSBzYW1lIENsaWVudCBpbnN0YW5jZSBhcyB0aGUgd3JhcHBlciAtIGEgbG9hZGVyIGhvbGRpbmcgaXRzIG93bgogKiBDbGllbnQgZXNjYXBlcyB0aGUgdHJhbnNhY3Rpb24uCiAqLw=="},{"repository_path":"src\/adapter\/etl-adapter-postgresql\/src\/Flow\/ETL\/Adapter\/PostgreSql\/functions.php","start_line_in_file":130,"slug":"pgsql-insert-options","name":"pgsql_insert_options","namespace":"Flow\\ETL\\Adapter\\PostgreSql","parameters":[{"name":"skipConflicts","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"conflictColumns","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"conflictConstraint","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":"updateColumns","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"InsertOptions","namespace":"Flow\\ETL\\Adapter\\PostgreSql\\LoaderOptions","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"POSTGRESQL","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBpbnNlcnQgb3B0aW9ucyBmb3IgUG9zdGdyZVNRTCBsb2FkZXIuCiAqCiAqIEBwYXJhbSBib29sICRza2lwQ29uZmxpY3RzIElmIHRydWUsIHVzZSBPTiBDT05GTElDVCBETyBOT1RISU5HCiAqIEBwYXJhbSBsaXN0PHN0cmluZz4gJGNvbmZsaWN0Q29sdW1ucyBDb2x1bW4gbmFtZXMgZm9yIE9OIENPTkZMSUNUIChjb2x1bW5zKQogKiBAcGFyYW0gbnVsbHxzdHJpbmcgJGNvbmZsaWN0Q29uc3RyYWludCBDb25zdHJhaW50IG5hbWUgZm9yIE9OIENPTkZMSUNUIE9OIENPTlNUUkFJTlQKICogQHBhcmFtIGxpc3Q8c3RyaW5nPiAkdXBkYXRlQ29sdW1ucyBDb2x1bW5zIHRvIHVwZGF0ZSBvbiBjb25mbGljdCAoZW1wdHkgPSBhbGwgbm9uLWtleSBjb2x1bW5zKQogKi8="},{"repository_path":"src\/adapter\/etl-adapter-postgresql\/src\/Flow\/ETL\/Adapter\/PostgreSql\/functions.php","start_line_in_file":145,"slug":"pgsql-update-options","name":"pgsql_update_options","namespace":"Flow\\ETL\\Adapter\\PostgreSql","parameters":[{"name":"primaryKeys","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":"UpdateOptions","namespace":"Flow\\ETL\\Adapter\\PostgreSql\\LoaderOptions","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"POSTGRESQL","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSB1cGRhdGUgb3B0aW9ucyBmb3IgUG9zdGdyZVNRTCBsb2FkZXIuCiAqCiAqIEBwYXJhbSBsaXN0PHN0cmluZz4gJHByaW1hcnlLZXlzIENvbHVtbnMgdG8gdXNlIGluIFdIRVJFIGNsYXVzZSBmb3IgbWF0Y2hpbmcgcm93cwogKi8="},{"repository_path":"src\/adapter\/etl-adapter-postgresql\/src\/Flow\/ETL\/Adapter\/PostgreSql\/functions.php","start_line_in_file":156,"slug":"pgsql-delete-options","name":"pgsql_delete_options","namespace":"Flow\\ETL\\Adapter\\PostgreSql","parameters":[{"name":"primaryKeys","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":"DeleteOptions","namespace":"Flow\\ETL\\Adapter\\PostgreSql\\LoaderOptions","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"POSTGRESQL","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBkZWxldGUgb3B0aW9ucyBmb3IgUG9zdGdyZVNRTCBsb2FkZXIuCiAqCiAqIEBwYXJhbSBsaXN0PHN0cmluZz4gJHByaW1hcnlLZXlzIENvbHVtbnMgdG8gdXNlIGluIFdIRVJFIGNsYXVzZSBmb3IgbWF0Y2hpbmcgcm93cwogKi8="},{"repository_path":"src\/adapter\/etl-adapter-postgresql\/src\/Flow\/ETL\/Adapter\/PostgreSql\/functions.php","start_line_in_file":168,"slug":"to-pgsql-schema-table","name":"to_pgsql_schema_table","namespace":"Flow\\ETL\\Adapter\\PostgreSql","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":"tableName","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":"databaseSchema","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'public'"},{"name":"typesMap","type":[{"name":"EntryTypesMap","namespace":"Flow\\ETL\\Adapter\\PostgreSql","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"options","type":[{"name":"TableOptions","namespace":"Flow\\PostgreSql\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Table","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"POSTGRESQL","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENvbnZlcnQgYSBGbG93IFNjaGVtYSBpbnRvIGEgUG9zdGdyZVNRTCB0YWJsZSBkZWZpbml0aW9uLgogKgogKiBAcGFyYW0gc3RyaW5nICRkYXRhYmFzZVNjaGVtYSBQb3N0Z3JlU1FMIHNjaGVtYSAobmFtZXNwYWNlKSB0aGUgdGFibGUgYmVsb25ncyB0bwogKiBAcGFyYW0gP1RhYmxlT3B0aW9ucyAkb3B0aW9ucyB0YWJsZS1sZXZlbCBvcHRpb25zIHRoZSBGbG93IFNjaGVtYSBjYW5ub3QgZXhwcmVzcyAoZS5nLiBVTkxPR0dFRCkKICov"},{"repository_path":"src\/adapter\/etl-adapter-postgresql\/src\/Flow\/ETL\/Adapter\/PostgreSql\/functions.php","start_line_in_file":182,"slug":"pgsql-table-to-flow-schema","name":"pgsql_table_to_flow_schema","namespace":"Flow\\ETL\\Adapter\\PostgreSql","parameters":[{"name":"table","type":[{"name":"Table","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"typesMap","type":[{"name":"EntryTypesMap","namespace":"Flow\\ETL\\Adapter\\PostgreSql","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Schema","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"POSTGRESQL","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENvbnZlcnQgYSBQb3N0Z3JlU1FMIHRhYmxlIGRlZmluaXRpb24gaW50byBhIEZsb3cgU2NoZW1hLgogKi8="},{"repository_path":"src\/adapter\/etl-adapter-postgresql\/src\/Flow\/ETL\/Adapter\/PostgreSql\/functions.php","start_line_in_file":188,"slug":"pgsql-schema-sort-by-type","name":"pgsql_schema_sort_by_type","namespace":"Flow\\ETL\\Adapter\\PostgreSql","parameters":[{"name":"typesMap","type":[{"name":"EntryTypesMap","namespace":"Flow\\ETL\\Adapter\\PostgreSql","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"TypeStrategy","namespace":"Flow\\ETL\\Adapter\\PostgreSql\\Schema\\SortingStrategy","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"POSTGRESQL","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-seal\/src\/Flow\/ETL\/Adapter\/Seal\/functions.php","start_line_in_file":15,"slug":"to-seal-upsert","name":"to_seal_upsert","namespace":"Flow\\ETL\\Adapter\\Seal","parameters":[{"name":"engine","type":[{"name":"EngineInterface","namespace":"CmsIg\\Seal","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"index","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":"SealLoader","namespace":"Flow\\ETL\\Adapter\\Seal","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"SEAL","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-seal\/src\/Flow\/ETL\/Adapter\/Seal\/functions.php","start_line_in_file":21,"slug":"to-seal-delete","name":"to_seal_delete","namespace":"Flow\\ETL\\Adapter\\Seal","parameters":[{"name":"engine","type":[{"name":"EngineInterface","namespace":"CmsIg\\Seal","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"index","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":"SealLoader","namespace":"Flow\\ETL\\Adapter\\Seal","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"SEAL","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-seal\/src\/Flow\/ETL\/Adapter\/Seal\/functions.php","start_line_in_file":27,"slug":"to-seal-schema","name":"to_seal_schema","namespace":"Flow\\ETL\\Adapter\\Seal","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":"index_name","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":"identifier","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Schema","namespace":"CmsIg\\Seal\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"SEAL","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-seal\/src\/Flow\/ETL\/Adapter\/Seal\/functions.php","start_line_in_file":33,"slug":"seal-schema-to-flow","name":"seal_schema_to_flow","namespace":"Flow\\ETL\\Adapter\\Seal","parameters":[{"name":"schema","type":[{"name":"Schema","namespace":"CmsIg\\Seal\\Schema","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Schema","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"SEAL","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-text\/src\/Flow\/ETL\/Adapter\/Text\/functions.php","start_line_in_file":21,"slug":"from-text","name":"from_text","namespace":"Flow\\ETL\\Adapter\\Text","parameters":[{"name":"path","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"TextExtractor","namespace":"Flow\\ETL\\Adapter\\Text","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TEXT","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBQYXRofHN0cmluZyAkcGF0aAogKi8="},{"repository_path":"src\/adapter\/etl-adapter-text\/src\/Flow\/ETL\/Adapter\/Text\/functions.php","start_line_in_file":31,"slug":"to-text","name":"to_text","namespace":"Flow\\ETL\\Adapter\\Text","parameters":[{"name":"path","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"new_line_separator","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'\\n'"},{"name":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"TextLoader","namespace":"Flow\\ETL\\Adapter\\Text","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TEXT","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBQYXRofHN0cmluZyAkcGF0aAogKiBAcGFyYW0gc3RyaW5nICRuZXdfbGluZV9zZXBhcmF0b3IgLSBkZWZhdWx0IFBIUF9FT0wgLSBAZGVwcmVjYXRlZCB1c2Ugd2l0aE5ld0xpbmVTZXBhcmF0b3IgbWV0aG9kIGluc3RlYWQKICov"},{"repository_path":"src\/adapter\/etl-adapter-xml\/src\/Flow\/ETL\/Adapter\/XML\/functions.php","start_line_in_file":38,"slug":"from-xml","name":"from_xml","namespace":"Flow\\ETL\\Adapter\\XML","parameters":[{"name":"path","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"xml_node_path","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"''"},{"name":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"XMLParserExtractor","namespace":"Flow\\ETL\\Adapter\\XML","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"XML","type":"EXTRACTOR"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"reading","example":"xml"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqICBJbiBvcmRlciB0byBpdGVyYXRlIG9ubHkgb3ZlciA8ZWxlbWVudD4gbm9kZXMgdXNlIGBmcm9tX3htbCgkZmlsZSktPndpdGhYTUxOb2RlUGF0aCgncm9vdC9lbGVtZW50cy9lbGVtZW50JylgLgogKgogKiAgPHJvb3Q+CiAqICAgIDxlbGVtZW50cz4KICogICAgICA8ZWxlbWVudD48L2VsZW1lbnQ+CiAqICAgICAgPGVsZW1lbnQ+PC9lbGVtZW50PgogKiAgICA8ZWxlbWVudHM+CiAqICA8L3Jvb3Q+CiAqCiAqICBYTUwgTm9kZSBQYXRoIGRvZXMgbm90IHN1cHBvcnQgYXR0cmlidXRlcyBhbmQgaXQncyBub3QgeHBhdGgsIGl0IGlzIGp1c3QgYSBzZXF1ZW5jZQogKiAgb2Ygbm9kZSBuYW1lcyBzZXBhcmF0ZWQgd2l0aCBzbGFzaC4KICoKICogQHBhcmFtIFBhdGh8c3RyaW5nICRwYXRoCiAqIEBwYXJhbSBzdHJpbmcgJHhtbF9ub2RlX3BhdGggLSBAZGVwcmVjYXRlZCB1c2UgYGZyb21feG1sKCRmaWxlKS0+d2l0aFhNTE5vZGVQYXRoKCR4bWxOb2RlUGF0aClgIG1ldGhvZCBpbnN0ZWFkCiAqLw=="},{"repository_path":"src\/adapter\/etl-adapter-xml\/src\/Flow\/ETL\/Adapter\/XML\/functions.php","start_line_in_file":57,"slug":"to-xml","name":"to_xml","namespace":"Flow\\ETL\\Adapter\\XML","parameters":[{"name":"path","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"root_element_name","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'rows'"},{"name":"row_element_name","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'row'"},{"name":"attribute_prefix","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'_'"},{"name":"date_time_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\\\\TH:i:s.uP'"},{"name":"xml_writer","type":[{"name":"XMLWriter","namespace":"Flow\\ETL\\Adapter\\XML","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Adapter\\XML\\XMLWriter\\StringXMLWriter::..."},{"name":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"XMLLoader","namespace":"Flow\\ETL\\Adapter\\XML\\Loader","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"XML","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBQYXRofHN0cmluZyAkcGF0aAogKiBAcGFyYW0gc3RyaW5nICRyb290X2VsZW1lbnRfbmFtZSAtIEBkZXByZWNhdGVkIHVzZSBgd2l0aFJvb3RFbGVtZW50TmFtZSgpYCBtZXRob2QgaW5zdGVhZAogKiBAcGFyYW0gc3RyaW5nICRyb3dfZWxlbWVudF9uYW1lIC0gQGRlcHJlY2F0ZWQgdXNlIGB3aXRoUm93RWxlbWVudE5hbWUoKWAgbWV0aG9kIGluc3RlYWQKICogQHBhcmFtIHN0cmluZyAkYXR0cmlidXRlX3ByZWZpeCAtIEBkZXByZWNhdGVkIHVzZSBgd2l0aEF0dHJpYnV0ZVByZWZpeCgpYCBtZXRob2QgaW5zdGVhZAogKiBAcGFyYW0gc3RyaW5nICRkYXRlX3RpbWVfZm9ybWF0IC0gQGRlcHJlY2F0ZWQgdXNlIGB3aXRoRGF0ZVRpbWVGb3JtYXQoKWAgbWV0aG9kIGluc3RlYWQKICogQHBhcmFtIFhNTFdyaXRlciAkeG1sX3dyaXRlcgogKi8="},{"repository_path":"src\/lib\/filesystem\/src\/Flow\/Filesystem\/DSL\/functions.php","start_line_in_file":32,"slug":"mount","name":"mount","namespace":"Flow\\Filesystem\\DSL","parameters":[{"name":"protocol","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":"Mount","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/filesystem\/src\/Flow\/Filesystem\/DSL\/functions.php","start_line_in_file":38,"slug":"partition","name":"partition","namespace":"Flow\\Filesystem\\DSL","parameters":[{"name":"name","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":"value","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":"Partition","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/filesystem\/src\/Flow\/Filesystem\/DSL\/functions.php","start_line_in_file":44,"slug":"partitions","name":"partitions","namespace":"Flow\\Filesystem\\DSL","parameters":[{"name":"partition","type":[{"name":"Partition","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"Partitions","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/filesystem\/src\/Flow\/Filesystem\/DSL\/functions.php","start_line_in_file":63,"slug":"path","name":"path","namespace":"Flow\\Filesystem\\DSL","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},{"name":"options","type":[{"name":"Options","namespace":"Flow\\Filesystem\\Path","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"Path","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFBhdGggc3VwcG9ydHMgZ2xvYiBwYXR0ZXJucy4KICogRXhhbXBsZXM6CiAqICAtIHBhdGgoJyouY3N2JykgLSBhbnkgY3N2IGZpbGUgaW4gY3VycmVudCBkaXJlY3RvcnkKICogIC0gcGF0aCgnLyoqIC8gKi5jc3YnKSAtIGFueSBjc3YgZmlsZSBpbiBhbnkgc3ViZGlyZWN0b3J5IChyZW1vdmUgZW1wdHkgc3BhY2VzKQogKiAgLSBwYXRoKCcvZGlyL3BhcnRpdGlvbj0qIC8qLnBhcnF1ZXQnKSAtIGFueSBwYXJxdWV0IGZpbGUgaW4gZ2l2ZW4gcGFydGl0aW9uIGRpcmVjdG9yeS4KICoKICogR2xvYiBwYXR0ZXJuIGlzIGFsc28gc3VwcG9ydGVkIGJ5IHJlbW90ZSBmaWxlc3lzdGVtcyBsaWtlIEF6dXJlCiAqCiAqICAtIHBhdGgoJ2F6dXJlLWJsb2I6Ly9kaXJlY3RvcnkvKi5jc3YnKSAtIGFueSBjc3YgZmlsZSBpbiBnaXZlbiBkaXJlY3RvcnkKICoKICogQHBhcmFtIGFycmF5PHN0cmluZywgbnVsbHxib29sfGZsb2F0fGludHxzdHJpbmd8XFVuaXRFbnVtPnxQYXRoXE9wdGlvbnMgJG9wdGlvbnMKICov"},{"repository_path":"src\/lib\/filesystem\/src\/Flow\/Filesystem\/DSL\/functions.php","start_line_in_file":74,"slug":"path-real","name":"path_real","namespace":"Flow\\Filesystem\\DSL","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},{"name":"options","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"Path","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFJlc29sdmUgcmVhbCBwYXRoIGZyb20gZ2l2ZW4gcGF0aC4KICoKICogQHBhcmFtIGFycmF5PHN0cmluZywgbnVsbHxib29sfGZsb2F0fGludHxzdHJpbmd8XFVuaXRFbnVtPiAkb3B0aW9ucwogKi8="},{"repository_path":"src\/lib\/filesystem\/src\/Flow\/Filesystem\/DSL\/functions.php","start_line_in_file":80,"slug":"native-local-filesystem","name":"native_local_filesystem","namespace":"Flow\\Filesystem\\DSL","parameters":[{"name":"protocol","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'file'"}],"return_type":[{"name":"NativeLocalFilesystem","namespace":"Flow\\Filesystem\\Local","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/filesystem\/src\/Flow\/Filesystem\/DSL\/functions.php","start_line_in_file":90,"slug":"stdout-filesystem","name":"stdout_filesystem","namespace":"Flow\\Filesystem\\DSL","parameters":[{"name":"protocol","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'stdout'"}],"return_type":[{"name":"StdOutFilesystem","namespace":"Flow\\Filesystem\\Local","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFdyaXRlLW9ubHkgZmlsZXN5c3RlbSB1c2VmdWwgd2hlbiB3ZSBqdXN0IHdhbnQgdG8gd3JpdGUgdGhlIG91dHB1dCB0byBzdGRvdXQuCiAqIFRoZSBtYWluIHVzZSBjYXNlIGlzIGZvciBzdHJlYW1pbmcgZGF0YXNldHMgb3ZlciBodHRwLgogKi8="},{"repository_path":"src\/lib\/filesystem\/src\/Flow\/Filesystem\/DSL\/functions.php","start_line_in_file":99,"slug":"memory-filesystem","name":"memory_filesystem","namespace":"Flow\\Filesystem\\DSL","parameters":[{"name":"protocol","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'memory'"}],"return_type":[{"name":"MemoryFilesystem","namespace":"Flow\\Filesystem\\Local","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIG5ldyBtZW1vcnkgZmlsZXN5c3RlbSBhbmQgd3JpdGVzIGRhdGEgdG8gaXQgaW4gbWVtb3J5LgogKi8="},{"repository_path":"src\/lib\/filesystem\/src\/Flow\/Filesystem\/DSL\/functions.php","start_line_in_file":110,"slug":"fstab","name":"fstab","namespace":"Flow\\Filesystem\\DSL","parameters":[{"name":"filesystems","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"FilesystemTable","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIG5ldyBmaWxlc3lzdGVtIHRhYmxlIHdpdGggZ2l2ZW4gZmlsZXN5c3RlbXMuCiAqIEZpbGVzeXN0ZW1zIGNhbiBiZSBhbHNvIG1vdW50ZWQgbGF0ZXIuCiAqIElmIG5vIGZpbGVzeXN0ZW1zIGFyZSBwcm92aWRlZCwgbG9jYWwgZmlsZXN5c3RlbSBpcyBtb3VudGVkLgogKi8="},{"repository_path":"src\/lib\/filesystem\/src\/Flow\/Filesystem\/DSL\/functions.php","start_line_in_file":126,"slug":"traceable-filesystem","name":"traceable_filesystem","namespace":"Flow\\Filesystem\\DSL","parameters":[{"name":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"telemetryConfig","type":[{"name":"FilesystemTelemetryConfig","namespace":"Flow\\Filesystem\\Telemetry","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"TraceableFilesystem","namespace":"Flow\\Filesystem\\Telemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFdyYXAgYSBmaWxlc3lzdGVtIHdpdGggdGVsZW1ldHJ5IHRyYWNpbmcgc3VwcG9ydC4KICogQWxsIGZpbGVzeXN0ZW0gYW5kIHN0cmVhbSBvcGVyYXRpb25zIHdpbGwgYmUgdHJhY2VkIGFjY29yZGluZyB0byB0aGUgY29uZmlndXJhdGlvbi4KICov"},{"repository_path":"src\/lib\/filesystem\/src\/Flow\/Filesystem\/DSL\/functions.php","start_line_in_file":135,"slug":"filesystem-telemetry-config","name":"filesystem_telemetry_config","namespace":"Flow\\Filesystem\\DSL","parameters":[{"name":"telemetry","type":[{"name":"Telemetry","namespace":"Flow\\Telemetry","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"clock","type":[{"name":"ClockInterface","namespace":"Psr\\Clock","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"options","type":[{"name":"FilesystemTelemetryOptions","namespace":"Flow\\Filesystem\\Telemetry","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"FilesystemTelemetryConfig","namespace":"Flow\\Filesystem\\Telemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHRlbGVtZXRyeSBjb25maWd1cmF0aW9uIGZvciB0aGUgZmlsZXN5c3RlbS4KICov"},{"repository_path":"src\/lib\/filesystem\/src\/Flow\/Filesystem\/DSL\/functions.php","start_line_in_file":150,"slug":"filesystem-telemetry-options","name":"filesystem_telemetry_options","namespace":"Flow\\Filesystem\\DSL","parameters":[{"name":"trace_streams","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"collect_metrics","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":"FilesystemTelemetryOptions","namespace":"Flow\\Filesystem\\Telemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBvcHRpb25zIGZvciBmaWxlc3lzdGVtIHRlbGVtZXRyeS4KICoKICogQHBhcmFtIGJvb2wgJHRyYWNlX3N0cmVhbXMgQ3JlYXRlIGEgc2luZ2xlIHNwYW4gcGVyIHN0cmVhbSBsaWZlY3ljbGUgKGRlZmF1bHQ6IE9OKQogKiBAcGFyYW0gYm9vbCAkY29sbGVjdF9tZXRyaWNzIENvbGxlY3QgbWV0cmljcyBmb3IgYnl0ZXMvb3BlcmF0aW9uIGNvdW50cyAoZGVmYXVsdDogT04pCiAqLw=="},{"repository_path":"src\/lib\/filesystem\/src\/Flow\/Filesystem\/DSL\/functions.php","start_line_in_file":163,"slug":"file-copy","name":"file_copy","namespace":"Flow\\Filesystem\\DSL","parameters":[{"name":"table","type":[{"name":"FilesystemTable","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"options","type":[{"name":"OperationOptions","namespace":"Flow\\Filesystem\\Operations","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Copy","namespace":"Flow\\Filesystem\\Operations","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENvcHkgYSBmaWxlIGZyb20gb25lIHBhdGggdG8gYW5vdGhlciwgYWNyb3NzIGFueSBmaWxlc3lzdGVtcyBtb3VudGVkIGluIHRoZSB0YWJsZS4KICogQWx3YXlzIHN0cmVhbXMgYnl0ZXM7IHNhbWUtZmlsZXN5c3RlbSBjb3BpZXMgZG8gbm90IHVzZSBzZXJ2ZXItc2lkZSBvcHRpbWl6YXRpb25zCiAqIGJlY2F1c2UgYEZpbGVzeXN0ZW06Om12YCBpcyBhIG1vdmUsIG5vdCBhIGNvcHkuCiAqLw=="},{"repository_path":"src\/lib\/filesystem\/src\/Flow\/Filesystem\/DSL\/functions.php","start_line_in_file":174,"slug":"file-move","name":"file_move","namespace":"Flow\\Filesystem\\DSL","parameters":[{"name":"table","type":[{"name":"FilesystemTable","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"options","type":[{"name":"OperationOptions","namespace":"Flow\\Filesystem\\Operations","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Move","namespace":"Flow\\Filesystem\\Operations","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIE1vdmUgYSBmaWxlIGZyb20gb25lIHBhdGggdG8gYW5vdGhlciwgYWNyb3NzIGFueSBmaWxlc3lzdGVtcyBtb3VudGVkIGluIHRoZSB0YWJsZS4KICogSW50cmEtZmlsZXN5c3RlbSBtb3ZlcyBkZWxlZ2F0ZSB0byBgRmlsZXN5c3RlbTo6bXZgIGZvciBzZXJ2ZXItc2lkZSBvcHRpbWl6YXRpb25zOwogKiBjcm9zcy1maWxlc3lzdGVtIG1vdmVzIHN0cmVhbS1jb3B5IHRoZW4gcmVtb3ZlIHRoZSBzb3VyY2UgKG5vbi1hdG9taWMpLgogKi8="},{"repository_path":"src\/lib\/filesystem\/src\/Flow\/Filesystem\/DSL\/functions.php","start_line_in_file":185,"slug":"operation-options","name":"operation_options","namespace":"Flow\\Filesystem\\DSL","parameters":[{"name":"chunkSize","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"8192"}],"return_type":[{"name":"OperationOptions","namespace":"Flow\\Filesystem\\Operations","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIE9wdGlvbnMgc2hhcmVkIGJ5IGZpbGVzeXN0ZW0gb3BlcmF0aW9ucy4KICoKICogQHBhcmFtIGludCAkY2h1bmtTaXplIE51bWJlciBvZiBieXRlcyByZWFkL3dyaXR0ZW4gcGVyIGl0ZXJhdGlvbiB3aGVuIHN0cmVhbWluZyBhY3Jvc3MgZmlsZXN5c3RlbXMgKGRlZmF1bHQ6IDgxOTIpCiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":70,"slug":"type-structure","name":"type_structure","namespace":"Flow\\Types\\DSL","parameters":[{"name":"elements","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"allow_extra","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":"StructureType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBhcnJheTxhcnJheS1rZXksIFN0cnVjdHVyZUVsZW1lbnQ8VD58VHlwZTxUPj4gJGVsZW1lbnRzCiAqCiAqIEByZXR1cm4gU3RydWN0dXJlVHlwZTxhcnJheTxhcnJheS1rZXksIFQ+PgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":85,"slug":"structure-element","name":"structure_element","namespace":"Flow\\Types\\DSL","parameters":[{"name":"name","type":[{"name":"string","namespace":null,"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":"type","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":"optional","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":"StructureElement","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqIEB0ZW1wbGF0ZSBUT3B0aW9uYWwgb2YgYm9vbAogKgogKiBAcGFyYW0gVHlwZTxUPiAkdHlwZQogKiBAcGFyYW0gVE9wdGlvbmFsICRvcHRpb25hbAogKgogKiBAcmV0dXJuIFN0cnVjdHVyZUVsZW1lbnQ8VCwgVE9wdGlvbmFsPgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":100,"slug":"type-union","name":"type_union","namespace":"Flow\\Types\\DSL","parameters":[{"name":"first","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":"second","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":"types","type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"UnionType","namespace":"Flow\\Types\\Type\\Native","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBUeXBlPFQ+ICRmaXJzdAogKiBAcGFyYW0gVHlwZTxUPiAkc2Vjb25kCiAqIEBwYXJhbSBUeXBlPFQ+IC4uLiR0eXBlcwogKgogKiBAcmV0dXJuIFVuaW9uVHlwZTxULCBUPgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":121,"slug":"type-intersection","name":"type_intersection","namespace":"Flow\\Types\\DSL","parameters":[{"name":"first","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":"second","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":"types","type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"IntersectionType","namespace":"Flow\\Types\\Type\\Native","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBUeXBlPFQ+ICRmaXJzdAogKiBAcGFyYW0gVHlwZTxUPiAkc2Vjb25kCiAqIEBwYXJhbSBUeXBlPFQ+IC4uLiR0eXBlcwogKgogKiBAcmV0dXJuIEludGVyc2VjdGlvblR5cGU8VCwgVD4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":136,"slug":"type-numeric-string","name":"type_numeric_string","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"NumericStringType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gTnVtZXJpY1N0cmluZ1R5cGU8bnVtZXJpYy1zdHJpbmc+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":149,"slug":"type-optional","name":"type_optional","namespace":"Flow\\Types\\DSL","parameters":[{"name":"type","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}],"return_type":[{"name":"OptionalType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBUeXBlPFQ+ICR0eXBlCiAqCiAqIEByZXR1cm4gT3B0aW9uYWxUeXBlPFQ+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":160,"slug":"type-from-array","name":"type_from_array","namespace":"Flow\\Types\\DSL","parameters":[{"name":"data","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":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxzdHJpbmcsIG1peGVkPiAkZGF0YQogKgogKiBAcmV0dXJuIFR5cGU8bWl4ZWQ+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":171,"slug":"type-is-nullable","name":"type_is_nullable","namespace":"Flow\\Types\\DSL","parameters":[{"name":"type","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}],"return_type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBUeXBlPFQ+ICR0eXBlCiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":187,"slug":"type-bare","name":"type_bare","namespace":"Flow\\Types\\DSL","parameters":[{"name":"type","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}],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFN0cmlwIGV4YWN0bHkgb25lIGxldmVsIG9mIG51bGxhYmlsaXR5LCB3aGljaGV2ZXIgb2YgdGhlIHR3byBzcGVsbGluZ3MgY2FycmllcyBpdAogKiAoT3B0aW9uYWxUeXBlLCBvciBhIFVuaW9uVHlwZSBjb250YWluaW5nIE51bGxUeXBlKS4gVG90YWw6IGEgTk9UIE5VTEwgdHlwZSBpcyByZXR1cm5lZCB1bmNoYW5nZWQuCiAqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBUeXBlPFQ+ICR0eXBlCiAqCiAqIEByZXR1cm4gVHlwZTxtaXhlZD4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":197,"slug":"type-equals","name":"type_equals","namespace":"Flow\\Types\\DSL","parameters":[{"name":"left","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":"right","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}],"return_type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBUeXBlPG1peGVkPiAkbGVmdAogKiBAcGFyYW0gVHlwZTxtaXhlZD4gJHJpZ2h0CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":210,"slug":"types","name":"types","namespace":"Flow\\Types\\DSL","parameters":[{"name":"types","type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"Types","namespace":"Flow\\Types\\Type","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBUeXBlPFQ+IC4uLiR0eXBlcwogKgogKiBAcmV0dXJuIFR5cGVzPFQ+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":223,"slug":"type-list","name":"type_list","namespace":"Flow\\Types\\DSL","parameters":[{"name":"element","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}],"return_type":[{"name":"ListType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBUeXBlPFQ+ICRlbGVtZW50CiAqCiAqIEByZXR1cm4gTGlzdFR5cGU8bGlzdDxUPj4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":238,"slug":"type-map","name":"type_map","namespace":"Flow\\Types\\DSL","parameters":[{"name":"key_type","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":"value_type","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}],"return_type":[{"name":"MapType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUS2V5IG9mIGFycmF5LWtleQogKiBAdGVtcGxhdGUgVFZhbHVlCiAqCiAqIEBwYXJhbSBUeXBlPFRLZXk+ICRrZXlfdHlwZQogKiBAcGFyYW0gVHlwZTxUVmFsdWU+ICR2YWx1ZV90eXBlCiAqCiAqIEByZXR1cm4gTWFwVHlwZTxhcnJheTxUS2V5LCBUVmFsdWU+PgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":247,"slug":"type-json","name":"type_json","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"JsonType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gSnNvblR5cGU8SnNvbj4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":256,"slug":"type-datetime","name":"type_datetime","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"DateTimeType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gRGF0ZVRpbWVUeXBlPFxEYXRlVGltZUludGVyZmFjZT4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":265,"slug":"type-date","name":"type_date","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"DateType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gRGF0ZVR5cGU8XERhdGVUaW1lSW50ZXJmYWNlPgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":274,"slug":"type-time","name":"type_time","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"TimeType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVGltZVR5cGU8XERhdGVJbnRlcnZhbD4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":283,"slug":"type-time-zone","name":"type_time_zone","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"TimeZoneType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVGltZVpvbmVUeXBlPFxEYXRlVGltZVpvbmU+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":292,"slug":"type-xml","name":"type_xml","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"XMLType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gWE1MVHlwZTxcRE9NRG9jdW1lbnR8WE1MRG9jdW1lbnQ+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":301,"slug":"type-xml-element","name":"type_xml_element","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"XMLElementType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gWE1MRWxlbWVudFR5cGU8XERPTUVsZW1lbnR8RWxlbWVudD4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":310,"slug":"type-uuid","name":"type_uuid","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"UuidType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVXVpZFR5cGU8VXVpZD4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":319,"slug":"type-integer","name":"type_integer","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"IntegerType","namespace":"Flow\\Types\\Type\\Native","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gSW50ZWdlclR5cGU8aW50PgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":328,"slug":"type-string","name":"type_string","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"StringType","namespace":"Flow\\Types\\Type\\Native","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gU3RyaW5nVHlwZTxzdHJpbmc+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":337,"slug":"type-float","name":"type_float","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"FloatType","namespace":"Flow\\Types\\Type\\Native","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gRmxvYXRUeXBlPGZsb2F0PgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":346,"slug":"type-boolean","name":"type_boolean","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"BooleanType","namespace":"Flow\\Types\\Type\\Native","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gQm9vbGVhblR5cGU8Ym9vbD4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":359,"slug":"type-instance-of","name":"type_instance_of","namespace":"Flow\\Types\\DSL","parameters":[{"name":"class","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":"InstanceOfType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUIG9mIG9iamVjdAogKgogKiBAcGFyYW0gY2xhc3Mtc3RyaW5nPFQ+ICRjbGFzcwogKgogKiBAcmV0dXJuIEluc3RhbmNlT2ZUeXBlPFQ+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":368,"slug":"type-object","name":"type_object","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"ObjectType","namespace":"Flow\\Types\\Type\\Native","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gT2JqZWN0VHlwZTxvYmplY3Q+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":377,"slug":"type-scalar","name":"type_scalar","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"ScalarType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gU2NhbGFyVHlwZTxib29sfGZsb2F0fGludHxzdHJpbmc+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":386,"slug":"type-resource","name":"type_resource","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"ResourceType","namespace":"Flow\\Types\\Type\\Native","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gUmVzb3VyY2VUeXBlPHJlc291cmNlPgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":395,"slug":"type-array","name":"type_array","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"ArrayType","namespace":"Flow\\Types\\Type\\Native","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gQXJyYXlUeXBlPGFycmF5PG1peGVkPj4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":404,"slug":"type-callable","name":"type_callable","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"CallableType","namespace":"Flow\\Types\\Type\\Native","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gQ2FsbGFibGVUeXBlPGNhbGxhYmxlPgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":413,"slug":"type-null","name":"type_null","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"NullType","namespace":"Flow\\Types\\Type\\Native","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gTnVsbFR5cGU8bnVsbD4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":422,"slug":"type-mixed","name":"type_mixed","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"MixedType","namespace":"Flow\\Types\\Type\\Native","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gTWl4ZWRUeXBlPG1peGVkPgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":431,"slug":"type-positive-integer","name":"type_positive_integer","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"PositiveIntegerType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gUG9zaXRpdmVJbnRlZ2VyVHlwZTxpbnQ8MCwgbWF4Pj4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":440,"slug":"type-non-empty-string","name":"type_non_empty_string","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"NonEmptyStringType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gTm9uRW1wdHlTdHJpbmdUeXBlPG5vbi1lbXB0eS1zdHJpbmc+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":449,"slug":"type-empty-array","name":"type_empty_array","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"EmptyArrayType","namespace":"Flow\\Types\\Type\\Native","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gRW1wdHlBcnJheVR5cGU8YXJyYXl7fT4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":462,"slug":"type-enum","name":"type_enum","namespace":"Flow\\Types\\DSL","parameters":[{"name":"class","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":"EnumType","namespace":"Flow\\Types\\Type\\Native","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUIG9mIFVuaXRFbnVtCiAqCiAqIEBwYXJhbSBjbGFzcy1zdHJpbmc8VD4gJGNsYXNzCiAqCiAqIEByZXR1cm4gRW51bVR5cGU8VD4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":475,"slug":"type-literal","name":"type_literal","namespace":"Flow\\Types\\DSL","parameters":[{"name":"value","type":[{"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":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"LiteralType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUIG9mIGJvb2x8ZmxvYXR8aW50fHN0cmluZwogKgogKiBAcGFyYW0gVCAkdmFsdWUKICoKICogQHJldHVybiBMaXRlcmFsVHlwZTxUPgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":484,"slug":"type-html","name":"type_html","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"HTMLType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gSFRNTFR5cGU8SFRNTERvY3VtZW50PgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":493,"slug":"type-html-element","name":"type_html_element","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"HTMLElementType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gSFRNTEVsZW1lbnRUeXBlPEhUTUxFbGVtZW50PgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":505,"slug":"type-is","name":"type_is","namespace":"Flow\\Types\\DSL","parameters":[{"name":"type","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":"typeClass","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":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBUeXBlPFQ+ICR0eXBlCiAqIEBwYXJhbSBjbGFzcy1zdHJpbmc8VHlwZTxtaXhlZD4+ICR0eXBlQ2xhc3MKICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":518,"slug":"type-is-any","name":"type_is_any","namespace":"Flow\\Types\\DSL","parameters":[{"name":"type","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":"typeClass","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":"typeClasses","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":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBUeXBlPFQ+ICR0eXBlCiAqIEBwYXJhbSBjbGFzcy1zdHJpbmc8VHlwZTxtaXhlZD4+ICR0eXBlQ2xhc3MKICogQHBhcmFtIGNsYXNzLXN0cmluZzxUeXBlPG1peGVkPj4gLi4uJHR5cGVDbGFzc2VzCiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":527,"slug":"get-type","name":"get_type","namespace":"Flow\\Types\\DSL","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":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxtaXhlZD4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":540,"slug":"type-class-string","name":"type_class_string","namespace":"Flow\\Types\\DSL","parameters":[{"name":"class","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"ClassStringType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUIG9mIG9iamVjdAogKgogKiBAcGFyYW0gbnVsbHxjbGFzcy1zdHJpbmc8VD4gJGNsYXNzCiAqCiAqIEByZXR1cm4gKCRjbGFzcyBpcyBudWxsID8gQ2xhc3NTdHJpbmdUeXBlPGNsYXNzLXN0cmluZz4gOiBDbGFzc1N0cmluZ1R5cGU8Y2xhc3Mtc3RyaW5nPFQ+PikKICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":546,"slug":"dom-element-to-string","name":"dom_element_to_string","namespace":"Flow\\Types\\DSL","parameters":[{"name":"element","type":[{"name":"DOMElement","namespace":"","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"format_output","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"preserver_white_space","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":"string","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"false","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":134,"slug":"column","name":"column","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"type","type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ColumnDefinition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGNvbHVtbiBkZWZpbml0aW9uIGZvciBDUkVBVEUgVEFCTEUuCiAqCiAqIEBwYXJhbSBzdHJpbmcgJG5hbWUgQ29sdW1uIG5hbWUKICogQHBhcmFtIENvbHVtblR5cGUgJHR5cGUgQ29sdW1uIGRhdGEgdHlwZQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":143,"slug":"catalog","name":"catalog","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"schemas","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":"Catalog","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBsaXN0PFNjaGVtYT4gJHNjaGVtYXMKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":154,"slug":"primary-key","name":"primary_key","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"columns","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":"PrimaryKeyConstraint","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Constraint","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBSSU1BUlkgS0VZIGNvbnN0cmFpbnQuCiAqCiAqIEBwYXJhbSBzdHJpbmcgLi4uJGNvbHVtbnMgQ29sdW1ucyB0aGF0IGZvcm0gdGhlIHByaW1hcnkga2V5CiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":165,"slug":"unique-constraint","name":"unique_constraint","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"columns","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":"UniqueConstraint","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Constraint","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFVOSVFVRSBjb25zdHJhaW50LgogKgogKiBAcGFyYW0gc3RyaW5nIC4uLiRjb2x1bW5zIENvbHVtbnMgdGhhdCBtdXN0IGJlIHVuaXF1ZSB0b2dldGhlcgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":178,"slug":"foreign-key","name":"foreign_key","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"columns","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":"referenceTable","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":"referenceColumns","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"ForeignKeyConstraint","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Constraint","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEZPUkVJR04gS0VZIGNvbnN0cmFpbnQuCiAqCiAqIEBwYXJhbSBsaXN0PHN0cmluZz4gJGNvbHVtbnMgTG9jYWwgY29sdW1ucwogKiBAcGFyYW0gc3RyaW5nICRyZWZlcmVuY2VUYWJsZSBSZWZlcmVuY2VkIHRhYmxlCiAqIEBwYXJhbSBsaXN0PHN0cmluZz4gJHJlZmVyZW5jZUNvbHVtbnMgUmVmZXJlbmNlZCBjb2x1bW5zIChkZWZhdWx0cyB0byBzYW1lIGFzICRjb2x1bW5zIGlmIGVtcHR5KQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":187,"slug":"check-constraint","name":"check_constraint","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"condition","type":[{"name":"Condition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"CheckConstraint","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Constraint","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENIRUNLIGNvbnN0cmFpbnQuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":218,"slug":"create","name":"create","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"CreateFactory","namespace":"Flow\\PostgreSql\\QueryBuilder\\Factory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGZhY3RvcnkgZm9yIGJ1aWxkaW5nIENSRUFURSBzdGF0ZW1lbnRzLgogKgogKiBQcm92aWRlcyBhIHVuaWZpZWQgZW50cnkgcG9pbnQgZm9yIGFsbCBDUkVBVEUgb3BlcmF0aW9uczoKICogLSBjcmVhdGUoKS0+dGFibGUoKSAtIENSRUFURSBUQUJMRQogKiAtIGNyZWF0ZSgpLT50YWJsZUFzKCkgLSBDUkVBVEUgVEFCTEUgQVMKICogLSBjcmVhdGUoKS0+aW5kZXgoKSAtIENSRUFURSBJTkRFWAogKiAtIGNyZWF0ZSgpLT52aWV3KCkgLSBDUkVBVEUgVklFVwogKiAtIGNyZWF0ZSgpLT5tYXRlcmlhbGl6ZWRWaWV3KCkgLSBDUkVBVEUgTUFURVJJQUxJWkVEIFZJRVcKICogLSBjcmVhdGUoKS0+c2VxdWVuY2UoKSAtIENSRUFURSBTRVFVRU5DRQogKiAtIGNyZWF0ZSgpLT5zY2hlbWEoKSAtIENSRUFURSBTQ0hFTUEKICogLSBjcmVhdGUoKS0+cm9sZSgpIC0gQ1JFQVRFIFJPTEUKICogLSBjcmVhdGUoKS0+ZnVuY3Rpb24oKSAtIENSRUFURSBGVU5DVElPTgogKiAtIGNyZWF0ZSgpLT5wcm9jZWR1cmUoKSAtIENSRUFURSBQUk9DRURVUkUKICogLSBjcmVhdGUoKS0+dHJpZ2dlcigpIC0gQ1JFQVRFIFRSSUdHRVIKICogLSBjcmVhdGUoKS0+cnVsZSgpIC0gQ1JFQVRFIFJVTEUKICogLSBjcmVhdGUoKS0+ZXh0ZW5zaW9uKCkgLSBDUkVBVEUgRVhURU5TSU9OCiAqIC0gY3JlYXRlKCktPmNvbXBvc2l0ZVR5cGUoKSAtIENSRUFURSBUWVBFIChjb21wb3NpdGUpCiAqIC0gY3JlYXRlKCktPmVudW1UeXBlKCkgLSBDUkVBVEUgVFlQRSAoZW51bSkKICogLSBjcmVhdGUoKS0+cmFuZ2VUeXBlKCkgLSBDUkVBVEUgVFlQRSAocmFuZ2UpCiAqIC0gY3JlYXRlKCktPmRvbWFpbigpIC0gQ1JFQVRFIERPTUFJTgogKgogKiBFeGFtcGxlOiBjcmVhdGUoKS0+dGFibGUoJ3VzZXJzJyktPmNvbHVtbnMoY29sX2RlZignaWQnLCBjb2x1bW5fdHlwZV9zZXJpYWwoKSkpCiAqIEV4YW1wbGU6IGNyZWF0ZSgpLT5pbmRleCgnaWR4X2VtYWlsJyktPm9uKCd1c2VycycpLT5jb2x1bW5zKCdlbWFpbCcpCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":247,"slug":"drop","name":"drop","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"DropFactory","namespace":"Flow\\PostgreSql\\QueryBuilder\\Factory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGZhY3RvcnkgZm9yIGJ1aWxkaW5nIERST1Agc3RhdGVtZW50cy4KICoKICogUHJvdmlkZXMgYSB1bmlmaWVkIGVudHJ5IHBvaW50IGZvciBhbGwgRFJPUCBvcGVyYXRpb25zOgogKiAtIGRyb3AoKS0+dGFibGUoKSAtIERST1AgVEFCTEUKICogLSBkcm9wKCktPmluZGV4KCkgLSBEUk9QIElOREVYCiAqIC0gZHJvcCgpLT52aWV3KCkgLSBEUk9QIFZJRVcKICogLSBkcm9wKCktPm1hdGVyaWFsaXplZFZpZXcoKSAtIERST1AgTUFURVJJQUxJWkVEIFZJRVcKICogLSBkcm9wKCktPnNlcXVlbmNlKCkgLSBEUk9QIFNFUVVFTkNFCiAqIC0gZHJvcCgpLT5zY2hlbWEoKSAtIERST1AgU0NIRU1BCiAqIC0gZHJvcCgpLT5yb2xlKCkgLSBEUk9QIFJPTEUKICogLSBkcm9wKCktPmZ1bmN0aW9uKCkgLSBEUk9QIEZVTkNUSU9OCiAqIC0gZHJvcCgpLT5wcm9jZWR1cmUoKSAtIERST1AgUFJPQ0VEVVJFCiAqIC0gZHJvcCgpLT50cmlnZ2VyKCkgLSBEUk9QIFRSSUdHRVIKICogLSBkcm9wKCktPnJ1bGUoKSAtIERST1AgUlVMRQogKiAtIGRyb3AoKS0+ZXh0ZW5zaW9uKCkgLSBEUk9QIEVYVEVOU0lPTgogKiAtIGRyb3AoKS0+dHlwZSgpIC0gRFJPUCBUWVBFCiAqIC0gZHJvcCgpLT5kb21haW4oKSAtIERST1AgRE9NQUlOCiAqIC0gZHJvcCgpLT5vd25lZCgpIC0gRFJPUCBPV05FRAogKgogKiBFeGFtcGxlOiBkcm9wKCktPnRhYmxlKCd1c2VycycsICdvcmRlcnMnKS0+aWZFeGlzdHMoKS0+Y2FzY2FkZSgpCiAqIEV4YW1wbGU6IGRyb3AoKS0+aW5kZXgoJ2lkeF9lbWFpbCcpLT5pZkV4aXN0cygpCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":281,"slug":"alter","name":"alter","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"AlterFactory","namespace":"Flow\\PostgreSql\\QueryBuilder\\Factory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGZhY3RvcnkgZm9yIGJ1aWxkaW5nIEFMVEVSIHN0YXRlbWVudHMuCiAqCiAqIFByb3ZpZGVzIGEgdW5pZmllZCBlbnRyeSBwb2ludCBmb3IgYWxsIEFMVEVSIG9wZXJhdGlvbnM6CiAqIC0gYWx0ZXIoKS0+dGFibGUoKSAtIEFMVEVSIFRBQkxFCiAqIC0gYWx0ZXIoKS0+aW5kZXgoKSAtIEFMVEVSIElOREVYCiAqIC0gYWx0ZXIoKS0+dmlldygpIC0gQUxURVIgVklFVwogKiAtIGFsdGVyKCktPm1hdGVyaWFsaXplZFZpZXcoKSAtIEFMVEVSIE1BVEVSSUFMSVpFRCBWSUVXCiAqIC0gYWx0ZXIoKS0+c2VxdWVuY2UoKSAtIEFMVEVSIFNFUVVFTkNFCiAqIC0gYWx0ZXIoKS0+c2NoZW1hKCkgLSBBTFRFUiBTQ0hFTUEKICogLSBhbHRlcigpLT5yb2xlKCkgLSBBTFRFUiBST0xFCiAqIC0gYWx0ZXIoKS0+ZnVuY3Rpb24oKSAtIEFMVEVSIEZVTkNUSU9OCiAqIC0gYWx0ZXIoKS0+cHJvY2VkdXJlKCkgLSBBTFRFUiBQUk9DRURVUkUKICogLSBhbHRlcigpLT50cmlnZ2VyKCkgLSBBTFRFUiBUUklHR0VSCiAqIC0gYWx0ZXIoKS0+ZXh0ZW5zaW9uKCkgLSBBTFRFUiBFWFRFTlNJT04KICogLSBhbHRlcigpLT5lbnVtVHlwZSgpIC0gQUxURVIgVFlQRSAoZW51bSkKICogLSBhbHRlcigpLT5kb21haW4oKSAtIEFMVEVSIERPTUFJTgogKgogKiBSZW5hbWUgb3BlcmF0aW9ucyBhcmUgYWxzbyB1bmRlciBhbHRlcigpOgogKiAtIGFsdGVyKCktPmluZGV4KCdvbGQnKS0+cmVuYW1lVG8oJ25ldycpCiAqIC0gYWx0ZXIoKS0+dmlldygnb2xkJyktPnJlbmFtZVRvKCduZXcnKQogKiAtIGFsdGVyKCktPnNjaGVtYSgnb2xkJyktPnJlbmFtZVRvKCduZXcnKQogKiAtIGFsdGVyKCktPnJvbGUoJ29sZCcpLT5yZW5hbWVUbygnbmV3JykKICogLSBhbHRlcigpLT50cmlnZ2VyKCdvbGQnKS0+b24oJ3RhYmxlJyktPnJlbmFtZVRvKCduZXcnKQogKgogKiBFeGFtcGxlOiBhbHRlcigpLT50YWJsZSgndXNlcnMnKS0+YWRkQ29sdW1uKGNvbF9kZWYoJ2VtYWlsJywgY29sdW1uX3R5cGVfdGV4dCgpKSkKICogRXhhbXBsZTogYWx0ZXIoKS0+c2VxdWVuY2UoJ3VzZXJfaWRfc2VxJyktPnJlc3RhcnQoMTAwMCkKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":292,"slug":"truncate-table","name":"truncate_table","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"tables","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":"TruncateFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Truncate","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFRSVU5DQVRFIFRBQkxFIGJ1aWxkZXIuCiAqCiAqIEBwYXJhbSBzdHJpbmcgLi4uJHRhYmxlcyBUYWJsZSBuYW1lcyB0byB0cnVuY2F0ZQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":310,"slug":"refresh-materialized-view","name":"refresh_materialized_view","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"schema","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"RefreshMatViewOptionsStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\View\\RefreshMaterializedView","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFJFRlJFU0ggTUFURVJJQUxJWkVEIFZJRVcgYnVpbGRlci4KICoKICogRXhhbXBsZTogcmVmcmVzaF9tYXRlcmlhbGl6ZWRfdmlldygndXNlcl9zdGF0cycpCiAqIFByb2R1Y2VzOiBSRUZSRVNIIE1BVEVSSUFMSVpFRCBWSUVXIHVzZXJfc3RhdHMKICoKICogRXhhbXBsZTogcmVmcmVzaF9tYXRlcmlhbGl6ZWRfdmlldygndXNlcl9zdGF0cycpLT5jb25jdXJyZW50bHkoKS0+d2l0aERhdGEoKQogKiBQcm9kdWNlczogUkVGUkVTSCBNQVRFUklBTElaRUQgVklFVyBDT05DVVJSRU5UTFkgdXNlcl9zdGF0cyBXSVRIIERBVEEKICoKICogQHBhcmFtIHN0cmluZyAkbmFtZSBWaWV3IG5hbWUgKG1heSBpbmNsdWRlIHNjaGVtYSBhcyAic2NoZW1hLnZpZXciKQogKiBAcGFyYW0gbnVsbHxzdHJpbmcgJHNjaGVtYSBTY2hlbWEgbmFtZSAob3B0aW9uYWwsIG92ZXJyaWRlcyBwYXJzZWQgc2NoZW1hKQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":319,"slug":"ref-action-cascade","name":"ref_action_cascade","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ReferentialAction","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEdldCBhIENBU0NBREUgcmVmZXJlbnRpYWwgYWN0aW9uLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":328,"slug":"ref-action-restrict","name":"ref_action_restrict","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ReferentialAction","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEdldCBhIFJFU1RSSUNUIHJlZmVyZW50aWFsIGFjdGlvbi4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":337,"slug":"ref-action-set-null","name":"ref_action_set_null","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ReferentialAction","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEdldCBhIFNFVCBOVUxMIHJlZmVyZW50aWFsIGFjdGlvbi4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":346,"slug":"ref-action-set-default","name":"ref_action_set_default","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ReferentialAction","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEdldCBhIFNFVCBERUZBVUxUIHJlZmVyZW50aWFsIGFjdGlvbi4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":355,"slug":"ref-action-no-action","name":"ref_action_no_action","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ReferentialAction","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEdldCBhIE5PIEFDVElPTiByZWZlcmVudGlhbCBhY3Rpb24uCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":370,"slug":"reindex-index","name":"reindex_index","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"ReindexFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Index\\Reindex","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFN0YXJ0IGJ1aWxkaW5nIGEgUkVJTkRFWCBJTkRFWCBzdGF0ZW1lbnQuCiAqCiAqIFVzZSBjaGFpbmFibGUgbWV0aG9kczogLT5jb25jdXJyZW50bHkoKSwgLT52ZXJib3NlKCksIC0+dGFibGVzcGFjZSgpCiAqCiAqIEV4YW1wbGU6IHJlaW5kZXhfaW5kZXgoJ2lkeF91c2Vyc19lbWFpbCcpLT5jb25jdXJyZW50bHkoKQogKgogKiBAcGFyYW0gc3RyaW5nICRuYW1lIFRoZSBpbmRleCBuYW1lIChtYXkgaW5jbHVkZSBzY2hlbWE6IHNjaGVtYS5pbmRleCkKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":385,"slug":"reindex-table","name":"reindex_table","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"ReindexFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Index\\Reindex","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFN0YXJ0IGJ1aWxkaW5nIGEgUkVJTkRFWCBUQUJMRSBzdGF0ZW1lbnQuCiAqCiAqIFVzZSBjaGFpbmFibGUgbWV0aG9kczogLT5jb25jdXJyZW50bHkoKSwgLT52ZXJib3NlKCksIC0+dGFibGVzcGFjZSgpCiAqCiAqIEV4YW1wbGU6IHJlaW5kZXhfdGFibGUoJ3VzZXJzJyktPmNvbmN1cnJlbnRseSgpCiAqCiAqIEBwYXJhbSBzdHJpbmcgJG5hbWUgVGhlIHRhYmxlIG5hbWUgKG1heSBpbmNsdWRlIHNjaGVtYTogc2NoZW1hLnRhYmxlKQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":400,"slug":"reindex-schema","name":"reindex_schema","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"ReindexFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Index\\Reindex","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFN0YXJ0IGJ1aWxkaW5nIGEgUkVJTkRFWCBTQ0hFTUEgc3RhdGVtZW50LgogKgogKiBVc2UgY2hhaW5hYmxlIG1ldGhvZHM6IC0+Y29uY3VycmVudGx5KCksIC0+dmVyYm9zZSgpLCAtPnRhYmxlc3BhY2UoKQogKgogKiBFeGFtcGxlOiByZWluZGV4X3NjaGVtYSgncHVibGljJyktPmNvbmN1cnJlbnRseSgpCiAqCiAqIEBwYXJhbSBzdHJpbmcgJG5hbWUgVGhlIHNjaGVtYSBuYW1lCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":415,"slug":"reindex-database","name":"reindex_database","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"ReindexFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Index\\Reindex","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFN0YXJ0IGJ1aWxkaW5nIGEgUkVJTkRFWCBEQVRBQkFTRSBzdGF0ZW1lbnQuCiAqCiAqIFVzZSBjaGFpbmFibGUgbWV0aG9kczogLT5jb25jdXJyZW50bHkoKSwgLT52ZXJib3NlKCksIC0+dGFibGVzcGFjZSgpCiAqCiAqIEV4YW1wbGU6IHJlaW5kZXhfZGF0YWJhc2UoJ215ZGInKS0+Y29uY3VycmVudGx5KCkKICoKICogQHBhcmFtIHN0cmluZyAkbmFtZSBUaGUgZGF0YWJhc2UgbmFtZQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":430,"slug":"index-col","name":"index_col","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"IndexColumn","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Index","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBpbmRleCBjb2x1bW4gc3BlY2lmaWNhdGlvbi4KICoKICogVXNlIGNoYWluYWJsZSBtZXRob2RzOiAtPmFzYygpLCAtPmRlc2MoKSwgLT5udWxsc0ZpcnN0KCksIC0+bnVsbHNMYXN0KCksIC0+b3BjbGFzcygpLCAtPmNvbGxhdGUoKQogKgogKiBFeGFtcGxlOiBpbmRleF9jb2woJ2VtYWlsJyktPmRlc2MoKS0+bnVsbHNMYXN0KCkKICoKICogQHBhcmFtIHN0cmluZyAkbmFtZSBUaGUgY29sdW1uIG5hbWUKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":445,"slug":"index-expr","name":"index_expr","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expression","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"IndexColumn","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Index","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBpbmRleCBjb2x1bW4gc3BlY2lmaWNhdGlvbiBmcm9tIGFuIGV4cHJlc3Npb24uCiAqCiAqIFVzZSBjaGFpbmFibGUgbWV0aG9kczogLT5hc2MoKSwgLT5kZXNjKCksIC0+bnVsbHNGaXJzdCgpLCAtPm51bGxzTGFzdCgpLCAtPm9wY2xhc3MoKSwgLT5jb2xsYXRlKCkKICoKICogRXhhbXBsZTogaW5kZXhfZXhwcihmbl9jYWxsKCdsb3dlcicsIGNvbCgnZW1haWwnKSkpLT5kZXNjKCkKICoKICogQHBhcmFtIEV4cHJlc3Npb24gJGV4cHJlc3Npb24gVGhlIGV4cHJlc3Npb24gdG8gaW5kZXgKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":454,"slug":"index-method-btree","name":"index_method_btree","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"IndexMethod","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Index","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEdldCB0aGUgQlRSRUUgaW5kZXggbWV0aG9kLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":463,"slug":"index-method-hash","name":"index_method_hash","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"IndexMethod","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Index","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEdldCB0aGUgSEFTSCBpbmRleCBtZXRob2QuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":472,"slug":"index-method-gist","name":"index_method_gist","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"IndexMethod","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Index","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEdldCB0aGUgR0lTVCBpbmRleCBtZXRob2QuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":481,"slug":"index-method-spgist","name":"index_method_spgist","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"IndexMethod","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Index","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEdldCB0aGUgU1BHSVNUIGluZGV4IG1ldGhvZC4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":490,"slug":"index-method-gin","name":"index_method_gin","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"IndexMethod","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Index","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEdldCB0aGUgR0lOIGluZGV4IG1ldGhvZC4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":499,"slug":"index-method-brin","name":"index_method_brin","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"IndexMethod","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Index","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEdldCB0aGUgQlJJTiBpbmRleCBtZXRob2QuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":511,"slug":"vacuum","name":"vacuum","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"VacuumFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Utility","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFZBQ1VVTSBidWlsZGVyLgogKgogKiBFeGFtcGxlOiB2YWN1dW0oKS0+dGFibGUoJ3VzZXJzJykKICogUHJvZHVjZXM6IFZBQ1VVTSB1c2VycwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":523,"slug":"analyze","name":"analyze","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"AnalyzeFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Utility","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBBTkFMWVpFIGJ1aWxkZXIuCiAqCiAqIEV4YW1wbGU6IGFuYWx5emUoKS0+dGFibGUoJ3VzZXJzJykKICogUHJvZHVjZXM6IEFOQUxZWkUgdXNlcnMKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":537,"slug":"explain","name":"explain","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"query","type":[{"name":"SelectFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Select","is_nullable":false,"is_variadic":false},{"name":"InsertBuilder","namespace":"Flow\\PostgreSql\\QueryBuilder\\Insert","is_nullable":false,"is_variadic":false},{"name":"UpdateBuilder","namespace":"Flow\\PostgreSql\\QueryBuilder\\Update","is_nullable":false,"is_variadic":false},{"name":"DeleteBuilder","namespace":"Flow\\PostgreSql\\QueryBuilder\\Delete","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ExplainFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Utility","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBFWFBMQUlOIGJ1aWxkZXIgZm9yIGEgcXVlcnkuCiAqCiAqIEV4YW1wbGU6IGV4cGxhaW4oc2VsZWN0KCktPmZyb20oJ3VzZXJzJykpCiAqIFByb2R1Y2VzOiBFWFBMQUlOIFNFTEVDVCAqIEZST00gdXNlcnMKICoKICogQHBhcmFtIERlbGV0ZUJ1aWxkZXJ8SW5zZXJ0QnVpbGRlcnxTZWxlY3RGaW5hbFN0ZXB8VXBkYXRlQnVpbGRlciAkcXVlcnkgUXVlcnkgdG8gZXhwbGFpbgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":549,"slug":"lock-table","name":"lock_table","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"tables","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":"LockFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Utility","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIExPQ0sgVEFCTEUgYnVpbGRlci4KICoKICogRXhhbXBsZTogbG9ja190YWJsZSgndXNlcnMnLCAnb3JkZXJzJyktPmFjY2Vzc0V4Y2x1c2l2ZSgpCiAqIFByb2R1Y2VzOiBMT0NLIFRBQkxFIHVzZXJzLCBvcmRlcnMgSU4gQUNDRVNTIEVYQ0xVU0lWRSBNT0RFCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":564,"slug":"comment","name":"comment","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"target","type":[{"name":"CommentTarget","namespace":"Flow\\PostgreSql\\QueryBuilder\\Utility","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"name","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":"CommentFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Utility","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENPTU1FTlQgT04gYnVpbGRlci4KICoKICogRXhhbXBsZTogY29tbWVudChDb21tZW50VGFyZ2V0OjpUQUJMRSwgJ3VzZXJzJyktPmlzKCdVc2VyIGFjY291bnRzIHRhYmxlJykKICogUHJvZHVjZXM6IENPTU1FTlQgT04gVEFCTEUgdXNlcnMgSVMgJ1VzZXIgYWNjb3VudHMgdGFibGUnCiAqCiAqIEBwYXJhbSBDb21tZW50VGFyZ2V0ICR0YXJnZXQgVGFyZ2V0IHR5cGUgKFRBQkxFLCBDT0xVTU4sIElOREVYLCBldGMuKQogKiBAcGFyYW0gc3RyaW5nICRuYW1lIFRhcmdldCBuYW1lICh1c2UgJ3RhYmxlLmNvbHVtbicgZm9yIENPTFVNTiB0YXJnZXRzKQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":576,"slug":"cluster","name":"cluster","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ClusterFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Utility","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENMVVNURVIgYnVpbGRlci4KICoKICogRXhhbXBsZTogY2x1c3RlcigpLT50YWJsZSgndXNlcnMnKS0+dXNpbmcoJ2lkeF91c2Vyc19wa2V5JykKICogUHJvZHVjZXM6IENMVVNURVIgdXNlcnMgVVNJTkcgaWR4X3VzZXJzX3BrZXkKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":590,"slug":"discard","name":"discard","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"type","type":[{"name":"DiscardType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Utility","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"DiscardFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Utility","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIERJU0NBUkQgYnVpbGRlci4KICoKICogRXhhbXBsZTogZGlzY2FyZChEaXNjYXJkVHlwZTo6QUxMKQogKiBQcm9kdWNlczogRElTQ0FSRCBBTEwKICoKICogQHBhcmFtIERpc2NhcmRUeXBlICR0eXBlIFR5cGUgb2YgcmVzb3VyY2VzIHRvIGRpc2NhcmQgKEFMTCwgUExBTlMsIFNFUVVFTkNFUywgVEVNUCkKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":609,"slug":"grant","name":"grant","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"privileges","type":[{"name":"TablePrivilege","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Grant","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":"GrantOnStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Grant","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEdSQU5UIHByaXZpbGVnZXMgYnVpbGRlci4KICoKICogRXhhbXBsZTogZ3JhbnQoVGFibGVQcml2aWxlZ2U6OlNFTEVDVCktPm9uVGFibGUoJ3VzZXJzJyktPnRvKCdhcHBfdXNlcicpCiAqIFByb2R1Y2VzOiBHUkFOVCBTRUxFQ1QgT04gdXNlcnMgVE8gYXBwX3VzZXIKICoKICogRXhhbXBsZTogZ3JhbnQoVGFibGVQcml2aWxlZ2U6OkFMTCktPm9uQWxsVGFibGVzSW5TY2hlbWEoJ3B1YmxpYycpLT50bygnYWRtaW4nKQogKiBQcm9kdWNlczogR1JBTlQgQUxMIE9OIEFMTCBUQUJMRVMgSU4gU0NIRU1BIHB1YmxpYyBUTyBhZG1pbgogKgogKiBAcGFyYW0gc3RyaW5nfFRhYmxlUHJpdmlsZWdlIC4uLiRwcml2aWxlZ2VzIFRoZSBwcml2aWxlZ2VzIHRvIGdyYW50CiAqCiAqIEByZXR1cm4gR3JhbnRPblN0ZXAgQnVpbGRlciBmb3IgZ3JhbnQgb3B0aW9ucwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":628,"slug":"grant-role","name":"grant_role","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"roles","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":"GrantRoleToStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Grant","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEdSQU5UIHJvbGUgYnVpbGRlci4KICoKICogRXhhbXBsZTogZ3JhbnRfcm9sZSgnYWRtaW4nKS0+dG8oJ3VzZXIxJykKICogUHJvZHVjZXM6IEdSQU5UIGFkbWluIFRPIHVzZXIxCiAqCiAqIEV4YW1wbGU6IGdyYW50X3JvbGUoJ2FkbWluJywgJ2RldmVsb3BlcicpLT50bygndXNlcjEnKS0+d2l0aEFkbWluT3B0aW9uKCkKICogUHJvZHVjZXM6IEdSQU5UIGFkbWluLCBkZXZlbG9wZXIgVE8gdXNlcjEgV0lUSCBBRE1JTiBPUFRJT04KICoKICogQHBhcmFtIHN0cmluZyAuLi4kcm9sZXMgVGhlIHJvbGVzIHRvIGdyYW50CiAqCiAqIEByZXR1cm4gR3JhbnRSb2xlVG9TdGVwIEJ1aWxkZXIgZm9yIGdyYW50IHJvbGUgb3B0aW9ucwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":647,"slug":"revoke","name":"revoke","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"privileges","type":[{"name":"TablePrivilege","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Grant","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":"RevokeOnStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Grant","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFJFVk9LRSBwcml2aWxlZ2VzIGJ1aWxkZXIuCiAqCiAqIEV4YW1wbGU6IHJldm9rZShUYWJsZVByaXZpbGVnZTo6U0VMRUNUKS0+b25UYWJsZSgndXNlcnMnKS0+ZnJvbSgnYXBwX3VzZXInKQogKiBQcm9kdWNlczogUkVWT0tFIFNFTEVDVCBPTiB1c2VycyBGUk9NIGFwcF91c2VyCiAqCiAqIEV4YW1wbGU6IHJldm9rZShUYWJsZVByaXZpbGVnZTo6QUxMKS0+b25UYWJsZSgndXNlcnMnKS0+ZnJvbSgnYXBwX3VzZXInKS0+Y2FzY2FkZSgpCiAqIFByb2R1Y2VzOiBSRVZPS0UgQUxMIE9OIHVzZXJzIEZST00gYXBwX3VzZXIgQ0FTQ0FERQogKgogKiBAcGFyYW0gc3RyaW5nfFRhYmxlUHJpdmlsZWdlIC4uLiRwcml2aWxlZ2VzIFRoZSBwcml2aWxlZ2VzIHRvIHJldm9rZQogKgogKiBAcmV0dXJuIFJldm9rZU9uU3RlcCBCdWlsZGVyIGZvciByZXZva2Ugb3B0aW9ucwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":666,"slug":"revoke-role","name":"revoke_role","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"roles","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":"RevokeRoleFromStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Grant","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFJFVk9LRSByb2xlIGJ1aWxkZXIuCiAqCiAqIEV4YW1wbGU6IHJldm9rZV9yb2xlKCdhZG1pbicpLT5mcm9tKCd1c2VyMScpCiAqIFByb2R1Y2VzOiBSRVZPS0UgYWRtaW4gRlJPTSB1c2VyMQogKgogKiBFeGFtcGxlOiByZXZva2Vfcm9sZSgnYWRtaW4nKS0+ZnJvbSgndXNlcjEnKS0+Y2FzY2FkZSgpCiAqIFByb2R1Y2VzOiBSRVZPS0UgYWRtaW4gRlJPTSB1c2VyMSBDQVNDQURFCiAqCiAqIEBwYXJhbSBzdHJpbmcgLi4uJHJvbGVzIFRoZSByb2xlcyB0byByZXZva2UKICoKICogQHJldHVybiBSZXZva2VSb2xlRnJvbVN0ZXAgQnVpbGRlciBmb3IgcmV2b2tlIHJvbGUgb3B0aW9ucwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":682,"slug":"set-role","name":"set_role","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"role","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":"SetRoleFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Session","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFNFVCBST0xFIGJ1aWxkZXIuCiAqCiAqIEV4YW1wbGU6IHNldF9yb2xlKCdhZG1pbicpCiAqIFByb2R1Y2VzOiBTRVQgUk9MRSBhZG1pbgogKgogKiBAcGFyYW0gc3RyaW5nICRyb2xlIFRoZSByb2xlIHRvIHNldAogKgogKiBAcmV0dXJuIFNldFJvbGVGaW5hbFN0ZXAgQnVpbGRlciBmb3Igc2V0IHJvbGUKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":696,"slug":"reset-role","name":"reset_role","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ResetRoleFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Session","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFJFU0VUIFJPTEUgYnVpbGRlci4KICoKICogRXhhbXBsZTogcmVzZXRfcm9sZSgpCiAqIFByb2R1Y2VzOiBSRVNFVCBST0xFCiAqCiAqIEByZXR1cm4gUmVzZXRSb2xlRmluYWxTdGVwIEJ1aWxkZXIgZm9yIHJlc2V0IHJvbGUKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":712,"slug":"reassign-owned","name":"reassign_owned","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"roles","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":"ReassignOwnedToStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Ownership","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFJFQVNTSUdOIE9XTkVEIGJ1aWxkZXIuCiAqCiAqIEV4YW1wbGU6IHJlYXNzaWduX293bmVkKCdvbGRfcm9sZScpLT50bygnbmV3X3JvbGUnKQogKiBQcm9kdWNlczogUkVBU1NJR04gT1dORUQgQlkgb2xkX3JvbGUgVE8gbmV3X3JvbGUKICoKICogQHBhcmFtIHN0cmluZyAuLi4kcm9sZXMgVGhlIHJvbGVzIHdob3NlIG93bmVkIG9iamVjdHMgc2hvdWxkIGJlIHJlYXNzaWduZWQKICoKICogQHJldHVybiBSZWFzc2lnbk93bmVkVG9TdGVwIEJ1aWxkZXIgZm9yIHJlYXNzaWduIG93bmVkIG9wdGlvbnMKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":731,"slug":"drop-owned","name":"drop_owned","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"roles","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":"DropOwnedFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Ownership","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIERST1AgT1dORUQgYnVpbGRlci4KICoKICogRXhhbXBsZTogZHJvcF9vd25lZCgncm9sZTEnKQogKiBQcm9kdWNlczogRFJPUCBPV05FRCBCWSByb2xlMQogKgogKiBFeGFtcGxlOiBkcm9wX293bmVkKCdyb2xlMScsICdyb2xlMicpLT5jYXNjYWRlKCkKICogUHJvZHVjZXM6IERST1AgT1dORUQgQlkgcm9sZTEsIHJvbGUyIENBU0NBREUKICoKICogQHBhcmFtIHN0cmluZyAuLi4kcm9sZXMgVGhlIHJvbGVzIHdob3NlIG93bmVkIG9iamVjdHMgc2hvdWxkIGJlIGRyb3BwZWQKICoKICogQHJldHVybiBEcm9wT3duZWRGaW5hbFN0ZXAgQnVpbGRlciBmb3IgZHJvcCBvd25lZCBvcHRpb25zCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":749,"slug":"func-arg","name":"func_arg","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"type","type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"FunctionArgument","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZXMgYSBuZXcgZnVuY3Rpb24gYXJndW1lbnQgZm9yIHVzZSBpbiBmdW5jdGlvbi9wcm9jZWR1cmUgZGVmaW5pdGlvbnMuCiAqCiAqIEV4YW1wbGU6IGZ1bmNfYXJnKGNvbHVtbl90eXBlX2ludGVnZXIoKSkKICogRXhhbXBsZTogZnVuY19hcmcoY29sdW1uX3R5cGVfdGV4dCgpKS0+bmFtZWQoJ3VzZXJuYW1lJykKICogRXhhbXBsZTogZnVuY19hcmcoY29sdW1uX3R5cGVfaW50ZWdlcigpKS0+bmFtZWQoJ2NvdW50JyktPmRlZmF1bHQoJzAnKQogKiBFeGFtcGxlOiBmdW5jX2FyZyhjb2x1bW5fdHlwZV90ZXh0KCkpLT5vdXQoKQogKgogKiBAcGFyYW0gQ29sdW1uVHlwZSAkdHlwZSBUaGUgUG9zdGdyZVNRTCBkYXRhIHR5cGUgZm9yIHRoZSBhcmd1bWVudAogKgogKiBAcmV0dXJuIEZ1bmN0aW9uQXJndW1lbnQgQnVpbGRlciBmb3IgZnVuY3Rpb24gYXJndW1lbnQgb3B0aW9ucwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":768,"slug":"call","name":"call","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"procedure","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":"CallFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZXMgYSBDQUxMIHN0YXRlbWVudCBidWlsZGVyIGZvciBpbnZva2luZyBhIHByb2NlZHVyZS4KICoKICogRXhhbXBsZTogY2FsbCgndXBkYXRlX3N0YXRzJyktPndpdGgoMTIzKQogKiBQcm9kdWNlczogQ0FMTCB1cGRhdGVfc3RhdHMoMTIzKQogKgogKiBFeGFtcGxlOiBjYWxsKCdwcm9jZXNzX2RhdGEnKS0+d2l0aCgndGVzdCcsIDQyLCB0cnVlKQogKiBQcm9kdWNlczogQ0FMTCBwcm9jZXNzX2RhdGEoJ3Rlc3QnLCA0MiwgdHJ1ZSkKICoKICogQHBhcmFtIHN0cmluZyAkcHJvY2VkdXJlIFRoZSBuYW1lIG9mIHRoZSBwcm9jZWR1cmUgdG8gY2FsbAogKgogKiBAcmV0dXJuIENhbGxGaW5hbFN0ZXAgQnVpbGRlciBmb3IgY2FsbCBzdGF0ZW1lbnQgb3B0aW9ucwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":787,"slug":"do-block","name":"do_block","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"code","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":"DoFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZXMgYSBETyBzdGF0ZW1lbnQgYnVpbGRlciBmb3IgZXhlY3V0aW5nIGFuIGFub255bW91cyBjb2RlIGJsb2NrLgogKgogKiBFeGFtcGxlOiBkb19ibG9jaygnQkVHSU4gUkFJU0UgTk9USUNFICQkSGVsbG8gV29ybGQkJDsgRU5EOycpCiAqIFByb2R1Y2VzOiBETyAkJCBCRUdJTiBSQUlTRSBOT1RJQ0UgJCRIZWxsbyBXb3JsZCQkOyBFTkQ7ICQkIExBTkdVQUdFIHBscGdzcWwKICoKICogRXhhbXBsZTogZG9fYmxvY2soJ1NFTEVDVCAxJyktPmxhbmd1YWdlKCdzcWwnKQogKiBQcm9kdWNlczogRE8gJCQgU0VMRUNUIDEgJCQgTEFOR1VBR0Ugc3FsCiAqCiAqIEBwYXJhbSBzdHJpbmcgJGNvZGUgVGhlIGFub255bW91cyBjb2RlIGJsb2NrIHRvIGV4ZWN1dGUKICoKICogQHJldHVybiBEb0ZpbmFsU3RlcCBCdWlsZGVyIGZvciBETyBzdGF0ZW1lbnQgb3B0aW9ucwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":807,"slug":"type-attr","name":"type_attr","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"type","type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"TypeAttribute","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Type","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZXMgYSB0eXBlIGF0dHJpYnV0ZSBmb3IgY29tcG9zaXRlIHR5cGVzLgogKgogKiBFeGFtcGxlOiB0eXBlX2F0dHIoJ25hbWUnLCBjb2x1bW5fdHlwZV90ZXh0KCkpCiAqIFByb2R1Y2VzOiBuYW1lIHRleHQKICoKICogRXhhbXBsZTogdHlwZV9hdHRyKCdkZXNjcmlwdGlvbicsIGNvbHVtbl90eXBlX3RleHQoKSktPmNvbGxhdGUoJ2VuX1VTJykKICogUHJvZHVjZXM6IGRlc2NyaXB0aW9uIHRleHQgQ09MTEFURSAiZW5fVVMiCiAqCiAqIEBwYXJhbSBzdHJpbmcgJG5hbWUgVGhlIGF0dHJpYnV0ZSBuYW1lCiAqIEBwYXJhbSBDb2x1bW5UeXBlICR0eXBlIFRoZSBhdHRyaWJ1dGUgdHlwZQogKgogKiBAcmV0dXJuIFR5cGVBdHRyaWJ1dGUgVHlwZSBhdHRyaWJ1dGUgdmFsdWUgb2JqZWN0CiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":816,"slug":"column-type-integer","name":"column_type_integer","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBpbnRlZ2VyIGRhdGEgdHlwZSAoUG9zdGdyZVNRTCBpbnQ0KS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":825,"slug":"column-type-smallint","name":"column_type_smallint","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHNtYWxsaW50IGRhdGEgdHlwZSAoUG9zdGdyZVNRTCBpbnQyKS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":834,"slug":"column-type-bigint","name":"column_type_bigint","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGJpZ2ludCBkYXRhIHR5cGUgKFBvc3RncmVTUUwgaW50OCkuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":843,"slug":"column-type-boolean","name":"column_type_boolean","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGJvb2xlYW4gZGF0YSB0eXBlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":852,"slug":"column-type-text","name":"column_type_text","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHRleHQgZGF0YSB0eXBlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":861,"slug":"column-type-varchar","name":"column_type_varchar","namespace":"Flow\\PostgreSql\\DSL","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}],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHZhcmNoYXIgZGF0YSB0eXBlIHdpdGggbGVuZ3RoIGNvbnN0cmFpbnQuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":870,"slug":"column-type-char","name":"column_type_char","namespace":"Flow\\PostgreSql\\DSL","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}],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGNoYXIgZGF0YSB0eXBlIHdpdGggbGVuZ3RoIGNvbnN0cmFpbnQuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":879,"slug":"column-type-numeric","name":"column_type_numeric","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"precision","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":"scale","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":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIG51bWVyaWMgZGF0YSB0eXBlIHdpdGggb3B0aW9uYWwgcHJlY2lzaW9uIGFuZCBzY2FsZS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":888,"slug":"column-type-decimal","name":"column_type_decimal","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"precision","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":"scale","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":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGRlY2ltYWwgZGF0YSB0eXBlIHdpdGggb3B0aW9uYWwgcHJlY2lzaW9uIGFuZCBzY2FsZS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":897,"slug":"column-type-real","name":"column_type_real","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHJlYWwgZGF0YSB0eXBlIChQb3N0Z3JlU1FMIGZsb2F0NCkuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":906,"slug":"column-type-double-precision","name":"column_type_double_precision","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGRvdWJsZSBwcmVjaXNpb24gZGF0YSB0eXBlIChQb3N0Z3JlU1FMIGZsb2F0OCkuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":915,"slug":"column-type-date","name":"column_type_date","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGRhdGUgZGF0YSB0eXBlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":924,"slug":"column-type-time","name":"column_type_time","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"precision","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":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHRpbWUgZGF0YSB0eXBlIHdpdGggb3B0aW9uYWwgcHJlY2lzaW9uLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":933,"slug":"column-type-timestamp","name":"column_type_timestamp","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"precision","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":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHRpbWVzdGFtcCBkYXRhIHR5cGUgd2l0aCBvcHRpb25hbCBwcmVjaXNpb24uCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":942,"slug":"column-type-timestamptz","name":"column_type_timestamptz","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"precision","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":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHRpbWVzdGFtcCB3aXRoIHRpbWUgem9uZSBkYXRhIHR5cGUgd2l0aCBvcHRpb25hbCBwcmVjaXNpb24uCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":951,"slug":"column-type-interval","name":"column_type_interval","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBpbnRlcnZhbCBkYXRhIHR5cGUuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":960,"slug":"column-type-uuid","name":"column_type_uuid","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFVVSUQgZGF0YSB0eXBlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":969,"slug":"column-type-json","name":"column_type_json","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEpTT04gZGF0YSB0eXBlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":978,"slug":"column-type-jsonb","name":"column_type_jsonb","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEpTT05CIGRhdGEgdHlwZS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":987,"slug":"column-type-bytea","name":"column_type_bytea","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGJ5dGVhIGRhdGEgdHlwZS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":996,"slug":"column-type-xml","name":"column_type_xml","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBYTUwgZGF0YSB0eXBlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1005,"slug":"column-type-inet","name":"column_type_inet","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBpbmV0IGRhdGEgdHlwZS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1014,"slug":"column-type-cidr","name":"column_type_cidr","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGNpZHIgZGF0YSB0eXBlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1023,"slug":"column-type-macaddr","name":"column_type_macaddr","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIG1hY2FkZHIgZGF0YSB0eXBlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1032,"slug":"column-type-serial","name":"column_type_serial","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHNlcmlhbCBkYXRhIHR5cGUuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1041,"slug":"column-type-smallserial","name":"column_type_smallserial","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHNtYWxsc2VyaWFsIGRhdGEgdHlwZS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1050,"slug":"column-type-bigserial","name":"column_type_bigserial","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGJpZ3NlcmlhbCBkYXRhIHR5cGUuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1059,"slug":"column-type-array","name":"column_type_array","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"elementType","type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBhcnJheSBkYXRhIHR5cGUgZnJvbSBhbiBlbGVtZW50IHR5cGUuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1071,"slug":"column-type-custom","name":"column_type_custom","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"typeName","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":"schema","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGN1c3RvbSBkYXRhIHR5cGUuCiAqCiAqIEBwYXJhbSBzdHJpbmcgJHR5cGVOYW1lIFR5cGUgbmFtZQogKiBAcGFyYW0gbnVsbHxzdHJpbmcgJHNjaGVtYSBPcHRpb25hbCBzY2hlbWEgbmFtZQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1084,"slug":"column-type-from-string","name":"column_type_from_string","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"typeName","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":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFBhcnNlIGEgUG9zdGdyZVNRTCB0eXBlIHN0cmluZyBpbnRvIGEgQ29sdW1uVHlwZS4KICoKICogSGFuZGxlcyBhbGwgUG9zdGdyZVNRTCB0eXBlIHN5bnRheCBpbmNsdWRpbmcgcHJlY2lzaW9uLCBhcnJheXMsIGFuZCBzY2hlbWEtcXVhbGlmaWVkIHR5cGVzLgogKgogKiBAcGFyYW0gc3RyaW5nICR0eXBlTmFtZSBQb3N0Z3JlU1FMIHR5cGUgc3RyaW5nIChlLmcuLCAnaW50ZWdlcicsICdjaGFyYWN0ZXIgdmFyeWluZygyNTUpJywgJ3RleHRbXScpCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1092,"slug":"value-type-text","name":"value_type_text","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1098,"slug":"value-type-varchar","name":"value_type_varchar","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1104,"slug":"value-type-char","name":"value_type_char","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1110,"slug":"value-type-bpchar","name":"value_type_bpchar","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1116,"slug":"value-type-int2","name":"value_type_int2","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1122,"slug":"value-type-smallint","name":"value_type_smallint","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1128,"slug":"value-type-int4","name":"value_type_int4","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1134,"slug":"value-type-integer","name":"value_type_integer","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1140,"slug":"value-type-int8","name":"value_type_int8","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1146,"slug":"value-type-bigint","name":"value_type_bigint","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1152,"slug":"value-type-float4","name":"value_type_float4","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1158,"slug":"value-type-real","name":"value_type_real","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1164,"slug":"value-type-float8","name":"value_type_float8","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1170,"slug":"value-type-double","name":"value_type_double","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1176,"slug":"value-type-numeric","name":"value_type_numeric","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1182,"slug":"value-type-money","name":"value_type_money","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1188,"slug":"value-type-bool","name":"value_type_bool","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1194,"slug":"value-type-boolean","name":"value_type_boolean","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1200,"slug":"value-type-bytea","name":"value_type_bytea","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1206,"slug":"value-type-bit","name":"value_type_bit","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1212,"slug":"value-type-varbit","name":"value_type_varbit","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1218,"slug":"value-type-date","name":"value_type_date","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1224,"slug":"value-type-time","name":"value_type_time","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1230,"slug":"value-type-timetz","name":"value_type_timetz","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1236,"slug":"value-type-timestamp","name":"value_type_timestamp","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1242,"slug":"value-type-timestamptz","name":"value_type_timestamptz","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1248,"slug":"value-type-interval","name":"value_type_interval","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1254,"slug":"value-type-json","name":"value_type_json","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1260,"slug":"value-type-jsonb","name":"value_type_jsonb","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1266,"slug":"value-type-uuid","name":"value_type_uuid","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1272,"slug":"value-type-inet","name":"value_type_inet","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1278,"slug":"value-type-cidr","name":"value_type_cidr","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1284,"slug":"value-type-macaddr","name":"value_type_macaddr","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1290,"slug":"value-type-macaddr8","name":"value_type_macaddr8","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1296,"slug":"value-type-xml","name":"value_type_xml","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1302,"slug":"value-type-oid","name":"value_type_oid","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1308,"slug":"value-type-text-array","name":"value_type_text_array","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1314,"slug":"value-type-varchar-array","name":"value_type_varchar_array","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1320,"slug":"value-type-int2-array","name":"value_type_int2_array","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1326,"slug":"value-type-int4-array","name":"value_type_int4_array","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1332,"slug":"value-type-int8-array","name":"value_type_int8_array","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1338,"slug":"value-type-float4-array","name":"value_type_float4_array","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1344,"slug":"value-type-float8-array","name":"value_type_float8_array","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1350,"slug":"value-type-bool-array","name":"value_type_bool_array","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1356,"slug":"value-type-uuid-array","name":"value_type_uuid_array","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1362,"slug":"value-type-json-array","name":"value_type_json_array","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1368,"slug":"value-type-jsonb-array","name":"value_type_jsonb_array","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1384,"slug":"schema","name":"schema","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"tables","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"sequences","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"views","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"materializedViews","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"functions","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"procedures","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"domains","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"extensions","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"Schema","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBsaXN0PFNjaGVtYVRhYmxlPiAkdGFibGVzCiAqIEBwYXJhbSBsaXN0PFNjaGVtYVNlcXVlbmNlPiAkc2VxdWVuY2VzCiAqIEBwYXJhbSBsaXN0PFNjaGVtYVZpZXc+ICR2aWV3cwogKiBAcGFyYW0gbGlzdDxTY2hlbWFNYXRlcmlhbGl6ZWRWaWV3PiAkbWF0ZXJpYWxpemVkVmlld3MKICogQHBhcmFtIGxpc3Q8U2NoZW1hRnVuY3Rpb24+ICRmdW5jdGlvbnMKICogQHBhcmFtIGxpc3Q8U2NoZW1hUHJvY2VkdXJlPiAkcHJvY2VkdXJlcwogKiBAcGFyYW0gbGlzdDxTY2hlbWFEb21haW4+ICRkb21haW5zCiAqIEBwYXJhbSBsaXN0PFNjaGVtYUV4dGVuc2lvbj4gJGV4dGVuc2lvbnMKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1420,"slug":"schema-table","name":"schema_table","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"columns","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":"primaryKey","type":[{"name":"PrimaryKey","namespace":"Flow\\PostgreSql\\Schema\\Constraint","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"indexes","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"foreignKeys","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"uniqueConstraints","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"checkConstraints","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"excludeConstraints","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"triggers","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"schema","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'public'"},{"name":"unlogged","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"partitionStrategy","type":[{"name":"PartitionStrategy","namespace":"Flow\\PostgreSql\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"partitionColumns","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"inherits","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"tablespace","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Table","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBub24tZW1wdHktbGlzdDxTY2hlbWFDb2x1bW4+ICRjb2x1bW5zCiAqIEBwYXJhbSBsaXN0PFNjaGVtYUluZGV4PiAkaW5kZXhlcwogKiBAcGFyYW0gbGlzdDxTY2hlbWFGb3JlaWduS2V5PiAkZm9yZWlnbktleXMKICogQHBhcmFtIGxpc3Q8U2NoZW1hVW5pcXVlQ29uc3RyYWludD4gJHVuaXF1ZUNvbnN0cmFpbnRzCiAqIEBwYXJhbSBsaXN0PFNjaGVtYUNoZWNrQ29uc3RyYWludD4gJGNoZWNrQ29uc3RyYWludHMKICogQHBhcmFtIGxpc3Q8U2NoZW1hRXhjbHVkZUNvbnN0cmFpbnQ+ICRleGNsdWRlQ29uc3RyYWludHMKICogQHBhcmFtIGxpc3Q8U2NoZW1hVHJpZ2dlcj4gJHRyaWdnZXJzCiAqIEBwYXJhbSBsaXN0PHN0cmluZz4gJHBhcnRpdGlvbkNvbHVtbnMKICogQHBhcmFtIGxpc3Q8c3RyaW5nPiAkaW5oZXJpdHMKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1465,"slug":"schema-table-options","name":"schema_table_options","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"foreignKeys","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"checkConstraints","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"excludeConstraints","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"triggers","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"unlogged","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"partitionStrategy","type":[{"name":"PartitionStrategy","namespace":"Flow\\PostgreSql\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"partitionColumns","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"inherits","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"tablespace","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"TableOptions","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBsaXN0PFNjaGVtYUZvcmVpZ25LZXk+ICRmb3JlaWduS2V5cwogKiBAcGFyYW0gbGlzdDxTY2hlbWFDaGVja0NvbnN0cmFpbnQ+ICRjaGVja0NvbnN0cmFpbnRzCiAqIEBwYXJhbSBsaXN0PFNjaGVtYUV4Y2x1ZGVDb25zdHJhaW50PiAkZXhjbHVkZUNvbnN0cmFpbnRzCiAqIEBwYXJhbSBsaXN0PFNjaGVtYVRyaWdnZXI+ICR0cmlnZ2VycwogKiBAcGFyYW0gbGlzdDxzdHJpbmc+ICRwYXJ0aXRpb25Db2x1bW5zCiAqIEBwYXJhbSBsaXN0PHN0cmluZz4gJGluaGVyaXRzCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1490,"slug":"schema-column","name":"schema_column","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"type","type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"isIdentity","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"identityGeneration","type":[{"name":"IdentityGeneration","namespace":"Flow\\PostgreSql\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"isGenerated","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"generationExpression","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":"ordinalPosition","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1515,"slug":"schema-column-integer","name":"schema_column_integer","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1524,"slug":"schema-column-smallint","name":"schema_column_smallint","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1533,"slug":"schema-column-bigint","name":"schema_column_bigint","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1542,"slug":"schema-column-serial","name":"schema_column_serial","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1548,"slug":"schema-column-small-serial","name":"schema_column_small_serial","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1554,"slug":"schema-column-big-serial","name":"schema_column_big_serial","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1560,"slug":"schema-column-boolean","name":"schema_column_boolean","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1569,"slug":"schema-column-text","name":"schema_column_text","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1578,"slug":"schema-column-varchar","name":"schema_column_varchar","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1588,"slug":"schema-column-char","name":"schema_column_char","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1598,"slug":"schema-column-numeric","name":"schema_column_numeric","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"precision","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":"scale","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1609,"slug":"schema-column-real","name":"schema_column_real","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1618,"slug":"schema-column-double-precision","name":"schema_column_double_precision","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1627,"slug":"schema-column-date","name":"schema_column_date","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1636,"slug":"schema-column-time","name":"schema_column_time","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"precision","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1646,"slug":"schema-column-timestamp","name":"schema_column_timestamp","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"precision","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1656,"slug":"schema-column-timestamp-tz","name":"schema_column_timestamp_tz","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"precision","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1666,"slug":"schema-column-interval","name":"schema_column_interval","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1675,"slug":"schema-column-uuid","name":"schema_column_uuid","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1684,"slug":"schema-column-json","name":"schema_column_json","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1693,"slug":"schema-column-jsonb","name":"schema_column_jsonb","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1702,"slug":"schema-column-bytea","name":"schema_column_bytea","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1711,"slug":"schema-column-inet","name":"schema_column_inet","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1720,"slug":"schema-column-cidr","name":"schema_column_cidr","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1729,"slug":"schema-column-macaddr","name":"schema_column_macaddr","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1741,"slug":"schema-primary-key","name":"schema_primary_key","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"columns","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":"name","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"PrimaryKey","namespace":"Flow\\PostgreSql\\Schema\\Constraint","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBub24tZW1wdHktbGlzdDxzdHJpbmc+ICRjb2x1bW5zCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1751,"slug":"schema-foreign-key","name":"schema_foreign_key","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"columns","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":"referenceTable","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":"referenceColumns","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":"name","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":"referenceSchema","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'public'"},{"name":"onUpdate","type":[{"name":"ReferentialAction","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\PostgreSql\\QueryBuilder\\Schema\\ReferentialAction::..."},{"name":"onDelete","type":[{"name":"ReferentialAction","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\PostgreSql\\QueryBuilder\\Schema\\ReferentialAction::..."},{"name":"deferrable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"initiallyDeferred","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":"ForeignKey","namespace":"Flow\\PostgreSql\\Schema\\Constraint","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBub24tZW1wdHktbGlzdDxzdHJpbmc+ICRjb2x1bW5zCiAqIEBwYXJhbSBub24tZW1wdHktbGlzdDxzdHJpbmc+ICRyZWZlcmVuY2VDb2x1bW5zCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1779,"slug":"schema-unique","name":"schema_unique","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"columns","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":"name","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":"nullsNotDistinct","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":"UniqueConstraint","namespace":"Flow\\PostgreSql\\Schema\\Constraint","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBub24tZW1wdHktbGlzdDxzdHJpbmc+ICRjb2x1bW5zCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1785,"slug":"schema-check","name":"schema_check","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expression","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":"name","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":"noInherit","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":"CheckConstraint","namespace":"Flow\\PostgreSql\\Schema\\Constraint","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1791,"slug":"schema-exclude","name":"schema_exclude","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"definition","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":"name","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"ExcludeConstraint","namespace":"Flow\\PostgreSql\\Schema\\Constraint","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1800,"slug":"schema-index","name":"schema_index","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"columns","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":"unique","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"method","type":[{"name":"IndexMethod","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\PostgreSql\\Schema\\IndexMethod::..."},{"name":"primary","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"predicate","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Index","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBub24tZW1wdHktbGlzdDxzdHJpbmc+ICRjb2x1bW5zCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1812,"slug":"schema-sequence","name":"schema_sequence","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"dataType","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'bigint'"},{"name":"startValue","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":"1"},{"name":"minValue","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":"1"},{"name":"maxValue","type":[{"name":"string","namespace":null,"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":"incrementBy","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":"1"},{"name":"cycle","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"cacheValue","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":"1"},{"name":"ownedByTable","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":"ownedByColumn","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Sequence","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1839,"slug":"schema-view","name":"schema_view","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"definition","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":"isUpdatable","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":"View","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1848,"slug":"schema-materialized-view","name":"schema_materialized_view","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"definition","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":"indexes","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"MaterializedView","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBsaXN0PFNjaGVtYUluZGV4PiAkaW5kZXhlcwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1857,"slug":"schema-function","name":"schema_function","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"returnType","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":"argumentTypes","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"language","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'sql'"},{"name":"definition","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":"isStrict","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"volatility","type":[{"name":"FunctionVolatility","namespace":"Flow\\PostgreSql\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Func","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBsaXN0PHN0cmluZz4gJGFyZ3VtZW50VHlwZXMKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1873,"slug":"schema-procedure","name":"schema_procedure","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"argumentTypes","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"language","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'sql'"},{"name":"definition","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Procedure","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBsaXN0PHN0cmluZz4gJGFyZ3VtZW50VHlwZXMKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1886,"slug":"schema-trigger","name":"schema_trigger","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"tableName","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":"timing","type":[{"name":"TriggerTiming","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"events","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":"functionName","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":"forEachRow","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"whenCondition","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Trigger","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBub24tZW1wdHktbGlzdDxUcmlnZ2VyRXZlbnQ+ICRldmVudHMKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1902,"slug":"schema-domain","name":"schema_domain","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"baseType","type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"checkConstraints","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"Domain","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBsaXN0PFNjaGVtYUNoZWNrQ29uc3RyYWludD4gJGNoZWNrQ29uc3RyYWludHMKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1913,"slug":"schema-extension","name":"schema_extension","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"version","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Extension","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1922,"slug":"client-catalog-provider","name":"client_catalog_provider","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"client","type":[{"name":"Client","namespace":"Flow\\PostgreSql\\Client","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"schemaNames","type":[{"name":"array","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"exclusionPolicy","type":[{"name":"ExclusionPolicy","namespace":"Flow\\PostgreSql\\Schema\\Exclusion","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"CatalogProvider","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSA\/bGlzdDxzdHJpbmc+ICRzY2hlbWFOYW1lcwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1931,"slug":"exclude-any","name":"exclude_any","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"policies","type":[{"name":"ExclusionPolicy","namespace":"Flow\\PostgreSql\\Schema\\Exclusion","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"ExclusionPolicy","namespace":"Flow\\PostgreSql\\Schema\\Exclusion","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1937,"slug":"exclude-exact","name":"exclude_exact","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"ExclusionPolicy","namespace":"Flow\\PostgreSql\\Schema\\Exclusion","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1943,"slug":"exclude-starts-with","name":"exclude_starts_with","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"prefix","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":"ExclusionPolicy","namespace":"Flow\\PostgreSql\\Schema\\Exclusion","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1949,"slug":"exclude-ends-with","name":"exclude_ends_with","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"suffix","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":"ExclusionPolicy","namespace":"Flow\\PostgreSql\\Schema\\Exclusion","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1955,"slug":"exclude-pattern","name":"exclude_pattern","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"pattern","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":"ExclusionPolicy","namespace":"Flow\\PostgreSql\\Schema\\Exclusion","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1961,"slug":"exclude-schema","name":"exclude_schema","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"schema","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":"ExclusionPolicy","namespace":"Flow\\PostgreSql\\Schema\\Exclusion","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1967,"slug":"exclude-scoped","name":"exclude_scoped","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"policy","type":[{"name":"ExclusionPolicy","namespace":"Flow\\PostgreSql\\Schema\\Exclusion","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"type","type":[{"name":"SchemaObjectType","namespace":"Flow\\PostgreSql\\Schema\\Exclusion","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"schema","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"ExclusionPolicy","namespace":"Flow\\PostgreSql\\Schema\\Exclusion","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1976,"slug":"manual-catalog-provider","name":"manual_catalog_provider","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"catalog","type":[{"name":"Catalog","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"CatalogProvider","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1982,"slug":"chain-catalog-provider","name":"chain_catalog_provider","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"providers","type":[{"name":"CatalogProvider","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"ChainCatalogProvider","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1991,"slug":"catalog-comparator","name":"catalog_comparator","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"renameStrategy","type":[{"name":"RenameStrategy","namespace":"Flow\\PostgreSql\\Schema\\Diff","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"viewDependencyResolver","type":[{"name":"ViewDependencyResolver","namespace":"Flow\\PostgreSql\\Schema\\Diff","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"tableOrderStrategy","type":[{"name":"ExecutionOrderStrategy","namespace":"Flow\\PostgreSql\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"dropIfExists","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":"CatalogComparator","namespace":"Flow\\PostgreSql\\Schema\\Diff","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBudWxsfEV4ZWN1dGlvbk9yZGVyU3RyYXRlZ3k8XEZsb3dcUG9zdGdyZVNxbFxTY2hlbWFcVGFibGU+ICR0YWJsZU9yZGVyU3RyYXRlZ3kKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":2006,"slug":"ast-view-dependency-resolver","name":"ast_view_dependency_resolver","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"AstViewDependencyResolver","namespace":"Flow\\PostgreSql\\Schema\\Diff","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":2012,"slug":"noop-view-dependency-resolver","name":"noop_view_dependency_resolver","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"NoopViewDependencyResolver","namespace":"Flow\\PostgreSql\\Schema\\Diff","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":2018,"slug":"foreign-key-dependency-order","name":"foreign_key_dependency_order","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ForeignKeyDependencyOrder","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":2027,"slug":"no-execution-order","name":"no_execution_order","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"NoExecutionOrder","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gTm9FeGVjdXRpb25PcmRlcjxtaXhlZD4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":2033,"slug":"view-dependency-order","name":"view_dependency_order","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ViewDependencyOrder","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":2039,"slug":"materialized-view-dependency-order","name":"materialized_view_dependency_order","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"MaterializedViewDependencyOrder","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":116,"slug":"select","name":"select","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expressions","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"SelectBuilder","namespace":"Flow\\PostgreSql\\QueryBuilder\\Select","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIG5ldyBTRUxFQ1QgcXVlcnkgYnVpbGRlci4KICoKICogQHBhcmFtIEV4cHJlc3Npb258c3RyaW5nIC4uLiRleHByZXNzaW9ucyBDb2x1bW5zIHRvIHNlbGVjdC4gSWYgZW1wdHksIHJldHVybnMgU2VsZWN0U2VsZWN0U3RlcC4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":133,"slug":"parsed-select","name":"parsed_select","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"sql","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":"ParsedSelect","namespace":"Flow\\PostgreSql\\QueryBuilder\\Select","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFNlbGVjdEZpbmFsU3RlcCBmcm9tIGEgcmF3IFNRTCBTRUxFQ1Qgc3RyaW5nLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":145,"slug":"with","name":"with","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"ctes","type":[{"name":"CTE","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"WithBuilder","namespace":"Flow\\PostgreSql\\QueryBuilder\\With","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFdJVEggY2xhdXNlIGJ1aWxkZXIgZm9yIENURXMuCiAqCiAqIEV4YW1wbGU6IHdpdGgoY3RlKCd1c2VycycsICRzdWJxdWVyeSkpLT5zZWxlY3Qoc3RhcigpKS0+ZnJvbSh0YWJsZSgndXNlcnMnKSkKICogRXhhbXBsZTogd2l0aChjdGUoJ2EnLCAkcTEpLCBjdGUoJ2InLCAkcTIpKS0+cmVjdXJzaXZlKCktPnNlbGVjdCguLi4pLT5mcm9tKHRhYmxlKCdhJykpCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":158,"slug":"insert","name":"insert","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"InsertIntoStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Insert","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIG5ldyBJTlNFUlQgcXVlcnkgYnVpbGRlci4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":174,"slug":"bulk-insert","name":"bulk_insert","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"table","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":"columns","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":"rowCount","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":"BulkInsert","namespace":"Flow\\PostgreSql\\QueryBuilder\\Insert","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBvcHRpbWl6ZWQgYnVsayBJTlNFUlQgcXVlcnkgZm9yIGhpZ2gtcGVyZm9ybWFuY2UgbXVsdGktcm93IGluc2VydHMuCiAqCiAqIFVubGlrZSBpbnNlcnQoKSB3aGljaCB1c2VzIGltbXV0YWJsZSBidWlsZGVyIHBhdHRlcm5zIChPKG7CsikgZm9yIG4gcm93cyksCiAqIHRoaXMgZnVuY3Rpb24gZ2VuZXJhdGVzIFNRTCBkaXJlY3RseSB1c2luZyBzdHJpbmcgb3BlcmF0aW9ucyAoTyhuKSBjb21wbGV4aXR5KS4KICoKICogQHBhcmFtIHN0cmluZyAkdGFibGUgVGFibGUgbmFtZQogKiBAcGFyYW0gbGlzdDxzdHJpbmc+ICRjb2x1bW5zIENvbHVtbiBuYW1lcwogKiBAcGFyYW0gaW50ICRyb3dDb3VudCBOdW1iZXIgb2Ygcm93cyB0byBpbnNlcnQKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":183,"slug":"update","name":"update","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"UpdateTableStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Update","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIG5ldyBVUERBVEUgcXVlcnkgYnVpbGRlci4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":192,"slug":"delete","name":"delete","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"DeleteFromStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Delete","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIG5ldyBERUxFVEUgcXVlcnkgYnVpbGRlci4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":204,"slug":"merge","name":"merge","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"table","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":"alias","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"MergeUsingStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Merge","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIG5ldyBNRVJHRSBxdWVyeSBidWlsZGVyLgogKgogKiBAcGFyYW0gc3RyaW5nICR0YWJsZSBUYXJnZXQgdGFibGUgbmFtZQogKiBAcGFyYW0gbnVsbHxzdHJpbmcgJGFsaWFzIE9wdGlvbmFsIHRhYmxlIGFsaWFzCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":218,"slug":"copy","name":"copy","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"CopyFactory","namespace":"Flow\\PostgreSql\\QueryBuilder\\Factory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIG5ldyBDT1BZIHF1ZXJ5IGJ1aWxkZXIgZm9yIGRhdGEgaW1wb3J0L2V4cG9ydC4KICoKICogVXNhZ2U6CiAqICAgY29weSgpLT5mcm9tKCd1c2VycycpLT5maWxlKCcvdG1wL3VzZXJzLmNzdicpLT5mb3JtYXQoQ29weUZvcm1hdDo6Q1NWKQogKiAgIGNvcHkoKS0+dG8oJ3VzZXJzJyktPmZpbGUoJy90bXAvdXNlcnMuY3N2JyktPmZvcm1hdChDb3B5Rm9ybWF0OjpDU1YpCiAqICAgY29weSgpLT50b1F1ZXJ5KHNlbGVjdCguLi4pKS0+ZmlsZSgnL3RtcC9kYXRhLmNzdicpCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":230,"slug":"listen","name":"listen","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"channel","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":"ListenFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Listen","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIExJU1RFTiBzdGF0ZW1lbnQgdG8gc3Vic2NyaWJlIHRoZSBjdXJyZW50IHNlc3Npb24gdG8gYSBub3RpZmljYXRpb24gY2hhbm5lbC4KICoKICogVXNhZ2U6CiAqICAgbGlzdGVuKCdteV9jaGFubmVsJyktPnRvU3FsKCkgIC8vIExJU1RFTiBteV9jaGFubmVsCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":242,"slug":"unlisten","name":"unlisten","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"channel","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":"UnlistenFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Unlisten","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBVTkxJU1RFTiBzdGF0ZW1lbnQgdG8gdW5zdWJzY3JpYmUgdGhlIGN1cnJlbnQgc2Vzc2lvbiBmcm9tIGEgbm90aWZpY2F0aW9uIGNoYW5uZWwuCiAqCiAqIFVzYWdlOgogKiAgIHVubGlzdGVuKCdteV9jaGFubmVsJyktPnRvU3FsKCkgIC8vIFVOTElTVEVOIG15X2NoYW5uZWwKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":255,"slug":"notify","name":"notify","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"channel","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":"NotifyFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Notify","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIE5PVElGWSBzdGF0ZW1lbnQgdG8gc2VuZCBhIG5vdGlmaWNhdGlvbiBvbiBhIGNoYW5uZWwsIG9wdGlvbmFsbHkgd2l0aCBhIHBheWxvYWQuCiAqCiAqIFVzYWdlOgogKiAgIG5vdGlmeSgnbXlfY2hhbm5lbCcpLT50b1NxbCgpICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTk9USUZZIG15X2NoYW5uZWwKICogICBub3RpZnkoJ215X2NoYW5uZWwnKS0+d2l0aFBheWxvYWQoJ2hlbGxvJyktPnRvU3FsKCkgICAgIC8vIE5PVElGWSBteV9jaGFubmVsLCAnaGVsbG8nCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":276,"slug":"col","name":"col","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"column","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":"table","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":"schema","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Column","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGNvbHVtbiByZWZlcmVuY2UgZXhwcmVzc2lvbi4KICoKICogQ2FuIGJlIHVzZWQgaW4gdHdvIG1vZGVzOgogKiAtIFBhcnNlIG1vZGU6IGNvbCgndXNlcnMuaWQnKSBvciBjb2woJ3NjaGVtYS50YWJsZS5jb2x1bW4nKSAtIHBhcnNlcyBkb3Qtc2VwYXJhdGVkIHN0cmluZwogKiAtIEV4cGxpY2l0IG1vZGU6IGNvbCgnaWQnLCAndXNlcnMnKSBvciBjb2woJ2lkJywgJ3VzZXJzJywgJ3NjaGVtYScpIC0gc2VwYXJhdGUgYXJndW1lbnRzCiAqCiAqIFdoZW4gJHRhYmxlIG9yICRzY2hlbWEgaXMgcHJvdmlkZWQsICRjb2x1bW4gbXVzdCBiZSBhIHBsYWluIGNvbHVtbiBuYW1lIChubyBkb3RzKS4KICoKICogQHBhcmFtIHN0cmluZyAkY29sdW1uIENvbHVtbiBuYW1lLCBvciBkb3Qtc2VwYXJhdGVkIHBhdGggbGlrZSAidGFibGUuY29sdW1uIiBvciAic2NoZW1hLnRhYmxlLmNvbHVtbiIKICogQHBhcmFtIG51bGx8c3RyaW5nICR0YWJsZSBUYWJsZSBuYW1lIChvcHRpb25hbCwgdHJpZ2dlcnMgZXhwbGljaXQgbW9kZSkKICogQHBhcmFtIG51bGx8c3RyaW5nICRzY2hlbWEgU2NoZW1hIG5hbWUgKG9wdGlvbmFsLCByZXF1aXJlcyAkdGFibGUpCiAqCiAqIEB0aHJvd3MgSW52YWxpZEV4cHJlc3Npb25FeGNlcHRpb24gd2hlbiAkc2NoZW1hIGlzIHByb3ZpZGVkIHdpdGhvdXQgJHRhYmxlLCBvciB3aGVuICRjb2x1bW4gY29udGFpbnMgZG90cyBpbiBleHBsaWNpdCBtb2RlCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":303,"slug":"star","name":"star","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"table","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Star","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFNFTEVDVCAqIGV4cHJlc3Npb24uCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":319,"slug":"literal","name":"literal","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"value","type":[{"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":"bool","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":false,"default_value":null}],"return_type":[{"name":"Literal","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGxpdGVyYWwgdmFsdWUgZm9yIHVzZSBpbiBxdWVyaWVzLgogKgogKiBBdXRvbWF0aWNhbGx5IGRldGVjdHMgdGhlIHR5cGUgYW5kIGNyZWF0ZXMgdGhlIGFwcHJvcHJpYXRlIGxpdGVyYWw6CiAqIC0gbGl0ZXJhbCgnaGVsbG8nKSBjcmVhdGVzIGEgc3RyaW5nIGxpdGVyYWwKICogLSBsaXRlcmFsKDQyKSBjcmVhdGVzIGFuIGludGVnZXIgbGl0ZXJhbAogKiAtIGxpdGVyYWwoMy4xNCkgY3JlYXRlcyBhIGZsb2F0IGxpdGVyYWwKICogLSBsaXRlcmFsKHRydWUpIGNyZWF0ZXMgYSBib29sZWFuIGxpdGVyYWwKICogLSBsaXRlcmFsKG51bGwpIGNyZWF0ZXMgYSBOVUxMIGxpdGVyYWwKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":334,"slug":"param","name":"param","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"position","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":"Parameter","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHBvc2l0aW9uYWwgcGFyYW1ldGVyICgkMSwgJDIsIGV0Yy4pLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":343,"slug":"parameters","name":"parameters","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"count","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":"startAt","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":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gbGlzdDxQYXJhbWV0ZXI+CiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":369,"slug":"func","name":"func","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"args","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"FunctionCall","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGZ1bmN0aW9uIGNhbGwgZXhwcmVzc2lvbi4KICoKICogQHBhcmFtIHN0cmluZyAkbmFtZSBGdW5jdGlvbiBuYW1lIChjYW4gaW5jbHVkZSBzY2hlbWEgbGlrZSAicGdfY2F0YWxvZy5ub3ciKQogKiBAcGFyYW0gbGlzdDxFeHByZXNzaW9ufHN0cmluZz4gJGFyZ3MgRnVuY3Rpb24gYXJndW1lbnRzCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":403,"slug":"agg","name":"agg","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"args","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"distinct","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":"AggregateCall","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBhZ2dyZWdhdGUgZnVuY3Rpb24gY2FsbCAoQ09VTlQsIFNVTSwgQVZHLCBldGMuKS4KICoKICogQHBhcmFtIHN0cmluZyAkbmFtZSBBZ2dyZWdhdGUgZnVuY3Rpb24gbmFtZQogKiBAcGFyYW0gbGlzdDxFeHByZXNzaW9ufHN0cmluZz4gJGFyZ3MgRnVuY3Rpb24gYXJndW1lbnRzCiAqIEBwYXJhbSBib29sICRkaXN0aW5jdCBVc2UgRElTVElOQ1QgbW9kaWZpZXIKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":417,"slug":"agg-count","name":"agg_count","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"distinct","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":"AggregateCall","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBDT1VOVCgqKSBhZ2dyZWdhdGUuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":430,"slug":"count-all","name":"count_all","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"AggregateCall","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBDT1VOVCgqKSBhZ2dyZWdhdGUuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":439,"slug":"agg-sum","name":"agg_sum","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"distinct","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":"AggregateCall","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBTVU0gYWdncmVnYXRlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":448,"slug":"agg-avg","name":"agg_avg","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"distinct","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":"AggregateCall","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBBVkcgYWdncmVnYXRlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":457,"slug":"agg-min","name":"agg_min","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"AggregateCall","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBNSU4gYWdncmVnYXRlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":466,"slug":"agg-max","name":"agg_max","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"AggregateCall","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBNQVggYWdncmVnYXRlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":477,"slug":"coalesce","name":"coalesce","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expressions","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"Coalesce","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENPQUxFU0NFIGV4cHJlc3Npb24uCiAqCiAqIEBwYXJhbSBFeHByZXNzaW9ufHN0cmluZyAuLi4kZXhwcmVzc2lvbnMgRXhwcmVzc2lvbnMgdG8gY29hbGVzY2UKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":488,"slug":"nullif","name":"nullif","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr1","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"expr2","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"NullIf","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIE5VTExJRiBleHByZXNzaW9uLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":502,"slug":"greatest","name":"greatest","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expressions","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"Greatest","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEdSRUFURVNUIGV4cHJlc3Npb24uCiAqCiAqIEBwYXJhbSBFeHByZXNzaW9ufHN0cmluZyAuLi4kZXhwcmVzc2lvbnMgRXhwcmVzc2lvbnMgdG8gY29tcGFyZQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":515,"slug":"least","name":"least","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expressions","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"Least","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIExFQVNUIGV4cHJlc3Npb24uCiAqCiAqIEBwYXJhbSBFeHByZXNzaW9ufHN0cmluZyAuLi4kZXhwcmVzc2lvbnMgRXhwcmVzc2lvbnMgdG8gY29tcGFyZQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":529,"slug":"cast","name":"cast","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"dataType","type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"TypeCast","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHR5cGUgY2FzdCBleHByZXNzaW9uLgogKgogKiBAcGFyYW0gRXhwcmVzc2lvbnxzdHJpbmcgJGV4cHIgRXhwcmVzc2lvbiB0byBjYXN0CiAqIEBwYXJhbSBDb2x1bW5UeXBlICRkYXRhVHlwZSBUYXJnZXQgZGF0YSB0eXBlICh1c2UgY29sdW1uX3R5cGVfKiBmdW5jdGlvbnMpCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":544,"slug":"current-timestamp","name":"current_timestamp","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"SQLValueFunctionExpression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFNRTCBzdGFuZGFyZCBDVVJSRU5UX1RJTUVTVEFNUCBmdW5jdGlvbi4KICoKICogUmV0dXJucyB0aGUgY3VycmVudCBkYXRlIGFuZCB0aW1lIChhdCB0aGUgc3RhcnQgb2YgdGhlIHRyYW5zYWN0aW9uKS4KICogVXNlZnVsIGFzIGEgY29sdW1uIGRlZmF1bHQgdmFsdWUgb3IgaW4gU0VMRUNUIHF1ZXJpZXMuCiAqCiAqIEV4YW1wbGU6IGNvbHVtbignY3JlYXRlZF9hdCcsIGNvbHVtbl90eXBlX3RpbWVzdGFtcCgpKS0+ZGVmYXVsdChjdXJyZW50X3RpbWVzdGFtcCgpKQogKiBFeGFtcGxlOiBzZWxlY3QoKS0+c2VsZWN0KGN1cnJlbnRfdGltZXN0YW1wKCktPmFzKCdub3cnKSkKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":559,"slug":"current-date","name":"current_date","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"SQLValueFunctionExpression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFNRTCBzdGFuZGFyZCBDVVJSRU5UX0RBVEUgZnVuY3Rpb24uCiAqCiAqIFJldHVybnMgdGhlIGN1cnJlbnQgZGF0ZSAoYXQgdGhlIHN0YXJ0IG9mIHRoZSB0cmFuc2FjdGlvbikuCiAqIFVzZWZ1bCBhcyBhIGNvbHVtbiBkZWZhdWx0IHZhbHVlIG9yIGluIFNFTEVDVCBxdWVyaWVzLgogKgogKiBFeGFtcGxlOiBjb2x1bW4oJ2JpcnRoX2RhdGUnLCBjb2x1bW5fdHlwZV9kYXRlKCkpLT5kZWZhdWx0KGN1cnJlbnRfZGF0ZSgpKQogKiBFeGFtcGxlOiBzZWxlY3QoKS0+c2VsZWN0KGN1cnJlbnRfZGF0ZSgpLT5hcygndG9kYXknKSkKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":574,"slug":"current-time","name":"current_time","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"SQLValueFunctionExpression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFNRTCBzdGFuZGFyZCBDVVJSRU5UX1RJTUUgZnVuY3Rpb24uCiAqCiAqIFJldHVybnMgdGhlIGN1cnJlbnQgdGltZSAoYXQgdGhlIHN0YXJ0IG9mIHRoZSB0cmFuc2FjdGlvbikuCiAqIFVzZWZ1bCBhcyBhIGNvbHVtbiBkZWZhdWx0IHZhbHVlIG9yIGluIFNFTEVDVCBxdWVyaWVzLgogKgogKiBFeGFtcGxlOiBjb2x1bW4oJ3N0YXJ0X3RpbWUnLCBjb2x1bW5fdHlwZV90aW1lKCkpLT5kZWZhdWx0KGN1cnJlbnRfdGltZSgpKQogKiBFeGFtcGxlOiBzZWxlY3QoKS0+c2VsZWN0KGN1cnJlbnRfdGltZSgpLT5hcygnbm93X3RpbWUnKSkKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":587,"slug":"case-when","name":"case_when","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"whenClauses","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":"elseResult","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"operand","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"CaseExpression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENBU0UgZXhwcmVzc2lvbi4KICoKICogQHBhcmFtIG5vbi1lbXB0eS1saXN0PFdoZW5DbGF1c2U+ICR3aGVuQ2xhdXNlcyBXSEVOIGNsYXVzZXMKICogQHBhcmFtIG51bGx8RXhwcmVzc2lvbnxzdHJpbmcgJGVsc2VSZXN1bHQgRUxTRSByZXN1bHQgKG9wdGlvbmFsKQogKiBAcGFyYW0gbnVsbHxFeHByZXNzaW9ufHN0cmluZyAkb3BlcmFuZCBDQVNFIG9wZXJhbmQgZm9yIHNpbXBsZSBDQVNFIChvcHRpb25hbCkKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":603,"slug":"when","name":"when","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"condition","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"result","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"WhenClause","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFdIRU4gY2xhdXNlIGZvciBDQVNFIGV4cHJlc3Npb24uCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":615,"slug":"sub-select","name":"sub_select","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"query","type":[{"name":"SelectFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Select","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Subquery","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHN1YnF1ZXJ5IGV4cHJlc3Npb24uCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":629,"slug":"array-expr","name":"array_expr","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"elements","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":"ArrayExpression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBhcnJheSBleHByZXNzaW9uLgogKgogKiBAcGFyYW0gbGlzdDxFeHByZXNzaW9ufHN0cmluZz4gJGVsZW1lbnRzIEFycmF5IGVsZW1lbnRzCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":642,"slug":"row-expr","name":"row_expr","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"elements","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":"RowExpression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHJvdyBleHByZXNzaW9uLgogKgogKiBAcGFyYW0gbGlzdDxFeHByZXNzaW9ufHN0cmluZz4gJGVsZW1lbnRzIFJvdyBlbGVtZW50cwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":653,"slug":"binary-expr","name":"binary_expr","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"left","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"operator","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":"right","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"BinaryExpression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGJpbmFyeSBleHByZXNzaW9uIChsZWZ0IG9wIHJpZ2h0KS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":671,"slug":"window-func","name":"window_func","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"args","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"partitionBy","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"orderBy","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"WindowFunction","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHdpbmRvdyBmdW5jdGlvbi4KICoKICogQHBhcmFtIHN0cmluZyAkbmFtZSBGdW5jdGlvbiBuYW1lCiAqIEBwYXJhbSBsaXN0PEV4cHJlc3Npb258c3RyaW5nPiAkYXJncyBGdW5jdGlvbiBhcmd1bWVudHMKICogQHBhcmFtIGxpc3Q8RXhwcmVzc2lvbnxzdHJpbmc+ICRwYXJ0aXRpb25CeSBQQVJUSVRJT04gQlkgZXhwcmVzc2lvbnMKICogQHBhcmFtIGxpc3Q8T3JkZXJCeT4gJG9yZGVyQnkgT1JERVIgQlkgaXRlbXMKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":692,"slug":"concat","name":"concat","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expressions","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"BinaryExpression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENvbmNhdGVuYXRlIGV4cHJlc3Npb25zIHdpdGggdGhlIHx8IG9wZXJhdG9yLgogKgogKiBFeGFtcGxlOiBjb25jYXQoY29sKCdzY2hlbWEnKSwgbGl0ZXJhbCgnLicpLCBjb2woJ3RhYmxlJykpCiAqIFByb2R1Y2VzOiBzY2hlbWEgfHwgJy4nIHx8IHRhYmxlCiAqCiAqIEBwYXJhbSBFeHByZXNzaW9ufHN0cmluZyAuLi4kZXhwcmVzc2lvbnMgQXQgbGVhc3QgMiBleHByZXNzaW9ucyB0byBjb25jYXRlbmF0ZQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":722,"slug":"table","name":"table","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"schema","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Table","namespace":"Flow\\PostgreSql\\QueryBuilder\\Table","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHRhYmxlIHJlZmVyZW5jZS4KICoKICogU3VwcG9ydHMgZG90IG5vdGF0aW9uIGZvciBzY2hlbWEtcXVhbGlmaWVkIG5hbWVzOiAicHVibGljLnVzZXJzIiBvciBleHBsaWNpdCBzY2hlbWEgcGFyYW1ldGVyLgogKiBEb3VibGUtcXVvdGVkIGlkZW50aWZpZXJzIHByZXNlcnZlIGRvdHM6ICcibXkudGFibGUiJyBjcmVhdGVzIGEgc2luZ2xlIGlkZW50aWZpZXIuCiAqCiAqIEBwYXJhbSBzdHJpbmcgJG5hbWUgVGFibGUgbmFtZSAobWF5IGluY2x1ZGUgc2NoZW1hIGFzICJzY2hlbWEudGFibGUiKQogKiBAcGFyYW0gbnVsbHxzdHJpbmcgJHNjaGVtYSBTY2hlbWEgbmFtZSAob3B0aW9uYWwsIG92ZXJyaWRlcyBwYXJzZWQgc2NoZW1hKQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":737,"slug":"derived","name":"derived","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"query","type":[{"name":"SelectFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Select","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"alias","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":"DerivedTable","namespace":"Flow\\PostgreSql\\QueryBuilder\\Table","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGRlcml2ZWQgdGFibGUgKHN1YnF1ZXJ5IGluIEZST00gY2xhdXNlKS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":751,"slug":"lateral","name":"lateral","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"reference","type":[{"name":"TableReference","namespace":"Flow\\PostgreSql\\QueryBuilder\\Table","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Lateral","namespace":"Flow\\PostgreSql\\QueryBuilder\\Table","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIExBVEVSQUwgc3VicXVlcnkuCiAqCiAqIEBwYXJhbSBUYWJsZVJlZmVyZW5jZSAkcmVmZXJlbmNlIFRoZSBzdWJxdWVyeSBvciB0YWJsZSBmdW5jdGlvbiByZWZlcmVuY2UKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":763,"slug":"table-func","name":"table_func","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"function","type":[{"name":"FunctionCall","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"withOrdinality","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":"TableFunction","namespace":"Flow\\PostgreSql\\QueryBuilder\\Table","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHRhYmxlIGZ1bmN0aW9uIHJlZmVyZW5jZS4KICoKICogQHBhcmFtIEZ1bmN0aW9uQ2FsbCAkZnVuY3Rpb24gVGhlIHRhYmxlLXZhbHVlZCBmdW5jdGlvbgogKiBAcGFyYW0gYm9vbCAkd2l0aE9yZGluYWxpdHkgV2hldGhlciB0byBhZGQgV0lUSCBPUkRJTkFMSVRZCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":782,"slug":"values-table","name":"values_table","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"rows","type":[{"name":"RowExpression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"ValuesTable","namespace":"Flow\\PostgreSql\\QueryBuilder\\Table","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFZBTFVFUyBjbGF1c2UgYXMgYSB0YWJsZSByZWZlcmVuY2UuCiAqCiAqIFVzYWdlOgogKiAgIHNlbGVjdCgpLT5mcm9tKAogKiAgICAgICB2YWx1ZXNfdGFibGUoCiAqICAgICAgICAgICByb3dfZXhwcihbbGl0ZXJhbCgxKSwgbGl0ZXJhbCgnQWxpY2UnKV0pLAogKiAgICAgICAgICAgcm93X2V4cHIoW2xpdGVyYWwoMiksIGxpdGVyYWwoJ0JvYicpXSkKICogICAgICAgKS0+YXMoJ3QnLCBbJ2lkJywgJ25hbWUnXSkKICogICApCiAqCiAqIEdlbmVyYXRlczogU0VMRUNUICogRlJPTSAoVkFMVUVTICgxLCAnQWxpY2UnKSwgKDIsICdCb2InKSkgQVMgdChpZCwgbmFtZSkKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":791,"slug":"order-by","name":"order_by","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"direction","type":[{"name":"SortDirection","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\PostgreSql\\QueryBuilder\\Clause\\SortDirection::..."},{"name":"nulls","type":[{"name":"NullsPosition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\PostgreSql\\QueryBuilder\\Clause\\NullsPosition::..."}],"return_type":[{"name":"OrderBy","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBPUkRFUiBCWSBpdGVtLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":803,"slug":"asc","name":"asc","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"nulls","type":[{"name":"NullsPosition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\PostgreSql\\QueryBuilder\\Clause\\NullsPosition::..."}],"return_type":[{"name":"OrderBy","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBPUkRFUiBCWSBpdGVtIHdpdGggQVNDIGRpcmVjdGlvbi4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":812,"slug":"desc","name":"desc","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"nulls","type":[{"name":"NullsPosition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\PostgreSql\\QueryBuilder\\Clause\\NullsPosition::..."}],"return_type":[{"name":"OrderBy","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBPUkRFUiBCWSBpdGVtIHdpdGggREVTQyBkaXJlY3Rpb24uCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":826,"slug":"cte","name":"cte","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"query","type":[{"name":"SelectFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Select","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"columnNames","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"materialization","type":[{"name":"CTEMaterialization","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\PostgreSql\\QueryBuilder\\Clause\\CTEMaterialization::..."},{"name":"recursive","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":"CTE","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENURSAoQ29tbW9uIFRhYmxlIEV4cHJlc3Npb24pLgogKgogKiBAcGFyYW0gc3RyaW5nICRuYW1lIENURSBuYW1lCiAqIEBwYXJhbSBTZWxlY3RGaW5hbFN0ZXAgJHF1ZXJ5IENURSBxdWVyeQogKiBAcGFyYW0gYXJyYXk8c3RyaW5nPiAkY29sdW1uTmFtZXMgQ29sdW1uIGFsaWFzZXMgKG9wdGlvbmFsKQogKiBAcGFyYW0gQ1RFTWF0ZXJpYWxpemF0aW9uICRtYXRlcmlhbGl6YXRpb24gTWF0ZXJpYWxpemF0aW9uIGhpbnQKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":848,"slug":"window-def","name":"window_def","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"partitionBy","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"orderBy","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"frame","type":[{"name":"WindowFrame","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"WindowDefinition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHdpbmRvdyBkZWZpbml0aW9uIGZvciBXSU5ET1cgY2xhdXNlLgogKgogKiBAcGFyYW0gc3RyaW5nICRuYW1lIFdpbmRvdyBuYW1lCiAqIEBwYXJhbSBsaXN0PEV4cHJlc3Npb258c3RyaW5nPiAkcGFydGl0aW9uQnkgUEFSVElUSU9OIEJZIGV4cHJlc3Npb25zCiAqIEBwYXJhbSBsaXN0PE9yZGVyQnk+ICRvcmRlckJ5IE9SREVSIEJZIGl0ZW1zCiAqIEBwYXJhbSBudWxsfFdpbmRvd0ZyYW1lICRmcmFtZSBXaW5kb3cgZnJhbWUgc3BlY2lmaWNhdGlvbgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":868,"slug":"window-frame","name":"window_frame","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"mode","type":[{"name":"FrameMode","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"start","type":[{"name":"FrameBound","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"end","type":[{"name":"FrameBound","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"exclusion","type":[{"name":"FrameExclusion","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\PostgreSql\\QueryBuilder\\Clause\\FrameExclusion::..."}],"return_type":[{"name":"WindowFrame","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHdpbmRvdyBmcmFtZSBzcGVjaWZpY2F0aW9uLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":881,"slug":"frame-current-row","name":"frame_current_row","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"FrameBound","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGZyYW1lIGJvdW5kIGZvciBDVVJSRU5UIFJPVy4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":890,"slug":"frame-unbounded-preceding","name":"frame_unbounded_preceding","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"FrameBound","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGZyYW1lIGJvdW5kIGZvciBVTkJPVU5ERUQgUFJFQ0VESU5HLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":899,"slug":"frame-unbounded-following","name":"frame_unbounded_following","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"FrameBound","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGZyYW1lIGJvdW5kIGZvciBVTkJPVU5ERUQgRk9MTE9XSU5HLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":908,"slug":"frame-preceding","name":"frame_preceding","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"offset","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"FrameBound","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGZyYW1lIGJvdW5kIGZvciBOIFBSRUNFRElORy4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":917,"slug":"frame-following","name":"frame_following","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"offset","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"FrameBound","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGZyYW1lIGJvdW5kIGZvciBOIEZPTExPV0lORy4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":930,"slug":"lock-for","name":"lock_for","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"strength","type":[{"name":"LockStrength","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"tables","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"waitPolicy","type":[{"name":"LockWaitPolicy","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\PostgreSql\\QueryBuilder\\Clause\\LockWaitPolicy::..."}],"return_type":[{"name":"LockingClause","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGxvY2tpbmcgY2xhdXNlIChGT1IgVVBEQVRFLCBGT1IgU0hBUkUsIGV0Yy4pLgogKgogKiBAcGFyYW0gTG9ja1N0cmVuZ3RoICRzdHJlbmd0aCBMb2NrIHN0cmVuZ3RoCiAqIEBwYXJhbSBsaXN0PHN0cmluZz4gJHRhYmxlcyBUYWJsZXMgdG8gbG9jayAoZW1wdHkgZm9yIGFsbCkKICogQHBhcmFtIExvY2tXYWl0UG9saWN5ICR3YWl0UG9saWN5IFdhaXQgcG9saWN5CiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":944,"slug":"for-update","name":"for_update","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"tables","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"LockingClause","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEZPUiBVUERBVEUgbG9ja2luZyBjbGF1c2UuCiAqCiAqIEBwYXJhbSBsaXN0PHN0cmluZz4gJHRhYmxlcyBUYWJsZXMgdG8gbG9jayAoZW1wdHkgZm9yIGFsbCkKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":955,"slug":"for-share","name":"for_share","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"tables","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"LockingClause","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEZPUiBTSEFSRSBsb2NraW5nIGNsYXVzZS4KICoKICogQHBhcmFtIGxpc3Q8c3RyaW5nPiAkdGFibGVzIFRhYmxlcyB0byBsb2NrIChlbXB0eSBmb3IgYWxsKQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":964,"slug":"on-conflict-nothing","name":"on_conflict_nothing","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"target","type":[{"name":"ConflictTarget","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"OnConflictClause","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBPTiBDT05GTElDVCBETyBOT1RISU5HIGNsYXVzZS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":976,"slug":"on-conflict-update","name":"on_conflict_update","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"target","type":[{"name":"ConflictTarget","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"updates","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":"OnConflictClause","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBPTiBDT05GTElDVCBETyBVUERBVEUgY2xhdXNlLgogKgogKiBAcGFyYW0gQ29uZmxpY3RUYXJnZXQgJHRhcmdldCBDb25mbGljdCB0YXJnZXQgKGNvbHVtbnMgb3IgY29uc3RyYWludCkKICogQHBhcmFtIGFycmF5PHN0cmluZywgRXhwcmVzc2lvbnxzdHJpbmc+ICR1cGRhdGVzIENvbHVtbiB1cGRhdGVzCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":990,"slug":"conflict-columns","name":"conflict_columns","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"columns","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":"ConflictTarget","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGNvbmZsaWN0IHRhcmdldCBmb3IgT04gQ09ORkxJQ1QgKGNvbHVtbnMpLgogKgogKiBAcGFyYW0gbGlzdDxzdHJpbmc+ICRjb2x1bW5zIENvbHVtbnMgdGhhdCBkZWZpbmUgdW5pcXVlbmVzcwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":999,"slug":"conflict-constraint","name":"conflict_constraint","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"ConflictTarget","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGNvbmZsaWN0IHRhcmdldCBmb3IgT04gQ09ORkxJQ1QgT04gQ09OU1RSQUlOVC4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":1010,"slug":"returning","name":"returning","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expressions","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"ReturningClause","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFJFVFVSTklORyBjbGF1c2UuCiAqCiAqIEBwYXJhbSBFeHByZXNzaW9ufHN0cmluZyAuLi4kZXhwcmVzc2lvbnMgRXhwcmVzc2lvbnMgdG8gcmV0dXJuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":1021,"slug":"returning-all","name":"returning_all","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ReturningClause","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFJFVFVSTklORyAqIGNsYXVzZS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":1033,"slug":"begin","name":"begin","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"BeginOptionsStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Transaction","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEJFR0lOIHRyYW5zYWN0aW9uIGJ1aWxkZXIuCiAqCiAqIEV4YW1wbGU6IGJlZ2luKCktPmlzb2xhdGlvbkxldmVsKElzb2xhdGlvbkxldmVsOjpTRVJJQUxJWkFCTEUpLT5yZWFkT25seSgpCiAqIFByb2R1Y2VzOiBCRUdJTiBJU09MQVRJT04gTEVWRUwgU0VSSUFMSVpBQkxFIFJFQUQgT05MWQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":1045,"slug":"commit","name":"commit","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"CommitOptionsStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Transaction","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENPTU1JVCB0cmFuc2FjdGlvbiBidWlsZGVyLgogKgogKiBFeGFtcGxlOiBjb21taXQoKS0+YW5kQ2hhaW4oKQogKiBQcm9kdWNlczogQ09NTUlUIEFORCBDSEFJTgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":1057,"slug":"rollback","name":"rollback","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"RollbackOptionsStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Transaction","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFJPTExCQUNLIHRyYW5zYWN0aW9uIGJ1aWxkZXIuCiAqCiAqIEV4YW1wbGU6IHJvbGxiYWNrKCktPnRvU2F2ZXBvaW50KCdteV9zYXZlcG9pbnQnKQogKiBQcm9kdWNlczogUk9MTEJBQ0sgVE8gU0FWRVBPSU5UIG15X3NhdmVwb2ludAogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":1069,"slug":"savepoint","name":"savepoint","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"SavepointFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Transaction","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFNBVkVQT0lOVC4KICoKICogRXhhbXBsZTogc2F2ZXBvaW50KCdteV9zYXZlcG9pbnQnKQogKiBQcm9kdWNlczogU0FWRVBPSU5UIG15X3NhdmVwb2ludAogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":1081,"slug":"release-savepoint","name":"release_savepoint","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"SavepointFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Transaction","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFJlbGVhc2UgYSBTQVZFUE9JTlQuCiAqCiAqIEV4YW1wbGU6IHJlbGVhc2Vfc2F2ZXBvaW50KCdteV9zYXZlcG9pbnQnKQogKiBQcm9kdWNlczogUkVMRUFTRSBteV9zYXZlcG9pbnQKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":1093,"slug":"set-transaction","name":"set_transaction","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"SetTransactionOptionsStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Transaction","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFNFVCBUUkFOU0FDVElPTiBidWlsZGVyLgogKgogKiBFeGFtcGxlOiBzZXRfdHJhbnNhY3Rpb24oKS0+aXNvbGF0aW9uTGV2ZWwoSXNvbGF0aW9uTGV2ZWw6OlNFUklBTElaQUJMRSktPnJlYWRPbmx5KCkKICogUHJvZHVjZXM6IFNFVCBUUkFOU0FDVElPTiBJU09MQVRJT04gTEVWRUwgU0VSSUFMSVpBQkxFLCBSRUFEIE9OTFkKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":1105,"slug":"set-session-transaction","name":"set_session_transaction","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"SetTransactionOptionsStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Transaction","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFNFVCBTRVNTSU9OIENIQVJBQ1RFUklTVElDUyBBUyBUUkFOU0FDVElPTiBidWlsZGVyLgogKgogKiBFeGFtcGxlOiBzZXRfc2Vzc2lvbl90cmFuc2FjdGlvbigpLT5pc29sYXRpb25MZXZlbChJc29sYXRpb25MZXZlbDo6U0VSSUFMSVpBQkxFKQogKiBQcm9kdWNlczogU0VUIFNFU1NJT04gQ0hBUkFDVEVSSVNUSUNTIEFTIFRSQU5TQUNUSU9OIElTT0xBVElPTiBMRVZFTCBTRVJJQUxJWkFCTEUKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":1117,"slug":"transaction-snapshot","name":"transaction_snapshot","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"snapshotId","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":"SetTransactionFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Transaction","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFNFVCBUUkFOU0FDVElPTiBTTkFQU0hPVCBidWlsZGVyLgogKgogKiBFeGFtcGxlOiB0cmFuc2FjdGlvbl9zbmFwc2hvdCgnMDAwMDAwMDMtMDAwMDAwMUEtMScpCiAqIFByb2R1Y2VzOiBTRVQgVFJBTlNBQ1RJT04gU05BUFNIT1QgJzAwMDAwMDAzLTAwMDAwMDFBLTEnCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":1129,"slug":"prepare-transaction","name":"prepare_transaction","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"transactionId","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":"PreparedTransactionFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Transaction","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBSRVBBUkUgVFJBTlNBQ1RJT04gYnVpbGRlci4KICoKICogRXhhbXBsZTogcHJlcGFyZV90cmFuc2FjdGlvbignbXlfdHJhbnNhY3Rpb24nKQogKiBQcm9kdWNlczogUFJFUEFSRSBUUkFOU0FDVElPTiAnbXlfdHJhbnNhY3Rpb24nCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":1141,"slug":"commit-prepared","name":"commit_prepared","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"transactionId","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":"PreparedTransactionFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Transaction","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENPTU1JVCBQUkVQQVJFRCBidWlsZGVyLgogKgogKiBFeGFtcGxlOiBjb21taXRfcHJlcGFyZWQoJ215X3RyYW5zYWN0aW9uJykKICogUHJvZHVjZXM6IENPTU1JVCBQUkVQQVJFRCAnbXlfdHJhbnNhY3Rpb24nCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":1153,"slug":"rollback-prepared","name":"rollback_prepared","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"transactionId","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":"PreparedTransactionFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Transaction","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFJPTExCQUNLIFBSRVBBUkVEIGJ1aWxkZXIuCiAqCiAqIEV4YW1wbGU6IHJvbGxiYWNrX3ByZXBhcmVkKCdteV90cmFuc2FjdGlvbicpCiAqIFByb2R1Y2VzOiBST0xMQkFDSyBQUkVQQVJFRCAnbXlfdHJhbnNhY3Rpb24nCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":1176,"slug":"declare-cursor","name":"declare_cursor","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"cursorName","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":"query","type":[{"name":"SelectFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Select","is_nullable":false,"is_variadic":false},{"name":"Sql","namespace":"Flow\\PostgreSql\\QueryBuilder","is_nullable":false,"is_variadic":false},{"name":"ParsedQuery","namespace":"Flow\\PostgreSql","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":"DeclareCursorOptionsStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Cursor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIERlY2xhcmUgYSBzZXJ2ZXItc2lkZSBjdXJzb3IgZm9yIGEgcXVlcnkuCiAqCiAqIEN1cnNvcnMgbXVzdCBiZSBkZWNsYXJlZCB3aXRoaW4gYSB0cmFuc2FjdGlvbiBhbmQgcHJvdmlkZSBtZW1vcnktZWZmaWNpZW50CiAqIGl0ZXJhdGlvbiBvdmVyIGxhcmdlIHJlc3VsdCBzZXRzIHZpYSBGRVRDSCBjb21tYW5kcy4KICoKICogRXhhbXBsZSB3aXRoIHF1ZXJ5IGJ1aWxkZXI6CiAqICAgZGVjbGFyZV9jdXJzb3IoJ215X2N1cnNvcicsIHNlbGVjdChzdGFyKCkpLT5mcm9tKHRhYmxlKCd1c2VycycpKSktPm5vU2Nyb2xsKCkKICogICBQcm9kdWNlczogREVDTEFSRSBteV9jdXJzb3IgTk8gU0NST0xMIENVUlNPUiBGT1IgU0VMRUNUICogRlJPTSB1c2VycwogKgogKiBFeGFtcGxlIHdpdGggcmF3IFNRTDoKICogICBkZWNsYXJlX2N1cnNvcignbXlfY3Vyc29yJywgJ1NFTEVDVCAqIEZST00gdXNlcnMgV0hFUkUgYWN0aXZlID0gdHJ1ZScpLT53aXRoSG9sZCgpCiAqICAgUHJvZHVjZXM6IERFQ0xBUkUgbXlfY3Vyc29yIE5PIFNDUk9MTCBDVVJTT1IgV0lUSCBIT0xEIEZPUiBTRUxFQ1QgKiBGUk9NIHVzZXJzIFdIRVJFIGFjdGl2ZSA9IHRydWUKICoKICogQHBhcmFtIHN0cmluZyAkY3Vyc29yTmFtZSBVbmlxdWUgY3Vyc29yIG5hbWUKICogQHBhcmFtIFBhcnNlZFF1ZXJ5fFNlbGVjdEZpbmFsU3RlcHxTcWx8c3RyaW5nICRxdWVyeSBRdWVyeSB0byBpdGVyYXRlIG92ZXIKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":1201,"slug":"fetch","name":"fetch","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"cursorName","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":"FetchCursorBuilder","namespace":"Flow\\PostgreSql\\QueryBuilder\\Cursor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEZldGNoIHJvd3MgZnJvbSBhIGN1cnNvci4KICoKICogRXhhbXBsZTogZmV0Y2goJ215X2N1cnNvcicpLT5mb3J3YXJkKDEwMCkKICogUHJvZHVjZXM6IEZFVENIIEZPUldBUkQgMTAwIG15X2N1cnNvcgogKgogKiBFeGFtcGxlOiBmZXRjaCgnbXlfY3Vyc29yJyktPmFsbCgpCiAqIFByb2R1Y2VzOiBGRVRDSCBBTEwgbXlfY3Vyc29yCiAqCiAqIEBwYXJhbSBzdHJpbmcgJGN1cnNvck5hbWUgQ3Vyc29yIHRvIGZldGNoIGZyb20KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":1218,"slug":"close-cursor","name":"close_cursor","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"cursorName","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"CloseCursorFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Cursor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENsb3NlIGEgY3Vyc29yLgogKgogKiBFeGFtcGxlOiBjbG9zZV9jdXJzb3IoJ215X2N1cnNvcicpCiAqIFByb2R1Y2VzOiBDTE9TRSBteV9jdXJzb3IKICoKICogRXhhbXBsZTogY2xvc2VfY3Vyc29yKCkgLSBjbG9zZXMgYWxsIGN1cnNvcnMKICogUHJvZHVjZXM6IENMT1NFIEFMTAogKgogKiBAcGFyYW0gbnVsbHxzdHJpbmcgJGN1cnNvck5hbWUgQ3Vyc29yIHRvIGNsb3NlLCBvciBudWxsIHRvIGNsb3NlIGFsbAogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":42,"slug":"eq","name":"eq","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"left","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"right","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"Comparison","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBlcXVhbGl0eSBjb21wYXJpc29uIChjb2x1bW4gPSB2YWx1ZSkuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":55,"slug":"ne","name":"ne","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"left","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"right","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"Comparison","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIG5vdC1lcXVhbCBjb21wYXJpc29uIChjb2x1bW4gIT0gdmFsdWUpLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":68,"slug":"lt","name":"lt","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"left","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"right","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"Comparison","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGxlc3MtdGhhbiBjb21wYXJpc29uIChjb2x1bW4gPCB2YWx1ZSkuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":81,"slug":"le","name":"le","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"left","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"right","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"Comparison","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGxlc3MtdGhhbi1vci1lcXVhbCBjb21wYXJpc29uIChjb2x1bW4gPD0gdmFsdWUpLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":94,"slug":"gt","name":"gt","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"left","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"right","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"Comparison","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGdyZWF0ZXItdGhhbiBjb21wYXJpc29uIChjb2x1bW4gPiB2YWx1ZSkuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":107,"slug":"ge","name":"ge","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"left","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"right","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"Comparison","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGdyZWF0ZXItdGhhbi1vci1lcXVhbCBjb21wYXJpc29uIChjb2x1bW4gPj0gdmFsdWUpLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":120,"slug":"between","name":"between","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"low","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"high","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"not","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":"Between","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEJFVFdFRU4gY29uZGl0aW9uLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":139,"slug":"in","name":"in_","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"values","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":"In","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBJTiBjb25kaXRpb24uCiAqCiAqIEBwYXJhbSBFeHByZXNzaW9ufHN0cmluZyAkZXhwciBFeHByZXNzaW9uIHRvIGNoZWNrCiAqIEBwYXJhbSBsaXN0PEV4cHJlc3Npb24+ICR2YWx1ZXMgTGlzdCBvZiB2YWx1ZXMgKG11c3QgYmUgbm9uLWVtcHR5KQogKgogKiBAdGhyb3dzIFxJbnZhbGlkQXJndW1lbnRFeGNlcHRpb24gd2hlbiB2YWx1ZXMgYXJyYXkgaXMgZW1wdHkKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":156,"slug":"is-null","name":"is_null","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"not","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":"IsNull","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBJUyBOVUxMIGNvbmRpdGlvbi4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":165,"slug":"like","name":"like","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"pattern","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"caseInsensitive","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"negated","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":"Like","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIExJS0UgY29uZGl0aW9uLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":183,"slug":"similar-to","name":"similar_to","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"pattern","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"SimilarTo","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFNJTUlMQVIgVE8gY29uZGl0aW9uLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":195,"slug":"distinct-from","name":"distinct_from","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"left","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"right","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"not","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":"IsDistinctFrom","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBJUyBESVNUSU5DVCBGUk9NIGNvbmRpdGlvbi4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":208,"slug":"exists","name":"exists","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"subquery","type":[{"name":"SelectFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Select","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Exists","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBFWElTVFMgY29uZGl0aW9uLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":223,"slug":"any","name":"any_","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"left","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"operator","type":[{"name":"ComparisonOperator","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"arrayOrSubquery","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false},{"name":"SelectFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Select","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\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBBTlkgY29uZGl0aW9uIHdpdGggYSBzdWJxdWVyeSBvciBhcnJheSBleHByZXNzaW9uLgogKgogKiBFeGFtcGxlOiBhbnlfKGNvbCgnaWQnKSwgQ29tcGFyaXNvbk9wZXJhdG9yOjpFUSwgc2VsZWN0KGNvbCgndXNlcl9pZCcpKS0+ZnJvbSh0YWJsZSgnb3JkZXJzJykpKQogKiBFeGFtcGxlOiBhbnlfKGNvbCgnYXR0bnVtJywgJ2EnKSwgQ29tcGFyaXNvbk9wZXJhdG9yOjpFUSwgY29sKCdjb25rZXknLCAnY29uJykpCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":243,"slug":"all","name":"all_","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"left","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"operator","type":[{"name":"ComparisonOperator","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"arrayOrSubquery","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false},{"name":"SelectFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Select","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\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBBTEwgY29uZGl0aW9uIHdpdGggYSBzdWJxdWVyeSBvciBhcnJheSBleHByZXNzaW9uLgogKgogKiBFeGFtcGxlOiBhbGxfKGNvbCgnaWQnKSwgQ29tcGFyaXNvbk9wZXJhdG9yOjpFUSwgc2VsZWN0KGNvbCgndXNlcl9pZCcpKS0+ZnJvbSh0YWJsZSgnb3JkZXJzJykpKQogKiBFeGFtcGxlOiBhbGxfKGNvbCgndmFsdWUnKSwgQ29tcGFyaXNvbk9wZXJhdG9yOjpHVCwgY29sKCd0aHJlc2hvbGRzJykpCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":262,"slug":"is-true","name":"is_true","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"BooleanCondition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFdyYXAgYW4gZXhwcmVzc2lvbiBhcyBhIGJvb2xlYW4gY29uZGl0aW9uIGZvciB1c2UgaW4gV0hFUkUvSEFWSU5HL0pPSU4gT04uCiAqCiAqIEV4YW1wbGU6IGlzX3RydWUoY29sKCdpc19hY3RpdmUnKSkg4oCUIHVzZXMgYSBib29sZWFuIGNvbHVtbiBpbiBXSEVSRSBjbGF1c2UuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":274,"slug":"not-like","name":"not_like","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"pattern","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"caseInsensitive","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":"Like","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIE5PVCBMSUtFIGNvbmRpdGlvbi4KICoKICogRXhhbXBsZTogbm90X2xpa2UoY29sKCduYW1lJyksIGxpdGVyYWwoJ3BnXyUnKSkKICogUHJvZHVjZXM6IG5hbWUgTk9UIExJS0UgJ3BnXyUnCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":302,"slug":"conditions","name":"conditions","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ConditionBuilder","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGNvbmRpdGlvbiBidWlsZGVyIGZvciBmbHVlbnQgY29uZGl0aW9uIGNvbXBvc2l0aW9uLgogKgogKiBUaGlzIGJ1aWxkZXIgYWxsb3dzIGluY3JlbWVudGFsIGNvbmRpdGlvbiBidWlsZGluZyB3aXRoIGEgZmx1ZW50IEFQSToKICoKICogYGBgcGhwCiAqICRidWlsZGVyID0gY29uZGl0aW9ucygpOwogKgogKiBpZiAoJGhhc0ZpbHRlcikgewogKiAgICAgJGJ1aWxkZXIgPSAkYnVpbGRlci0+YW5kKGVxKGNvbCgnc3RhdHVzJyksIGxpdGVyYWwoJ2FjdGl2ZScpKSk7CiAqIH0KICoKICogaWYgKCEkYnVpbGRlci0+aXNFbXB0eSgpKSB7CiAqICAgICAkcXVlcnkgPSBzZWxlY3QoKS0+ZnJvbSh0YWJsZSgndXNlcnMnKSktPndoZXJlKCRidWlsZGVyKTsKICogfQogKiBgYGAKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":313,"slug":"and","name":"and_","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"conditions","type":[{"name":"Condition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"AndCondition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENvbWJpbmUgY29uZGl0aW9ucyB3aXRoIEFORC4KICoKICogQHBhcmFtIENvbmRpdGlvbiAuLi4kY29uZGl0aW9ucyBDb25kaXRpb25zIHRvIGNvbWJpbmUKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":324,"slug":"or","name":"or_","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"conditions","type":[{"name":"Condition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"OrCondition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENvbWJpbmUgY29uZGl0aW9ucyB3aXRoIE9SLgogKgogKiBAcGFyYW0gQ29uZGl0aW9uIC4uLiRjb25kaXRpb25zIENvbmRpdGlvbnMgdG8gY29tYmluZQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":336,"slug":"not","name":"not_","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expression","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"NotCondition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIE5lZ2F0ZSBhIGNvbmRpdGlvbiBvciBleHByZXNzaW9uIHdpdGggTk9ULgogKgogKiBBY2NlcHRzIGJvdGggQ29uZGl0aW9uIGFuZCBFeHByZXNzaW9uIOKAlCBOT1QgYWx3YXlzIHByb2R1Y2VzIGEgYm9vbGVhbiByZXN1bHQuCiAqIENhbiBiZSB1c2VkIGluIFdIRVJFIGNsYXVzZXMgYW5kIFNFTEVDVCBsaXN0cyAodmlhIC0+YXMoJ2FsaWFzJykpLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":348,"slug":"json-contains","name":"json_contains","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"left","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"right","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"OperatorCondition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEpTT05CIGNvbnRhaW5zIGNvbmRpdGlvbiAoQD4pLgogKgogKiBFeGFtcGxlOiBqc29uX2NvbnRhaW5zKGNvbCgnbWV0YWRhdGEnKSwgbGl0ZXJhbF9qc29uKCd7ImNhdGVnb3J5IjogImVsZWN0cm9uaWNzIn0nKSkKICogUHJvZHVjZXM6IG1ldGFkYXRhIEA+ICd7ImNhdGVnb3J5IjogImVsZWN0cm9uaWNzIn0nCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":364,"slug":"json-contained-by","name":"json_contained_by","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"left","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"right","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"OperatorCondition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEpTT05CIGlzIGNvbnRhaW5lZCBieSBjb25kaXRpb24gKDxAKS4KICoKICogRXhhbXBsZToganNvbl9jb250YWluZWRfYnkoY29sKCdtZXRhZGF0YScpLCBsaXRlcmFsX2pzb24oJ3siY2F0ZWdvcnkiOiAiZWxlY3Ryb25pY3MiLCAicHJpY2UiOiAxMDB9JykpCiAqIFByb2R1Y2VzOiBtZXRhZGF0YSA8QCAneyJjYXRlZ29yeSI6ICJlbGVjdHJvbmljcyIsICJwcmljZSI6IDEwMH0nCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":381,"slug":"json-get","name":"json_get","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"key","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"BinaryExpression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEpTT04gZmllbGQgYWNjZXNzIGV4cHJlc3Npb24gKC0+KS4KICogUmV0dXJucyBKU09OLgogKgogKiBFeGFtcGxlOiBqc29uX2dldChjb2woJ21ldGFkYXRhJyksIGxpdGVyYWxfc3RyaW5nKCdjYXRlZ29yeScpKQogKiBQcm9kdWNlczogbWV0YWRhdGEgLT4gJ2NhdGVnb3J5JwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":398,"slug":"json-get-text","name":"json_get_text","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"key","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"BinaryExpression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEpTT04gZmllbGQgYWNjZXNzIGV4cHJlc3Npb24gKC0+PikuCiAqIFJldHVybnMgdGV4dC4KICoKICogRXhhbXBsZToganNvbl9nZXRfdGV4dChjb2woJ21ldGFkYXRhJyksIGxpdGVyYWxfc3RyaW5nKCduYW1lJykpCiAqIFByb2R1Y2VzOiBtZXRhZGF0YSAtPj4gJ25hbWUnCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":415,"slug":"json-path","name":"json_path","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"path","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"BinaryExpression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEpTT04gcGF0aCBhY2Nlc3MgZXhwcmVzc2lvbiAoIz4pLgogKiBSZXR1cm5zIEpTT04uCiAqCiAqIEV4YW1wbGU6IGpzb25fcGF0aChjb2woJ21ldGFkYXRhJyksIGxpdGVyYWxfc3RyaW5nKCd7Y2F0ZWdvcnksbmFtZX0nKSkKICogUHJvZHVjZXM6IG1ldGFkYXRhICM+ICd7Y2F0ZWdvcnksbmFtZX0nCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":432,"slug":"json-path-text","name":"json_path_text","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"path","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"BinaryExpression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEpTT04gcGF0aCBhY2Nlc3MgZXhwcmVzc2lvbiAoIz4+KS4KICogUmV0dXJucyB0ZXh0LgogKgogKiBFeGFtcGxlOiBqc29uX3BhdGhfdGV4dChjb2woJ21ldGFkYXRhJyksIGxpdGVyYWxfc3RyaW5nKCd7Y2F0ZWdvcnksbmFtZX0nKSkKICogUHJvZHVjZXM6IG1ldGFkYXRhICM+PiAne2NhdGVnb3J5LG5hbWV9JwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":448,"slug":"json-exists","name":"json_exists","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"key","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"OperatorCondition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEpTT05CIGtleSBleGlzdHMgY29uZGl0aW9uICg\/KS4KICoKICogRXhhbXBsZToganNvbl9leGlzdHMoY29sKCdtZXRhZGF0YScpLCBsaXRlcmFsX3N0cmluZygnY2F0ZWdvcnknKSkKICogUHJvZHVjZXM6IG1ldGFkYXRhID8gJ2NhdGVnb3J5JwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":464,"slug":"json-exists-any","name":"json_exists_any","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"keys","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"OperatorCondition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEpTT05CIGFueSBrZXkgZXhpc3RzIGNvbmRpdGlvbiAoP3wpLgogKgogKiBFeGFtcGxlOiBqc29uX2V4aXN0c19hbnkoY29sKCdtZXRhZGF0YScpLCBhcnJheV9leHByKFtsaXRlcmFsKCdjYXRlZ29yeScpLCBsaXRlcmFsKCduYW1lJyldKSkKICogUHJvZHVjZXM6IG1ldGFkYXRhID98IGFycmF5WydjYXRlZ29yeScsICduYW1lJ10KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":480,"slug":"json-exists-all","name":"json_exists_all","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"keys","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"OperatorCondition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEpTT05CIGFsbCBrZXlzIGV4aXN0IGNvbmRpdGlvbiAoPyYpLgogKgogKiBFeGFtcGxlOiBqc29uX2V4aXN0c19hbGwoY29sKCdtZXRhZGF0YScpLCBhcnJheV9leHByKFtsaXRlcmFsKCdjYXRlZ29yeScpLCBsaXRlcmFsKCduYW1lJyldKSkKICogUHJvZHVjZXM6IG1ldGFkYXRhID8mIGFycmF5WydjYXRlZ29yeScsICduYW1lJ10KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":496,"slug":"array-contains","name":"array_contains","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"left","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"right","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"OperatorCondition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBhcnJheSBjb250YWlucyBjb25kaXRpb24gKEA+KS4KICoKICogRXhhbXBsZTogYXJyYXlfY29udGFpbnMoY29sKCd0YWdzJyksIGFycmF5X2V4cHIoW2xpdGVyYWwoJ3NhbGUnKV0pKQogKiBQcm9kdWNlczogdGFncyBAPiBBUlJBWVsnc2FsZSddCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":512,"slug":"array-contained-by","name":"array_contained_by","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"left","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"right","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"OperatorCondition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBhcnJheSBpcyBjb250YWluZWQgYnkgY29uZGl0aW9uICg8QCkuCiAqCiAqIEV4YW1wbGU6IGFycmF5X2NvbnRhaW5lZF9ieShjb2woJ3RhZ3MnKSwgYXJyYXlfZXhwcihbbGl0ZXJhbCgnc2FsZScpLCBsaXRlcmFsKCdmZWF0dXJlZCcpLCBsaXRlcmFsKCduZXcnKV0pKQogKiBQcm9kdWNlczogdGFncyA8QCBBUlJBWVsnc2FsZScsICdmZWF0dXJlZCcsICduZXcnXQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":528,"slug":"array-overlap","name":"array_overlap","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"left","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"right","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"OperatorCondition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBhcnJheSBvdmVybGFwIGNvbmRpdGlvbiAoJiYpLgogKgogKiBFeGFtcGxlOiBhcnJheV9vdmVybGFwKGNvbCgndGFncycpLCBhcnJheV9leHByKFtsaXRlcmFsKCdzYWxlJyksIGxpdGVyYWwoJ2ZlYXR1cmVkJyldKSkKICogUHJvZHVjZXM6IHRhZ3MgJiYgQVJSQVlbJ3NhbGUnLCAnZmVhdHVyZWQnXQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":546,"slug":"regex-match","name":"regex_match","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"pattern","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"OperatorCondition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBPU0lYIHJlZ2V4IG1hdGNoIGNvbmRpdGlvbiAofikuCiAqIENhc2Utc2Vuc2l0aXZlLgogKgogKiBFeGFtcGxlOiByZWdleF9tYXRjaChjb2woJ2VtYWlsJyksIGxpdGVyYWxfc3RyaW5nKCcuKkBnbWFpbFxcLmNvbScpKQogKgogKiBQcm9kdWNlczogZW1haWwgfiAnLipAZ21haWxcLmNvbScKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":564,"slug":"regex-imatch","name":"regex_imatch","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"pattern","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"OperatorCondition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBPU0lYIHJlZ2V4IG1hdGNoIGNvbmRpdGlvbiAofiopLgogKiBDYXNlLWluc2Vuc2l0aXZlLgogKgogKiBFeGFtcGxlOiByZWdleF9pbWF0Y2goY29sKCdlbWFpbCcpLCBsaXRlcmFsX3N0cmluZygnLipAZ21haWxcXC5jb20nKSkKICoKICogUHJvZHVjZXM6IGVtYWlsIH4qICcuKkBnbWFpbFwuY29tJwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":582,"slug":"not-regex-match","name":"not_regex_match","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"pattern","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"OperatorCondition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBPU0lYIHJlZ2V4IG5vdCBtYXRjaCBjb25kaXRpb24gKCF+KS4KICogQ2FzZS1zZW5zaXRpdmUuCiAqCiAqIEV4YW1wbGU6IG5vdF9yZWdleF9tYXRjaChjb2woJ2VtYWlsJyksIGxpdGVyYWxfc3RyaW5nKCcuKkBzcGFtXFwuY29tJykpCiAqCiAqIFByb2R1Y2VzOiBlbWFpbCAhfiAnLipAc3BhbVwuY29tJwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":600,"slug":"not-regex-imatch","name":"not_regex_imatch","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"pattern","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"OperatorCondition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBPU0lYIHJlZ2V4IG5vdCBtYXRjaCBjb25kaXRpb24gKCF+KikuCiAqIENhc2UtaW5zZW5zaXRpdmUuCiAqCiAqIEV4YW1wbGU6IG5vdF9yZWdleF9pbWF0Y2goY29sKCdlbWFpbCcpLCBsaXRlcmFsX3N0cmluZygnLipAc3BhbVxcLmNvbScpKQogKgogKiBQcm9kdWNlczogZW1haWwgIX4qICcuKkBzcGFtXC5jb20nCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":616,"slug":"text-search-match","name":"text_search_match","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"document","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"query","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"OperatorCondition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGZ1bGwtdGV4dCBzZWFyY2ggbWF0Y2ggY29uZGl0aW9uIChAQCkuCiAqCiAqIEV4YW1wbGU6IHRleHRfc2VhcmNoX21hdGNoKGNvbCgnZG9jdW1lbnQnKSwgZnVuYygndG9fdHNxdWVyeScsIFtsaXRlcmFsKCdlbmdsaXNoJyksIGxpdGVyYWwoJ2hlbGxvICYgd29ybGQnKV0pKQogKiBQcm9kdWNlczogZG9jdW1lbnQgQEAgdG9fdHNxdWVyeSgnZW5nbGlzaCcsICdoZWxsbyAmIHdvcmxkJykKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":33,"slug":"sql-parser","name":"sql_parser","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"Parser","namespace":"Flow\\PostgreSql","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":39,"slug":"sql-parse","name":"sql_parse","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"sql","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":"ParsedQuery","namespace":"Flow\\PostgreSql","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":49,"slug":"sql-fingerprint","name":"sql_fingerprint","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"sql","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":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFJldHVybnMgYSBmaW5nZXJwcmludCBvZiB0aGUgZ2l2ZW4gU1FMIHF1ZXJ5LgogKiBMaXRlcmFsIHZhbHVlcyBhcmUgbm9ybWFsaXplZCBzbyB0aGV5IHdvbid0IGFmZmVjdCB0aGUgZmluZ2VycHJpbnQuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":60,"slug":"sql-normalize","name":"sql_normalize","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"sql","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":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIE5vcm1hbGl6ZSBTUUwgcXVlcnkgYnkgcmVwbGFjaW5nIGxpdGVyYWwgdmFsdWVzIGFuZCBuYW1lZCBwYXJhbWV0ZXJzIHdpdGggcG9zaXRpb25hbCBwYXJhbWV0ZXJzLgogKiBXSEVSRSBpZCA9IDppZCB3aWxsIGJlIGNoYW5nZWQgaW50byBXSEVSRSBpZCA9ICQxCiAqIFdIRVJFIGlkID0gMSB3aWxsIGJlIGNoYW5nZWQgaW50byBXSEVSRSBpZCA9ICQxLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":70,"slug":"sql-normalize-utility","name":"sql_normalize_utility","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"sql","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":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIE5vcm1hbGl6ZSB1dGlsaXR5IFNRTCBzdGF0ZW1lbnRzIChEREwgbGlrZSBDUkVBVEUsIEFMVEVSLCBEUk9QKS4KICogVGhpcyBoYW5kbGVzIERETCBzdGF0ZW1lbnRzIGRpZmZlcmVudGx5IGZyb20gcGdfbm9ybWFsaXplKCkgd2hpY2ggaXMgb3B0aW1pemVkIGZvciBETUwuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":81,"slug":"sql-split","name":"sql_split","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"sql","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":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFNwbGl0IHN0cmluZyB3aXRoIG11bHRpcGxlIFNRTCBzdGF0ZW1lbnRzIGludG8gYXJyYXkgb2YgaW5kaXZpZHVhbCBzdGF0ZW1lbnRzLgogKgogKiBAcmV0dXJuIGFycmF5PHN0cmluZz4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":90,"slug":"sql-deparse-options","name":"sql_deparse_options","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"DeparseOptions","namespace":"Flow\\PostgreSql","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBEZXBhcnNlT3B0aW9ucyBmb3IgY29uZmlndXJpbmcgU1FMIGZvcm1hdHRpbmcuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":104,"slug":"sql-deparse","name":"sql_deparse","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"query","type":[{"name":"ParsedQuery","namespace":"Flow\\PostgreSql","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"options","type":[{"name":"DeparseOptions","namespace":"Flow\\PostgreSql","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENvbnZlcnQgYSBQYXJzZWRRdWVyeSBBU1QgYmFjayB0byBTUUwgc3RyaW5nLgogKgogKiBXaGVuIGNhbGxlZCB3aXRob3V0IG9wdGlvbnMsIHJldHVybnMgdGhlIFNRTCBhcyBhIHNpbXBsZSBzdHJpbmcuCiAqIFdoZW4gY2FsbGVkIHdpdGggRGVwYXJzZU9wdGlvbnMsIGFwcGxpZXMgZm9ybWF0dGluZyAocHJldHR5LXByaW50aW5nLCBpbmRlbnRhdGlvbiwgZXRjLikuCiAqCiAqIEB0aHJvd3MgXFJ1bnRpbWVFeGNlcHRpb24gaWYgZGVwYXJzaW5nIGZhaWxzCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":120,"slug":"sql-format","name":"sql_format","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"sql","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":"options","type":[{"name":"DeparseOptions","namespace":"Flow\\PostgreSql","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFBhcnNlIGFuZCBmb3JtYXQgU1FMIHF1ZXJ5IHdpdGggcHJldHR5IHByaW50aW5nLgogKgogKiBUaGlzIGlzIGEgY29udmVuaWVuY2UgZnVuY3Rpb24gdGhhdCBwYXJzZXMgU1FMIGFuZCByZXR1cm5zIGl0IGZvcm1hdHRlZC4KICoKICogQHBhcmFtIHN0cmluZyAkc3FsIFRoZSBTUUwgcXVlcnkgdG8gZm9ybWF0CiAqIEBwYXJhbSBudWxsfERlcGFyc2VPcHRpb25zICRvcHRpb25zIEZvcm1hdHRpbmcgb3B0aW9ucyAoZGVmYXVsdHMgdG8gcHJldHR5LXByaW50IGVuYWJsZWQpCiAqCiAqIEB0aHJvd3MgXFJ1bnRpbWVFeGNlcHRpb24gaWYgcGFyc2luZyBvciBkZXBhcnNpbmcgZmFpbHMKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":132,"slug":"sql-summary","name":"sql_summary","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"sql","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":"options","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":"truncateLimit","type":[{"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":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEdlbmVyYXRlIGEgc3VtbWFyeSBvZiBwYXJzZWQgcXVlcmllcyBpbiBwcm90b2J1ZiBmb3JtYXQuCiAqIFVzZWZ1bCBmb3IgcXVlcnkgbW9uaXRvcmluZyBhbmQgbG9nZ2luZyB3aXRob3V0IGZ1bGwgQVNUIG92ZXJoZWFkLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":147,"slug":"sql-to-paginated-query","name":"sql_to_paginated_query","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"sql","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":"limit","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":"offset","type":[{"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":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFRyYW5zZm9ybSBhIFNRTCBxdWVyeSBpbnRvIGEgcGFnaW5hdGVkIHF1ZXJ5IHdpdGggTElNSVQgYW5kIE9GRlNFVC4KICoKICogQHBhcmFtIHN0cmluZyAkc3FsIFRoZSBTUUwgcXVlcnkgdG8gcGFnaW5hdGUKICogQHBhcmFtIGludCAkbGltaXQgTWF4aW11bSBudW1iZXIgb2Ygcm93cyB0byByZXR1cm4KICogQHBhcmFtIGludCAkb2Zmc2V0IE51bWJlciBvZiByb3dzIHRvIHNraXAgKHJlcXVpcmVzIE9SREVSIEJZIGluIHF1ZXJ5KQogKgogKiBAcmV0dXJuIHN0cmluZyBUaGUgcGFnaW5hdGVkIFNRTCBxdWVyeQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":164,"slug":"sql-to-limited-query","name":"sql_to_limited_query","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"sql","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":"limit","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":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFRyYW5zZm9ybSBhIFNRTCBxdWVyeSB0byBsaW1pdCByZXN1bHRzIHRvIGEgc3BlY2lmaWMgbnVtYmVyIG9mIHJvd3MuCiAqCiAqIEBwYXJhbSBzdHJpbmcgJHNxbCBUaGUgU1FMIHF1ZXJ5IHRvIGxpbWl0CiAqIEBwYXJhbSBpbnQgJGxpbWl0IE1heGltdW0gbnVtYmVyIG9mIHJvd3MgdG8gcmV0dXJuCiAqCiAqIEByZXR1cm4gc3RyaW5nIFRoZSBsaW1pdGVkIFNRTCBxdWVyeQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":183,"slug":"sql-to-count-query","name":"sql_to_count_query","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"sql","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":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFRyYW5zZm9ybSBhIFNRTCBxdWVyeSBpbnRvIGEgQ09VTlQgcXVlcnkgZm9yIHBhZ2luYXRpb24uCiAqCiAqIFdyYXBzIHRoZSBxdWVyeSBpbjogU0VMRUNUIENPVU5UKCopIEZST00gKC4uLikgQVMgX2NvdW50X3N1YnEKICogUmVtb3ZlcyBPUkRFUiBCWSBhbmQgTElNSVQvT0ZGU0VUIGZyb20gdGhlIGlubmVyIHF1ZXJ5LgogKgogKiBAcGFyYW0gc3RyaW5nICRzcWwgVGhlIFNRTCBxdWVyeSB0byB0cmFuc2Zvcm0KICoKICogQHJldHVybiBzdHJpbmcgVGhlIENPVU5UIHF1ZXJ5CiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":205,"slug":"sql-to-keyset-query","name":"sql_to_keyset_query","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"sql","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":"limit","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":"columns","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":"cursor","type":[{"name":"array","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFRyYW5zZm9ybSBhIFNRTCBxdWVyeSBpbnRvIGEga2V5c2V0IChjdXJzb3ItYmFzZWQpIHBhZ2luYXRlZCBxdWVyeS4KICoKICogTW9yZSBlZmZpY2llbnQgdGhhbiBPRkZTRVQgZm9yIGxhcmdlIGRhdGFzZXRzIC0gdXNlcyBpbmRleGVkIFdIRVJFIGNvbmRpdGlvbnMuCiAqIEF1dG9tYXRpY2FsbHkgZGV0ZWN0cyBleGlzdGluZyBxdWVyeSBwYXJhbWV0ZXJzIGFuZCBhcHBlbmRzIGtleXNldCBwbGFjZWhvbGRlcnMgYXQgdGhlIGVuZC4KICoKICogQHBhcmFtIHN0cmluZyAkc3FsIFRoZSBTUUwgcXVlcnkgdG8gcGFnaW5hdGUgKG11c3QgaGF2ZSBPUkRFUiBCWSkKICogQHBhcmFtIGludCAkbGltaXQgTWF4aW11bSBudW1iZXIgb2Ygcm93cyB0byByZXR1cm4KICogQHBhcmFtIGxpc3Q8S2V5c2V0Q29sdW1uPiAkY29sdW1ucyBDb2x1bW5zIGZvciBrZXlzZXQgcGFnaW5hdGlvbiAobXVzdCBtYXRjaCBPUkRFUiBCWSkKICogQHBhcmFtIG51bGx8bGlzdDxudWxsfGJvb2x8ZmxvYXR8aW50fHN0cmluZz4gJGN1cnNvciBWYWx1ZXMgZnJvbSBsYXN0IHJvdyBvZiBwcmV2aW91cyBwYWdlIChudWxsIGZvciBmaXJzdCBwYWdlKQogKgogKiBAcmV0dXJuIHN0cmluZyBUaGUgcGFnaW5hdGVkIFNRTCBxdWVyeQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":220,"slug":"sql-keyset-column","name":"sql_keyset_column","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"column","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":"order","type":[{"name":"SortOrder","namespace":"Flow\\PostgreSql\\AST\\Transformers","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\PostgreSql\\AST\\Transformers\\SortOrder::..."}],"return_type":[{"name":"KeysetColumn","namespace":"Flow\\PostgreSql\\AST\\Transformers","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEtleXNldENvbHVtbiBmb3Iga2V5c2V0IHBhZ2luYXRpb24uCiAqCiAqIEBwYXJhbSBzdHJpbmcgJGNvbHVtbiBDb2x1bW4gbmFtZSAoY2FuIGluY2x1ZGUgdGFibGUgYWxpYXMgbGlrZSAidS5pZCIpCiAqIEBwYXJhbSBTb3J0T3JkZXIgJG9yZGVyIFNvcnQgb3JkZXIgKEFTQyBvciBERVNDKQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":229,"slug":"sql-query-columns","name":"sql_query_columns","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"query","type":[{"name":"ParsedQuery","namespace":"Flow\\PostgreSql","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Columns","namespace":"Flow\\PostgreSql\\Extractors","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEV4dHJhY3QgY29sdW1ucyBmcm9tIGEgcGFyc2VkIFNRTCBxdWVyeS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":238,"slug":"sql-query-tables","name":"sql_query_tables","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"query","type":[{"name":"ParsedQuery","namespace":"Flow\\PostgreSql","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Tables","namespace":"Flow\\PostgreSql\\Extractors","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEV4dHJhY3QgdGFibGVzIGZyb20gYSBwYXJzZWQgU1FMIHF1ZXJ5LgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":247,"slug":"sql-query-functions","name":"sql_query_functions","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"query","type":[{"name":"ParsedQuery","namespace":"Flow\\PostgreSql","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Functions","namespace":"Flow\\PostgreSql\\Extractors","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEV4dHJhY3QgZnVuY3Rpb25zIGZyb20gYSBwYXJzZWQgU1FMIHF1ZXJ5LgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":256,"slug":"sql-query-order-by","name":"sql_query_order_by","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"query","type":[{"name":"ParsedQuery","namespace":"Flow\\PostgreSql","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"OrderBy","namespace":"Flow\\PostgreSql\\Extractors","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEV4dHJhY3QgT1JERVIgQlkgY2xhdXNlcyBmcm9tIGEgcGFyc2VkIFNRTCBxdWVyeS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":270,"slug":"sql-query-depth","name":"sql_query_depth","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"sql","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":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEdldCB0aGUgbWF4aW11bSBuZXN0aW5nIGRlcHRoIG9mIGEgU1FMIHF1ZXJ5LgogKgogKiBFeGFtcGxlOgogKiAtICJTRUxFQ1QgKiBGUk9NIHQiID0+IDEKICogLSAiU0VMRUNUICogRlJPTSAoU0VMRUNUICogRlJPTSB0KSIgPT4gMgogKiAtICJTRUxFQ1QgKiBGUk9NIChTRUxFQ1QgKiBGUk9NIChTRUxFQ1QgKiBGUk9NIHQpKSIgPT4gMwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":287,"slug":"sql-to-explain","name":"sql_to_explain","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"sql","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":"config","type":[{"name":"ExplainConfig","namespace":"Flow\\PostgreSql\\AST\\Transformers","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFRyYW5zZm9ybSBhIFNRTCBxdWVyeSBpbnRvIGFuIEVYUExBSU4gcXVlcnkuCiAqCiAqIFJldHVybnMgdGhlIG1vZGlmaWVkIFNRTCB3aXRoIEVYUExBSU4gd3JhcHBlZCBhcm91bmQgaXQuCiAqIERlZmF1bHRzIHRvIEVYUExBSU4gQU5BTFlaRSB3aXRoIEpTT04gZm9ybWF0IGZvciBlYXN5IHBhcnNpbmcuCiAqCiAqIEBwYXJhbSBzdHJpbmcgJHNxbCBUaGUgU1FMIHF1ZXJ5IHRvIGV4cGxhaW4KICogQHBhcmFtIG51bGx8RXhwbGFpbkNvbmZpZyAkY29uZmlnIEVYUExBSU4gY29uZmlndXJhdGlvbiAoZGVmYXVsdHMgdG8gZm9yQW5hbHlzaXMoKSkKICoKICogQHJldHVybiBzdHJpbmcgVGhlIEVYUExBSU4gcXVlcnkKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":307,"slug":"sql-explain-config","name":"sql_explain_config","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"analyze","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"verbose","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"costs","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"buffers","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"timing","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"format","type":[{"name":"ExplainFormat","namespace":"Flow\\PostgreSql\\QueryBuilder\\Utility","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\PostgreSql\\QueryBuilder\\Utility\\ExplainFormat::..."}],"return_type":[{"name":"ExplainConfig","namespace":"Flow\\PostgreSql\\AST\\Transformers","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBFeHBsYWluQ29uZmlnIGZvciBjdXN0b21pemluZyBFWFBMQUlOIG9wdGlvbnMuCiAqCiAqIEBwYXJhbSBib29sICRhbmFseXplIFdoZXRoZXIgdG8gYWN0dWFsbHkgZXhlY3V0ZSB0aGUgcXVlcnkgKEFOQUxZWkUpCiAqIEBwYXJhbSBib29sICR2ZXJib3NlIEluY2x1ZGUgdmVyYm9zZSBvdXRwdXQKICogQHBhcmFtIGJvb2wgJGNvc3RzIEluY2x1ZGUgY29zdCBlc3RpbWF0ZXMgKGRlZmF1bHQgdHJ1ZSkKICogQHBhcmFtIGJvb2wgJGJ1ZmZlcnMgSW5jbHVkZSBidWZmZXIgdXNhZ2Ugc3RhdGlzdGljcyAocmVxdWlyZXMgYW5hbHl6ZSkKICogQHBhcmFtIGJvb2wgJHRpbWluZyBJbmNsdWRlIHRpbWluZyBpbmZvcm1hdGlvbiAocmVxdWlyZXMgYW5hbHl6ZSkKICogQHBhcmFtIEV4cGxhaW5Gb3JtYXQgJGZvcm1hdCBPdXRwdXQgZm9ybWF0IChKU09OIHJlY29tbWVuZGVkIGZvciBwYXJzaW5nKQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":329,"slug":"sql-explain-modifier","name":"sql_explain_modifier","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"config","type":[{"name":"ExplainConfig","namespace":"Flow\\PostgreSql\\AST\\Transformers","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ExplainModifier","namespace":"Flow\\PostgreSql\\AST\\Transformers","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBFeHBsYWluTW9kaWZpZXIgZm9yIHRyYW5zZm9ybWluZyBxdWVyaWVzIGludG8gRVhQTEFJTiBxdWVyaWVzLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":342,"slug":"sql-explain-parse","name":"sql_explain_parse","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"jsonOutput","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":"Plan","namespace":"Flow\\PostgreSql\\Explain\\Plan","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFBhcnNlIEVYUExBSU4gSlNPTiBvdXRwdXQgaW50byBhIFBsYW4gb2JqZWN0LgogKgogKiBAcGFyYW0gc3RyaW5nICRqc29uT3V0cHV0IFRoZSBKU09OIG91dHB1dCBmcm9tIEVYUExBSU4gKEZPUk1BVCBKU09OKQogKgogKiBAcmV0dXJuIFBsYW4gVGhlIHBhcnNlZCBleGVjdXRpb24gcGxhbgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":355,"slug":"sql-analyze","name":"sql_analyze","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"plan","type":[{"name":"Plan","namespace":"Flow\\PostgreSql\\Explain\\Plan","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"PlanAnalyzer","namespace":"Flow\\PostgreSql\\Explain\\Analyzer","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHBsYW4gYW5hbHl6ZXIgZm9yIGFuYWx5emluZyBFWFBMQUlOIHBsYW5zLgogKgogKiBAcGFyYW0gUGxhbiAkcGxhbiBUaGUgZXhlY3V0aW9uIHBsYW4gdG8gYW5hbHl6ZQogKgogKiBAcmV0dXJuIFBsYW5BbmFseXplciBUaGUgYW5hbHl6ZXIgZm9yIGV4dHJhY3RpbmcgaW5zaWdodHMKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/client.php","start_line_in_file":46,"slug":"pgsql-connection","name":"pgsql_connection","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"connectionString","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":"ConnectionParameters","namespace":"Flow\\PostgreSql\\Client","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBjb25uZWN0aW9uIHBhcmFtZXRlcnMgZnJvbSBhIGNvbm5lY3Rpb24gc3RyaW5nLgogKgogKiBBY2NlcHRzIGxpYnBxLXN0eWxlIGNvbm5lY3Rpb24gc3RyaW5nczoKICogLSBLZXktdmFsdWUgZm9ybWF0OiAiaG9zdD1sb2NhbGhvc3QgcG9ydD01NDMyIGRibmFtZT1teWRiIHVzZXI9bXl1c2VyIHBhc3N3b3JkPXNlY3JldCIKICogLSBVUkkgZm9ybWF0OiAicG9zdGdyZXNxbDovL3VzZXI6cGFzc3dvcmRAbG9jYWxob3N0OjU0MzIvZGJuYW1lIgogKgogKiBAZXhhbXBsZQogKiAkcGFyYW1zID0gcGdzcWxfY29ubmVjdGlvbignaG9zdD1sb2NhbGhvc3QgZGJuYW1lPW15ZGInKTsKICogJHBhcmFtcyA9IHBnc3FsX2Nvbm5lY3Rpb24oJ3Bvc3RncmVzcWw6Ly91c2VyOnBhc3NAbG9jYWxob3N0L215ZGInKTsKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/client.php","start_line_in_file":68,"slug":"pgsql-connection-dsn","name":"pgsql_connection_dsn","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"dsn","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":"ConnectionParameters","namespace":"Flow\\PostgreSql\\Client","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBjb25uZWN0aW9uIHBhcmFtZXRlcnMgZnJvbSBhIERTTiBzdHJpbmcuCiAqCiAqIFBhcnNlcyBzdGFuZGFyZCBQb3N0Z3JlU1FMIERTTiBmb3JtYXQgY29tbW9ubHkgdXNlZCBpbiBlbnZpcm9ubWVudCB2YXJpYWJsZXMKICogKGUuZy4sIERBVEFCQVNFX1VSTCkuIFN1cHBvcnRzIHBvc3RncmVzOi8vLCBwb3N0Z3Jlc3FsOi8vLCBhbmQgcGdzcWw6Ly8gc2NoZW1lcy4KICoKICogQHBhcmFtIHN0cmluZyAkZHNuIERTTiBzdHJpbmcgaW4gZm9ybWF0OiBwb3N0Z3JlczovL3VzZXI6cGFzc3dvcmRAaG9zdDpwb3J0L2RhdGFiYXNlP29wdGlvbnMKICoKICogQHRocm93cyBDbGllbnRcRHNuUGFyc2VyRXhjZXB0aW9uIElmIHRoZSBEU04gY2Fubm90IGJlIHBhcnNlZAogKgogKiBAZXhhbXBsZQogKiAkcGFyYW1zID0gcGdzcWxfY29ubmVjdGlvbl9kc24oJ3Bvc3RncmVzOi8vbXl1c2VyOnNlY3JldEBsb2NhbGhvc3Q6NTQzMi9teWRiJyk7CiAqICRwYXJhbXMgPSBwZ3NxbF9jb25uZWN0aW9uX2RzbigncG9zdGdyZXNxbDovL3VzZXI6cGFzc0BkYi5leGFtcGxlLmNvbS9hcHA\/c3NsbW9kZT1yZXF1aXJlJyk7CiAqICRwYXJhbXMgPSBwZ3NxbF9jb25uZWN0aW9uX2RzbigncGdzcWw6Ly91c2VyOnBhc3NAbG9jYWxob3N0L215ZGInKTsgLy8gU3ltZm9ueS9Eb2N0cmluZSBmb3JtYXQKICogJHBhcmFtcyA9IHBnc3FsX2Nvbm5lY3Rpb25fZHNuKGdldGVudignREFUQUJBU0VfVVJMJykpOwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/client.php","start_line_in_file":95,"slug":"pgsql-connection-params","name":"pgsql_connection_params","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"database","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":"host","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'localhost'"},{"name":"port","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"5432"},{"name":"user","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":"password","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":"options","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"ConnectionParameters","namespace":"Flow\\PostgreSql\\Client","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBjb25uZWN0aW9uIHBhcmFtZXRlcnMgZnJvbSBpbmRpdmlkdWFsIHZhbHVlcy4KICoKICogQWxsb3dzIHNwZWNpZnlpbmcgY29ubmVjdGlvbiBwYXJhbWV0ZXJzIGluZGl2aWR1YWxseSBmb3IgYmV0dGVyIHR5cGUgc2FmZXR5CiAqIGFuZCBJREUgc3VwcG9ydC4KICoKICogQHBhcmFtIHN0cmluZyAkZGF0YWJhc2UgRGF0YWJhc2UgbmFtZSAocmVxdWlyZWQpCiAqIEBwYXJhbSBzdHJpbmcgJGhvc3QgSG9zdG5hbWUgKGRlZmF1bHQ6IGxvY2FsaG9zdCkKICogQHBhcmFtIGludCAkcG9ydCBQb3J0IG51bWJlciAoZGVmYXVsdDogNTQzMikKICogQHBhcmFtIG51bGx8c3RyaW5nICR1c2VyIFVzZXJuYW1lIChvcHRpb25hbCkKICogQHBhcmFtIG51bGx8c3RyaW5nICRwYXNzd29yZCBQYXNzd29yZCAob3B0aW9uYWwpCiAqIEBwYXJhbSBhcnJheTxzdHJpbmcsIHN0cmluZz4gJG9wdGlvbnMgQWRkaXRpb25hbCBsaWJwcSBvcHRpb25zCiAqCiAqIEBleGFtcGxlCiAqICRwYXJhbXMgPSBwZ3NxbF9jb25uZWN0aW9uX3BhcmFtcygKICogICAgIGRhdGFiYXNlOiAnbXlkYicsCiAqICAgICBob3N0OiAnbG9jYWxob3N0JywKICogICAgIHVzZXI6ICdteXVzZXInLAogKiAgICAgcGFzc3dvcmQ6ICdzZWNyZXQnLAogKiApOwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/client.php","start_line_in_file":126,"slug":"pgsql-client","name":"pgsql_client","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"params","type":[{"name":"ConnectionParameters","namespace":"Flow\\PostgreSql\\Client","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"valueConverters","type":[{"name":"ValueConverters","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"context","type":[{"name":"Context","namespace":"Flow\\PostgreSql\\Client","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Client","namespace":"Flow\\PostgreSql\\Client","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBvc3RncmVTUUwgY2xpZW50IHVzaW5nIGV4dC1wZ3NxbC4KICoKICogVGhlIGNsaWVudCBjb25uZWN0cyBpbW1lZGlhdGVseSBhbmQgaXMgcmVhZHkgdG8gZXhlY3V0ZSBxdWVyaWVzLgogKgogKiBAcGFyYW0gQ2xpZW50XENvbm5lY3Rpb25QYXJhbWV0ZXJzICRwYXJhbXMgQ29ubmVjdGlvbiBwYXJhbWV0ZXJzCiAqIEBwYXJhbSBudWxsfFZhbHVlQ29udmVydGVycyAkdmFsdWVDb252ZXJ0ZXJzIEN1c3RvbSB0eXBlIGNvbnZlcnRlcnMgKG9wdGlvbmFsKQogKiBAcGFyYW0gbnVsbHxDb250ZXh0ICRjb250ZXh0IEJhc2UgbWFwcGVyIENvbnRleHQg4oCUIHRoZSBDbGllbnQgZW5yaWNoZXMgaXQgd2l0aCBzcWwvcGFyYW1ldGVycy9zZWxmIHBlciBxdWVyeSBiZWZvcmUgaGFuZGluZyBpdCB0byBSb3dNYXBwZXI6Om1hcCgpCiAqCiAqIEB0aHJvd3MgQ29ubmVjdGlvbkV4Y2VwdGlvbiBJZiBjb25uZWN0aW9uIGZhaWxzCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/client.php","start_line_in_file":143,"slug":"postgresql-context","name":"postgresql_context","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"data","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"catalog","type":[{"name":"Catalog","namespace":"Flow\\PostgreSql\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Context","namespace":"Flow\\PostgreSql\\Client","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFJvd01hcHBlciBDb250ZXh0IHNlZWRlZCB3aXRoIHVzZXItc3VwcGxpZWQga2V5L3ZhbHVlIGRhdGEgYW5kIGFuIG9wdGlvbmFsIENhdGFsb2cuCiAqCiAqIFRoZSBDb250ZXh0IGlzIGxhdGVyIGVucmljaGVkIHdpdGggYSBRdWVyeSAoc3FsICsgcGFyYW1ldGVycykgYW5kIHRoZSBleGVjdXRpbmcgQ2xpZW50IGJ5IHRoZQogKiBQb3N0Z3JlU1FMIENsaWVudCBiZWZvcmUgYmVpbmcgaGFuZGVkIHRvIFJvd01hcHBlcjo6bWFwKCkuCiAqCiAqIEBwYXJhbSBhcnJheTxzdHJpbmcsIG1peGVkPiAkZGF0YSBVc2VyLXN1cHBsaWVkIGtleS92YWx1ZSBwYWlycwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/client.php","start_line_in_file":176,"slug":"postgresql-telemetry-options","name":"postgresql_telemetry_options","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"traceQueries","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"transactionSpans","type":[{"name":"TransactionSpanMode","namespace":"Flow\\PostgreSql\\Client\\Telemetry","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\PostgreSql\\Client\\Telemetry\\TransactionSpanMode::..."},{"name":"collectMetrics","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"logQueries","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"maxQueryLength","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"1000"},{"name":"includeParameters","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"maxParameters","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"10"},{"name":"maxParameterLength","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"100"}],"return_type":[{"name":"PostgreSqlTelemetryOptions","namespace":"Flow\\PostgreSql\\Client\\Telemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSB0ZWxlbWV0cnkgb3B0aW9ucyBmb3IgUG9zdGdyZVNRTCBjbGllbnQgaW5zdHJ1bWVudGF0aW9uLgogKgogKiBDb250cm9scyB3aGljaCB0ZWxlbWV0cnkgc2lnbmFscyAodHJhY2VzLCBtZXRyaWNzLCBsb2dzKSBhcmUgZW5hYmxlZAogKiBhbmQgaG93IHF1ZXJ5IGluZm9ybWF0aW9uIGlzIGNhcHR1cmVkLgogKgogKiBAcGFyYW0gYm9vbCAkdHJhY2VRdWVyaWVzIENyZWF0ZSBzcGFucyBmb3IgcXVlcnkgZXhlY3V0aW9uIChkZWZhdWx0OiB0cnVlKQogKiBAcGFyYW0gVHJhbnNhY3Rpb25TcGFuTW9kZSAkdHJhbnNhY3Rpb25TcGFucyBIb3cgdHJhbnNhY3Rpb25zIGFyZSB0cmFjZWQ6IEdST1VQRUQgKGRlZmF1bHQpLCBQRVJfT1BFUkFUSU9OIG9yIE9GRgogKiBAcGFyYW0gYm9vbCAkY29sbGVjdE1ldHJpY3MgQ29sbGVjdCBkdXJhdGlvbiBhbmQgcm93IGNvdW50IG1ldHJpY3MgKGRlZmF1bHQ6IHRydWUpCiAqIEBwYXJhbSBib29sICRsb2dRdWVyaWVzIExvZyBleGVjdXRlZCBxdWVyaWVzIChkZWZhdWx0OiBmYWxzZSkKICogQHBhcmFtIG51bGx8aW50ICRtYXhRdWVyeUxlbmd0aCBNYXhpbXVtIHF1ZXJ5IHRleHQgbGVuZ3RoIGluIHRlbGVtZXRyeSAoZGVmYXVsdDogMTAwMCwgbnVsbCA9IHVubGltaXRlZCkKICogQHBhcmFtIGJvb2wgJGluY2x1ZGVQYXJhbWV0ZXJzIEluY2x1ZGUgcXVlcnkgcGFyYW1ldGVycyBpbiB0ZWxlbWV0cnkgKGRlZmF1bHQ6IGZhbHNlLCBzZWN1cml0eSBjb25zaWRlcmF0aW9uKQogKgogKiBAZXhhbXBsZQogKiAvLyBEZWZhdWx0IG9wdGlvbnMgKHRyYWNlcyBhbmQgbWV0cmljcyBlbmFibGVkKQogKiAkb3B0aW9ucyA9IHBvc3RncmVzcWxfdGVsZW1ldHJ5X29wdGlvbnMoKTsKICoKICogLy8gRW5hYmxlIHF1ZXJ5IGxvZ2dpbmcKICogJG9wdGlvbnMgPSBwb3N0Z3Jlc3FsX3RlbGVtZXRyeV9vcHRpb25zKGxvZ1F1ZXJpZXM6IHRydWUpOwogKgogKiAvLyBNZXRyaWNzIG9ubHksIG5vIHNwYW5zCiAqICRvcHRpb25zID0gcG9zdGdyZXNxbF90ZWxlbWV0cnlfb3B0aW9ucygKICogICAgIHRyYWNlUXVlcmllczogZmFsc2UsCiAqICAgICB0cmFuc2FjdGlvblNwYW5zOiBUcmFuc2FjdGlvblNwYW5Nb2RlOjpPRkYsCiAqICAgICBjb2xsZWN0TWV0cmljczogdHJ1ZSwKICogKTsKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/client.php","start_line_in_file":214,"slug":"postgresql-telemetry-config","name":"postgresql_telemetry_config","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"telemetry","type":[{"name":"Telemetry","namespace":"Flow\\Telemetry","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"clock","type":[{"name":"ClockInterface","namespace":"Psr\\Clock","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"options","type":[{"name":"PostgreSqlTelemetryOptions","namespace":"Flow\\PostgreSql\\Client\\Telemetry","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"PostgreSqlTelemetryConfig","namespace":"Flow\\PostgreSql\\Client\\Telemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSB0ZWxlbWV0cnkgY29uZmlndXJhdGlvbiBmb3IgUG9zdGdyZVNRTCBjbGllbnQuCiAqCiAqIEJ1bmRsZXMgdGVsZW1ldHJ5IGluc3RhbmNlLCBjbG9jaywgYW5kIG9wdGlvbnMgbmVlZGVkIHRvIGluc3RydW1lbnQgYSBQb3N0Z3JlU1FMIGNsaWVudC4KICoKICogQHBhcmFtIFRlbGVtZXRyeSAkdGVsZW1ldHJ5IFRoZSB0ZWxlbWV0cnkgaW5zdGFuY2UKICogQHBhcmFtIENsb2NrSW50ZXJmYWNlICRjbG9jayBDbG9jayBmb3IgdGltZXN0YW1wcwogKiBAcGFyYW0gbnVsbHxQb3N0Z3JlU3FsVGVsZW1ldHJ5T3B0aW9ucyAkb3B0aW9ucyBUZWxlbWV0cnkgb3B0aW9ucyAoZGVmYXVsdDogYWxsIGVuYWJsZWQpCiAqCiAqIEBleGFtcGxlCiAqICRjb25maWcgPSBwb3N0Z3Jlc3FsX3RlbGVtZXRyeV9jb25maWcoCiAqICAgICB0ZWxlbWV0cnkocmVzb3VyY2UoWydzZXJ2aWNlLm5hbWUnID0+ICdteS1hcHAnXSkpLAogKiAgICAgbmV3IFN5c3RlbUNsb2NrKCksCiAqICk7CiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/client.php","start_line_in_file":260,"slug":"traceable-postgresql-client","name":"traceable_postgresql_client","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"client","type":[{"name":"Client","namespace":"Flow\\PostgreSql\\Client","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"telemetryConfig","type":[{"name":"PostgreSqlTelemetryConfig","namespace":"Flow\\PostgreSql\\Client\\Telemetry","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"TraceableClient","namespace":"Flow\\PostgreSql\\Client\\Telemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFdyYXAgYSBQb3N0Z3JlU1FMIGNsaWVudCB3aXRoIHRlbGVtZXRyeSBpbnN0cnVtZW50YXRpb24uCiAqCiAqIFJldHVybnMgYSBkZWNvcmF0b3IgdGhhdCBhZGRzIHNwYW5zLCBtZXRyaWNzLCBhbmQgbG9ncyB0byBhbGwKICogcXVlcnkgYW5kIHRyYW5zYWN0aW9uIG9wZXJhdGlvbnMgZm9sbG93aW5nIE9wZW5UZWxlbWV0cnkgY29udmVudGlvbnMuCiAqCiAqIEBwYXJhbSBDbGllbnRcQ2xpZW50ICRjbGllbnQgVGhlIFBvc3RncmVTUUwgY2xpZW50IHRvIGluc3RydW1lbnQKICogQHBhcmFtIFBvc3RncmVTcWxUZWxlbWV0cnlDb25maWcgJHRlbGVtZXRyeUNvbmZpZyBUZWxlbWV0cnkgY29uZmlndXJhdGlvbgogKgogKiBAZXhhbXBsZQogKiAkY2xpZW50ID0gcGdzcWxfY2xpZW50KHBnc3FsX2Nvbm5lY3Rpb24oJ2hvc3Q9bG9jYWxob3N0IGRibmFtZT1teWRiJykpOwogKgogKiAkdHJhY2VhYmxlQ2xpZW50ID0gdHJhY2VhYmxlX3Bvc3RncmVzcWxfY2xpZW50KAogKiAgICAgJGNsaWVudCwKICogICAgIHBvc3RncmVzcWxfdGVsZW1ldHJ5X2NvbmZpZygKICogICAgICAgICB0ZWxlbWV0cnkocmVzb3VyY2UoWydzZXJ2aWNlLm5hbWUnID0+ICdteS1hcHAnXSkpLAogKiAgICAgICAgIG5ldyBTeXN0ZW1DbG9jaygpLAogKiAgICAgICAgIHBvc3RncmVzcWxfdGVsZW1ldHJ5X29wdGlvbnMoCiAqICAgICAgICAgICAgIHRyYWNlUXVlcmllczogdHJ1ZSwKICogICAgICAgICAgICAgdHJhbnNhY3Rpb25TcGFuczogVHJhbnNhY3Rpb25TcGFuTW9kZTo6R1JPVVBFRCwKICogICAgICAgICAgICAgY29sbGVjdE1ldHJpY3M6IHRydWUsCiAqICAgICAgICAgICAgIGxvZ1F1ZXJpZXM6IHRydWUsCiAqICAgICAgICAgICAgIG1heFF1ZXJ5TGVuZ3RoOiA1MDAsCiAqICAgICAgICAgKSwKICogICAgICksCiAqICk7CiAqCiAqIC8vIEFsbCBvcGVyYXRpb25zIG5vdyB0cmFjZWQKICogJHRyYWNlYWJsZUNsaWVudC0+dHJhbnNhY3Rpb24oZnVuY3Rpb24gKENsaWVudCAkY2xpZW50KSB7CiAqICAgICAkdXNlciA9ICRjbGllbnQtPmZldGNoU2luZ2xlKCdTRUxFQ1QgKiBGUk9NIHVzZXJzIFdIRVJFIGlkID0gJDEnLCBbMTIzXSk7CiAqICAgICAkY2xpZW50LT5leGVjdXRlKCdVUERBVEUgdXNlcnMgU0VUIGxhc3RfbG9naW4gPSBOT1coKSBXSEVSRSBpZCA9ICQxJywgWzEyM10pOwogKiB9KTsKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/client.php","start_line_in_file":300,"slug":"constructor-mapper","name":"constructor_mapper","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"class","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":"ConstructorMapper","namespace":"Flow\\PostgreSql\\Client\\RowMapper","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUIG9mIG9iamVjdAogKgogKiBAcGFyYW0gY2xhc3Mtc3RyaW5nPFQ+ICRjbGFzcwogKgogKiBAcmV0dXJuIENvbnN0cnVjdG9yTWFwcGVyPFQ+CiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/client.php","start_line_in_file":315,"slug":"type-mapper","name":"type_mapper","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"type","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":"next","type":[{"name":"RowMapper","namespace":"Flow\\PostgreSql\\Client","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"TypeMapper","namespace":"Flow\\PostgreSql\\Client\\RowMapper","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUVHlwZQogKiBAdGVtcGxhdGUgVE91dAogKgogKiBAcGFyYW0gRmxvd1R5cGU8VFR5cGU+ICR0eXBlCiAqIEBwYXJhbSBudWxsfFJvd01hcHBlcjxUT3V0PiAkbmV4dAogKgogKiBAcmV0dXJuICgkbmV4dCBpcyBudWxsID8gVHlwZU1hcHBlcjxUVHlwZSwgVFR5cGU+IDogVHlwZU1hcHBlcjxUVHlwZSwgVE91dD4pCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/client.php","start_line_in_file":343,"slug":"static-factory-mapper","name":"static_factory_mapper","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"class","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":"method","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":"StaticFactoryMapper","namespace":"Flow\\PostgreSql\\Client\\RowMapper","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHJvdyBtYXBwZXIgYmFja2VkIGJ5IGEgcHVibGljIHN0YXRpYyBmYWN0b3J5IG1ldGhvZC4KICoKICogVGhlIGZhY3RvcnkgbWV0aG9kIG11c3QgYWNjZXB0IGEgc2luZ2xlIGFycmF5PHN0cmluZywgbWl4ZWQ+ICRyb3cgYW5kIHJldHVybgogKiBhbiBpbnN0YW5jZSBvZiB0aGUgdGFyZ2V0IGNsYXNzLiBJZiB5b3VyIGZhY3RvcnkgbmVlZHMgYWNjZXNzIHRvIHRoZSBtYXBwaW5nCiAqIENvbnRleHQgKHNxbC9wYXJhbWV0ZXJzL2NsaWVudC9jYXRhbG9nL3VzZXItZGF0YSksIGltcGxlbWVudCBSb3dNYXBwZXIgZGlyZWN0bHkuCiAqCiAqIEB0ZW1wbGF0ZSBUIG9mIG9iamVjdAogKgogKiBAcGFyYW0gY2xhc3Mtc3RyaW5nPFQ+ICRjbGFzcwogKiBAcGFyYW0gbm9uLWVtcHR5LXN0cmluZyAkbWV0aG9kCiAqCiAqIEByZXR1cm4gU3RhdGljRmFjdG9yeU1hcHBlcjxUPgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/client.php","start_line_in_file":372,"slug":"typed","name":"typed","namespace":"Flow\\PostgreSql\\DSL","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},{"name":"targetType","type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"TypedValue","namespace":"Flow\\PostgreSql\\Client","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFdyYXAgYSB2YWx1ZSB3aXRoIGV4cGxpY2l0IFBvc3RncmVTUUwgdHlwZSBpbmZvcm1hdGlvbiBmb3IgcGFyYW1ldGVyIGJpbmRpbmcuCiAqCiAqIFVzZSB3aGVuIGF1dG8tZGV0ZWN0aW9uIGlzbid0IHN1ZmZpY2llbnQgb3Igd2hlbiB5b3UgbmVlZCB0byBzcGVjaWZ5CiAqIHRoZSBleGFjdCBQb3N0Z3JlU1FMIHR5cGUgKHNpbmNlIG9uZSBQSFAgdHlwZSBjYW4gbWFwIHRvIG11bHRpcGxlIFBvc3RncmVTUUwgdHlwZXMpOgogKiAtIGludCBjb3VsZCBiZSBJTlQyLCBJTlQ0LCBvciBJTlQ4CiAqIC0gc3RyaW5nIGNvdWxkIGJlIFRFWFQsIFZBUkNIQVIsIG9yIENIQVIKICogLSBhcnJheSBtdXN0IGFsd2F5cyB1c2UgdHlwZWQoKSBzaW5jZSBhdXRvLWRldGVjdGlvbiBjYW5ub3QgZGV0ZXJtaW5lIGVsZW1lbnQgdHlwZQogKiAtIERhdGVUaW1lSW50ZXJmYWNlIGNvdWxkIGJlIFRJTUVTVEFNUCBvciBUSU1FU1RBTVBUWgogKiAtIEpzb24gY291bGQgYmUgSlNPTiBvciBKU09OQgogKgogKiBAcGFyYW0gbWl4ZWQgJHZhbHVlIFRoZSB2YWx1ZSB0byBiaW5kCiAqIEBwYXJhbSBWYWx1ZVR5cGUgJHRhcmdldFR5cGUgVGhlIFBvc3RncmVTUUwgdHlwZSB0byBjb252ZXJ0IHRoZSB2YWx1ZSB0bwogKgogKiBAZXhhbXBsZQogKiAkY2xpZW50LT5mZXRjaCgKICogICAgICdTRUxFQ1QgKiBGUk9NIHVzZXJzIFdIRVJFIGlkID0gJDEgQU5EIHRhZ3MgPSAkMicsCiAqICAgICBbCiAqICAgICAgICAgdHlwZWQoJzU1MGU4NDAwLWUyOWItNDFkNC1hNzE2LTQ0NjY1NTQ0MDAwMCcsIFZhbHVlVHlwZTo6VVVJRCksCiAqICAgICAgICAgdHlwZWQoWyd0YWcxJywgJ3RhZzInXSwgVmFsdWVUeXBlOjpURVhUX0FSUkFZKSwKICogICAgIF0KICogKTsKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/client.php","start_line_in_file":386,"slug":"converted-parameters","name":"converted_parameters","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"values","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":"ConvertedParameters","namespace":"Flow\\PostgreSql\\Client","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFBhcmFtZXRlcnMgYWxyZWFkeSBpbiBQb3N0Z3JlU1FMJ3MgdGV4dCBmb3JtLCB3aGljaCBDbGllbnQ6OmV4ZWN1dGUoKSBzZW5kcyB3aXRob3V0IHJ1bm5pbmcgYSBjb252ZXJ0ZXIuCiAqCiAqIEBwYXJhbSBsaXN0PG51bGx8c3RyaW5nPiAkdmFsdWVzCiAqCiAqIEBleGFtcGxlCiAqICRjbGllbnQtPmV4ZWN1dGUoJ1VQREFURSB1c2VycyBTRVQgYWN0aXZlID0gJDEgV0hFUkUgaWQgPSAkMicsIGNvbnZlcnRlZF9wYXJhbWV0ZXJzKFsnZicsICcxJ10pKTsKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":126,"slug":"trace-id","name":"trace_id","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"hex","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"TraceId","namespace":"Flow\\Telemetry\\Context","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFRyYWNlSWQuCiAqCiAqIElmIGEgaGV4IHN0cmluZyBpcyBwcm92aWRlZCwgY3JlYXRlcyBhIFRyYWNlSWQgZnJvbSBpdC4KICogT3RoZXJ3aXNlLCBnZW5lcmF0ZXMgYSBuZXcgcmFuZG9tIFRyYWNlSWQuCiAqCiAqIEBwYXJhbSBudWxsfHN0cmluZyAkaGV4IE9wdGlvbmFsIDMyLWNoYXJhY3RlciBoZXhhZGVjaW1hbCBzdHJpbmcKICoKICogQHRocm93cyBcSW52YWxpZEFyZ3VtZW50RXhjZXB0aW9uIGlmIHRoZSBoZXggc3RyaW5nIGlzIGludmFsaWQKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":146,"slug":"span-id","name":"span_id","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"hex","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"SpanId","namespace":"Flow\\Telemetry\\Context","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFNwYW5JZC4KICoKICogSWYgYSBoZXggc3RyaW5nIGlzIHByb3ZpZGVkLCBjcmVhdGVzIGEgU3BhbklkIGZyb20gaXQuCiAqIE90aGVyd2lzZSwgZ2VuZXJhdGVzIGEgbmV3IHJhbmRvbSBTcGFuSWQuCiAqCiAqIEBwYXJhbSBudWxsfHN0cmluZyAkaGV4IE9wdGlvbmFsIDE2LWNoYXJhY3RlciBoZXhhZGVjaW1hbCBzdHJpbmcKICoKICogQHRocm93cyBcSW52YWxpZEFyZ3VtZW50RXhjZXB0aW9uIGlmIHRoZSBoZXggc3RyaW5nIGlzIGludmFsaWQKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":161,"slug":"baggage","name":"baggage","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"entries","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"Baggage","namespace":"Flow\\Telemetry\\Context","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEJhZ2dhZ2UuCiAqCiAqIEBwYXJhbSBhcnJheTxzdHJpbmcsIHN0cmluZz4gJGVudHJpZXMgSW5pdGlhbCBrZXktdmFsdWUgZW50cmllcwogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":175,"slug":"context","name":"context","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"baggage","type":[{"name":"Baggage","namespace":"Flow\\Telemetry\\Context","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Context","namespace":"Flow\\Telemetry\\Context","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHJvb3QgQ29udGV4dCAobm8gYWN0aXZlIHNwYW4pLgogKgogKiBBIHNwYW4gY3JlYXRlZCBpbiB0aGlzIGNvbnRleHQgYmVjb21lcyBhIG5ldyB0cmFjZSByb290LiBBdHRhY2ggYW4gYWN0aXZlIHNwYW4gd2l0aAogKiBDb250ZXh0Ojp3aXRoQWN0aXZlU3BhbigpIHRvIG1ha2Ugc3Vic2VxdWVudCBzcGFucyBpdHMgY2hpbGRyZW4uCiAqCiAqIEBwYXJhbSBudWxsfEJhZ2dhZ2UgJGJhZ2dhZ2UgT3B0aW9uYWwgQmFnZ2FnZSB0byB1c2UKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":189,"slug":"memory-context-storage","name":"memory_context_storage","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"context","type":[{"name":"Context","namespace":"Flow\\Telemetry\\Context","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"MemoryContextStorage","namespace":"Flow\\Telemetry\\Context","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIE1lbW9yeUNvbnRleHRTdG9yYWdlLgogKgogKiBJbi1tZW1vcnkgY29udGV4dCBzdG9yYWdlIGZvciBzdG9yaW5nIGFuZCByZXRyaWV2aW5nIHRoZSBjdXJyZW50IGNvbnRleHQuCiAqIEEgc2luZ2xlIGluc3RhbmNlIHNob3VsZCBiZSBzaGFyZWQgYWNyb3NzIGFsbCBwcm92aWRlcnMgd2l0aGluIGEgcmVxdWVzdCBsaWZlY3ljbGUuCiAqCiAqIEBwYXJhbSBudWxsfENvbnRleHQgJGNvbnRleHQgT3B0aW9uYWwgaW5pdGlhbCBjb250ZXh0CiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":200,"slug":"resource","name":"resource","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"attributes","type":[{"name":"Attributes","namespace":"Flow\\Telemetry","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"Resource","namespace":"Flow\\Telemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFJlc291cmNlLgogKgogKiBAcGFyYW0gYXJyYXk8c3RyaW5nLCBhcnJheTxhcnJheS1rZXksIG1peGVkPnxib29sfFxEYXRlVGltZUludGVyZmFjZXxmbG9hdHxpbnR8c3RyaW5nfFxUaHJvd2FibGU+fEF0dHJpYnV0ZXMgJGF0dHJpYnV0ZXMgUmVzb3VyY2UgYXR0cmlidXRlcwogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":213,"slug":"span-context","name":"span_context","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"traceId","type":[{"name":"TraceId","namespace":"Flow\\Telemetry\\Context","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"spanId","type":[{"name":"SpanId","namespace":"Flow\\Telemetry\\Context","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"parentSpanId","type":[{"name":"SpanId","namespace":"Flow\\Telemetry\\Context","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"SpanContext","namespace":"Flow\\Telemetry\\Tracer","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFNwYW5Db250ZXh0LgogKgogKiBAcGFyYW0gVHJhY2VJZCAkdHJhY2VJZCBUaGUgdHJhY2UgSUQKICogQHBhcmFtIFNwYW5JZCAkc3BhbklkIFRoZSBzcGFuIElECiAqIEBwYXJhbSBudWxsfFNwYW5JZCAkcGFyZW50U3BhbklkIE9wdGlvbmFsIHBhcmVudCBzcGFuIElECiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":226,"slug":"span-event","name":"span_event","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"name","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":"timestamp","type":[{"name":"DateTimeImmutable","namespace":"","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"attributes","type":[{"name":"Attributes","namespace":"Flow\\Telemetry","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"GenericEvent","namespace":"Flow\\Telemetry\\Tracer","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFNwYW5FdmVudCAoR2VuZXJpY0V2ZW50KSB3aXRoIGFuIGV4cGxpY2l0IHRpbWVzdGFtcC4KICoKICogQHBhcmFtIHN0cmluZyAkbmFtZSBFdmVudCBuYW1lCiAqIEBwYXJhbSBcRGF0ZVRpbWVJbW11dGFibGUgJHRpbWVzdGFtcCBFdmVudCB0aW1lc3RhbXAKICogQHBhcmFtIGFycmF5PHN0cmluZywgYXJyYXk8YXJyYXkta2V5LCBtaXhlZD58Ym9vbHxcRGF0ZVRpbWVJbnRlcmZhY2V8ZmxvYXR8aW50fHN0cmluZ3xcVGhyb3dhYmxlPnxBdHRyaWJ1dGVzICRhdHRyaWJ1dGVzIEV2ZW50IGF0dHJpYnV0ZXMKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":238,"slug":"span-link","name":"span_link","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"context","type":[{"name":"SpanContext","namespace":"Flow\\Telemetry\\Tracer","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"attributes","type":[{"name":"Attributes","namespace":"Flow\\Telemetry","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"SpanLink","namespace":"Flow\\Telemetry\\Tracer","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFNwYW5MaW5rLgogKgogKiBAcGFyYW0gU3BhbkNvbnRleHQgJGNvbnRleHQgVGhlIGxpbmtlZCBzcGFuIGNvbnRleHQKICogQHBhcmFtIGFycmF5PHN0cmluZywgYXJyYXk8YXJyYXkta2V5LCBtaXhlZD58Ym9vbHxcRGF0ZVRpbWVJbnRlcmZhY2V8ZmxvYXR8aW50fHN0cmluZ3xcVGhyb3dhYmxlPnxBdHRyaWJ1dGVzICRhdHRyaWJ1dGVzIExpbmsgYXR0cmlidXRlcwogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":254,"slug":"span-limits","name":"span_limits","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"attributeCountLimit","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"128"},{"name":"eventCountLimit","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"128"},{"name":"linkCountLimit","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"128"},{"name":"attributePerEventCountLimit","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"128"},{"name":"attributePerLinkCountLimit","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"128"},{"name":"attributeValueLengthLimit","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":"SpanLimits","namespace":"Flow\\Telemetry\\Tracer","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBTcGFuTGltaXRzIGNvbmZpZ3VyYXRpb24uCiAqCiAqIEBwYXJhbSBpbnQgJGF0dHJpYnV0ZUNvdW50TGltaXQgTWF4aW11bSBudW1iZXIgb2YgYXR0cmlidXRlcyBwZXIgc3BhbgogKiBAcGFyYW0gaW50ICRldmVudENvdW50TGltaXQgTWF4aW11bSBudW1iZXIgb2YgZXZlbnRzIHBlciBzcGFuCiAqIEBwYXJhbSBpbnQgJGxpbmtDb3VudExpbWl0IE1heGltdW0gbnVtYmVyIG9mIGxpbmtzIHBlciBzcGFuCiAqIEBwYXJhbSBpbnQgJGF0dHJpYnV0ZVBlckV2ZW50Q291bnRMaW1pdCBNYXhpbXVtIG51bWJlciBvZiBhdHRyaWJ1dGVzIHBlciBldmVudAogKiBAcGFyYW0gaW50ICRhdHRyaWJ1dGVQZXJMaW5rQ291bnRMaW1pdCBNYXhpbXVtIG51bWJlciBvZiBhdHRyaWJ1dGVzIHBlciBsaW5rCiAqIEBwYXJhbSBudWxsfGludCAkYXR0cmlidXRlVmFsdWVMZW5ndGhMaW1pdCBNYXhpbXVtIGxlbmd0aCBmb3Igc3RyaW5nIGF0dHJpYnV0ZSB2YWx1ZXMgKG51bGwgPSB1bmxpbWl0ZWQpCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":279,"slug":"log-record-limits","name":"log_record_limits","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"attributeCountLimit","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"128"},{"name":"attributeValueLengthLimit","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":"LogRecordLimits","namespace":"Flow\\Telemetry\\Logger","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBMb2dSZWNvcmRMaW1pdHMgY29uZmlndXJhdGlvbi4KICoKICogQHBhcmFtIGludCAkYXR0cmlidXRlQ291bnRMaW1pdCBNYXhpbXVtIG51bWJlciBvZiBhdHRyaWJ1dGVzIHBlciBsb2cgcmVjb3JkCiAqIEBwYXJhbSBudWxsfGludCAkYXR0cmlidXRlVmFsdWVMZW5ndGhMaW1pdCBNYXhpbXVtIGxlbmd0aCBmb3Igc3RyaW5nIGF0dHJpYnV0ZSB2YWx1ZXMgKG51bGwgPSB1bmxpbWl0ZWQpCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":290,"slug":"metric-limits","name":"metric_limits","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"cardinalityLimit","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"2000"}],"return_type":[{"name":"MetricLimits","namespace":"Flow\\Telemetry\\Meter","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBNZXRyaWNMaW1pdHMgY29uZmlndXJhdGlvbi4KICoKICogQHBhcmFtIGludCAkY2FyZGluYWxpdHlMaW1pdCBNYXhpbXVtIG51bWJlciBvZiB1bmlxdWUgYXR0cmlidXRlIGNvbWJpbmF0aW9ucyBwZXIgaW5zdHJ1bWVudAogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":301,"slug":"void-span-processor","name":"void_span_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"VoidSpanProcessor","namespace":"Flow\\Telemetry\\Provider\\Void","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFZvaWRTcGFuUHJvY2Vzc29yLgogKgogKiBOby1vcCBzcGFuIHByb2Nlc3NvciB0aGF0IGRpc2NhcmRzIGFsbCBkYXRhLgogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":312,"slug":"void-metric-processor","name":"void_metric_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"VoidMetricProcessor","namespace":"Flow\\Telemetry\\Provider\\Void","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFZvaWRNZXRyaWNQcm9jZXNzb3IuCiAqCiAqIE5vLW9wIG1ldHJpYyBwcm9jZXNzb3IgdGhhdCBkaXNjYXJkcyBhbGwgZGF0YS4KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":323,"slug":"void-log-processor","name":"void_log_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"VoidLogProcessor","namespace":"Flow\\Telemetry\\Provider\\Void","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFZvaWRMb2dQcm9jZXNzb3IuCiAqCiAqIE5vLW9wIGxvZyBwcm9jZXNzb3IgdGhhdCBkaXNjYXJkcyBhbGwgZGF0YS4KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":334,"slug":"void-exporter","name":"void_exporter","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"VoidExporter","namespace":"Flow\\Telemetry\\Provider\\Void","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFZvaWRFeHBvcnRlci4KICoKICogTm8tb3AgdW5pZmllZCBleHBvcnRlciB0aGF0IGRpc2NhcmRzIGxvZ3MsIG1ldHJpY3MsIGFuZCBzcGFucy4KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":348,"slug":"memory-exporter","name":"memory_exporter","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"maxEntriesPerSignal","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":"MemoryExporter","namespace":"Flow\\Telemetry\\Provider\\Memory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIE1lbW9yeUV4cG9ydGVyLgogKgogKiBVbmlmaWVkIGV4cG9ydGVyIHRoYXQgc3RvcmVzIGxvZ3MsIG1ldHJpY3MsIGFuZCBzcGFucyBpbiBtZW1vcnkgZm9yIGRpcmVjdCBhY2Nlc3MuCiAqIFVzZWZ1bCBmb3IgdGVzdGluZyBhbmQgaW5zcGVjdGlvbiB3aXRob3V0IHNlcmlhbGl6YXRpb24uCiAqCiAqIEBwYXJhbSBudWxsfGludCAkbWF4RW50cmllc1BlclNpZ25hbCBtYXhpbXVtIGVudHJpZXMgcmV0YWluZWQgcGVyIHNpZ25hbCB0eXBlOyBudWxsIGtlZXBzIGV2ZXJ5dGhpbmcKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":360,"slug":"memory-span-processor","name":"memory_span_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"exporter","type":[{"name":"Exporter","namespace":"Flow\\Telemetry\\Exporter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"errorHandler","type":[{"name":"ErrorHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\ErrorHandler\\ErrorLogHandler::..."}],"return_type":[{"name":"MemorySpanProcessor","namespace":"Flow\\Telemetry\\Provider\\Memory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIE1lbW9yeVNwYW5Qcm9jZXNzb3IuCiAqCiAqIEBwYXJhbSBFeHBvcnRlciAkZXhwb3J0ZXIgVGhlIGV4cG9ydGVyIHRvIHNlbmQgc3BhbnMgdG8KICogQHBhcmFtIEVycm9ySGFuZGxlciAkZXJyb3JIYW5kbGVyIEhhbmRsZXIgZm9yIFRocm93YWJsZXMgcmFpc2VkIGJ5IHRoZSBleHBvcnRlcgogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":374,"slug":"memory-metric-processor","name":"memory_metric_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"exporter","type":[{"name":"Exporter","namespace":"Flow\\Telemetry\\Exporter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"errorHandler","type":[{"name":"ErrorHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\ErrorHandler\\ErrorLogHandler::..."}],"return_type":[{"name":"MemoryMetricProcessor","namespace":"Flow\\Telemetry\\Provider\\Memory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIE1lbW9yeU1ldHJpY1Byb2Nlc3Nvci4KICoKICogQHBhcmFtIEV4cG9ydGVyICRleHBvcnRlciBUaGUgZXhwb3J0ZXIgdG8gc2VuZCBtZXRyaWNzIHRvCiAqIEBwYXJhbSBFcnJvckhhbmRsZXIgJGVycm9ySGFuZGxlciBIYW5kbGVyIGZvciBUaHJvd2FibGVzIHJhaXNlZCBieSB0aGUgZXhwb3J0ZXIKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":388,"slug":"memory-log-processor","name":"memory_log_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"exporter","type":[{"name":"Exporter","namespace":"Flow\\Telemetry\\Exporter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"errorHandler","type":[{"name":"ErrorHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\ErrorHandler\\ErrorLogHandler::..."}],"return_type":[{"name":"MemoryLogProcessor","namespace":"Flow\\Telemetry\\Provider\\Memory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIE1lbW9yeUxvZ1Byb2Nlc3Nvci4KICoKICogQHBhcmFtIEV4cG9ydGVyICRleHBvcnRlciBUaGUgZXhwb3J0ZXIgdG8gc2VuZCBsb2dzIHRvCiAqIEBwYXJhbSBFcnJvckhhbmRsZXIgJGVycm9ySGFuZGxlciBIYW5kbGVyIGZvciBUaHJvd2FibGVzIHJhaXNlZCBieSB0aGUgZXhwb3J0ZXIKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":406,"slug":"tracer-provider","name":"tracer_provider","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"processor","type":[{"name":"SpanProcessor","namespace":"Flow\\Telemetry\\Tracer","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"clock","type":[{"name":"ClockInterface","namespace":"Psr\\Clock","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"contextStorage","type":[{"name":"ContextStorage","namespace":"Flow\\Telemetry\\Context","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"sampler","type":[{"name":"Sampler","namespace":"Flow\\Telemetry\\Tracer\\Sampler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\Tracer\\Sampler\\ParentBasedSampler::..."},{"name":"limits","type":[{"name":"SpanLimits","namespace":"Flow\\Telemetry\\Tracer","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\Tracer\\SpanLimits::..."},{"name":"errorHandler","type":[{"name":"ErrorHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\ErrorHandler\\ErrorLogHandler::..."}],"return_type":[{"name":"TracerProvider","namespace":"Flow\\Telemetry\\Tracer","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFRyYWNlclByb3ZpZGVyLgogKgogKiBAcGFyYW0gU3BhblByb2Nlc3NvciAkcHJvY2Vzc29yIFRoZSBwcm9jZXNzb3IgZm9yIHNwYW5zCiAqIEBwYXJhbSBDbG9ja0ludGVyZmFjZSAkY2xvY2sgVGhlIGNsb2NrIGZvciB0aW1lc3RhbXBzCiAqIEBwYXJhbSBDb250ZXh0U3RvcmFnZSAkY29udGV4dFN0b3JhZ2UgU3RvcmFnZSBmb3IgY29udGV4dCBwcm9wYWdhdGlvbgogKiBAcGFyYW0gU2FtcGxlciAkc2FtcGxlciBTYW1wbGluZyBzdHJhdGVneSBmb3Igc3BhbnMKICogQHBhcmFtIFNwYW5MaW1pdHMgJGxpbWl0cyBMaW1pdHMgZm9yIHNwYW4gYXR0cmlidXRlcywgZXZlbnRzLCBhbmQgbGlua3MKICogQHBhcmFtIEVycm9ySGFuZGxlciAkZXJyb3JIYW5kbGVyIEhhbmRsZXIgZm9yIHJ1bnRpbWUgVGhyb3dhYmxlcyByYWlzZWQgYnkgdGhlIHByb2Nlc3NvcgogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":427,"slug":"logger-provider","name":"logger_provider","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"processor","type":[{"name":"LogProcessor","namespace":"Flow\\Telemetry\\Logger","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"clock","type":[{"name":"ClockInterface","namespace":"Psr\\Clock","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"contextStorage","type":[{"name":"ContextStorage","namespace":"Flow\\Telemetry\\Context","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"limits","type":[{"name":"LogRecordLimits","namespace":"Flow\\Telemetry\\Logger","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\Logger\\LogRecordLimits::..."},{"name":"errorHandler","type":[{"name":"ErrorHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\ErrorHandler\\ErrorLogHandler::..."}],"return_type":[{"name":"LoggerProvider","namespace":"Flow\\Telemetry\\Logger","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIExvZ2dlclByb3ZpZGVyLgogKgogKiBAcGFyYW0gTG9nUHJvY2Vzc29yICRwcm9jZXNzb3IgVGhlIHByb2Nlc3NvciBmb3IgbG9ncwogKiBAcGFyYW0gQ2xvY2tJbnRlcmZhY2UgJGNsb2NrIFRoZSBjbG9jayBmb3IgdGltZXN0YW1wcwogKiBAcGFyYW0gQ29udGV4dFN0b3JhZ2UgJGNvbnRleHRTdG9yYWdlIFN0b3JhZ2UgZm9yIHNwYW4gY29ycmVsYXRpb24KICogQHBhcmFtIExvZ1JlY29yZExpbWl0cyAkbGltaXRzIExpbWl0cyBmb3IgbG9nIHJlY29yZCBhdHRyaWJ1dGVzCiAqIEBwYXJhbSBFcnJvckhhbmRsZXIgJGVycm9ySGFuZGxlciBIYW5kbGVyIGZvciBydW50aW1lIFRocm93YWJsZXMgcmFpc2VkIGJ5IHRoZSBwcm9jZXNzb3IKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":448,"slug":"meter-provider","name":"meter_provider","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"processor","type":[{"name":"MetricProcessor","namespace":"Flow\\Telemetry\\Meter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"clock","type":[{"name":"ClockInterface","namespace":"Psr\\Clock","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"temporality","type":[{"name":"AggregationTemporality","namespace":"Flow\\Telemetry\\Meter","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\Meter\\AggregationTemporality::..."},{"name":"exemplarFilter","type":[{"name":"ExemplarFilter","namespace":"Flow\\Telemetry\\Meter\\Exemplar","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\Meter\\Exemplar\\TraceBasedExemplarFilter::..."},{"name":"limits","type":[{"name":"MetricLimits","namespace":"Flow\\Telemetry\\Meter","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\Meter\\MetricLimits::..."},{"name":"errorHandler","type":[{"name":"ErrorHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\ErrorHandler\\ErrorLogHandler::..."}],"return_type":[{"name":"MeterProvider","namespace":"Flow\\Telemetry\\Meter","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIE1ldGVyUHJvdmlkZXIuCiAqCiAqIEBwYXJhbSBNZXRyaWNQcm9jZXNzb3IgJHByb2Nlc3NvciBUaGUgcHJvY2Vzc29yIGZvciBtZXRyaWNzCiAqIEBwYXJhbSBDbG9ja0ludGVyZmFjZSAkY2xvY2sgVGhlIGNsb2NrIGZvciB0aW1lc3RhbXBzCiAqIEBwYXJhbSBBZ2dyZWdhdGlvblRlbXBvcmFsaXR5ICR0ZW1wb3JhbGl0eSBBZ2dyZWdhdGlvbiB0ZW1wb3JhbGl0eSBmb3IgbWV0cmljcwogKiBAcGFyYW0gRXhlbXBsYXJGaWx0ZXIgJGV4ZW1wbGFyRmlsdGVyIEZpbHRlciBmb3IgZXhlbXBsYXIgc2FtcGxpbmcgKGRlZmF1bHQ6IFRyYWNlQmFzZWRFeGVtcGxhckZpbHRlcikKICogQHBhcmFtIE1ldHJpY0xpbWl0cyAkbGltaXRzIENhcmRpbmFsaXR5IGxpbWl0cyBmb3IgbWV0cmljIGluc3RydW1lbnRzCiAqIEBwYXJhbSBFcnJvckhhbmRsZXIgJGVycm9ySGFuZGxlciBIYW5kbGVyIGZvciBydW50aW1lIFRocm93YWJsZXMgcmFpc2VkIGJ5IHRoZSBwcm9jZXNzb3IKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":471,"slug":"telemetry","name":"telemetry","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"resource","type":[{"name":"Resource","namespace":"Flow\\Telemetry","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"tracerProvider","type":[{"name":"TracerProvider","namespace":"Flow\\Telemetry\\Tracer","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"meterProvider","type":[{"name":"MeterProvider","namespace":"Flow\\Telemetry\\Meter","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"loggerProvider","type":[{"name":"LoggerProvider","namespace":"Flow\\Telemetry\\Logger","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"errorHandler","type":[{"name":"ErrorHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\ErrorHandler\\ErrorLogHandler::..."}],"return_type":[{"name":"Telemetry","namespace":"Flow\\Telemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIG5ldyBUZWxlbWV0cnkgaW5zdGFuY2Ugd2l0aCB0aGUgZ2l2ZW4gcHJvdmlkZXJzLgogKgogKiBJZiBwcm92aWRlcnMgYXJlIG5vdCBzcGVjaWZpZWQsIHZvaWQgcHJvdmlkZXJzIChuby1vcCkgYXJlIHVzZWQuCiAqCiAqIEBwYXJhbSBcRmxvd1xUZWxlbWV0cnlcUmVzb3VyY2UgJHJlc291cmNlIFRoZSByZXNvdXJjZSBkZXNjcmliaW5nIHRoZSBlbnRpdHkgcHJvZHVjaW5nIHRlbGVtZXRyeQogKiBAcGFyYW0gbnVsbHxUcmFjZXJQcm92aWRlciAkdHJhY2VyUHJvdmlkZXIgVGhlIHRyYWNlciBwcm92aWRlciAobnVsbCBmb3Igdm9pZC9kaXNhYmxlZCkKICogQHBhcmFtIG51bGx8TWV0ZXJQcm92aWRlciAkbWV0ZXJQcm92aWRlciBUaGUgbWV0ZXIgcHJvdmlkZXIgKG51bGwgZm9yIHZvaWQvZGlzYWJsZWQpCiAqIEBwYXJhbSBudWxsfExvZ2dlclByb3ZpZGVyICRsb2dnZXJQcm92aWRlciBUaGUgbG9nZ2VyIHByb3ZpZGVyIChudWxsIGZvciB2b2lkL2Rpc2FibGVkKQogKiBAcGFyYW0gRXJyb3JIYW5kbGVyICRlcnJvckhhbmRsZXIgSGFuZGxlciBwcm9wYWdhdGVkIHRvIGRlZmF1bHQgdm9pZCBwcm92aWRlcnMgd2hlbiBleHBsaWNpdCBvbmVzIGFyZSBub3Qgc3VwcGxpZWQKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":507,"slug":"instrumentation-scope","name":"instrumentation_scope","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"name","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":"version","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'unknown'"},{"name":"schemaUrl","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":"attributes","type":[{"name":"Attributes","namespace":"Flow\\Telemetry","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\Attributes::..."}],"return_type":[{"name":"InstrumentationScope","namespace":"Flow\\Telemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBJbnN0cnVtZW50YXRpb25TY29wZS4KICoKICogQHBhcmFtIHN0cmluZyAkbmFtZSBUaGUgaW5zdHJ1bWVudGF0aW9uIHNjb3BlIG5hbWUKICogQHBhcmFtIHN0cmluZyAkdmVyc2lvbiBUaGUgaW5zdHJ1bWVudGF0aW9uIHNjb3BlIHZlcnNpb24KICogQHBhcmFtIG51bGx8c3RyaW5nICRzY2hlbWFVcmwgT3B0aW9uYWwgc2NoZW1hIFVSTAogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":524,"slug":"batching-span-processor","name":"batching_span_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"exporter","type":[{"name":"Exporter","namespace":"Flow\\Telemetry\\Exporter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"batchSize","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"512"},{"name":"errorHandler","type":[{"name":"ErrorHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\ErrorHandler\\ErrorLogHandler::..."}],"return_type":[{"name":"BatchingSpanProcessor","namespace":"Flow\\Telemetry\\Tracer\\Processor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEJhdGNoaW5nU3BhblByb2Nlc3Nvci4KICoKICogQHBhcmFtIEV4cG9ydGVyICRleHBvcnRlciBUaGUgZXhwb3J0ZXIgdG8gc2VuZCBzcGFucyB0bwogKiBAcGFyYW0gaW50ICRiYXRjaFNpemUgTnVtYmVyIG9mIHNwYW5zIHRvIGNvbGxlY3QgYmVmb3JlIGV4cG9ydGluZyAoZGVmYXVsdCA1MTIpCiAqIEBwYXJhbSBFcnJvckhhbmRsZXIgJGVycm9ySGFuZGxlciBIYW5kbGVyIGZvciBUaHJvd2FibGVzIHJhaXNlZCBieSB0aGUgZXhwb3J0ZXIKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":539,"slug":"pass-through-span-processor","name":"pass_through_span_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"exporter","type":[{"name":"Exporter","namespace":"Flow\\Telemetry\\Exporter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"errorHandler","type":[{"name":"ErrorHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\ErrorHandler\\ErrorLogHandler::..."}],"return_type":[{"name":"PassThroughSpanProcessor","namespace":"Flow\\Telemetry\\Tracer\\Processor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBhc3NUaHJvdWdoU3BhblByb2Nlc3Nvci4KICoKICogQHBhcmFtIEV4cG9ydGVyICRleHBvcnRlciBUaGUgZXhwb3J0ZXIgdG8gc2VuZCBzcGFucyB0bwogKiBAcGFyYW0gRXJyb3JIYW5kbGVyICRlcnJvckhhbmRsZXIgSGFuZGxlciBmb3IgVGhyb3dhYmxlcyByYWlzZWQgYnkgdGhlIGV4cG9ydGVyCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":554,"slug":"batching-metric-processor","name":"batching_metric_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"exporter","type":[{"name":"Exporter","namespace":"Flow\\Telemetry\\Exporter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"batchSize","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"512"},{"name":"errorHandler","type":[{"name":"ErrorHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\ErrorHandler\\ErrorLogHandler::..."}],"return_type":[{"name":"BatchingMetricProcessor","namespace":"Flow\\Telemetry\\Meter\\Processor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEJhdGNoaW5nTWV0cmljUHJvY2Vzc29yLgogKgogKiBAcGFyYW0gRXhwb3J0ZXIgJGV4cG9ydGVyIFRoZSBleHBvcnRlciB0byBzZW5kIG1ldHJpY3MgdG8KICogQHBhcmFtIGludCAkYmF0Y2hTaXplIE51bWJlciBvZiBtZXRyaWNzIHRvIGNvbGxlY3QgYmVmb3JlIGV4cG9ydGluZyAoZGVmYXVsdCA1MTIpCiAqIEBwYXJhbSBFcnJvckhhbmRsZXIgJGVycm9ySGFuZGxlciBIYW5kbGVyIGZvciBUaHJvd2FibGVzIHJhaXNlZCBieSB0aGUgZXhwb3J0ZXIKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":569,"slug":"pass-through-metric-processor","name":"pass_through_metric_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"exporter","type":[{"name":"Exporter","namespace":"Flow\\Telemetry\\Exporter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"errorHandler","type":[{"name":"ErrorHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\ErrorHandler\\ErrorLogHandler::..."}],"return_type":[{"name":"PassThroughMetricProcessor","namespace":"Flow\\Telemetry\\Meter\\Processor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBhc3NUaHJvdWdoTWV0cmljUHJvY2Vzc29yLgogKgogKiBAcGFyYW0gRXhwb3J0ZXIgJGV4cG9ydGVyIFRoZSBleHBvcnRlciB0byBzZW5kIG1ldHJpY3MgdG8KICogQHBhcmFtIEVycm9ySGFuZGxlciAkZXJyb3JIYW5kbGVyIEhhbmRsZXIgZm9yIFRocm93YWJsZXMgcmFpc2VkIGJ5IHRoZSBleHBvcnRlcgogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":584,"slug":"batching-log-processor","name":"batching_log_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"exporter","type":[{"name":"Exporter","namespace":"Flow\\Telemetry\\Exporter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"batchSize","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"512"},{"name":"errorHandler","type":[{"name":"ErrorHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\ErrorHandler\\ErrorLogHandler::..."}],"return_type":[{"name":"BatchingLogProcessor","namespace":"Flow\\Telemetry\\Logger\\Processor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEJhdGNoaW5nTG9nUHJvY2Vzc29yLgogKgogKiBAcGFyYW0gRXhwb3J0ZXIgJGV4cG9ydGVyIFRoZSBleHBvcnRlciB0byBzZW5kIGxvZ3MgdG8KICogQHBhcmFtIGludCAkYmF0Y2hTaXplIE51bWJlciBvZiBsb2dzIHRvIGNvbGxlY3QgYmVmb3JlIGV4cG9ydGluZyAoZGVmYXVsdCA1MTIpCiAqIEBwYXJhbSBFcnJvckhhbmRsZXIgJGVycm9ySGFuZGxlciBIYW5kbGVyIGZvciBUaHJvd2FibGVzIHJhaXNlZCBieSB0aGUgZXhwb3J0ZXIKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":599,"slug":"pass-through-log-processor","name":"pass_through_log_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"exporter","type":[{"name":"Exporter","namespace":"Flow\\Telemetry\\Exporter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"errorHandler","type":[{"name":"ErrorHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\ErrorHandler\\ErrorLogHandler::..."}],"return_type":[{"name":"PassThroughLogProcessor","namespace":"Flow\\Telemetry\\Logger\\Processor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBhc3NUaHJvdWdoTG9nUHJvY2Vzc29yLgogKgogKiBAcGFyYW0gRXhwb3J0ZXIgJGV4cG9ydGVyIFRoZSBleHBvcnRlciB0byBzZW5kIGxvZ3MgdG8KICogQHBhcmFtIEVycm9ySGFuZGxlciAkZXJyb3JIYW5kbGVyIEhhbmRsZXIgZm9yIFRocm93YWJsZXMgcmFpc2VkIGJ5IHRoZSBleHBvcnRlcgogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":614,"slug":"pipeline-log-processor","name":"pipeline_log_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"middleware","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":"sink","type":[{"name":"LogSink","namespace":"Flow\\Telemetry\\Logger","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"PipelineLogProcessor","namespace":"Flow\\Telemetry\\Logger\\Processor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBpcGVsaW5lTG9nUHJvY2Vzc29yOiBydW4gZWFjaCBsb2cgZW50cnkgdGhyb3VnaCBhbiBvcmRlcmVkIGNoYWluIG9mCiAqIG1pZGRsZXdhcmUsIHRoZW4gZm9yd2FyZCB0aGUgc3Vydml2b3JzIHRvIGEgc2luZ2xlIHNpbmsuCiAqCiAqIEBwYXJhbSBsaXN0PExvZ01pZGRsZXdhcmU+ICRtaWRkbGV3YXJlIHJ1biBpbiBvcmRlcjsgdGhlIGZpcnN0IHRvIGRyb3AgYW4gZW50cnkgc2hvcnQtY2lyY3VpdHMgdGhlIHJlc3QKICogQHBhcmFtIExvZ1NpbmsgJHNpbmsgdGhlIHRlcm1pbmFsIHByb2Nlc3NvciB0aGF0IGV4cG9ydHMgc3Vydml2aW5nIGVudHJpZXMKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":626,"slug":"enriching-log-middleware","name":"enriching_log_middleware","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"attributes","type":[{"name":"Attributes","namespace":"Flow\\Telemetry","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":"EnrichingLogMiddleware","namespace":"Flow\\Telemetry\\Logger\\Middleware","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBFbnJpY2hpbmdMb2dNaWRkbGV3YXJlIHRoYXQgbWVyZ2VzIGRlZmF1bHQgYXR0cmlidXRlcyBpbnRvIGV2ZXJ5IGxvZwogKiBlbnRyeS4gQXR0cmlidXRlcyBzZXQgYXQgdGhlIGNhbGwgc2l0ZSB3aW4gb3ZlciB0aGVzZSBkZWZhdWx0cy4KICoKICogQHBhcmFtIGFycmF5PHN0cmluZywgYXJyYXk8YXJyYXkta2V5LCBtaXhlZD58Ym9vbHxcRGF0ZVRpbWVJbnRlcmZhY2V8ZmxvYXR8aW50fHN0cmluZ3xcVGhyb3dhYmxlPnxBdHRyaWJ1dGVzICRhdHRyaWJ1dGVzCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":637,"slug":"attribute-filtering-log-middleware","name":"attribute_filtering_log_middleware","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"filter","type":[{"name":"AttributeFilter","namespace":"Flow\\Telemetry\\Filter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"AttributeFilteringLogMiddleware","namespace":"Flow\\Telemetry\\Logger\\Middleware","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBBdHRyaWJ1dGVGaWx0ZXJpbmdMb2dNaWRkbGV3YXJlIHRoYXQgZHJvcHMgbG9nIGVudHJpZXMgbWF0Y2hpbmcgdGhlIGZpbHRlci4KICoKICogQHBhcmFtIEF0dHJpYnV0ZUZpbHRlciAkZmlsdGVyIFRoZSBhdHRyaWJ1dGUgZmlsdGVyIHRvIGFwcGx5CiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":648,"slug":"severity-filtering-log-middleware","name":"severity_filtering_log_middleware","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"minimumSeverity","type":[{"name":"Severity","namespace":"Flow\\Telemetry\\Logger","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\Logger\\Severity::..."}],"return_type":[{"name":"SeverityFilteringLogMiddleware","namespace":"Flow\\Telemetry\\Logger\\Middleware","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFNldmVyaXR5RmlsdGVyaW5nTG9nTWlkZGxld2FyZSB0aGF0IGRyb3BzIGxvZyBlbnRyaWVzIGJlbG93IGEgbWluaW11bSBzZXZlcml0eS4KICoKICogQHBhcmFtIFNldmVyaXR5ICRtaW5pbXVtU2V2ZXJpdHkgTWluaW11bSBzZXZlcml0eSBsZXZlbCAoZGVmYXVsdDogSU5GTykKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":662,"slug":"attribute-rule","name":"attribute_rule","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"path","type":[{"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":"mode","type":[{"name":"MatchMode","namespace":"Flow\\Telemetry\\Filter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"expected","type":[{"name":"DateTimeInterface","namespace":"","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":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"caseSensitive","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":"AttributeRule","namespace":"Flow\\Telemetry\\Filter","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHNpbmdsZSBhdHRyaWJ1dGUtbWF0Y2hpbmcgcnVsZSBmb3IgYW4gQXR0cmlidXRlRmlsdGVyLgogKgogKiBAcGFyYW0gYXJyYXk8c3RyaW5nPnxzdHJpbmcgJHBhdGggYXR0cmlidXRlIHBhdGg6IGEgdG9wLWxldmVsIGtleSwgb3Igc2VnbWVudHMgZGVzY2VuZGluZyBpbnRvIG5lc3RlZCBhcnJheSB2YWx1ZXMKICogQHBhcmFtIE1hdGNoTW9kZSAkbW9kZSBjb21wYXJpc29uIGFwcGxpZWQgYmV0d2VlbiB0aGUgdmFsdWUgYXQgdGhlIHBhdGggYW5kIHRoZSBleHBlY3RlZCB2YWx1ZQogKiBAcGFyYW0gYm9vbHxEYXRlVGltZUludGVyZmFjZXxmbG9hdHxpbnR8c3RyaW5nICRleHBlY3RlZCBleHBlY3RlZCB2YWx1ZSAobXVzdCBiZSBhIHN0cmluZyBmb3IgdGhlIHBhdHRlcm4gbW9kZXMpCiAqIEBwYXJhbSBib29sICRjYXNlU2Vuc2l0aXZlIGFwcGxpZXMgdG8gdGhlIHN1YnN0cmluZyBtb2RlcyBvbmx5IChTVEFSVFNfV0lUSCwgRU5EU19XSVRILCBDT05UQUlOUykKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":675,"slug":"all","name":"all","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"matchers","type":[{"name":"Matcher","namespace":"Flow\\Telemetry\\Filter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"All","namespace":"Flow\\Telemetry\\Filter","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENvbWJpbmUgbWF0Y2hlcnMgc28gdGhhdCBldmVyeSBvbmUgbXVzdCBtYXRjaCAobG9naWNhbCBBTkQpLgogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":684,"slug":"any","name":"any","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"matchers","type":[{"name":"Matcher","namespace":"Flow\\Telemetry\\Filter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"Any","namespace":"Flow\\Telemetry\\Filter","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENvbWJpbmUgbWF0Y2hlcnMgc28gdGhhdCBhdCBsZWFzdCBvbmUgbXVzdCBtYXRjaCAobG9naWNhbCBPUikuCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":693,"slug":"not","name":"not","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"matcher","type":[{"name":"Matcher","namespace":"Flow\\Telemetry\\Filter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Not","namespace":"Flow\\Telemetry\\Filter","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIE5lZ2F0ZSBhIG1hdGNoZXIgKGxvZ2ljYWwgTk9UKS4KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":712,"slug":"attribute-filter","name":"attribute_filter","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"matcher","type":[{"name":"Matcher","namespace":"Flow\\Telemetry\\Filter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"exclude","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"sources","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[...]"},{"name":"cacheDir","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":"cacheDirPermissions","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"448"}],"return_type":[{"name":"AttributeFilter","namespace":"Flow\\Telemetry\\Filter","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBBdHRyaWJ1dGVGaWx0ZXIgZnJvbSBhIG1hdGNoZXIuCiAqCiAqIEBwYXJhbSBNYXRjaGVyICRtYXRjaGVyIHRoZSBtYXRjaGVyIHRvIGV2YWx1YXRlIGFnYWluc3QgYSBzaWduYWwncyBhdHRyaWJ1dGVzIChjb21wb3NlIHdpdGggYWxsKCksIGFueSgpLCBub3QoKSkKICogQHBhcmFtIGJvb2wgJGV4Y2x1ZGUgd2hlbiB0cnVlIChkZWZhdWx0KSBhIG1hdGNoIGRyb3BzIHRoZSBzaWduYWw7IHdoZW4gZmFsc2Ugb25seSBtYXRjaGluZyBzaWduYWxzIGFyZSBrZXB0CiAqIEBwYXJhbSBsaXN0PEF0dHJpYnV0ZVNvdXJjZT4gJHNvdXJjZXMgd2hpY2ggYXR0cmlidXRlIHNldHMgdG8gaW5zcGVjdCAoc2lnbmFsLCByZXNvdXJjZSBhbmQvb3Igc2NvcGUpOyB0aGUgbWF0Y2hlciBpcwogKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9SLWNvbWJpbmVkIGFjcm9zcyB0aGVtLCBkZWZhdWx0aW5nIHRvIHRoZSBzaWduYWwncyBvd24gYXR0cmlidXRlcwogKiBAcGFyYW0gbnVsbHxzdHJpbmcgJGNhY2hlRGlyIGRpcmVjdG9yeSBmb3IgdGhlIGdlbmVyYXRlZCBtYXRjaGVyIGZpbGUgKGRlZmF1bHRzIHRvIHRoZSBzeXN0ZW0gdGVtcCBkaXJlY3RvcnkpLiBJdCBpcwogKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGByZXF1aXJlYGQsIHNvIGl0IE1VU1QgYmUgdHJ1c3RlZCAtIG5vdCB3cml0YWJsZSBieSB1bnRydXN0ZWQgdXNlcnMuIFByZWZlciBhbgogKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGxpY2F0aW9uLXByaXZhdGUgZGlyZWN0b3J5IG92ZXIgdGhlIHNoYXJlZCBzeXN0ZW0gdGVtcCBpbiBtdWx0aS10ZW5hbnQgZW52aXJvbm1lbnRzLgogKiBAcGFyYW0gaW50ICRjYWNoZURpclBlcm1pc3Npb25zIG1vZGUgYXBwbGllZCB3aGVuIHRoZSBjYWNoZSBkaXJlY3RvcnkgaXMgY3JlYXRlZCAob2N0YWwsIHN1YmplY3QgdG8gdW1hc2s7IGRlZmF1bHRzCiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG8gMDcwMCAtIG93bmVyIG9ubHksIHNpbmNlIHRoZSBkaXJlY3RvcnkgaG9sZHMgYHJlcXVpcmVgZCBQSFApCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":729,"slug":"attribute-filtering-metric-processor","name":"attribute_filtering_metric_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"processor","type":[{"name":"MetricProcessor","namespace":"Flow\\Telemetry\\Meter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"filter","type":[{"name":"AttributeFilter","namespace":"Flow\\Telemetry\\Filter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"AttributeFilteringMetricProcessor","namespace":"Flow\\Telemetry\\Meter\\Processor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBBdHRyaWJ1dGVGaWx0ZXJpbmdNZXRyaWNQcm9jZXNzb3IuCiAqCiAqIEBwYXJhbSBNZXRyaWNQcm9jZXNzb3IgJHByb2Nlc3NvciBUaGUgcHJvY2Vzc29yIHRvIHdyYXAKICogQHBhcmFtIEF0dHJpYnV0ZUZpbHRlciAkZmlsdGVyIFRoZSBhdHRyaWJ1dGUgZmlsdGVyIHRvIGFwcGx5CiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":743,"slug":"attribute-filtering-span-processor","name":"attribute_filtering_span_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"processor","type":[{"name":"SpanProcessor","namespace":"Flow\\Telemetry\\Tracer","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"filter","type":[{"name":"AttributeFilter","namespace":"Flow\\Telemetry\\Filter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"AttributeFilteringSpanProcessor","namespace":"Flow\\Telemetry\\Tracer\\Processor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBBdHRyaWJ1dGVGaWx0ZXJpbmdTcGFuUHJvY2Vzc29yLgogKgogKiBAcGFyYW0gU3BhblByb2Nlc3NvciAkcHJvY2Vzc29yIFRoZSBwcm9jZXNzb3IgdG8gd3JhcAogKiBAcGFyYW0gQXR0cmlidXRlRmlsdGVyICRmaWx0ZXIgVGhlIGF0dHJpYnV0ZSBmaWx0ZXIgdG8gYXBwbHkKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":762,"slug":"console-exporter","name":"console_exporter","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"colors","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"maxLogBodyLength","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"100"},{"name":"logOptions","type":[{"name":"ConsoleLogOptions","namespace":"Flow\\Telemetry\\Provider\\Console","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\Provider\\Console\\ConsoleLogOptions::..."},{"name":"metricOptions","type":[{"name":"ConsoleMetricOptions","namespace":"Flow\\Telemetry\\Provider\\Console","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\Provider\\Console\\ConsoleMetricOptions::..."},{"name":"spanOptions","type":[{"name":"ConsoleSpanOptions","namespace":"Flow\\Telemetry\\Provider\\Console","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\Provider\\Console\\ConsoleSpanOptions::..."}],"return_type":[{"name":"ConsoleExporter","namespace":"Flow\\Telemetry\\Provider\\Console","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHVuaWZpZWQgQ29uc29sZUV4cG9ydGVyIGZvciBsb2dzLCBtZXRyaWNzLCBhbmQgc3BhbnMuCiAqCiAqIE91dHB1dHMgdGVsZW1ldHJ5IHRvIHRoZSBjb25zb2xlIHdpdGggQVNDSUkgdGFibGUgZm9ybWF0dGluZyBhbmQgb3B0aW9uYWwgQU5TSSBjb2xvcnMuCiAqCiAqIEBwYXJhbSBib29sICRjb2xvcnMgV2hldGhlciB0byB1c2UgQU5TSSBjb2xvcnMgKGRlZmF1bHQ6IHRydWUpCiAqIEBwYXJhbSBudWxsfGludCAkbWF4TG9nQm9keUxlbmd0aCBNYXhpbXVtIGxlbmd0aCBmb3IgbG9nIGJvZHkrYXR0cmlidXRlcyBjb2x1bW4gKG51bGwgPSBubyBsaW1pdCkKICogQHBhcmFtIENvbnNvbGVMb2dPcHRpb25zICRsb2dPcHRpb25zIERpc3BsYXkgb3B0aW9ucyBmb3IgbG9nIHJlY29yZHMKICogQHBhcmFtIENvbnNvbGVNZXRyaWNPcHRpb25zICRtZXRyaWNPcHRpb25zIERpc3BsYXkgb3B0aW9ucyBmb3IgbWV0cmljcwogKiBAcGFyYW0gQ29uc29sZVNwYW5PcHRpb25zICRzcGFuT3B0aW9ucyBEaXNwbGF5IG9wdGlvbnMgZm9yIHNwYW5zCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":776,"slug":"console-span-options","name":"console_span_options","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"ConsoleSpanOptions","namespace":"Flow\\Telemetry\\Provider\\Console","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBDb25zb2xlU3Bhbk9wdGlvbnMgd2l0aCBhbGwgZGlzcGxheSBvcHRpb25zIGVuYWJsZWQgKGRlZmF1bHQgYmVoYXZpb3IpLgogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":785,"slug":"console-span-options-minimal","name":"console_span_options_minimal","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"ConsoleSpanOptions","namespace":"Flow\\Telemetry\\Provider\\Console","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBDb25zb2xlU3Bhbk9wdGlvbnMgd2l0aCBtaW5pbWFsIGRpc3BsYXkgKGxlZ2FjeSBjb21wYWN0IGZvcm1hdCkuCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":794,"slug":"console-log-options","name":"console_log_options","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"ConsoleLogOptions","namespace":"Flow\\Telemetry\\Provider\\Console","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBDb25zb2xlTG9nT3B0aW9ucyB3aXRoIGFsbCBkaXNwbGF5IG9wdGlvbnMgZW5hYmxlZCAoZGVmYXVsdCBiZWhhdmlvcikuCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":803,"slug":"console-log-options-minimal","name":"console_log_options_minimal","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"ConsoleLogOptions","namespace":"Flow\\Telemetry\\Provider\\Console","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBDb25zb2xlTG9nT3B0aW9ucyB3aXRoIG1pbmltYWwgZGlzcGxheSAobGVnYWN5IGNvbXBhY3QgZm9ybWF0KS4KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":812,"slug":"console-metric-options","name":"console_metric_options","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"ConsoleMetricOptions","namespace":"Flow\\Telemetry\\Provider\\Console","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBDb25zb2xlTWV0cmljT3B0aW9ucyB3aXRoIGFsbCBkaXNwbGF5IG9wdGlvbnMgZW5hYmxlZCAoZGVmYXVsdCBiZWhhdmlvcikuCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":821,"slug":"console-metric-options-minimal","name":"console_metric_options_minimal","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"ConsoleMetricOptions","namespace":"Flow\\Telemetry\\Provider\\Console","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBDb25zb2xlTWV0cmljT3B0aW9ucyB3aXRoIG1pbmltYWwgZGlzcGxheSAobGVnYWN5IGNvbXBhY3QgZm9ybWF0KS4KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":830,"slug":"always-on-exemplar-filter","name":"always_on_exemplar_filter","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"AlwaysOnExemplarFilter","namespace":"Flow\\Telemetry\\Meter\\Exemplar","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBBbHdheXNPbkV4ZW1wbGFyRmlsdGVyLgogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":839,"slug":"always-off-exemplar-filter","name":"always_off_exemplar_filter","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"AlwaysOffExemplarFilter","namespace":"Flow\\Telemetry\\Meter\\Exemplar","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBBbHdheXNPZmZFeGVtcGxhckZpbHRlci4KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":848,"slug":"trace-based-exemplar-filter","name":"trace_based_exemplar_filter","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"TraceBasedExemplarFilter","namespace":"Flow\\Telemetry\\Meter\\Exemplar","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFRyYWNlQmFzZWRFeGVtcGxhckZpbHRlci4KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":857,"slug":"always-on-sampler","name":"always_on_sampler","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"AlwaysOnSampler","namespace":"Flow\\Telemetry\\Tracer\\Sampler","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBBbHdheXNPblNhbXBsZXIuIFJlY29yZHMgYW5kIHNhbXBsZXMgZXZlcnkgc3Bhbi4KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":866,"slug":"always-off-sampler","name":"always_off_sampler","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"AlwaysOffSampler","namespace":"Flow\\Telemetry\\Tracer\\Sampler","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBBbHdheXNPZmZTYW1wbGVyLiBEcm9wcyBldmVyeSBzcGFuLgogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":877,"slug":"trace-id-ratio-based-sampler","name":"trace_id_ratio_based_sampler","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"ratio","type":[{"name":"float","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"TraceIdRatioBasedSampler","namespace":"Flow\\Telemetry\\Tracer\\Sampler","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFRyYWNlSWRSYXRpb0Jhc2VkU2FtcGxlci4gU2FtcGxlcyBhIGRldGVybWluaXN0aWMgZnJhY3Rpb24gb2YgdHJhY2VzLgogKgogKiBAcGFyYW0gZmxvYXQgJHJhdGlvIFNhbXBsaW5nIHByb2JhYmlsaXR5IGJldHdlZW4gMC4wIGFuZCAxLjAKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":889,"slug":"parent-based-sampler","name":"parent_based_sampler","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"root","type":[{"name":"Sampler","namespace":"Flow\\Telemetry\\Tracer\\Sampler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\Tracer\\Sampler\\AlwaysOnSampler::..."}],"return_type":[{"name":"ParentBasedSampler","namespace":"Flow\\Telemetry\\Tracer\\Sampler","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBhcmVudEJhc2VkU2FtcGxlci4gSG9ub3JzIHRoZSBwYXJlbnQgc3BhbidzIHNhbXBsaW5nIGRlY2lzaW9uLCBmYWxsaW5nCiAqIGJhY2sgdG8gdGhlIHJvb3Qgc2FtcGxlciBmb3Igc3BhbnMgd2l0aG91dCBhIHBhcmVudC4KICoKICogQHBhcmFtIFNhbXBsZXIgJHJvb3QgU2FtcGxlciB1c2VkIGZvciByb290IHNwYW5zIChubyBwYXJlbnQpCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":905,"slug":"attribute-matching-sampler","name":"attribute_matching_sampler","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"filter","type":[{"name":"AttributeFilter","namespace":"Flow\\Telemetry\\Filter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"delegate","type":[{"name":"Sampler","namespace":"Flow\\Telemetry\\Tracer\\Sampler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\Tracer\\Sampler\\AlwaysOnSampler::..."}],"return_type":[{"name":"AttributeMatchingSampler","namespace":"Flow\\Telemetry\\Tracer\\Sampler","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBBdHRyaWJ1dGVNYXRjaGluZ1NhbXBsZXIuIERyb3BzIHNwYW5zIHdob3NlIHN0YXJ0LXRpbWUgYXR0cmlidXRlcyBtYXRjaAogKiB0aGUgZmlsdGVyIChvciBrZWVwcyBPTkxZIG1hdGNoaW5nIHNwYW5zIHdoZW4gdGhlIGZpbHRlcidzIGV4Y2x1ZGUgaXMgZmFsc2UpLCBhbmQKICogZGVmZXJzIGFsbCBvdGhlciBzcGFucyB0byB0aGUgZGVsZWdhdGUgc2FtcGxlci4KICoKICogT25seSBhdHRyaWJ1dGVzIGF2YWlsYWJsZSBhdCBzcGFuIHN0YXJ0IGFyZSB2aXNpYmxlOyBhdHRyaWJ1dGVzIGFkZGVkIGxhdGVyIGFyZSBub3QuCiAqCiAqIEBwYXJhbSBBdHRyaWJ1dGVGaWx0ZXIgJGZpbHRlciBUaGUgYXR0cmlidXRlIGZpbHRlciBldmFsdWF0ZWQgYWdhaW5zdCB0aGUgc3BhbidzIHN0YXJ0IGF0dHJpYnV0ZXMKICogQHBhcmFtIFNhbXBsZXIgJGRlbGVnYXRlIFNhbXBsZXIgdGhhdCBkZWNpZGVzIHNwYW5zIHdoaWNoIGRvIG5vdCBtYXRjaCAoZGVmYXVsdDogQWx3YXlzT25TYW1wbGVyKQogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":919,"slug":"propagation-context","name":"propagation_context","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"spanContext","type":[{"name":"SpanContext","namespace":"Flow\\Telemetry\\Tracer","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"baggage","type":[{"name":"Baggage","namespace":"Flow\\Telemetry\\Context","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"PropagationContext","namespace":"Flow\\Telemetry\\Propagation","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFByb3BhZ2F0aW9uQ29udGV4dC4KICoKICogQHBhcmFtIG51bGx8U3BhbkNvbnRleHQgJHNwYW5Db250ZXh0IE9wdGlvbmFsIHNwYW4gY29udGV4dAogKiBAcGFyYW0gbnVsbHxCYWdnYWdlICRiYWdnYWdlIE9wdGlvbmFsIGJhZ2dhZ2UKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":930,"slug":"array-carrier","name":"array_carrier","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"data","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"ArrayCarrier","namespace":"Flow\\Telemetry\\Propagation","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBBcnJheUNhcnJpZXIuCiAqCiAqIEBwYXJhbSBhcnJheTxzdHJpbmcsIHN0cmluZz4gJGRhdGEgSW5pdGlhbCBjYXJyaWVyIGRhdGEKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":939,"slug":"superglobal-carrier","name":"superglobal_carrier","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"SuperglobalCarrier","namespace":"Flow\\Telemetry\\Propagation","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFN1cGVyZ2xvYmFsQ2Fycmllci4KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":948,"slug":"w3c-trace-context","name":"w3c_trace_context","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"W3CTraceContext","namespace":"Flow\\Telemetry\\Propagation","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFczQ1RyYWNlQ29udGV4dCBwcm9wYWdhdG9yLgogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":957,"slug":"w3c-baggage","name":"w3c_baggage","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"W3CBaggage","namespace":"Flow\\Telemetry\\Propagation","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFczQ0JhZ2dhZ2UgcHJvcGFnYXRvci4KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":968,"slug":"composite-propagator","name":"composite_propagator","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"propagators","type":[{"name":"Propagator","namespace":"Flow\\Telemetry\\Propagation","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"CompositePropagator","namespace":"Flow\\Telemetry\\Propagation","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENvbXBvc2l0ZVByb3BhZ2F0b3IuCiAqCiAqIEBwYXJhbSBQcm9wYWdhdG9yIC4uLiRwcm9wYWdhdG9ycyBUaGUgcHJvcGFnYXRvcnMgdG8gY29tYmluZQogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":979,"slug":"chain-detector","name":"chain_detector","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"detectors","type":[{"name":"ResourceDetector","namespace":"Flow\\Telemetry\\Resource","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"ChainDetector","namespace":"Flow\\Telemetry\\Resource\\Detector","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENoYWluRGV0ZWN0b3IuCiAqCiAqIEBwYXJhbSBSZXNvdXJjZURldGVjdG9yIC4uLiRkZXRlY3RvcnMgVGhlIGRldGVjdG9ycyB0byBjaGFpbgogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":988,"slug":"os-detector","name":"os_detector","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"OsDetector","namespace":"Flow\\Telemetry\\Resource\\Detector","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBPc0RldGVjdG9yLgogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":997,"slug":"host-detector","name":"host_detector","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"HostDetector","namespace":"Flow\\Telemetry\\Resource\\Detector","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEhvc3REZXRlY3Rvci4KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":1006,"slug":"process-detector","name":"process_detector","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"ProcessDetector","namespace":"Flow\\Telemetry\\Resource\\Detector","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFByb2Nlc3NEZXRlY3Rvci4KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":1015,"slug":"environment-detector","name":"environment_detector","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"EnvironmentDetector","namespace":"Flow\\Telemetry\\Resource\\Detector","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBFbnZpcm9ubWVudERldGVjdG9yLgogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":1024,"slug":"composer-detector","name":"composer_detector","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"ComposerDetector","namespace":"Flow\\Telemetry\\Resource\\Detector","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENvbXBvc2VyRGV0ZWN0b3IuCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":1036,"slug":"git-detector","name":"git_detector","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"workingDirectory","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":"gitBinary","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'git'"}],"return_type":[{"name":"GitDetector","namespace":"Flow\\Telemetry\\Resource\\Detector","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEdpdERldGVjdG9yLgogKgogKiBAcGFyYW0gbnVsbHxzdHJpbmcgJHdvcmtpbmdEaXJlY3RvcnkgRGlyZWN0b3J5IHRvIHJ1biBnaXQgaW4gKGRlZmF1bHQ6IGN1cnJlbnQgd29ya2luZyBkaXJlY3RvcnkpCiAqIEBwYXJhbSBzdHJpbmcgJGdpdEJpbmFyeSBQYXRoIHRvIHRoZSBnaXQgYmluYXJ5IChkZWZhdWx0OiAiZ2l0IiwgcmVzb2x2ZWQgZnJvbSAkUEFUSCkKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":1047,"slug":"manual-detector","name":"manual_detector","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"attributes","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":"ManualDetector","namespace":"Flow\\Telemetry\\Resource\\Detector","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIE1hbnVhbERldGVjdG9yLgogKgogKiBAcGFyYW0gYXJyYXk8c3RyaW5nLCBhcnJheTxhcnJheS1rZXksIG1peGVkPnxib29sfFxEYXRlVGltZUludGVyZmFjZXxmbG9hdHxpbnR8c3RyaW5nfFxUaHJvd2FibGU+ICRhdHRyaWJ1dGVzIFJlc291cmNlIGF0dHJpYnV0ZXMKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":1059,"slug":"caching-detector","name":"caching_detector","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"detector","type":[{"name":"ResourceDetector","namespace":"Flow\\Telemetry\\Resource","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"cachePath","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"CachingDetector","namespace":"Flow\\Telemetry\\Resource\\Detector","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENhY2hpbmdEZXRlY3Rvci4KICoKICogQHBhcmFtIFJlc291cmNlRGV0ZWN0b3IgJGRldGVjdG9yIFRoZSBkZXRlY3RvciB0byB3cmFwCiAqIEBwYXJhbSBudWxsfHN0cmluZyAkY2FjaGVQYXRoIENhY2hlIGZpbGUgcGF0aCAoZGVmYXVsdDogc3lzX2dldF90ZW1wX2RpcigpL2Zsb3dfdGVsZW1ldHJ5X3Jlc291cmNlLmNhY2hlKQogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":1070,"slug":"resource-detector","name":"resource_detector","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"detectors","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"ChainDetector","namespace":"Flow\\Telemetry\\Resource\\Detector","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHJlc291cmNlIGRldGVjdG9yIGNoYWluLgogKgogKiBAcGFyYW0gYXJyYXk8UmVzb3VyY2VEZXRlY3Rvcj4gJGRldGVjdG9ycyBPcHRpb25hbCBjdXN0b20gZGV0ZWN0b3JzIChlbXB0eSA9IHVzZSBkZWZhdWx0cykKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":1089,"slug":"error-log-handler","name":"error_log_handler","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"messageType","type":[{"name":"ErrorLogMessageType","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\ErrorHandler\\ErrorLogMessageType::..."},{"name":"expandNewlines","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"messagePrefix","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'[flow-telemetry]'"}],"return_type":[{"name":"ErrorLogHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSB0aGUgZGVmYXVsdCBFcnJvckxvZ0hhbmRsZXIuIFdyaXRlcyB2aWEgUEhQJ3MgZXJyb3JfbG9nKCkuCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":1102,"slug":"stream-error-handler","name":"stream_error_handler","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"destination","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":"filePermissions","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"420"},{"name":"createDirectories","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"messagePrefix","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'[flow-telemetry]'"}],"return_type":[{"name":"StreamHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFN0cmVhbUhhbmRsZXIuIEFwcGVuZHMgZm9ybWF0dGVkIFRocm93YWJsZXMgKG9uZSBwZXIgbGluZSkgdG8gYSBmaWxlCiAqIHBhdGggb3IgcGhwOi8vIHN0cmVhbSB3cmFwcGVyLgogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":1115,"slug":"syslog-error-handler","name":"syslog_error_handler","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"ident","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'flow-telemetry'"},{"name":"facility","type":[{"name":"SyslogFacility","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\ErrorHandler\\SyslogFacility::..."},{"name":"logOpts","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"1"},{"name":"severity","type":[{"name":"SyslogSeverity","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\ErrorHandler\\SyslogSeverity::..."}],"return_type":[{"name":"SyslogHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFN5c2xvZ0hhbmRsZXIuIFdyaXRlcyB2aWEgb3BlbmxvZy9zeXNsb2cvY2xvc2Vsb2cuCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":1128,"slug":"udp-syslog-error-handler","name":"udp_syslog_error_handler","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"host","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":"port","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"514"},{"name":"ident","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'flow-telemetry'"},{"name":"facility","type":[{"name":"SyslogFacility","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\ErrorHandler\\SyslogFacility::..."},{"name":"severity","type":[{"name":"SyslogSeverity","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\ErrorHandler\\SyslogSeverity::..."}],"return_type":[{"name":"UdpSyslogHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFVkcFN5c2xvZ0hhbmRsZXIuIFNlbmRzIFJGQyA1NDI0LXN0eWxlIHN5c2xvZyBmcmFtZXMgb3ZlciBVRFAuCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":1142,"slug":"composite-error-handler","name":"composite_error_handler","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"handlers","type":[{"name":"ErrorHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"CompositeErrorHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEZhbiBlcnJvcnMgb3V0IHRvIG11bHRpcGxlIGhhbmRsZXJzLgogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":1151,"slug":"null-error-handler","name":"null_error_handler","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"NullErrorHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIERpc2NhcmQgZXZlcnkgZXJyb3IuIFVzZSBvbmx5IGluIHRlc3RzIG9yIGZvciBleHBsaWNpdCBzaWxlbmNlLgogKi8="},{"repository_path":"src\/lib\/azure-sdk\/src\/Flow\/Azure\/SDK\/DSL\/functions.php","start_line_in_file":29,"slug":"azurite-url-factory","name":"azurite_url_factory","namespace":"Flow\\Azure\\SDK\\DSL","parameters":[{"name":"host","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'localhost'"},{"name":"port","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'10000'"},{"name":"secure","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":"AzuriteURLFactory","namespace":"Flow\\Azure\\SDK\\BlobService\\URLFactory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"AZURE_SDK","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/azure-sdk\/src\/Flow\/Azure\/SDK\/DSL\/functions.php","start_line_in_file":38,"slug":"azure-shared-key-authorization-factory","name":"azure_shared_key_authorization_factory","namespace":"Flow\\Azure\\SDK\\DSL","parameters":[{"name":"account","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":"key","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":"SharedKeyFactory","namespace":"Flow\\Azure\\SDK\\AuthorizationFactory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"AZURE_SDK","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/azure-sdk\/src\/Flow\/Azure\/SDK\/DSL\/functions.php","start_line_in_file":48,"slug":"azure-blob-service-config","name":"azure_blob_service_config","namespace":"Flow\\Azure\\SDK\\DSL","parameters":[{"name":"account","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":"container","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":"Configuration","namespace":"Flow\\Azure\\SDK\\BlobService","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"AZURE_SDK","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/azure-sdk\/src\/Flow\/Azure\/SDK\/DSL\/functions.php","start_line_in_file":54,"slug":"azure-url-factory","name":"azure_url_factory","namespace":"Flow\\Azure\\SDK\\DSL","parameters":[{"name":"host","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'blob.core.windows.net'"}],"return_type":[{"name":"AzureURLFactory","namespace":"Flow\\Azure\\SDK\\BlobService\\URLFactory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"AZURE_SDK","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/azure-sdk\/src\/Flow\/Azure\/SDK\/DSL\/functions.php","start_line_in_file":60,"slug":"azure-http-factory","name":"azure_http_factory","namespace":"Flow\\Azure\\SDK\\DSL","parameters":[{"name":"request_factory","type":[{"name":"RequestFactoryInterface","namespace":"Psr\\Http\\Message","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"stream_factory","type":[{"name":"StreamFactoryInterface","namespace":"Psr\\Http\\Message","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"HttpFactory","namespace":"Flow\\Azure\\SDK","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"AZURE_SDK","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/azure-sdk\/src\/Flow\/Azure\/SDK\/DSL\/functions.php","start_line_in_file":68,"slug":"azure-blob-service","name":"azure_blob_service","namespace":"Flow\\Azure\\SDK\\DSL","parameters":[{"name":"configuration","type":[{"name":"Configuration","namespace":"Flow\\Azure\\SDK\\BlobService","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"azure_authorization_factory","type":[{"name":"AuthorizationFactory","namespace":"Flow\\Azure\\SDK","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"client","type":[{"name":"ClientInterface","namespace":"Psr\\Http\\Client","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"azure_http_factory","type":[{"name":"HttpFactory","namespace":"Flow\\Azure\\SDK","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"azure_url_factory","type":[{"name":"URLFactory","namespace":"Flow\\Azure\\SDK","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"logger","type":[{"name":"LoggerInterface","namespace":"Psr\\Log","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"BlobServiceInterface","namespace":"Flow\\Azure\\SDK","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"AZURE_SDK","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/bridge\/filesystem\/azure\/src\/Flow\/Filesystem\/Bridge\/Azure\/DSL\/functions.php","start_line_in_file":16,"slug":"azure-filesystem-options","name":"azure_filesystem_options","namespace":"Flow\\Filesystem\\Bridge\\Azure\\DSL","parameters":[],"return_type":[{"name":"Options","namespace":"Flow\\Filesystem\\Bridge\\Azure","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"AZURE_FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/bridge\/filesystem\/azure\/src\/Flow\/Filesystem\/Bridge\/Azure\/DSL\/functions.php","start_line_in_file":22,"slug":"azure-filesystem","name":"azure_filesystem","namespace":"Flow\\Filesystem\\Bridge\\Azure\\DSL","parameters":[{"name":"blob_service","type":[{"name":"BlobServiceInterface","namespace":"Flow\\Azure\\SDK","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"options","type":[{"name":"Options","namespace":"Flow\\Filesystem\\Bridge\\Azure","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Bridge\\Azure\\Options::..."},{"name":"protocol","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'azure-blob'"}],"return_type":[{"name":"AzureBlobFilesystem","namespace":"Flow\\Filesystem\\Bridge\\Azure","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"AZURE_FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/bridge\/filesystem\/async-aws\/src\/Flow\/Filesystem\/Bridge\/AsyncAWS\/DSL\/functions.php","start_line_in_file":20,"slug":"aws-s3-client","name":"aws_s3_client","namespace":"Flow\\Filesystem\\Bridge\\AsyncAWS\\DSL","parameters":[{"name":"configuration","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":"S3Client","namespace":"AsyncAws\\S3","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"S3_FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxDb25maWd1cmF0aW9uOjpPUFRJT05fKiwgbnVsbHxzdHJpbmc+ICRjb25maWd1cmF0aW9uIC0gZm9yIGRldGFpbHMgcGxlYXNlIHNlZSBodHRwczovL2FzeW5jLWF3cy5jb20vY2xpZW50cy9zMy5odG1sCiAqLw=="},{"repository_path":"src\/bridge\/filesystem\/async-aws\/src\/Flow\/Filesystem\/Bridge\/AsyncAWS\/DSL\/functions.php","start_line_in_file":26,"slug":"aws-s3-filesystem","name":"aws_s3_filesystem","namespace":"Flow\\Filesystem\\Bridge\\AsyncAWS\\DSL","parameters":[{"name":"bucket","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":"s3Client","type":[{"name":"S3Client","namespace":"AsyncAws\\S3","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"options","type":[{"name":"Options","namespace":"Flow\\Filesystem\\Bridge\\AsyncAWS","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Bridge\\AsyncAWS\\Options::..."},{"name":"protocol","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'aws-s3'"}],"return_type":[{"name":"AsyncAWSS3Filesystem","namespace":"Flow\\Filesystem\\Bridge\\AsyncAWS","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"S3_FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/bridge\/filesystem\/sftp\/src\/Flow\/Filesystem\/Bridge\/SFTP\/DSL\/functions.php","start_line_in_file":24,"slug":"sftp-client","name":"sftp_client","namespace":"Flow\\Filesystem\\Bridge\\SFTP\\DSL","parameters":[{"name":"host","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":"user","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":"credential","type":[{"name":"PrivateKey","namespace":"phpseclib4\\Crypt\\Common","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":"port","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"22"}],"return_type":[{"name":"SFTP","namespace":"phpseclib4\\Net","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"SFTP_FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0aHJvd3MgUnVudGltZUV4Y2VwdGlvbgogKi8="},{"repository_path":"src\/bridge\/filesystem\/sftp\/src\/Flow\/Filesystem\/Bridge\/SFTP\/DSL\/functions.php","start_line_in_file":46,"slug":"sftp-filesystem","name":"sftp_filesystem","namespace":"Flow\\Filesystem\\Bridge\\SFTP\\DSL","parameters":[{"name":"sftp","type":[{"name":"SFTP","namespace":"phpseclib4\\Net","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"options","type":[{"name":"Options","namespace":"Flow\\Filesystem\\Bridge\\SFTP","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Bridge\\SFTP\\Options::..."},{"name":"protocol","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'sftp'"}],"return_type":[{"name":"SFTPFilesystem","namespace":"Flow\\Filesystem\\Bridge\\SFTP","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"SFTP_FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/bridge\/filesystem\/sftp\/src\/Flow\/Filesystem\/Bridge\/SFTP\/DSL\/functions.php","start_line_in_file":52,"slug":"sftp-filesystem-options","name":"sftp_filesystem_options","namespace":"Flow\\Filesystem\\Bridge\\SFTP\\DSL","parameters":[],"return_type":[{"name":"Options","namespace":"Flow\\Filesystem\\Bridge\\SFTP","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"SFTP_FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/bridge\/monolog\/telemetry\/src\/Flow\/Bridge\/Monolog\/Telemetry\/DSL\/functions.php","start_line_in_file":40,"slug":"value-normalizer","name":"value_normalizer","namespace":"Flow\\Bridge\\Monolog\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"ValueNormalizer","namespace":"Flow\\Bridge\\Monolog\\Telemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"MONOLOG_TELEMETRY_BRIDGE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFZhbHVlTm9ybWFsaXplciBmb3IgY29udmVydGluZyBhcmJpdHJhcnkgUEhQIHZhbHVlcyB0byBUZWxlbWV0cnkgYXR0cmlidXRlIHR5cGVzLgogKgogKiBUaGUgbm9ybWFsaXplciBoYW5kbGVzOgogKiAtIG51bGwg4oaSICdudWxsJyBzdHJpbmcKICogLSBzY2FsYXJzIChzdHJpbmcsIGludCwgZmxvYXQsIGJvb2wpIOKGkiB1bmNoYW5nZWQKICogLSBEYXRlVGltZUludGVyZmFjZSDihpIgdW5jaGFuZ2VkCiAqIC0gVGhyb3dhYmxlIOKGkiB1bmNoYW5nZWQKICogLSBhcnJheXMg4oaSIHJlY3Vyc2l2ZWx5IG5vcm1hbGl6ZWQKICogLSBvYmplY3RzIHdpdGggX190b1N0cmluZygpIOKGkiBzdHJpbmcgY2FzdAogKiAtIG9iamVjdHMgd2l0aG91dCBfX3RvU3RyaW5nKCkg4oaSIGNsYXNzIG5hbWUKICogLSBvdGhlciB0eXBlcyDihpIgZ2V0X2RlYnVnX3R5cGUoKSByZXN1bHQKICoKICogRXhhbXBsZSB1c2FnZToKICogYGBgcGhwCiAqICRub3JtYWxpemVyID0gdmFsdWVfbm9ybWFsaXplcigpOwogKiAkbm9ybWFsaXplZCA9ICRub3JtYWxpemVyLT5ub3JtYWxpemUoJHZhbHVlKTsKICogYGBgCiAqLw=="},{"repository_path":"src\/bridge\/monolog\/telemetry\/src\/Flow\/Bridge\/Monolog\/Telemetry\/DSL\/functions.php","start_line_in_file":73,"slug":"severity-mapper","name":"severity_mapper","namespace":"Flow\\Bridge\\Monolog\\Telemetry\\DSL","parameters":[{"name":"customMapping","type":[{"name":"array","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"SeverityMapper","namespace":"Flow\\Bridge\\Monolog\\Telemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"MONOLOG_TELEMETRY_BRIDGE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFNldmVyaXR5TWFwcGVyIGZvciBtYXBwaW5nIE1vbm9sb2cgbGV2ZWxzIHRvIFRlbGVtZXRyeSBzZXZlcml0aWVzLgogKgogKiBAcGFyYW0gbnVsbHxhcnJheTxpbnQsIFNldmVyaXR5PiAkY3VzdG9tTWFwcGluZyBPcHRpb25hbCBjdXN0b20gbWFwcGluZyAoTW9ub2xvZyBMZXZlbCB2YWx1ZSA9PiBUZWxlbWV0cnkgU2V2ZXJpdHkpCiAqCiAqIEV4YW1wbGUgd2l0aCBkZWZhdWx0IG1hcHBpbmc6CiAqIGBgYHBocAogKiAkbWFwcGVyID0gc2V2ZXJpdHlfbWFwcGVyKCk7CiAqIGBgYAogKgogKiBFeGFtcGxlIHdpdGggY3VzdG9tIG1hcHBpbmc6CiAqIGBgYHBocAogKiB1c2UgTW9ub2xvZ1xMZXZlbDsKICogdXNlIEZsb3dcVGVsZW1ldHJ5XExvZ2dlclxTZXZlcml0eTsKICoKICogJG1hcHBlciA9IHNldmVyaXR5X21hcHBlcihbCiAqICAgICBMZXZlbDo6RGVidWctPnZhbHVlID0+IFNldmVyaXR5OjpERUJVRywKICogICAgIExldmVsOjpJbmZvLT52YWx1ZSA9PiBTZXZlcml0eTo6SU5GTywKICogICAgIExldmVsOjpOb3RpY2UtPnZhbHVlID0+IFNldmVyaXR5OjpXQVJOLCAgLy8gQ3VzdG9tOiBOT1RJQ0Ug4oaSIFdBUk4gaW5zdGVhZCBvZiBJTkZPCiAqICAgICBMZXZlbDo6V2FybmluZy0+dmFsdWUgPT4gU2V2ZXJpdHk6OldBUk4sCiAqICAgICBMZXZlbDo6RXJyb3ItPnZhbHVlID0+IFNldmVyaXR5OjpFUlJPUiwKICogICAgIExldmVsOjpDcml0aWNhbC0+dmFsdWUgPT4gU2V2ZXJpdHk6OkZBVEFMLAogKiAgICAgTGV2ZWw6OkFsZXJ0LT52YWx1ZSA9PiBTZXZlcml0eTo6RkFUQUwsCiAqICAgICBMZXZlbDo6RW1lcmdlbmN5LT52YWx1ZSA9PiBTZXZlcml0eTo6RkFUQUwsCiAqIF0pOwogKiBgYGAKICov"},{"repository_path":"src\/bridge\/monolog\/telemetry\/src\/Flow\/Bridge\/Monolog\/Telemetry\/DSL\/functions.php","start_line_in_file":107,"slug":"log-record-converter","name":"log_record_converter","namespace":"Flow\\Bridge\\Monolog\\Telemetry\\DSL","parameters":[{"name":"severityMapper","type":[{"name":"SeverityMapper","namespace":"Flow\\Bridge\\Monolog\\Telemetry","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"valueNormalizer","type":[{"name":"ValueNormalizer","namespace":"Flow\\Bridge\\Monolog\\Telemetry","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"LogRecordConverter","namespace":"Flow\\Bridge\\Monolog\\Telemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"MONOLOG_TELEMETRY_BRIDGE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIExvZ1JlY29yZENvbnZlcnRlciBmb3IgY29udmVydGluZyBNb25vbG9nIExvZ1JlY29yZCB0byBUZWxlbWV0cnkgTG9nUmVjb3JkLgogKgogKiBUaGUgY29udmVydGVyIGhhbmRsZXM6CiAqIC0gU2V2ZXJpdHkgbWFwcGluZyBmcm9tIE1vbm9sb2cgTGV2ZWwgdG8gVGVsZW1ldHJ5IFNldmVyaXR5CiAqIC0gTWVzc2FnZSBib2R5IGNvbnZlcnNpb24KICogLSBDaGFubmVsIGFuZCBsZXZlbCBuYW1lIGFzIG1vbm9sb2cuKiBhdHRyaWJ1dGVzCiAqIC0gQ29udGV4dCB2YWx1ZXMgYXMgY29udGV4dC4qIGF0dHJpYnV0ZXMgKFRocm93YWJsZXMgdXNlIHNldEV4Y2VwdGlvbigpKQogKiAtIEV4dHJhIHZhbHVlcyBhcyBleHRyYS4qIGF0dHJpYnV0ZXMKICoKICogQHBhcmFtIG51bGx8U2V2ZXJpdHlNYXBwZXIgJHNldmVyaXR5TWFwcGVyIEN1c3RvbSBzZXZlcml0eSBtYXBwZXIgKGRlZmF1bHRzIHRvIHN0YW5kYXJkIG1hcHBpbmcpCiAqIEBwYXJhbSBudWxsfFZhbHVlTm9ybWFsaXplciAkdmFsdWVOb3JtYWxpemVyIEN1c3RvbSB2YWx1ZSBub3JtYWxpemVyIChkZWZhdWx0cyB0byBzdGFuZGFyZCBub3JtYWxpemVyKQogKgogKiBFeGFtcGxlIHVzYWdlOgogKiBgYGBwaHAKICogJGNvbnZlcnRlciA9IGxvZ19yZWNvcmRfY29udmVydGVyKCk7CiAqICR0ZWxlbWV0cnlSZWNvcmQgPSAkY29udmVydGVyLT5jb252ZXJ0KCRtb25vbG9nUmVjb3JkKTsKICogYGBgCiAqCiAqIEV4YW1wbGUgd2l0aCBjdXN0b20gbWFwcGVyOgogKiBgYGBwaHAKICogJGNvbnZlcnRlciA9IGxvZ19yZWNvcmRfY29udmVydGVyKAogKiAgICAgc2V2ZXJpdHlNYXBwZXI6IHNldmVyaXR5X21hcHBlcihbCiAqICAgICAgICAgTGV2ZWw6OkRlYnVnLT52YWx1ZSA9PiBTZXZlcml0eTo6VFJBQ0UsCiAqICAgICBdKQogKiApOwogKiBgYGAKICov"},{"repository_path":"src\/bridge\/monolog\/telemetry\/src\/Flow\/Bridge\/Monolog\/Telemetry\/DSL\/functions.php","start_line_in_file":149,"slug":"telemetry-handler","name":"telemetry_handler","namespace":"Flow\\Bridge\\Monolog\\Telemetry\\DSL","parameters":[{"name":"logger","type":[{"name":"Logger","namespace":"Flow\\Telemetry\\Logger","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"converter","type":[{"name":"LogRecordConverter","namespace":"Flow\\Bridge\\Monolog\\Telemetry","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Bridge\\Monolog\\Telemetry\\LogRecordConverter::..."},{"name":"level","type":[{"name":"Level","namespace":"Monolog","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Monolog\\Level::..."},{"name":"bubble","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"errorHandler","type":[{"name":"ErrorHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\ErrorHandler\\ErrorLogHandler::..."}],"return_type":[{"name":"TelemetryHandler","namespace":"Flow\\Bridge\\Monolog\\Telemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"MONOLOG_TELEMETRY_BRIDGE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFRlbGVtZXRyeUhhbmRsZXIgZm9yIGZvcndhcmRpbmcgTW9ub2xvZyBsb2dzIHRvIEZsb3cgVGVsZW1ldHJ5LgogKgogKiBAcGFyYW0gTG9nZ2VyICRsb2dnZXIgVGhlIEZsb3cgVGVsZW1ldHJ5IGxvZ2dlciB0byBmb3J3YXJkIGxvZ3MgdG8KICogQHBhcmFtIExvZ1JlY29yZENvbnZlcnRlciAkY29udmVydGVyIENvbnZlcnRlciB0byB0cmFuc2Zvcm0gTW9ub2xvZyBMb2dSZWNvcmQgdG8gVGVsZW1ldHJ5IExvZ1JlY29yZAogKiBAcGFyYW0gTGV2ZWwgJGxldmVsIFRoZSBtaW5pbXVtIGxvZ2dpbmcgbGV2ZWwgYXQgd2hpY2ggdGhpcyBoYW5kbGVyIHdpbGwgYmUgdHJpZ2dlcmVkCiAqIEBwYXJhbSBib29sICRidWJibGUgV2hldGhlciBtZXNzYWdlcyBoYW5kbGVkIGJ5IHRoaXMgaGFuZGxlciBzaG91bGQgYnViYmxlIHVwIHRvIG90aGVyIGhhbmRsZXJzCiAqCiAqIEV4YW1wbGUgdXNhZ2U6CiAqIGBgYHBocAogKiB1c2UgTW9ub2xvZ1xMb2dnZXIgYXMgTW9ub2xvZ0xvZ2dlcjsKICogdXNlIGZ1bmN0aW9uIEZsb3dcQnJpZGdlXE1vbm9sb2dcVGVsZW1ldHJ5XERTTFx0ZWxlbWV0cnlfaGFuZGxlcjsKICogdXNlIGZ1bmN0aW9uIEZsb3dcVGVsZW1ldHJ5XERTTFx0ZWxlbWV0cnk7CiAqCiAqICR0ZWxlbWV0cnkgPSB0ZWxlbWV0cnkoKTsKICogJGxvZ2dlciA9ICR0ZWxlbWV0cnktPmxvZ2dlcignbXktYXBwJyk7CiAqCiAqICRtb25vbG9nID0gbmV3IE1vbm9sb2dMb2dnZXIoJ2NoYW5uZWwnKTsKICogJG1vbm9sb2ctPnB1c2hIYW5kbGVyKHRlbGVtZXRyeV9oYW5kbGVyKCRsb2dnZXIpKTsKICoKICogJG1vbm9sb2ctPmluZm8oJ1VzZXIgbG9nZ2VkIGluJywgWyd1c2VyX2lkJyA9PiAxMjNdKTsKICogLy8g4oaSIEZvcndhcmRlZCB0byBGbG93IFRlbGVtZXRyeSB3aXRoIElORk8gc2V2ZXJpdHkKICogYGBgCiAqCiAqIEV4YW1wbGUgd2l0aCBjdXN0b20gY29udmVydGVyOgogKiBgYGBwaHAKICogJGNvbnZlcnRlciA9IGxvZ19yZWNvcmRfY29udmVydGVyKAogKiAgICAgc2V2ZXJpdHlNYXBwZXI6IHNldmVyaXR5X21hcHBlcihbCiAqICAgICAgICAgTGV2ZWw6OkRlYnVnLT52YWx1ZSA9PiBTZXZlcml0eTo6VFJBQ0UsCiAqICAgICBdKQogKiApOwogKiAkbW9ub2xvZy0+cHVzaEhhbmRsZXIodGVsZW1ldHJ5X2hhbmRsZXIoJGxvZ2dlciwgJGNvbnZlcnRlcikpOwogKiBgYGAKICov"},{"repository_path":"src\/bridge\/symfony\/http-foundation-telemetry\/src\/Flow\/Bridge\/Symfony\/HttpFoundationTelemetry\/DSL\/functions.php","start_line_in_file":16,"slug":"symfony-request-carrier","name":"symfony_request_carrier","namespace":"Flow\\Bridge\\Symfony\\HttpFoundationTelemetry\\DSL","parameters":[{"name":"request","type":[{"name":"Request","namespace":"Symfony\\Component\\HttpFoundation","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"RequestCarrier","namespace":"Flow\\Bridge\\Symfony\\HttpFoundationTelemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"SYMFONY_HTTP_FOUNDATION_TELEMETRY_BRIDGE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/bridge\/symfony\/http-foundation-telemetry\/src\/Flow\/Bridge\/Symfony\/HttpFoundationTelemetry\/DSL\/functions.php","start_line_in_file":22,"slug":"symfony-response-carrier","name":"symfony_response_carrier","namespace":"Flow\\Bridge\\Symfony\\HttpFoundationTelemetry\\DSL","parameters":[{"name":"response","type":[{"name":"Response","namespace":"Symfony\\Component\\HttpFoundation","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ResponseCarrier","namespace":"Flow\\Bridge\\Symfony\\HttpFoundationTelemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"SYMFONY_HTTP_FOUNDATION_TELEMETRY_BRIDGE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/bridge\/psr7\/telemetry\/src\/Flow\/Bridge\/Psr7\/Telemetry\/DSL\/functions.php","start_line_in_file":16,"slug":"psr7-request-carrier","name":"psr7_request_carrier","namespace":"Flow\\Bridge\\Psr7\\Telemetry\\DSL","parameters":[{"name":"request","type":[{"name":"ServerRequestInterface","namespace":"Psr\\Http\\Message","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"RequestCarrier","namespace":"Flow\\Bridge\\Psr7\\Telemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PSR7_TELEMETRY_BRIDGE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/bridge\/psr7\/telemetry\/src\/Flow\/Bridge\/Psr7\/Telemetry\/DSL\/functions.php","start_line_in_file":22,"slug":"psr7-response-carrier","name":"psr7_response_carrier","namespace":"Flow\\Bridge\\Psr7\\Telemetry\\DSL","parameters":[{"name":"response","type":[{"name":"ResponseInterface","namespace":"Psr\\Http\\Message","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ResponseCarrier","namespace":"Flow\\Bridge\\Psr7\\Telemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PSR7_TELEMETRY_BRIDGE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/bridge\/psr18\/telemetry\/src\/Flow\/Bridge\/Psr18\/Telemetry\/DSL\/functions.php","start_line_in_file":15,"slug":"psr18-traceable-client","name":"psr18_traceable_client","namespace":"Flow\\Bridge\\Psr18\\Telemetry\\DSL","parameters":[{"name":"client","type":[{"name":"ClientInterface","namespace":"Psr\\Http\\Client","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"telemetry","type":[{"name":"Telemetry","namespace":"Flow\\Telemetry","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"PSR18TraceableClient","namespace":"Flow\\Bridge\\Psr18\\Telemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PSR18_TELEMETRY_BRIDGE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":49,"slug":"otlp-json-serializer","name":"otlp_json_serializer","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\DSL","parameters":[],"return_type":[{"name":"JsonSerializer","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Serializer","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEpTT04gc2VyaWFsaXplciBmb3IgT1RMUC4KICoKICogUmV0dXJucyBhIEpzb25TZXJpYWxpemVyIHRoYXQgY29udmVydHMgdGVsZW1ldHJ5IGRhdGEgdG8gT1RMUCBKU09OIHdpcmUgZm9ybWF0LgogKiBVc2UgdGhpcyB3aXRoIEN1cmxUcmFuc3BvcnQgZm9yIEpTT04gb3ZlciBIVFRQLgogKgogKiBFeGFtcGxlIHVzYWdlOgogKiBgYGBwaHAKICogJHNlcmlhbGl6ZXIgPSBvdGxwX2pzb25fc2VyaWFsaXplcigpOwogKiAkdHJhbnNwb3J0ID0gb3RscF9jdXJsX3RyYW5zcG9ydCgkZW5kcG9pbnQsICRzZXJpYWxpemVyKTsKICogYGBgCiAqLw=="},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":70,"slug":"otlp-protobuf-serializer","name":"otlp_protobuf_serializer","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\DSL","parameters":[],"return_type":[{"name":"ProtobufSerializer","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Serializer","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFByb3RvYnVmIHNlcmlhbGl6ZXIgZm9yIE9UTFAuCiAqCiAqIFJldHVybnMgYSBQcm90b2J1ZlNlcmlhbGl6ZXIgdGhhdCBjb252ZXJ0cyB0ZWxlbWV0cnkgZGF0YSB0byBPVExQIFByb3RvYnVmIGJpbmFyeSBmb3JtYXQuCiAqIFVzZSB0aGlzIHdpdGggQ3VybFRyYW5zcG9ydCBmb3IgUHJvdG9idWYgb3ZlciBIVFRQLCBvciB3aXRoIEdycGNUcmFuc3BvcnQuCiAqCiAqIFJlcXVpcmVzOgogKiAtIGdvb2dsZS9wcm90b2J1ZiBwYWNrYWdlCiAqCiAqIEV4YW1wbGUgdXNhZ2U6CiAqIGBgYHBocAogKiAkc2VyaWFsaXplciA9IG90bHBfcHJvdG9idWZfc2VyaWFsaXplcigpOwogKiAkdHJhbnNwb3J0ID0gb3RscF9jdXJsX3RyYW5zcG9ydCgkZW5kcG9pbnQsICRzZXJpYWxpemVyKTsKICogYGBgCiAqLw=="},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":94,"slug":"otlp-grpc-transport","name":"otlp_grpc_transport","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\DSL","parameters":[{"name":"endpoint","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":"headers","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"insecure","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"timeoutMs","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"250"},{"name":"shutdownTimeoutMs","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"5000"},{"name":"failover","type":[{"name":"Transport","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Transport","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Transport","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Transport","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGdSUEMgdHJhbnNwb3J0IGZvciBPVExQIGVuZHBvaW50cy4KICoKICogQ3JlYXRlcyBhIEdycGNUcmFuc3BvcnQgY29uZmlndXJlZCB0byBzZW5kIHRlbGVtZXRyeSBkYXRhIHRvIGFuIE9UTFAtY29tcGF0aWJsZQogKiBlbmRwb2ludCB1c2luZyBnUlBDIHByb3RvY29sIHdpdGggUHJvdG9idWYgc2VyaWFsaXphdGlvbi4gT1RMUC9nUlBDIG1hbmRhdGVzCiAqIFByb3RvYnVmLCBzbyB0aGUgc2VyaWFsaXplciBpcyBidWlsdCBpbnRlcm5hbGx5IGFuZCBub3QgY29uZmlndXJhYmxlLgogKgogKiBSZXF1aXJlczoKICogLSBleHQtZ3JwYyBQSFAgZXh0ZW5zaW9uCiAqIC0gZ29vZ2xlL3Byb3RvYnVmIHBhY2thZ2UKICoKICogQHBhcmFtIHN0cmluZyAkZW5kcG9pbnQgZ1JQQyBlbmRwb2ludCAoZS5nLiwgJ2xvY2FsaG9zdDo0MzE3JykKICogQHBhcmFtIGFycmF5PHN0cmluZywgc3RyaW5nPiAkaGVhZGVycyBBZGRpdGlvbmFsIGhlYWRlcnMgKG1ldGFkYXRhKSB0byBpbmNsdWRlIGluIHJlcXVlc3RzCiAqIEBwYXJhbSBib29sICRpbnNlY3VyZSBXaGV0aGVyIHRvIHVzZSBpbnNlY3VyZSBjaGFubmVsIGNyZWRlbnRpYWxzIChkZWZhdWx0IHRydWUgZm9yIGxvY2FsIGRldikKICogQHBhcmFtIGludCAkdGltZW91dE1zIFBlci1jYWxsIGRlYWRsaW5lIGluIG1pbGxpc2Vjb25kcyAoY292ZXJzIGNvbm5lY3QgKyBzZW5kICsgcmVjZWl2ZSkKICogQHBhcmFtIGludCAkc2h1dGRvd25UaW1lb3V0TXMgV2FsbC1jbG9jayBidWRnZXQgZm9yIGRyYWluaW5nIHBlbmRpbmcgY2FsbHMgYXQgc2h1dGRvd24KICogQHBhcmFtID9UcmFuc3BvcnQgJGZhaWxvdmVyIE9wdGlvbmFsIGZhaWxvdmVyIHRyYW5zcG9ydCByZWNlaXZpbmcgcHJpb3IgYmF0Y2hlcyB3aGVuIHByaW1hcnkgZmFpbHMKICov"},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":109,"slug":"otlp-curl-options","name":"otlp_curl_options","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\DSL","parameters":[],"return_type":[{"name":"CurlTransportOptions","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Transport","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBjdXJsIHRyYW5zcG9ydCBvcHRpb25zIGZvciBPVExQLgogKi8="},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":130,"slug":"otlp-curl-transport","name":"otlp_curl_transport","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\DSL","parameters":[{"name":"endpoint","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":"serializer","type":[{"name":"JsonSerializer","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Serializer","is_nullable":false,"is_variadic":false},{"name":"ProtobufSerializer","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Serializer","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Bridge\\Telemetry\\OTLP\\Serializer\\JsonSerializer::..."},{"name":"options","type":[{"name":"CurlTransportOptions","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Transport","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Bridge\\Telemetry\\OTLP\\Transport\\CurlTransportOptions::..."},{"name":"failover","type":[{"name":"Transport","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Transport","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Transport","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Transport","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHN5bmNocm9ub3VzIGN1cmwgdHJhbnNwb3J0IGZvciBPVExQIGVuZHBvaW50cy4KICoKICogQ3JlYXRlcyBhIEN1cmxUcmFuc3BvcnQgdGhhdCBkcml2ZXMgZWFjaCByZXF1ZXN0IHRvIGNvbXBsZXRpb24gYW5kIHJlcG9ydHMgdGhlCiAqIG91dGNvbWUgaW1tZWRpYXRlbHkgKHJldHVybnMgb24gc3VjY2VzcywgdGhyb3dzIG9uIGZhaWx1cmUpLiBPVExQL0hUVFAgYWxsb3dzCiAqIEpTT04gb3IgUHJvdG9idWYgZW5jb2Rpbmc7IGRlZmF1bHRzIHRvIEpTT04uIEtlZXBpbmcgZXhwb3J0IG9mZiB0aGUgYXBwbGljYXRpb24KICogaG90IHBhdGggaXMgdGhlIGpvYiBvZiB0aGUgYmF0Y2hpbmcgcHJvY2Vzc29yIGluIGZyb250IG9mIHRoZSBleHBvcnRlci4KICoKICogUmVxdWlyZXM6IGV4dC1jdXJsIFBIUCBleHRlbnNpb24KICoKICogQHBhcmFtIHN0cmluZyAkZW5kcG9pbnQgT1RMUCBlbmRwb2ludCBVUkwgKGUuZy4sICdodHRwOi8vbG9jYWxob3N0OjQzMTgnKQogKiBAcGFyYW0gSnNvblNlcmlhbGl6ZXJ8UHJvdG9idWZTZXJpYWxpemVyICRzZXJpYWxpemVyIFNlcmlhbGl6ZXIgZm9yIGVuY29kaW5nIHRlbGVtZXRyeSBkYXRhIChKU09OIG9yIFByb3RvYnVmKQogKiBAcGFyYW0gQ3VybFRyYW5zcG9ydE9wdGlvbnMgJG9wdGlvbnMgVHJhbnNwb3J0IGNvbmZpZ3VyYXRpb24gb3B0aW9ucwogKiBAcGFyYW0gP1RyYW5zcG9ydCAkZmFpbG92ZXIgT3B0aW9uYWwgZmFpbG92ZXIgdHJhbnNwb3J0IHJlY2VpdmluZyB0aGUgYmF0Y2ggd2hlbiB0aGUgcHJpbWFyeSBmYWlscwogKi8="},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":143,"slug":"otlp-async-curl-options","name":"otlp_async_curl_options","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\DSL","parameters":[],"return_type":[{"name":"AsyncCurlTransportOptions","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Transport","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhc3luYyBjdXJsIHRyYW5zcG9ydCBvcHRpb25zIGZvciBPVExQLgogKi8="},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":158,"slug":"otlp-async-curl-transport","name":"otlp_async_curl_transport","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\DSL","parameters":[{"name":"endpoint","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":"serializer","type":[{"name":"JsonSerializer","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Serializer","is_nullable":false,"is_variadic":false},{"name":"ProtobufSerializer","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Serializer","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Bridge\\Telemetry\\OTLP\\Serializer\\JsonSerializer::..."},{"name":"options","type":[{"name":"AsyncCurlTransportOptions","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Transport","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Bridge\\Telemetry\\OTLP\\Transport\\AsyncCurlTransportOptions::..."},{"name":"failover","type":[{"name":"Transport","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Transport","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"error_handler","type":[{"name":"ErrorHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\ErrorHandler\\ErrorLogHandler::..."}],"return_type":[{"name":"AsyncCurlTransport","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Transport","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBhc3luY2hyb25vdXMgY3VybCB0cmFuc3BvcnQgZm9yIE9UTFAgZW5kcG9pbnRzLgogKgogKiBAcGFyYW0gc3RyaW5nICRlbmRwb2ludCBPVExQIGVuZHBvaW50IFVSTCAoZS5nLiwgJ2h0dHA6Ly9sb2NhbGhvc3Q6NDMxOCcpCiAqIEBwYXJhbSBKc29uU2VyaWFsaXplcnxQcm90b2J1ZlNlcmlhbGl6ZXIgJHNlcmlhbGl6ZXIgU2VyaWFsaXplciBmb3IgZW5jb2RpbmcgdGVsZW1ldHJ5IGRhdGEgKEpTT04gb3IgUHJvdG9idWYpCiAqIEBwYXJhbSBBc3luY0N1cmxUcmFuc3BvcnRPcHRpb25zICRvcHRpb25zIFRyYW5zcG9ydCBjb25maWd1cmF0aW9uIG9wdGlvbnMKICogQHBhcmFtID9UcmFuc3BvcnQgJGZhaWxvdmVyIE9wdGlvbmFsIGZhaWxvdmVyIHRyYW5zcG9ydCByZWNlaXZpbmcgcHJpb3IgYmF0Y2hlcyB3aGVuIHByaW1hcnkgZmFpbHMKICogQHBhcmFtIEVycm9ySGFuZGxlciAkZXJyb3JfaGFuZGxlciBIYW5kbGVyIGZvciBmYWlsdXJlcyByZWFwZWQgb24gc2VuZCgpL3RpY2soKS9zaHV0ZG93bigpIChubyBmYWlsb3ZlcikKICov"},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":180,"slug":"otlp-stream-transport","name":"otlp_stream_transport","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\DSL","parameters":[{"name":"destination","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":"filePermissions","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"420"},{"name":"createDirectories","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":"Transport","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Transport","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHN0cmVhbSB0cmFuc3BvcnQgZm9yIE9UTFAgdGhhdCB3cml0ZXMgSlNPTkwgdG8gYSBzaW5nbGUgZGVzdGluYXRpb24uCiAqCiAqIEFjY2VwdHMgYW4gYWJzb2x1dGUgZmlsZSBwYXRoIG9yIGEgcGhwOi8vIHN0cmVhbSB3cmFwcGVyIHN1Y2ggYXMKICogJ3BocDovL3N0ZG91dCcsICdwaHA6Ly9zdGRlcnInLCAncGhwOi8vbWVtb3J5Jywgb3IgJ3BocDovL3RlbXAnLiBFYWNoCiAqIGV4cG9ydCgpIGNhbGwgYXBwZW5kcyBvbmUgSlNPTiBMaW5lIHVuZGVyIExPQ0tfRVggc28gY29uY3VycmVudCB3cml0ZXJzCiAqIGludGVybGVhdmUgYXQgbGluZSBib3VuZGFyaWVzLiBUaGUgJGZpbGVQZXJtaXNzaW9ucyBhbmQgJGNyZWF0ZURpcmVjdG9yaWVzCiAqIHBhcmFtZXRlcnMgYXBwbHkgb25seSB3aGVuIHRoZSBkZXN0aW5hdGlvbiBpcyBhIGZpbGUgcGF0aC4KICoKICogUGVyIHRoZSBPVExQIEZpbGUgRXhwb3J0ZXIgc3BlYyBvbmx5IEpTT04gZW5jb2RpbmcgaXMgc3VwcG9ydGVkLgogKi8="},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":203,"slug":"otlp-exporter","name":"otlp_exporter","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\DSL","parameters":[{"name":"transport","type":[{"name":"Transport","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Transport","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"errorHandler","type":[{"name":"ErrorHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\ErrorHandler\\ErrorLogHandler::..."}],"return_type":[{"name":"OTLPExporter","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Exporter","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBPVExQIGV4cG9ydGVyIHRoYXQgZGlzcGF0Y2hlcyBsb2dzLCBtZXRyaWNzLCBhbmQgc3BhbnMgdGhyb3VnaCBhIHNpbmdsZSB0cmFuc3BvcnQuCiAqCiAqIEV4YW1wbGUgdXNhZ2U6CiAqIGBgYHBocAogKiAkZXhwb3J0ZXIgPSBvdGxwX2V4cG9ydGVyKCR0cmFuc3BvcnQpOwogKiAkc3BhblByb2Nlc3NvciA9IGJhdGNoaW5nX3NwYW5fcHJvY2Vzc29yKCRleHBvcnRlcik7CiAqICRtZXRyaWNQcm9jZXNzb3IgPSBiYXRjaGluZ19tZXRyaWNfcHJvY2Vzc29yKCRleHBvcnRlcik7CiAqICRsb2dQcm9jZXNzb3IgPSBiYXRjaGluZ19sb2dfcHJvY2Vzc29yKCRleHBvcnRlcik7CiAqIGBgYAogKgogKiBAcGFyYW0gVHJhbnNwb3J0ICR0cmFuc3BvcnQgVGhlIHRyYW5zcG9ydCBmb3Igc2VuZGluZyB0ZWxlbWV0cnkgZGF0YQogKiBAcGFyYW0gRXJyb3JIYW5kbGVyICRlcnJvckhhbmRsZXIgSGFuZGxlciBmb3IgVGhyb3dhYmxlcyByYWlzZWQgYnkgdGhlIHRyYW5zcG9ydAogKi8="},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":217,"slug":"otlp-tracer-provider","name":"otlp_tracer_provider","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\DSL","parameters":[{"name":"processor","type":[{"name":"SpanProcessor","namespace":"Flow\\Telemetry\\Tracer","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"clock","type":[{"name":"ClockInterface","namespace":"Psr\\Clock","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"sampler","type":[{"name":"Sampler","namespace":"Flow\\Telemetry\\Tracer\\Sampler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\Tracer\\Sampler\\ParentBasedSampler::..."},{"name":"contextStorage","type":[{"name":"ContextStorage","namespace":"Flow\\Telemetry\\Context","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\Context\\MemoryContextStorage::..."}],"return_type":[{"name":"TracerProvider","namespace":"Flow\\Telemetry\\Tracer","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHRyYWNlciBwcm92aWRlciBjb25maWd1cmVkIGZvciBPVExQIGV4cG9ydC4KICoKICogQHBhcmFtIFNwYW5Qcm9jZXNzb3IgJHByb2Nlc3NvciBUaGUgcHJvY2Vzc29yIGZvciBoYW5kbGluZyBzcGFucwogKiBAcGFyYW0gQ2xvY2tJbnRlcmZhY2UgJGNsb2NrIFRoZSBjbG9jayBmb3IgdGltZXN0YW1wcwogKiBAcGFyYW0gU2FtcGxlciAkc2FtcGxlciBUaGUgc2FtcGxlciBmb3IgZGVjaWRpbmcgd2hldGhlciB0byByZWNvcmQgc3BhbnMKICogQHBhcmFtIENvbnRleHRTdG9yYWdlICRjb250ZXh0U3RvcmFnZSBUaGUgY29udGV4dCBzdG9yYWdlIGZvciBwcm9wYWdhdGluZyB0cmFjZSBjb250ZXh0CiAqLw=="},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":234,"slug":"otlp-meter-provider","name":"otlp_meter_provider","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\DSL","parameters":[{"name":"processor","type":[{"name":"MetricProcessor","namespace":"Flow\\Telemetry\\Meter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"clock","type":[{"name":"ClockInterface","namespace":"Psr\\Clock","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"temporality","type":[{"name":"AggregationTemporality","namespace":"Flow\\Telemetry\\Meter","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\Meter\\AggregationTemporality::..."}],"return_type":[{"name":"MeterProvider","namespace":"Flow\\Telemetry\\Meter","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIG1ldGVyIHByb3ZpZGVyIGNvbmZpZ3VyZWQgZm9yIE9UTFAgZXhwb3J0LgogKgogKiBAcGFyYW0gTWV0cmljUHJvY2Vzc29yICRwcm9jZXNzb3IgVGhlIHByb2Nlc3NvciBmb3IgaGFuZGxpbmcgbWV0cmljcwogKiBAcGFyYW0gQ2xvY2tJbnRlcmZhY2UgJGNsb2NrIFRoZSBjbG9jayBmb3IgdGltZXN0YW1wcwogKiBAcGFyYW0gQWdncmVnYXRpb25UZW1wb3JhbGl0eSAkdGVtcG9yYWxpdHkgVGhlIGFnZ3JlZ2F0aW9uIHRlbXBvcmFsaXR5IGZvciBtZXRyaWNzCiAqLw=="},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":250,"slug":"otlp-logger-provider","name":"otlp_logger_provider","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\DSL","parameters":[{"name":"processor","type":[{"name":"LogProcessor","namespace":"Flow\\Telemetry\\Logger","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"clock","type":[{"name":"ClockInterface","namespace":"Psr\\Clock","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"contextStorage","type":[{"name":"ContextStorage","namespace":"Flow\\Telemetry\\Context","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\Context\\MemoryContextStorage::..."}],"return_type":[{"name":"LoggerProvider","namespace":"Flow\\Telemetry\\Logger","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGxvZ2dlciBwcm92aWRlciBjb25maWd1cmVkIGZvciBPVExQIGV4cG9ydC4KICoKICogQHBhcmFtIExvZ1Byb2Nlc3NvciAkcHJvY2Vzc29yIFRoZSBwcm9jZXNzb3IgZm9yIGhhbmRsaW5nIGxvZyByZWNvcmRzCiAqIEBwYXJhbSBDbG9ja0ludGVyZmFjZSAkY2xvY2sgVGhlIGNsb2NrIGZvciB0aW1lc3RhbXBzCiAqIEBwYXJhbSBDb250ZXh0U3RvcmFnZSAkY29udGV4dFN0b3JhZ2UgVGhlIGNvbnRleHQgc3RvcmFnZSBmb3IgcHJvcGFnYXRpbmcgY29udGV4dAogKi8="}] \ No newline at end of file +[{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":279,"slug":"df","name":"df","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"config","type":[{"name":"Config","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"ConfigBuilder","namespace":"Flow\\ETL\\Config","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":"Flow","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"reading","example":"data_frame"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"writing","example":"overwrite"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEFsaWFzIGZvciBkYXRhX2ZyYW1lKCkgOiBGbG93LgogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":287,"slug":"data-frame","name":"data_frame","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"config","type":[{"name":"Config","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"ConfigBuilder","namespace":"Flow\\ETL\\Config","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":"Flow","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"reading","example":"data_frame"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"writing","example":"overwrite"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":293,"slug":"telemetry-options","name":"telemetry_options","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"trace_loading","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"trace_transformations","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"trace_cache","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"collect_metrics","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":"TelemetryOptions","namespace":"Flow\\ETL\\Config\\Telemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":305,"slug":"from-rows","name":"from_rows","namespace":"Flow\\ETL\\DSL","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":"RowsExtractor","namespace":"Flow\\ETL\\Extractor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"EXTRACTOR"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"reading","example":"data_frame"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"writing","example":"overwrite"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":312,"slug":"from-path-partitions","name":"from_path_partitions","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"path","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"PathPartitionsExtractor","namespace":"Flow\\ETL\\Extractor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"EXTRACTOR"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"partitioning","example":"path_partitions"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":328,"slug":"from-array","name":"from_array","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"array","type":[{"name":"iterable","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"schema","type":[{"name":"Schema","namespace":"Flow\\ETL","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."},{"name":"spillRoot","type":[{"name":"Path","namespace":"Flow\\Filesystem","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"ArrayExtractor","namespace":"Flow\\ETL\\Extractor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"EXTRACTOR"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"reading","example":"array"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"reading","example":"data_frame"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBpdGVyYWJsZTxhcnJheTxtaXhlZD4+ICRhcnJheQogKiBAcGFyYW0gbnVsbHxTY2hlbWEgJHNjaGVtYSAtIEBkZXByZWNhdGVkIHVzZSB3aXRoU2NoZW1hKCkgbWV0aG9kIGluc3RlYWQKICogQHBhcmFtIG51bGx8UGF0aCAkc3BpbGxSb290IC0gd2hlcmUgYSBub24tYXJyYXkgJGFycmF5IGlzIHNwaWxsZWQgd2hpbGUgaXQgaXMgZGVzY3JpYmVkOyBudWxsIHJlc29sdmVzIHRvCiAqICAgICAgICAgICAgICAgICAgICAgICAgICAkZmlsZXN5c3RlbS0+Z2V0U3lzdGVtVG1wRGlyKCkgYW5kIG9ubHkgb24gdGhhdCBwYXRoCiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":349,"slug":"from-cache","name":"from_cache","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"id","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":"fallback_extractor","type":[{"name":"Extractor","namespace":"Flow\\ETL","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"clear","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"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":"CacheExtractor","namespace":"Flow\\ETL\\Extractor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBzdHJpbmcgJGlkIC0gY2FjaGUgaWQgZnJvbSB3aGljaCBkYXRhIHdpbGwgYmUgZXh0cmFjdGVkCiAqIEBwYXJhbSBudWxsfEV4dHJhY3RvciAkZmFsbGJhY2tfZXh0cmFjdG9yIC0gZXh0cmFjdG9yIHRoYXQgd2lsbCBiZSB1c2VkIHdoZW4gY2FjaGUgaXMgZW1wdHkgLSBAZGVwcmVjYXRlZCB1c2Ugd2l0aEZhbGxiYWNrRXh0cmFjdG9yKCkgbWV0aG9kIGluc3RlYWQKICogQHBhcmFtIGJvb2wgJGNsZWFyIC0gY2xlYXIgY2FjaGUgYWZ0ZXIgZXh0cmFjdGlvbiAtIEBkZXByZWNhdGVkIHVzZSB3aXRoQ2xlYXJPbkZpbmlzaCgpIG1ldGhvZCBpbnN0ZWFkCiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":369,"slug":"from-all","name":"from_all","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"extractors","type":[{"name":"Extractor","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":"ChainExtractor","namespace":"Flow\\ETL\\Extractor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":375,"slug":"from-memory","name":"from_memory","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"memory","type":[{"name":"Memory","namespace":"Flow\\ETL\\Memory","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"MemoryExtractor","namespace":"Flow\\ETL\\Extractor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":381,"slug":"files","name":"files","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"directory","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"FilesExtractor","namespace":"Flow\\ETL\\Extractor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":387,"slug":"filesystem-cache","name":"filesystem_cache","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"cache_dir","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."},{"name":"serializer","type":[{"name":"Serializer","namespace":"Flow\\Serializer","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Floe\\FloeSerializer::..."}],"return_type":[{"name":"FilesystemCache","namespace":"Flow\\ETL\\Cache\\Implementation","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":399,"slug":"batched-by","name":"batched_by","namespace":"Flow\\ETL\\DSL","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},{"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":"min_size","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":"BatchByExtractor","namespace":"Flow\\ETL\\Extractor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBudWxsfGludDwxLCBtYXg+ICRtaW5fc2l6ZQogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":413,"slug":"batches","name":"batches","namespace":"Flow\\ETL\\DSL","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},{"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":"BatchExtractor","namespace":"Flow\\ETL\\Extractor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBpbnQ8MSwgbWF4PiAkc2l6ZQogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":419,"slug":"from-data-frame","name":"from_data_frame","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"data_frame","type":[{"name":"DataFrame","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":"DataFrameExtractor","namespace":"Flow\\ETL\\Extractor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":425,"slug":"from-sequence-date-period","name":"from_sequence_date_period","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"entry_name","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":"start","type":[{"name":"DateTimeInterface","namespace":"","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"interval","type":[{"name":"DateInterval","namespace":"","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"end","type":[{"name":"DateTimeInterface","namespace":"","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"options","type":[{"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":"SequenceExtractor","namespace":"Flow\\ETL\\Extractor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":439,"slug":"from-sequence-date-period-recurrences","name":"from_sequence_date_period_recurrences","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"entry_name","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":"start","type":[{"name":"DateTimeInterface","namespace":"","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"interval","type":[{"name":"DateInterval","namespace":"","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"recurrences","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":"options","type":[{"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":"SequenceExtractor","namespace":"Flow\\ETL\\Extractor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":453,"slug":"from-sequence-number","name":"from_sequence_number","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"entry_name","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":"start","type":[{"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":"end","type":[{"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":"step","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"float","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"1"}],"return_type":[{"name":"SequenceExtractor","namespace":"Flow\\ETL\\Extractor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":463,"slug":"to-memory","name":"to_memory","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"memory","type":[{"name":"Memory","namespace":"Flow\\ETL\\Memory","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"MemoryLoader","namespace":"Flow\\ETL\\Loader","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":477,"slug":"to-array","name":"to_array","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"array","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":"ArrayLoader","namespace":"Flow\\ETL\\Loader","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"LOADER"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"writing","example":"array"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENvbnZlcnQgcm93cyB0byBhbiBhcnJheSBhbmQgc3RvcmUgdGhlbSBpbiBwYXNzZWQgYXJyYXkgdmFyaWFibGUuCiAqCiAqIEBwYXJhbSBhcnJheTxhcnJheS1rZXksIG1peGVkPiAkYXJyYXkKICoKICogQHBhcmFtLW91dCBhcnJheTxhcnJheTxtaXhlZD4+ICRhcnJheQogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":485,"slug":"to-output","name":"to_output","namespace":"Flow\\ETL\\DSL","parameters":[{"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":"output","type":[{"name":"Output","namespace":"Flow\\ETL\\Loader\\StreamLoader","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Loader\\StreamLoader\\Output::..."},{"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::..."},{"name":"schemaFormatter","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":"StreamLoader","namespace":"Flow\\ETL\\Loader","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":495,"slug":"to-stderr","name":"to_stderr","namespace":"Flow\\ETL\\DSL","parameters":[{"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":"output","type":[{"name":"Output","namespace":"Flow\\ETL\\Loader\\StreamLoader","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Loader\\StreamLoader\\Output::..."},{"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::..."},{"name":"schemaFormatter","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":"StreamLoader","namespace":"Flow\\ETL\\Loader","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":505,"slug":"to-stdout","name":"to_stdout","namespace":"Flow\\ETL\\DSL","parameters":[{"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":"output","type":[{"name":"Output","namespace":"Flow\\ETL\\Loader\\StreamLoader","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Loader\\StreamLoader\\Output::..."},{"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::..."},{"name":"schemaFormatter","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":"StreamLoader","namespace":"Flow\\ETL\\Loader","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":515,"slug":"to-stream","name":"to_stream","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"uri","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":"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":"output","type":[{"name":"Output","namespace":"Flow\\ETL\\Loader\\StreamLoader","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Loader\\StreamLoader\\Output::..."},{"name":"mode","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'w'"},{"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::..."},{"name":"schemaFormatter","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":"StreamLoader","namespace":"Flow\\ETL\\Loader","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":535,"slug":"to-transformation","name":"to_transformation","namespace":"Flow\\ETL\\DSL","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},{"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":"Transformed","namespace":"Flow\\ETL\\Sink","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":541,"slug":"to-branch","name":"to_branch","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"condition","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":"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":"Branched","namespace":"Flow\\ETL\\Sink","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":547,"slug":"rename-style","name":"rename_style","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"style","type":[{"name":"StringStyles","namespace":"Flow\\ETL\\String","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"RenameCaseEntryStrategy","namespace":"Flow\\ETL\\Transformer\\Rename","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"TRANSFORMER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":557,"slug":"rename-replace","name":"rename_replace","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"search","type":[{"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":"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":"RenameReplaceEntryStrategy","namespace":"Flow\\ETL\\Transformer\\Rename","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"TRANSFORMER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxzdHJpbmc+fHN0cmluZyAkc2VhcmNoCiAqIEBwYXJhbSBhcnJheTxzdHJpbmc+fHN0cmluZyAkcmVwbGFjZQogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":566,"slug":"rename-map","name":"rename_map","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"renames","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":"RenameMapEntryStrategy","namespace":"Flow\\ETL\\Transformer\\Rename","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"TRANSFORMER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxhcnJheS1rZXksIHN0cmluZz4gJHJlbmFtZXMgTWFwIG9mIG9sZF9uYW1lID0+IG5ld19uYW1lCiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":575,"slug":"row","name":"row","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"values","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":"Row","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxhcnJheS1rZXksIG1peGVkPiAkdmFsdWVzCiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":581,"slug":"rows","name":"rows","namespace":"Flow\\ETL\\DSL","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":"row","type":[{"name":"Row","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":"Rows","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":590,"slug":"col","name":"col","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"entry","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":"UnresolvedReference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIEFuIGFsaWFzIGZvciBgcmVmYC4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":600,"slug":"entry","name":"entry","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"entry","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":"UnresolvedReference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"columns","example":"create"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIEFuIGFsaWFzIGZvciBgcmVmYC4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":607,"slug":"ref","name":"ref","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"entry","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":"UnresolvedReference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"columns","example":"create"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":613,"slug":"structure-ref","name":"structure_ref","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"entry","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":"StructureFunctions","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":625,"slug":"structure","name":"structure","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"elements","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":"Structure","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIEJ1aWxkcyBhIHN0cnVjdHVyZSBmcm9tIHNjYWxhciBmdW5jdGlvbnM6IG9uZSBlbGVtZW50IHBlciBrZXksIGluIGtleSBvcmRlci4KICogQW4gZWxlbWVudCBpcyBudWxsYWJsZSB3aGVuIGl0cyBmdW5jdGlvbiBpczsgdGhlIHN0cnVjdHVyZSBpdHNlbGYgbmV2ZXIgaXMuCiAqCiAqIEBwYXJhbSBhcnJheTxhcnJheS1rZXksIFNjYWxhckZ1bmN0aW9uPiAkZWxlbWVudHMKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":631,"slug":"list-ref","name":"list_ref","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"entry","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":"ListFunctions","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":637,"slug":"refs","name":"refs","namespace":"Flow\\ETL\\DSL","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":"References","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":643,"slug":"select","name":"select","namespace":"Flow\\ETL\\DSL","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":"Select","namespace":"Flow\\ETL\\Transformation","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"TRANSFORMER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":649,"slug":"drop","name":"drop","namespace":"Flow\\ETL\\DSL","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":"Drop","namespace":"Flow\\ETL\\Transformation","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"TRANSFORMER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":655,"slug":"add-row-index","name":"add_row_index","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"column","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'index'"},{"name":"startFrom","type":[{"name":"StartFrom","namespace":"Flow\\ETL\\Transformation\\AddRowIndex","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Transformation\\AddRowIndex\\StartFrom::..."}],"return_type":[{"name":"AddRowIndex","namespace":"Flow\\ETL\\Transformation","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"TRANSFORMER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":664,"slug":"batch-size","name":"batch_size","namespace":"Flow\\ETL\\DSL","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":"BatchSize","namespace":"Flow\\ETL\\Transformation","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"TRANSFORMER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBpbnQ8MSwgbWF4PiAkc2l6ZQogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":670,"slug":"limit","name":"limit","namespace":"Flow\\ETL\\DSL","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":"Limit","namespace":"Flow\\ETL\\Transformation","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"TRANSFORMER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":679,"slug":"mask-columns","name":"mask_columns","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"columns","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"mask","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":"MaskColumns","namespace":"Flow\\ETL\\Transformation","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"TRANSFORMER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxpbnQsIHN0cmluZz4gJGNvbHVtbnMKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":685,"slug":"optional","name":"optional","namespace":"Flow\\ETL\\DSL","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":"Optional","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":692,"slug":"lit","name":"lit","namespace":"Flow\\ETL\\DSL","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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"columns","example":"create"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":698,"slug":"exists","name":"exists","namespace":"Flow\\ETL\\DSL","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":"Exists","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":704,"slug":"when","name":"when","namespace":"Flow\\ETL\\DSL","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":"then","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":"else","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"When","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":713,"slug":"structure-get","name":"structure_get","namespace":"Flow\\ETL\\DSL","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},{"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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIEFsaWFzIGZvciBgYXJyYXlfZ2V0YC4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":719,"slug":"array-get","name":"array_get","namespace":"Flow\\ETL\\DSL","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},{"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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":730,"slug":"structure-get-collection","name":"structure_get_collection","namespace":"Flow\\ETL\\DSL","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},{"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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIEFsaWFzIGZvciBgYXJyYXlfZ2V0X2NvbGxlY3Rpb25gLgogKgogKiBAcGFyYW0gYXJyYXk8YXJyYXkta2V5LCBtaXhlZD58U2NhbGFyRnVuY3Rpb24gJGtleXMKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":739,"slug":"array-get-collection","name":"array_get_collection","namespace":"Flow\\ETL\\DSL","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},{"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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxhcnJheS1rZXksIG1peGVkPnxTY2FsYXJGdW5jdGlvbiAka2V5cwogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":748,"slug":"structure-get-collection-first","name":"structure_get_collection_first","namespace":"Flow\\ETL\\DSL","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},{"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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIEFsaWFzIGZvciBgYXJyYXlfZ2V0X2NvbGxlY3Rpb25fZmlyc3RgLgogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":754,"slug":"array-get-collection-first","name":"array_get_collection_first","namespace":"Flow\\ETL\\DSL","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},{"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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":763,"slug":"array-exists","name":"array_exists","namespace":"Flow\\ETL\\DSL","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},{"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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxhcnJheS1rZXksIG1peGVkPnxTY2FsYXJGdW5jdGlvbiAkcmVmCiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":773,"slug":"array-merge","name":"array_merge","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"left","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},{"name":"right","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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxhcnJheS1rZXksIG1peGVkPnxTY2FsYXJGdW5jdGlvbiAkbGVmdAogKiBAcGFyYW0gYXJyYXk8YXJyYXkta2V5LCBtaXhlZD58U2NhbGFyRnVuY3Rpb24gJHJpZ2h0CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":782,"slug":"array-merge-collection","name":"array_merge_collection","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"array","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":"ArrayMergeCollection","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxhcnJheS1rZXksIG1peGVkPnxTY2FsYXJGdW5jdGlvbiAkYXJyYXkKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":788,"slug":"array-key-rename","name":"array_key_rename","namespace":"Flow\\ETL\\DSL","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},{"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},{"name":"newName","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":"ArrayKeyRename","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":794,"slug":"array-keys-style-convert","name":"array_keys_style_convert","namespace":"Flow\\ETL\\DSL","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},{"name":"style","type":[{"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":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\String\\StringStyles::..."}],"return_type":[{"name":"ArrayKeysStyleConvert","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":802,"slug":"array-sort","name":"array_sort","namespace":"Flow\\ETL\\DSL","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":"sort_function","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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":815,"slug":"array-reverse","name":"array_reverse","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"function","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},{"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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxhcnJheS1rZXksIG1peGVkPnxTY2FsYXJGdW5jdGlvbiAkZnVuY3Rpb24KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":821,"slug":"now","name":"now","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"time_zone","type":[{"name":"DateTimeZone","namespace":"","is_nullable":false,"is_variadic":false},{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"DateTimeZone::..."}],"return_type":[{"name":"Now","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":827,"slug":"between","name":"between","namespace":"Flow\\ETL\\DSL","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},{"name":"lower_bound","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":"upper_bound","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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":837,"slug":"to-date-time","name":"to_date_time","namespace":"Flow\\ETL\\DSL","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},{"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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":846,"slug":"to-date","name":"to_date","namespace":"Flow\\ETL\\DSL","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},{"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'"},{"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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":855,"slug":"date-time-format","name":"date_time_format","namespace":"Flow\\ETL\\DSL","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},{"name":"format","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":"DateTimeFormat","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":861,"slug":"split","name":"split","namespace":"Flow\\ETL\\DSL","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}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":874,"slug":"combine","name":"combine","namespace":"Flow\\ETL\\DSL","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},{"name":"values","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":"Combine","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxhcnJheS1rZXksIG1peGVkPnxTY2FsYXJGdW5jdGlvbiAka2V5cwogKiBAcGFyYW0gYXJyYXk8YXJyYXkta2V5LCBtaXhlZD58U2NhbGFyRnVuY3Rpb24gJHZhbHVlcwogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":883,"slug":"concat","name":"concat","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"functions","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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIENvbmNhdCBhbGwgdmFsdWVzLiBJZiB5b3Ugd2FudCB0byBjb25jYXRlbmF0ZSB2YWx1ZXMgd2l0aCBzZXBhcmF0b3IgdXNlIGNvbmNhdF93cyBmdW5jdGlvbi4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":892,"slug":"concat-ws","name":"concat_ws","namespace":"Flow\\ETL\\DSL","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":"functions","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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIENvbmNhdCBhbGwgdmFsdWVzIHdpdGggc2VwYXJhdG9yLgogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":898,"slug":"hash","name":"hash","namespace":"Flow\\ETL\\DSL","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},{"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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":907,"slug":"cast","name":"cast","namespace":"Flow\\ETL\\DSL","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},{"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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIEBwYXJhbSBcRmxvd1xUeXBlc1xUeXBlPG1peGVkPnxzdHJpbmcgJHR5cGUKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":913,"slug":"coalesce","name":"coalesce","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"values","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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":919,"slug":"enum-name","name":"enum_name","namespace":"Flow\\ETL\\DSL","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":"EnumName","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":925,"slug":"enum-value","name":"enum_value","namespace":"Flow\\ETL\\DSL","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":"EnumValue","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":931,"slug":"count","name":"count","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"function","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Count","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"AGGREGATING_FUNCTION"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":943,"slug":"call","name":"call","namespace":"Flow\\ETL\\DSL","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":"return_type","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":"parameters","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"CallUserFunc","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIENhbGxzIGEgdXNlci1kZWZpbmVkIGZ1bmN0aW9uIHdpdGggdGhlIGdpdmVuIHBhcmFtZXRlcnMuCiAqCiAqIEBwYXJhbSBUeXBlPG1peGVkPiAkcmV0dXJuX3R5cGUKICogQHBhcmFtIGFycmF5PG1peGVkPiAkcGFyYW1ldGVycwogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":970,"slug":"array-unpack","name":"array_unpack","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"array","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},{"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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIFVucGFja3MgZWFjaCBlbGVtZW50IG9mIGFuIGFycmF5IGludG8gYSBuZXcgZW50cnksIHVzaW5nIHRoZSBhcnJheSBrZXkgYXMgdGhlIGVudHJ5IG5hbWUuCiAqCiAqIEJlZm9yZToKICogKy0tKy0tLS0tLS0tLS0tLS0tLS0tLS0rCiAqIHxpZHwgICAgICAgICAgICAgIGFycmF5fAogKiArLS0rLS0tLS0tLS0tLS0tLS0tLS0tLSsKICogfCAxfHsiYSI6MSwiYiI6MiwiYyI6M318CiAqIHwgMnx7ImQiOjQsImUiOjUsImYiOjZ9fAogKiArLS0rLS0tLS0tLS0tLS0tLS0tLS0tLSsKICoKICogQWZ0ZXI6CiAqICstLSstLS0tLSstLS0tLSstLS0tLSstLS0tLSstLS0tLSsKICogfGlkfGFyci5ifGFyci5jfGFyci5kfGFyci5lfGFyci5mfAogKiArLS0rLS0tLS0rLS0tLS0rLS0tLS0rLS0tLS0rLS0tLS0rCiAqIHwgMXwgICAgMnwgICAgM3wgICAgIHwgICAgIHwgICAgIHwKICogfCAyfCAgICAgfCAgICAgfCAgICA0fCAgICA1fCAgICA2fAogKiArLS0rLS0tLS0rLS0tLS0rLS0tLS0rLS0tLS0rLS0tLS0rCiAqCiAqIEBwYXJhbSBhcnJheTxhcnJheS1rZXksIG1peGVkPnxTY2FsYXJGdW5jdGlvbiAkYXJyYXkKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1000,"slug":"array-expand","name":"array_expand","namespace":"Flow\\ETL\\DSL","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":"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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIEV4cGFuZHMgZWFjaCB2YWx1ZSBpbnRvIGVudHJ5LCBpZiB0aGVyZSBhcmUgbW9yZSB0aGFuIG9uZSB2YWx1ZSwgbXVsdGlwbGUgcm93cyB3aWxsIGJlIGNyZWF0ZWQuCiAqIEFycmF5IGtleXMgYXJlIGlnbm9yZWQsIG9ubHkgdmFsdWVzIGFyZSB1c2VkIHRvIGNyZWF0ZSBuZXcgcm93cy4KICogTmVzdGVkIGluIGFub3RoZXIgZnVuY3Rpb24gKHN0cnVjdHVyZSgpLCBjb25jYXQoKSwgLi4uKSBpdCBzdGlsbCBnaXZlcyBvbmUgcm93IHBlciBlbGVtZW50LiBTZXZlcmFsCiAqIGV4cGFuZHMgaW4gb25lIGV4cHJlc3Npb24gYXJlIHppcHBlZCB0byB0aGUgbG9uZ2VzdCBsaXN0OyBhIHNob3J0ZXIgb25lIGdpdmVzIG51bGwsIHNvIGl0cyBlbGVtZW50CiAqIHR5cGUgYmVjb21lcyBudWxsYWJsZS4gSXQgaXMgcmVmdXNlZCBpbnNpZGUgYW5vdGhlciBhcnJheV9leHBhbmQoKSBhbmQgaW4gZmlsdGVyKCksIHVudGlsKCksCiAqIGR1cGxpY2F0ZVJvdygpLCBhZ2dyZWdhdGUoKSwgb3ZlcigpIGFuZCBvbkVhY2goKS4KICoKICogQmVmb3JlOgogKiAgICstLSstLS0tLS0tLS0tLS0tLS0tLS0tKwogKiAgIHxpZHwgICAgICAgICAgICAgIGFycmF5fAogKiAgICstLSstLS0tLS0tLS0tLS0tLS0tLS0tKwogKiAgIHwgMXx7ImEiOjEsImIiOjIsImMiOjN9fAogKiAgICstLSstLS0tLS0tLS0tLS0tLS0tLS0tKwogKgogKiBBZnRlcjoKICogICArLS0rLS0tLS0tLS0rCiAqICAgfGlkfGV4cGFuZGVkfAogKiAgICstLSstLS0tLS0tLSsKICogICB8IDF8ICAgICAgIDF8CiAqICAgfCAxfCAgICAgICAyfAogKiAgIHwgMXwgICAgICAgM3wKICogICArLS0rLS0tLS0tLS0rCiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1006,"slug":"size","name":"size","namespace":"Flow\\ETL\\DSL","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":"Size","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1012,"slug":"uuid-v4","name":"uuid_v4","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"Uuid","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1018,"slug":"uuid-v7","name":"uuid_v7","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"value","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"DateTimeInterface","namespace":"","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Uuid","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1024,"slug":"ulid","name":"ulid","namespace":"Flow\\ETL\\DSL","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":"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":"Ulid","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1030,"slug":"lower","name":"lower","namespace":"Flow\\ETL\\DSL","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}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ToLower","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1036,"slug":"capitalize","name":"capitalize","namespace":"Flow\\ETL\\DSL","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}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Capitalize","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1042,"slug":"upper","name":"upper","namespace":"Flow\\ETL\\DSL","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}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ToUpper","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1048,"slug":"all","name":"all","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"functions","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":"All","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1054,"slug":"any","name":"any","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"values","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":"Any","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1060,"slug":"not","name":"not","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"value","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":"Not","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1066,"slug":"to-timezone","name":"to_timezone","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"value","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"DateTimeInterface","namespace":"","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"timeZone","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"DateTimeZone","namespace":"","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":"ToTimeZone","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1072,"slug":"ignore-error-handler","name":"ignore_error_handler","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"IgnoreError","namespace":"Flow\\ETL\\ErrorHandler","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1078,"slug":"skip-rows-handler","name":"skip_rows_handler","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"SkipRows","namespace":"Flow\\ETL\\ErrorHandler","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1084,"slug":"throw-error-handler","name":"throw_error_handler","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"ThrowError","namespace":"Flow\\ETL\\ErrorHandler","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1090,"slug":"regex-replace","name":"regex_replace","namespace":"Flow\\ETL\\DSL","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":"subject","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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1100,"slug":"regex-match-all","name":"regex_match_all","namespace":"Flow\\ETL\\DSL","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":"subject","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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1110,"slug":"regex-match","name":"regex_match","namespace":"Flow\\ETL\\DSL","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":"subject","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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1120,"slug":"regex","name":"regex","namespace":"Flow\\ETL\\DSL","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":"subject","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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1130,"slug":"regex-all","name":"regex_all","namespace":"Flow\\ETL\\DSL","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":"subject","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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1140,"slug":"sprintf","name":"sprintf","namespace":"Flow\\ETL\\DSL","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":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"args","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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1146,"slug":"sanitize","name":"sanitize","namespace":"Flow\\ETL\\DSL","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}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1155,"slug":"round","name":"round","namespace":"Flow\\ETL\\DSL","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":"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":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1164,"slug":"number-format","name":"number_format","namespace":"Flow\\ETL\\DSL","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":"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":"decimal_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":"thousands_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":"','"}],"return_type":[{"name":"NumberFormat","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1178,"slug":"array-to-row","name":"array_to_row","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"data","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":"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":"hydrator","type":[{"name":"Hydrator","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Row\\AdaptiveRowHydrator::..."},{"name":"partitions","type":[{"name":"Partitions","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"Row","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxhcnJheTxtaXhlZD4+fGFycmF5PG1peGVkfHN0cmluZz4gJGRhdGEKICogQHBhcmFtIGFycmF5PFBhcnRpdGlvbj58UGFydGl0aW9ucyAkcGFydGl0aW9ucwogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1204,"slug":"array-to-rows","name":"array_to_rows","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"data","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":"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":"hydrator","type":[{"name":"Hydrator","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Row\\AdaptiveRowHydrator::..."}],"return_type":[{"name":"Rows","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxhcnJheTxtaXhlZD4+fGFycmF5PG1peGVkfHN0cmluZz4gJGRhdGEKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1241,"slug":"rank","name":"rank","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"Rank","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"WINDOW_FUNCTION"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1247,"slug":"dens-rank","name":"dens_rank","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"DenseRank","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"WINDOW_FUNCTION"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1253,"slug":"dense-rank","name":"dense_rank","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"DenseRank","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"WINDOW_FUNCTION"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1259,"slug":"average","name":"average","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"ref","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":"scale","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"2"},{"name":"rounding","type":[{"name":"Rounding","namespace":"Flow\\Calculator","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Calculator\\Rounding::..."}],"return_type":[{"name":"Average","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"AGGREGATING_FUNCTION"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1265,"slug":"greatest","name":"greatest","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"values","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":true,"default_value":null}],"return_type":[{"name":"Greatest","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1271,"slug":"least","name":"least","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"values","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":true,"default_value":null}],"return_type":[{"name":"Least","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1277,"slug":"collect","name":"collect","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"ref","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}],"return_type":[{"name":"Collect","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"AGGREGATING_FUNCTION"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1283,"slug":"string-agg","name":"string_agg","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"ref","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":"separator","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"', '"},{"name":"sort","type":[{"name":"SortOrder","namespace":"Flow\\ETL\\Row","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"StringAggregate","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"AGGREGATING_FUNCTION"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1289,"slug":"collect-unique","name":"collect_unique","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"ref","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}],"return_type":[{"name":"CollectUnique","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"AGGREGATING_FUNCTION"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1295,"slug":"window","name":"window","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"Window","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1301,"slug":"unbounded-preceding","name":"unbounded_preceding","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"FrameBound","namespace":"Flow\\ETL\\Window","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1307,"slug":"preceding","name":"preceding","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"offset","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":"FrameBound","namespace":"Flow\\ETL\\Window","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1313,"slug":"current-row","name":"current_row","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"FrameBound","namespace":"Flow\\ETL\\Window","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1319,"slug":"following","name":"following","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"offset","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":"FrameBound","namespace":"Flow\\ETL\\Window","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1325,"slug":"unbounded-following","name":"unbounded_following","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"FrameBound","namespace":"Flow\\ETL\\Window","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1331,"slug":"sum","name":"sum","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"ref","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":"exact","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":"Sum","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"AGGREGATING_FUNCTION"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1337,"slug":"first","name":"first","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"ref","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}],"return_type":[{"name":"First","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"AGGREGATING_FUNCTION"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1343,"slug":"last","name":"last","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"ref","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}],"return_type":[{"name":"Last","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"AGGREGATING_FUNCTION"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1349,"slug":"max","name":"max","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"ref","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}],"return_type":[{"name":"Max","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"AGGREGATING_FUNCTION"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1355,"slug":"min","name":"min","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"ref","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}],"return_type":[{"name":"Min","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"AGGREGATING_FUNCTION"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1361,"slug":"row-number","name":"row_number","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"RowNumber","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1372,"slug":"schema","name":"schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"definitions","type":[{"name":"Definition","namespace":"Flow\\ETL\\Schema","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"Schema","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBEZWZpbml0aW9uPG1peGVkPiAuLi4kZGVmaW5pdGlvbnMKICoKICogQHJldHVybiBTY2hlbWEKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1381,"slug":"schema-to-json","name":"schema_to_json","namespace":"Flow\\ETL\\DSL","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":"pretty","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":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBTY2hlbWEgJHNjaGVtYQogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1390,"slug":"schema-to-php","name":"schema_to_php","namespace":"Flow\\ETL\\DSL","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":"valueFormatter","type":[{"name":"ValueFormatter","namespace":"Flow\\ETL\\Schema\\Formatter\\PHPFormatter","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Schema\\Formatter\\PHPFormatter\\ValueFormatter::..."},{"name":"typeFormatter","type":[{"name":"TypeFormatter","namespace":"Flow\\ETL\\Schema\\Formatter\\PHPFormatter","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Schema\\Formatter\\PHPFormatter\\TypeFormatter::..."}],"return_type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBTY2hlbWEgJHNjaGVtYQogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1402,"slug":"schema-to-ascii","name":"schema_to_ascii","namespace":"Flow\\ETL\\DSL","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":"formatter","type":[{"name":"SchemaFormatter","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBTY2hlbWEgJHNjaGVtYQogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1412,"slug":"schema-validate","name":"schema_validate","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"expected","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":"given","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":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Schema\\Validator\\StrictValidator::..."}],"return_type":[{"name":"ValidationContext","namespace":"Flow\\ETL\\Schema\\Validator","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBTY2hlbWEgJGV4cGVjdGVkCiAqIEBwYXJhbSBTY2hlbWEgJGdpdmVuCiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1421,"slug":"schema-evolving-validator","name":"schema_evolving_validator","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"EvolvingValidator","namespace":"Flow\\ETL\\Schema\\Validator","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1427,"slug":"schema-strict-validator","name":"schema_strict_validator","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"StrictValidator","namespace":"Flow\\ETL\\Schema\\Validator","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1433,"slug":"schema-selective-validator","name":"schema_selective_validator","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"SelectiveValidator","namespace":"Flow\\ETL\\Schema\\Validator","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1442,"slug":"schema-from-json","name":"schema_from_json","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"schema","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":"Schema","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gU2NoZW1hCiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1455,"slug":"schema-metadata","name":"schema_metadata","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"metadata","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxzdHJpbmcsIGFycmF5PGJvb2x8ZmxvYXR8aW50fHN0cmluZz58Ym9vbHxmbG9hdHxpbnR8c3RyaW5nPiAkbWV0YWRhdGEKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1464,"slug":"int-schema","name":"int_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"IntegerDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEFsaWFzIGZvciBgaW50ZWdlcl9zY2hlbWFgLgogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1470,"slug":"integer-schema","name":"integer_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"IntegerDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1479,"slug":"str-schema","name":"str_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"StringDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEFsaWFzIGZvciBgc3RyaW5nX3NjaGVtYWAuCiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1485,"slug":"string-schema","name":"string_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"StringDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1491,"slug":"bool-schema","name":"bool_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"BooleanDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1497,"slug":"float-schema","name":"float_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"FloatDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1511,"slug":"map-schema","name":"map_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"type","type":[{"name":"MapType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false},{"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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"MapDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUS2V5IG9mIGFycmF5LWtleQogKiBAdGVtcGxhdGUgVFZhbHVlCiAqCiAqIEBwYXJhbSBNYXBUeXBlPGFycmF5PFRLZXksIFRWYWx1ZT4+fFR5cGU8YXJyYXk8VEtleSwgVFZhbHVlPj4gJHR5cGUKICoKICogQHJldHVybiBNYXBEZWZpbml0aW9uPFRLZXksIFRWYWx1ZT4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1525,"slug":"list-schema","name":"list_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"type","type":[{"name":"ListType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false},{"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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"ListDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBMaXN0VHlwZTxsaXN0PFQ+PnxUeXBlPGxpc3Q8VD4+ICR0eXBlCiAqCiAqIEByZXR1cm4gTGlzdERlZmluaXRpb248VD4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1543,"slug":"enum-schema","name":"enum_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"type","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"EnumDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUIG9mIFxVbml0RW51bQogKgogKiBAcGFyYW0gY2xhc3Mtc3RyaW5nPFQ+ICR0eXBlCiAqCiAqIEByZXR1cm4gRW51bURlZmluaXRpb248VD4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1549,"slug":"null-schema","name":"null_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"NullDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1555,"slug":"datetime-schema","name":"datetime_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"DateTimeDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1561,"slug":"time-schema","name":"time_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"TimeDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1567,"slug":"date-schema","name":"date_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"DateDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1573,"slug":"json-schema","name":"json_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"JsonDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1579,"slug":"html-schema","name":"html_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"HTMLDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1585,"slug":"html-element-schema","name":"html_element_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"HTMLElementDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1591,"slug":"xml-schema","name":"xml_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"XMLDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1597,"slug":"xml-element-schema","name":"xml_element_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"XMLElementDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1610,"slug":"structure-schema","name":"structure_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"type","type":[{"name":"StructureType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false},{"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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"StructureDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBTdHJ1Y3R1cmVUeXBlPGFycmF5PGFycmF5LWtleSwgVD4+fFR5cGU8YXJyYXk8YXJyYXkta2V5LCBUPj4gJHR5cGUKICoKICogQHJldHVybiBTdHJ1Y3R1cmVEZWZpbml0aW9uPFQ+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1628,"slug":"union-schema","name":"union_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"type","type":[{"name":"UnionType","namespace":"Flow\\Types\\Type\\Native","is_nullable":false,"is_variadic":false},{"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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Definition","namespace":"Flow\\ETL\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBUeXBlPG1peGVkPnxVbmlvblR5cGU8bWl4ZWQsIG1peGVkPiAkdHlwZQogKgogKiBAZGVwcmVjYXRlZCBhIGNvbHVtbiBob2xkcyBleGFjdGx5IG9uZSB0eXBlIC0gdXNlIGRlZmluaXRpb25fZnJvbV90eXBlKCkgaW5zdGVhZAogKgogKiBAcmV0dXJuIERlZmluaXRpb248bWl4ZWQ+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1638,"slug":"uuid-schema","name":"uuid_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"UuidDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1644,"slug":"time-zone-schema","name":"time_zone_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"TimeZoneDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1657,"slug":"definition-from-array","name":"definition_from_array","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"definition","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":"Definition","namespace":"Flow\\ETL\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIERlZmluaXRpb24gZnJvbSBhbiBhcnJheSByZXByZXNlbnRhdGlvbi4KICoKICogQHBhcmFtIGFycmF5PGFycmF5LWtleSwgbWl4ZWQ+ICRkZWZpbml0aW9uCiAqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxtaXhlZD4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1690,"slug":"definition-from-type","name":"definition_from_type","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"ref","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":"type","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Definition","namespace":"Flow\\ETL\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIERlZmluaXRpb24gZnJvbSBhIFR5cGUuCiAqCiAqIEBwYXJhbSBUeXBlPG1peGVkPiAkdHlwZQogKgogKiBAcmV0dXJuIERlZmluaXRpb248bWl4ZWQ+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1742,"slug":"infer-schema","name":"infer_schema","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"SchemaInferenceBuilder","namespace":"Flow\\ETL\\Schema\\Inference","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1748,"slug":"execution-context","name":"execution_context","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"config","type":[{"name":"Config","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":"FlowContext","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1754,"slug":"flow-context","name":"flow_context","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"config","type":[{"name":"Config","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":"FlowContext","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1760,"slug":"config","name":"config","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"Config","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1766,"slug":"config-builder","name":"config_builder","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"ConfigBuilder","namespace":"Flow\\ETL\\Config","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1772,"slug":"memory-sort","name":"memory_sort","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"MemorySortBuilder","namespace":"Flow\\ETL\\Config\\Sort","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1778,"slug":"external-sort","name":"external_sort","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"ExternalSortBuilder","namespace":"Flow\\ETL\\Config\\Sort","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1784,"slug":"hash-join","name":"hash_join","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"HashJoinBuilder","namespace":"Flow\\ETL\\Config\\Join","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1790,"slug":"hash-group-by","name":"hash_group_by","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"HashGroupByBuilder","namespace":"Flow\\ETL\\Config\\Grouping","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1796,"slug":"hash-repartition","name":"hash_repartition","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"HashRepartitionBuilder","namespace":"Flow\\ETL\\Config\\Repartition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1805,"slug":"pivot-values","name":"pivot_values","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"values","type":[{"name":"string","namespace":null,"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":true,"default_value":null}],"return_type":[{"name":"DeclaredPivotValues","namespace":"Flow\\ETL\\GroupBy","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIERlY2xhcmVzIHRoZSBwaXZvdCBjb2x1bW5zIGEgZ3JvdXBCeSgpLT5waXZvdCgpIHByb2R1Y2VzLCBzbyB0aGUgcGxhbiBjYW4gbmFtZSB0aGVtIGJlZm9yZSBhIHJvdyBmbG93cy4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1815,"slug":"discover-pivot-values","name":"discover_pivot_values","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"maxValues","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"10000"}],"return_type":[{"name":"DiscoveredPivotValues","namespace":"Flow\\ETL\\GroupBy","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFJlYWRzIHRoZSBwaXZvdCBjb2x1bW4gb25jZSBhdCBidWlsZCB0aW1lIGFuZCB0dXJucyB3aGF0IGl0IGZpbmRzIGludG8gZGVjbGFyZWQgdmFsdWVzLiBSZWZ1c2VzIGEKICogc291cmNlIHRoYXQgY2Fubm90IGJlIHJlYWQgdHdpY2UuCiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1821,"slug":"partition-by","name":"partition_by","namespace":"Flow\\ETL\\DSL","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":"Partitioning","namespace":"Flow\\ETL\\Loader","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1830,"slug":"partition-types","name":"partition_types","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"types","type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"PartitionTypes","namespace":"Flow\\ETL\\Extractor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBUeXBlPG1peGVkPiAuLi4kdHlwZXMgcGFydGl0aW9uIGNvbHVtbiBuYW1lID0+IHR5cGUsIHBhc3NlZCBhcyBuYW1lZCBhcmd1bWVudHMKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1840,"slug":"overwrite","name":"overwrite","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"SaveMode","namespace":"Flow\\ETL\\Filesystem","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEFsaWFzIGZvciBzYXZlX21vZGVfb3ZlcndyaXRlKCkuCiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1846,"slug":"save-mode-overwrite","name":"save_mode_overwrite","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"SaveMode","namespace":"Flow\\ETL\\Filesystem","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1855,"slug":"ignore","name":"ignore","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"SaveMode","namespace":"Flow\\ETL\\Filesystem","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEFsaWFzIGZvciBzYXZlX21vZGVfaWdub3JlKCkuCiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1861,"slug":"save-mode-ignore","name":"save_mode_ignore","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"SaveMode","namespace":"Flow\\ETL\\Filesystem","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1870,"slug":"exception-if-exists","name":"exception_if_exists","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"SaveMode","namespace":"Flow\\ETL\\Filesystem","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEFsaWFzIGZvciBzYXZlX21vZGVfZXhjZXB0aW9uX2lmX2V4aXN0cygpLgogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1876,"slug":"save-mode-exception-if-exists","name":"save_mode_exception_if_exists","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"SaveMode","namespace":"Flow\\ETL\\Filesystem","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1885,"slug":"append","name":"append","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"SaveMode","namespace":"Flow\\ETL\\Filesystem","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEFsaWFzIGZvciBzYXZlX21vZGVfYXBwZW5kKCkuCiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1891,"slug":"save-mode-append","name":"save_mode_append","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"SaveMode","namespace":"Flow\\ETL\\Filesystem","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1897,"slug":"print-rows","name":"print_rows","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"rows","type":[{"name":"Rows","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"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":"false"},{"name":"formatter","type":[{"name":"Formatter","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":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1903,"slug":"identical","name":"identical","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"left","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":"right","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}],"return_type":[{"name":"Identical","namespace":"Flow\\ETL\\Join\\Comparison","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"COMPARISON"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1909,"slug":"equal","name":"equal","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"left","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":"right","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}],"return_type":[{"name":"Equal","namespace":"Flow\\ETL\\Join\\Comparison","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"COMPARISON"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1915,"slug":"compare-all","name":"compare_all","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"comparison","type":[{"name":"Comparison","namespace":"Flow\\ETL\\Join","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"comparisons","type":[{"name":"Comparison","namespace":"Flow\\ETL\\Join","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"All","namespace":"Flow\\ETL\\Join\\Comparison","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"COMPARISON"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1921,"slug":"compare-any","name":"compare_any","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"comparison","type":[{"name":"Comparison","namespace":"Flow\\ETL\\Join","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"comparisons","type":[{"name":"Comparison","namespace":"Flow\\ETL\\Join","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"Any","namespace":"Flow\\ETL\\Join\\Comparison","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"COMPARISON"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1932,"slug":"join-on","name":"join_on","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"comparisons","type":[{"name":"Comparison","namespace":"Flow\\ETL\\Join","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},{"name":"join_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":"Expression","namespace":"Flow\\ETL\\Join","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"joins","example":"join"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"joins","example":"join_each"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxDb21wYXJpc29ufHN0cmluZz58Q29tcGFyaXNvbiAkY29tcGFyaXNvbnMKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1938,"slug":"schema-sort-by-name","name":"schema_sort_by_name","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"order","type":[{"name":"SortOrder","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Row\\SortOrder::..."}],"return_type":[{"name":"SortingStrategy","namespace":"Flow\\ETL\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1947,"slug":"schema-sort-by-type","name":"schema_sort_by_type","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"priorities","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[...]"},{"name":"order","type":[{"name":"SortOrder","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Row\\SortOrder::..."}],"return_type":[{"name":"SortingStrategy","namespace":"Flow\\ETL\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxjbGFzcy1zdHJpbmc8VHlwZTxtaXhlZD4+LCBpbnQ+ICRwcmlvcml0aWVzCiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1958,"slug":"schema-sort-by-type-and-name","name":"schema_sort_by_type_and_name","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"priorities","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[...]"},{"name":"order","type":[{"name":"SortOrder","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Row\\SortOrder::..."}],"return_type":[{"name":"SortingStrategy","namespace":"Flow\\ETL\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxjbGFzcy1zdHJpbmc8VHlwZTxtaXhlZD4+LCBpbnQ+ICRwcmlvcml0aWVzCiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1969,"slug":"schema-sort-by-metadata","name":"schema_sort_by_metadata","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"key","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":"order","type":[{"name":"SortOrder","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Row\\SortOrder::..."}],"return_type":[{"name":"SortingStrategy","namespace":"Flow\\ETL\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1979,"slug":"is-type","name":"is_type","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"type","type":[{"name":"Type","namespace":"Flow\\Types","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},{"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":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxzdHJpbmd8VHlwZTxtaXhlZD4+fFR5cGU8bWl4ZWQ+ICR0eXBlCiAqIEBwYXJhbSBtaXhlZCAkdmFsdWUKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2013,"slug":"generate-random-string","name":"generate_random_string","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"length","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"32"},{"name":"generator","type":[{"name":"RandomValueGenerator","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\NativePHPRandomValueGenerator::..."}],"return_type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2021,"slug":"generate-random-int","name":"generate_random_int","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"start","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"-9223372036854775808"},{"name":"end","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"9223372036854775807"},{"name":"generator","type":[{"name":"RandomValueGenerator","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\NativePHPRandomValueGenerator::..."}],"return_type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2030,"slug":"random-string","name":"random_string","namespace":"Flow\\ETL\\DSL","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":"generator","type":[{"name":"RandomValueGenerator","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\NativePHPRandomValueGenerator::..."}],"return_type":[{"name":"RandomString","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2038,"slug":"date-interval-to-milliseconds","name":"date_interval_to_milliseconds","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"interval","type":[{"name":"DateInterval","namespace":"","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2055,"slug":"date-interval-to-seconds","name":"date_interval_to_seconds","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"interval","type":[{"name":"DateInterval","namespace":"","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2072,"slug":"date-interval-to-microseconds","name":"date_interval_to_microseconds","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"interval","type":[{"name":"DateInterval","namespace":"","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2089,"slug":"with-entry","name":"with_entry","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","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":"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":"WithEntry","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2095,"slug":"constraint-unique","name":"constraint_unique","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"reference","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":"references","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":"UniqueConstraint","namespace":"Flow\\ETL\\Constraint","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2101,"slug":"constraint-sorted-by","name":"constraint_sorted_by","namespace":"Flow\\ETL\\DSL","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":"columns","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":"SortedByConstraint","namespace":"Flow\\ETL\\Constraint","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2111,"slug":"analyze","name":"analyze","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"Analyze","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2120,"slug":"match-cases","name":"match_cases","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"cases","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":"default","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"MatchCases","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxNYXRjaENvbmRpdGlvbj4gJGNhc2VzCiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2126,"slug":"match-condition","name":"match_condition","namespace":"Flow\\ETL\\DSL","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":"then","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":"MatchCondition","namespace":"Flow\\ETL\\Function\\MatchCases","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2132,"slug":"clock","name":"clock","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"time_zone","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'UTC'"}],"return_type":[{"name":"ClockInterface","namespace":"Psr\\Clock","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/Floe\/DSL\/functions.php","start_line_in_file":31,"slug":"from-floe","name":"from_floe","namespace":"Flow\\Floe\\DSL","parameters":[{"name":"path","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"codec","type":[{"name":"Codec","namespace":"Flow\\Floe","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Floe\\Codec\\NoopCodec::..."},{"name":"chunk_size","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"65536"},{"name":"engine","type":[{"name":"FloeEngine","namespace":"Flow\\Floe","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Floe\\FloeEngine::..."},{"name":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"FloeExtractor","namespace":"Flow\\Floe","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"FLOE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBQYXRofHN0cmluZyAkcGF0aAogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/Floe\/DSL\/functions.php","start_line_in_file":45,"slug":"to-floe","name":"to_floe","namespace":"Flow\\Floe\\DSL","parameters":[{"name":"path","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"options","type":[{"name":"Options","namespace":"Flow\\Floe","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Floe\\Options::..."},{"name":"engine","type":[{"name":"FloeEngine","namespace":"Flow\\Floe","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Floe\\FloeEngine::..."},{"name":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"FloeLoader","namespace":"Flow\\Floe","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"FLOE","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBQYXRofHN0cmluZyAkcGF0aAogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/Floe\/DSL\/functions.php","start_line_in_file":56,"slug":"floe-options","name":"floe_options","namespace":"Flow\\Floe\\DSL","parameters":[{"name":"buffer_size","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"65536"},{"name":"codec","type":[{"name":"Codec","namespace":"Flow\\Floe","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Floe\\Codec\\NoopCodec::..."}],"return_type":[{"name":"Options","namespace":"Flow\\Floe","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"FLOE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/Floe\/DSL\/functions.php","start_line_in_file":68,"slug":"merge-floe","name":"merge_floe","namespace":"Flow\\Floe\\DSL","parameters":[{"name":"sources","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":"dest","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"compact","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"void","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"FLOE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIE1lcmdlcyBzZXZlcmFsIEZsb2UgZmlsZXMgKHNhbWUgb3IgYXBwZW5kLWNvbXBhdGlibGUgZXZvbHZpbmcgc2NoZW1hKSBpbnRvIG9uZS4gQnl0ZS1zcGxpY2VzIGZyYW1lCiAqIHJlZ2lvbnMgYnkgZGVmYXVsdCAoTyhieXRlcyksIG5vIHJlLWVuY29kZSk7IGNvbXBhY3QgcmUtZW5jb2RlcyBhbGwgcm93cyBpbnRvIGZld2VyIHNlY3Rpb25zLgogKgogKiBAcGFyYW0gYXJyYXk8aW50LCBQYXRofHN0cmluZz4gJHNvdXJjZXMKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/Serializer\/DSL\/functions.php","start_line_in_file":18,"slug":"serialize-to-string","name":"serialize_to_string","namespace":"Flow\\Serializer\\DSL","parameters":[{"name":"serializer","type":[{"name":"Serializer","namespace":"Flow\\Serializer","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"rows","type":[{"name":"Rows","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":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/Serializer\/DSL\/functions.php","start_line_in_file":27,"slug":"unserialize-from-string","name":"unserialize_from_string","namespace":"Flow\\Serializer\\DSL","parameters":[{"name":"serializer","type":[{"name":"Serializer","namespace":"Flow\\Serializer","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"payload","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":"Rows","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-avro\/src\/Flow\/ETL\/Adapter\/Avro\/functions.php","start_line_in_file":21,"slug":"from-avro","name":"from_avro","namespace":"Flow\\ETL\\DSL\\Adapter\\Avro","parameters":[{"name":"path","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"AvroExtractor","namespace":"Flow\\ETL\\Adapter\\Avro\\FlixTech","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"AVRO","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-avro\/src\/Flow\/ETL\/Adapter\/Avro\/functions.php","start_line_in_file":27,"slug":"to-avro","name":"to_avro","namespace":"Flow\\ETL\\DSL\\Adapter\\Avro","parameters":[{"name":"path","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"schema","type":[{"name":"Schema","namespace":"Flow\\ETL","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"AvroLoader","namespace":"Flow\\ETL\\Adapter\\Avro\\FlixTech","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"AVRO","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-chartjs\/src\/Flow\/ETL\/Adapter\/ChartJS\/functions.php","start_line_in_file":23,"slug":"bar-chart","name":"bar_chart","namespace":"Flow\\ETL\\Adapter\\ChartJS","parameters":[{"name":"label","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":"datasets","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":"BarChart","namespace":"Flow\\ETL\\Adapter\\ChartJS\\Chart","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CHART_JS","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-chartjs\/src\/Flow\/ETL\/Adapter\/ChartJS\/functions.php","start_line_in_file":29,"slug":"line-chart","name":"line_chart","namespace":"Flow\\ETL\\Adapter\\ChartJS","parameters":[{"name":"label","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":"datasets","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":"LineChart","namespace":"Flow\\ETL\\Adapter\\ChartJS\\Chart","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CHART_JS","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-chartjs\/src\/Flow\/ETL\/Adapter\/ChartJS\/functions.php","start_line_in_file":35,"slug":"pie-chart","name":"pie_chart","namespace":"Flow\\ETL\\Adapter\\ChartJS","parameters":[{"name":"label","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":"datasets","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":"PieChart","namespace":"Flow\\ETL\\Adapter\\ChartJS\\Chart","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CHART_JS","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-chartjs\/src\/Flow\/ETL\/Adapter\/ChartJS\/functions.php","start_line_in_file":41,"slug":"to-chartjs","name":"to_chartjs","namespace":"Flow\\ETL\\Adapter\\ChartJS","parameters":[{"name":"type","type":[{"name":"Chart","namespace":"Flow\\ETL\\Adapter\\ChartJS","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ChartJSLoader","namespace":"Flow\\ETL\\Adapter\\ChartJS","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CHART_JS","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-chartjs\/src\/Flow\/ETL\/Adapter\/ChartJS\/functions.php","start_line_in_file":52,"slug":"to-chartjs-file","name":"to_chartjs_file","namespace":"Flow\\ETL\\Adapter\\ChartJS","parameters":[{"name":"type","type":[{"name":"Chart","namespace":"Flow\\ETL\\Adapter\\ChartJS","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"output","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"template","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"ChartJSLoader","namespace":"Flow\\ETL\\Adapter\\ChartJS","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CHART_JS","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBDaGFydCAkdHlwZQogKiBAcGFyYW0gbnVsbHxQYXRofHN0cmluZyAkb3V0cHV0IC0gQGRlcHJlY2F0ZWQgdXNlICRsb2FkZXItPndpdGhPdXRwdXRQYXRoKCkgaW5zdGVhZAogKiBAcGFyYW0gbnVsbHxQYXRofHN0cmluZyAkdGVtcGxhdGUgLSBAZGVwcmVjYXRlZCB1c2UgJGxvYWRlci0+d2l0aFRlbXBsYXRlKCkgaW5zdGVhZAogKi8="},{"repository_path":"src\/adapter\/etl-adapter-chartjs\/src\/Flow\/ETL\/Adapter\/ChartJS\/functions.php","start_line_in_file":84,"slug":"to-chartjs-var","name":"to_chartjs_var","namespace":"Flow\\ETL\\Adapter\\ChartJS","parameters":[{"name":"type","type":[{"name":"Chart","namespace":"Flow\\ETL\\Adapter\\ChartJS","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"output","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":"ChartJSLoader","namespace":"Flow\\ETL\\Adapter\\ChartJS","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CHART_JS","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBDaGFydCAkdHlwZQogKiBAcGFyYW0gYXJyYXk8YXJyYXkta2V5LCBtaXhlZD4gJG91dHB1dCAtIEBkZXByZWNhdGVkIHVzZSAkbG9hZGVyLT53aXRoT3V0cHV0VmFyKCkgaW5zdGVhZAogKi8="},{"repository_path":"src\/adapter\/etl-adapter-csv\/src\/Flow\/ETL\/Adapter\/CSV\/functions.php","start_line_in_file":35,"slug":"from-csv","name":"from_csv","namespace":"Flow\\ETL\\Adapter\\CSV","parameters":[{"name":"path","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"with_header","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"empty_to_null","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"separator","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":"enclosure","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":"escape","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":"characters_read_in_line","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"10485760"},{"name":"schema","type":[{"name":"Schema","namespace":"Flow\\ETL","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"CSVExtractor","namespace":"Flow\\ETL\\Adapter\\CSV","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CSV","type":"EXTRACTOR"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"reading","example":"csv"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBQYXRofHN0cmluZyAkcGF0aAogKiBAcGFyYW0gYm9vbCAkZW1wdHlfdG9fbnVsbCAtIEBkZXByZWNhdGVkIHVzZSAkbG9hZGVyLT53aXRoRW1wdHlUb051bGwoKSBpbnN0ZWFkCiAqIEBwYXJhbSBib29sICR3aXRoX2hlYWRlciAtIEBkZXByZWNhdGVkIHVzZSAkbG9hZGVyLT53aXRoSGVhZGVyKCkgaW5zdGVhZAogKiBAcGFyYW0gbnVsbHxzdHJpbmcgJHNlcGFyYXRvciAtIEBkZXByZWNhdGVkIHVzZSAkbG9hZGVyLT53aXRoU2VwYXJhdG9yKCkgaW5zdGVhZAogKiBAcGFyYW0gbnVsbHxzdHJpbmcgJGVuY2xvc3VyZSAtIEBkZXByZWNhdGVkIHVzZSAkbG9hZGVyLT53aXRoRW5jbG9zdXJlKCkgaW5zdGVhZAogKiBAcGFyYW0gbnVsbHxzdHJpbmcgJGVzY2FwZSAtIEBkZXByZWNhdGVkIHVzZSAkbG9hZGVyLT53aXRoRXNjYXBlKCkgaW5zdGVhZAogKiBAcGFyYW0gaW50PDEsIG1heD4gJGNoYXJhY3RlcnNfcmVhZF9pbl9saW5lIC0gQGRlcHJlY2F0ZWQgdXNlICRsb2FkZXItPndpdGhDaGFyYWN0ZXJzUmVhZEluTGluZSgpIGluc3RlYWQKICogQHBhcmFtIG51bGx8U2NoZW1hICRzY2hlbWEgLSBAZGVwcmVjYXRlZCB1c2UgJGxvYWRlci0+d2l0aFNjaGVtYSgpIGluc3RlYWQKICov"},{"repository_path":"src\/adapter\/etl-adapter-csv\/src\/Flow\/ETL\/Adapter\/CSV\/functions.php","start_line_in_file":80,"slug":"to-csv","name":"to_csv","namespace":"Flow\\ETL\\Adapter\\CSV","parameters":[{"name":"uri","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"with_header","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"separator","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"','"},{"name":"enclosure","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'\\\"'"},{"name":"escape","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'\\\\'"},{"name":"new_line_separator","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'\\n'"},{"name":"datetime_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\\\\TH:i:sP'"},{"name":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"CSVLoader","namespace":"Flow\\ETL\\Adapter\\CSV","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CSV","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBQYXRofHN0cmluZyAkdXJpCiAqIEBwYXJhbSBib29sICR3aXRoX2hlYWRlciAtIEBkZXByZWNhdGVkIHVzZSAkbG9hZGVyLT53aXRoSGVhZGVyKCkgaW5zdGVhZAogKiBAcGFyYW0gc3RyaW5nICRzZXBhcmF0b3IgLSBAZGVwcmVjYXRlZCB1c2UgJGxvYWRlci0+d2l0aFNlcGFyYXRvcigpIGluc3RlYWQKICogQHBhcmFtIHN0cmluZyAkZW5jbG9zdXJlIC0gQGRlcHJlY2F0ZWQgdXNlICRsb2FkZXItPndpdGhFbmNsb3N1cmUoKSBpbnN0ZWFkCiAqIEBwYXJhbSBzdHJpbmcgJGVzY2FwZSAtIEBkZXByZWNhdGVkIHVzZSAkbG9hZGVyLT53aXRoRXNjYXBlKCkgaW5zdGVhZAogKiBAcGFyYW0gc3RyaW5nICRuZXdfbGluZV9zZXBhcmF0b3IgLSBAZGVwcmVjYXRlZCB1c2UgJGxvYWRlci0+d2l0aE5ld0xpbmVTZXBhcmF0b3IoKSBpbnN0ZWFkCiAqIEBwYXJhbSBzdHJpbmcgJGRhdGV0aW1lX2Zvcm1hdCAtIEBkZXByZWNhdGVkIHVzZSAkbG9hZGVyLT53aXRoRGF0ZVRpbWVGb3JtYXQoKSBpbnN0ZWFkCiAqLw=="},{"repository_path":"src\/adapter\/etl-adapter-csv\/src\/Flow\/ETL\/Adapter\/CSV\/functions.php","start_line_in_file":106,"slug":"csv-detect-separator","name":"csv_detect_separator","namespace":"Flow\\ETL\\Adapter\\CSV","parameters":[{"name":"stream","type":[{"name":"SourceStream","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"lines","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"5"},{"name":"fallback","type":[{"name":"Option","namespace":"Flow\\ETL\\Adapter\\CSV\\Detector","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"Flow\\ETL\\Adapter\\CSV\\Detector\\Option::..."},{"name":"options","type":[{"name":"Options","namespace":"Flow\\ETL\\Adapter\\CSV\\Detector","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Option","namespace":"Flow\\ETL\\Adapter\\CSV\\Detector","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"CSV","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBTb3VyY2VTdHJlYW0gJHN0cmVhbSAtIHZhbGlkIHJlc291cmNlIHRvIENTViBmaWxlCiAqIEBwYXJhbSBpbnQ8MSwgbWF4PiAkbGluZXMgLSBudW1iZXIgb2YgbGluZXMgdG8gcmVhZCBmcm9tIENTViBmaWxlLCBkZWZhdWx0IDUsIG1vcmUgbGluZXMgbWVhbnMgbW9yZSBhY2N1cmF0ZSBkZXRlY3Rpb24gYnV0IHNsb3dlciBkZXRlY3Rpb24KICogQHBhcmFtIG51bGx8T3B0aW9uICRmYWxsYmFjayAtIGZhbGxiYWNrIG9wdGlvbiB0byB1c2Ugd2hlbiBubyBiZXN0IG9wdGlvbiBjYW4gYmUgZGV0ZWN0ZWQsIGRlZmF1bHQgaXMgT3B0aW9uKCcsJywgJyInLCAnXFwnKQogKiBAcGFyYW0gbnVsbHxPcHRpb25zICRvcHRpb25zIC0gb3B0aW9ucyB0byB1c2UgZm9yIGRldGVjdGlvbiwgZGVmYXVsdCBpcyBPcHRpb25zOjphbGwoKQogKi8="},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":41,"slug":"dbal-dataframe-factory","name":"dbal_dataframe_factory","namespace":"Flow\\ETL\\Adapter\\Doctrine","parameters":[{"name":"connection","type":[{"name":"Connection","namespace":"Doctrine\\DBAL","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},{"name":"query","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":"parameters","type":[{"name":"QueryParameter","namespace":"Flow\\ETL\\Adapter\\Doctrine","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"DbalDataFrameFactory","namespace":"Flow\\ETL\\Adapter\\Doctrine","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"DOCTRINE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxzdHJpbmcsIG1peGVkPnxDb25uZWN0aW9uICRjb25uZWN0aW9uCiAqIEBwYXJhbSBzdHJpbmcgJHF1ZXJ5CiAqIEBwYXJhbSBRdWVyeVBhcmFtZXRlciAuLi4kcGFyYW1ldGVycwogKi8="},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":61,"slug":"from-dbal-limit-offset","name":"from_dbal_limit_offset","namespace":"Flow\\ETL\\Adapter\\Doctrine","parameters":[{"name":"connection","type":[{"name":"Connection","namespace":"Doctrine\\DBAL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"table","type":[{"name":"Table","namespace":"Flow\\ETL\\Adapter\\Doctrine","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":"order_by","type":[{"name":"OrderBy","namespace":"Flow\\ETL\\Adapter\\Doctrine","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},{"name":"page_size","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"1000"},{"name":"maximum","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":"DbalLimitOffsetExtractor","namespace":"Flow\\ETL\\Adapter\\Doctrine","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"DOCTRINE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBDb25uZWN0aW9uICRjb25uZWN0aW9uCiAqIEBwYXJhbSBzdHJpbmd8VGFibGUgJHRhYmxlCiAqIEBwYXJhbSBhcnJheTxPcmRlckJ5PnxPcmRlckJ5ICRvcmRlcl9ieQogKiBAcGFyYW0gaW50ICRwYWdlX3NpemUgLSBiZWNvbWVzIHRoZSBleHRyYWN0b3IncyBiYXRjaCBzaXplOiByb3dzIHBlciBwYWdlCiAqIEBwYXJhbSBudWxsfGludCAkbWF4aW11bQogKgogKiBAdGhyb3dzIEludmFsaWRBcmd1bWVudEV4Y2VwdGlvbgogKi8="},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":88,"slug":"from-dbal-limit-offset-qb","name":"from_dbal_limit_offset_qb","namespace":"Flow\\ETL\\Adapter\\Doctrine","parameters":[{"name":"connection","type":[{"name":"Connection","namespace":"Doctrine\\DBAL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"queryBuilder","type":[{"name":"QueryBuilder","namespace":"Doctrine\\DBAL\\Query","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"page_size","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"1000"},{"name":"maximum","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":"offset","type":[{"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":"DbalLimitOffsetExtractor","namespace":"Flow\\ETL\\Adapter\\Doctrine","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"DOCTRINE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBDb25uZWN0aW9uICRjb25uZWN0aW9uCiAqIEBwYXJhbSBpbnQgJHBhZ2Vfc2l6ZSAtIGJlY29tZXMgdGhlIGV4dHJhY3RvcidzIGJhdGNoIHNpemU6IHJvd3MgcGVyIHBhZ2UKICogQHBhcmFtIG51bGx8aW50ICRtYXhpbXVtIC0gbWF4aW11bSBjYW4gYWxzbyBiZSB0YWtlbiBmcm9tIGEgcXVlcnkgYnVpbGRlciwgJG1heGltdW0gaG93ZXZlciBpcyB1c2VkIHJlZ2FyZGxlc3Mgb2YgdGhlIHF1ZXJ5IGJ1aWxkZXIgaWYgaXQncyBzZXQKICogQHBhcmFtIGludCAkb2Zmc2V0IC0gb2Zmc2V0IGNhbiBhbHNvIGJlIHRha2VuIGZyb20gYSBxdWVyeSBidWlsZGVyLCAkb2Zmc2V0IGhvd2V2ZXIgaXMgdXNlZCByZWdhcmRsZXNzIG9mIHRoZSBxdWVyeSBidWlsZGVyIGlmIGl0J3Mgc2V0IHRvIG5vbiAwIHZhbHVlCiAqLw=="},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":107,"slug":"from-dbal-key-set-qb","name":"from_dbal_key_set_qb","namespace":"Flow\\ETL\\Adapter\\Doctrine","parameters":[{"name":"connection","type":[{"name":"Connection","namespace":"Doctrine\\DBAL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"queryBuilder","type":[{"name":"QueryBuilder","namespace":"Doctrine\\DBAL\\Query","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"key_set","type":[{"name":"KeySet","namespace":"Flow\\ETL\\Adapter\\Doctrine\\Pagination","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"DbalKeySetExtractor","namespace":"Flow\\ETL\\Adapter\\Doctrine","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"DOCTRINE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":117,"slug":"from-dbal-queries","name":"from_dbal_queries","namespace":"Flow\\ETL\\Adapter\\Doctrine","parameters":[{"name":"connection","type":[{"name":"Connection","namespace":"Doctrine\\DBAL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"query","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":"parameters_set","type":[{"name":"ParametersSet","namespace":"Flow\\ETL\\Adapter\\Doctrine","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"types","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"DbalQueryExtractor","namespace":"Flow\\ETL\\Adapter\\Doctrine","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"DOCTRINE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBudWxsfFBhcmFtZXRlcnNTZXQgJHBhcmFtZXRlcnNfc2V0IC0gZWFjaCBvbmUgcGFyYW1ldGVycyBhcnJheSB3aWxsIGJlIGV2YWx1YXRlZCBhcyBuZXcgcXVlcnkKICogQHBhcmFtIGFycmF5PGludDwwLCBtYXg+fHN0cmluZywgRGJhbEFycmF5VHlwZXxEYmFsUGFyYW1ldGVyVHlwZXxEYmFsVHlwZXxzdHJpbmc+ICR0eXBlcwogKi8="},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":143,"slug":"dbal-from-queries","name":"dbal_from_queries","namespace":"Flow\\ETL\\Adapter\\Doctrine","parameters":[{"name":"connection","type":[{"name":"Connection","namespace":"Doctrine\\DBAL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"query","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":"parameters_set","type":[{"name":"ParametersSet","namespace":"Flow\\ETL\\Adapter\\Doctrine","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"types","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"DbalQueryExtractor","namespace":"Flow\\ETL\\Adapter\\Doctrine","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"DOCTRINE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBkZXByZWNhdGVkIHVzZSBmcm9tX2RiYWxfcXVlcmllcygpIGluc3RlYWQKICoKICogQHBhcmFtIG51bGx8UGFyYW1ldGVyc1NldCAkcGFyYW1ldGVyc19zZXQgLSBlYWNoIG9uZSBwYXJhbWV0ZXJzIGFycmF5IHdpbGwgYmUgZXZhbHVhdGVkIGFzIG5ldyBxdWVyeQogKiBAcGFyYW0gYXJyYXk8aW50PDAsIG1heD58c3RyaW5nLCBEYmFsQXJyYXlUeXBlfERiYWxQYXJhbWV0ZXJUeXBlfERiYWxUeXBlfHN0cmluZz4gJHR5cGVzCiAqLw=="},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":157,"slug":"from-dbal-query","name":"from_dbal_query","namespace":"Flow\\ETL\\Adapter\\Doctrine","parameters":[{"name":"connection","type":[{"name":"Connection","namespace":"Doctrine\\DBAL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"query","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":"parameters","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"types","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"DbalQueryExtractor","namespace":"Flow\\ETL\\Adapter\\Doctrine","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"DOCTRINE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxzdHJpbmcsIG1peGVkPnxsaXN0PG1peGVkPiAkcGFyYW1ldGVycyAtIEBkZXByZWNhdGVkIHVzZSBEYmFsUXVlcnlFeHRyYWN0b3I6OndpdGhQYXJhbWV0ZXJzKCkgaW5zdGVhZAogKiBAcGFyYW0gYXJyYXk8aW50PDAsIG1heD58c3RyaW5nLCBEYmFsQXJyYXlUeXBlfERiYWxQYXJhbWV0ZXJUeXBlfERiYWxUeXBlfHN0cmluZz4gJHR5cGVzIC0gQGRlcHJlY2F0ZWQgdXNlIERiYWxRdWVyeUV4dHJhY3Rvcjo6d2l0aFR5cGVzKCkgaW5zdGVhZAogKi8="},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":173,"slug":"dbal-from-query","name":"dbal_from_query","namespace":"Flow\\ETL\\Adapter\\Doctrine","parameters":[{"name":"connection","type":[{"name":"Connection","namespace":"Doctrine\\DBAL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"query","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":"parameters","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"types","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"DbalQueryExtractor","namespace":"Flow\\ETL\\Adapter\\Doctrine","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"DOCTRINE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBkZXByZWNhdGVkIHVzZSBmcm9tX2RiYWxfcXVlcnkoKSBpbnN0ZWFkCiAqCiAqIEBwYXJhbSBhcnJheTxzdHJpbmcsIG1peGVkPnxsaXN0PG1peGVkPiAkcGFyYW1ldGVycyAtIEBkZXByZWNhdGVkIHVzZSBEYmFsUXVlcnlFeHRyYWN0b3I6OndpdGhQYXJhbWV0ZXJzKCkgaW5zdGVhZAogKiBAcGFyYW0gYXJyYXk8aW50PDAsIG1heD58c3RyaW5nLCBEYmFsQXJyYXlUeXBlfERiYWxQYXJhbWV0ZXJUeXBlfERiYWxUeXBlfHN0cmluZz4gJHR5cGVzIC0gQGRlcHJlY2F0ZWQgdXNlIERiYWxRdWVyeUV4dHJhY3Rvcjo6d2l0aFR5cGVzKCkgaW5zdGVhZAogKi8="},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":199,"slug":"to-dbal-table-insert","name":"to_dbal_table_insert","namespace":"Flow\\ETL\\Adapter\\Doctrine","parameters":[{"name":"connection","type":[{"name":"Connection","namespace":"Doctrine\\DBAL","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},{"name":"table","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":"options","type":[{"name":"InsertOptions","namespace":"Flow\\Doctrine\\Bulk","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"DbalLoader","namespace":"Flow\\ETL\\Adapter\\Doctrine","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"DOCTRINE","type":"LOADER"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"writing","example":"dbal","option":"upsert"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEluc2VydCBuZXcgcm93cyBpbnRvIGEgZGF0YWJhc2UgdGFibGUuCiAqIEluc2VydCBjYW4gYWxzbyBiZSB1c2VkIGFzIGFuIHVwc2VydCB3aXRoIHRoZSBoZWxwIG9mIEluc2VydE9wdGlvbnMuCiAqIEluc2VydE9wdGlvbnMgYXJlIHBsYXRmb3JtIHNwZWNpZmljLCBzbyBwbGVhc2UgY2hvb3NlIHRoZSByaWdodCBvbmUgZm9yIHlvdXIgZGF0YWJhc2UuCiAqCiAqICAtIE15U1FMSW5zZXJ0T3B0aW9ucwogKiAgLSBQb3N0Z3JlU1FMSW5zZXJ0T3B0aW9ucwogKiAgLSBTcWxpdGVJbnNlcnRPcHRpb25zCiAqCiAqIEluIG9yZGVyIHRvIGNvbnRyb2wgdGhlIHNpemUgb2YgdGhlIHNpbmdsZSBpbnNlcnQsIHVzZSBEYXRhRnJhbWU6OmNodW5rU2l6ZSgpIG1ldGhvZCBqdXN0IGJlZm9yZSBjYWxsaW5nIERhdGFGcmFtZTo6bG9hZCgpLgogKgogKiBAcGFyYW0gYXJyYXk8c3RyaW5nLCBtaXhlZD58Q29ubmVjdGlvbiAkY29ubmVjdGlvbgogKgogKiBAdGhyb3dzIEludmFsaWRBcmd1bWVudEV4Y2VwdGlvbgogKi8="},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":216,"slug":"to-dbal-table-update","name":"to_dbal_table_update","namespace":"Flow\\ETL\\Adapter\\Doctrine","parameters":[{"name":"connection","type":[{"name":"Connection","namespace":"Doctrine\\DBAL","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},{"name":"table","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":"options","type":[{"name":"UpdateOptions","namespace":"Flow\\Doctrine\\Bulk","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"DbalLoader","namespace":"Flow\\ETL\\Adapter\\Doctrine","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"DOCTRINE","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqICBVcGRhdGUgZXhpc3Rpbmcgcm93cyBpbiBkYXRhYmFzZS4KICoKICogIEluIG9yZGVyIHRvIGNvbnRyb2wgdGhlIHNpemUgb2YgdGhlIHNpbmdsZSByZXF1ZXN0LCB1c2UgRGF0YUZyYW1lOjpjaHVua1NpemUoKSBtZXRob2QganVzdCBiZWZvcmUgY2FsbGluZyBEYXRhRnJhbWU6OmxvYWQoKS4KICoKICogQHBhcmFtIGFycmF5PHN0cmluZywgbWl4ZWQ+fENvbm5lY3Rpb24gJGNvbm5lY3Rpb24KICoKICogQHRocm93cyBJbnZhbGlkQXJndW1lbnRFeGNlcHRpb24KICov"},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":235,"slug":"to-dbal-table-delete","name":"to_dbal_table_delete","namespace":"Flow\\ETL\\Adapter\\Doctrine","parameters":[{"name":"connection","type":[{"name":"Connection","namespace":"Doctrine\\DBAL","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},{"name":"table","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":"DbalLoader","namespace":"Flow\\ETL\\Adapter\\Doctrine","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"DOCTRINE","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIERlbGV0ZSByb3dzIGZyb20gZGF0YWJhc2UgdGFibGUgYmFzZWQgb24gdGhlIHByb3ZpZGVkIGRhdGEuCiAqCiAqIEluIG9yZGVyIHRvIGNvbnRyb2wgdGhlIHNpemUgb2YgdGhlIHNpbmdsZSByZXF1ZXN0LCB1c2UgRGF0YUZyYW1lOjpjaHVua1NpemUoKSBtZXRob2QganVzdCBiZWZvcmUgY2FsbGluZyBEYXRhRnJhbWU6OmxvYWQoKS4KICoKICogQHBhcmFtIGFycmF5PHN0cmluZywgbWl4ZWQ+fENvbm5lY3Rpb24gJGNvbm5lY3Rpb24KICoKICogQHRocm93cyBJbnZhbGlkQXJndW1lbnRFeGNlcHRpb24KICov"},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":250,"slug":"to-dbal-schema-table","name":"to_dbal_schema_table","namespace":"Flow\\ETL\\Adapter\\Doctrine","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":"table_name","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":"table_options","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"types_map","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"Table","namespace":"Doctrine\\DBAL\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"DOCTRINE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENvbnZlcnRzIGEgRmxvd1xFVExcU2NoZW1hIHRvIGEgRG9jdHJpbmVcREJBTFxTY2hlbWFcVGFibGUuCiAqCiAqIEBwYXJhbSBTY2hlbWEgJHNjaGVtYQogKiBAcGFyYW0gYXJyYXk8c3RyaW5nLCBtaXhlZD4gJHRhYmxlX29wdGlvbnMKICogQHBhcmFtIGFycmF5PGNsYXNzLXN0cmluZzxcRmxvd1xUeXBlc1xUeXBlPG1peGVkPj4sIGNsYXNzLXN0cmluZzxcRG9jdHJpbmVcREJBTFxUeXBlc1xUeXBlPj4gJHR5cGVzX21hcAogKi8="},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":267,"slug":"table-schema-to-flow-schema","name":"table_schema_to_flow_schema","namespace":"Flow\\ETL\\Adapter\\Doctrine","parameters":[{"name":"table","type":[{"name":"Table","namespace":"Doctrine\\DBAL\\Schema","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"types_map","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"Schema","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"DOCTRINE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENvbnZlcnRzIGEgRG9jdHJpbmVcREJBTFxTY2hlbWFcVGFibGUgdG8gYSBGbG93XEVUTFxTY2hlbWEuCiAqCiAqIEBwYXJhbSBhcnJheTxjbGFzcy1zdHJpbmc8XEZsb3dcVHlwZXNcVHlwZTxtaXhlZD4+LCBjbGFzcy1zdHJpbmc8XERvY3RyaW5lXERCQUxcVHlwZXNcVHlwZT4+ICR0eXBlc19tYXAKICoKICogQHJldHVybiBTY2hlbWEKICov"},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":278,"slug":"postgresql-insert-options","name":"postgresql_insert_options","namespace":"Flow\\ETL\\Adapter\\Doctrine","parameters":[{"name":"skip_conflicts","type":[{"name":"bool","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"constraint","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":"conflict_columns","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"update_columns","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"PostgreSQLInsertOptions","namespace":"Flow\\Doctrine\\Bulk\\Dialect","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"DOCTRINE","type":"HELPER"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"writing","example":"dbal","option":"upsert"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxzdHJpbmc+ICRjb25mbGljdF9jb2x1bW5zCiAqIEBwYXJhbSBhcnJheTxzdHJpbmc+ICR1cGRhdGVfY29sdW1ucwogKi8="},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":291,"slug":"mysql-insert-options","name":"mysql_insert_options","namespace":"Flow\\ETL\\Adapter\\Doctrine","parameters":[{"name":"skip_conflicts","type":[{"name":"bool","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"upsert","type":[{"name":"bool","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"update_columns","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"MySQLInsertOptions","namespace":"Flow\\Doctrine\\Bulk\\Dialect","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"DOCTRINE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxzdHJpbmc+ICR1cGRhdGVfY29sdW1ucwogKi8="},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":304,"slug":"sqlite-insert-options","name":"sqlite_insert_options","namespace":"Flow\\ETL\\Adapter\\Doctrine","parameters":[{"name":"skip_conflicts","type":[{"name":"bool","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"conflict_columns","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"update_columns","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"SqliteInsertOptions","namespace":"Flow\\Doctrine\\Bulk\\Dialect","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"DOCTRINE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxzdHJpbmc+ICRjb25mbGljdF9jb2x1bW5zCiAqIEBwYXJhbSBhcnJheTxzdHJpbmc+ICR1cGRhdGVfY29sdW1ucwogKi8="},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":317,"slug":"postgresql-update-options","name":"postgresql_update_options","namespace":"Flow\\ETL\\Adapter\\Doctrine","parameters":[{"name":"primary_key_columns","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"update_columns","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"PostgreSQLUpdateOptions","namespace":"Flow\\Doctrine\\Bulk\\Dialect","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"DOCTRINE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxzdHJpbmc+ICRwcmltYXJ5X2tleV9jb2x1bW5zCiAqIEBwYXJhbSBhcnJheTxzdHJpbmc+ICR1cGRhdGVfY29sdW1ucwogKi8="},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":338,"slug":"to-dbal-transaction","name":"to_dbal_transaction","namespace":"Flow\\ETL\\Adapter\\Doctrine","parameters":[{"name":"connection","type":[{"name":"Connection","namespace":"Doctrine\\DBAL","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},{"name":"sinks","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":true,"default_value":null}],"return_type":[{"name":"Transactional","namespace":"Flow\\ETL\\Sink","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"DOCTRINE","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFdyaXRlIGV2ZXJ5IHNpbmsgd2l0aGluIGRhdGFiYXNlIHRyYW5zYWN0aW9ucy4KICogRWFjaCBiYXRjaCBvZiByb3dzIGlzIHdyaXR0ZW4gaW4gaXRzIG93biB0cmFuc2FjdGlvbjsgcm93cyBhIHNpbmsncyBUcmFuc2Zvcm1hdGlvbiBkZWxpdmVycyB3aGVuCiAqIHRoZSBydW4gZW5kcyAoYmxvY2tpbmcgb3BlcmF0aW9ucyBkcmFpbiB0aGVyZSkgYXJlIGNvbW1pdHRlZCBpbiBvbmUgZmluYWwgdHJhbnNhY3Rpb24uCiAqIElmIGFueSBzaW5rIGZhaWxzLCB0aGUgb3BlbiB0cmFuc2FjdGlvbiBpcyByb2xsZWQgYmFjay4KICogQSBwbGFpbiBMb2FkZXIgY2hpbGQgaXMgYSBiYXJlIHNpbmsgcm9vdDsgYSB0b190cmFuc2Zvcm1hdGlvbiguLi4pIGNoaWxkIGRlbGl2ZXJzIGluc2lkZSB0aGUgc2FtZQogKiB0cmFuc2FjdGlvbi4gRXZlcnkgY2hpbGQncyBsb2FkZXIgbXVzdCB1c2UgdGhlIHNhbWUgY29ubmVjdGlvbiBhcyB0aGUgdHJhbnNhY3Rpb246IHBhc3Mgb25lIGxpdmUKICogQ29ubmVjdGlvbiB0byBib3RoIC0gYSBsb2FkZXIgYnVpbHQgZnJvbSBhcnJheSBwYXJhbXMgb3BlbnMgaXRzIG93biBjb25uZWN0aW9uIGFuZCBlc2NhcGVzIHRoZQogKiB0cmFuc2FjdGlvbi4KICoKICogQHBhcmFtIGFycmF5PHN0cmluZywgbWl4ZWQ+fENvbm5lY3Rpb24gJGNvbm5lY3Rpb24KICogQHBhcmFtIExvYWRlcnxTaW5rIC4uLiRzaW5rcyAtIHNpbmtzIHdyaXR0ZW4gd2l0aGluIHRoZSB0cmFuc2FjdGlvbgogKgogKiBAdGhyb3dzIEludmFsaWRBcmd1bWVudEV4Y2VwdGlvbgogKi8="},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":347,"slug":"pagination-key-asc","name":"pagination_key_asc","namespace":"Flow\\ETL\\Adapter\\Doctrine","parameters":[{"name":"column","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":"type","type":[{"name":"ParameterType","namespace":"Doctrine\\DBAL","is_nullable":false,"is_variadic":false},{"name":"Type","namespace":"Doctrine\\DBAL\\Types","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":"Doctrine\\DBAL\\ParameterType::..."}],"return_type":[{"name":"Key","namespace":"Flow\\ETL\\Adapter\\Doctrine\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"DOCTRINE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":353,"slug":"pagination-key-desc","name":"pagination_key_desc","namespace":"Flow\\ETL\\Adapter\\Doctrine","parameters":[{"name":"column","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":"type","type":[{"name":"ParameterType","namespace":"Doctrine\\DBAL","is_nullable":false,"is_variadic":false},{"name":"Type","namespace":"Doctrine\\DBAL\\Types","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":"Doctrine\\DBAL\\ParameterType::..."}],"return_type":[{"name":"Key","namespace":"Flow\\ETL\\Adapter\\Doctrine\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"DOCTRINE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":359,"slug":"pagination-key-set","name":"pagination_key_set","namespace":"Flow\\ETL\\Adapter\\Doctrine","parameters":[{"name":"keys","type":[{"name":"Key","namespace":"Flow\\ETL\\Adapter\\Doctrine\\Pagination","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"KeySet","namespace":"Flow\\ETL\\Adapter\\Doctrine\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"DOCTRINE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-excel\/src\/Flow\/ETL\/Adapter\/Excel\/DSL\/functions.php","start_line_in_file":22,"slug":"from-excel","name":"from_excel","namespace":"Flow\\ETL\\Adapter\\Excel\\DSL","parameters":[{"name":"path","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"ExcelExtractor","namespace":"Flow\\ETL\\Adapter\\Excel","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"EXCEL","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-excel\/src\/Flow\/ETL\/Adapter\/Excel\/DSL\/functions.php","start_line_in_file":28,"slug":"to-excel","name":"to_excel","namespace":"Flow\\ETL\\Adapter\\Excel\\DSL","parameters":[{"name":"path","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"ExcelLoader","namespace":"Flow\\ETL\\Adapter\\Excel","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"EXCEL","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-excel\/src\/Flow\/ETL\/Adapter\/Excel\/DSL\/functions.php","start_line_in_file":34,"slug":"is-valid-excel-sheet-name","name":"is_valid_excel_sheet_name","namespace":"Flow\\ETL\\Adapter\\Excel\\DSL","parameters":[{"name":"sheet_name","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":"IsValidExcelSheetName","namespace":"Flow\\ETL\\Adapter\\Excel\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"EXCEL","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-google-sheet\/src\/Flow\/ETL\/Adapter\/GoogleSheet\/functions.php","start_line_in_file":22,"slug":"from-google-sheet","name":"from_google_sheet","namespace":"Flow\\ETL\\Adapter\\GoogleSheet","parameters":[{"name":"auth_config","type":[{"name":"Sheets","namespace":"Google\\Service","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},{"name":"spreadsheet_id","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":"sheet_name","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":"with_header","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"rows_per_page","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"1000"},{"name":"options","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"GoogleSheetExtractor","namespace":"Flow\\ETL\\Adapter\\GoogleSheet","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"GOOGLE_SHEET","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheXt0eXBlOiBzdHJpbmcsIHByb2plY3RfaWQ6IHN0cmluZywgcHJpdmF0ZV9rZXlfaWQ6IHN0cmluZywgcHJpdmF0ZV9rZXk6IHN0cmluZywgY2xpZW50X2VtYWlsOiBzdHJpbmcsIGNsaWVudF9pZDogc3RyaW5nLCBhdXRoX3VyaTogc3RyaW5nLCB0b2tlbl91cmk6IHN0cmluZywgYXV0aF9wcm92aWRlcl94NTA5X2NlcnRfdXJsOiBzdHJpbmcsIGNsaWVudF94NTA5X2NlcnRfdXJsOiBzdHJpbmd9fFNoZWV0cyAkYXV0aF9jb25maWcKICogQHBhcmFtIHN0cmluZyAkc3ByZWFkc2hlZXRfaWQKICogQHBhcmFtIHN0cmluZyAkc2hlZXRfbmFtZQogKiBAcGFyYW0gYm9vbCAkd2l0aF9oZWFkZXIgLSBAZGVwcmVjYXRlZCB1c2Ugd2l0aEhlYWRlciBtZXRob2QgaW5zdGVhZAogKiBAcGFyYW0gaW50ICRyb3dzX3Blcl9wYWdlIC0gaG93IG1hbnkgcm93cyBwZXIgcGFnZSB0byBmZXRjaCBmcm9tIEdvb2dsZSBTaGVldHMgQVBJIC0gQGRlcHJlY2F0ZWQgdXNlIHdpdGhSb3dzUGVyUGFnZSBtZXRob2QgaW5zdGVhZAogKiBAcGFyYW0gYXJyYXl7ZGF0ZVRpbWVSZW5kZXJPcHRpb24\/OiBzdHJpbmcsIG1ham9yRGltZW5zaW9uPzogc3RyaW5nLCB2YWx1ZVJlbmRlck9wdGlvbj86IHN0cmluZ30gJG9wdGlvbnMgLSBAZGVwcmVjYXRlZCB1c2Ugd2l0aE9wdGlvbnMgbWV0aG9kIGluc3RlYWQKICov"},{"repository_path":"src\/adapter\/etl-adapter-google-sheet\/src\/Flow\/ETL\/Adapter\/GoogleSheet\/functions.php","start_line_in_file":56,"slug":"from-google-sheet-columns","name":"from_google_sheet_columns","namespace":"Flow\\ETL\\Adapter\\GoogleSheet","parameters":[{"name":"auth_config","type":[{"name":"Sheets","namespace":"Google\\Service","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},{"name":"spreadsheet_id","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":"sheet_name","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":"start_range_column","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":"end_range_column","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":"with_header","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"rows_per_page","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"1000"},{"name":"options","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"GoogleSheetExtractor","namespace":"Flow\\ETL\\Adapter\\GoogleSheet","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"GOOGLE_SHEET","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheXt0eXBlOiBzdHJpbmcsIHByb2plY3RfaWQ6IHN0cmluZywgcHJpdmF0ZV9rZXlfaWQ6IHN0cmluZywgcHJpdmF0ZV9rZXk6IHN0cmluZywgY2xpZW50X2VtYWlsOiBzdHJpbmcsIGNsaWVudF9pZDogc3RyaW5nLCBhdXRoX3VyaTogc3RyaW5nLCB0b2tlbl91cmk6IHN0cmluZywgYXV0aF9wcm92aWRlcl94NTA5X2NlcnRfdXJsOiBzdHJpbmcsIGNsaWVudF94NTA5X2NlcnRfdXJsOiBzdHJpbmd9fFNoZWV0cyAkYXV0aF9jb25maWcKICogQHBhcmFtIHN0cmluZyAkc3ByZWFkc2hlZXRfaWQKICogQHBhcmFtIHN0cmluZyAkc2hlZXRfbmFtZQogKiBAcGFyYW0gc3RyaW5nICRzdGFydF9yYW5nZV9jb2x1bW4KICogQHBhcmFtIHN0cmluZyAkZW5kX3JhbmdlX2NvbHVtbgogKiBAcGFyYW0gYm9vbCAkd2l0aF9oZWFkZXIgLSBAZGVwcmVjYXRlZCB1c2Ugd2l0aEhlYWRlciBtZXRob2QgaW5zdGVhZAogKiBAcGFyYW0gaW50ICRyb3dzX3Blcl9wYWdlIC0gaG93IG1hbnkgcm93cyBwZXIgcGFnZSB0byBmZXRjaCBmcm9tIEdvb2dsZSBTaGVldHMgQVBJLCBkZWZhdWx0IDEwMDAgLSBAZGVwcmVjYXRlZCB1c2Ugd2l0aFJvd3NQZXJQYWdlIG1ldGhvZCBpbnN0ZWFkCiAqIEBwYXJhbSBhcnJheXtkYXRlVGltZVJlbmRlck9wdGlvbj86IHN0cmluZywgbWFqb3JEaW1lbnNpb24\/OiBzdHJpbmcsIHZhbHVlUmVuZGVyT3B0aW9uPzogc3RyaW5nfSAkb3B0aW9ucyAtIEBkZXByZWNhdGVkIHVzZSB3aXRoT3B0aW9ucyBtZXRob2QgaW5zdGVhZAogKi8="},{"repository_path":"src\/adapter\/etl-adapter-http\/src\/Flow\/ETL\/Adapter\/Http\/DSL\/functions.php","start_line_in_file":35,"slug":"from-dynamic-http-requests","name":"from_dynamic_http_requests","namespace":"Flow\\ETL\\Adapter\\Http","parameters":[{"name":"client","type":[{"name":"ClientInterface","namespace":"Psr\\Http\\Client","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"requestFactory","type":[{"name":"NextRequestFactory","namespace":"Flow\\ETL\\Adapter\\Http\\DynamicExtractor","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"schema","type":[{"name":"Schema","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":"PsrHttpClientDynamicExtractor","namespace":"Flow\\ETL\\Adapter\\Http","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"HTTP","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-http\/src\/Flow\/ETL\/Adapter\/Http\/DSL\/functions.php","start_line_in_file":53,"slug":"from-static-http-requests","name":"from_static_http_requests","namespace":"Flow\\ETL\\Adapter\\Http","parameters":[{"name":"client","type":[{"name":"ClientInterface","namespace":"Psr\\Http\\Client","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"requests","type":[{"name":"iterable","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"schema","type":[{"name":"Schema","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":"PsrHttpClientStaticExtractor","namespace":"Flow\\ETL\\Adapter\\Http","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"HTTP","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBpdGVyYWJsZTxSZXF1ZXN0SW50ZXJmYWNlPiAkcmVxdWVzdHMKICov"},{"repository_path":"src\/adapter\/etl-adapter-http\/src\/Flow\/ETL\/Adapter\/Http\/DSL\/functions.php","start_line_in_file":68,"slug":"from-http-paginated","name":"from_http_paginated","namespace":"Flow\\ETL\\Adapter\\Http","parameters":[{"name":"client","type":[{"name":"ClientInterface","namespace":"Psr\\Http\\Client","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"request","type":[{"name":"RequestInterface","namespace":"Psr\\Http\\Message","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"paginator","type":[{"name":"Paginator","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"schema","type":[{"name":"Schema","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":"PsrHttpClientPaginatedExtractor","namespace":"Flow\\ETL\\Adapter\\Http","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"HTTP","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-http\/src\/Flow\/ETL\/Adapter\/Http\/DSL\/functions.php","start_line_in_file":84,"slug":"http-pagination-page-number","name":"http_pagination_page_number","namespace":"Flow\\ETL\\Adapter\\Http","parameters":[{"name":"inject","type":[{"name":"RequestOption","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"start_page","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"1"},{"name":"page_size","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":"size_option","type":[{"name":"RequestOption","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"inject_on_first_request","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"records_path","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":"stop_on_client_error","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"stop_when","type":[{"name":"StopWhen","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Paginator","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"HTTP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-http\/src\/Flow\/ETL\/Adapter\/Http\/DSL\/functions.php","start_line_in_file":104,"slug":"http-pagination-offset","name":"http_pagination_offset","namespace":"Flow\\ETL\\Adapter\\Http","parameters":[{"name":"offset_option","type":[{"name":"RequestOption","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"limit_option","type":[{"name":"RequestOption","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"limit","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":"start_offset","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":"total_path","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":"inject_on_first_request","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"stop_on_client_error","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"stop_when","type":[{"name":"StopWhen","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Paginator","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"HTTP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-http\/src\/Flow\/ETL\/Adapter\/Http\/DSL\/functions.php","start_line_in_file":124,"slug":"http-pagination-cursor","name":"http_pagination_cursor","namespace":"Flow\\ETL\\Adapter\\Http","parameters":[{"name":"cursor_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},{"name":"inject","type":[{"name":"RequestOption","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"stop_on_client_error","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"stop_when","type":[{"name":"StopWhen","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Paginator","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"HTTP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-http\/src\/Flow\/ETL\/Adapter\/Http\/DSL\/functions.php","start_line_in_file":140,"slug":"http-pagination-next-url","name":"http_pagination_next_url","namespace":"Flow\\ETL\\Adapter\\Http","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},{"name":"stop_on_client_error","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"stop_when","type":[{"name":"StopWhen","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Paginator","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"HTTP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-http\/src\/Flow\/ETL\/Adapter\/Http\/DSL\/functions.php","start_line_in_file":155,"slug":"http-pagination-link-header","name":"http_pagination_link_header","namespace":"Flow\\ETL\\Adapter\\Http","parameters":[{"name":"rel","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'next'"},{"name":"stop_on_client_error","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"stop_when","type":[{"name":"StopWhen","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Paginator","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"HTTP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-http\/src\/Flow\/ETL\/Adapter\/Http\/DSL\/functions.php","start_line_in_file":164,"slug":"http-pagination-last-record-cursor","name":"http_pagination_last_record_cursor","namespace":"Flow\\ETL\\Adapter\\Http","parameters":[{"name":"record_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},{"name":"inject","type":[{"name":"RequestOption","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"stop_on_client_error","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"stop_when","type":[{"name":"StopWhen","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Paginator","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"HTTP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-http\/src\/Flow\/ETL\/Adapter\/Http\/DSL\/functions.php","start_line_in_file":180,"slug":"http-request-option-query","name":"http_request_option_query","namespace":"Flow\\ETL\\Adapter\\Http","parameters":[{"name":"name","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":"RequestOption","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"HTTP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-http\/src\/Flow\/ETL\/Adapter\/Http\/DSL\/functions.php","start_line_in_file":186,"slug":"http-request-option-header","name":"http_request_option_header","namespace":"Flow\\ETL\\Adapter\\Http","parameters":[{"name":"name","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":"RequestOption","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"HTTP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-http\/src\/Flow\/ETL\/Adapter\/Http\/DSL\/functions.php","start_line_in_file":192,"slug":"http-request-option-body","name":"http_request_option_body","namespace":"Flow\\ETL\\Adapter\\Http","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},{"name":"stream_factory","type":[{"name":"StreamFactoryInterface","namespace":"Psr\\Http\\Message","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"RequestOption","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"HTTP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-http\/src\/Flow\/ETL\/Adapter\/Http\/DSL\/functions.php","start_line_in_file":198,"slug":"http-request-option-uri","name":"http_request_option_uri","namespace":"Flow\\ETL\\Adapter\\Http","parameters":[],"return_type":[{"name":"RequestOption","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"HTTP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-http\/src\/Flow\/ETL\/Adapter\/Http\/DSL\/functions.php","start_line_in_file":204,"slug":"http-stop-when-path-missing","name":"http_stop_when_path_missing","namespace":"Flow\\ETL\\Adapter\\Http","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":"StopWhen","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"HTTP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-http\/src\/Flow\/ETL\/Adapter\/Http\/DSL\/functions.php","start_line_in_file":210,"slug":"http-stop-when-empty-path","name":"http_stop_when_empty_path","namespace":"Flow\\ETL\\Adapter\\Http","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":"StopWhen","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"HTTP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-http\/src\/Flow\/ETL\/Adapter\/Http\/DSL\/functions.php","start_line_in_file":216,"slug":"http-stop-when-flag-false","name":"http_stop_when_flag_false","namespace":"Flow\\ETL\\Adapter\\Http","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":"StopWhen","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"HTTP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-http\/src\/Flow\/ETL\/Adapter\/Http\/DSL\/functions.php","start_line_in_file":222,"slug":"http-stop-when-flag-true","name":"http_stop_when_flag_true","namespace":"Flow\\ETL\\Adapter\\Http","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":"StopWhen","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"HTTP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-http\/src\/Flow\/ETL\/Adapter\/Http\/DSL\/functions.php","start_line_in_file":228,"slug":"http-stop-when-total-reached","name":"http_stop_when_total_reached","namespace":"Flow\\ETL\\Adapter\\Http","parameters":[{"name":"total_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":"StopWhen","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"HTTP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-http\/src\/Flow\/ETL\/Adapter\/Http\/DSL\/functions.php","start_line_in_file":234,"slug":"http-stop-when-max-pages","name":"http_stop_when_max_pages","namespace":"Flow\\ETL\\Adapter\\Http","parameters":[{"name":"pages","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":"StopWhen","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"HTTP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-http\/src\/Flow\/ETL\/Adapter\/Http\/DSL\/functions.php","start_line_in_file":240,"slug":"http-stop-when-max-results","name":"http_stop_when_max_results","namespace":"Flow\\ETL\\Adapter\\Http","parameters":[{"name":"count","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":"StopWhen","namespace":"Flow\\ETL\\Adapter\\Http\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"HTTP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-json\/src\/Flow\/ETL\/Adapter\/JSON\/functions.php","start_line_in_file":32,"slug":"from-json","name":"from_json","namespace":"Flow\\ETL\\Adapter\\JSON","parameters":[{"name":"path","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"pointer","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":"schema","type":[{"name":"Schema","namespace":"Flow\\ETL","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"JsonExtractor","namespace":"Flow\\ETL\\Adapter\\JSON\\JSONMachine","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"JSON","type":"EXTRACTOR"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"reading","example":"json"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBQYXRofHN0cmluZyAkcGF0aCAtIHN0cmluZyBpcyBpbnRlcm5hbGx5IHR1cm5lZCBpbnRvIHN0cmVhbQogKiBAcGFyYW0gP3N0cmluZyAkcG9pbnRlciAtIGlmIHlvdSB3YW50IHRvIGl0ZXJhdGUgb25seSByZXN1bHRzIG9mIGEgc3VidHJlZSwgdXNlIGEgcG9pbnRlciwgcmVhZCBtb3JlIGF0IGh0dHBzOi8vZ2l0aHViLmNvbS9oYWxheGEvanNvbi1tYWNoaW5lI3BhcnNpbmctYS1zdWJ0cmVlIC0gQGRlcHJlY2F0ZSB1c2Ugd2l0aFBvaW50ZXIgbWV0aG9kIGluc3RlYWQKICogQHBhcmFtIG51bGx8U2NoZW1hICRzY2hlbWEgLSBlbmZvcmNlIHNjaGVtYSBvbiB0aGUgZXh0cmFjdGVkIGRhdGEgLSBAZGVwcmVjYXRlIHVzZSB3aXRoU2NoZW1hIG1ldGhvZCBpbnN0ZWFkCiAqLw=="},{"repository_path":"src\/adapter\/etl-adapter-json\/src\/Flow\/ETL\/Adapter\/JSON\/functions.php","start_line_in_file":58,"slug":"from-json-lines","name":"from_json_lines","namespace":"Flow\\ETL\\Adapter\\JSON","parameters":[{"name":"path","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"JsonLinesExtractor","namespace":"Flow\\ETL\\Adapter\\JSON\\JSONMachine","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"JSON","type":"EXTRACTOR"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"reading","example":"jsonl"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFVzZWQgdG8gcmVhZCBmcm9tIGEgSlNPTiBsaW5lcyBodHRwczovL2pzb25saW5lcy5vcmcvIGZvcm1hdHRlZCBmaWxlLgogKgogKiBAcGFyYW0gUGF0aHxzdHJpbmcgJHBhdGggLSBzdHJpbmcgaXMgaW50ZXJuYWxseSB0dXJuZWQgaW50byBzdHJlYW0KICov"},{"repository_path":"src\/adapter\/etl-adapter-json\/src\/Flow\/ETL\/Adapter\/JSON\/functions.php","start_line_in_file":72,"slug":"to-json","name":"to_json","namespace":"Flow\\ETL\\Adapter\\JSON","parameters":[{"name":"path","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"4194304"},{"name":"date_time_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\\\\TH:i:sP'"},{"name":"put_rows_in_new_lines","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"JsonLoader","namespace":"Flow\\ETL\\Adapter\\JSON","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"JSON","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBQYXRofHN0cmluZyAkcGF0aAogKiBAcGFyYW0gaW50ICRmbGFncyAtIFBIUCBKU09OIEZsYWdzIC0gQGRlcHJlY2F0ZSB1c2Ugd2l0aEZsYWdzIG1ldGhvZCBpbnN0ZWFkCiAqIEBwYXJhbSBzdHJpbmcgJGRhdGVfdGltZV9mb3JtYXQgLSBmb3JtYXQgZm9yIERhdGVUaW1lSW50ZXJmYWNlOjpmb3JtYXQoKSAtIEBkZXByZWNhdGUgdXNlIHdpdGhEYXRlVGltZUZvcm1hdCBtZXRob2QgaW5zdGVhZAogKiBAcGFyYW0gYm9vbCAkcHV0X3Jvd3NfaW5fbmV3X2xpbmVzIC0gaWYgeW91IHdhbnQgdG8gcHV0IGVhY2ggcm93IGluIGEgbmV3IGxpbmUgLSBAZGVwcmVjYXRlIHVzZSB3aXRoUm93c0luTmV3TGluZXMgbWV0aG9kIGluc3RlYWQKICoKICogQHJldHVybiBKc29uTG9hZGVyCiAqLw=="},{"repository_path":"src\/adapter\/etl-adapter-json\/src\/Flow\/ETL\/Adapter\/JSON\/functions.php","start_line_in_file":93,"slug":"to-json-lines","name":"to_json_lines","namespace":"Flow\\ETL\\Adapter\\JSON","parameters":[{"name":"path","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"JsonLinesLoader","namespace":"Flow\\ETL\\Adapter\\JSON","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"JSON","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFVzZWQgdG8gd3JpdGUgdG8gYSBKU09OIGxpbmVzIGh0dHBzOi8vanNvbmxpbmVzLm9yZy8gZm9ybWF0dGVkIGZpbGUuCiAqCiAqIEBwYXJhbSBQYXRofHN0cmluZyAkcGF0aAogKgogKiBAcmV0dXJuIEpzb25MaW5lc0xvYWRlcgogKi8="},{"repository_path":"src\/adapter\/etl-adapter-json\/src\/Flow\/ETL\/Adapter\/JSON\/functions.php","start_line_in_file":107,"slug":"schema-from-json-schema","name":"schema_from_json_schema","namespace":"Flow\\ETL\\Adapter\\JSON","parameters":[{"name":"json_schema","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"client","type":[{"name":"ClientInterface","namespace":"Psr\\Http\\Client","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"request_factory","type":[{"name":"RequestFactoryInterface","namespace":"Psr\\Http\\Message","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"Schema","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"JSON","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENvbnZlcnQgYSBKU09OIFNjaGVtYSAoaHR0cHM6Ly9qc29uLXNjaGVtYS5vcmcpIGRvY3VtZW50IGludG8gYSBGbG93IFNjaGVtYS4KICoKICogQHBhcmFtIGFycmF5PHN0cmluZywgbWl4ZWQ+fFBhdGh8c3RyaW5nICRqc29uX3NjaGVtYSAtIGRlY29kZWQgZG9jdW1lbnQsIHJhdyBKU09OIGRvY3VtZW50IG9yIGEgcGF0aCB0byBhIHNjaGVtYSBmaWxlCiAqIEBwYXJhbSBudWxsfENsaWVudEludGVyZmFjZSAkY2xpZW50IC0gUFNSLTE4IGh0dHAgY2xpZW50LCByZXF1aXJlZCB0byByZXNvbHZlIHJlbW90ZSBodHRwKHMpIHJlZmVyZW5jZXMKICogQHBhcmFtIG51bGx8UmVxdWVzdEZhY3RvcnlJbnRlcmZhY2UgJHJlcXVlc3RfZmFjdG9yeSAtIFBTUi0xNyByZXF1ZXN0IGZhY3RvcnksIHJlcXVpcmVkIHRvIHJlc29sdmUgcmVtb3RlIGh0dHAocykgcmVmZXJlbmNlcwogKiBAcGFyYW0gRmlsZXN5c3RlbSAkZmlsZXN5c3RlbSAtIGZpbGVzeXN0ZW0gdXNlZCB0byByZWFkIGxvY2FsIHNjaGVtYSByZWZlcmVuY2VzCiAqLw=="},{"repository_path":"src\/adapter\/etl-adapter-json\/src\/Flow\/ETL\/Adapter\/JSON\/functions.php","start_line_in_file":122,"slug":"schema-to-json-schema","name":"schema_to_json_schema","namespace":"Flow\\ETL\\Adapter\\JSON","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":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"JSON","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENvbnZlcnQgYSBGbG93IFNjaGVtYSBpbnRvIGEgSlNPTiBTY2hlbWEgKGh0dHBzOi8vanNvbi1zY2hlbWEub3JnLCBkcmFmdCAyMDIwLTEyKSBkb2N1bWVudC4KICoKICogQHJldHVybiBhcnJheTxzdHJpbmcsIG1peGVkPgogKi8="},{"repository_path":"src\/adapter\/etl-adapter-parquet\/src\/Flow\/ETL\/Adapter\/Parquet\/functions.php","start_line_in_file":36,"slug":"from-parquet","name":"from_parquet","namespace":"Flow\\ETL\\Adapter\\Parquet","parameters":[{"name":"path","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"columns","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"options","type":[{"name":"Options","namespace":"Flow\\Parquet","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Parquet\\Options::..."},{"name":"byte_order","type":[{"name":"ByteOrder","namespace":"Flow\\Parquet\\Binary","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Parquet\\Binary\\ByteOrder::..."},{"name":"offset","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":"engine","type":[{"name":"ParquetEngine","namespace":"Flow\\Parquet","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"ParquetExtractor","namespace":"Flow\\ETL\\Adapter\\Parquet","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PARQUET","type":"EXTRACTOR"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"reading","example":"parquet"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBQYXRofHN0cmluZyAkcGF0aAogKiBAcGFyYW0gYXJyYXk8c3RyaW5nPiAkY29sdW1ucyAtIGxpc3Qgb2YgY29sdW1ucyB0byByZWFkIGZyb20gcGFycXVldCBmaWxlIC0gQGRlcHJlY2F0ZWQgdXNlIGB3aXRoQ29sdW1uc2AgbWV0aG9kIGluc3RlYWQKICogQHBhcmFtIE9wdGlvbnMgJG9wdGlvbnMgLSBAZGVwcmVjYXRlZCB1c2UgYHdpdGhPcHRpb25zYCBtZXRob2QgaW5zdGVhZAogKiBAcGFyYW0gQnl0ZU9yZGVyICRieXRlX29yZGVyIC0gQGRlcHJlY2F0ZWQgdXNlIGB3aXRoQnl0ZU9yZGVyYCBtZXRob2QgaW5zdGVhZAogKiBAcGFyYW0gbnVsbHxpbnQgJG9mZnNldCAtIEBkZXByZWNhdGVkIHVzZSBgd2l0aE9mZnNldGAgbWV0aG9kIGluc3RlYWQKICov"},{"repository_path":"src\/adapter\/etl-adapter-parquet\/src\/Flow\/ETL\/Adapter\/Parquet\/functions.php","start_line_in_file":69,"slug":"to-parquet","name":"to_parquet","namespace":"Flow\\ETL\\Adapter\\Parquet","parameters":[{"name":"path","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"options","type":[{"name":"Options","namespace":"Flow\\Parquet","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"compressions","type":[{"name":"Compressions","namespace":"Flow\\Parquet\\ParquetFile","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Parquet\\ParquetFile\\Compressions::..."},{"name":"schema","type":[{"name":"Schema","namespace":"Flow\\ETL","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"engine","type":[{"name":"ParquetEngine","namespace":"Flow\\Parquet","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"ParquetLoader","namespace":"Flow\\ETL\\Adapter\\Parquet","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PARQUET","type":"LOADER"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"writing","example":"parquet"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBQYXRofHN0cmluZyAkcGF0aAogKiBAcGFyYW0gbnVsbHxPcHRpb25zICRvcHRpb25zIC0gQGRlcHJlY2F0ZWQgdXNlIGB3aXRoT3B0aW9uc2AgbWV0aG9kIGluc3RlYWQKICogQHBhcmFtIENvbXByZXNzaW9ucyAkY29tcHJlc3Npb25zIC0gQGRlcHJlY2F0ZWQgdXNlIGB3aXRoQ29tcHJlc3Npb25zYCBtZXRob2QgaW5zdGVhZAogKiBAcGFyYW0gbnVsbHxTY2hlbWEgJHNjaGVtYSAtIEBkZXByZWNhdGVkIHVzZSBgd2l0aFNjaGVtYWAgbWV0aG9kIGluc3RlYWQKICov"},{"repository_path":"src\/adapter\/etl-adapter-parquet\/src\/Flow\/ETL\/Adapter\/Parquet\/functions.php","start_line_in_file":100,"slug":"array-to-generator","name":"array_to_generator","namespace":"Flow\\ETL\\Adapter\\Parquet","parameters":[{"name":"data","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":"Generator","namespace":"","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PARQUET","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBhcnJheTxUPiAkZGF0YQogKgogKiBAcmV0dXJuIFxHZW5lcmF0b3I8VD4KICov"},{"repository_path":"src\/adapter\/etl-adapter-parquet\/src\/Flow\/ETL\/Adapter\/Parquet\/functions.php","start_line_in_file":111,"slug":"empty-generator","name":"empty_generator","namespace":"Flow\\ETL\\Adapter\\Parquet","parameters":[],"return_type":[{"name":"Generator","namespace":"","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PARQUET","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBkZXByZWNhdGVkIHVzZSBGbG93XFBhcnF1ZXRcZW1wdHlfZ2VuZXJhdG9yKCkgaW5zdGVhZAogKi8="},{"repository_path":"src\/adapter\/etl-adapter-parquet\/src\/Flow\/ETL\/Adapter\/Parquet\/functions.php","start_line_in_file":117,"slug":"schema-to-parquet","name":"schema_to_parquet","namespace":"Flow\\ETL\\Adapter\\Parquet","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":"Schema","namespace":"Flow\\Parquet\\ParquetFile","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PARQUET","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-parquet\/src\/Flow\/ETL\/Adapter\/Parquet\/functions.php","start_line_in_file":123,"slug":"schema-from-parquet","name":"schema_from_parquet","namespace":"Flow\\ETL\\Adapter\\Parquet","parameters":[{"name":"schema","type":[{"name":"Schema","namespace":"Flow\\Parquet\\ParquetFile","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Schema","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PARQUET","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-postgresql\/src\/Flow\/ETL\/Adapter\/PostgreSql\/functions.php","start_line_in_file":39,"slug":"from-pgsql-cursor","name":"from_pgsql_cursor","namespace":"Flow\\ETL\\Adapter\\PostgreSql","parameters":[{"name":"client","type":[{"name":"Client","namespace":"Flow\\PostgreSql\\Client","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"query","type":[{"name":"Sql","namespace":"Flow\\PostgreSql\\QueryBuilder","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":"parameters","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"PostgreSqlCursorExtractor","namespace":"Flow\\ETL\\Adapter\\PostgreSql","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"POSTGRESQL","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBvc3RncmVTUUwgY3Vyc29yIGV4dHJhY3RvciB1c2luZyBzZXJ2ZXItc2lkZSBjdXJzb3JzIGZvciBtZW1vcnktZWZmaWNpZW50IGV4dHJhY3Rpb24uCiAqCiAqIFVzZXMgREVDTEFSRSBDVVJTT1IgKyBGRVRDSCB0byBzdHJlYW0gZGF0YSB3aXRob3V0IGxvYWRpbmcgZW50aXJlIHJlc3VsdCBzZXQgaW50byBtZW1vcnkuCiAqIFRoaXMgaXMgdGhlIG9ubHkgd2F5IHRvIGFjaGlldmUgdHJ1ZSBsb3cgbWVtb3J5IGV4dHJhY3Rpb24gd2l0aCBQSFAncyBleHQtcGdzcWwuCiAqCiAqIE5vdGU6IFJlcXVpcmVzIGEgdHJhbnNhY3Rpb24gY29udGV4dCAoYXV0by1zdGFydGVkIGlmIG5vdCBpbiBvbmUpLgogKgogKiBAcGFyYW0gQ2xpZW50ICRjbGllbnQgUG9zdGdyZVNRTCBjbGllbnQKICogQHBhcmFtIFNxbHxzdHJpbmcgJHF1ZXJ5IFNRTCBxdWVyeSB0byBleGVjdXRlICh3cmFwcGVkIGluIERFQ0xBUkUgQ1VSU09SKQogKiBAcGFyYW0gbGlzdDxtaXhlZD4gJHBhcmFtZXRlcnMgVmFsdWVzIGJvdW5kIGJ5IHBvc2l0aW9uIHRvICQxLCAkMiwgLi4uIHBsYWNlaG9sZGVyczsgd3JhcCB3aXRoIHtAc2VlIFxGbG93XFBvc3RncmVTcWxcRFNMXHR5cGVkKCl9IHRvIGZvcmNlIGEgc3BlY2lmaWMgUG9zdGdyZVNRTCB0eXBlCiAqLw=="},{"repository_path":"src\/adapter\/etl-adapter-postgresql\/src\/Flow\/ETL\/Adapter\/PostgreSql\/functions.php","start_line_in_file":55,"slug":"from-pgsql-limit-offset","name":"from_pgsql_limit_offset","namespace":"Flow\\ETL\\Adapter\\PostgreSql","parameters":[{"name":"client","type":[{"name":"Client","namespace":"Flow\\PostgreSql\\Client","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"query","type":[{"name":"Sql","namespace":"Flow\\PostgreSql\\QueryBuilder","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":"parameters","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"PostgreSqlLimitOffsetExtractor","namespace":"Flow\\ETL\\Adapter\\PostgreSql","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"POSTGRESQL","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBvc3RncmVTUUwgZXh0cmFjdG9yIHVzaW5nIExJTUlUL09GRlNFVCBwYWdpbmF0aW9uLgogKgogKiBTdWl0YWJsZSBmb3Igc21hbGxlciBkYXRhc2V0cy4gRm9yIGxhcmdlIGRhdGFzZXRzLCBjb25zaWRlciB1c2luZyBrZXlzZXQgcGFnaW5hdGlvbgogKiAoZnJvbV9wZ3NxbF9rZXlfc2V0KSB3aGljaCBpcyBtb3JlIGVmZmljaWVudC4KICoKICogQHBhcmFtIENsaWVudCAkY2xpZW50IFBvc3RncmVTUUwgY2xpZW50CiAqIEBwYXJhbSBTcWx8c3RyaW5nICRxdWVyeSBTUUwgcXVlcnkgdG8gZXhlY3V0ZSAobXVzdCBoYXZlIE9SREVSIEJZIGNsYXVzZSkKICogQHBhcmFtIGxpc3Q8bWl4ZWQ+ICRwYXJhbWV0ZXJzIFZhbHVlcyBib3VuZCBieSBwb3NpdGlvbiB0byAkMSwgJDIsIC4uLiBwbGFjZWhvbGRlcnM7IHdyYXAgd2l0aCB7QHNlZSBcRmxvd1xQb3N0Z3JlU3FsXERTTFx0eXBlZCgpfSB0byBmb3JjZSBhIHNwZWNpZmljIFBvc3RncmVTUUwgdHlwZQogKi8="},{"repository_path":"src\/adapter\/etl-adapter-postgresql\/src\/Flow\/ETL\/Adapter\/PostgreSql\/functions.php","start_line_in_file":75,"slug":"from-pgsql-key-set","name":"from_pgsql_key_set","namespace":"Flow\\ETL\\Adapter\\PostgreSql","parameters":[{"name":"client","type":[{"name":"Client","namespace":"Flow\\PostgreSql\\Client","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"query","type":[{"name":"Sql","namespace":"Flow\\PostgreSql\\QueryBuilder","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":"keySet","type":[{"name":"KeySet","namespace":"Flow\\ETL\\Adapter\\PostgreSql\\Pagination","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"parameters","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"PostgreSqlKeySetExtractor","namespace":"Flow\\ETL\\Adapter\\PostgreSql","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"POSTGRESQL","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBvc3RncmVTUUwgZXh0cmFjdG9yIHVzaW5nIGtleXNldCAoY3Vyc29yLWJhc2VkKSBwYWdpbmF0aW9uLgogKgogKiBNb3JlIGVmZmljaWVudCB0aGFuIExJTUlUL09GRlNFVCBmb3IgbGFyZ2UgZGF0YXNldHMgLSB1c2VzIGluZGV4ZWQgV0hFUkUgY29uZGl0aW9ucwogKiBpbnN0ZWFkIG9mIHNraXBwaW5nIHJvd3MuCiAqCiAqIEBwYXJhbSBDbGllbnQgJGNsaWVudCBQb3N0Z3JlU1FMIGNsaWVudAogKiBAcGFyYW0gU3FsfHN0cmluZyAkcXVlcnkgU1FMIHF1ZXJ5IHRvIGV4ZWN1dGUgKG11c3QgaGF2ZSBPUkRFUiBCWSBtYXRjaGluZyBrZXlzZXQgY29sdW1ucykKICogQHBhcmFtIEtleVNldCAka2V5U2V0IENvbHVtbnMgdG8gdXNlIGZvciBrZXlzZXQgcGFnaW5hdGlvbgogKiBAcGFyYW0gbGlzdDxtaXhlZD4gJHBhcmFtZXRlcnMgVmFsdWVzIGJvdW5kIGJ5IHBvc2l0aW9uIHRvICQxLCAkMiwgLi4uIHBsYWNlaG9sZGVyczsgd3JhcCB3aXRoIHtAc2VlIFxGbG93XFBvc3RncmVTcWxcRFNMXHR5cGVkKCl9IHRvIGZvcmNlIGEgc3BlY2lmaWMgUG9zdGdyZVNRTCB0eXBlCiAqLw=="},{"repository_path":"src\/adapter\/etl-adapter-postgresql\/src\/Flow\/ETL\/Adapter\/PostgreSql\/functions.php","start_line_in_file":85,"slug":"pgsql-pagination-key-asc","name":"pgsql_pagination_key_asc","namespace":"Flow\\ETL\\Adapter\\PostgreSql","parameters":[{"name":"column","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":"Key","namespace":"Flow\\ETL\\Adapter\\PostgreSql\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"POSTGRESQL","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-postgresql\/src\/Flow\/ETL\/Adapter\/PostgreSql\/functions.php","start_line_in_file":91,"slug":"pgsql-pagination-key-desc","name":"pgsql_pagination_key_desc","namespace":"Flow\\ETL\\Adapter\\PostgreSql","parameters":[{"name":"column","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":"Key","namespace":"Flow\\ETL\\Adapter\\PostgreSql\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"POSTGRESQL","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-postgresql\/src\/Flow\/ETL\/Adapter\/PostgreSql\/functions.php","start_line_in_file":97,"slug":"pgsql-pagination-key-set","name":"pgsql_pagination_key_set","namespace":"Flow\\ETL\\Adapter\\PostgreSql","parameters":[{"name":"keys","type":[{"name":"Key","namespace":"Flow\\ETL\\Adapter\\PostgreSql\\Pagination","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"KeySet","namespace":"Flow\\ETL\\Adapter\\PostgreSql\\Pagination","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"POSTGRESQL","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-postgresql\/src\/Flow\/ETL\/Adapter\/PostgreSql\/functions.php","start_line_in_file":103,"slug":"to-pgsql-table","name":"to_pgsql_table","namespace":"Flow\\ETL\\Adapter\\PostgreSql","parameters":[{"name":"client","type":[{"name":"Client","namespace":"Flow\\PostgreSql\\Client","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"table","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":"PostgreSqlLoader","namespace":"Flow\\ETL\\Adapter\\PostgreSql","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"POSTGRESQL","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-postgresql\/src\/Flow\/ETL\/Adapter\/PostgreSql\/functions.php","start_line_in_file":112,"slug":"to-pgsql-transaction","name":"to_pgsql_transaction","namespace":"Flow\\ETL\\Adapter\\PostgreSql","parameters":[{"name":"client","type":[{"name":"Client","namespace":"Flow\\PostgreSql\\Client","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"sinks","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":true,"default_value":null}],"return_type":[{"name":"Transactional","namespace":"Flow\\ETL\\Sink","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"POSTGRESQL","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFdyaXRlIGV2ZXJ5IHNpbmsgd2l0aGluIFBvc3RncmVTUUwgdHJhbnNhY3Rpb25zLgogKi8="},{"repository_path":"src\/adapter\/etl-adapter-postgresql\/src\/Flow\/ETL\/Adapter\/PostgreSql\/functions.php","start_line_in_file":126,"slug":"pgsql-insert-options","name":"pgsql_insert_options","namespace":"Flow\\ETL\\Adapter\\PostgreSql","parameters":[{"name":"skipConflicts","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"conflictColumns","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"conflictConstraint","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":"updateColumns","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"InsertOptions","namespace":"Flow\\ETL\\Adapter\\PostgreSql\\LoaderOptions","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"POSTGRESQL","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBpbnNlcnQgb3B0aW9ucyBmb3IgUG9zdGdyZVNRTCBsb2FkZXIuCiAqCiAqIEBwYXJhbSBib29sICRza2lwQ29uZmxpY3RzIElmIHRydWUsIHVzZSBPTiBDT05GTElDVCBETyBOT1RISU5HCiAqIEBwYXJhbSBsaXN0PHN0cmluZz4gJGNvbmZsaWN0Q29sdW1ucyBDb2x1bW4gbmFtZXMgZm9yIE9OIENPTkZMSUNUIChjb2x1bW5zKQogKiBAcGFyYW0gbnVsbHxzdHJpbmcgJGNvbmZsaWN0Q29uc3RyYWludCBDb25zdHJhaW50IG5hbWUgZm9yIE9OIENPTkZMSUNUIE9OIENPTlNUUkFJTlQKICogQHBhcmFtIGxpc3Q8c3RyaW5nPiAkdXBkYXRlQ29sdW1ucyBDb2x1bW5zIHRvIHVwZGF0ZSBvbiBjb25mbGljdCAoZW1wdHkgPSBhbGwgbm9uLWtleSBjb2x1bW5zKQogKi8="},{"repository_path":"src\/adapter\/etl-adapter-postgresql\/src\/Flow\/ETL\/Adapter\/PostgreSql\/functions.php","start_line_in_file":141,"slug":"pgsql-update-options","name":"pgsql_update_options","namespace":"Flow\\ETL\\Adapter\\PostgreSql","parameters":[{"name":"primaryKeys","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":"UpdateOptions","namespace":"Flow\\ETL\\Adapter\\PostgreSql\\LoaderOptions","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"POSTGRESQL","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSB1cGRhdGUgb3B0aW9ucyBmb3IgUG9zdGdyZVNRTCBsb2FkZXIuCiAqCiAqIEBwYXJhbSBsaXN0PHN0cmluZz4gJHByaW1hcnlLZXlzIENvbHVtbnMgdG8gdXNlIGluIFdIRVJFIGNsYXVzZSBmb3IgbWF0Y2hpbmcgcm93cwogKi8="},{"repository_path":"src\/adapter\/etl-adapter-postgresql\/src\/Flow\/ETL\/Adapter\/PostgreSql\/functions.php","start_line_in_file":152,"slug":"pgsql-delete-options","name":"pgsql_delete_options","namespace":"Flow\\ETL\\Adapter\\PostgreSql","parameters":[{"name":"primaryKeys","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":"DeleteOptions","namespace":"Flow\\ETL\\Adapter\\PostgreSql\\LoaderOptions","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"POSTGRESQL","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBkZWxldGUgb3B0aW9ucyBmb3IgUG9zdGdyZVNRTCBsb2FkZXIuCiAqCiAqIEBwYXJhbSBsaXN0PHN0cmluZz4gJHByaW1hcnlLZXlzIENvbHVtbnMgdG8gdXNlIGluIFdIRVJFIGNsYXVzZSBmb3IgbWF0Y2hpbmcgcm93cwogKi8="},{"repository_path":"src\/adapter\/etl-adapter-postgresql\/src\/Flow\/ETL\/Adapter\/PostgreSql\/functions.php","start_line_in_file":164,"slug":"to-pgsql-schema-table","name":"to_pgsql_schema_table","namespace":"Flow\\ETL\\Adapter\\PostgreSql","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":"tableName","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":"databaseSchema","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'public'"},{"name":"typesMap","type":[{"name":"EntryTypesMap","namespace":"Flow\\ETL\\Adapter\\PostgreSql","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"options","type":[{"name":"TableOptions","namespace":"Flow\\PostgreSql\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Table","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"POSTGRESQL","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENvbnZlcnQgYSBGbG93IFNjaGVtYSBpbnRvIGEgUG9zdGdyZVNRTCB0YWJsZSBkZWZpbml0aW9uLgogKgogKiBAcGFyYW0gc3RyaW5nICRkYXRhYmFzZVNjaGVtYSBQb3N0Z3JlU1FMIHNjaGVtYSAobmFtZXNwYWNlKSB0aGUgdGFibGUgYmVsb25ncyB0bwogKiBAcGFyYW0gP1RhYmxlT3B0aW9ucyAkb3B0aW9ucyB0YWJsZS1sZXZlbCBvcHRpb25zIHRoZSBGbG93IFNjaGVtYSBjYW5ub3QgZXhwcmVzcyAoZS5nLiBVTkxPR0dFRCkKICov"},{"repository_path":"src\/adapter\/etl-adapter-postgresql\/src\/Flow\/ETL\/Adapter\/PostgreSql\/functions.php","start_line_in_file":178,"slug":"pgsql-table-to-flow-schema","name":"pgsql_table_to_flow_schema","namespace":"Flow\\ETL\\Adapter\\PostgreSql","parameters":[{"name":"table","type":[{"name":"Table","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"typesMap","type":[{"name":"EntryTypesMap","namespace":"Flow\\ETL\\Adapter\\PostgreSql","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Schema","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"POSTGRESQL","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENvbnZlcnQgYSBQb3N0Z3JlU1FMIHRhYmxlIGRlZmluaXRpb24gaW50byBhIEZsb3cgU2NoZW1hLgogKi8="},{"repository_path":"src\/adapter\/etl-adapter-postgresql\/src\/Flow\/ETL\/Adapter\/PostgreSql\/functions.php","start_line_in_file":184,"slug":"pgsql-schema-sort-by-type","name":"pgsql_schema_sort_by_type","namespace":"Flow\\ETL\\Adapter\\PostgreSql","parameters":[{"name":"typesMap","type":[{"name":"EntryTypesMap","namespace":"Flow\\ETL\\Adapter\\PostgreSql","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"TypeStrategy","namespace":"Flow\\ETL\\Adapter\\PostgreSql\\Schema\\SortingStrategy","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"POSTGRESQL","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-seal\/src\/Flow\/ETL\/Adapter\/Seal\/functions.php","start_line_in_file":15,"slug":"to-seal-upsert","name":"to_seal_upsert","namespace":"Flow\\ETL\\Adapter\\Seal","parameters":[{"name":"engine","type":[{"name":"EngineInterface","namespace":"CmsIg\\Seal","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"index","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":"SealLoader","namespace":"Flow\\ETL\\Adapter\\Seal","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"SEAL","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-seal\/src\/Flow\/ETL\/Adapter\/Seal\/functions.php","start_line_in_file":21,"slug":"to-seal-delete","name":"to_seal_delete","namespace":"Flow\\ETL\\Adapter\\Seal","parameters":[{"name":"engine","type":[{"name":"EngineInterface","namespace":"CmsIg\\Seal","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"index","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":"SealLoader","namespace":"Flow\\ETL\\Adapter\\Seal","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"SEAL","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-seal\/src\/Flow\/ETL\/Adapter\/Seal\/functions.php","start_line_in_file":27,"slug":"to-seal-schema","name":"to_seal_schema","namespace":"Flow\\ETL\\Adapter\\Seal","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":"index_name","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":"identifier","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Schema","namespace":"CmsIg\\Seal\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"SEAL","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-seal\/src\/Flow\/ETL\/Adapter\/Seal\/functions.php","start_line_in_file":33,"slug":"seal-schema-to-flow","name":"seal_schema_to_flow","namespace":"Flow\\ETL\\Adapter\\Seal","parameters":[{"name":"schema","type":[{"name":"Schema","namespace":"CmsIg\\Seal\\Schema","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Schema","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"SEAL","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-text\/src\/Flow\/ETL\/Adapter\/Text\/functions.php","start_line_in_file":21,"slug":"from-text","name":"from_text","namespace":"Flow\\ETL\\Adapter\\Text","parameters":[{"name":"path","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"TextExtractor","namespace":"Flow\\ETL\\Adapter\\Text","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TEXT","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBQYXRofHN0cmluZyAkcGF0aAogKi8="},{"repository_path":"src\/adapter\/etl-adapter-text\/src\/Flow\/ETL\/Adapter\/Text\/functions.php","start_line_in_file":31,"slug":"to-text","name":"to_text","namespace":"Flow\\ETL\\Adapter\\Text","parameters":[{"name":"path","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"new_line_separator","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'\\n'"},{"name":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"TextLoader","namespace":"Flow\\ETL\\Adapter\\Text","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TEXT","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBQYXRofHN0cmluZyAkcGF0aAogKiBAcGFyYW0gc3RyaW5nICRuZXdfbGluZV9zZXBhcmF0b3IgLSBkZWZhdWx0IFBIUF9FT0wgLSBAZGVwcmVjYXRlZCB1c2Ugd2l0aE5ld0xpbmVTZXBhcmF0b3IgbWV0aG9kIGluc3RlYWQKICov"},{"repository_path":"src\/adapter\/etl-adapter-xml\/src\/Flow\/ETL\/Adapter\/XML\/functions.php","start_line_in_file":38,"slug":"from-xml","name":"from_xml","namespace":"Flow\\ETL\\Adapter\\XML","parameters":[{"name":"path","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"xml_node_path","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"''"},{"name":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"XMLParserExtractor","namespace":"Flow\\ETL\\Adapter\\XML","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"XML","type":"EXTRACTOR"}},{"name":"DocumentationExample","namespace":"Flow\\Documentation\\Attribute","arguments":{"topic":"reading","example":"xml"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqICBJbiBvcmRlciB0byBpdGVyYXRlIG9ubHkgb3ZlciA8ZWxlbWVudD4gbm9kZXMgdXNlIGBmcm9tX3htbCgkZmlsZSktPndpdGhYTUxOb2RlUGF0aCgncm9vdC9lbGVtZW50cy9lbGVtZW50JylgLgogKgogKiAgPHJvb3Q+CiAqICAgIDxlbGVtZW50cz4KICogICAgICA8ZWxlbWVudD48L2VsZW1lbnQ+CiAqICAgICAgPGVsZW1lbnQ+PC9lbGVtZW50PgogKiAgICA8ZWxlbWVudHM+CiAqICA8L3Jvb3Q+CiAqCiAqICBYTUwgTm9kZSBQYXRoIGRvZXMgbm90IHN1cHBvcnQgYXR0cmlidXRlcyBhbmQgaXQncyBub3QgeHBhdGgsIGl0IGlzIGp1c3QgYSBzZXF1ZW5jZQogKiAgb2Ygbm9kZSBuYW1lcyBzZXBhcmF0ZWQgd2l0aCBzbGFzaC4KICoKICogQHBhcmFtIFBhdGh8c3RyaW5nICRwYXRoCiAqIEBwYXJhbSBzdHJpbmcgJHhtbF9ub2RlX3BhdGggLSBAZGVwcmVjYXRlZCB1c2UgYGZyb21feG1sKCRmaWxlKS0+d2l0aFhNTE5vZGVQYXRoKCR4bWxOb2RlUGF0aClgIG1ldGhvZCBpbnN0ZWFkCiAqLw=="},{"repository_path":"src\/adapter\/etl-adapter-xml\/src\/Flow\/ETL\/Adapter\/XML\/functions.php","start_line_in_file":57,"slug":"to-xml","name":"to_xml","namespace":"Flow\\ETL\\Adapter\\XML","parameters":[{"name":"path","type":[{"name":"Path","namespace":"Flow\\Filesystem","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":"root_element_name","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'rows'"},{"name":"row_element_name","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'row'"},{"name":"attribute_prefix","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'_'"},{"name":"date_time_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\\\\TH:i:s.uP'"},{"name":"xml_writer","type":[{"name":"XMLWriter","namespace":"Flow\\ETL\\Adapter\\XML","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Adapter\\XML\\XMLWriter\\StringXMLWriter::..."},{"name":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Local\\NativeLocalFilesystem::..."}],"return_type":[{"name":"XMLLoader","namespace":"Flow\\ETL\\Adapter\\XML\\Loader","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"XML","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBQYXRofHN0cmluZyAkcGF0aAogKiBAcGFyYW0gc3RyaW5nICRyb290X2VsZW1lbnRfbmFtZSAtIEBkZXByZWNhdGVkIHVzZSBgd2l0aFJvb3RFbGVtZW50TmFtZSgpYCBtZXRob2QgaW5zdGVhZAogKiBAcGFyYW0gc3RyaW5nICRyb3dfZWxlbWVudF9uYW1lIC0gQGRlcHJlY2F0ZWQgdXNlIGB3aXRoUm93RWxlbWVudE5hbWUoKWAgbWV0aG9kIGluc3RlYWQKICogQHBhcmFtIHN0cmluZyAkYXR0cmlidXRlX3ByZWZpeCAtIEBkZXByZWNhdGVkIHVzZSBgd2l0aEF0dHJpYnV0ZVByZWZpeCgpYCBtZXRob2QgaW5zdGVhZAogKiBAcGFyYW0gc3RyaW5nICRkYXRlX3RpbWVfZm9ybWF0IC0gQGRlcHJlY2F0ZWQgdXNlIGB3aXRoRGF0ZVRpbWVGb3JtYXQoKWAgbWV0aG9kIGluc3RlYWQKICogQHBhcmFtIFhNTFdyaXRlciAkeG1sX3dyaXRlcgogKi8="},{"repository_path":"src\/lib\/filesystem\/src\/Flow\/Filesystem\/DSL\/functions.php","start_line_in_file":32,"slug":"mount","name":"mount","namespace":"Flow\\Filesystem\\DSL","parameters":[{"name":"protocol","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":"Mount","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/filesystem\/src\/Flow\/Filesystem\/DSL\/functions.php","start_line_in_file":38,"slug":"partition","name":"partition","namespace":"Flow\\Filesystem\\DSL","parameters":[{"name":"name","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":"value","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":"Partition","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/filesystem\/src\/Flow\/Filesystem\/DSL\/functions.php","start_line_in_file":44,"slug":"partitions","name":"partitions","namespace":"Flow\\Filesystem\\DSL","parameters":[{"name":"partition","type":[{"name":"Partition","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"Partitions","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/filesystem\/src\/Flow\/Filesystem\/DSL\/functions.php","start_line_in_file":63,"slug":"path","name":"path","namespace":"Flow\\Filesystem\\DSL","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},{"name":"options","type":[{"name":"Options","namespace":"Flow\\Filesystem\\Path","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"Path","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFBhdGggc3VwcG9ydHMgZ2xvYiBwYXR0ZXJucy4KICogRXhhbXBsZXM6CiAqICAtIHBhdGgoJyouY3N2JykgLSBhbnkgY3N2IGZpbGUgaW4gY3VycmVudCBkaXJlY3RvcnkKICogIC0gcGF0aCgnLyoqIC8gKi5jc3YnKSAtIGFueSBjc3YgZmlsZSBpbiBhbnkgc3ViZGlyZWN0b3J5IChyZW1vdmUgZW1wdHkgc3BhY2VzKQogKiAgLSBwYXRoKCcvZGlyL3BhcnRpdGlvbj0qIC8qLnBhcnF1ZXQnKSAtIGFueSBwYXJxdWV0IGZpbGUgaW4gZ2l2ZW4gcGFydGl0aW9uIGRpcmVjdG9yeS4KICoKICogR2xvYiBwYXR0ZXJuIGlzIGFsc28gc3VwcG9ydGVkIGJ5IHJlbW90ZSBmaWxlc3lzdGVtcyBsaWtlIEF6dXJlCiAqCiAqICAtIHBhdGgoJ2F6dXJlLWJsb2I6Ly9kaXJlY3RvcnkvKi5jc3YnKSAtIGFueSBjc3YgZmlsZSBpbiBnaXZlbiBkaXJlY3RvcnkKICoKICogQHBhcmFtIGFycmF5PHN0cmluZywgbnVsbHxib29sfGZsb2F0fGludHxzdHJpbmd8XFVuaXRFbnVtPnxQYXRoXE9wdGlvbnMgJG9wdGlvbnMKICov"},{"repository_path":"src\/lib\/filesystem\/src\/Flow\/Filesystem\/DSL\/functions.php","start_line_in_file":74,"slug":"path-real","name":"path_real","namespace":"Flow\\Filesystem\\DSL","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},{"name":"options","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"Path","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFJlc29sdmUgcmVhbCBwYXRoIGZyb20gZ2l2ZW4gcGF0aC4KICoKICogQHBhcmFtIGFycmF5PHN0cmluZywgbnVsbHxib29sfGZsb2F0fGludHxzdHJpbmd8XFVuaXRFbnVtPiAkb3B0aW9ucwogKi8="},{"repository_path":"src\/lib\/filesystem\/src\/Flow\/Filesystem\/DSL\/functions.php","start_line_in_file":80,"slug":"native-local-filesystem","name":"native_local_filesystem","namespace":"Flow\\Filesystem\\DSL","parameters":[{"name":"protocol","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'file'"}],"return_type":[{"name":"NativeLocalFilesystem","namespace":"Flow\\Filesystem\\Local","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/filesystem\/src\/Flow\/Filesystem\/DSL\/functions.php","start_line_in_file":90,"slug":"stdout-filesystem","name":"stdout_filesystem","namespace":"Flow\\Filesystem\\DSL","parameters":[{"name":"protocol","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'stdout'"}],"return_type":[{"name":"StdOutFilesystem","namespace":"Flow\\Filesystem\\Local","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFdyaXRlLW9ubHkgZmlsZXN5c3RlbSB1c2VmdWwgd2hlbiB3ZSBqdXN0IHdhbnQgdG8gd3JpdGUgdGhlIG91dHB1dCB0byBzdGRvdXQuCiAqIFRoZSBtYWluIHVzZSBjYXNlIGlzIGZvciBzdHJlYW1pbmcgZGF0YXNldHMgb3ZlciBodHRwLgogKi8="},{"repository_path":"src\/lib\/filesystem\/src\/Flow\/Filesystem\/DSL\/functions.php","start_line_in_file":99,"slug":"memory-filesystem","name":"memory_filesystem","namespace":"Flow\\Filesystem\\DSL","parameters":[{"name":"protocol","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'memory'"}],"return_type":[{"name":"MemoryFilesystem","namespace":"Flow\\Filesystem\\Local","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIG5ldyBtZW1vcnkgZmlsZXN5c3RlbSBhbmQgd3JpdGVzIGRhdGEgdG8gaXQgaW4gbWVtb3J5LgogKi8="},{"repository_path":"src\/lib\/filesystem\/src\/Flow\/Filesystem\/DSL\/functions.php","start_line_in_file":110,"slug":"fstab","name":"fstab","namespace":"Flow\\Filesystem\\DSL","parameters":[{"name":"filesystems","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"FilesystemTable","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIG5ldyBmaWxlc3lzdGVtIHRhYmxlIHdpdGggZ2l2ZW4gZmlsZXN5c3RlbXMuCiAqIEZpbGVzeXN0ZW1zIGNhbiBiZSBhbHNvIG1vdW50ZWQgbGF0ZXIuCiAqIElmIG5vIGZpbGVzeXN0ZW1zIGFyZSBwcm92aWRlZCwgbG9jYWwgZmlsZXN5c3RlbSBpcyBtb3VudGVkLgogKi8="},{"repository_path":"src\/lib\/filesystem\/src\/Flow\/Filesystem\/DSL\/functions.php","start_line_in_file":126,"slug":"traceable-filesystem","name":"traceable_filesystem","namespace":"Flow\\Filesystem\\DSL","parameters":[{"name":"filesystem","type":[{"name":"Filesystem","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"telemetryConfig","type":[{"name":"FilesystemTelemetryConfig","namespace":"Flow\\Filesystem\\Telemetry","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"TraceableFilesystem","namespace":"Flow\\Filesystem\\Telemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFdyYXAgYSBmaWxlc3lzdGVtIHdpdGggdGVsZW1ldHJ5IHRyYWNpbmcgc3VwcG9ydC4KICogQWxsIGZpbGVzeXN0ZW0gYW5kIHN0cmVhbSBvcGVyYXRpb25zIHdpbGwgYmUgdHJhY2VkIGFjY29yZGluZyB0byB0aGUgY29uZmlndXJhdGlvbi4KICov"},{"repository_path":"src\/lib\/filesystem\/src\/Flow\/Filesystem\/DSL\/functions.php","start_line_in_file":135,"slug":"filesystem-telemetry-config","name":"filesystem_telemetry_config","namespace":"Flow\\Filesystem\\DSL","parameters":[{"name":"telemetry","type":[{"name":"Telemetry","namespace":"Flow\\Telemetry","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"clock","type":[{"name":"ClockInterface","namespace":"Psr\\Clock","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"options","type":[{"name":"FilesystemTelemetryOptions","namespace":"Flow\\Filesystem\\Telemetry","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"FilesystemTelemetryConfig","namespace":"Flow\\Filesystem\\Telemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHRlbGVtZXRyeSBjb25maWd1cmF0aW9uIGZvciB0aGUgZmlsZXN5c3RlbS4KICov"},{"repository_path":"src\/lib\/filesystem\/src\/Flow\/Filesystem\/DSL\/functions.php","start_line_in_file":150,"slug":"filesystem-telemetry-options","name":"filesystem_telemetry_options","namespace":"Flow\\Filesystem\\DSL","parameters":[{"name":"trace_streams","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"collect_metrics","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":"FilesystemTelemetryOptions","namespace":"Flow\\Filesystem\\Telemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBvcHRpb25zIGZvciBmaWxlc3lzdGVtIHRlbGVtZXRyeS4KICoKICogQHBhcmFtIGJvb2wgJHRyYWNlX3N0cmVhbXMgQ3JlYXRlIGEgc2luZ2xlIHNwYW4gcGVyIHN0cmVhbSBsaWZlY3ljbGUgKGRlZmF1bHQ6IE9OKQogKiBAcGFyYW0gYm9vbCAkY29sbGVjdF9tZXRyaWNzIENvbGxlY3QgbWV0cmljcyBmb3IgYnl0ZXMvb3BlcmF0aW9uIGNvdW50cyAoZGVmYXVsdDogT04pCiAqLw=="},{"repository_path":"src\/lib\/filesystem\/src\/Flow\/Filesystem\/DSL\/functions.php","start_line_in_file":163,"slug":"file-copy","name":"file_copy","namespace":"Flow\\Filesystem\\DSL","parameters":[{"name":"table","type":[{"name":"FilesystemTable","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"options","type":[{"name":"OperationOptions","namespace":"Flow\\Filesystem\\Operations","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Copy","namespace":"Flow\\Filesystem\\Operations","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENvcHkgYSBmaWxlIGZyb20gb25lIHBhdGggdG8gYW5vdGhlciwgYWNyb3NzIGFueSBmaWxlc3lzdGVtcyBtb3VudGVkIGluIHRoZSB0YWJsZS4KICogQWx3YXlzIHN0cmVhbXMgYnl0ZXM7IHNhbWUtZmlsZXN5c3RlbSBjb3BpZXMgZG8gbm90IHVzZSBzZXJ2ZXItc2lkZSBvcHRpbWl6YXRpb25zCiAqIGJlY2F1c2UgYEZpbGVzeXN0ZW06Om12YCBpcyBhIG1vdmUsIG5vdCBhIGNvcHkuCiAqLw=="},{"repository_path":"src\/lib\/filesystem\/src\/Flow\/Filesystem\/DSL\/functions.php","start_line_in_file":174,"slug":"file-move","name":"file_move","namespace":"Flow\\Filesystem\\DSL","parameters":[{"name":"table","type":[{"name":"FilesystemTable","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"options","type":[{"name":"OperationOptions","namespace":"Flow\\Filesystem\\Operations","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Move","namespace":"Flow\\Filesystem\\Operations","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIE1vdmUgYSBmaWxlIGZyb20gb25lIHBhdGggdG8gYW5vdGhlciwgYWNyb3NzIGFueSBmaWxlc3lzdGVtcyBtb3VudGVkIGluIHRoZSB0YWJsZS4KICogSW50cmEtZmlsZXN5c3RlbSBtb3ZlcyBkZWxlZ2F0ZSB0byBgRmlsZXN5c3RlbTo6bXZgIGZvciBzZXJ2ZXItc2lkZSBvcHRpbWl6YXRpb25zOwogKiBjcm9zcy1maWxlc3lzdGVtIG1vdmVzIHN0cmVhbS1jb3B5IHRoZW4gcmVtb3ZlIHRoZSBzb3VyY2UgKG5vbi1hdG9taWMpLgogKi8="},{"repository_path":"src\/lib\/filesystem\/src\/Flow\/Filesystem\/DSL\/functions.php","start_line_in_file":185,"slug":"operation-options","name":"operation_options","namespace":"Flow\\Filesystem\\DSL","parameters":[{"name":"chunkSize","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"8192"}],"return_type":[{"name":"OperationOptions","namespace":"Flow\\Filesystem\\Operations","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIE9wdGlvbnMgc2hhcmVkIGJ5IGZpbGVzeXN0ZW0gb3BlcmF0aW9ucy4KICoKICogQHBhcmFtIGludCAkY2h1bmtTaXplIE51bWJlciBvZiBieXRlcyByZWFkL3dyaXR0ZW4gcGVyIGl0ZXJhdGlvbiB3aGVuIHN0cmVhbWluZyBhY3Jvc3MgZmlsZXN5c3RlbXMgKGRlZmF1bHQ6IDgxOTIpCiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":70,"slug":"type-structure","name":"type_structure","namespace":"Flow\\Types\\DSL","parameters":[{"name":"elements","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"allow_extra","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":"StructureType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBhcnJheTxhcnJheS1rZXksIFN0cnVjdHVyZUVsZW1lbnQ8VD58VHlwZTxUPj4gJGVsZW1lbnRzCiAqCiAqIEByZXR1cm4gU3RydWN0dXJlVHlwZTxhcnJheTxhcnJheS1rZXksIFQ+PgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":85,"slug":"structure-element","name":"structure_element","namespace":"Flow\\Types\\DSL","parameters":[{"name":"name","type":[{"name":"string","namespace":null,"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":"type","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":"optional","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":"StructureElement","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqIEB0ZW1wbGF0ZSBUT3B0aW9uYWwgb2YgYm9vbAogKgogKiBAcGFyYW0gVHlwZTxUPiAkdHlwZQogKiBAcGFyYW0gVE9wdGlvbmFsICRvcHRpb25hbAogKgogKiBAcmV0dXJuIFN0cnVjdHVyZUVsZW1lbnQ8VCwgVE9wdGlvbmFsPgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":100,"slug":"type-union","name":"type_union","namespace":"Flow\\Types\\DSL","parameters":[{"name":"first","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":"second","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":"types","type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"UnionType","namespace":"Flow\\Types\\Type\\Native","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBUeXBlPFQ+ICRmaXJzdAogKiBAcGFyYW0gVHlwZTxUPiAkc2Vjb25kCiAqIEBwYXJhbSBUeXBlPFQ+IC4uLiR0eXBlcwogKgogKiBAcmV0dXJuIFVuaW9uVHlwZTxULCBUPgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":121,"slug":"type-intersection","name":"type_intersection","namespace":"Flow\\Types\\DSL","parameters":[{"name":"first","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":"second","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":"types","type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"IntersectionType","namespace":"Flow\\Types\\Type\\Native","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBUeXBlPFQ+ICRmaXJzdAogKiBAcGFyYW0gVHlwZTxUPiAkc2Vjb25kCiAqIEBwYXJhbSBUeXBlPFQ+IC4uLiR0eXBlcwogKgogKiBAcmV0dXJuIEludGVyc2VjdGlvblR5cGU8VCwgVD4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":136,"slug":"type-numeric-string","name":"type_numeric_string","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"NumericStringType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gTnVtZXJpY1N0cmluZ1R5cGU8bnVtZXJpYy1zdHJpbmc+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":149,"slug":"type-optional","name":"type_optional","namespace":"Flow\\Types\\DSL","parameters":[{"name":"type","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}],"return_type":[{"name":"OptionalType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBUeXBlPFQ+ICR0eXBlCiAqCiAqIEByZXR1cm4gT3B0aW9uYWxUeXBlPFQ+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":160,"slug":"type-from-array","name":"type_from_array","namespace":"Flow\\Types\\DSL","parameters":[{"name":"data","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":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxzdHJpbmcsIG1peGVkPiAkZGF0YQogKgogKiBAcmV0dXJuIFR5cGU8bWl4ZWQ+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":171,"slug":"type-is-nullable","name":"type_is_nullable","namespace":"Flow\\Types\\DSL","parameters":[{"name":"type","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}],"return_type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBUeXBlPFQ+ICR0eXBlCiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":187,"slug":"type-bare","name":"type_bare","namespace":"Flow\\Types\\DSL","parameters":[{"name":"type","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}],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFN0cmlwIGV4YWN0bHkgb25lIGxldmVsIG9mIG51bGxhYmlsaXR5LCB3aGljaGV2ZXIgb2YgdGhlIHR3byBzcGVsbGluZ3MgY2FycmllcyBpdAogKiAoT3B0aW9uYWxUeXBlLCBvciBhIFVuaW9uVHlwZSBjb250YWluaW5nIE51bGxUeXBlKS4gVG90YWw6IGEgTk9UIE5VTEwgdHlwZSBpcyByZXR1cm5lZCB1bmNoYW5nZWQuCiAqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBUeXBlPFQ+ICR0eXBlCiAqCiAqIEByZXR1cm4gVHlwZTxtaXhlZD4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":197,"slug":"type-equals","name":"type_equals","namespace":"Flow\\Types\\DSL","parameters":[{"name":"left","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":"right","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}],"return_type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBUeXBlPG1peGVkPiAkbGVmdAogKiBAcGFyYW0gVHlwZTxtaXhlZD4gJHJpZ2h0CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":210,"slug":"types","name":"types","namespace":"Flow\\Types\\DSL","parameters":[{"name":"types","type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"Types","namespace":"Flow\\Types\\Type","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBUeXBlPFQ+IC4uLiR0eXBlcwogKgogKiBAcmV0dXJuIFR5cGVzPFQ+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":223,"slug":"type-list","name":"type_list","namespace":"Flow\\Types\\DSL","parameters":[{"name":"element","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}],"return_type":[{"name":"ListType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBUeXBlPFQ+ICRlbGVtZW50CiAqCiAqIEByZXR1cm4gTGlzdFR5cGU8bGlzdDxUPj4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":238,"slug":"type-map","name":"type_map","namespace":"Flow\\Types\\DSL","parameters":[{"name":"key_type","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":"value_type","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}],"return_type":[{"name":"MapType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUS2V5IG9mIGFycmF5LWtleQogKiBAdGVtcGxhdGUgVFZhbHVlCiAqCiAqIEBwYXJhbSBUeXBlPFRLZXk+ICRrZXlfdHlwZQogKiBAcGFyYW0gVHlwZTxUVmFsdWU+ICR2YWx1ZV90eXBlCiAqCiAqIEByZXR1cm4gTWFwVHlwZTxhcnJheTxUS2V5LCBUVmFsdWU+PgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":247,"slug":"type-json","name":"type_json","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"JsonType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gSnNvblR5cGU8SnNvbj4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":256,"slug":"type-datetime","name":"type_datetime","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"DateTimeType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gRGF0ZVRpbWVUeXBlPFxEYXRlVGltZUludGVyZmFjZT4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":265,"slug":"type-date","name":"type_date","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"DateType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gRGF0ZVR5cGU8XERhdGVUaW1lSW50ZXJmYWNlPgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":274,"slug":"type-time","name":"type_time","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"TimeType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVGltZVR5cGU8XERhdGVJbnRlcnZhbD4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":283,"slug":"type-time-zone","name":"type_time_zone","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"TimeZoneType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVGltZVpvbmVUeXBlPFxEYXRlVGltZVpvbmU+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":292,"slug":"type-xml","name":"type_xml","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"XMLType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gWE1MVHlwZTxcRE9NRG9jdW1lbnR8WE1MRG9jdW1lbnQ+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":301,"slug":"type-xml-element","name":"type_xml_element","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"XMLElementType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gWE1MRWxlbWVudFR5cGU8XERPTUVsZW1lbnR8RWxlbWVudD4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":310,"slug":"type-uuid","name":"type_uuid","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"UuidType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVXVpZFR5cGU8VXVpZD4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":319,"slug":"type-integer","name":"type_integer","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"IntegerType","namespace":"Flow\\Types\\Type\\Native","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gSW50ZWdlclR5cGU8aW50PgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":328,"slug":"type-string","name":"type_string","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"StringType","namespace":"Flow\\Types\\Type\\Native","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gU3RyaW5nVHlwZTxzdHJpbmc+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":337,"slug":"type-float","name":"type_float","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"FloatType","namespace":"Flow\\Types\\Type\\Native","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gRmxvYXRUeXBlPGZsb2F0PgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":346,"slug":"type-boolean","name":"type_boolean","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"BooleanType","namespace":"Flow\\Types\\Type\\Native","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gQm9vbGVhblR5cGU8Ym9vbD4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":359,"slug":"type-instance-of","name":"type_instance_of","namespace":"Flow\\Types\\DSL","parameters":[{"name":"class","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":"InstanceOfType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUIG9mIG9iamVjdAogKgogKiBAcGFyYW0gY2xhc3Mtc3RyaW5nPFQ+ICRjbGFzcwogKgogKiBAcmV0dXJuIEluc3RhbmNlT2ZUeXBlPFQ+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":368,"slug":"type-object","name":"type_object","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"ObjectType","namespace":"Flow\\Types\\Type\\Native","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gT2JqZWN0VHlwZTxvYmplY3Q+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":377,"slug":"type-scalar","name":"type_scalar","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"ScalarType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gU2NhbGFyVHlwZTxib29sfGZsb2F0fGludHxzdHJpbmc+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":386,"slug":"type-resource","name":"type_resource","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"ResourceType","namespace":"Flow\\Types\\Type\\Native","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gUmVzb3VyY2VUeXBlPHJlc291cmNlPgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":395,"slug":"type-array","name":"type_array","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"ArrayType","namespace":"Flow\\Types\\Type\\Native","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gQXJyYXlUeXBlPGFycmF5PG1peGVkPj4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":404,"slug":"type-callable","name":"type_callable","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"CallableType","namespace":"Flow\\Types\\Type\\Native","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gQ2FsbGFibGVUeXBlPGNhbGxhYmxlPgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":413,"slug":"type-null","name":"type_null","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"NullType","namespace":"Flow\\Types\\Type\\Native","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gTnVsbFR5cGU8bnVsbD4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":422,"slug":"type-mixed","name":"type_mixed","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"MixedType","namespace":"Flow\\Types\\Type\\Native","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gTWl4ZWRUeXBlPG1peGVkPgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":431,"slug":"type-positive-integer","name":"type_positive_integer","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"PositiveIntegerType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gUG9zaXRpdmVJbnRlZ2VyVHlwZTxpbnQ8MCwgbWF4Pj4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":440,"slug":"type-non-empty-string","name":"type_non_empty_string","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"NonEmptyStringType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gTm9uRW1wdHlTdHJpbmdUeXBlPG5vbi1lbXB0eS1zdHJpbmc+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":449,"slug":"type-empty-array","name":"type_empty_array","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"EmptyArrayType","namespace":"Flow\\Types\\Type\\Native","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gRW1wdHlBcnJheVR5cGU8YXJyYXl7fT4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":462,"slug":"type-enum","name":"type_enum","namespace":"Flow\\Types\\DSL","parameters":[{"name":"class","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":"EnumType","namespace":"Flow\\Types\\Type\\Native","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUIG9mIFVuaXRFbnVtCiAqCiAqIEBwYXJhbSBjbGFzcy1zdHJpbmc8VD4gJGNsYXNzCiAqCiAqIEByZXR1cm4gRW51bVR5cGU8VD4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":475,"slug":"type-literal","name":"type_literal","namespace":"Flow\\Types\\DSL","parameters":[{"name":"value","type":[{"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":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"LiteralType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUIG9mIGJvb2x8ZmxvYXR8aW50fHN0cmluZwogKgogKiBAcGFyYW0gVCAkdmFsdWUKICoKICogQHJldHVybiBMaXRlcmFsVHlwZTxUPgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":484,"slug":"type-html","name":"type_html","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"HTMLType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gSFRNTFR5cGU8SFRNTERvY3VtZW50PgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":493,"slug":"type-html-element","name":"type_html_element","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"HTMLElementType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gSFRNTEVsZW1lbnRUeXBlPEhUTUxFbGVtZW50PgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":505,"slug":"type-is","name":"type_is","namespace":"Flow\\Types\\DSL","parameters":[{"name":"type","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":"typeClass","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":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBUeXBlPFQ+ICR0eXBlCiAqIEBwYXJhbSBjbGFzcy1zdHJpbmc8VHlwZTxtaXhlZD4+ICR0eXBlQ2xhc3MKICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":518,"slug":"type-is-any","name":"type_is_any","namespace":"Flow\\Types\\DSL","parameters":[{"name":"type","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":"typeClass","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":"typeClasses","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":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBUeXBlPFQ+ICR0eXBlCiAqIEBwYXJhbSBjbGFzcy1zdHJpbmc8VHlwZTxtaXhlZD4+ICR0eXBlQ2xhc3MKICogQHBhcmFtIGNsYXNzLXN0cmluZzxUeXBlPG1peGVkPj4gLi4uJHR5cGVDbGFzc2VzCiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":527,"slug":"get-type","name":"get_type","namespace":"Flow\\Types\\DSL","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":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxtaXhlZD4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":540,"slug":"type-class-string","name":"type_class_string","namespace":"Flow\\Types\\DSL","parameters":[{"name":"class","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"ClassStringType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUIG9mIG9iamVjdAogKgogKiBAcGFyYW0gbnVsbHxjbGFzcy1zdHJpbmc8VD4gJGNsYXNzCiAqCiAqIEByZXR1cm4gKCRjbGFzcyBpcyBudWxsID8gQ2xhc3NTdHJpbmdUeXBlPGNsYXNzLXN0cmluZz4gOiBDbGFzc1N0cmluZ1R5cGU8Y2xhc3Mtc3RyaW5nPFQ+PikKICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":546,"slug":"dom-element-to-string","name":"dom_element_to_string","namespace":"Flow\\Types\\DSL","parameters":[{"name":"element","type":[{"name":"DOMElement","namespace":"","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"format_output","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"preserver_white_space","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":"string","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"false","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TYPES","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":134,"slug":"column","name":"column","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"type","type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ColumnDefinition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGNvbHVtbiBkZWZpbml0aW9uIGZvciBDUkVBVEUgVEFCTEUuCiAqCiAqIEBwYXJhbSBzdHJpbmcgJG5hbWUgQ29sdW1uIG5hbWUKICogQHBhcmFtIENvbHVtblR5cGUgJHR5cGUgQ29sdW1uIGRhdGEgdHlwZQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":143,"slug":"catalog","name":"catalog","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"schemas","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":"Catalog","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBsaXN0PFNjaGVtYT4gJHNjaGVtYXMKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":154,"slug":"primary-key","name":"primary_key","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"columns","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":"PrimaryKeyConstraint","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Constraint","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBSSU1BUlkgS0VZIGNvbnN0cmFpbnQuCiAqCiAqIEBwYXJhbSBzdHJpbmcgLi4uJGNvbHVtbnMgQ29sdW1ucyB0aGF0IGZvcm0gdGhlIHByaW1hcnkga2V5CiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":165,"slug":"unique-constraint","name":"unique_constraint","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"columns","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":"UniqueConstraint","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Constraint","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFVOSVFVRSBjb25zdHJhaW50LgogKgogKiBAcGFyYW0gc3RyaW5nIC4uLiRjb2x1bW5zIENvbHVtbnMgdGhhdCBtdXN0IGJlIHVuaXF1ZSB0b2dldGhlcgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":178,"slug":"foreign-key","name":"foreign_key","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"columns","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":"referenceTable","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":"referenceColumns","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"ForeignKeyConstraint","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Constraint","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEZPUkVJR04gS0VZIGNvbnN0cmFpbnQuCiAqCiAqIEBwYXJhbSBsaXN0PHN0cmluZz4gJGNvbHVtbnMgTG9jYWwgY29sdW1ucwogKiBAcGFyYW0gc3RyaW5nICRyZWZlcmVuY2VUYWJsZSBSZWZlcmVuY2VkIHRhYmxlCiAqIEBwYXJhbSBsaXN0PHN0cmluZz4gJHJlZmVyZW5jZUNvbHVtbnMgUmVmZXJlbmNlZCBjb2x1bW5zIChkZWZhdWx0cyB0byBzYW1lIGFzICRjb2x1bW5zIGlmIGVtcHR5KQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":187,"slug":"check-constraint","name":"check_constraint","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"condition","type":[{"name":"Condition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"CheckConstraint","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Constraint","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENIRUNLIGNvbnN0cmFpbnQuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":218,"slug":"create","name":"create","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"CreateFactory","namespace":"Flow\\PostgreSql\\QueryBuilder\\Factory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGZhY3RvcnkgZm9yIGJ1aWxkaW5nIENSRUFURSBzdGF0ZW1lbnRzLgogKgogKiBQcm92aWRlcyBhIHVuaWZpZWQgZW50cnkgcG9pbnQgZm9yIGFsbCBDUkVBVEUgb3BlcmF0aW9uczoKICogLSBjcmVhdGUoKS0+dGFibGUoKSAtIENSRUFURSBUQUJMRQogKiAtIGNyZWF0ZSgpLT50YWJsZUFzKCkgLSBDUkVBVEUgVEFCTEUgQVMKICogLSBjcmVhdGUoKS0+aW5kZXgoKSAtIENSRUFURSBJTkRFWAogKiAtIGNyZWF0ZSgpLT52aWV3KCkgLSBDUkVBVEUgVklFVwogKiAtIGNyZWF0ZSgpLT5tYXRlcmlhbGl6ZWRWaWV3KCkgLSBDUkVBVEUgTUFURVJJQUxJWkVEIFZJRVcKICogLSBjcmVhdGUoKS0+c2VxdWVuY2UoKSAtIENSRUFURSBTRVFVRU5DRQogKiAtIGNyZWF0ZSgpLT5zY2hlbWEoKSAtIENSRUFURSBTQ0hFTUEKICogLSBjcmVhdGUoKS0+cm9sZSgpIC0gQ1JFQVRFIFJPTEUKICogLSBjcmVhdGUoKS0+ZnVuY3Rpb24oKSAtIENSRUFURSBGVU5DVElPTgogKiAtIGNyZWF0ZSgpLT5wcm9jZWR1cmUoKSAtIENSRUFURSBQUk9DRURVUkUKICogLSBjcmVhdGUoKS0+dHJpZ2dlcigpIC0gQ1JFQVRFIFRSSUdHRVIKICogLSBjcmVhdGUoKS0+cnVsZSgpIC0gQ1JFQVRFIFJVTEUKICogLSBjcmVhdGUoKS0+ZXh0ZW5zaW9uKCkgLSBDUkVBVEUgRVhURU5TSU9OCiAqIC0gY3JlYXRlKCktPmNvbXBvc2l0ZVR5cGUoKSAtIENSRUFURSBUWVBFIChjb21wb3NpdGUpCiAqIC0gY3JlYXRlKCktPmVudW1UeXBlKCkgLSBDUkVBVEUgVFlQRSAoZW51bSkKICogLSBjcmVhdGUoKS0+cmFuZ2VUeXBlKCkgLSBDUkVBVEUgVFlQRSAocmFuZ2UpCiAqIC0gY3JlYXRlKCktPmRvbWFpbigpIC0gQ1JFQVRFIERPTUFJTgogKgogKiBFeGFtcGxlOiBjcmVhdGUoKS0+dGFibGUoJ3VzZXJzJyktPmNvbHVtbnMoY29sX2RlZignaWQnLCBjb2x1bW5fdHlwZV9zZXJpYWwoKSkpCiAqIEV4YW1wbGU6IGNyZWF0ZSgpLT5pbmRleCgnaWR4X2VtYWlsJyktPm9uKCd1c2VycycpLT5jb2x1bW5zKCdlbWFpbCcpCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":247,"slug":"drop","name":"drop","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"DropFactory","namespace":"Flow\\PostgreSql\\QueryBuilder\\Factory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGZhY3RvcnkgZm9yIGJ1aWxkaW5nIERST1Agc3RhdGVtZW50cy4KICoKICogUHJvdmlkZXMgYSB1bmlmaWVkIGVudHJ5IHBvaW50IGZvciBhbGwgRFJPUCBvcGVyYXRpb25zOgogKiAtIGRyb3AoKS0+dGFibGUoKSAtIERST1AgVEFCTEUKICogLSBkcm9wKCktPmluZGV4KCkgLSBEUk9QIElOREVYCiAqIC0gZHJvcCgpLT52aWV3KCkgLSBEUk9QIFZJRVcKICogLSBkcm9wKCktPm1hdGVyaWFsaXplZFZpZXcoKSAtIERST1AgTUFURVJJQUxJWkVEIFZJRVcKICogLSBkcm9wKCktPnNlcXVlbmNlKCkgLSBEUk9QIFNFUVVFTkNFCiAqIC0gZHJvcCgpLT5zY2hlbWEoKSAtIERST1AgU0NIRU1BCiAqIC0gZHJvcCgpLT5yb2xlKCkgLSBEUk9QIFJPTEUKICogLSBkcm9wKCktPmZ1bmN0aW9uKCkgLSBEUk9QIEZVTkNUSU9OCiAqIC0gZHJvcCgpLT5wcm9jZWR1cmUoKSAtIERST1AgUFJPQ0VEVVJFCiAqIC0gZHJvcCgpLT50cmlnZ2VyKCkgLSBEUk9QIFRSSUdHRVIKICogLSBkcm9wKCktPnJ1bGUoKSAtIERST1AgUlVMRQogKiAtIGRyb3AoKS0+ZXh0ZW5zaW9uKCkgLSBEUk9QIEVYVEVOU0lPTgogKiAtIGRyb3AoKS0+dHlwZSgpIC0gRFJPUCBUWVBFCiAqIC0gZHJvcCgpLT5kb21haW4oKSAtIERST1AgRE9NQUlOCiAqIC0gZHJvcCgpLT5vd25lZCgpIC0gRFJPUCBPV05FRAogKgogKiBFeGFtcGxlOiBkcm9wKCktPnRhYmxlKCd1c2VycycsICdvcmRlcnMnKS0+aWZFeGlzdHMoKS0+Y2FzY2FkZSgpCiAqIEV4YW1wbGU6IGRyb3AoKS0+aW5kZXgoJ2lkeF9lbWFpbCcpLT5pZkV4aXN0cygpCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":281,"slug":"alter","name":"alter","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"AlterFactory","namespace":"Flow\\PostgreSql\\QueryBuilder\\Factory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGZhY3RvcnkgZm9yIGJ1aWxkaW5nIEFMVEVSIHN0YXRlbWVudHMuCiAqCiAqIFByb3ZpZGVzIGEgdW5pZmllZCBlbnRyeSBwb2ludCBmb3IgYWxsIEFMVEVSIG9wZXJhdGlvbnM6CiAqIC0gYWx0ZXIoKS0+dGFibGUoKSAtIEFMVEVSIFRBQkxFCiAqIC0gYWx0ZXIoKS0+aW5kZXgoKSAtIEFMVEVSIElOREVYCiAqIC0gYWx0ZXIoKS0+dmlldygpIC0gQUxURVIgVklFVwogKiAtIGFsdGVyKCktPm1hdGVyaWFsaXplZFZpZXcoKSAtIEFMVEVSIE1BVEVSSUFMSVpFRCBWSUVXCiAqIC0gYWx0ZXIoKS0+c2VxdWVuY2UoKSAtIEFMVEVSIFNFUVVFTkNFCiAqIC0gYWx0ZXIoKS0+c2NoZW1hKCkgLSBBTFRFUiBTQ0hFTUEKICogLSBhbHRlcigpLT5yb2xlKCkgLSBBTFRFUiBST0xFCiAqIC0gYWx0ZXIoKS0+ZnVuY3Rpb24oKSAtIEFMVEVSIEZVTkNUSU9OCiAqIC0gYWx0ZXIoKS0+cHJvY2VkdXJlKCkgLSBBTFRFUiBQUk9DRURVUkUKICogLSBhbHRlcigpLT50cmlnZ2VyKCkgLSBBTFRFUiBUUklHR0VSCiAqIC0gYWx0ZXIoKS0+ZXh0ZW5zaW9uKCkgLSBBTFRFUiBFWFRFTlNJT04KICogLSBhbHRlcigpLT5lbnVtVHlwZSgpIC0gQUxURVIgVFlQRSAoZW51bSkKICogLSBhbHRlcigpLT5kb21haW4oKSAtIEFMVEVSIERPTUFJTgogKgogKiBSZW5hbWUgb3BlcmF0aW9ucyBhcmUgYWxzbyB1bmRlciBhbHRlcigpOgogKiAtIGFsdGVyKCktPmluZGV4KCdvbGQnKS0+cmVuYW1lVG8oJ25ldycpCiAqIC0gYWx0ZXIoKS0+dmlldygnb2xkJyktPnJlbmFtZVRvKCduZXcnKQogKiAtIGFsdGVyKCktPnNjaGVtYSgnb2xkJyktPnJlbmFtZVRvKCduZXcnKQogKiAtIGFsdGVyKCktPnJvbGUoJ29sZCcpLT5yZW5hbWVUbygnbmV3JykKICogLSBhbHRlcigpLT50cmlnZ2VyKCdvbGQnKS0+b24oJ3RhYmxlJyktPnJlbmFtZVRvKCduZXcnKQogKgogKiBFeGFtcGxlOiBhbHRlcigpLT50YWJsZSgndXNlcnMnKS0+YWRkQ29sdW1uKGNvbF9kZWYoJ2VtYWlsJywgY29sdW1uX3R5cGVfdGV4dCgpKSkKICogRXhhbXBsZTogYWx0ZXIoKS0+c2VxdWVuY2UoJ3VzZXJfaWRfc2VxJyktPnJlc3RhcnQoMTAwMCkKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":292,"slug":"truncate-table","name":"truncate_table","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"tables","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":"TruncateFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Truncate","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFRSVU5DQVRFIFRBQkxFIGJ1aWxkZXIuCiAqCiAqIEBwYXJhbSBzdHJpbmcgLi4uJHRhYmxlcyBUYWJsZSBuYW1lcyB0byB0cnVuY2F0ZQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":310,"slug":"refresh-materialized-view","name":"refresh_materialized_view","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"schema","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"RefreshMatViewOptionsStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\View\\RefreshMaterializedView","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFJFRlJFU0ggTUFURVJJQUxJWkVEIFZJRVcgYnVpbGRlci4KICoKICogRXhhbXBsZTogcmVmcmVzaF9tYXRlcmlhbGl6ZWRfdmlldygndXNlcl9zdGF0cycpCiAqIFByb2R1Y2VzOiBSRUZSRVNIIE1BVEVSSUFMSVpFRCBWSUVXIHVzZXJfc3RhdHMKICoKICogRXhhbXBsZTogcmVmcmVzaF9tYXRlcmlhbGl6ZWRfdmlldygndXNlcl9zdGF0cycpLT5jb25jdXJyZW50bHkoKS0+d2l0aERhdGEoKQogKiBQcm9kdWNlczogUkVGUkVTSCBNQVRFUklBTElaRUQgVklFVyBDT05DVVJSRU5UTFkgdXNlcl9zdGF0cyBXSVRIIERBVEEKICoKICogQHBhcmFtIHN0cmluZyAkbmFtZSBWaWV3IG5hbWUgKG1heSBpbmNsdWRlIHNjaGVtYSBhcyAic2NoZW1hLnZpZXciKQogKiBAcGFyYW0gbnVsbHxzdHJpbmcgJHNjaGVtYSBTY2hlbWEgbmFtZSAob3B0aW9uYWwsIG92ZXJyaWRlcyBwYXJzZWQgc2NoZW1hKQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":319,"slug":"ref-action-cascade","name":"ref_action_cascade","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ReferentialAction","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEdldCBhIENBU0NBREUgcmVmZXJlbnRpYWwgYWN0aW9uLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":328,"slug":"ref-action-restrict","name":"ref_action_restrict","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ReferentialAction","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEdldCBhIFJFU1RSSUNUIHJlZmVyZW50aWFsIGFjdGlvbi4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":337,"slug":"ref-action-set-null","name":"ref_action_set_null","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ReferentialAction","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEdldCBhIFNFVCBOVUxMIHJlZmVyZW50aWFsIGFjdGlvbi4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":346,"slug":"ref-action-set-default","name":"ref_action_set_default","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ReferentialAction","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEdldCBhIFNFVCBERUZBVUxUIHJlZmVyZW50aWFsIGFjdGlvbi4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":355,"slug":"ref-action-no-action","name":"ref_action_no_action","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ReferentialAction","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEdldCBhIE5PIEFDVElPTiByZWZlcmVudGlhbCBhY3Rpb24uCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":370,"slug":"reindex-index","name":"reindex_index","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"ReindexFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Index\\Reindex","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFN0YXJ0IGJ1aWxkaW5nIGEgUkVJTkRFWCBJTkRFWCBzdGF0ZW1lbnQuCiAqCiAqIFVzZSBjaGFpbmFibGUgbWV0aG9kczogLT5jb25jdXJyZW50bHkoKSwgLT52ZXJib3NlKCksIC0+dGFibGVzcGFjZSgpCiAqCiAqIEV4YW1wbGU6IHJlaW5kZXhfaW5kZXgoJ2lkeF91c2Vyc19lbWFpbCcpLT5jb25jdXJyZW50bHkoKQogKgogKiBAcGFyYW0gc3RyaW5nICRuYW1lIFRoZSBpbmRleCBuYW1lIChtYXkgaW5jbHVkZSBzY2hlbWE6IHNjaGVtYS5pbmRleCkKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":385,"slug":"reindex-table","name":"reindex_table","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"ReindexFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Index\\Reindex","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFN0YXJ0IGJ1aWxkaW5nIGEgUkVJTkRFWCBUQUJMRSBzdGF0ZW1lbnQuCiAqCiAqIFVzZSBjaGFpbmFibGUgbWV0aG9kczogLT5jb25jdXJyZW50bHkoKSwgLT52ZXJib3NlKCksIC0+dGFibGVzcGFjZSgpCiAqCiAqIEV4YW1wbGU6IHJlaW5kZXhfdGFibGUoJ3VzZXJzJyktPmNvbmN1cnJlbnRseSgpCiAqCiAqIEBwYXJhbSBzdHJpbmcgJG5hbWUgVGhlIHRhYmxlIG5hbWUgKG1heSBpbmNsdWRlIHNjaGVtYTogc2NoZW1hLnRhYmxlKQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":400,"slug":"reindex-schema","name":"reindex_schema","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"ReindexFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Index\\Reindex","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFN0YXJ0IGJ1aWxkaW5nIGEgUkVJTkRFWCBTQ0hFTUEgc3RhdGVtZW50LgogKgogKiBVc2UgY2hhaW5hYmxlIG1ldGhvZHM6IC0+Y29uY3VycmVudGx5KCksIC0+dmVyYm9zZSgpLCAtPnRhYmxlc3BhY2UoKQogKgogKiBFeGFtcGxlOiByZWluZGV4X3NjaGVtYSgncHVibGljJyktPmNvbmN1cnJlbnRseSgpCiAqCiAqIEBwYXJhbSBzdHJpbmcgJG5hbWUgVGhlIHNjaGVtYSBuYW1lCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":415,"slug":"reindex-database","name":"reindex_database","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"ReindexFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Index\\Reindex","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFN0YXJ0IGJ1aWxkaW5nIGEgUkVJTkRFWCBEQVRBQkFTRSBzdGF0ZW1lbnQuCiAqCiAqIFVzZSBjaGFpbmFibGUgbWV0aG9kczogLT5jb25jdXJyZW50bHkoKSwgLT52ZXJib3NlKCksIC0+dGFibGVzcGFjZSgpCiAqCiAqIEV4YW1wbGU6IHJlaW5kZXhfZGF0YWJhc2UoJ215ZGInKS0+Y29uY3VycmVudGx5KCkKICoKICogQHBhcmFtIHN0cmluZyAkbmFtZSBUaGUgZGF0YWJhc2UgbmFtZQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":430,"slug":"index-col","name":"index_col","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"IndexColumn","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Index","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBpbmRleCBjb2x1bW4gc3BlY2lmaWNhdGlvbi4KICoKICogVXNlIGNoYWluYWJsZSBtZXRob2RzOiAtPmFzYygpLCAtPmRlc2MoKSwgLT5udWxsc0ZpcnN0KCksIC0+bnVsbHNMYXN0KCksIC0+b3BjbGFzcygpLCAtPmNvbGxhdGUoKQogKgogKiBFeGFtcGxlOiBpbmRleF9jb2woJ2VtYWlsJyktPmRlc2MoKS0+bnVsbHNMYXN0KCkKICoKICogQHBhcmFtIHN0cmluZyAkbmFtZSBUaGUgY29sdW1uIG5hbWUKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":445,"slug":"index-expr","name":"index_expr","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expression","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"IndexColumn","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Index","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBpbmRleCBjb2x1bW4gc3BlY2lmaWNhdGlvbiBmcm9tIGFuIGV4cHJlc3Npb24uCiAqCiAqIFVzZSBjaGFpbmFibGUgbWV0aG9kczogLT5hc2MoKSwgLT5kZXNjKCksIC0+bnVsbHNGaXJzdCgpLCAtPm51bGxzTGFzdCgpLCAtPm9wY2xhc3MoKSwgLT5jb2xsYXRlKCkKICoKICogRXhhbXBsZTogaW5kZXhfZXhwcihmbl9jYWxsKCdsb3dlcicsIGNvbCgnZW1haWwnKSkpLT5kZXNjKCkKICoKICogQHBhcmFtIEV4cHJlc3Npb24gJGV4cHJlc3Npb24gVGhlIGV4cHJlc3Npb24gdG8gaW5kZXgKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":454,"slug":"index-method-btree","name":"index_method_btree","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"IndexMethod","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Index","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEdldCB0aGUgQlRSRUUgaW5kZXggbWV0aG9kLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":463,"slug":"index-method-hash","name":"index_method_hash","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"IndexMethod","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Index","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEdldCB0aGUgSEFTSCBpbmRleCBtZXRob2QuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":472,"slug":"index-method-gist","name":"index_method_gist","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"IndexMethod","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Index","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEdldCB0aGUgR0lTVCBpbmRleCBtZXRob2QuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":481,"slug":"index-method-spgist","name":"index_method_spgist","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"IndexMethod","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Index","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEdldCB0aGUgU1BHSVNUIGluZGV4IG1ldGhvZC4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":490,"slug":"index-method-gin","name":"index_method_gin","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"IndexMethod","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Index","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEdldCB0aGUgR0lOIGluZGV4IG1ldGhvZC4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":499,"slug":"index-method-brin","name":"index_method_brin","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"IndexMethod","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Index","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEdldCB0aGUgQlJJTiBpbmRleCBtZXRob2QuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":511,"slug":"vacuum","name":"vacuum","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"VacuumFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Utility","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFZBQ1VVTSBidWlsZGVyLgogKgogKiBFeGFtcGxlOiB2YWN1dW0oKS0+dGFibGUoJ3VzZXJzJykKICogUHJvZHVjZXM6IFZBQ1VVTSB1c2VycwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":523,"slug":"analyze","name":"analyze","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"AnalyzeFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Utility","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBBTkFMWVpFIGJ1aWxkZXIuCiAqCiAqIEV4YW1wbGU6IGFuYWx5emUoKS0+dGFibGUoJ3VzZXJzJykKICogUHJvZHVjZXM6IEFOQUxZWkUgdXNlcnMKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":537,"slug":"explain","name":"explain","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"query","type":[{"name":"SelectFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Select","is_nullable":false,"is_variadic":false},{"name":"InsertBuilder","namespace":"Flow\\PostgreSql\\QueryBuilder\\Insert","is_nullable":false,"is_variadic":false},{"name":"UpdateBuilder","namespace":"Flow\\PostgreSql\\QueryBuilder\\Update","is_nullable":false,"is_variadic":false},{"name":"DeleteBuilder","namespace":"Flow\\PostgreSql\\QueryBuilder\\Delete","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ExplainFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Utility","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBFWFBMQUlOIGJ1aWxkZXIgZm9yIGEgcXVlcnkuCiAqCiAqIEV4YW1wbGU6IGV4cGxhaW4oc2VsZWN0KCktPmZyb20oJ3VzZXJzJykpCiAqIFByb2R1Y2VzOiBFWFBMQUlOIFNFTEVDVCAqIEZST00gdXNlcnMKICoKICogQHBhcmFtIERlbGV0ZUJ1aWxkZXJ8SW5zZXJ0QnVpbGRlcnxTZWxlY3RGaW5hbFN0ZXB8VXBkYXRlQnVpbGRlciAkcXVlcnkgUXVlcnkgdG8gZXhwbGFpbgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":549,"slug":"lock-table","name":"lock_table","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"tables","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":"LockFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Utility","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIExPQ0sgVEFCTEUgYnVpbGRlci4KICoKICogRXhhbXBsZTogbG9ja190YWJsZSgndXNlcnMnLCAnb3JkZXJzJyktPmFjY2Vzc0V4Y2x1c2l2ZSgpCiAqIFByb2R1Y2VzOiBMT0NLIFRBQkxFIHVzZXJzLCBvcmRlcnMgSU4gQUNDRVNTIEVYQ0xVU0lWRSBNT0RFCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":564,"slug":"comment","name":"comment","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"target","type":[{"name":"CommentTarget","namespace":"Flow\\PostgreSql\\QueryBuilder\\Utility","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"name","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":"CommentFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Utility","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENPTU1FTlQgT04gYnVpbGRlci4KICoKICogRXhhbXBsZTogY29tbWVudChDb21tZW50VGFyZ2V0OjpUQUJMRSwgJ3VzZXJzJyktPmlzKCdVc2VyIGFjY291bnRzIHRhYmxlJykKICogUHJvZHVjZXM6IENPTU1FTlQgT04gVEFCTEUgdXNlcnMgSVMgJ1VzZXIgYWNjb3VudHMgdGFibGUnCiAqCiAqIEBwYXJhbSBDb21tZW50VGFyZ2V0ICR0YXJnZXQgVGFyZ2V0IHR5cGUgKFRBQkxFLCBDT0xVTU4sIElOREVYLCBldGMuKQogKiBAcGFyYW0gc3RyaW5nICRuYW1lIFRhcmdldCBuYW1lICh1c2UgJ3RhYmxlLmNvbHVtbicgZm9yIENPTFVNTiB0YXJnZXRzKQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":576,"slug":"cluster","name":"cluster","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ClusterFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Utility","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENMVVNURVIgYnVpbGRlci4KICoKICogRXhhbXBsZTogY2x1c3RlcigpLT50YWJsZSgndXNlcnMnKS0+dXNpbmcoJ2lkeF91c2Vyc19wa2V5JykKICogUHJvZHVjZXM6IENMVVNURVIgdXNlcnMgVVNJTkcgaWR4X3VzZXJzX3BrZXkKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":590,"slug":"discard","name":"discard","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"type","type":[{"name":"DiscardType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Utility","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"DiscardFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Utility","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIERJU0NBUkQgYnVpbGRlci4KICoKICogRXhhbXBsZTogZGlzY2FyZChEaXNjYXJkVHlwZTo6QUxMKQogKiBQcm9kdWNlczogRElTQ0FSRCBBTEwKICoKICogQHBhcmFtIERpc2NhcmRUeXBlICR0eXBlIFR5cGUgb2YgcmVzb3VyY2VzIHRvIGRpc2NhcmQgKEFMTCwgUExBTlMsIFNFUVVFTkNFUywgVEVNUCkKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":609,"slug":"grant","name":"grant","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"privileges","type":[{"name":"TablePrivilege","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Grant","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":"GrantOnStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Grant","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEdSQU5UIHByaXZpbGVnZXMgYnVpbGRlci4KICoKICogRXhhbXBsZTogZ3JhbnQoVGFibGVQcml2aWxlZ2U6OlNFTEVDVCktPm9uVGFibGUoJ3VzZXJzJyktPnRvKCdhcHBfdXNlcicpCiAqIFByb2R1Y2VzOiBHUkFOVCBTRUxFQ1QgT04gdXNlcnMgVE8gYXBwX3VzZXIKICoKICogRXhhbXBsZTogZ3JhbnQoVGFibGVQcml2aWxlZ2U6OkFMTCktPm9uQWxsVGFibGVzSW5TY2hlbWEoJ3B1YmxpYycpLT50bygnYWRtaW4nKQogKiBQcm9kdWNlczogR1JBTlQgQUxMIE9OIEFMTCBUQUJMRVMgSU4gU0NIRU1BIHB1YmxpYyBUTyBhZG1pbgogKgogKiBAcGFyYW0gc3RyaW5nfFRhYmxlUHJpdmlsZWdlIC4uLiRwcml2aWxlZ2VzIFRoZSBwcml2aWxlZ2VzIHRvIGdyYW50CiAqCiAqIEByZXR1cm4gR3JhbnRPblN0ZXAgQnVpbGRlciBmb3IgZ3JhbnQgb3B0aW9ucwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":628,"slug":"grant-role","name":"grant_role","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"roles","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":"GrantRoleToStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Grant","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEdSQU5UIHJvbGUgYnVpbGRlci4KICoKICogRXhhbXBsZTogZ3JhbnRfcm9sZSgnYWRtaW4nKS0+dG8oJ3VzZXIxJykKICogUHJvZHVjZXM6IEdSQU5UIGFkbWluIFRPIHVzZXIxCiAqCiAqIEV4YW1wbGU6IGdyYW50X3JvbGUoJ2FkbWluJywgJ2RldmVsb3BlcicpLT50bygndXNlcjEnKS0+d2l0aEFkbWluT3B0aW9uKCkKICogUHJvZHVjZXM6IEdSQU5UIGFkbWluLCBkZXZlbG9wZXIgVE8gdXNlcjEgV0lUSCBBRE1JTiBPUFRJT04KICoKICogQHBhcmFtIHN0cmluZyAuLi4kcm9sZXMgVGhlIHJvbGVzIHRvIGdyYW50CiAqCiAqIEByZXR1cm4gR3JhbnRSb2xlVG9TdGVwIEJ1aWxkZXIgZm9yIGdyYW50IHJvbGUgb3B0aW9ucwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":647,"slug":"revoke","name":"revoke","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"privileges","type":[{"name":"TablePrivilege","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Grant","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":"RevokeOnStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Grant","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFJFVk9LRSBwcml2aWxlZ2VzIGJ1aWxkZXIuCiAqCiAqIEV4YW1wbGU6IHJldm9rZShUYWJsZVByaXZpbGVnZTo6U0VMRUNUKS0+b25UYWJsZSgndXNlcnMnKS0+ZnJvbSgnYXBwX3VzZXInKQogKiBQcm9kdWNlczogUkVWT0tFIFNFTEVDVCBPTiB1c2VycyBGUk9NIGFwcF91c2VyCiAqCiAqIEV4YW1wbGU6IHJldm9rZShUYWJsZVByaXZpbGVnZTo6QUxMKS0+b25UYWJsZSgndXNlcnMnKS0+ZnJvbSgnYXBwX3VzZXInKS0+Y2FzY2FkZSgpCiAqIFByb2R1Y2VzOiBSRVZPS0UgQUxMIE9OIHVzZXJzIEZST00gYXBwX3VzZXIgQ0FTQ0FERQogKgogKiBAcGFyYW0gc3RyaW5nfFRhYmxlUHJpdmlsZWdlIC4uLiRwcml2aWxlZ2VzIFRoZSBwcml2aWxlZ2VzIHRvIHJldm9rZQogKgogKiBAcmV0dXJuIFJldm9rZU9uU3RlcCBCdWlsZGVyIGZvciByZXZva2Ugb3B0aW9ucwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":666,"slug":"revoke-role","name":"revoke_role","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"roles","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":"RevokeRoleFromStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Grant","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFJFVk9LRSByb2xlIGJ1aWxkZXIuCiAqCiAqIEV4YW1wbGU6IHJldm9rZV9yb2xlKCdhZG1pbicpLT5mcm9tKCd1c2VyMScpCiAqIFByb2R1Y2VzOiBSRVZPS0UgYWRtaW4gRlJPTSB1c2VyMQogKgogKiBFeGFtcGxlOiByZXZva2Vfcm9sZSgnYWRtaW4nKS0+ZnJvbSgndXNlcjEnKS0+Y2FzY2FkZSgpCiAqIFByb2R1Y2VzOiBSRVZPS0UgYWRtaW4gRlJPTSB1c2VyMSBDQVNDQURFCiAqCiAqIEBwYXJhbSBzdHJpbmcgLi4uJHJvbGVzIFRoZSByb2xlcyB0byByZXZva2UKICoKICogQHJldHVybiBSZXZva2VSb2xlRnJvbVN0ZXAgQnVpbGRlciBmb3IgcmV2b2tlIHJvbGUgb3B0aW9ucwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":682,"slug":"set-role","name":"set_role","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"role","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":"SetRoleFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Session","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFNFVCBST0xFIGJ1aWxkZXIuCiAqCiAqIEV4YW1wbGU6IHNldF9yb2xlKCdhZG1pbicpCiAqIFByb2R1Y2VzOiBTRVQgUk9MRSBhZG1pbgogKgogKiBAcGFyYW0gc3RyaW5nICRyb2xlIFRoZSByb2xlIHRvIHNldAogKgogKiBAcmV0dXJuIFNldFJvbGVGaW5hbFN0ZXAgQnVpbGRlciBmb3Igc2V0IHJvbGUKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":696,"slug":"reset-role","name":"reset_role","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ResetRoleFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Session","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFJFU0VUIFJPTEUgYnVpbGRlci4KICoKICogRXhhbXBsZTogcmVzZXRfcm9sZSgpCiAqIFByb2R1Y2VzOiBSRVNFVCBST0xFCiAqCiAqIEByZXR1cm4gUmVzZXRSb2xlRmluYWxTdGVwIEJ1aWxkZXIgZm9yIHJlc2V0IHJvbGUKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":712,"slug":"reassign-owned","name":"reassign_owned","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"roles","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":"ReassignOwnedToStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Ownership","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFJFQVNTSUdOIE9XTkVEIGJ1aWxkZXIuCiAqCiAqIEV4YW1wbGU6IHJlYXNzaWduX293bmVkKCdvbGRfcm9sZScpLT50bygnbmV3X3JvbGUnKQogKiBQcm9kdWNlczogUkVBU1NJR04gT1dORUQgQlkgb2xkX3JvbGUgVE8gbmV3X3JvbGUKICoKICogQHBhcmFtIHN0cmluZyAuLi4kcm9sZXMgVGhlIHJvbGVzIHdob3NlIG93bmVkIG9iamVjdHMgc2hvdWxkIGJlIHJlYXNzaWduZWQKICoKICogQHJldHVybiBSZWFzc2lnbk93bmVkVG9TdGVwIEJ1aWxkZXIgZm9yIHJlYXNzaWduIG93bmVkIG9wdGlvbnMKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":731,"slug":"drop-owned","name":"drop_owned","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"roles","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":"DropOwnedFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Ownership","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIERST1AgT1dORUQgYnVpbGRlci4KICoKICogRXhhbXBsZTogZHJvcF9vd25lZCgncm9sZTEnKQogKiBQcm9kdWNlczogRFJPUCBPV05FRCBCWSByb2xlMQogKgogKiBFeGFtcGxlOiBkcm9wX293bmVkKCdyb2xlMScsICdyb2xlMicpLT5jYXNjYWRlKCkKICogUHJvZHVjZXM6IERST1AgT1dORUQgQlkgcm9sZTEsIHJvbGUyIENBU0NBREUKICoKICogQHBhcmFtIHN0cmluZyAuLi4kcm9sZXMgVGhlIHJvbGVzIHdob3NlIG93bmVkIG9iamVjdHMgc2hvdWxkIGJlIGRyb3BwZWQKICoKICogQHJldHVybiBEcm9wT3duZWRGaW5hbFN0ZXAgQnVpbGRlciBmb3IgZHJvcCBvd25lZCBvcHRpb25zCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":749,"slug":"func-arg","name":"func_arg","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"type","type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"FunctionArgument","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZXMgYSBuZXcgZnVuY3Rpb24gYXJndW1lbnQgZm9yIHVzZSBpbiBmdW5jdGlvbi9wcm9jZWR1cmUgZGVmaW5pdGlvbnMuCiAqCiAqIEV4YW1wbGU6IGZ1bmNfYXJnKGNvbHVtbl90eXBlX2ludGVnZXIoKSkKICogRXhhbXBsZTogZnVuY19hcmcoY29sdW1uX3R5cGVfdGV4dCgpKS0+bmFtZWQoJ3VzZXJuYW1lJykKICogRXhhbXBsZTogZnVuY19hcmcoY29sdW1uX3R5cGVfaW50ZWdlcigpKS0+bmFtZWQoJ2NvdW50JyktPmRlZmF1bHQoJzAnKQogKiBFeGFtcGxlOiBmdW5jX2FyZyhjb2x1bW5fdHlwZV90ZXh0KCkpLT5vdXQoKQogKgogKiBAcGFyYW0gQ29sdW1uVHlwZSAkdHlwZSBUaGUgUG9zdGdyZVNRTCBkYXRhIHR5cGUgZm9yIHRoZSBhcmd1bWVudAogKgogKiBAcmV0dXJuIEZ1bmN0aW9uQXJndW1lbnQgQnVpbGRlciBmb3IgZnVuY3Rpb24gYXJndW1lbnQgb3B0aW9ucwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":768,"slug":"call","name":"call","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"procedure","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":"CallFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZXMgYSBDQUxMIHN0YXRlbWVudCBidWlsZGVyIGZvciBpbnZva2luZyBhIHByb2NlZHVyZS4KICoKICogRXhhbXBsZTogY2FsbCgndXBkYXRlX3N0YXRzJyktPndpdGgoMTIzKQogKiBQcm9kdWNlczogQ0FMTCB1cGRhdGVfc3RhdHMoMTIzKQogKgogKiBFeGFtcGxlOiBjYWxsKCdwcm9jZXNzX2RhdGEnKS0+d2l0aCgndGVzdCcsIDQyLCB0cnVlKQogKiBQcm9kdWNlczogQ0FMTCBwcm9jZXNzX2RhdGEoJ3Rlc3QnLCA0MiwgdHJ1ZSkKICoKICogQHBhcmFtIHN0cmluZyAkcHJvY2VkdXJlIFRoZSBuYW1lIG9mIHRoZSBwcm9jZWR1cmUgdG8gY2FsbAogKgogKiBAcmV0dXJuIENhbGxGaW5hbFN0ZXAgQnVpbGRlciBmb3IgY2FsbCBzdGF0ZW1lbnQgb3B0aW9ucwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":787,"slug":"do-block","name":"do_block","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"code","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":"DoFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZXMgYSBETyBzdGF0ZW1lbnQgYnVpbGRlciBmb3IgZXhlY3V0aW5nIGFuIGFub255bW91cyBjb2RlIGJsb2NrLgogKgogKiBFeGFtcGxlOiBkb19ibG9jaygnQkVHSU4gUkFJU0UgTk9USUNFICQkSGVsbG8gV29ybGQkJDsgRU5EOycpCiAqIFByb2R1Y2VzOiBETyAkJCBCRUdJTiBSQUlTRSBOT1RJQ0UgJCRIZWxsbyBXb3JsZCQkOyBFTkQ7ICQkIExBTkdVQUdFIHBscGdzcWwKICoKICogRXhhbXBsZTogZG9fYmxvY2soJ1NFTEVDVCAxJyktPmxhbmd1YWdlKCdzcWwnKQogKiBQcm9kdWNlczogRE8gJCQgU0VMRUNUIDEgJCQgTEFOR1VBR0Ugc3FsCiAqCiAqIEBwYXJhbSBzdHJpbmcgJGNvZGUgVGhlIGFub255bW91cyBjb2RlIGJsb2NrIHRvIGV4ZWN1dGUKICoKICogQHJldHVybiBEb0ZpbmFsU3RlcCBCdWlsZGVyIGZvciBETyBzdGF0ZW1lbnQgb3B0aW9ucwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":807,"slug":"type-attr","name":"type_attr","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"type","type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"TypeAttribute","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Type","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZXMgYSB0eXBlIGF0dHJpYnV0ZSBmb3IgY29tcG9zaXRlIHR5cGVzLgogKgogKiBFeGFtcGxlOiB0eXBlX2F0dHIoJ25hbWUnLCBjb2x1bW5fdHlwZV90ZXh0KCkpCiAqIFByb2R1Y2VzOiBuYW1lIHRleHQKICoKICogRXhhbXBsZTogdHlwZV9hdHRyKCdkZXNjcmlwdGlvbicsIGNvbHVtbl90eXBlX3RleHQoKSktPmNvbGxhdGUoJ2VuX1VTJykKICogUHJvZHVjZXM6IGRlc2NyaXB0aW9uIHRleHQgQ09MTEFURSAiZW5fVVMiCiAqCiAqIEBwYXJhbSBzdHJpbmcgJG5hbWUgVGhlIGF0dHJpYnV0ZSBuYW1lCiAqIEBwYXJhbSBDb2x1bW5UeXBlICR0eXBlIFRoZSBhdHRyaWJ1dGUgdHlwZQogKgogKiBAcmV0dXJuIFR5cGVBdHRyaWJ1dGUgVHlwZSBhdHRyaWJ1dGUgdmFsdWUgb2JqZWN0CiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":816,"slug":"column-type-integer","name":"column_type_integer","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBpbnRlZ2VyIGRhdGEgdHlwZSAoUG9zdGdyZVNRTCBpbnQ0KS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":825,"slug":"column-type-smallint","name":"column_type_smallint","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHNtYWxsaW50IGRhdGEgdHlwZSAoUG9zdGdyZVNRTCBpbnQyKS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":834,"slug":"column-type-bigint","name":"column_type_bigint","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGJpZ2ludCBkYXRhIHR5cGUgKFBvc3RncmVTUUwgaW50OCkuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":843,"slug":"column-type-boolean","name":"column_type_boolean","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGJvb2xlYW4gZGF0YSB0eXBlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":852,"slug":"column-type-text","name":"column_type_text","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHRleHQgZGF0YSB0eXBlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":861,"slug":"column-type-varchar","name":"column_type_varchar","namespace":"Flow\\PostgreSql\\DSL","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}],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHZhcmNoYXIgZGF0YSB0eXBlIHdpdGggbGVuZ3RoIGNvbnN0cmFpbnQuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":870,"slug":"column-type-char","name":"column_type_char","namespace":"Flow\\PostgreSql\\DSL","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}],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGNoYXIgZGF0YSB0eXBlIHdpdGggbGVuZ3RoIGNvbnN0cmFpbnQuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":879,"slug":"column-type-numeric","name":"column_type_numeric","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"precision","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":"scale","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":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIG51bWVyaWMgZGF0YSB0eXBlIHdpdGggb3B0aW9uYWwgcHJlY2lzaW9uIGFuZCBzY2FsZS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":888,"slug":"column-type-decimal","name":"column_type_decimal","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"precision","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":"scale","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":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGRlY2ltYWwgZGF0YSB0eXBlIHdpdGggb3B0aW9uYWwgcHJlY2lzaW9uIGFuZCBzY2FsZS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":897,"slug":"column-type-real","name":"column_type_real","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHJlYWwgZGF0YSB0eXBlIChQb3N0Z3JlU1FMIGZsb2F0NCkuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":906,"slug":"column-type-double-precision","name":"column_type_double_precision","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGRvdWJsZSBwcmVjaXNpb24gZGF0YSB0eXBlIChQb3N0Z3JlU1FMIGZsb2F0OCkuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":915,"slug":"column-type-date","name":"column_type_date","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGRhdGUgZGF0YSB0eXBlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":924,"slug":"column-type-time","name":"column_type_time","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"precision","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":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHRpbWUgZGF0YSB0eXBlIHdpdGggb3B0aW9uYWwgcHJlY2lzaW9uLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":933,"slug":"column-type-timestamp","name":"column_type_timestamp","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"precision","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":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHRpbWVzdGFtcCBkYXRhIHR5cGUgd2l0aCBvcHRpb25hbCBwcmVjaXNpb24uCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":942,"slug":"column-type-timestamptz","name":"column_type_timestamptz","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"precision","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":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHRpbWVzdGFtcCB3aXRoIHRpbWUgem9uZSBkYXRhIHR5cGUgd2l0aCBvcHRpb25hbCBwcmVjaXNpb24uCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":951,"slug":"column-type-interval","name":"column_type_interval","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBpbnRlcnZhbCBkYXRhIHR5cGUuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":960,"slug":"column-type-uuid","name":"column_type_uuid","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFVVSUQgZGF0YSB0eXBlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":969,"slug":"column-type-json","name":"column_type_json","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEpTT04gZGF0YSB0eXBlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":978,"slug":"column-type-jsonb","name":"column_type_jsonb","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEpTT05CIGRhdGEgdHlwZS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":987,"slug":"column-type-bytea","name":"column_type_bytea","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGJ5dGVhIGRhdGEgdHlwZS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":996,"slug":"column-type-xml","name":"column_type_xml","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBYTUwgZGF0YSB0eXBlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1005,"slug":"column-type-inet","name":"column_type_inet","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBpbmV0IGRhdGEgdHlwZS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1014,"slug":"column-type-cidr","name":"column_type_cidr","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGNpZHIgZGF0YSB0eXBlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1023,"slug":"column-type-macaddr","name":"column_type_macaddr","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIG1hY2FkZHIgZGF0YSB0eXBlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1032,"slug":"column-type-serial","name":"column_type_serial","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHNlcmlhbCBkYXRhIHR5cGUuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1041,"slug":"column-type-smallserial","name":"column_type_smallserial","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHNtYWxsc2VyaWFsIGRhdGEgdHlwZS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1050,"slug":"column-type-bigserial","name":"column_type_bigserial","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGJpZ3NlcmlhbCBkYXRhIHR5cGUuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1059,"slug":"column-type-array","name":"column_type_array","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"elementType","type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBhcnJheSBkYXRhIHR5cGUgZnJvbSBhbiBlbGVtZW50IHR5cGUuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1071,"slug":"column-type-custom","name":"column_type_custom","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"typeName","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":"schema","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGN1c3RvbSBkYXRhIHR5cGUuCiAqCiAqIEBwYXJhbSBzdHJpbmcgJHR5cGVOYW1lIFR5cGUgbmFtZQogKiBAcGFyYW0gbnVsbHxzdHJpbmcgJHNjaGVtYSBPcHRpb25hbCBzY2hlbWEgbmFtZQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1084,"slug":"column-type-from-string","name":"column_type_from_string","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"typeName","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":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFBhcnNlIGEgUG9zdGdyZVNRTCB0eXBlIHN0cmluZyBpbnRvIGEgQ29sdW1uVHlwZS4KICoKICogSGFuZGxlcyBhbGwgUG9zdGdyZVNRTCB0eXBlIHN5bnRheCBpbmNsdWRpbmcgcHJlY2lzaW9uLCBhcnJheXMsIGFuZCBzY2hlbWEtcXVhbGlmaWVkIHR5cGVzLgogKgogKiBAcGFyYW0gc3RyaW5nICR0eXBlTmFtZSBQb3N0Z3JlU1FMIHR5cGUgc3RyaW5nIChlLmcuLCAnaW50ZWdlcicsICdjaGFyYWN0ZXIgdmFyeWluZygyNTUpJywgJ3RleHRbXScpCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1092,"slug":"value-type-text","name":"value_type_text","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1098,"slug":"value-type-varchar","name":"value_type_varchar","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1104,"slug":"value-type-char","name":"value_type_char","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1110,"slug":"value-type-bpchar","name":"value_type_bpchar","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1116,"slug":"value-type-int2","name":"value_type_int2","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1122,"slug":"value-type-smallint","name":"value_type_smallint","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1128,"slug":"value-type-int4","name":"value_type_int4","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1134,"slug":"value-type-integer","name":"value_type_integer","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1140,"slug":"value-type-int8","name":"value_type_int8","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1146,"slug":"value-type-bigint","name":"value_type_bigint","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1152,"slug":"value-type-float4","name":"value_type_float4","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1158,"slug":"value-type-real","name":"value_type_real","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1164,"slug":"value-type-float8","name":"value_type_float8","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1170,"slug":"value-type-double","name":"value_type_double","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1176,"slug":"value-type-numeric","name":"value_type_numeric","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1182,"slug":"value-type-money","name":"value_type_money","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1188,"slug":"value-type-bool","name":"value_type_bool","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1194,"slug":"value-type-boolean","name":"value_type_boolean","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1200,"slug":"value-type-bytea","name":"value_type_bytea","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1206,"slug":"value-type-bit","name":"value_type_bit","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1212,"slug":"value-type-varbit","name":"value_type_varbit","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1218,"slug":"value-type-date","name":"value_type_date","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1224,"slug":"value-type-time","name":"value_type_time","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1230,"slug":"value-type-timetz","name":"value_type_timetz","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1236,"slug":"value-type-timestamp","name":"value_type_timestamp","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1242,"slug":"value-type-timestamptz","name":"value_type_timestamptz","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1248,"slug":"value-type-interval","name":"value_type_interval","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1254,"slug":"value-type-json","name":"value_type_json","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1260,"slug":"value-type-jsonb","name":"value_type_jsonb","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1266,"slug":"value-type-uuid","name":"value_type_uuid","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1272,"slug":"value-type-inet","name":"value_type_inet","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1278,"slug":"value-type-cidr","name":"value_type_cidr","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1284,"slug":"value-type-macaddr","name":"value_type_macaddr","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1290,"slug":"value-type-macaddr8","name":"value_type_macaddr8","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1296,"slug":"value-type-xml","name":"value_type_xml","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1302,"slug":"value-type-oid","name":"value_type_oid","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1308,"slug":"value-type-text-array","name":"value_type_text_array","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1314,"slug":"value-type-varchar-array","name":"value_type_varchar_array","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1320,"slug":"value-type-int2-array","name":"value_type_int2_array","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1326,"slug":"value-type-int4-array","name":"value_type_int4_array","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1332,"slug":"value-type-int8-array","name":"value_type_int8_array","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1338,"slug":"value-type-float4-array","name":"value_type_float4_array","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1344,"slug":"value-type-float8-array","name":"value_type_float8_array","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1350,"slug":"value-type-bool-array","name":"value_type_bool_array","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1356,"slug":"value-type-uuid-array","name":"value_type_uuid_array","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1362,"slug":"value-type-json-array","name":"value_type_json_array","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1368,"slug":"value-type-jsonb-array","name":"value_type_jsonb_array","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1384,"slug":"schema","name":"schema","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"tables","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"sequences","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"views","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"materializedViews","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"functions","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"procedures","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"domains","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"extensions","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"Schema","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBsaXN0PFNjaGVtYVRhYmxlPiAkdGFibGVzCiAqIEBwYXJhbSBsaXN0PFNjaGVtYVNlcXVlbmNlPiAkc2VxdWVuY2VzCiAqIEBwYXJhbSBsaXN0PFNjaGVtYVZpZXc+ICR2aWV3cwogKiBAcGFyYW0gbGlzdDxTY2hlbWFNYXRlcmlhbGl6ZWRWaWV3PiAkbWF0ZXJpYWxpemVkVmlld3MKICogQHBhcmFtIGxpc3Q8U2NoZW1hRnVuY3Rpb24+ICRmdW5jdGlvbnMKICogQHBhcmFtIGxpc3Q8U2NoZW1hUHJvY2VkdXJlPiAkcHJvY2VkdXJlcwogKiBAcGFyYW0gbGlzdDxTY2hlbWFEb21haW4+ICRkb21haW5zCiAqIEBwYXJhbSBsaXN0PFNjaGVtYUV4dGVuc2lvbj4gJGV4dGVuc2lvbnMKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1420,"slug":"schema-table","name":"schema_table","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"columns","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":"primaryKey","type":[{"name":"PrimaryKey","namespace":"Flow\\PostgreSql\\Schema\\Constraint","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"indexes","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"foreignKeys","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"uniqueConstraints","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"checkConstraints","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"excludeConstraints","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"triggers","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"schema","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'public'"},{"name":"unlogged","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"partitionStrategy","type":[{"name":"PartitionStrategy","namespace":"Flow\\PostgreSql\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"partitionColumns","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"inherits","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"tablespace","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Table","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBub24tZW1wdHktbGlzdDxTY2hlbWFDb2x1bW4+ICRjb2x1bW5zCiAqIEBwYXJhbSBsaXN0PFNjaGVtYUluZGV4PiAkaW5kZXhlcwogKiBAcGFyYW0gbGlzdDxTY2hlbWFGb3JlaWduS2V5PiAkZm9yZWlnbktleXMKICogQHBhcmFtIGxpc3Q8U2NoZW1hVW5pcXVlQ29uc3RyYWludD4gJHVuaXF1ZUNvbnN0cmFpbnRzCiAqIEBwYXJhbSBsaXN0PFNjaGVtYUNoZWNrQ29uc3RyYWludD4gJGNoZWNrQ29uc3RyYWludHMKICogQHBhcmFtIGxpc3Q8U2NoZW1hRXhjbHVkZUNvbnN0cmFpbnQ+ICRleGNsdWRlQ29uc3RyYWludHMKICogQHBhcmFtIGxpc3Q8U2NoZW1hVHJpZ2dlcj4gJHRyaWdnZXJzCiAqIEBwYXJhbSBsaXN0PHN0cmluZz4gJHBhcnRpdGlvbkNvbHVtbnMKICogQHBhcmFtIGxpc3Q8c3RyaW5nPiAkaW5oZXJpdHMKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1465,"slug":"schema-table-options","name":"schema_table_options","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"foreignKeys","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"checkConstraints","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"excludeConstraints","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"triggers","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"unlogged","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"partitionStrategy","type":[{"name":"PartitionStrategy","namespace":"Flow\\PostgreSql\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"partitionColumns","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"inherits","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"tablespace","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"TableOptions","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBsaXN0PFNjaGVtYUZvcmVpZ25LZXk+ICRmb3JlaWduS2V5cwogKiBAcGFyYW0gbGlzdDxTY2hlbWFDaGVja0NvbnN0cmFpbnQ+ICRjaGVja0NvbnN0cmFpbnRzCiAqIEBwYXJhbSBsaXN0PFNjaGVtYUV4Y2x1ZGVDb25zdHJhaW50PiAkZXhjbHVkZUNvbnN0cmFpbnRzCiAqIEBwYXJhbSBsaXN0PFNjaGVtYVRyaWdnZXI+ICR0cmlnZ2VycwogKiBAcGFyYW0gbGlzdDxzdHJpbmc+ICRwYXJ0aXRpb25Db2x1bW5zCiAqIEBwYXJhbSBsaXN0PHN0cmluZz4gJGluaGVyaXRzCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1490,"slug":"schema-column","name":"schema_column","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"type","type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"isIdentity","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"identityGeneration","type":[{"name":"IdentityGeneration","namespace":"Flow\\PostgreSql\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"isGenerated","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"generationExpression","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":"ordinalPosition","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1515,"slug":"schema-column-integer","name":"schema_column_integer","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1524,"slug":"schema-column-smallint","name":"schema_column_smallint","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1533,"slug":"schema-column-bigint","name":"schema_column_bigint","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1542,"slug":"schema-column-serial","name":"schema_column_serial","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1548,"slug":"schema-column-small-serial","name":"schema_column_small_serial","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1554,"slug":"schema-column-big-serial","name":"schema_column_big_serial","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1560,"slug":"schema-column-boolean","name":"schema_column_boolean","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1569,"slug":"schema-column-text","name":"schema_column_text","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1578,"slug":"schema-column-varchar","name":"schema_column_varchar","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1588,"slug":"schema-column-char","name":"schema_column_char","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1598,"slug":"schema-column-numeric","name":"schema_column_numeric","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"precision","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":"scale","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1609,"slug":"schema-column-real","name":"schema_column_real","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1618,"slug":"schema-column-double-precision","name":"schema_column_double_precision","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1627,"slug":"schema-column-date","name":"schema_column_date","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1636,"slug":"schema-column-time","name":"schema_column_time","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"precision","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1646,"slug":"schema-column-timestamp","name":"schema_column_timestamp","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"precision","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1656,"slug":"schema-column-timestamp-tz","name":"schema_column_timestamp_tz","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"precision","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1666,"slug":"schema-column-interval","name":"schema_column_interval","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1675,"slug":"schema-column-uuid","name":"schema_column_uuid","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1684,"slug":"schema-column-json","name":"schema_column_json","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1693,"slug":"schema-column-jsonb","name":"schema_column_jsonb","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1702,"slug":"schema-column-bytea","name":"schema_column_bytea","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1711,"slug":"schema-column-inet","name":"schema_column_inet","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1720,"slug":"schema-column-cidr","name":"schema_column_cidr","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1729,"slug":"schema-column-macaddr","name":"schema_column_macaddr","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1741,"slug":"schema-primary-key","name":"schema_primary_key","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"columns","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":"name","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"PrimaryKey","namespace":"Flow\\PostgreSql\\Schema\\Constraint","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBub24tZW1wdHktbGlzdDxzdHJpbmc+ICRjb2x1bW5zCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1751,"slug":"schema-foreign-key","name":"schema_foreign_key","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"columns","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":"referenceTable","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":"referenceColumns","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":"name","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":"referenceSchema","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'public'"},{"name":"onUpdate","type":[{"name":"ReferentialAction","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\PostgreSql\\QueryBuilder\\Schema\\ReferentialAction::..."},{"name":"onDelete","type":[{"name":"ReferentialAction","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\PostgreSql\\QueryBuilder\\Schema\\ReferentialAction::..."},{"name":"deferrable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"initiallyDeferred","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":"ForeignKey","namespace":"Flow\\PostgreSql\\Schema\\Constraint","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBub24tZW1wdHktbGlzdDxzdHJpbmc+ICRjb2x1bW5zCiAqIEBwYXJhbSBub24tZW1wdHktbGlzdDxzdHJpbmc+ICRyZWZlcmVuY2VDb2x1bW5zCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1779,"slug":"schema-unique","name":"schema_unique","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"columns","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":"name","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":"nullsNotDistinct","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":"UniqueConstraint","namespace":"Flow\\PostgreSql\\Schema\\Constraint","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBub24tZW1wdHktbGlzdDxzdHJpbmc+ICRjb2x1bW5zCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1785,"slug":"schema-check","name":"schema_check","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expression","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":"name","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":"noInherit","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":"CheckConstraint","namespace":"Flow\\PostgreSql\\Schema\\Constraint","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1791,"slug":"schema-exclude","name":"schema_exclude","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"definition","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":"name","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"ExcludeConstraint","namespace":"Flow\\PostgreSql\\Schema\\Constraint","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1800,"slug":"schema-index","name":"schema_index","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"columns","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":"unique","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"method","type":[{"name":"IndexMethod","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\PostgreSql\\Schema\\IndexMethod::..."},{"name":"primary","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"predicate","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Index","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBub24tZW1wdHktbGlzdDxzdHJpbmc+ICRjb2x1bW5zCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1812,"slug":"schema-sequence","name":"schema_sequence","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"dataType","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'bigint'"},{"name":"startValue","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":"1"},{"name":"minValue","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":"1"},{"name":"maxValue","type":[{"name":"string","namespace":null,"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":"incrementBy","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":"1"},{"name":"cycle","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"cacheValue","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":"1"},{"name":"ownedByTable","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":"ownedByColumn","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Sequence","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1839,"slug":"schema-view","name":"schema_view","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"definition","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":"isUpdatable","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":"View","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1848,"slug":"schema-materialized-view","name":"schema_materialized_view","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"definition","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":"indexes","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"MaterializedView","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBsaXN0PFNjaGVtYUluZGV4PiAkaW5kZXhlcwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1857,"slug":"schema-function","name":"schema_function","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"returnType","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":"argumentTypes","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"language","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'sql'"},{"name":"definition","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":"isStrict","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"volatility","type":[{"name":"FunctionVolatility","namespace":"Flow\\PostgreSql\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Func","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBsaXN0PHN0cmluZz4gJGFyZ3VtZW50VHlwZXMKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1873,"slug":"schema-procedure","name":"schema_procedure","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"argumentTypes","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"language","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'sql'"},{"name":"definition","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Procedure","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBsaXN0PHN0cmluZz4gJGFyZ3VtZW50VHlwZXMKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1886,"slug":"schema-trigger","name":"schema_trigger","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"tableName","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":"timing","type":[{"name":"TriggerTiming","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"events","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":"functionName","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":"forEachRow","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"whenCondition","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Trigger","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBub24tZW1wdHktbGlzdDxUcmlnZ2VyRXZlbnQ+ICRldmVudHMKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1902,"slug":"schema-domain","name":"schema_domain","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"baseType","type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"default","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"bool","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":"checkConstraints","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"Domain","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBsaXN0PFNjaGVtYUNoZWNrQ29uc3RyYWludD4gJGNoZWNrQ29uc3RyYWludHMKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1913,"slug":"schema-extension","name":"schema_extension","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"version","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Extension","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1922,"slug":"client-catalog-provider","name":"client_catalog_provider","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"client","type":[{"name":"Client","namespace":"Flow\\PostgreSql\\Client","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"schemaNames","type":[{"name":"array","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"exclusionPolicy","type":[{"name":"ExclusionPolicy","namespace":"Flow\\PostgreSql\\Schema\\Exclusion","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"CatalogProvider","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSA\/bGlzdDxzdHJpbmc+ICRzY2hlbWFOYW1lcwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1931,"slug":"exclude-any","name":"exclude_any","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"policies","type":[{"name":"ExclusionPolicy","namespace":"Flow\\PostgreSql\\Schema\\Exclusion","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"ExclusionPolicy","namespace":"Flow\\PostgreSql\\Schema\\Exclusion","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1937,"slug":"exclude-exact","name":"exclude_exact","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"ExclusionPolicy","namespace":"Flow\\PostgreSql\\Schema\\Exclusion","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1943,"slug":"exclude-starts-with","name":"exclude_starts_with","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"prefix","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":"ExclusionPolicy","namespace":"Flow\\PostgreSql\\Schema\\Exclusion","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1949,"slug":"exclude-ends-with","name":"exclude_ends_with","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"suffix","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":"ExclusionPolicy","namespace":"Flow\\PostgreSql\\Schema\\Exclusion","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1955,"slug":"exclude-pattern","name":"exclude_pattern","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"pattern","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":"ExclusionPolicy","namespace":"Flow\\PostgreSql\\Schema\\Exclusion","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1961,"slug":"exclude-schema","name":"exclude_schema","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"schema","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":"ExclusionPolicy","namespace":"Flow\\PostgreSql\\Schema\\Exclusion","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1967,"slug":"exclude-scoped","name":"exclude_scoped","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"policy","type":[{"name":"ExclusionPolicy","namespace":"Flow\\PostgreSql\\Schema\\Exclusion","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"type","type":[{"name":"SchemaObjectType","namespace":"Flow\\PostgreSql\\Schema\\Exclusion","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"schema","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"ExclusionPolicy","namespace":"Flow\\PostgreSql\\Schema\\Exclusion","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1976,"slug":"manual-catalog-provider","name":"manual_catalog_provider","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"catalog","type":[{"name":"Catalog","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"CatalogProvider","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1982,"slug":"chain-catalog-provider","name":"chain_catalog_provider","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"providers","type":[{"name":"CatalogProvider","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"ChainCatalogProvider","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1991,"slug":"catalog-comparator","name":"catalog_comparator","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"renameStrategy","type":[{"name":"RenameStrategy","namespace":"Flow\\PostgreSql\\Schema\\Diff","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"viewDependencyResolver","type":[{"name":"ViewDependencyResolver","namespace":"Flow\\PostgreSql\\Schema\\Diff","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"tableOrderStrategy","type":[{"name":"ExecutionOrderStrategy","namespace":"Flow\\PostgreSql\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"dropIfExists","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":"CatalogComparator","namespace":"Flow\\PostgreSql\\Schema\\Diff","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBudWxsfEV4ZWN1dGlvbk9yZGVyU3RyYXRlZ3k8XEZsb3dcUG9zdGdyZVNxbFxTY2hlbWFcVGFibGU+ICR0YWJsZU9yZGVyU3RyYXRlZ3kKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":2006,"slug":"ast-view-dependency-resolver","name":"ast_view_dependency_resolver","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"AstViewDependencyResolver","namespace":"Flow\\PostgreSql\\Schema\\Diff","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":2012,"slug":"noop-view-dependency-resolver","name":"noop_view_dependency_resolver","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"NoopViewDependencyResolver","namespace":"Flow\\PostgreSql\\Schema\\Diff","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":2018,"slug":"foreign-key-dependency-order","name":"foreign_key_dependency_order","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ForeignKeyDependencyOrder","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":2027,"slug":"no-execution-order","name":"no_execution_order","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"NoExecutionOrder","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gTm9FeGVjdXRpb25PcmRlcjxtaXhlZD4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":2033,"slug":"view-dependency-order","name":"view_dependency_order","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ViewDependencyOrder","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":2039,"slug":"materialized-view-dependency-order","name":"materialized_view_dependency_order","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"MaterializedViewDependencyOrder","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":116,"slug":"select","name":"select","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expressions","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"SelectBuilder","namespace":"Flow\\PostgreSql\\QueryBuilder\\Select","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIG5ldyBTRUxFQ1QgcXVlcnkgYnVpbGRlci4KICoKICogQHBhcmFtIEV4cHJlc3Npb258c3RyaW5nIC4uLiRleHByZXNzaW9ucyBDb2x1bW5zIHRvIHNlbGVjdC4gSWYgZW1wdHksIHJldHVybnMgU2VsZWN0U2VsZWN0U3RlcC4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":133,"slug":"parsed-select","name":"parsed_select","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"sql","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":"ParsedSelect","namespace":"Flow\\PostgreSql\\QueryBuilder\\Select","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFNlbGVjdEZpbmFsU3RlcCBmcm9tIGEgcmF3IFNRTCBTRUxFQ1Qgc3RyaW5nLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":145,"slug":"with","name":"with","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"ctes","type":[{"name":"CTE","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"WithBuilder","namespace":"Flow\\PostgreSql\\QueryBuilder\\With","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFdJVEggY2xhdXNlIGJ1aWxkZXIgZm9yIENURXMuCiAqCiAqIEV4YW1wbGU6IHdpdGgoY3RlKCd1c2VycycsICRzdWJxdWVyeSkpLT5zZWxlY3Qoc3RhcigpKS0+ZnJvbSh0YWJsZSgndXNlcnMnKSkKICogRXhhbXBsZTogd2l0aChjdGUoJ2EnLCAkcTEpLCBjdGUoJ2InLCAkcTIpKS0+cmVjdXJzaXZlKCktPnNlbGVjdCguLi4pLT5mcm9tKHRhYmxlKCdhJykpCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":158,"slug":"insert","name":"insert","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"InsertIntoStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Insert","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIG5ldyBJTlNFUlQgcXVlcnkgYnVpbGRlci4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":174,"slug":"bulk-insert","name":"bulk_insert","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"table","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":"columns","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":"rowCount","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":"BulkInsert","namespace":"Flow\\PostgreSql\\QueryBuilder\\Insert","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBvcHRpbWl6ZWQgYnVsayBJTlNFUlQgcXVlcnkgZm9yIGhpZ2gtcGVyZm9ybWFuY2UgbXVsdGktcm93IGluc2VydHMuCiAqCiAqIFVubGlrZSBpbnNlcnQoKSB3aGljaCB1c2VzIGltbXV0YWJsZSBidWlsZGVyIHBhdHRlcm5zIChPKG7CsikgZm9yIG4gcm93cyksCiAqIHRoaXMgZnVuY3Rpb24gZ2VuZXJhdGVzIFNRTCBkaXJlY3RseSB1c2luZyBzdHJpbmcgb3BlcmF0aW9ucyAoTyhuKSBjb21wbGV4aXR5KS4KICoKICogQHBhcmFtIHN0cmluZyAkdGFibGUgVGFibGUgbmFtZQogKiBAcGFyYW0gbGlzdDxzdHJpbmc+ICRjb2x1bW5zIENvbHVtbiBuYW1lcwogKiBAcGFyYW0gaW50ICRyb3dDb3VudCBOdW1iZXIgb2Ygcm93cyB0byBpbnNlcnQKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":183,"slug":"update","name":"update","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"UpdateTableStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Update","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIG5ldyBVUERBVEUgcXVlcnkgYnVpbGRlci4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":192,"slug":"delete","name":"delete","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"DeleteFromStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Delete","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIG5ldyBERUxFVEUgcXVlcnkgYnVpbGRlci4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":204,"slug":"merge","name":"merge","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"table","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":"alias","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"MergeUsingStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Merge","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIG5ldyBNRVJHRSBxdWVyeSBidWlsZGVyLgogKgogKiBAcGFyYW0gc3RyaW5nICR0YWJsZSBUYXJnZXQgdGFibGUgbmFtZQogKiBAcGFyYW0gbnVsbHxzdHJpbmcgJGFsaWFzIE9wdGlvbmFsIHRhYmxlIGFsaWFzCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":218,"slug":"copy","name":"copy","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"CopyFactory","namespace":"Flow\\PostgreSql\\QueryBuilder\\Factory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIG5ldyBDT1BZIHF1ZXJ5IGJ1aWxkZXIgZm9yIGRhdGEgaW1wb3J0L2V4cG9ydC4KICoKICogVXNhZ2U6CiAqICAgY29weSgpLT5mcm9tKCd1c2VycycpLT5maWxlKCcvdG1wL3VzZXJzLmNzdicpLT5mb3JtYXQoQ29weUZvcm1hdDo6Q1NWKQogKiAgIGNvcHkoKS0+dG8oJ3VzZXJzJyktPmZpbGUoJy90bXAvdXNlcnMuY3N2JyktPmZvcm1hdChDb3B5Rm9ybWF0OjpDU1YpCiAqICAgY29weSgpLT50b1F1ZXJ5KHNlbGVjdCguLi4pKS0+ZmlsZSgnL3RtcC9kYXRhLmNzdicpCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":230,"slug":"listen","name":"listen","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"channel","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":"ListenFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Listen","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIExJU1RFTiBzdGF0ZW1lbnQgdG8gc3Vic2NyaWJlIHRoZSBjdXJyZW50IHNlc3Npb24gdG8gYSBub3RpZmljYXRpb24gY2hhbm5lbC4KICoKICogVXNhZ2U6CiAqICAgbGlzdGVuKCdteV9jaGFubmVsJyktPnRvU3FsKCkgIC8vIExJU1RFTiBteV9jaGFubmVsCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":242,"slug":"unlisten","name":"unlisten","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"channel","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":"UnlistenFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Unlisten","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBVTkxJU1RFTiBzdGF0ZW1lbnQgdG8gdW5zdWJzY3JpYmUgdGhlIGN1cnJlbnQgc2Vzc2lvbiBmcm9tIGEgbm90aWZpY2F0aW9uIGNoYW5uZWwuCiAqCiAqIFVzYWdlOgogKiAgIHVubGlzdGVuKCdteV9jaGFubmVsJyktPnRvU3FsKCkgIC8vIFVOTElTVEVOIG15X2NoYW5uZWwKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":255,"slug":"notify","name":"notify","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"channel","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":"NotifyFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Notify","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIE5PVElGWSBzdGF0ZW1lbnQgdG8gc2VuZCBhIG5vdGlmaWNhdGlvbiBvbiBhIGNoYW5uZWwsIG9wdGlvbmFsbHkgd2l0aCBhIHBheWxvYWQuCiAqCiAqIFVzYWdlOgogKiAgIG5vdGlmeSgnbXlfY2hhbm5lbCcpLT50b1NxbCgpICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTk9USUZZIG15X2NoYW5uZWwKICogICBub3RpZnkoJ215X2NoYW5uZWwnKS0+d2l0aFBheWxvYWQoJ2hlbGxvJyktPnRvU3FsKCkgICAgIC8vIE5PVElGWSBteV9jaGFubmVsLCAnaGVsbG8nCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":276,"slug":"col","name":"col","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"column","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":"table","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":"schema","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Column","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGNvbHVtbiByZWZlcmVuY2UgZXhwcmVzc2lvbi4KICoKICogQ2FuIGJlIHVzZWQgaW4gdHdvIG1vZGVzOgogKiAtIFBhcnNlIG1vZGU6IGNvbCgndXNlcnMuaWQnKSBvciBjb2woJ3NjaGVtYS50YWJsZS5jb2x1bW4nKSAtIHBhcnNlcyBkb3Qtc2VwYXJhdGVkIHN0cmluZwogKiAtIEV4cGxpY2l0IG1vZGU6IGNvbCgnaWQnLCAndXNlcnMnKSBvciBjb2woJ2lkJywgJ3VzZXJzJywgJ3NjaGVtYScpIC0gc2VwYXJhdGUgYXJndW1lbnRzCiAqCiAqIFdoZW4gJHRhYmxlIG9yICRzY2hlbWEgaXMgcHJvdmlkZWQsICRjb2x1bW4gbXVzdCBiZSBhIHBsYWluIGNvbHVtbiBuYW1lIChubyBkb3RzKS4KICoKICogQHBhcmFtIHN0cmluZyAkY29sdW1uIENvbHVtbiBuYW1lLCBvciBkb3Qtc2VwYXJhdGVkIHBhdGggbGlrZSAidGFibGUuY29sdW1uIiBvciAic2NoZW1hLnRhYmxlLmNvbHVtbiIKICogQHBhcmFtIG51bGx8c3RyaW5nICR0YWJsZSBUYWJsZSBuYW1lIChvcHRpb25hbCwgdHJpZ2dlcnMgZXhwbGljaXQgbW9kZSkKICogQHBhcmFtIG51bGx8c3RyaW5nICRzY2hlbWEgU2NoZW1hIG5hbWUgKG9wdGlvbmFsLCByZXF1aXJlcyAkdGFibGUpCiAqCiAqIEB0aHJvd3MgSW52YWxpZEV4cHJlc3Npb25FeGNlcHRpb24gd2hlbiAkc2NoZW1hIGlzIHByb3ZpZGVkIHdpdGhvdXQgJHRhYmxlLCBvciB3aGVuICRjb2x1bW4gY29udGFpbnMgZG90cyBpbiBleHBsaWNpdCBtb2RlCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":303,"slug":"star","name":"star","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"table","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Star","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFNFTEVDVCAqIGV4cHJlc3Npb24uCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":319,"slug":"literal","name":"literal","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"value","type":[{"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":"bool","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":false,"default_value":null}],"return_type":[{"name":"Literal","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGxpdGVyYWwgdmFsdWUgZm9yIHVzZSBpbiBxdWVyaWVzLgogKgogKiBBdXRvbWF0aWNhbGx5IGRldGVjdHMgdGhlIHR5cGUgYW5kIGNyZWF0ZXMgdGhlIGFwcHJvcHJpYXRlIGxpdGVyYWw6CiAqIC0gbGl0ZXJhbCgnaGVsbG8nKSBjcmVhdGVzIGEgc3RyaW5nIGxpdGVyYWwKICogLSBsaXRlcmFsKDQyKSBjcmVhdGVzIGFuIGludGVnZXIgbGl0ZXJhbAogKiAtIGxpdGVyYWwoMy4xNCkgY3JlYXRlcyBhIGZsb2F0IGxpdGVyYWwKICogLSBsaXRlcmFsKHRydWUpIGNyZWF0ZXMgYSBib29sZWFuIGxpdGVyYWwKICogLSBsaXRlcmFsKG51bGwpIGNyZWF0ZXMgYSBOVUxMIGxpdGVyYWwKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":334,"slug":"param","name":"param","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"position","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":"Parameter","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHBvc2l0aW9uYWwgcGFyYW1ldGVyICgkMSwgJDIsIGV0Yy4pLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":343,"slug":"parameters","name":"parameters","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"count","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":"startAt","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":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gbGlzdDxQYXJhbWV0ZXI+CiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":369,"slug":"func","name":"func","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"args","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"FunctionCall","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGZ1bmN0aW9uIGNhbGwgZXhwcmVzc2lvbi4KICoKICogQHBhcmFtIHN0cmluZyAkbmFtZSBGdW5jdGlvbiBuYW1lIChjYW4gaW5jbHVkZSBzY2hlbWEgbGlrZSAicGdfY2F0YWxvZy5ub3ciKQogKiBAcGFyYW0gbGlzdDxFeHByZXNzaW9ufHN0cmluZz4gJGFyZ3MgRnVuY3Rpb24gYXJndW1lbnRzCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":403,"slug":"agg","name":"agg","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"args","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"distinct","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":"AggregateCall","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBhZ2dyZWdhdGUgZnVuY3Rpb24gY2FsbCAoQ09VTlQsIFNVTSwgQVZHLCBldGMuKS4KICoKICogQHBhcmFtIHN0cmluZyAkbmFtZSBBZ2dyZWdhdGUgZnVuY3Rpb24gbmFtZQogKiBAcGFyYW0gbGlzdDxFeHByZXNzaW9ufHN0cmluZz4gJGFyZ3MgRnVuY3Rpb24gYXJndW1lbnRzCiAqIEBwYXJhbSBib29sICRkaXN0aW5jdCBVc2UgRElTVElOQ1QgbW9kaWZpZXIKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":417,"slug":"agg-count","name":"agg_count","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"distinct","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":"AggregateCall","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBDT1VOVCgqKSBhZ2dyZWdhdGUuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":430,"slug":"count-all","name":"count_all","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"AggregateCall","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBDT1VOVCgqKSBhZ2dyZWdhdGUuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":439,"slug":"agg-sum","name":"agg_sum","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"distinct","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":"AggregateCall","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBTVU0gYWdncmVnYXRlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":448,"slug":"agg-avg","name":"agg_avg","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"distinct","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":"AggregateCall","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBBVkcgYWdncmVnYXRlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":457,"slug":"agg-min","name":"agg_min","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"AggregateCall","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBNSU4gYWdncmVnYXRlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":466,"slug":"agg-max","name":"agg_max","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"AggregateCall","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBNQVggYWdncmVnYXRlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":477,"slug":"coalesce","name":"coalesce","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expressions","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"Coalesce","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENPQUxFU0NFIGV4cHJlc3Npb24uCiAqCiAqIEBwYXJhbSBFeHByZXNzaW9ufHN0cmluZyAuLi4kZXhwcmVzc2lvbnMgRXhwcmVzc2lvbnMgdG8gY29hbGVzY2UKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":488,"slug":"nullif","name":"nullif","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr1","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"expr2","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"NullIf","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIE5VTExJRiBleHByZXNzaW9uLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":502,"slug":"greatest","name":"greatest","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expressions","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"Greatest","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEdSRUFURVNUIGV4cHJlc3Npb24uCiAqCiAqIEBwYXJhbSBFeHByZXNzaW9ufHN0cmluZyAuLi4kZXhwcmVzc2lvbnMgRXhwcmVzc2lvbnMgdG8gY29tcGFyZQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":515,"slug":"least","name":"least","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expressions","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"Least","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIExFQVNUIGV4cHJlc3Npb24uCiAqCiAqIEBwYXJhbSBFeHByZXNzaW9ufHN0cmluZyAuLi4kZXhwcmVzc2lvbnMgRXhwcmVzc2lvbnMgdG8gY29tcGFyZQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":529,"slug":"cast","name":"cast","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"dataType","type":[{"name":"ColumnType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"TypeCast","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHR5cGUgY2FzdCBleHByZXNzaW9uLgogKgogKiBAcGFyYW0gRXhwcmVzc2lvbnxzdHJpbmcgJGV4cHIgRXhwcmVzc2lvbiB0byBjYXN0CiAqIEBwYXJhbSBDb2x1bW5UeXBlICRkYXRhVHlwZSBUYXJnZXQgZGF0YSB0eXBlICh1c2UgY29sdW1uX3R5cGVfKiBmdW5jdGlvbnMpCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":544,"slug":"current-timestamp","name":"current_timestamp","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"SQLValueFunctionExpression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFNRTCBzdGFuZGFyZCBDVVJSRU5UX1RJTUVTVEFNUCBmdW5jdGlvbi4KICoKICogUmV0dXJucyB0aGUgY3VycmVudCBkYXRlIGFuZCB0aW1lIChhdCB0aGUgc3RhcnQgb2YgdGhlIHRyYW5zYWN0aW9uKS4KICogVXNlZnVsIGFzIGEgY29sdW1uIGRlZmF1bHQgdmFsdWUgb3IgaW4gU0VMRUNUIHF1ZXJpZXMuCiAqCiAqIEV4YW1wbGU6IGNvbHVtbignY3JlYXRlZF9hdCcsIGNvbHVtbl90eXBlX3RpbWVzdGFtcCgpKS0+ZGVmYXVsdChjdXJyZW50X3RpbWVzdGFtcCgpKQogKiBFeGFtcGxlOiBzZWxlY3QoKS0+c2VsZWN0KGN1cnJlbnRfdGltZXN0YW1wKCktPmFzKCdub3cnKSkKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":559,"slug":"current-date","name":"current_date","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"SQLValueFunctionExpression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFNRTCBzdGFuZGFyZCBDVVJSRU5UX0RBVEUgZnVuY3Rpb24uCiAqCiAqIFJldHVybnMgdGhlIGN1cnJlbnQgZGF0ZSAoYXQgdGhlIHN0YXJ0IG9mIHRoZSB0cmFuc2FjdGlvbikuCiAqIFVzZWZ1bCBhcyBhIGNvbHVtbiBkZWZhdWx0IHZhbHVlIG9yIGluIFNFTEVDVCBxdWVyaWVzLgogKgogKiBFeGFtcGxlOiBjb2x1bW4oJ2JpcnRoX2RhdGUnLCBjb2x1bW5fdHlwZV9kYXRlKCkpLT5kZWZhdWx0KGN1cnJlbnRfZGF0ZSgpKQogKiBFeGFtcGxlOiBzZWxlY3QoKS0+c2VsZWN0KGN1cnJlbnRfZGF0ZSgpLT5hcygndG9kYXknKSkKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":574,"slug":"current-time","name":"current_time","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"SQLValueFunctionExpression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFNRTCBzdGFuZGFyZCBDVVJSRU5UX1RJTUUgZnVuY3Rpb24uCiAqCiAqIFJldHVybnMgdGhlIGN1cnJlbnQgdGltZSAoYXQgdGhlIHN0YXJ0IG9mIHRoZSB0cmFuc2FjdGlvbikuCiAqIFVzZWZ1bCBhcyBhIGNvbHVtbiBkZWZhdWx0IHZhbHVlIG9yIGluIFNFTEVDVCBxdWVyaWVzLgogKgogKiBFeGFtcGxlOiBjb2x1bW4oJ3N0YXJ0X3RpbWUnLCBjb2x1bW5fdHlwZV90aW1lKCkpLT5kZWZhdWx0KGN1cnJlbnRfdGltZSgpKQogKiBFeGFtcGxlOiBzZWxlY3QoKS0+c2VsZWN0KGN1cnJlbnRfdGltZSgpLT5hcygnbm93X3RpbWUnKSkKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":587,"slug":"case-when","name":"case_when","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"whenClauses","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":"elseResult","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"operand","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"CaseExpression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENBU0UgZXhwcmVzc2lvbi4KICoKICogQHBhcmFtIG5vbi1lbXB0eS1saXN0PFdoZW5DbGF1c2U+ICR3aGVuQ2xhdXNlcyBXSEVOIGNsYXVzZXMKICogQHBhcmFtIG51bGx8RXhwcmVzc2lvbnxzdHJpbmcgJGVsc2VSZXN1bHQgRUxTRSByZXN1bHQgKG9wdGlvbmFsKQogKiBAcGFyYW0gbnVsbHxFeHByZXNzaW9ufHN0cmluZyAkb3BlcmFuZCBDQVNFIG9wZXJhbmQgZm9yIHNpbXBsZSBDQVNFIChvcHRpb25hbCkKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":603,"slug":"when","name":"when","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"condition","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"result","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"WhenClause","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFdIRU4gY2xhdXNlIGZvciBDQVNFIGV4cHJlc3Npb24uCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":615,"slug":"sub-select","name":"sub_select","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"query","type":[{"name":"SelectFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Select","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Subquery","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHN1YnF1ZXJ5IGV4cHJlc3Npb24uCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":629,"slug":"array-expr","name":"array_expr","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"elements","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":"ArrayExpression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBhcnJheSBleHByZXNzaW9uLgogKgogKiBAcGFyYW0gbGlzdDxFeHByZXNzaW9ufHN0cmluZz4gJGVsZW1lbnRzIEFycmF5IGVsZW1lbnRzCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":642,"slug":"row-expr","name":"row_expr","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"elements","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":"RowExpression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHJvdyBleHByZXNzaW9uLgogKgogKiBAcGFyYW0gbGlzdDxFeHByZXNzaW9ufHN0cmluZz4gJGVsZW1lbnRzIFJvdyBlbGVtZW50cwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":653,"slug":"binary-expr","name":"binary_expr","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"left","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"operator","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":"right","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"BinaryExpression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGJpbmFyeSBleHByZXNzaW9uIChsZWZ0IG9wIHJpZ2h0KS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":671,"slug":"window-func","name":"window_func","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"args","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"partitionBy","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"orderBy","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"WindowFunction","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHdpbmRvdyBmdW5jdGlvbi4KICoKICogQHBhcmFtIHN0cmluZyAkbmFtZSBGdW5jdGlvbiBuYW1lCiAqIEBwYXJhbSBsaXN0PEV4cHJlc3Npb258c3RyaW5nPiAkYXJncyBGdW5jdGlvbiBhcmd1bWVudHMKICogQHBhcmFtIGxpc3Q8RXhwcmVzc2lvbnxzdHJpbmc+ICRwYXJ0aXRpb25CeSBQQVJUSVRJT04gQlkgZXhwcmVzc2lvbnMKICogQHBhcmFtIGxpc3Q8T3JkZXJCeT4gJG9yZGVyQnkgT1JERVIgQlkgaXRlbXMKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":692,"slug":"concat","name":"concat","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expressions","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"BinaryExpression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENvbmNhdGVuYXRlIGV4cHJlc3Npb25zIHdpdGggdGhlIHx8IG9wZXJhdG9yLgogKgogKiBFeGFtcGxlOiBjb25jYXQoY29sKCdzY2hlbWEnKSwgbGl0ZXJhbCgnLicpLCBjb2woJ3RhYmxlJykpCiAqIFByb2R1Y2VzOiBzY2hlbWEgfHwgJy4nIHx8IHRhYmxlCiAqCiAqIEBwYXJhbSBFeHByZXNzaW9ufHN0cmluZyAuLi4kZXhwcmVzc2lvbnMgQXQgbGVhc3QgMiBleHByZXNzaW9ucyB0byBjb25jYXRlbmF0ZQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":722,"slug":"table","name":"table","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"schema","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Table","namespace":"Flow\\PostgreSql\\QueryBuilder\\Table","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHRhYmxlIHJlZmVyZW5jZS4KICoKICogU3VwcG9ydHMgZG90IG5vdGF0aW9uIGZvciBzY2hlbWEtcXVhbGlmaWVkIG5hbWVzOiAicHVibGljLnVzZXJzIiBvciBleHBsaWNpdCBzY2hlbWEgcGFyYW1ldGVyLgogKiBEb3VibGUtcXVvdGVkIGlkZW50aWZpZXJzIHByZXNlcnZlIGRvdHM6ICcibXkudGFibGUiJyBjcmVhdGVzIGEgc2luZ2xlIGlkZW50aWZpZXIuCiAqCiAqIEBwYXJhbSBzdHJpbmcgJG5hbWUgVGFibGUgbmFtZSAobWF5IGluY2x1ZGUgc2NoZW1hIGFzICJzY2hlbWEudGFibGUiKQogKiBAcGFyYW0gbnVsbHxzdHJpbmcgJHNjaGVtYSBTY2hlbWEgbmFtZSAob3B0aW9uYWwsIG92ZXJyaWRlcyBwYXJzZWQgc2NoZW1hKQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":737,"slug":"derived","name":"derived","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"query","type":[{"name":"SelectFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Select","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"alias","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":"DerivedTable","namespace":"Flow\\PostgreSql\\QueryBuilder\\Table","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGRlcml2ZWQgdGFibGUgKHN1YnF1ZXJ5IGluIEZST00gY2xhdXNlKS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":751,"slug":"lateral","name":"lateral","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"reference","type":[{"name":"TableReference","namespace":"Flow\\PostgreSql\\QueryBuilder\\Table","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Lateral","namespace":"Flow\\PostgreSql\\QueryBuilder\\Table","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIExBVEVSQUwgc3VicXVlcnkuCiAqCiAqIEBwYXJhbSBUYWJsZVJlZmVyZW5jZSAkcmVmZXJlbmNlIFRoZSBzdWJxdWVyeSBvciB0YWJsZSBmdW5jdGlvbiByZWZlcmVuY2UKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":763,"slug":"table-func","name":"table_func","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"function","type":[{"name":"FunctionCall","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"withOrdinality","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":"TableFunction","namespace":"Flow\\PostgreSql\\QueryBuilder\\Table","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHRhYmxlIGZ1bmN0aW9uIHJlZmVyZW5jZS4KICoKICogQHBhcmFtIEZ1bmN0aW9uQ2FsbCAkZnVuY3Rpb24gVGhlIHRhYmxlLXZhbHVlZCBmdW5jdGlvbgogKiBAcGFyYW0gYm9vbCAkd2l0aE9yZGluYWxpdHkgV2hldGhlciB0byBhZGQgV0lUSCBPUkRJTkFMSVRZCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":782,"slug":"values-table","name":"values_table","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"rows","type":[{"name":"RowExpression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"ValuesTable","namespace":"Flow\\PostgreSql\\QueryBuilder\\Table","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFZBTFVFUyBjbGF1c2UgYXMgYSB0YWJsZSByZWZlcmVuY2UuCiAqCiAqIFVzYWdlOgogKiAgIHNlbGVjdCgpLT5mcm9tKAogKiAgICAgICB2YWx1ZXNfdGFibGUoCiAqICAgICAgICAgICByb3dfZXhwcihbbGl0ZXJhbCgxKSwgbGl0ZXJhbCgnQWxpY2UnKV0pLAogKiAgICAgICAgICAgcm93X2V4cHIoW2xpdGVyYWwoMiksIGxpdGVyYWwoJ0JvYicpXSkKICogICAgICAgKS0+YXMoJ3QnLCBbJ2lkJywgJ25hbWUnXSkKICogICApCiAqCiAqIEdlbmVyYXRlczogU0VMRUNUICogRlJPTSAoVkFMVUVTICgxLCAnQWxpY2UnKSwgKDIsICdCb2InKSkgQVMgdChpZCwgbmFtZSkKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":791,"slug":"order-by","name":"order_by","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"direction","type":[{"name":"SortDirection","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\PostgreSql\\QueryBuilder\\Clause\\SortDirection::..."},{"name":"nulls","type":[{"name":"NullsPosition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\PostgreSql\\QueryBuilder\\Clause\\NullsPosition::..."}],"return_type":[{"name":"OrderBy","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBPUkRFUiBCWSBpdGVtLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":803,"slug":"asc","name":"asc","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"nulls","type":[{"name":"NullsPosition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\PostgreSql\\QueryBuilder\\Clause\\NullsPosition::..."}],"return_type":[{"name":"OrderBy","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBPUkRFUiBCWSBpdGVtIHdpdGggQVNDIGRpcmVjdGlvbi4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":812,"slug":"desc","name":"desc","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"nulls","type":[{"name":"NullsPosition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\PostgreSql\\QueryBuilder\\Clause\\NullsPosition::..."}],"return_type":[{"name":"OrderBy","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBPUkRFUiBCWSBpdGVtIHdpdGggREVTQyBkaXJlY3Rpb24uCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":826,"slug":"cte","name":"cte","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"query","type":[{"name":"SelectFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Select","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"columnNames","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"materialization","type":[{"name":"CTEMaterialization","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\PostgreSql\\QueryBuilder\\Clause\\CTEMaterialization::..."},{"name":"recursive","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":"CTE","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENURSAoQ29tbW9uIFRhYmxlIEV4cHJlc3Npb24pLgogKgogKiBAcGFyYW0gc3RyaW5nICRuYW1lIENURSBuYW1lCiAqIEBwYXJhbSBTZWxlY3RGaW5hbFN0ZXAgJHF1ZXJ5IENURSBxdWVyeQogKiBAcGFyYW0gYXJyYXk8c3RyaW5nPiAkY29sdW1uTmFtZXMgQ29sdW1uIGFsaWFzZXMgKG9wdGlvbmFsKQogKiBAcGFyYW0gQ1RFTWF0ZXJpYWxpemF0aW9uICRtYXRlcmlhbGl6YXRpb24gTWF0ZXJpYWxpemF0aW9uIGhpbnQKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":848,"slug":"window-def","name":"window_def","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"partitionBy","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"orderBy","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"frame","type":[{"name":"WindowFrame","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"WindowDefinition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHdpbmRvdyBkZWZpbml0aW9uIGZvciBXSU5ET1cgY2xhdXNlLgogKgogKiBAcGFyYW0gc3RyaW5nICRuYW1lIFdpbmRvdyBuYW1lCiAqIEBwYXJhbSBsaXN0PEV4cHJlc3Npb258c3RyaW5nPiAkcGFydGl0aW9uQnkgUEFSVElUSU9OIEJZIGV4cHJlc3Npb25zCiAqIEBwYXJhbSBsaXN0PE9yZGVyQnk+ICRvcmRlckJ5IE9SREVSIEJZIGl0ZW1zCiAqIEBwYXJhbSBudWxsfFdpbmRvd0ZyYW1lICRmcmFtZSBXaW5kb3cgZnJhbWUgc3BlY2lmaWNhdGlvbgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":868,"slug":"window-frame","name":"window_frame","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"mode","type":[{"name":"FrameMode","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"start","type":[{"name":"FrameBound","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"end","type":[{"name":"FrameBound","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"exclusion","type":[{"name":"FrameExclusion","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\PostgreSql\\QueryBuilder\\Clause\\FrameExclusion::..."}],"return_type":[{"name":"WindowFrame","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHdpbmRvdyBmcmFtZSBzcGVjaWZpY2F0aW9uLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":881,"slug":"frame-current-row","name":"frame_current_row","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"FrameBound","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGZyYW1lIGJvdW5kIGZvciBDVVJSRU5UIFJPVy4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":890,"slug":"frame-unbounded-preceding","name":"frame_unbounded_preceding","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"FrameBound","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGZyYW1lIGJvdW5kIGZvciBVTkJPVU5ERUQgUFJFQ0VESU5HLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":899,"slug":"frame-unbounded-following","name":"frame_unbounded_following","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"FrameBound","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGZyYW1lIGJvdW5kIGZvciBVTkJPVU5ERUQgRk9MTE9XSU5HLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":908,"slug":"frame-preceding","name":"frame_preceding","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"offset","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"FrameBound","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGZyYW1lIGJvdW5kIGZvciBOIFBSRUNFRElORy4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":917,"slug":"frame-following","name":"frame_following","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"offset","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"FrameBound","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGZyYW1lIGJvdW5kIGZvciBOIEZPTExPV0lORy4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":930,"slug":"lock-for","name":"lock_for","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"strength","type":[{"name":"LockStrength","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"tables","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"waitPolicy","type":[{"name":"LockWaitPolicy","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\PostgreSql\\QueryBuilder\\Clause\\LockWaitPolicy::..."}],"return_type":[{"name":"LockingClause","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGxvY2tpbmcgY2xhdXNlIChGT1IgVVBEQVRFLCBGT1IgU0hBUkUsIGV0Yy4pLgogKgogKiBAcGFyYW0gTG9ja1N0cmVuZ3RoICRzdHJlbmd0aCBMb2NrIHN0cmVuZ3RoCiAqIEBwYXJhbSBsaXN0PHN0cmluZz4gJHRhYmxlcyBUYWJsZXMgdG8gbG9jayAoZW1wdHkgZm9yIGFsbCkKICogQHBhcmFtIExvY2tXYWl0UG9saWN5ICR3YWl0UG9saWN5IFdhaXQgcG9saWN5CiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":944,"slug":"for-update","name":"for_update","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"tables","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"LockingClause","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEZPUiBVUERBVEUgbG9ja2luZyBjbGF1c2UuCiAqCiAqIEBwYXJhbSBsaXN0PHN0cmluZz4gJHRhYmxlcyBUYWJsZXMgdG8gbG9jayAoZW1wdHkgZm9yIGFsbCkKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":955,"slug":"for-share","name":"for_share","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"tables","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"LockingClause","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEZPUiBTSEFSRSBsb2NraW5nIGNsYXVzZS4KICoKICogQHBhcmFtIGxpc3Q8c3RyaW5nPiAkdGFibGVzIFRhYmxlcyB0byBsb2NrIChlbXB0eSBmb3IgYWxsKQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":964,"slug":"on-conflict-nothing","name":"on_conflict_nothing","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"target","type":[{"name":"ConflictTarget","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"OnConflictClause","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBPTiBDT05GTElDVCBETyBOT1RISU5HIGNsYXVzZS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":976,"slug":"on-conflict-update","name":"on_conflict_update","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"target","type":[{"name":"ConflictTarget","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"updates","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":"OnConflictClause","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBPTiBDT05GTElDVCBETyBVUERBVEUgY2xhdXNlLgogKgogKiBAcGFyYW0gQ29uZmxpY3RUYXJnZXQgJHRhcmdldCBDb25mbGljdCB0YXJnZXQgKGNvbHVtbnMgb3IgY29uc3RyYWludCkKICogQHBhcmFtIGFycmF5PHN0cmluZywgRXhwcmVzc2lvbnxzdHJpbmc+ICR1cGRhdGVzIENvbHVtbiB1cGRhdGVzCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":990,"slug":"conflict-columns","name":"conflict_columns","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"columns","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":"ConflictTarget","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGNvbmZsaWN0IHRhcmdldCBmb3IgT04gQ09ORkxJQ1QgKGNvbHVtbnMpLgogKgogKiBAcGFyYW0gbGlzdDxzdHJpbmc+ICRjb2x1bW5zIENvbHVtbnMgdGhhdCBkZWZpbmUgdW5pcXVlbmVzcwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":999,"slug":"conflict-constraint","name":"conflict_constraint","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"ConflictTarget","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGNvbmZsaWN0IHRhcmdldCBmb3IgT04gQ09ORkxJQ1QgT04gQ09OU1RSQUlOVC4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":1010,"slug":"returning","name":"returning","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expressions","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"ReturningClause","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFJFVFVSTklORyBjbGF1c2UuCiAqCiAqIEBwYXJhbSBFeHByZXNzaW9ufHN0cmluZyAuLi4kZXhwcmVzc2lvbnMgRXhwcmVzc2lvbnMgdG8gcmV0dXJuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":1021,"slug":"returning-all","name":"returning_all","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ReturningClause","namespace":"Flow\\PostgreSql\\QueryBuilder\\Clause","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFJFVFVSTklORyAqIGNsYXVzZS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":1033,"slug":"begin","name":"begin","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"BeginOptionsStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Transaction","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEJFR0lOIHRyYW5zYWN0aW9uIGJ1aWxkZXIuCiAqCiAqIEV4YW1wbGU6IGJlZ2luKCktPmlzb2xhdGlvbkxldmVsKElzb2xhdGlvbkxldmVsOjpTRVJJQUxJWkFCTEUpLT5yZWFkT25seSgpCiAqIFByb2R1Y2VzOiBCRUdJTiBJU09MQVRJT04gTEVWRUwgU0VSSUFMSVpBQkxFIFJFQUQgT05MWQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":1045,"slug":"commit","name":"commit","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"CommitOptionsStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Transaction","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENPTU1JVCB0cmFuc2FjdGlvbiBidWlsZGVyLgogKgogKiBFeGFtcGxlOiBjb21taXQoKS0+YW5kQ2hhaW4oKQogKiBQcm9kdWNlczogQ09NTUlUIEFORCBDSEFJTgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":1057,"slug":"rollback","name":"rollback","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"RollbackOptionsStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Transaction","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFJPTExCQUNLIHRyYW5zYWN0aW9uIGJ1aWxkZXIuCiAqCiAqIEV4YW1wbGU6IHJvbGxiYWNrKCktPnRvU2F2ZXBvaW50KCdteV9zYXZlcG9pbnQnKQogKiBQcm9kdWNlczogUk9MTEJBQ0sgVE8gU0FWRVBPSU5UIG15X3NhdmVwb2ludAogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":1069,"slug":"savepoint","name":"savepoint","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"SavepointFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Transaction","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFNBVkVQT0lOVC4KICoKICogRXhhbXBsZTogc2F2ZXBvaW50KCdteV9zYXZlcG9pbnQnKQogKiBQcm9kdWNlczogU0FWRVBPSU5UIG15X3NhdmVwb2ludAogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":1081,"slug":"release-savepoint","name":"release_savepoint","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"name","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":"SavepointFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Transaction","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFJlbGVhc2UgYSBTQVZFUE9JTlQuCiAqCiAqIEV4YW1wbGU6IHJlbGVhc2Vfc2F2ZXBvaW50KCdteV9zYXZlcG9pbnQnKQogKiBQcm9kdWNlczogUkVMRUFTRSBteV9zYXZlcG9pbnQKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":1093,"slug":"set-transaction","name":"set_transaction","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"SetTransactionOptionsStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Transaction","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFNFVCBUUkFOU0FDVElPTiBidWlsZGVyLgogKgogKiBFeGFtcGxlOiBzZXRfdHJhbnNhY3Rpb24oKS0+aXNvbGF0aW9uTGV2ZWwoSXNvbGF0aW9uTGV2ZWw6OlNFUklBTElaQUJMRSktPnJlYWRPbmx5KCkKICogUHJvZHVjZXM6IFNFVCBUUkFOU0FDVElPTiBJU09MQVRJT04gTEVWRUwgU0VSSUFMSVpBQkxFLCBSRUFEIE9OTFkKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":1105,"slug":"set-session-transaction","name":"set_session_transaction","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"SetTransactionOptionsStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Transaction","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFNFVCBTRVNTSU9OIENIQVJBQ1RFUklTVElDUyBBUyBUUkFOU0FDVElPTiBidWlsZGVyLgogKgogKiBFeGFtcGxlOiBzZXRfc2Vzc2lvbl90cmFuc2FjdGlvbigpLT5pc29sYXRpb25MZXZlbChJc29sYXRpb25MZXZlbDo6U0VSSUFMSVpBQkxFKQogKiBQcm9kdWNlczogU0VUIFNFU1NJT04gQ0hBUkFDVEVSSVNUSUNTIEFTIFRSQU5TQUNUSU9OIElTT0xBVElPTiBMRVZFTCBTRVJJQUxJWkFCTEUKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":1117,"slug":"transaction-snapshot","name":"transaction_snapshot","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"snapshotId","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":"SetTransactionFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Transaction","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFNFVCBUUkFOU0FDVElPTiBTTkFQU0hPVCBidWlsZGVyLgogKgogKiBFeGFtcGxlOiB0cmFuc2FjdGlvbl9zbmFwc2hvdCgnMDAwMDAwMDMtMDAwMDAwMUEtMScpCiAqIFByb2R1Y2VzOiBTRVQgVFJBTlNBQ1RJT04gU05BUFNIT1QgJzAwMDAwMDAzLTAwMDAwMDFBLTEnCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":1129,"slug":"prepare-transaction","name":"prepare_transaction","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"transactionId","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":"PreparedTransactionFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Transaction","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBSRVBBUkUgVFJBTlNBQ1RJT04gYnVpbGRlci4KICoKICogRXhhbXBsZTogcHJlcGFyZV90cmFuc2FjdGlvbignbXlfdHJhbnNhY3Rpb24nKQogKiBQcm9kdWNlczogUFJFUEFSRSBUUkFOU0FDVElPTiAnbXlfdHJhbnNhY3Rpb24nCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":1141,"slug":"commit-prepared","name":"commit_prepared","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"transactionId","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":"PreparedTransactionFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Transaction","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENPTU1JVCBQUkVQQVJFRCBidWlsZGVyLgogKgogKiBFeGFtcGxlOiBjb21taXRfcHJlcGFyZWQoJ215X3RyYW5zYWN0aW9uJykKICogUHJvZHVjZXM6IENPTU1JVCBQUkVQQVJFRCAnbXlfdHJhbnNhY3Rpb24nCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":1153,"slug":"rollback-prepared","name":"rollback_prepared","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"transactionId","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":"PreparedTransactionFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Transaction","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFJPTExCQUNLIFBSRVBBUkVEIGJ1aWxkZXIuCiAqCiAqIEV4YW1wbGU6IHJvbGxiYWNrX3ByZXBhcmVkKCdteV90cmFuc2FjdGlvbicpCiAqIFByb2R1Y2VzOiBST0xMQkFDSyBQUkVQQVJFRCAnbXlfdHJhbnNhY3Rpb24nCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":1176,"slug":"declare-cursor","name":"declare_cursor","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"cursorName","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":"query","type":[{"name":"SelectFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Select","is_nullable":false,"is_variadic":false},{"name":"Sql","namespace":"Flow\\PostgreSql\\QueryBuilder","is_nullable":false,"is_variadic":false},{"name":"ParsedQuery","namespace":"Flow\\PostgreSql","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":"DeclareCursorOptionsStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Cursor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIERlY2xhcmUgYSBzZXJ2ZXItc2lkZSBjdXJzb3IgZm9yIGEgcXVlcnkuCiAqCiAqIEN1cnNvcnMgbXVzdCBiZSBkZWNsYXJlZCB3aXRoaW4gYSB0cmFuc2FjdGlvbiBhbmQgcHJvdmlkZSBtZW1vcnktZWZmaWNpZW50CiAqIGl0ZXJhdGlvbiBvdmVyIGxhcmdlIHJlc3VsdCBzZXRzIHZpYSBGRVRDSCBjb21tYW5kcy4KICoKICogRXhhbXBsZSB3aXRoIHF1ZXJ5IGJ1aWxkZXI6CiAqICAgZGVjbGFyZV9jdXJzb3IoJ215X2N1cnNvcicsIHNlbGVjdChzdGFyKCkpLT5mcm9tKHRhYmxlKCd1c2VycycpKSktPm5vU2Nyb2xsKCkKICogICBQcm9kdWNlczogREVDTEFSRSBteV9jdXJzb3IgTk8gU0NST0xMIENVUlNPUiBGT1IgU0VMRUNUICogRlJPTSB1c2VycwogKgogKiBFeGFtcGxlIHdpdGggcmF3IFNRTDoKICogICBkZWNsYXJlX2N1cnNvcignbXlfY3Vyc29yJywgJ1NFTEVDVCAqIEZST00gdXNlcnMgV0hFUkUgYWN0aXZlID0gdHJ1ZScpLT53aXRoSG9sZCgpCiAqICAgUHJvZHVjZXM6IERFQ0xBUkUgbXlfY3Vyc29yIE5PIFNDUk9MTCBDVVJTT1IgV0lUSCBIT0xEIEZPUiBTRUxFQ1QgKiBGUk9NIHVzZXJzIFdIRVJFIGFjdGl2ZSA9IHRydWUKICoKICogQHBhcmFtIHN0cmluZyAkY3Vyc29yTmFtZSBVbmlxdWUgY3Vyc29yIG5hbWUKICogQHBhcmFtIFBhcnNlZFF1ZXJ5fFNlbGVjdEZpbmFsU3RlcHxTcWx8c3RyaW5nICRxdWVyeSBRdWVyeSB0byBpdGVyYXRlIG92ZXIKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":1201,"slug":"fetch","name":"fetch","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"cursorName","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":"FetchCursorBuilder","namespace":"Flow\\PostgreSql\\QueryBuilder\\Cursor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEZldGNoIHJvd3MgZnJvbSBhIGN1cnNvci4KICoKICogRXhhbXBsZTogZmV0Y2goJ215X2N1cnNvcicpLT5mb3J3YXJkKDEwMCkKICogUHJvZHVjZXM6IEZFVENIIEZPUldBUkQgMTAwIG15X2N1cnNvcgogKgogKiBFeGFtcGxlOiBmZXRjaCgnbXlfY3Vyc29yJyktPmFsbCgpCiAqIFByb2R1Y2VzOiBGRVRDSCBBTEwgbXlfY3Vyc29yCiAqCiAqIEBwYXJhbSBzdHJpbmcgJGN1cnNvck5hbWUgQ3Vyc29yIHRvIGZldGNoIGZyb20KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":1218,"slug":"close-cursor","name":"close_cursor","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"cursorName","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"CloseCursorFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Cursor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENsb3NlIGEgY3Vyc29yLgogKgogKiBFeGFtcGxlOiBjbG9zZV9jdXJzb3IoJ215X2N1cnNvcicpCiAqIFByb2R1Y2VzOiBDTE9TRSBteV9jdXJzb3IKICoKICogRXhhbXBsZTogY2xvc2VfY3Vyc29yKCkgLSBjbG9zZXMgYWxsIGN1cnNvcnMKICogUHJvZHVjZXM6IENMT1NFIEFMTAogKgogKiBAcGFyYW0gbnVsbHxzdHJpbmcgJGN1cnNvck5hbWUgQ3Vyc29yIHRvIGNsb3NlLCBvciBudWxsIHRvIGNsb3NlIGFsbAogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":42,"slug":"eq","name":"eq","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"left","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"right","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"Comparison","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBlcXVhbGl0eSBjb21wYXJpc29uIChjb2x1bW4gPSB2YWx1ZSkuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":55,"slug":"ne","name":"ne","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"left","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"right","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"Comparison","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIG5vdC1lcXVhbCBjb21wYXJpc29uIChjb2x1bW4gIT0gdmFsdWUpLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":68,"slug":"lt","name":"lt","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"left","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"right","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"Comparison","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGxlc3MtdGhhbiBjb21wYXJpc29uIChjb2x1bW4gPCB2YWx1ZSkuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":81,"slug":"le","name":"le","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"left","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"right","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"Comparison","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGxlc3MtdGhhbi1vci1lcXVhbCBjb21wYXJpc29uIChjb2x1bW4gPD0gdmFsdWUpLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":94,"slug":"gt","name":"gt","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"left","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"right","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"Comparison","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGdyZWF0ZXItdGhhbiBjb21wYXJpc29uIChjb2x1bW4gPiB2YWx1ZSkuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":107,"slug":"ge","name":"ge","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"left","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"right","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"Comparison","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGdyZWF0ZXItdGhhbi1vci1lcXVhbCBjb21wYXJpc29uIChjb2x1bW4gPj0gdmFsdWUpLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":120,"slug":"between","name":"between","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"low","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"high","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"not","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":"Between","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEJFVFdFRU4gY29uZGl0aW9uLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":139,"slug":"in","name":"in_","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"values","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":"In","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBJTiBjb25kaXRpb24uCiAqCiAqIEBwYXJhbSBFeHByZXNzaW9ufHN0cmluZyAkZXhwciBFeHByZXNzaW9uIHRvIGNoZWNrCiAqIEBwYXJhbSBsaXN0PEV4cHJlc3Npb24+ICR2YWx1ZXMgTGlzdCBvZiB2YWx1ZXMgKG11c3QgYmUgbm9uLWVtcHR5KQogKgogKiBAdGhyb3dzIFxJbnZhbGlkQXJndW1lbnRFeGNlcHRpb24gd2hlbiB2YWx1ZXMgYXJyYXkgaXMgZW1wdHkKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":156,"slug":"is-null","name":"is_null","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"not","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":"IsNull","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBJUyBOVUxMIGNvbmRpdGlvbi4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":165,"slug":"like","name":"like","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"pattern","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"caseInsensitive","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"negated","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":"Like","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIExJS0UgY29uZGl0aW9uLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":183,"slug":"similar-to","name":"similar_to","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"pattern","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"SimilarTo","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFNJTUlMQVIgVE8gY29uZGl0aW9uLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":195,"slug":"distinct-from","name":"distinct_from","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"left","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"right","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"not","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":"IsDistinctFrom","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBJUyBESVNUSU5DVCBGUk9NIGNvbmRpdGlvbi4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":208,"slug":"exists","name":"exists","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"subquery","type":[{"name":"SelectFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Select","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Exists","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBFWElTVFMgY29uZGl0aW9uLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":223,"slug":"any","name":"any_","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"left","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"operator","type":[{"name":"ComparisonOperator","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"arrayOrSubquery","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false},{"name":"SelectFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Select","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\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBBTlkgY29uZGl0aW9uIHdpdGggYSBzdWJxdWVyeSBvciBhcnJheSBleHByZXNzaW9uLgogKgogKiBFeGFtcGxlOiBhbnlfKGNvbCgnaWQnKSwgQ29tcGFyaXNvbk9wZXJhdG9yOjpFUSwgc2VsZWN0KGNvbCgndXNlcl9pZCcpKS0+ZnJvbSh0YWJsZSgnb3JkZXJzJykpKQogKiBFeGFtcGxlOiBhbnlfKGNvbCgnYXR0bnVtJywgJ2EnKSwgQ29tcGFyaXNvbk9wZXJhdG9yOjpFUSwgY29sKCdjb25rZXknLCAnY29uJykpCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":243,"slug":"all","name":"all_","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"left","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"operator","type":[{"name":"ComparisonOperator","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"arrayOrSubquery","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false},{"name":"SelectFinalStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Select","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\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBBTEwgY29uZGl0aW9uIHdpdGggYSBzdWJxdWVyeSBvciBhcnJheSBleHByZXNzaW9uLgogKgogKiBFeGFtcGxlOiBhbGxfKGNvbCgnaWQnKSwgQ29tcGFyaXNvbk9wZXJhdG9yOjpFUSwgc2VsZWN0KGNvbCgndXNlcl9pZCcpKS0+ZnJvbSh0YWJsZSgnb3JkZXJzJykpKQogKiBFeGFtcGxlOiBhbGxfKGNvbCgndmFsdWUnKSwgQ29tcGFyaXNvbk9wZXJhdG9yOjpHVCwgY29sKCd0aHJlc2hvbGRzJykpCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":262,"slug":"is-true","name":"is_true","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"BooleanCondition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFdyYXAgYW4gZXhwcmVzc2lvbiBhcyBhIGJvb2xlYW4gY29uZGl0aW9uIGZvciB1c2UgaW4gV0hFUkUvSEFWSU5HL0pPSU4gT04uCiAqCiAqIEV4YW1wbGU6IGlzX3RydWUoY29sKCdpc19hY3RpdmUnKSkg4oCUIHVzZXMgYSBib29sZWFuIGNvbHVtbiBpbiBXSEVSRSBjbGF1c2UuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":274,"slug":"not-like","name":"not_like","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"pattern","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"caseInsensitive","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":"Like","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIE5PVCBMSUtFIGNvbmRpdGlvbi4KICoKICogRXhhbXBsZTogbm90X2xpa2UoY29sKCduYW1lJyksIGxpdGVyYWwoJ3BnXyUnKSkKICogUHJvZHVjZXM6IG5hbWUgTk9UIExJS0UgJ3BnXyUnCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":302,"slug":"conditions","name":"conditions","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ConditionBuilder","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGNvbmRpdGlvbiBidWlsZGVyIGZvciBmbHVlbnQgY29uZGl0aW9uIGNvbXBvc2l0aW9uLgogKgogKiBUaGlzIGJ1aWxkZXIgYWxsb3dzIGluY3JlbWVudGFsIGNvbmRpdGlvbiBidWlsZGluZyB3aXRoIGEgZmx1ZW50IEFQSToKICoKICogYGBgcGhwCiAqICRidWlsZGVyID0gY29uZGl0aW9ucygpOwogKgogKiBpZiAoJGhhc0ZpbHRlcikgewogKiAgICAgJGJ1aWxkZXIgPSAkYnVpbGRlci0+YW5kKGVxKGNvbCgnc3RhdHVzJyksIGxpdGVyYWwoJ2FjdGl2ZScpKSk7CiAqIH0KICoKICogaWYgKCEkYnVpbGRlci0+aXNFbXB0eSgpKSB7CiAqICAgICAkcXVlcnkgPSBzZWxlY3QoKS0+ZnJvbSh0YWJsZSgndXNlcnMnKSktPndoZXJlKCRidWlsZGVyKTsKICogfQogKiBgYGAKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":313,"slug":"and","name":"and_","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"conditions","type":[{"name":"Condition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"AndCondition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENvbWJpbmUgY29uZGl0aW9ucyB3aXRoIEFORC4KICoKICogQHBhcmFtIENvbmRpdGlvbiAuLi4kY29uZGl0aW9ucyBDb25kaXRpb25zIHRvIGNvbWJpbmUKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":324,"slug":"or","name":"or_","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"conditions","type":[{"name":"Condition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"OrCondition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENvbWJpbmUgY29uZGl0aW9ucyB3aXRoIE9SLgogKgogKiBAcGFyYW0gQ29uZGl0aW9uIC4uLiRjb25kaXRpb25zIENvbmRpdGlvbnMgdG8gY29tYmluZQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":336,"slug":"not","name":"not_","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expression","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"NotCondition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIE5lZ2F0ZSBhIGNvbmRpdGlvbiBvciBleHByZXNzaW9uIHdpdGggTk9ULgogKgogKiBBY2NlcHRzIGJvdGggQ29uZGl0aW9uIGFuZCBFeHByZXNzaW9uIOKAlCBOT1QgYWx3YXlzIHByb2R1Y2VzIGEgYm9vbGVhbiByZXN1bHQuCiAqIENhbiBiZSB1c2VkIGluIFdIRVJFIGNsYXVzZXMgYW5kIFNFTEVDVCBsaXN0cyAodmlhIC0+YXMoJ2FsaWFzJykpLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":348,"slug":"json-contains","name":"json_contains","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"left","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"right","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"OperatorCondition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEpTT05CIGNvbnRhaW5zIGNvbmRpdGlvbiAoQD4pLgogKgogKiBFeGFtcGxlOiBqc29uX2NvbnRhaW5zKGNvbCgnbWV0YWRhdGEnKSwgbGl0ZXJhbF9qc29uKCd7ImNhdGVnb3J5IjogImVsZWN0cm9uaWNzIn0nKSkKICogUHJvZHVjZXM6IG1ldGFkYXRhIEA+ICd7ImNhdGVnb3J5IjogImVsZWN0cm9uaWNzIn0nCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":364,"slug":"json-contained-by","name":"json_contained_by","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"left","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"right","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"OperatorCondition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEpTT05CIGlzIGNvbnRhaW5lZCBieSBjb25kaXRpb24gKDxAKS4KICoKICogRXhhbXBsZToganNvbl9jb250YWluZWRfYnkoY29sKCdtZXRhZGF0YScpLCBsaXRlcmFsX2pzb24oJ3siY2F0ZWdvcnkiOiAiZWxlY3Ryb25pY3MiLCAicHJpY2UiOiAxMDB9JykpCiAqIFByb2R1Y2VzOiBtZXRhZGF0YSA8QCAneyJjYXRlZ29yeSI6ICJlbGVjdHJvbmljcyIsICJwcmljZSI6IDEwMH0nCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":381,"slug":"json-get","name":"json_get","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"key","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"BinaryExpression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEpTT04gZmllbGQgYWNjZXNzIGV4cHJlc3Npb24gKC0+KS4KICogUmV0dXJucyBKU09OLgogKgogKiBFeGFtcGxlOiBqc29uX2dldChjb2woJ21ldGFkYXRhJyksIGxpdGVyYWxfc3RyaW5nKCdjYXRlZ29yeScpKQogKiBQcm9kdWNlczogbWV0YWRhdGEgLT4gJ2NhdGVnb3J5JwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":398,"slug":"json-get-text","name":"json_get_text","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"key","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"BinaryExpression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEpTT04gZmllbGQgYWNjZXNzIGV4cHJlc3Npb24gKC0+PikuCiAqIFJldHVybnMgdGV4dC4KICoKICogRXhhbXBsZToganNvbl9nZXRfdGV4dChjb2woJ21ldGFkYXRhJyksIGxpdGVyYWxfc3RyaW5nKCduYW1lJykpCiAqIFByb2R1Y2VzOiBtZXRhZGF0YSAtPj4gJ25hbWUnCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":415,"slug":"json-path","name":"json_path","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"path","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"BinaryExpression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEpTT04gcGF0aCBhY2Nlc3MgZXhwcmVzc2lvbiAoIz4pLgogKiBSZXR1cm5zIEpTT04uCiAqCiAqIEV4YW1wbGU6IGpzb25fcGF0aChjb2woJ21ldGFkYXRhJyksIGxpdGVyYWxfc3RyaW5nKCd7Y2F0ZWdvcnksbmFtZX0nKSkKICogUHJvZHVjZXM6IG1ldGFkYXRhICM+ICd7Y2F0ZWdvcnksbmFtZX0nCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":432,"slug":"json-path-text","name":"json_path_text","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"path","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"BinaryExpression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEpTT04gcGF0aCBhY2Nlc3MgZXhwcmVzc2lvbiAoIz4+KS4KICogUmV0dXJucyB0ZXh0LgogKgogKiBFeGFtcGxlOiBqc29uX3BhdGhfdGV4dChjb2woJ21ldGFkYXRhJyksIGxpdGVyYWxfc3RyaW5nKCd7Y2F0ZWdvcnksbmFtZX0nKSkKICogUHJvZHVjZXM6IG1ldGFkYXRhICM+PiAne2NhdGVnb3J5LG5hbWV9JwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":448,"slug":"json-exists","name":"json_exists","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"key","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"OperatorCondition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEpTT05CIGtleSBleGlzdHMgY29uZGl0aW9uICg\/KS4KICoKICogRXhhbXBsZToganNvbl9leGlzdHMoY29sKCdtZXRhZGF0YScpLCBsaXRlcmFsX3N0cmluZygnY2F0ZWdvcnknKSkKICogUHJvZHVjZXM6IG1ldGFkYXRhID8gJ2NhdGVnb3J5JwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":464,"slug":"json-exists-any","name":"json_exists_any","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"keys","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"OperatorCondition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEpTT05CIGFueSBrZXkgZXhpc3RzIGNvbmRpdGlvbiAoP3wpLgogKgogKiBFeGFtcGxlOiBqc29uX2V4aXN0c19hbnkoY29sKCdtZXRhZGF0YScpLCBhcnJheV9leHByKFtsaXRlcmFsKCdjYXRlZ29yeScpLCBsaXRlcmFsKCduYW1lJyldKSkKICogUHJvZHVjZXM6IG1ldGFkYXRhID98IGFycmF5WydjYXRlZ29yeScsICduYW1lJ10KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":480,"slug":"json-exists-all","name":"json_exists_all","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"keys","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"OperatorCondition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEpTT05CIGFsbCBrZXlzIGV4aXN0IGNvbmRpdGlvbiAoPyYpLgogKgogKiBFeGFtcGxlOiBqc29uX2V4aXN0c19hbGwoY29sKCdtZXRhZGF0YScpLCBhcnJheV9leHByKFtsaXRlcmFsKCdjYXRlZ29yeScpLCBsaXRlcmFsKCduYW1lJyldKSkKICogUHJvZHVjZXM6IG1ldGFkYXRhID8mIGFycmF5WydjYXRlZ29yeScsICduYW1lJ10KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":496,"slug":"array-contains","name":"array_contains","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"left","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"right","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"OperatorCondition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBhcnJheSBjb250YWlucyBjb25kaXRpb24gKEA+KS4KICoKICogRXhhbXBsZTogYXJyYXlfY29udGFpbnMoY29sKCd0YWdzJyksIGFycmF5X2V4cHIoW2xpdGVyYWwoJ3NhbGUnKV0pKQogKiBQcm9kdWNlczogdGFncyBAPiBBUlJBWVsnc2FsZSddCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":512,"slug":"array-contained-by","name":"array_contained_by","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"left","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"right","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"OperatorCondition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBhcnJheSBpcyBjb250YWluZWQgYnkgY29uZGl0aW9uICg8QCkuCiAqCiAqIEV4YW1wbGU6IGFycmF5X2NvbnRhaW5lZF9ieShjb2woJ3RhZ3MnKSwgYXJyYXlfZXhwcihbbGl0ZXJhbCgnc2FsZScpLCBsaXRlcmFsKCdmZWF0dXJlZCcpLCBsaXRlcmFsKCduZXcnKV0pKQogKiBQcm9kdWNlczogdGFncyA8QCBBUlJBWVsnc2FsZScsICdmZWF0dXJlZCcsICduZXcnXQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":528,"slug":"array-overlap","name":"array_overlap","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"left","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"right","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"OperatorCondition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBhcnJheSBvdmVybGFwIGNvbmRpdGlvbiAoJiYpLgogKgogKiBFeGFtcGxlOiBhcnJheV9vdmVybGFwKGNvbCgndGFncycpLCBhcnJheV9leHByKFtsaXRlcmFsKCdzYWxlJyksIGxpdGVyYWwoJ2ZlYXR1cmVkJyldKSkKICogUHJvZHVjZXM6IHRhZ3MgJiYgQVJSQVlbJ3NhbGUnLCAnZmVhdHVyZWQnXQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":546,"slug":"regex-match","name":"regex_match","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"pattern","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"OperatorCondition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBPU0lYIHJlZ2V4IG1hdGNoIGNvbmRpdGlvbiAofikuCiAqIENhc2Utc2Vuc2l0aXZlLgogKgogKiBFeGFtcGxlOiByZWdleF9tYXRjaChjb2woJ2VtYWlsJyksIGxpdGVyYWxfc3RyaW5nKCcuKkBnbWFpbFxcLmNvbScpKQogKgogKiBQcm9kdWNlczogZW1haWwgfiAnLipAZ21haWxcLmNvbScKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":564,"slug":"regex-imatch","name":"regex_imatch","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"pattern","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"OperatorCondition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBPU0lYIHJlZ2V4IG1hdGNoIGNvbmRpdGlvbiAofiopLgogKiBDYXNlLWluc2Vuc2l0aXZlLgogKgogKiBFeGFtcGxlOiByZWdleF9pbWF0Y2goY29sKCdlbWFpbCcpLCBsaXRlcmFsX3N0cmluZygnLipAZ21haWxcXC5jb20nKSkKICoKICogUHJvZHVjZXM6IGVtYWlsIH4qICcuKkBnbWFpbFwuY29tJwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":582,"slug":"not-regex-match","name":"not_regex_match","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"pattern","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"OperatorCondition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBPU0lYIHJlZ2V4IG5vdCBtYXRjaCBjb25kaXRpb24gKCF+KS4KICogQ2FzZS1zZW5zaXRpdmUuCiAqCiAqIEV4YW1wbGU6IG5vdF9yZWdleF9tYXRjaChjb2woJ2VtYWlsJyksIGxpdGVyYWxfc3RyaW5nKCcuKkBzcGFtXFwuY29tJykpCiAqCiAqIFByb2R1Y2VzOiBlbWFpbCAhfiAnLipAc3BhbVwuY29tJwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":600,"slug":"not-regex-imatch","name":"not_regex_imatch","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"pattern","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"OperatorCondition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBPU0lYIHJlZ2V4IG5vdCBtYXRjaCBjb25kaXRpb24gKCF+KikuCiAqIENhc2UtaW5zZW5zaXRpdmUuCiAqCiAqIEV4YW1wbGU6IG5vdF9yZWdleF9pbWF0Y2goY29sKCdlbWFpbCcpLCBsaXRlcmFsX3N0cmluZygnLipAc3BhbVxcLmNvbScpKQogKgogKiBQcm9kdWNlczogZW1haWwgIX4qICcuKkBzcGFtXC5jb20nCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":616,"slug":"text-search-match","name":"text_search_match","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"document","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"query","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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":"OperatorCondition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGZ1bGwtdGV4dCBzZWFyY2ggbWF0Y2ggY29uZGl0aW9uIChAQCkuCiAqCiAqIEV4YW1wbGU6IHRleHRfc2VhcmNoX21hdGNoKGNvbCgnZG9jdW1lbnQnKSwgZnVuYygndG9fdHNxdWVyeScsIFtsaXRlcmFsKCdlbmdsaXNoJyksIGxpdGVyYWwoJ2hlbGxvICYgd29ybGQnKV0pKQogKiBQcm9kdWNlczogZG9jdW1lbnQgQEAgdG9fdHNxdWVyeSgnZW5nbGlzaCcsICdoZWxsbyAmIHdvcmxkJykKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":33,"slug":"sql-parser","name":"sql_parser","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"Parser","namespace":"Flow\\PostgreSql","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":39,"slug":"sql-parse","name":"sql_parse","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"sql","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":"ParsedQuery","namespace":"Flow\\PostgreSql","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":49,"slug":"sql-fingerprint","name":"sql_fingerprint","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"sql","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":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFJldHVybnMgYSBmaW5nZXJwcmludCBvZiB0aGUgZ2l2ZW4gU1FMIHF1ZXJ5LgogKiBMaXRlcmFsIHZhbHVlcyBhcmUgbm9ybWFsaXplZCBzbyB0aGV5IHdvbid0IGFmZmVjdCB0aGUgZmluZ2VycHJpbnQuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":60,"slug":"sql-normalize","name":"sql_normalize","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"sql","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":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIE5vcm1hbGl6ZSBTUUwgcXVlcnkgYnkgcmVwbGFjaW5nIGxpdGVyYWwgdmFsdWVzIGFuZCBuYW1lZCBwYXJhbWV0ZXJzIHdpdGggcG9zaXRpb25hbCBwYXJhbWV0ZXJzLgogKiBXSEVSRSBpZCA9IDppZCB3aWxsIGJlIGNoYW5nZWQgaW50byBXSEVSRSBpZCA9ICQxCiAqIFdIRVJFIGlkID0gMSB3aWxsIGJlIGNoYW5nZWQgaW50byBXSEVSRSBpZCA9ICQxLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":70,"slug":"sql-normalize-utility","name":"sql_normalize_utility","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"sql","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":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIE5vcm1hbGl6ZSB1dGlsaXR5IFNRTCBzdGF0ZW1lbnRzIChEREwgbGlrZSBDUkVBVEUsIEFMVEVSLCBEUk9QKS4KICogVGhpcyBoYW5kbGVzIERETCBzdGF0ZW1lbnRzIGRpZmZlcmVudGx5IGZyb20gcGdfbm9ybWFsaXplKCkgd2hpY2ggaXMgb3B0aW1pemVkIGZvciBETUwuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":81,"slug":"sql-split","name":"sql_split","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"sql","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":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFNwbGl0IHN0cmluZyB3aXRoIG11bHRpcGxlIFNRTCBzdGF0ZW1lbnRzIGludG8gYXJyYXkgb2YgaW5kaXZpZHVhbCBzdGF0ZW1lbnRzLgogKgogKiBAcmV0dXJuIGFycmF5PHN0cmluZz4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":90,"slug":"sql-deparse-options","name":"sql_deparse_options","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"DeparseOptions","namespace":"Flow\\PostgreSql","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBEZXBhcnNlT3B0aW9ucyBmb3IgY29uZmlndXJpbmcgU1FMIGZvcm1hdHRpbmcuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":104,"slug":"sql-deparse","name":"sql_deparse","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"query","type":[{"name":"ParsedQuery","namespace":"Flow\\PostgreSql","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"options","type":[{"name":"DeparseOptions","namespace":"Flow\\PostgreSql","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENvbnZlcnQgYSBQYXJzZWRRdWVyeSBBU1QgYmFjayB0byBTUUwgc3RyaW5nLgogKgogKiBXaGVuIGNhbGxlZCB3aXRob3V0IG9wdGlvbnMsIHJldHVybnMgdGhlIFNRTCBhcyBhIHNpbXBsZSBzdHJpbmcuCiAqIFdoZW4gY2FsbGVkIHdpdGggRGVwYXJzZU9wdGlvbnMsIGFwcGxpZXMgZm9ybWF0dGluZyAocHJldHR5LXByaW50aW5nLCBpbmRlbnRhdGlvbiwgZXRjLikuCiAqCiAqIEB0aHJvd3MgXFJ1bnRpbWVFeGNlcHRpb24gaWYgZGVwYXJzaW5nIGZhaWxzCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":120,"slug":"sql-format","name":"sql_format","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"sql","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":"options","type":[{"name":"DeparseOptions","namespace":"Flow\\PostgreSql","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFBhcnNlIGFuZCBmb3JtYXQgU1FMIHF1ZXJ5IHdpdGggcHJldHR5IHByaW50aW5nLgogKgogKiBUaGlzIGlzIGEgY29udmVuaWVuY2UgZnVuY3Rpb24gdGhhdCBwYXJzZXMgU1FMIGFuZCByZXR1cm5zIGl0IGZvcm1hdHRlZC4KICoKICogQHBhcmFtIHN0cmluZyAkc3FsIFRoZSBTUUwgcXVlcnkgdG8gZm9ybWF0CiAqIEBwYXJhbSBudWxsfERlcGFyc2VPcHRpb25zICRvcHRpb25zIEZvcm1hdHRpbmcgb3B0aW9ucyAoZGVmYXVsdHMgdG8gcHJldHR5LXByaW50IGVuYWJsZWQpCiAqCiAqIEB0aHJvd3MgXFJ1bnRpbWVFeGNlcHRpb24gaWYgcGFyc2luZyBvciBkZXBhcnNpbmcgZmFpbHMKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":132,"slug":"sql-summary","name":"sql_summary","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"sql","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":"options","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":"truncateLimit","type":[{"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":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEdlbmVyYXRlIGEgc3VtbWFyeSBvZiBwYXJzZWQgcXVlcmllcyBpbiBwcm90b2J1ZiBmb3JtYXQuCiAqIFVzZWZ1bCBmb3IgcXVlcnkgbW9uaXRvcmluZyBhbmQgbG9nZ2luZyB3aXRob3V0IGZ1bGwgQVNUIG92ZXJoZWFkLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":147,"slug":"sql-to-paginated-query","name":"sql_to_paginated_query","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"sql","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":"limit","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":"offset","type":[{"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":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFRyYW5zZm9ybSBhIFNRTCBxdWVyeSBpbnRvIGEgcGFnaW5hdGVkIHF1ZXJ5IHdpdGggTElNSVQgYW5kIE9GRlNFVC4KICoKICogQHBhcmFtIHN0cmluZyAkc3FsIFRoZSBTUUwgcXVlcnkgdG8gcGFnaW5hdGUKICogQHBhcmFtIGludCAkbGltaXQgTWF4aW11bSBudW1iZXIgb2Ygcm93cyB0byByZXR1cm4KICogQHBhcmFtIGludCAkb2Zmc2V0IE51bWJlciBvZiByb3dzIHRvIHNraXAgKHJlcXVpcmVzIE9SREVSIEJZIGluIHF1ZXJ5KQogKgogKiBAcmV0dXJuIHN0cmluZyBUaGUgcGFnaW5hdGVkIFNRTCBxdWVyeQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":164,"slug":"sql-to-limited-query","name":"sql_to_limited_query","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"sql","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":"limit","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":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFRyYW5zZm9ybSBhIFNRTCBxdWVyeSB0byBsaW1pdCByZXN1bHRzIHRvIGEgc3BlY2lmaWMgbnVtYmVyIG9mIHJvd3MuCiAqCiAqIEBwYXJhbSBzdHJpbmcgJHNxbCBUaGUgU1FMIHF1ZXJ5IHRvIGxpbWl0CiAqIEBwYXJhbSBpbnQgJGxpbWl0IE1heGltdW0gbnVtYmVyIG9mIHJvd3MgdG8gcmV0dXJuCiAqCiAqIEByZXR1cm4gc3RyaW5nIFRoZSBsaW1pdGVkIFNRTCBxdWVyeQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":183,"slug":"sql-to-count-query","name":"sql_to_count_query","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"sql","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":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFRyYW5zZm9ybSBhIFNRTCBxdWVyeSBpbnRvIGEgQ09VTlQgcXVlcnkgZm9yIHBhZ2luYXRpb24uCiAqCiAqIFdyYXBzIHRoZSBxdWVyeSBpbjogU0VMRUNUIENPVU5UKCopIEZST00gKC4uLikgQVMgX2NvdW50X3N1YnEKICogUmVtb3ZlcyBPUkRFUiBCWSBhbmQgTElNSVQvT0ZGU0VUIGZyb20gdGhlIGlubmVyIHF1ZXJ5LgogKgogKiBAcGFyYW0gc3RyaW5nICRzcWwgVGhlIFNRTCBxdWVyeSB0byB0cmFuc2Zvcm0KICoKICogQHJldHVybiBzdHJpbmcgVGhlIENPVU5UIHF1ZXJ5CiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":205,"slug":"sql-to-keyset-query","name":"sql_to_keyset_query","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"sql","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":"limit","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":"columns","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":"cursor","type":[{"name":"array","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFRyYW5zZm9ybSBhIFNRTCBxdWVyeSBpbnRvIGEga2V5c2V0IChjdXJzb3ItYmFzZWQpIHBhZ2luYXRlZCBxdWVyeS4KICoKICogTW9yZSBlZmZpY2llbnQgdGhhbiBPRkZTRVQgZm9yIGxhcmdlIGRhdGFzZXRzIC0gdXNlcyBpbmRleGVkIFdIRVJFIGNvbmRpdGlvbnMuCiAqIEF1dG9tYXRpY2FsbHkgZGV0ZWN0cyBleGlzdGluZyBxdWVyeSBwYXJhbWV0ZXJzIGFuZCBhcHBlbmRzIGtleXNldCBwbGFjZWhvbGRlcnMgYXQgdGhlIGVuZC4KICoKICogQHBhcmFtIHN0cmluZyAkc3FsIFRoZSBTUUwgcXVlcnkgdG8gcGFnaW5hdGUgKG11c3QgaGF2ZSBPUkRFUiBCWSkKICogQHBhcmFtIGludCAkbGltaXQgTWF4aW11bSBudW1iZXIgb2Ygcm93cyB0byByZXR1cm4KICogQHBhcmFtIGxpc3Q8S2V5c2V0Q29sdW1uPiAkY29sdW1ucyBDb2x1bW5zIGZvciBrZXlzZXQgcGFnaW5hdGlvbiAobXVzdCBtYXRjaCBPUkRFUiBCWSkKICogQHBhcmFtIG51bGx8bGlzdDxudWxsfGJvb2x8ZmxvYXR8aW50fHN0cmluZz4gJGN1cnNvciBWYWx1ZXMgZnJvbSBsYXN0IHJvdyBvZiBwcmV2aW91cyBwYWdlIChudWxsIGZvciBmaXJzdCBwYWdlKQogKgogKiBAcmV0dXJuIHN0cmluZyBUaGUgcGFnaW5hdGVkIFNRTCBxdWVyeQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":220,"slug":"sql-keyset-column","name":"sql_keyset_column","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"column","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":"order","type":[{"name":"SortOrder","namespace":"Flow\\PostgreSql\\AST\\Transformers","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\PostgreSql\\AST\\Transformers\\SortOrder::..."}],"return_type":[{"name":"KeysetColumn","namespace":"Flow\\PostgreSql\\AST\\Transformers","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEtleXNldENvbHVtbiBmb3Iga2V5c2V0IHBhZ2luYXRpb24uCiAqCiAqIEBwYXJhbSBzdHJpbmcgJGNvbHVtbiBDb2x1bW4gbmFtZSAoY2FuIGluY2x1ZGUgdGFibGUgYWxpYXMgbGlrZSAidS5pZCIpCiAqIEBwYXJhbSBTb3J0T3JkZXIgJG9yZGVyIFNvcnQgb3JkZXIgKEFTQyBvciBERVNDKQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":229,"slug":"sql-query-columns","name":"sql_query_columns","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"query","type":[{"name":"ParsedQuery","namespace":"Flow\\PostgreSql","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Columns","namespace":"Flow\\PostgreSql\\Extractors","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEV4dHJhY3QgY29sdW1ucyBmcm9tIGEgcGFyc2VkIFNRTCBxdWVyeS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":238,"slug":"sql-query-tables","name":"sql_query_tables","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"query","type":[{"name":"ParsedQuery","namespace":"Flow\\PostgreSql","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Tables","namespace":"Flow\\PostgreSql\\Extractors","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEV4dHJhY3QgdGFibGVzIGZyb20gYSBwYXJzZWQgU1FMIHF1ZXJ5LgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":247,"slug":"sql-query-functions","name":"sql_query_functions","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"query","type":[{"name":"ParsedQuery","namespace":"Flow\\PostgreSql","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Functions","namespace":"Flow\\PostgreSql\\Extractors","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEV4dHJhY3QgZnVuY3Rpb25zIGZyb20gYSBwYXJzZWQgU1FMIHF1ZXJ5LgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":256,"slug":"sql-query-order-by","name":"sql_query_order_by","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"query","type":[{"name":"ParsedQuery","namespace":"Flow\\PostgreSql","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"OrderBy","namespace":"Flow\\PostgreSql\\Extractors","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEV4dHJhY3QgT1JERVIgQlkgY2xhdXNlcyBmcm9tIGEgcGFyc2VkIFNRTCBxdWVyeS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":270,"slug":"sql-query-depth","name":"sql_query_depth","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"sql","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":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEdldCB0aGUgbWF4aW11bSBuZXN0aW5nIGRlcHRoIG9mIGEgU1FMIHF1ZXJ5LgogKgogKiBFeGFtcGxlOgogKiAtICJTRUxFQ1QgKiBGUk9NIHQiID0+IDEKICogLSAiU0VMRUNUICogRlJPTSAoU0VMRUNUICogRlJPTSB0KSIgPT4gMgogKiAtICJTRUxFQ1QgKiBGUk9NIChTRUxFQ1QgKiBGUk9NIChTRUxFQ1QgKiBGUk9NIHQpKSIgPT4gMwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":287,"slug":"sql-to-explain","name":"sql_to_explain","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"sql","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":"config","type":[{"name":"ExplainConfig","namespace":"Flow\\PostgreSql\\AST\\Transformers","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFRyYW5zZm9ybSBhIFNRTCBxdWVyeSBpbnRvIGFuIEVYUExBSU4gcXVlcnkuCiAqCiAqIFJldHVybnMgdGhlIG1vZGlmaWVkIFNRTCB3aXRoIEVYUExBSU4gd3JhcHBlZCBhcm91bmQgaXQuCiAqIERlZmF1bHRzIHRvIEVYUExBSU4gQU5BTFlaRSB3aXRoIEpTT04gZm9ybWF0IGZvciBlYXN5IHBhcnNpbmcuCiAqCiAqIEBwYXJhbSBzdHJpbmcgJHNxbCBUaGUgU1FMIHF1ZXJ5IHRvIGV4cGxhaW4KICogQHBhcmFtIG51bGx8RXhwbGFpbkNvbmZpZyAkY29uZmlnIEVYUExBSU4gY29uZmlndXJhdGlvbiAoZGVmYXVsdHMgdG8gZm9yQW5hbHlzaXMoKSkKICoKICogQHJldHVybiBzdHJpbmcgVGhlIEVYUExBSU4gcXVlcnkKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":307,"slug":"sql-explain-config","name":"sql_explain_config","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"analyze","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"verbose","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"costs","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"buffers","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"timing","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"format","type":[{"name":"ExplainFormat","namespace":"Flow\\PostgreSql\\QueryBuilder\\Utility","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\PostgreSql\\QueryBuilder\\Utility\\ExplainFormat::..."}],"return_type":[{"name":"ExplainConfig","namespace":"Flow\\PostgreSql\\AST\\Transformers","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBFeHBsYWluQ29uZmlnIGZvciBjdXN0b21pemluZyBFWFBMQUlOIG9wdGlvbnMuCiAqCiAqIEBwYXJhbSBib29sICRhbmFseXplIFdoZXRoZXIgdG8gYWN0dWFsbHkgZXhlY3V0ZSB0aGUgcXVlcnkgKEFOQUxZWkUpCiAqIEBwYXJhbSBib29sICR2ZXJib3NlIEluY2x1ZGUgdmVyYm9zZSBvdXRwdXQKICogQHBhcmFtIGJvb2wgJGNvc3RzIEluY2x1ZGUgY29zdCBlc3RpbWF0ZXMgKGRlZmF1bHQgdHJ1ZSkKICogQHBhcmFtIGJvb2wgJGJ1ZmZlcnMgSW5jbHVkZSBidWZmZXIgdXNhZ2Ugc3RhdGlzdGljcyAocmVxdWlyZXMgYW5hbHl6ZSkKICogQHBhcmFtIGJvb2wgJHRpbWluZyBJbmNsdWRlIHRpbWluZyBpbmZvcm1hdGlvbiAocmVxdWlyZXMgYW5hbHl6ZSkKICogQHBhcmFtIEV4cGxhaW5Gb3JtYXQgJGZvcm1hdCBPdXRwdXQgZm9ybWF0IChKU09OIHJlY29tbWVuZGVkIGZvciBwYXJzaW5nKQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":329,"slug":"sql-explain-modifier","name":"sql_explain_modifier","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"config","type":[{"name":"ExplainConfig","namespace":"Flow\\PostgreSql\\AST\\Transformers","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ExplainModifier","namespace":"Flow\\PostgreSql\\AST\\Transformers","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBFeHBsYWluTW9kaWZpZXIgZm9yIHRyYW5zZm9ybWluZyBxdWVyaWVzIGludG8gRVhQTEFJTiBxdWVyaWVzLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":342,"slug":"sql-explain-parse","name":"sql_explain_parse","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"jsonOutput","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":"Plan","namespace":"Flow\\PostgreSql\\Explain\\Plan","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFBhcnNlIEVYUExBSU4gSlNPTiBvdXRwdXQgaW50byBhIFBsYW4gb2JqZWN0LgogKgogKiBAcGFyYW0gc3RyaW5nICRqc29uT3V0cHV0IFRoZSBKU09OIG91dHB1dCBmcm9tIEVYUExBSU4gKEZPUk1BVCBKU09OKQogKgogKiBAcmV0dXJuIFBsYW4gVGhlIHBhcnNlZCBleGVjdXRpb24gcGxhbgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/parser.php","start_line_in_file":355,"slug":"sql-analyze","name":"sql_analyze","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"plan","type":[{"name":"Plan","namespace":"Flow\\PostgreSql\\Explain\\Plan","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"PlanAnalyzer","namespace":"Flow\\PostgreSql\\Explain\\Analyzer","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHBsYW4gYW5hbHl6ZXIgZm9yIGFuYWx5emluZyBFWFBMQUlOIHBsYW5zLgogKgogKiBAcGFyYW0gUGxhbiAkcGxhbiBUaGUgZXhlY3V0aW9uIHBsYW4gdG8gYW5hbHl6ZQogKgogKiBAcmV0dXJuIFBsYW5BbmFseXplciBUaGUgYW5hbHl6ZXIgZm9yIGV4dHJhY3RpbmcgaW5zaWdodHMKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/client.php","start_line_in_file":46,"slug":"pgsql-connection","name":"pgsql_connection","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"connectionString","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":"ConnectionParameters","namespace":"Flow\\PostgreSql\\Client","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBjb25uZWN0aW9uIHBhcmFtZXRlcnMgZnJvbSBhIGNvbm5lY3Rpb24gc3RyaW5nLgogKgogKiBBY2NlcHRzIGxpYnBxLXN0eWxlIGNvbm5lY3Rpb24gc3RyaW5nczoKICogLSBLZXktdmFsdWUgZm9ybWF0OiAiaG9zdD1sb2NhbGhvc3QgcG9ydD01NDMyIGRibmFtZT1teWRiIHVzZXI9bXl1c2VyIHBhc3N3b3JkPXNlY3JldCIKICogLSBVUkkgZm9ybWF0OiAicG9zdGdyZXNxbDovL3VzZXI6cGFzc3dvcmRAbG9jYWxob3N0OjU0MzIvZGJuYW1lIgogKgogKiBAZXhhbXBsZQogKiAkcGFyYW1zID0gcGdzcWxfY29ubmVjdGlvbignaG9zdD1sb2NhbGhvc3QgZGJuYW1lPW15ZGInKTsKICogJHBhcmFtcyA9IHBnc3FsX2Nvbm5lY3Rpb24oJ3Bvc3RncmVzcWw6Ly91c2VyOnBhc3NAbG9jYWxob3N0L215ZGInKTsKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/client.php","start_line_in_file":68,"slug":"pgsql-connection-dsn","name":"pgsql_connection_dsn","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"dsn","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":"ConnectionParameters","namespace":"Flow\\PostgreSql\\Client","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBjb25uZWN0aW9uIHBhcmFtZXRlcnMgZnJvbSBhIERTTiBzdHJpbmcuCiAqCiAqIFBhcnNlcyBzdGFuZGFyZCBQb3N0Z3JlU1FMIERTTiBmb3JtYXQgY29tbW9ubHkgdXNlZCBpbiBlbnZpcm9ubWVudCB2YXJpYWJsZXMKICogKGUuZy4sIERBVEFCQVNFX1VSTCkuIFN1cHBvcnRzIHBvc3RncmVzOi8vLCBwb3N0Z3Jlc3FsOi8vLCBhbmQgcGdzcWw6Ly8gc2NoZW1lcy4KICoKICogQHBhcmFtIHN0cmluZyAkZHNuIERTTiBzdHJpbmcgaW4gZm9ybWF0OiBwb3N0Z3JlczovL3VzZXI6cGFzc3dvcmRAaG9zdDpwb3J0L2RhdGFiYXNlP29wdGlvbnMKICoKICogQHRocm93cyBDbGllbnRcRHNuUGFyc2VyRXhjZXB0aW9uIElmIHRoZSBEU04gY2Fubm90IGJlIHBhcnNlZAogKgogKiBAZXhhbXBsZQogKiAkcGFyYW1zID0gcGdzcWxfY29ubmVjdGlvbl9kc24oJ3Bvc3RncmVzOi8vbXl1c2VyOnNlY3JldEBsb2NhbGhvc3Q6NTQzMi9teWRiJyk7CiAqICRwYXJhbXMgPSBwZ3NxbF9jb25uZWN0aW9uX2RzbigncG9zdGdyZXNxbDovL3VzZXI6cGFzc0BkYi5leGFtcGxlLmNvbS9hcHA\/c3NsbW9kZT1yZXF1aXJlJyk7CiAqICRwYXJhbXMgPSBwZ3NxbF9jb25uZWN0aW9uX2RzbigncGdzcWw6Ly91c2VyOnBhc3NAbG9jYWxob3N0L215ZGInKTsgLy8gU3ltZm9ueS9Eb2N0cmluZSBmb3JtYXQKICogJHBhcmFtcyA9IHBnc3FsX2Nvbm5lY3Rpb25fZHNuKGdldGVudignREFUQUJBU0VfVVJMJykpOwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/client.php","start_line_in_file":95,"slug":"pgsql-connection-params","name":"pgsql_connection_params","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"database","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":"host","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'localhost'"},{"name":"port","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"5432"},{"name":"user","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":"password","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":"options","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"ConnectionParameters","namespace":"Flow\\PostgreSql\\Client","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBjb25uZWN0aW9uIHBhcmFtZXRlcnMgZnJvbSBpbmRpdmlkdWFsIHZhbHVlcy4KICoKICogQWxsb3dzIHNwZWNpZnlpbmcgY29ubmVjdGlvbiBwYXJhbWV0ZXJzIGluZGl2aWR1YWxseSBmb3IgYmV0dGVyIHR5cGUgc2FmZXR5CiAqIGFuZCBJREUgc3VwcG9ydC4KICoKICogQHBhcmFtIHN0cmluZyAkZGF0YWJhc2UgRGF0YWJhc2UgbmFtZSAocmVxdWlyZWQpCiAqIEBwYXJhbSBzdHJpbmcgJGhvc3QgSG9zdG5hbWUgKGRlZmF1bHQ6IGxvY2FsaG9zdCkKICogQHBhcmFtIGludCAkcG9ydCBQb3J0IG51bWJlciAoZGVmYXVsdDogNTQzMikKICogQHBhcmFtIG51bGx8c3RyaW5nICR1c2VyIFVzZXJuYW1lIChvcHRpb25hbCkKICogQHBhcmFtIG51bGx8c3RyaW5nICRwYXNzd29yZCBQYXNzd29yZCAob3B0aW9uYWwpCiAqIEBwYXJhbSBhcnJheTxzdHJpbmcsIHN0cmluZz4gJG9wdGlvbnMgQWRkaXRpb25hbCBsaWJwcSBvcHRpb25zCiAqCiAqIEBleGFtcGxlCiAqICRwYXJhbXMgPSBwZ3NxbF9jb25uZWN0aW9uX3BhcmFtcygKICogICAgIGRhdGFiYXNlOiAnbXlkYicsCiAqICAgICBob3N0OiAnbG9jYWxob3N0JywKICogICAgIHVzZXI6ICdteXVzZXInLAogKiAgICAgcGFzc3dvcmQ6ICdzZWNyZXQnLAogKiApOwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/client.php","start_line_in_file":126,"slug":"pgsql-client","name":"pgsql_client","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"params","type":[{"name":"ConnectionParameters","namespace":"Flow\\PostgreSql\\Client","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"valueConverters","type":[{"name":"ValueConverters","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"context","type":[{"name":"Context","namespace":"Flow\\PostgreSql\\Client","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Client","namespace":"Flow\\PostgreSql\\Client","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBvc3RncmVTUUwgY2xpZW50IHVzaW5nIGV4dC1wZ3NxbC4KICoKICogVGhlIGNsaWVudCBjb25uZWN0cyBpbW1lZGlhdGVseSBhbmQgaXMgcmVhZHkgdG8gZXhlY3V0ZSBxdWVyaWVzLgogKgogKiBAcGFyYW0gQ2xpZW50XENvbm5lY3Rpb25QYXJhbWV0ZXJzICRwYXJhbXMgQ29ubmVjdGlvbiBwYXJhbWV0ZXJzCiAqIEBwYXJhbSBudWxsfFZhbHVlQ29udmVydGVycyAkdmFsdWVDb252ZXJ0ZXJzIEN1c3RvbSB0eXBlIGNvbnZlcnRlcnMgKG9wdGlvbmFsKQogKiBAcGFyYW0gbnVsbHxDb250ZXh0ICRjb250ZXh0IEJhc2UgbWFwcGVyIENvbnRleHQg4oCUIHRoZSBDbGllbnQgZW5yaWNoZXMgaXQgd2l0aCBzcWwvcGFyYW1ldGVycy9zZWxmIHBlciBxdWVyeSBiZWZvcmUgaGFuZGluZyBpdCB0byBSb3dNYXBwZXI6Om1hcCgpCiAqCiAqIEB0aHJvd3MgQ29ubmVjdGlvbkV4Y2VwdGlvbiBJZiBjb25uZWN0aW9uIGZhaWxzCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/client.php","start_line_in_file":143,"slug":"postgresql-context","name":"postgresql_context","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"data","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"catalog","type":[{"name":"Catalog","namespace":"Flow\\PostgreSql\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Context","namespace":"Flow\\PostgreSql\\Client","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFJvd01hcHBlciBDb250ZXh0IHNlZWRlZCB3aXRoIHVzZXItc3VwcGxpZWQga2V5L3ZhbHVlIGRhdGEgYW5kIGFuIG9wdGlvbmFsIENhdGFsb2cuCiAqCiAqIFRoZSBDb250ZXh0IGlzIGxhdGVyIGVucmljaGVkIHdpdGggYSBRdWVyeSAoc3FsICsgcGFyYW1ldGVycykgYW5kIHRoZSBleGVjdXRpbmcgQ2xpZW50IGJ5IHRoZQogKiBQb3N0Z3JlU1FMIENsaWVudCBiZWZvcmUgYmVpbmcgaGFuZGVkIHRvIFJvd01hcHBlcjo6bWFwKCkuCiAqCiAqIEBwYXJhbSBhcnJheTxzdHJpbmcsIG1peGVkPiAkZGF0YSBVc2VyLXN1cHBsaWVkIGtleS92YWx1ZSBwYWlycwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/client.php","start_line_in_file":176,"slug":"postgresql-telemetry-options","name":"postgresql_telemetry_options","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"traceQueries","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"transactionSpans","type":[{"name":"TransactionSpanMode","namespace":"Flow\\PostgreSql\\Client\\Telemetry","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\PostgreSql\\Client\\Telemetry\\TransactionSpanMode::..."},{"name":"collectMetrics","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"logQueries","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"maxQueryLength","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"1000"},{"name":"includeParameters","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"maxParameters","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"10"},{"name":"maxParameterLength","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"100"}],"return_type":[{"name":"PostgreSqlTelemetryOptions","namespace":"Flow\\PostgreSql\\Client\\Telemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSB0ZWxlbWV0cnkgb3B0aW9ucyBmb3IgUG9zdGdyZVNRTCBjbGllbnQgaW5zdHJ1bWVudGF0aW9uLgogKgogKiBDb250cm9scyB3aGljaCB0ZWxlbWV0cnkgc2lnbmFscyAodHJhY2VzLCBtZXRyaWNzLCBsb2dzKSBhcmUgZW5hYmxlZAogKiBhbmQgaG93IHF1ZXJ5IGluZm9ybWF0aW9uIGlzIGNhcHR1cmVkLgogKgogKiBAcGFyYW0gYm9vbCAkdHJhY2VRdWVyaWVzIENyZWF0ZSBzcGFucyBmb3IgcXVlcnkgZXhlY3V0aW9uIChkZWZhdWx0OiB0cnVlKQogKiBAcGFyYW0gVHJhbnNhY3Rpb25TcGFuTW9kZSAkdHJhbnNhY3Rpb25TcGFucyBIb3cgdHJhbnNhY3Rpb25zIGFyZSB0cmFjZWQ6IEdST1VQRUQgKGRlZmF1bHQpLCBQRVJfT1BFUkFUSU9OIG9yIE9GRgogKiBAcGFyYW0gYm9vbCAkY29sbGVjdE1ldHJpY3MgQ29sbGVjdCBkdXJhdGlvbiBhbmQgcm93IGNvdW50IG1ldHJpY3MgKGRlZmF1bHQ6IHRydWUpCiAqIEBwYXJhbSBib29sICRsb2dRdWVyaWVzIExvZyBleGVjdXRlZCBxdWVyaWVzIChkZWZhdWx0OiBmYWxzZSkKICogQHBhcmFtIG51bGx8aW50ICRtYXhRdWVyeUxlbmd0aCBNYXhpbXVtIHF1ZXJ5IHRleHQgbGVuZ3RoIGluIHRlbGVtZXRyeSAoZGVmYXVsdDogMTAwMCwgbnVsbCA9IHVubGltaXRlZCkKICogQHBhcmFtIGJvb2wgJGluY2x1ZGVQYXJhbWV0ZXJzIEluY2x1ZGUgcXVlcnkgcGFyYW1ldGVycyBpbiB0ZWxlbWV0cnkgKGRlZmF1bHQ6IGZhbHNlLCBzZWN1cml0eSBjb25zaWRlcmF0aW9uKQogKgogKiBAZXhhbXBsZQogKiAvLyBEZWZhdWx0IG9wdGlvbnMgKHRyYWNlcyBhbmQgbWV0cmljcyBlbmFibGVkKQogKiAkb3B0aW9ucyA9IHBvc3RncmVzcWxfdGVsZW1ldHJ5X29wdGlvbnMoKTsKICoKICogLy8gRW5hYmxlIHF1ZXJ5IGxvZ2dpbmcKICogJG9wdGlvbnMgPSBwb3N0Z3Jlc3FsX3RlbGVtZXRyeV9vcHRpb25zKGxvZ1F1ZXJpZXM6IHRydWUpOwogKgogKiAvLyBNZXRyaWNzIG9ubHksIG5vIHNwYW5zCiAqICRvcHRpb25zID0gcG9zdGdyZXNxbF90ZWxlbWV0cnlfb3B0aW9ucygKICogICAgIHRyYWNlUXVlcmllczogZmFsc2UsCiAqICAgICB0cmFuc2FjdGlvblNwYW5zOiBUcmFuc2FjdGlvblNwYW5Nb2RlOjpPRkYsCiAqICAgICBjb2xsZWN0TWV0cmljczogdHJ1ZSwKICogKTsKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/client.php","start_line_in_file":214,"slug":"postgresql-telemetry-config","name":"postgresql_telemetry_config","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"telemetry","type":[{"name":"Telemetry","namespace":"Flow\\Telemetry","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"clock","type":[{"name":"ClockInterface","namespace":"Psr\\Clock","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"options","type":[{"name":"PostgreSqlTelemetryOptions","namespace":"Flow\\PostgreSql\\Client\\Telemetry","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"PostgreSqlTelemetryConfig","namespace":"Flow\\PostgreSql\\Client\\Telemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSB0ZWxlbWV0cnkgY29uZmlndXJhdGlvbiBmb3IgUG9zdGdyZVNRTCBjbGllbnQuCiAqCiAqIEJ1bmRsZXMgdGVsZW1ldHJ5IGluc3RhbmNlLCBjbG9jaywgYW5kIG9wdGlvbnMgbmVlZGVkIHRvIGluc3RydW1lbnQgYSBQb3N0Z3JlU1FMIGNsaWVudC4KICoKICogQHBhcmFtIFRlbGVtZXRyeSAkdGVsZW1ldHJ5IFRoZSB0ZWxlbWV0cnkgaW5zdGFuY2UKICogQHBhcmFtIENsb2NrSW50ZXJmYWNlICRjbG9jayBDbG9jayBmb3IgdGltZXN0YW1wcwogKiBAcGFyYW0gbnVsbHxQb3N0Z3JlU3FsVGVsZW1ldHJ5T3B0aW9ucyAkb3B0aW9ucyBUZWxlbWV0cnkgb3B0aW9ucyAoZGVmYXVsdDogYWxsIGVuYWJsZWQpCiAqCiAqIEBleGFtcGxlCiAqICRjb25maWcgPSBwb3N0Z3Jlc3FsX3RlbGVtZXRyeV9jb25maWcoCiAqICAgICB0ZWxlbWV0cnkocmVzb3VyY2UoWydzZXJ2aWNlLm5hbWUnID0+ICdteS1hcHAnXSkpLAogKiAgICAgbmV3IFN5c3RlbUNsb2NrKCksCiAqICk7CiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/client.php","start_line_in_file":260,"slug":"traceable-postgresql-client","name":"traceable_postgresql_client","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"client","type":[{"name":"Client","namespace":"Flow\\PostgreSql\\Client","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"telemetryConfig","type":[{"name":"PostgreSqlTelemetryConfig","namespace":"Flow\\PostgreSql\\Client\\Telemetry","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"TraceableClient","namespace":"Flow\\PostgreSql\\Client\\Telemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFdyYXAgYSBQb3N0Z3JlU1FMIGNsaWVudCB3aXRoIHRlbGVtZXRyeSBpbnN0cnVtZW50YXRpb24uCiAqCiAqIFJldHVybnMgYSBkZWNvcmF0b3IgdGhhdCBhZGRzIHNwYW5zLCBtZXRyaWNzLCBhbmQgbG9ncyB0byBhbGwKICogcXVlcnkgYW5kIHRyYW5zYWN0aW9uIG9wZXJhdGlvbnMgZm9sbG93aW5nIE9wZW5UZWxlbWV0cnkgY29udmVudGlvbnMuCiAqCiAqIEBwYXJhbSBDbGllbnRcQ2xpZW50ICRjbGllbnQgVGhlIFBvc3RncmVTUUwgY2xpZW50IHRvIGluc3RydW1lbnQKICogQHBhcmFtIFBvc3RncmVTcWxUZWxlbWV0cnlDb25maWcgJHRlbGVtZXRyeUNvbmZpZyBUZWxlbWV0cnkgY29uZmlndXJhdGlvbgogKgogKiBAZXhhbXBsZQogKiAkY2xpZW50ID0gcGdzcWxfY2xpZW50KHBnc3FsX2Nvbm5lY3Rpb24oJ2hvc3Q9bG9jYWxob3N0IGRibmFtZT1teWRiJykpOwogKgogKiAkdHJhY2VhYmxlQ2xpZW50ID0gdHJhY2VhYmxlX3Bvc3RncmVzcWxfY2xpZW50KAogKiAgICAgJGNsaWVudCwKICogICAgIHBvc3RncmVzcWxfdGVsZW1ldHJ5X2NvbmZpZygKICogICAgICAgICB0ZWxlbWV0cnkocmVzb3VyY2UoWydzZXJ2aWNlLm5hbWUnID0+ICdteS1hcHAnXSkpLAogKiAgICAgICAgIG5ldyBTeXN0ZW1DbG9jaygpLAogKiAgICAgICAgIHBvc3RncmVzcWxfdGVsZW1ldHJ5X29wdGlvbnMoCiAqICAgICAgICAgICAgIHRyYWNlUXVlcmllczogdHJ1ZSwKICogICAgICAgICAgICAgdHJhbnNhY3Rpb25TcGFuczogVHJhbnNhY3Rpb25TcGFuTW9kZTo6R1JPVVBFRCwKICogICAgICAgICAgICAgY29sbGVjdE1ldHJpY3M6IHRydWUsCiAqICAgICAgICAgICAgIGxvZ1F1ZXJpZXM6IHRydWUsCiAqICAgICAgICAgICAgIG1heFF1ZXJ5TGVuZ3RoOiA1MDAsCiAqICAgICAgICAgKSwKICogICAgICksCiAqICk7CiAqCiAqIC8vIEFsbCBvcGVyYXRpb25zIG5vdyB0cmFjZWQKICogJHRyYWNlYWJsZUNsaWVudC0+dHJhbnNhY3Rpb24oZnVuY3Rpb24gKENsaWVudCAkY2xpZW50KSB7CiAqICAgICAkdXNlciA9ICRjbGllbnQtPmZldGNoU2luZ2xlKCdTRUxFQ1QgKiBGUk9NIHVzZXJzIFdIRVJFIGlkID0gJDEnLCBbMTIzXSk7CiAqICAgICAkY2xpZW50LT5leGVjdXRlKCdVUERBVEUgdXNlcnMgU0VUIGxhc3RfbG9naW4gPSBOT1coKSBXSEVSRSBpZCA9ICQxJywgWzEyM10pOwogKiB9KTsKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/client.php","start_line_in_file":300,"slug":"constructor-mapper","name":"constructor_mapper","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"class","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":"ConstructorMapper","namespace":"Flow\\PostgreSql\\Client\\RowMapper","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUIG9mIG9iamVjdAogKgogKiBAcGFyYW0gY2xhc3Mtc3RyaW5nPFQ+ICRjbGFzcwogKgogKiBAcmV0dXJuIENvbnN0cnVjdG9yTWFwcGVyPFQ+CiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/client.php","start_line_in_file":315,"slug":"type-mapper","name":"type_mapper","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"type","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":"next","type":[{"name":"RowMapper","namespace":"Flow\\PostgreSql\\Client","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"TypeMapper","namespace":"Flow\\PostgreSql\\Client\\RowMapper","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUVHlwZQogKiBAdGVtcGxhdGUgVE91dAogKgogKiBAcGFyYW0gRmxvd1R5cGU8VFR5cGU+ICR0eXBlCiAqIEBwYXJhbSBudWxsfFJvd01hcHBlcjxUT3V0PiAkbmV4dAogKgogKiBAcmV0dXJuICgkbmV4dCBpcyBudWxsID8gVHlwZU1hcHBlcjxUVHlwZSwgVFR5cGU+IDogVHlwZU1hcHBlcjxUVHlwZSwgVE91dD4pCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/client.php","start_line_in_file":343,"slug":"static-factory-mapper","name":"static_factory_mapper","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"class","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":"method","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":"StaticFactoryMapper","namespace":"Flow\\PostgreSql\\Client\\RowMapper","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHJvdyBtYXBwZXIgYmFja2VkIGJ5IGEgcHVibGljIHN0YXRpYyBmYWN0b3J5IG1ldGhvZC4KICoKICogVGhlIGZhY3RvcnkgbWV0aG9kIG11c3QgYWNjZXB0IGEgc2luZ2xlIGFycmF5PHN0cmluZywgbWl4ZWQ+ICRyb3cgYW5kIHJldHVybgogKiBhbiBpbnN0YW5jZSBvZiB0aGUgdGFyZ2V0IGNsYXNzLiBJZiB5b3VyIGZhY3RvcnkgbmVlZHMgYWNjZXNzIHRvIHRoZSBtYXBwaW5nCiAqIENvbnRleHQgKHNxbC9wYXJhbWV0ZXJzL2NsaWVudC9jYXRhbG9nL3VzZXItZGF0YSksIGltcGxlbWVudCBSb3dNYXBwZXIgZGlyZWN0bHkuCiAqCiAqIEB0ZW1wbGF0ZSBUIG9mIG9iamVjdAogKgogKiBAcGFyYW0gY2xhc3Mtc3RyaW5nPFQ+ICRjbGFzcwogKiBAcGFyYW0gbm9uLWVtcHR5LXN0cmluZyAkbWV0aG9kCiAqCiAqIEByZXR1cm4gU3RhdGljRmFjdG9yeU1hcHBlcjxUPgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/client.php","start_line_in_file":372,"slug":"typed","name":"typed","namespace":"Flow\\PostgreSql\\DSL","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},{"name":"targetType","type":[{"name":"ValueType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"TypedValue","namespace":"Flow\\PostgreSql\\Client","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFdyYXAgYSB2YWx1ZSB3aXRoIGV4cGxpY2l0IFBvc3RncmVTUUwgdHlwZSBpbmZvcm1hdGlvbiBmb3IgcGFyYW1ldGVyIGJpbmRpbmcuCiAqCiAqIFVzZSB3aGVuIGF1dG8tZGV0ZWN0aW9uIGlzbid0IHN1ZmZpY2llbnQgb3Igd2hlbiB5b3UgbmVlZCB0byBzcGVjaWZ5CiAqIHRoZSBleGFjdCBQb3N0Z3JlU1FMIHR5cGUgKHNpbmNlIG9uZSBQSFAgdHlwZSBjYW4gbWFwIHRvIG11bHRpcGxlIFBvc3RncmVTUUwgdHlwZXMpOgogKiAtIGludCBjb3VsZCBiZSBJTlQyLCBJTlQ0LCBvciBJTlQ4CiAqIC0gc3RyaW5nIGNvdWxkIGJlIFRFWFQsIFZBUkNIQVIsIG9yIENIQVIKICogLSBhcnJheSBtdXN0IGFsd2F5cyB1c2UgdHlwZWQoKSBzaW5jZSBhdXRvLWRldGVjdGlvbiBjYW5ub3QgZGV0ZXJtaW5lIGVsZW1lbnQgdHlwZQogKiAtIERhdGVUaW1lSW50ZXJmYWNlIGNvdWxkIGJlIFRJTUVTVEFNUCBvciBUSU1FU1RBTVBUWgogKiAtIEpzb24gY291bGQgYmUgSlNPTiBvciBKU09OQgogKgogKiBAcGFyYW0gbWl4ZWQgJHZhbHVlIFRoZSB2YWx1ZSB0byBiaW5kCiAqIEBwYXJhbSBWYWx1ZVR5cGUgJHRhcmdldFR5cGUgVGhlIFBvc3RncmVTUUwgdHlwZSB0byBjb252ZXJ0IHRoZSB2YWx1ZSB0bwogKgogKiBAZXhhbXBsZQogKiAkY2xpZW50LT5mZXRjaCgKICogICAgICdTRUxFQ1QgKiBGUk9NIHVzZXJzIFdIRVJFIGlkID0gJDEgQU5EIHRhZ3MgPSAkMicsCiAqICAgICBbCiAqICAgICAgICAgdHlwZWQoJzU1MGU4NDAwLWUyOWItNDFkNC1hNzE2LTQ0NjY1NTQ0MDAwMCcsIFZhbHVlVHlwZTo6VVVJRCksCiAqICAgICAgICAgdHlwZWQoWyd0YWcxJywgJ3RhZzInXSwgVmFsdWVUeXBlOjpURVhUX0FSUkFZKSwKICogICAgIF0KICogKTsKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/client.php","start_line_in_file":386,"slug":"converted-parameters","name":"converted_parameters","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"values","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":"ConvertedParameters","namespace":"Flow\\PostgreSql\\Client","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFBhcmFtZXRlcnMgYWxyZWFkeSBpbiBQb3N0Z3JlU1FMJ3MgdGV4dCBmb3JtLCB3aGljaCBDbGllbnQ6OmV4ZWN1dGUoKSBzZW5kcyB3aXRob3V0IHJ1bm5pbmcgYSBjb252ZXJ0ZXIuCiAqCiAqIEBwYXJhbSBsaXN0PG51bGx8c3RyaW5nPiAkdmFsdWVzCiAqCiAqIEBleGFtcGxlCiAqICRjbGllbnQtPmV4ZWN1dGUoJ1VQREFURSB1c2VycyBTRVQgYWN0aXZlID0gJDEgV0hFUkUgaWQgPSAkMicsIGNvbnZlcnRlZF9wYXJhbWV0ZXJzKFsnZicsICcxJ10pKTsKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":126,"slug":"trace-id","name":"trace_id","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"hex","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"TraceId","namespace":"Flow\\Telemetry\\Context","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFRyYWNlSWQuCiAqCiAqIElmIGEgaGV4IHN0cmluZyBpcyBwcm92aWRlZCwgY3JlYXRlcyBhIFRyYWNlSWQgZnJvbSBpdC4KICogT3RoZXJ3aXNlLCBnZW5lcmF0ZXMgYSBuZXcgcmFuZG9tIFRyYWNlSWQuCiAqCiAqIEBwYXJhbSBudWxsfHN0cmluZyAkaGV4IE9wdGlvbmFsIDMyLWNoYXJhY3RlciBoZXhhZGVjaW1hbCBzdHJpbmcKICoKICogQHRocm93cyBcSW52YWxpZEFyZ3VtZW50RXhjZXB0aW9uIGlmIHRoZSBoZXggc3RyaW5nIGlzIGludmFsaWQKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":146,"slug":"span-id","name":"span_id","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"hex","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"SpanId","namespace":"Flow\\Telemetry\\Context","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFNwYW5JZC4KICoKICogSWYgYSBoZXggc3RyaW5nIGlzIHByb3ZpZGVkLCBjcmVhdGVzIGEgU3BhbklkIGZyb20gaXQuCiAqIE90aGVyd2lzZSwgZ2VuZXJhdGVzIGEgbmV3IHJhbmRvbSBTcGFuSWQuCiAqCiAqIEBwYXJhbSBudWxsfHN0cmluZyAkaGV4IE9wdGlvbmFsIDE2LWNoYXJhY3RlciBoZXhhZGVjaW1hbCBzdHJpbmcKICoKICogQHRocm93cyBcSW52YWxpZEFyZ3VtZW50RXhjZXB0aW9uIGlmIHRoZSBoZXggc3RyaW5nIGlzIGludmFsaWQKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":161,"slug":"baggage","name":"baggage","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"entries","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"Baggage","namespace":"Flow\\Telemetry\\Context","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEJhZ2dhZ2UuCiAqCiAqIEBwYXJhbSBhcnJheTxzdHJpbmcsIHN0cmluZz4gJGVudHJpZXMgSW5pdGlhbCBrZXktdmFsdWUgZW50cmllcwogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":175,"slug":"context","name":"context","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"baggage","type":[{"name":"Baggage","namespace":"Flow\\Telemetry\\Context","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Context","namespace":"Flow\\Telemetry\\Context","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHJvb3QgQ29udGV4dCAobm8gYWN0aXZlIHNwYW4pLgogKgogKiBBIHNwYW4gY3JlYXRlZCBpbiB0aGlzIGNvbnRleHQgYmVjb21lcyBhIG5ldyB0cmFjZSByb290LiBBdHRhY2ggYW4gYWN0aXZlIHNwYW4gd2l0aAogKiBDb250ZXh0Ojp3aXRoQWN0aXZlU3BhbigpIHRvIG1ha2Ugc3Vic2VxdWVudCBzcGFucyBpdHMgY2hpbGRyZW4uCiAqCiAqIEBwYXJhbSBudWxsfEJhZ2dhZ2UgJGJhZ2dhZ2UgT3B0aW9uYWwgQmFnZ2FnZSB0byB1c2UKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":189,"slug":"memory-context-storage","name":"memory_context_storage","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"context","type":[{"name":"Context","namespace":"Flow\\Telemetry\\Context","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"MemoryContextStorage","namespace":"Flow\\Telemetry\\Context","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIE1lbW9yeUNvbnRleHRTdG9yYWdlLgogKgogKiBJbi1tZW1vcnkgY29udGV4dCBzdG9yYWdlIGZvciBzdG9yaW5nIGFuZCByZXRyaWV2aW5nIHRoZSBjdXJyZW50IGNvbnRleHQuCiAqIEEgc2luZ2xlIGluc3RhbmNlIHNob3VsZCBiZSBzaGFyZWQgYWNyb3NzIGFsbCBwcm92aWRlcnMgd2l0aGluIGEgcmVxdWVzdCBsaWZlY3ljbGUuCiAqCiAqIEBwYXJhbSBudWxsfENvbnRleHQgJGNvbnRleHQgT3B0aW9uYWwgaW5pdGlhbCBjb250ZXh0CiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":200,"slug":"resource","name":"resource","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"attributes","type":[{"name":"Attributes","namespace":"Flow\\Telemetry","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"Resource","namespace":"Flow\\Telemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFJlc291cmNlLgogKgogKiBAcGFyYW0gYXJyYXk8c3RyaW5nLCBhcnJheTxhcnJheS1rZXksIG1peGVkPnxib29sfFxEYXRlVGltZUludGVyZmFjZXxmbG9hdHxpbnR8c3RyaW5nfFxUaHJvd2FibGU+fEF0dHJpYnV0ZXMgJGF0dHJpYnV0ZXMgUmVzb3VyY2UgYXR0cmlidXRlcwogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":213,"slug":"span-context","name":"span_context","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"traceId","type":[{"name":"TraceId","namespace":"Flow\\Telemetry\\Context","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"spanId","type":[{"name":"SpanId","namespace":"Flow\\Telemetry\\Context","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"parentSpanId","type":[{"name":"SpanId","namespace":"Flow\\Telemetry\\Context","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"SpanContext","namespace":"Flow\\Telemetry\\Tracer","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFNwYW5Db250ZXh0LgogKgogKiBAcGFyYW0gVHJhY2VJZCAkdHJhY2VJZCBUaGUgdHJhY2UgSUQKICogQHBhcmFtIFNwYW5JZCAkc3BhbklkIFRoZSBzcGFuIElECiAqIEBwYXJhbSBudWxsfFNwYW5JZCAkcGFyZW50U3BhbklkIE9wdGlvbmFsIHBhcmVudCBzcGFuIElECiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":226,"slug":"span-event","name":"span_event","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"name","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":"timestamp","type":[{"name":"DateTimeImmutable","namespace":"","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"attributes","type":[{"name":"Attributes","namespace":"Flow\\Telemetry","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"GenericEvent","namespace":"Flow\\Telemetry\\Tracer","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFNwYW5FdmVudCAoR2VuZXJpY0V2ZW50KSB3aXRoIGFuIGV4cGxpY2l0IHRpbWVzdGFtcC4KICoKICogQHBhcmFtIHN0cmluZyAkbmFtZSBFdmVudCBuYW1lCiAqIEBwYXJhbSBcRGF0ZVRpbWVJbW11dGFibGUgJHRpbWVzdGFtcCBFdmVudCB0aW1lc3RhbXAKICogQHBhcmFtIGFycmF5PHN0cmluZywgYXJyYXk8YXJyYXkta2V5LCBtaXhlZD58Ym9vbHxcRGF0ZVRpbWVJbnRlcmZhY2V8ZmxvYXR8aW50fHN0cmluZ3xcVGhyb3dhYmxlPnxBdHRyaWJ1dGVzICRhdHRyaWJ1dGVzIEV2ZW50IGF0dHJpYnV0ZXMKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":238,"slug":"span-link","name":"span_link","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"context","type":[{"name":"SpanContext","namespace":"Flow\\Telemetry\\Tracer","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"attributes","type":[{"name":"Attributes","namespace":"Flow\\Telemetry","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"SpanLink","namespace":"Flow\\Telemetry\\Tracer","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFNwYW5MaW5rLgogKgogKiBAcGFyYW0gU3BhbkNvbnRleHQgJGNvbnRleHQgVGhlIGxpbmtlZCBzcGFuIGNvbnRleHQKICogQHBhcmFtIGFycmF5PHN0cmluZywgYXJyYXk8YXJyYXkta2V5LCBtaXhlZD58Ym9vbHxcRGF0ZVRpbWVJbnRlcmZhY2V8ZmxvYXR8aW50fHN0cmluZ3xcVGhyb3dhYmxlPnxBdHRyaWJ1dGVzICRhdHRyaWJ1dGVzIExpbmsgYXR0cmlidXRlcwogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":254,"slug":"span-limits","name":"span_limits","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"attributeCountLimit","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"128"},{"name":"eventCountLimit","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"128"},{"name":"linkCountLimit","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"128"},{"name":"attributePerEventCountLimit","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"128"},{"name":"attributePerLinkCountLimit","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"128"},{"name":"attributeValueLengthLimit","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":"SpanLimits","namespace":"Flow\\Telemetry\\Tracer","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBTcGFuTGltaXRzIGNvbmZpZ3VyYXRpb24uCiAqCiAqIEBwYXJhbSBpbnQgJGF0dHJpYnV0ZUNvdW50TGltaXQgTWF4aW11bSBudW1iZXIgb2YgYXR0cmlidXRlcyBwZXIgc3BhbgogKiBAcGFyYW0gaW50ICRldmVudENvdW50TGltaXQgTWF4aW11bSBudW1iZXIgb2YgZXZlbnRzIHBlciBzcGFuCiAqIEBwYXJhbSBpbnQgJGxpbmtDb3VudExpbWl0IE1heGltdW0gbnVtYmVyIG9mIGxpbmtzIHBlciBzcGFuCiAqIEBwYXJhbSBpbnQgJGF0dHJpYnV0ZVBlckV2ZW50Q291bnRMaW1pdCBNYXhpbXVtIG51bWJlciBvZiBhdHRyaWJ1dGVzIHBlciBldmVudAogKiBAcGFyYW0gaW50ICRhdHRyaWJ1dGVQZXJMaW5rQ291bnRMaW1pdCBNYXhpbXVtIG51bWJlciBvZiBhdHRyaWJ1dGVzIHBlciBsaW5rCiAqIEBwYXJhbSBudWxsfGludCAkYXR0cmlidXRlVmFsdWVMZW5ndGhMaW1pdCBNYXhpbXVtIGxlbmd0aCBmb3Igc3RyaW5nIGF0dHJpYnV0ZSB2YWx1ZXMgKG51bGwgPSB1bmxpbWl0ZWQpCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":279,"slug":"log-record-limits","name":"log_record_limits","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"attributeCountLimit","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"128"},{"name":"attributeValueLengthLimit","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":"LogRecordLimits","namespace":"Flow\\Telemetry\\Logger","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBMb2dSZWNvcmRMaW1pdHMgY29uZmlndXJhdGlvbi4KICoKICogQHBhcmFtIGludCAkYXR0cmlidXRlQ291bnRMaW1pdCBNYXhpbXVtIG51bWJlciBvZiBhdHRyaWJ1dGVzIHBlciBsb2cgcmVjb3JkCiAqIEBwYXJhbSBudWxsfGludCAkYXR0cmlidXRlVmFsdWVMZW5ndGhMaW1pdCBNYXhpbXVtIGxlbmd0aCBmb3Igc3RyaW5nIGF0dHJpYnV0ZSB2YWx1ZXMgKG51bGwgPSB1bmxpbWl0ZWQpCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":290,"slug":"metric-limits","name":"metric_limits","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"cardinalityLimit","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"2000"}],"return_type":[{"name":"MetricLimits","namespace":"Flow\\Telemetry\\Meter","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBNZXRyaWNMaW1pdHMgY29uZmlndXJhdGlvbi4KICoKICogQHBhcmFtIGludCAkY2FyZGluYWxpdHlMaW1pdCBNYXhpbXVtIG51bWJlciBvZiB1bmlxdWUgYXR0cmlidXRlIGNvbWJpbmF0aW9ucyBwZXIgaW5zdHJ1bWVudAogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":301,"slug":"void-span-processor","name":"void_span_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"VoidSpanProcessor","namespace":"Flow\\Telemetry\\Provider\\Void","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFZvaWRTcGFuUHJvY2Vzc29yLgogKgogKiBOby1vcCBzcGFuIHByb2Nlc3NvciB0aGF0IGRpc2NhcmRzIGFsbCBkYXRhLgogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":312,"slug":"void-metric-processor","name":"void_metric_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"VoidMetricProcessor","namespace":"Flow\\Telemetry\\Provider\\Void","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFZvaWRNZXRyaWNQcm9jZXNzb3IuCiAqCiAqIE5vLW9wIG1ldHJpYyBwcm9jZXNzb3IgdGhhdCBkaXNjYXJkcyBhbGwgZGF0YS4KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":323,"slug":"void-log-processor","name":"void_log_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"VoidLogProcessor","namespace":"Flow\\Telemetry\\Provider\\Void","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFZvaWRMb2dQcm9jZXNzb3IuCiAqCiAqIE5vLW9wIGxvZyBwcm9jZXNzb3IgdGhhdCBkaXNjYXJkcyBhbGwgZGF0YS4KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":334,"slug":"void-exporter","name":"void_exporter","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"VoidExporter","namespace":"Flow\\Telemetry\\Provider\\Void","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFZvaWRFeHBvcnRlci4KICoKICogTm8tb3AgdW5pZmllZCBleHBvcnRlciB0aGF0IGRpc2NhcmRzIGxvZ3MsIG1ldHJpY3MsIGFuZCBzcGFucy4KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":348,"slug":"memory-exporter","name":"memory_exporter","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"maxEntriesPerSignal","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":"MemoryExporter","namespace":"Flow\\Telemetry\\Provider\\Memory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIE1lbW9yeUV4cG9ydGVyLgogKgogKiBVbmlmaWVkIGV4cG9ydGVyIHRoYXQgc3RvcmVzIGxvZ3MsIG1ldHJpY3MsIGFuZCBzcGFucyBpbiBtZW1vcnkgZm9yIGRpcmVjdCBhY2Nlc3MuCiAqIFVzZWZ1bCBmb3IgdGVzdGluZyBhbmQgaW5zcGVjdGlvbiB3aXRob3V0IHNlcmlhbGl6YXRpb24uCiAqCiAqIEBwYXJhbSBudWxsfGludCAkbWF4RW50cmllc1BlclNpZ25hbCBtYXhpbXVtIGVudHJpZXMgcmV0YWluZWQgcGVyIHNpZ25hbCB0eXBlOyBudWxsIGtlZXBzIGV2ZXJ5dGhpbmcKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":360,"slug":"memory-span-processor","name":"memory_span_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"exporter","type":[{"name":"Exporter","namespace":"Flow\\Telemetry\\Exporter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"errorHandler","type":[{"name":"ErrorHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\ErrorHandler\\ErrorLogHandler::..."}],"return_type":[{"name":"MemorySpanProcessor","namespace":"Flow\\Telemetry\\Provider\\Memory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIE1lbW9yeVNwYW5Qcm9jZXNzb3IuCiAqCiAqIEBwYXJhbSBFeHBvcnRlciAkZXhwb3J0ZXIgVGhlIGV4cG9ydGVyIHRvIHNlbmQgc3BhbnMgdG8KICogQHBhcmFtIEVycm9ySGFuZGxlciAkZXJyb3JIYW5kbGVyIEhhbmRsZXIgZm9yIFRocm93YWJsZXMgcmFpc2VkIGJ5IHRoZSBleHBvcnRlcgogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":374,"slug":"memory-metric-processor","name":"memory_metric_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"exporter","type":[{"name":"Exporter","namespace":"Flow\\Telemetry\\Exporter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"errorHandler","type":[{"name":"ErrorHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\ErrorHandler\\ErrorLogHandler::..."}],"return_type":[{"name":"MemoryMetricProcessor","namespace":"Flow\\Telemetry\\Provider\\Memory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIE1lbW9yeU1ldHJpY1Byb2Nlc3Nvci4KICoKICogQHBhcmFtIEV4cG9ydGVyICRleHBvcnRlciBUaGUgZXhwb3J0ZXIgdG8gc2VuZCBtZXRyaWNzIHRvCiAqIEBwYXJhbSBFcnJvckhhbmRsZXIgJGVycm9ySGFuZGxlciBIYW5kbGVyIGZvciBUaHJvd2FibGVzIHJhaXNlZCBieSB0aGUgZXhwb3J0ZXIKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":388,"slug":"memory-log-processor","name":"memory_log_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"exporter","type":[{"name":"Exporter","namespace":"Flow\\Telemetry\\Exporter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"errorHandler","type":[{"name":"ErrorHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\ErrorHandler\\ErrorLogHandler::..."}],"return_type":[{"name":"MemoryLogProcessor","namespace":"Flow\\Telemetry\\Provider\\Memory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIE1lbW9yeUxvZ1Byb2Nlc3Nvci4KICoKICogQHBhcmFtIEV4cG9ydGVyICRleHBvcnRlciBUaGUgZXhwb3J0ZXIgdG8gc2VuZCBsb2dzIHRvCiAqIEBwYXJhbSBFcnJvckhhbmRsZXIgJGVycm9ySGFuZGxlciBIYW5kbGVyIGZvciBUaHJvd2FibGVzIHJhaXNlZCBieSB0aGUgZXhwb3J0ZXIKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":406,"slug":"tracer-provider","name":"tracer_provider","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"processor","type":[{"name":"SpanProcessor","namespace":"Flow\\Telemetry\\Tracer","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"clock","type":[{"name":"ClockInterface","namespace":"Psr\\Clock","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"contextStorage","type":[{"name":"ContextStorage","namespace":"Flow\\Telemetry\\Context","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"sampler","type":[{"name":"Sampler","namespace":"Flow\\Telemetry\\Tracer\\Sampler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\Tracer\\Sampler\\ParentBasedSampler::..."},{"name":"limits","type":[{"name":"SpanLimits","namespace":"Flow\\Telemetry\\Tracer","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\Tracer\\SpanLimits::..."},{"name":"errorHandler","type":[{"name":"ErrorHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\ErrorHandler\\ErrorLogHandler::..."}],"return_type":[{"name":"TracerProvider","namespace":"Flow\\Telemetry\\Tracer","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFRyYWNlclByb3ZpZGVyLgogKgogKiBAcGFyYW0gU3BhblByb2Nlc3NvciAkcHJvY2Vzc29yIFRoZSBwcm9jZXNzb3IgZm9yIHNwYW5zCiAqIEBwYXJhbSBDbG9ja0ludGVyZmFjZSAkY2xvY2sgVGhlIGNsb2NrIGZvciB0aW1lc3RhbXBzCiAqIEBwYXJhbSBDb250ZXh0U3RvcmFnZSAkY29udGV4dFN0b3JhZ2UgU3RvcmFnZSBmb3IgY29udGV4dCBwcm9wYWdhdGlvbgogKiBAcGFyYW0gU2FtcGxlciAkc2FtcGxlciBTYW1wbGluZyBzdHJhdGVneSBmb3Igc3BhbnMKICogQHBhcmFtIFNwYW5MaW1pdHMgJGxpbWl0cyBMaW1pdHMgZm9yIHNwYW4gYXR0cmlidXRlcywgZXZlbnRzLCBhbmQgbGlua3MKICogQHBhcmFtIEVycm9ySGFuZGxlciAkZXJyb3JIYW5kbGVyIEhhbmRsZXIgZm9yIHJ1bnRpbWUgVGhyb3dhYmxlcyByYWlzZWQgYnkgdGhlIHByb2Nlc3NvcgogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":427,"slug":"logger-provider","name":"logger_provider","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"processor","type":[{"name":"LogProcessor","namespace":"Flow\\Telemetry\\Logger","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"clock","type":[{"name":"ClockInterface","namespace":"Psr\\Clock","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"contextStorage","type":[{"name":"ContextStorage","namespace":"Flow\\Telemetry\\Context","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"limits","type":[{"name":"LogRecordLimits","namespace":"Flow\\Telemetry\\Logger","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\Logger\\LogRecordLimits::..."},{"name":"errorHandler","type":[{"name":"ErrorHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\ErrorHandler\\ErrorLogHandler::..."}],"return_type":[{"name":"LoggerProvider","namespace":"Flow\\Telemetry\\Logger","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIExvZ2dlclByb3ZpZGVyLgogKgogKiBAcGFyYW0gTG9nUHJvY2Vzc29yICRwcm9jZXNzb3IgVGhlIHByb2Nlc3NvciBmb3IgbG9ncwogKiBAcGFyYW0gQ2xvY2tJbnRlcmZhY2UgJGNsb2NrIFRoZSBjbG9jayBmb3IgdGltZXN0YW1wcwogKiBAcGFyYW0gQ29udGV4dFN0b3JhZ2UgJGNvbnRleHRTdG9yYWdlIFN0b3JhZ2UgZm9yIHNwYW4gY29ycmVsYXRpb24KICogQHBhcmFtIExvZ1JlY29yZExpbWl0cyAkbGltaXRzIExpbWl0cyBmb3IgbG9nIHJlY29yZCBhdHRyaWJ1dGVzCiAqIEBwYXJhbSBFcnJvckhhbmRsZXIgJGVycm9ySGFuZGxlciBIYW5kbGVyIGZvciBydW50aW1lIFRocm93YWJsZXMgcmFpc2VkIGJ5IHRoZSBwcm9jZXNzb3IKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":448,"slug":"meter-provider","name":"meter_provider","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"processor","type":[{"name":"MetricProcessor","namespace":"Flow\\Telemetry\\Meter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"clock","type":[{"name":"ClockInterface","namespace":"Psr\\Clock","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"temporality","type":[{"name":"AggregationTemporality","namespace":"Flow\\Telemetry\\Meter","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\Meter\\AggregationTemporality::..."},{"name":"exemplarFilter","type":[{"name":"ExemplarFilter","namespace":"Flow\\Telemetry\\Meter\\Exemplar","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\Meter\\Exemplar\\TraceBasedExemplarFilter::..."},{"name":"limits","type":[{"name":"MetricLimits","namespace":"Flow\\Telemetry\\Meter","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\Meter\\MetricLimits::..."},{"name":"errorHandler","type":[{"name":"ErrorHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\ErrorHandler\\ErrorLogHandler::..."}],"return_type":[{"name":"MeterProvider","namespace":"Flow\\Telemetry\\Meter","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIE1ldGVyUHJvdmlkZXIuCiAqCiAqIEBwYXJhbSBNZXRyaWNQcm9jZXNzb3IgJHByb2Nlc3NvciBUaGUgcHJvY2Vzc29yIGZvciBtZXRyaWNzCiAqIEBwYXJhbSBDbG9ja0ludGVyZmFjZSAkY2xvY2sgVGhlIGNsb2NrIGZvciB0aW1lc3RhbXBzCiAqIEBwYXJhbSBBZ2dyZWdhdGlvblRlbXBvcmFsaXR5ICR0ZW1wb3JhbGl0eSBBZ2dyZWdhdGlvbiB0ZW1wb3JhbGl0eSBmb3IgbWV0cmljcwogKiBAcGFyYW0gRXhlbXBsYXJGaWx0ZXIgJGV4ZW1wbGFyRmlsdGVyIEZpbHRlciBmb3IgZXhlbXBsYXIgc2FtcGxpbmcgKGRlZmF1bHQ6IFRyYWNlQmFzZWRFeGVtcGxhckZpbHRlcikKICogQHBhcmFtIE1ldHJpY0xpbWl0cyAkbGltaXRzIENhcmRpbmFsaXR5IGxpbWl0cyBmb3IgbWV0cmljIGluc3RydW1lbnRzCiAqIEBwYXJhbSBFcnJvckhhbmRsZXIgJGVycm9ySGFuZGxlciBIYW5kbGVyIGZvciBydW50aW1lIFRocm93YWJsZXMgcmFpc2VkIGJ5IHRoZSBwcm9jZXNzb3IKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":471,"slug":"telemetry","name":"telemetry","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"resource","type":[{"name":"Resource","namespace":"Flow\\Telemetry","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"tracerProvider","type":[{"name":"TracerProvider","namespace":"Flow\\Telemetry\\Tracer","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"meterProvider","type":[{"name":"MeterProvider","namespace":"Flow\\Telemetry\\Meter","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"loggerProvider","type":[{"name":"LoggerProvider","namespace":"Flow\\Telemetry\\Logger","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"errorHandler","type":[{"name":"ErrorHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\ErrorHandler\\ErrorLogHandler::..."}],"return_type":[{"name":"Telemetry","namespace":"Flow\\Telemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIG5ldyBUZWxlbWV0cnkgaW5zdGFuY2Ugd2l0aCB0aGUgZ2l2ZW4gcHJvdmlkZXJzLgogKgogKiBJZiBwcm92aWRlcnMgYXJlIG5vdCBzcGVjaWZpZWQsIHZvaWQgcHJvdmlkZXJzIChuby1vcCkgYXJlIHVzZWQuCiAqCiAqIEBwYXJhbSBcRmxvd1xUZWxlbWV0cnlcUmVzb3VyY2UgJHJlc291cmNlIFRoZSByZXNvdXJjZSBkZXNjcmliaW5nIHRoZSBlbnRpdHkgcHJvZHVjaW5nIHRlbGVtZXRyeQogKiBAcGFyYW0gbnVsbHxUcmFjZXJQcm92aWRlciAkdHJhY2VyUHJvdmlkZXIgVGhlIHRyYWNlciBwcm92aWRlciAobnVsbCBmb3Igdm9pZC9kaXNhYmxlZCkKICogQHBhcmFtIG51bGx8TWV0ZXJQcm92aWRlciAkbWV0ZXJQcm92aWRlciBUaGUgbWV0ZXIgcHJvdmlkZXIgKG51bGwgZm9yIHZvaWQvZGlzYWJsZWQpCiAqIEBwYXJhbSBudWxsfExvZ2dlclByb3ZpZGVyICRsb2dnZXJQcm92aWRlciBUaGUgbG9nZ2VyIHByb3ZpZGVyIChudWxsIGZvciB2b2lkL2Rpc2FibGVkKQogKiBAcGFyYW0gRXJyb3JIYW5kbGVyICRlcnJvckhhbmRsZXIgSGFuZGxlciBwcm9wYWdhdGVkIHRvIGRlZmF1bHQgdm9pZCBwcm92aWRlcnMgd2hlbiBleHBsaWNpdCBvbmVzIGFyZSBub3Qgc3VwcGxpZWQKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":507,"slug":"instrumentation-scope","name":"instrumentation_scope","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"name","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":"version","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'unknown'"},{"name":"schemaUrl","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":"attributes","type":[{"name":"Attributes","namespace":"Flow\\Telemetry","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\Attributes::..."}],"return_type":[{"name":"InstrumentationScope","namespace":"Flow\\Telemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBJbnN0cnVtZW50YXRpb25TY29wZS4KICoKICogQHBhcmFtIHN0cmluZyAkbmFtZSBUaGUgaW5zdHJ1bWVudGF0aW9uIHNjb3BlIG5hbWUKICogQHBhcmFtIHN0cmluZyAkdmVyc2lvbiBUaGUgaW5zdHJ1bWVudGF0aW9uIHNjb3BlIHZlcnNpb24KICogQHBhcmFtIG51bGx8c3RyaW5nICRzY2hlbWFVcmwgT3B0aW9uYWwgc2NoZW1hIFVSTAogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":524,"slug":"batching-span-processor","name":"batching_span_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"exporter","type":[{"name":"Exporter","namespace":"Flow\\Telemetry\\Exporter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"batchSize","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"512"},{"name":"errorHandler","type":[{"name":"ErrorHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\ErrorHandler\\ErrorLogHandler::..."}],"return_type":[{"name":"BatchingSpanProcessor","namespace":"Flow\\Telemetry\\Tracer\\Processor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEJhdGNoaW5nU3BhblByb2Nlc3Nvci4KICoKICogQHBhcmFtIEV4cG9ydGVyICRleHBvcnRlciBUaGUgZXhwb3J0ZXIgdG8gc2VuZCBzcGFucyB0bwogKiBAcGFyYW0gaW50ICRiYXRjaFNpemUgTnVtYmVyIG9mIHNwYW5zIHRvIGNvbGxlY3QgYmVmb3JlIGV4cG9ydGluZyAoZGVmYXVsdCA1MTIpCiAqIEBwYXJhbSBFcnJvckhhbmRsZXIgJGVycm9ySGFuZGxlciBIYW5kbGVyIGZvciBUaHJvd2FibGVzIHJhaXNlZCBieSB0aGUgZXhwb3J0ZXIKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":539,"slug":"pass-through-span-processor","name":"pass_through_span_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"exporter","type":[{"name":"Exporter","namespace":"Flow\\Telemetry\\Exporter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"errorHandler","type":[{"name":"ErrorHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\ErrorHandler\\ErrorLogHandler::..."}],"return_type":[{"name":"PassThroughSpanProcessor","namespace":"Flow\\Telemetry\\Tracer\\Processor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBhc3NUaHJvdWdoU3BhblByb2Nlc3Nvci4KICoKICogQHBhcmFtIEV4cG9ydGVyICRleHBvcnRlciBUaGUgZXhwb3J0ZXIgdG8gc2VuZCBzcGFucyB0bwogKiBAcGFyYW0gRXJyb3JIYW5kbGVyICRlcnJvckhhbmRsZXIgSGFuZGxlciBmb3IgVGhyb3dhYmxlcyByYWlzZWQgYnkgdGhlIGV4cG9ydGVyCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":554,"slug":"batching-metric-processor","name":"batching_metric_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"exporter","type":[{"name":"Exporter","namespace":"Flow\\Telemetry\\Exporter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"batchSize","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"512"},{"name":"errorHandler","type":[{"name":"ErrorHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\ErrorHandler\\ErrorLogHandler::..."}],"return_type":[{"name":"BatchingMetricProcessor","namespace":"Flow\\Telemetry\\Meter\\Processor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEJhdGNoaW5nTWV0cmljUHJvY2Vzc29yLgogKgogKiBAcGFyYW0gRXhwb3J0ZXIgJGV4cG9ydGVyIFRoZSBleHBvcnRlciB0byBzZW5kIG1ldHJpY3MgdG8KICogQHBhcmFtIGludCAkYmF0Y2hTaXplIE51bWJlciBvZiBtZXRyaWNzIHRvIGNvbGxlY3QgYmVmb3JlIGV4cG9ydGluZyAoZGVmYXVsdCA1MTIpCiAqIEBwYXJhbSBFcnJvckhhbmRsZXIgJGVycm9ySGFuZGxlciBIYW5kbGVyIGZvciBUaHJvd2FibGVzIHJhaXNlZCBieSB0aGUgZXhwb3J0ZXIKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":569,"slug":"pass-through-metric-processor","name":"pass_through_metric_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"exporter","type":[{"name":"Exporter","namespace":"Flow\\Telemetry\\Exporter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"errorHandler","type":[{"name":"ErrorHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\ErrorHandler\\ErrorLogHandler::..."}],"return_type":[{"name":"PassThroughMetricProcessor","namespace":"Flow\\Telemetry\\Meter\\Processor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBhc3NUaHJvdWdoTWV0cmljUHJvY2Vzc29yLgogKgogKiBAcGFyYW0gRXhwb3J0ZXIgJGV4cG9ydGVyIFRoZSBleHBvcnRlciB0byBzZW5kIG1ldHJpY3MgdG8KICogQHBhcmFtIEVycm9ySGFuZGxlciAkZXJyb3JIYW5kbGVyIEhhbmRsZXIgZm9yIFRocm93YWJsZXMgcmFpc2VkIGJ5IHRoZSBleHBvcnRlcgogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":584,"slug":"batching-log-processor","name":"batching_log_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"exporter","type":[{"name":"Exporter","namespace":"Flow\\Telemetry\\Exporter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"batchSize","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"512"},{"name":"errorHandler","type":[{"name":"ErrorHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\ErrorHandler\\ErrorLogHandler::..."}],"return_type":[{"name":"BatchingLogProcessor","namespace":"Flow\\Telemetry\\Logger\\Processor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEJhdGNoaW5nTG9nUHJvY2Vzc29yLgogKgogKiBAcGFyYW0gRXhwb3J0ZXIgJGV4cG9ydGVyIFRoZSBleHBvcnRlciB0byBzZW5kIGxvZ3MgdG8KICogQHBhcmFtIGludCAkYmF0Y2hTaXplIE51bWJlciBvZiBsb2dzIHRvIGNvbGxlY3QgYmVmb3JlIGV4cG9ydGluZyAoZGVmYXVsdCA1MTIpCiAqIEBwYXJhbSBFcnJvckhhbmRsZXIgJGVycm9ySGFuZGxlciBIYW5kbGVyIGZvciBUaHJvd2FibGVzIHJhaXNlZCBieSB0aGUgZXhwb3J0ZXIKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":599,"slug":"pass-through-log-processor","name":"pass_through_log_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"exporter","type":[{"name":"Exporter","namespace":"Flow\\Telemetry\\Exporter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"errorHandler","type":[{"name":"ErrorHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\ErrorHandler\\ErrorLogHandler::..."}],"return_type":[{"name":"PassThroughLogProcessor","namespace":"Flow\\Telemetry\\Logger\\Processor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBhc3NUaHJvdWdoTG9nUHJvY2Vzc29yLgogKgogKiBAcGFyYW0gRXhwb3J0ZXIgJGV4cG9ydGVyIFRoZSBleHBvcnRlciB0byBzZW5kIGxvZ3MgdG8KICogQHBhcmFtIEVycm9ySGFuZGxlciAkZXJyb3JIYW5kbGVyIEhhbmRsZXIgZm9yIFRocm93YWJsZXMgcmFpc2VkIGJ5IHRoZSBleHBvcnRlcgogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":614,"slug":"pipeline-log-processor","name":"pipeline_log_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"middleware","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":"sink","type":[{"name":"LogSink","namespace":"Flow\\Telemetry\\Logger","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"PipelineLogProcessor","namespace":"Flow\\Telemetry\\Logger\\Processor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBpcGVsaW5lTG9nUHJvY2Vzc29yOiBydW4gZWFjaCBsb2cgZW50cnkgdGhyb3VnaCBhbiBvcmRlcmVkIGNoYWluIG9mCiAqIG1pZGRsZXdhcmUsIHRoZW4gZm9yd2FyZCB0aGUgc3Vydml2b3JzIHRvIGEgc2luZ2xlIHNpbmsuCiAqCiAqIEBwYXJhbSBsaXN0PExvZ01pZGRsZXdhcmU+ICRtaWRkbGV3YXJlIHJ1biBpbiBvcmRlcjsgdGhlIGZpcnN0IHRvIGRyb3AgYW4gZW50cnkgc2hvcnQtY2lyY3VpdHMgdGhlIHJlc3QKICogQHBhcmFtIExvZ1NpbmsgJHNpbmsgdGhlIHRlcm1pbmFsIHByb2Nlc3NvciB0aGF0IGV4cG9ydHMgc3Vydml2aW5nIGVudHJpZXMKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":626,"slug":"enriching-log-middleware","name":"enriching_log_middleware","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"attributes","type":[{"name":"Attributes","namespace":"Flow\\Telemetry","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":"EnrichingLogMiddleware","namespace":"Flow\\Telemetry\\Logger\\Middleware","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBFbnJpY2hpbmdMb2dNaWRkbGV3YXJlIHRoYXQgbWVyZ2VzIGRlZmF1bHQgYXR0cmlidXRlcyBpbnRvIGV2ZXJ5IGxvZwogKiBlbnRyeS4gQXR0cmlidXRlcyBzZXQgYXQgdGhlIGNhbGwgc2l0ZSB3aW4gb3ZlciB0aGVzZSBkZWZhdWx0cy4KICoKICogQHBhcmFtIGFycmF5PHN0cmluZywgYXJyYXk8YXJyYXkta2V5LCBtaXhlZD58Ym9vbHxcRGF0ZVRpbWVJbnRlcmZhY2V8ZmxvYXR8aW50fHN0cmluZ3xcVGhyb3dhYmxlPnxBdHRyaWJ1dGVzICRhdHRyaWJ1dGVzCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":637,"slug":"attribute-filtering-log-middleware","name":"attribute_filtering_log_middleware","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"filter","type":[{"name":"AttributeFilter","namespace":"Flow\\Telemetry\\Filter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"AttributeFilteringLogMiddleware","namespace":"Flow\\Telemetry\\Logger\\Middleware","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBBdHRyaWJ1dGVGaWx0ZXJpbmdMb2dNaWRkbGV3YXJlIHRoYXQgZHJvcHMgbG9nIGVudHJpZXMgbWF0Y2hpbmcgdGhlIGZpbHRlci4KICoKICogQHBhcmFtIEF0dHJpYnV0ZUZpbHRlciAkZmlsdGVyIFRoZSBhdHRyaWJ1dGUgZmlsdGVyIHRvIGFwcGx5CiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":648,"slug":"severity-filtering-log-middleware","name":"severity_filtering_log_middleware","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"minimumSeverity","type":[{"name":"Severity","namespace":"Flow\\Telemetry\\Logger","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\Logger\\Severity::..."}],"return_type":[{"name":"SeverityFilteringLogMiddleware","namespace":"Flow\\Telemetry\\Logger\\Middleware","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFNldmVyaXR5RmlsdGVyaW5nTG9nTWlkZGxld2FyZSB0aGF0IGRyb3BzIGxvZyBlbnRyaWVzIGJlbG93IGEgbWluaW11bSBzZXZlcml0eS4KICoKICogQHBhcmFtIFNldmVyaXR5ICRtaW5pbXVtU2V2ZXJpdHkgTWluaW11bSBzZXZlcml0eSBsZXZlbCAoZGVmYXVsdDogSU5GTykKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":662,"slug":"attribute-rule","name":"attribute_rule","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"path","type":[{"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":"mode","type":[{"name":"MatchMode","namespace":"Flow\\Telemetry\\Filter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"expected","type":[{"name":"DateTimeInterface","namespace":"","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":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"caseSensitive","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":"AttributeRule","namespace":"Flow\\Telemetry\\Filter","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHNpbmdsZSBhdHRyaWJ1dGUtbWF0Y2hpbmcgcnVsZSBmb3IgYW4gQXR0cmlidXRlRmlsdGVyLgogKgogKiBAcGFyYW0gYXJyYXk8c3RyaW5nPnxzdHJpbmcgJHBhdGggYXR0cmlidXRlIHBhdGg6IGEgdG9wLWxldmVsIGtleSwgb3Igc2VnbWVudHMgZGVzY2VuZGluZyBpbnRvIG5lc3RlZCBhcnJheSB2YWx1ZXMKICogQHBhcmFtIE1hdGNoTW9kZSAkbW9kZSBjb21wYXJpc29uIGFwcGxpZWQgYmV0d2VlbiB0aGUgdmFsdWUgYXQgdGhlIHBhdGggYW5kIHRoZSBleHBlY3RlZCB2YWx1ZQogKiBAcGFyYW0gYm9vbHxEYXRlVGltZUludGVyZmFjZXxmbG9hdHxpbnR8c3RyaW5nICRleHBlY3RlZCBleHBlY3RlZCB2YWx1ZSAobXVzdCBiZSBhIHN0cmluZyBmb3IgdGhlIHBhdHRlcm4gbW9kZXMpCiAqIEBwYXJhbSBib29sICRjYXNlU2Vuc2l0aXZlIGFwcGxpZXMgdG8gdGhlIHN1YnN0cmluZyBtb2RlcyBvbmx5IChTVEFSVFNfV0lUSCwgRU5EU19XSVRILCBDT05UQUlOUykKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":675,"slug":"all","name":"all","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"matchers","type":[{"name":"Matcher","namespace":"Flow\\Telemetry\\Filter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"All","namespace":"Flow\\Telemetry\\Filter","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENvbWJpbmUgbWF0Y2hlcnMgc28gdGhhdCBldmVyeSBvbmUgbXVzdCBtYXRjaCAobG9naWNhbCBBTkQpLgogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":684,"slug":"any","name":"any","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"matchers","type":[{"name":"Matcher","namespace":"Flow\\Telemetry\\Filter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"Any","namespace":"Flow\\Telemetry\\Filter","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENvbWJpbmUgbWF0Y2hlcnMgc28gdGhhdCBhdCBsZWFzdCBvbmUgbXVzdCBtYXRjaCAobG9naWNhbCBPUikuCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":693,"slug":"not","name":"not","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"matcher","type":[{"name":"Matcher","namespace":"Flow\\Telemetry\\Filter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Not","namespace":"Flow\\Telemetry\\Filter","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIE5lZ2F0ZSBhIG1hdGNoZXIgKGxvZ2ljYWwgTk9UKS4KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":712,"slug":"attribute-filter","name":"attribute_filter","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"matcher","type":[{"name":"Matcher","namespace":"Flow\\Telemetry\\Filter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"exclude","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"sources","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[...]"},{"name":"cacheDir","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":"cacheDirPermissions","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"448"}],"return_type":[{"name":"AttributeFilter","namespace":"Flow\\Telemetry\\Filter","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBBdHRyaWJ1dGVGaWx0ZXIgZnJvbSBhIG1hdGNoZXIuCiAqCiAqIEBwYXJhbSBNYXRjaGVyICRtYXRjaGVyIHRoZSBtYXRjaGVyIHRvIGV2YWx1YXRlIGFnYWluc3QgYSBzaWduYWwncyBhdHRyaWJ1dGVzIChjb21wb3NlIHdpdGggYWxsKCksIGFueSgpLCBub3QoKSkKICogQHBhcmFtIGJvb2wgJGV4Y2x1ZGUgd2hlbiB0cnVlIChkZWZhdWx0KSBhIG1hdGNoIGRyb3BzIHRoZSBzaWduYWw7IHdoZW4gZmFsc2Ugb25seSBtYXRjaGluZyBzaWduYWxzIGFyZSBrZXB0CiAqIEBwYXJhbSBsaXN0PEF0dHJpYnV0ZVNvdXJjZT4gJHNvdXJjZXMgd2hpY2ggYXR0cmlidXRlIHNldHMgdG8gaW5zcGVjdCAoc2lnbmFsLCByZXNvdXJjZSBhbmQvb3Igc2NvcGUpOyB0aGUgbWF0Y2hlciBpcwogKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9SLWNvbWJpbmVkIGFjcm9zcyB0aGVtLCBkZWZhdWx0aW5nIHRvIHRoZSBzaWduYWwncyBvd24gYXR0cmlidXRlcwogKiBAcGFyYW0gbnVsbHxzdHJpbmcgJGNhY2hlRGlyIGRpcmVjdG9yeSBmb3IgdGhlIGdlbmVyYXRlZCBtYXRjaGVyIGZpbGUgKGRlZmF1bHRzIHRvIHRoZSBzeXN0ZW0gdGVtcCBkaXJlY3RvcnkpLiBJdCBpcwogKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGByZXF1aXJlYGQsIHNvIGl0IE1VU1QgYmUgdHJ1c3RlZCAtIG5vdCB3cml0YWJsZSBieSB1bnRydXN0ZWQgdXNlcnMuIFByZWZlciBhbgogKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGxpY2F0aW9uLXByaXZhdGUgZGlyZWN0b3J5IG92ZXIgdGhlIHNoYXJlZCBzeXN0ZW0gdGVtcCBpbiBtdWx0aS10ZW5hbnQgZW52aXJvbm1lbnRzLgogKiBAcGFyYW0gaW50ICRjYWNoZURpclBlcm1pc3Npb25zIG1vZGUgYXBwbGllZCB3aGVuIHRoZSBjYWNoZSBkaXJlY3RvcnkgaXMgY3JlYXRlZCAob2N0YWwsIHN1YmplY3QgdG8gdW1hc2s7IGRlZmF1bHRzCiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG8gMDcwMCAtIG93bmVyIG9ubHksIHNpbmNlIHRoZSBkaXJlY3RvcnkgaG9sZHMgYHJlcXVpcmVgZCBQSFApCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":729,"slug":"attribute-filtering-metric-processor","name":"attribute_filtering_metric_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"processor","type":[{"name":"MetricProcessor","namespace":"Flow\\Telemetry\\Meter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"filter","type":[{"name":"AttributeFilter","namespace":"Flow\\Telemetry\\Filter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"AttributeFilteringMetricProcessor","namespace":"Flow\\Telemetry\\Meter\\Processor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBBdHRyaWJ1dGVGaWx0ZXJpbmdNZXRyaWNQcm9jZXNzb3IuCiAqCiAqIEBwYXJhbSBNZXRyaWNQcm9jZXNzb3IgJHByb2Nlc3NvciBUaGUgcHJvY2Vzc29yIHRvIHdyYXAKICogQHBhcmFtIEF0dHJpYnV0ZUZpbHRlciAkZmlsdGVyIFRoZSBhdHRyaWJ1dGUgZmlsdGVyIHRvIGFwcGx5CiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":743,"slug":"attribute-filtering-span-processor","name":"attribute_filtering_span_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"processor","type":[{"name":"SpanProcessor","namespace":"Flow\\Telemetry\\Tracer","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"filter","type":[{"name":"AttributeFilter","namespace":"Flow\\Telemetry\\Filter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"AttributeFilteringSpanProcessor","namespace":"Flow\\Telemetry\\Tracer\\Processor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBBdHRyaWJ1dGVGaWx0ZXJpbmdTcGFuUHJvY2Vzc29yLgogKgogKiBAcGFyYW0gU3BhblByb2Nlc3NvciAkcHJvY2Vzc29yIFRoZSBwcm9jZXNzb3IgdG8gd3JhcAogKiBAcGFyYW0gQXR0cmlidXRlRmlsdGVyICRmaWx0ZXIgVGhlIGF0dHJpYnV0ZSBmaWx0ZXIgdG8gYXBwbHkKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":762,"slug":"console-exporter","name":"console_exporter","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"colors","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"maxLogBodyLength","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"100"},{"name":"logOptions","type":[{"name":"ConsoleLogOptions","namespace":"Flow\\Telemetry\\Provider\\Console","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\Provider\\Console\\ConsoleLogOptions::..."},{"name":"metricOptions","type":[{"name":"ConsoleMetricOptions","namespace":"Flow\\Telemetry\\Provider\\Console","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\Provider\\Console\\ConsoleMetricOptions::..."},{"name":"spanOptions","type":[{"name":"ConsoleSpanOptions","namespace":"Flow\\Telemetry\\Provider\\Console","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\Provider\\Console\\ConsoleSpanOptions::..."}],"return_type":[{"name":"ConsoleExporter","namespace":"Flow\\Telemetry\\Provider\\Console","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHVuaWZpZWQgQ29uc29sZUV4cG9ydGVyIGZvciBsb2dzLCBtZXRyaWNzLCBhbmQgc3BhbnMuCiAqCiAqIE91dHB1dHMgdGVsZW1ldHJ5IHRvIHRoZSBjb25zb2xlIHdpdGggQVNDSUkgdGFibGUgZm9ybWF0dGluZyBhbmQgb3B0aW9uYWwgQU5TSSBjb2xvcnMuCiAqCiAqIEBwYXJhbSBib29sICRjb2xvcnMgV2hldGhlciB0byB1c2UgQU5TSSBjb2xvcnMgKGRlZmF1bHQ6IHRydWUpCiAqIEBwYXJhbSBudWxsfGludCAkbWF4TG9nQm9keUxlbmd0aCBNYXhpbXVtIGxlbmd0aCBmb3IgbG9nIGJvZHkrYXR0cmlidXRlcyBjb2x1bW4gKG51bGwgPSBubyBsaW1pdCkKICogQHBhcmFtIENvbnNvbGVMb2dPcHRpb25zICRsb2dPcHRpb25zIERpc3BsYXkgb3B0aW9ucyBmb3IgbG9nIHJlY29yZHMKICogQHBhcmFtIENvbnNvbGVNZXRyaWNPcHRpb25zICRtZXRyaWNPcHRpb25zIERpc3BsYXkgb3B0aW9ucyBmb3IgbWV0cmljcwogKiBAcGFyYW0gQ29uc29sZVNwYW5PcHRpb25zICRzcGFuT3B0aW9ucyBEaXNwbGF5IG9wdGlvbnMgZm9yIHNwYW5zCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":776,"slug":"console-span-options","name":"console_span_options","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"ConsoleSpanOptions","namespace":"Flow\\Telemetry\\Provider\\Console","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBDb25zb2xlU3Bhbk9wdGlvbnMgd2l0aCBhbGwgZGlzcGxheSBvcHRpb25zIGVuYWJsZWQgKGRlZmF1bHQgYmVoYXZpb3IpLgogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":785,"slug":"console-span-options-minimal","name":"console_span_options_minimal","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"ConsoleSpanOptions","namespace":"Flow\\Telemetry\\Provider\\Console","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBDb25zb2xlU3Bhbk9wdGlvbnMgd2l0aCBtaW5pbWFsIGRpc3BsYXkgKGxlZ2FjeSBjb21wYWN0IGZvcm1hdCkuCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":794,"slug":"console-log-options","name":"console_log_options","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"ConsoleLogOptions","namespace":"Flow\\Telemetry\\Provider\\Console","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBDb25zb2xlTG9nT3B0aW9ucyB3aXRoIGFsbCBkaXNwbGF5IG9wdGlvbnMgZW5hYmxlZCAoZGVmYXVsdCBiZWhhdmlvcikuCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":803,"slug":"console-log-options-minimal","name":"console_log_options_minimal","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"ConsoleLogOptions","namespace":"Flow\\Telemetry\\Provider\\Console","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBDb25zb2xlTG9nT3B0aW9ucyB3aXRoIG1pbmltYWwgZGlzcGxheSAobGVnYWN5IGNvbXBhY3QgZm9ybWF0KS4KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":812,"slug":"console-metric-options","name":"console_metric_options","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"ConsoleMetricOptions","namespace":"Flow\\Telemetry\\Provider\\Console","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBDb25zb2xlTWV0cmljT3B0aW9ucyB3aXRoIGFsbCBkaXNwbGF5IG9wdGlvbnMgZW5hYmxlZCAoZGVmYXVsdCBiZWhhdmlvcikuCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":821,"slug":"console-metric-options-minimal","name":"console_metric_options_minimal","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"ConsoleMetricOptions","namespace":"Flow\\Telemetry\\Provider\\Console","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBDb25zb2xlTWV0cmljT3B0aW9ucyB3aXRoIG1pbmltYWwgZGlzcGxheSAobGVnYWN5IGNvbXBhY3QgZm9ybWF0KS4KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":830,"slug":"always-on-exemplar-filter","name":"always_on_exemplar_filter","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"AlwaysOnExemplarFilter","namespace":"Flow\\Telemetry\\Meter\\Exemplar","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBBbHdheXNPbkV4ZW1wbGFyRmlsdGVyLgogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":839,"slug":"always-off-exemplar-filter","name":"always_off_exemplar_filter","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"AlwaysOffExemplarFilter","namespace":"Flow\\Telemetry\\Meter\\Exemplar","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBBbHdheXNPZmZFeGVtcGxhckZpbHRlci4KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":848,"slug":"trace-based-exemplar-filter","name":"trace_based_exemplar_filter","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"TraceBasedExemplarFilter","namespace":"Flow\\Telemetry\\Meter\\Exemplar","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFRyYWNlQmFzZWRFeGVtcGxhckZpbHRlci4KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":857,"slug":"always-on-sampler","name":"always_on_sampler","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"AlwaysOnSampler","namespace":"Flow\\Telemetry\\Tracer\\Sampler","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBBbHdheXNPblNhbXBsZXIuIFJlY29yZHMgYW5kIHNhbXBsZXMgZXZlcnkgc3Bhbi4KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":866,"slug":"always-off-sampler","name":"always_off_sampler","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"AlwaysOffSampler","namespace":"Flow\\Telemetry\\Tracer\\Sampler","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBBbHdheXNPZmZTYW1wbGVyLiBEcm9wcyBldmVyeSBzcGFuLgogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":877,"slug":"trace-id-ratio-based-sampler","name":"trace_id_ratio_based_sampler","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"ratio","type":[{"name":"float","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"TraceIdRatioBasedSampler","namespace":"Flow\\Telemetry\\Tracer\\Sampler","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFRyYWNlSWRSYXRpb0Jhc2VkU2FtcGxlci4gU2FtcGxlcyBhIGRldGVybWluaXN0aWMgZnJhY3Rpb24gb2YgdHJhY2VzLgogKgogKiBAcGFyYW0gZmxvYXQgJHJhdGlvIFNhbXBsaW5nIHByb2JhYmlsaXR5IGJldHdlZW4gMC4wIGFuZCAxLjAKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":889,"slug":"parent-based-sampler","name":"parent_based_sampler","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"root","type":[{"name":"Sampler","namespace":"Flow\\Telemetry\\Tracer\\Sampler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\Tracer\\Sampler\\AlwaysOnSampler::..."}],"return_type":[{"name":"ParentBasedSampler","namespace":"Flow\\Telemetry\\Tracer\\Sampler","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBhcmVudEJhc2VkU2FtcGxlci4gSG9ub3JzIHRoZSBwYXJlbnQgc3BhbidzIHNhbXBsaW5nIGRlY2lzaW9uLCBmYWxsaW5nCiAqIGJhY2sgdG8gdGhlIHJvb3Qgc2FtcGxlciBmb3Igc3BhbnMgd2l0aG91dCBhIHBhcmVudC4KICoKICogQHBhcmFtIFNhbXBsZXIgJHJvb3QgU2FtcGxlciB1c2VkIGZvciByb290IHNwYW5zIChubyBwYXJlbnQpCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":905,"slug":"attribute-matching-sampler","name":"attribute_matching_sampler","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"filter","type":[{"name":"AttributeFilter","namespace":"Flow\\Telemetry\\Filter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"delegate","type":[{"name":"Sampler","namespace":"Flow\\Telemetry\\Tracer\\Sampler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\Tracer\\Sampler\\AlwaysOnSampler::..."}],"return_type":[{"name":"AttributeMatchingSampler","namespace":"Flow\\Telemetry\\Tracer\\Sampler","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBBdHRyaWJ1dGVNYXRjaGluZ1NhbXBsZXIuIERyb3BzIHNwYW5zIHdob3NlIHN0YXJ0LXRpbWUgYXR0cmlidXRlcyBtYXRjaAogKiB0aGUgZmlsdGVyIChvciBrZWVwcyBPTkxZIG1hdGNoaW5nIHNwYW5zIHdoZW4gdGhlIGZpbHRlcidzIGV4Y2x1ZGUgaXMgZmFsc2UpLCBhbmQKICogZGVmZXJzIGFsbCBvdGhlciBzcGFucyB0byB0aGUgZGVsZWdhdGUgc2FtcGxlci4KICoKICogT25seSBhdHRyaWJ1dGVzIGF2YWlsYWJsZSBhdCBzcGFuIHN0YXJ0IGFyZSB2aXNpYmxlOyBhdHRyaWJ1dGVzIGFkZGVkIGxhdGVyIGFyZSBub3QuCiAqCiAqIEBwYXJhbSBBdHRyaWJ1dGVGaWx0ZXIgJGZpbHRlciBUaGUgYXR0cmlidXRlIGZpbHRlciBldmFsdWF0ZWQgYWdhaW5zdCB0aGUgc3BhbidzIHN0YXJ0IGF0dHJpYnV0ZXMKICogQHBhcmFtIFNhbXBsZXIgJGRlbGVnYXRlIFNhbXBsZXIgdGhhdCBkZWNpZGVzIHNwYW5zIHdoaWNoIGRvIG5vdCBtYXRjaCAoZGVmYXVsdDogQWx3YXlzT25TYW1wbGVyKQogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":919,"slug":"propagation-context","name":"propagation_context","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"spanContext","type":[{"name":"SpanContext","namespace":"Flow\\Telemetry\\Tracer","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"baggage","type":[{"name":"Baggage","namespace":"Flow\\Telemetry\\Context","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"PropagationContext","namespace":"Flow\\Telemetry\\Propagation","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFByb3BhZ2F0aW9uQ29udGV4dC4KICoKICogQHBhcmFtIG51bGx8U3BhbkNvbnRleHQgJHNwYW5Db250ZXh0IE9wdGlvbmFsIHNwYW4gY29udGV4dAogKiBAcGFyYW0gbnVsbHxCYWdnYWdlICRiYWdnYWdlIE9wdGlvbmFsIGJhZ2dhZ2UKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":930,"slug":"array-carrier","name":"array_carrier","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"data","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"ArrayCarrier","namespace":"Flow\\Telemetry\\Propagation","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBBcnJheUNhcnJpZXIuCiAqCiAqIEBwYXJhbSBhcnJheTxzdHJpbmcsIHN0cmluZz4gJGRhdGEgSW5pdGlhbCBjYXJyaWVyIGRhdGEKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":939,"slug":"superglobal-carrier","name":"superglobal_carrier","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"SuperglobalCarrier","namespace":"Flow\\Telemetry\\Propagation","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFN1cGVyZ2xvYmFsQ2Fycmllci4KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":948,"slug":"w3c-trace-context","name":"w3c_trace_context","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"W3CTraceContext","namespace":"Flow\\Telemetry\\Propagation","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFczQ1RyYWNlQ29udGV4dCBwcm9wYWdhdG9yLgogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":957,"slug":"w3c-baggage","name":"w3c_baggage","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"W3CBaggage","namespace":"Flow\\Telemetry\\Propagation","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFczQ0JhZ2dhZ2UgcHJvcGFnYXRvci4KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":968,"slug":"composite-propagator","name":"composite_propagator","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"propagators","type":[{"name":"Propagator","namespace":"Flow\\Telemetry\\Propagation","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"CompositePropagator","namespace":"Flow\\Telemetry\\Propagation","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENvbXBvc2l0ZVByb3BhZ2F0b3IuCiAqCiAqIEBwYXJhbSBQcm9wYWdhdG9yIC4uLiRwcm9wYWdhdG9ycyBUaGUgcHJvcGFnYXRvcnMgdG8gY29tYmluZQogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":979,"slug":"chain-detector","name":"chain_detector","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"detectors","type":[{"name":"ResourceDetector","namespace":"Flow\\Telemetry\\Resource","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"ChainDetector","namespace":"Flow\\Telemetry\\Resource\\Detector","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENoYWluRGV0ZWN0b3IuCiAqCiAqIEBwYXJhbSBSZXNvdXJjZURldGVjdG9yIC4uLiRkZXRlY3RvcnMgVGhlIGRldGVjdG9ycyB0byBjaGFpbgogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":988,"slug":"os-detector","name":"os_detector","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"OsDetector","namespace":"Flow\\Telemetry\\Resource\\Detector","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBPc0RldGVjdG9yLgogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":997,"slug":"host-detector","name":"host_detector","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"HostDetector","namespace":"Flow\\Telemetry\\Resource\\Detector","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEhvc3REZXRlY3Rvci4KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":1006,"slug":"process-detector","name":"process_detector","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"ProcessDetector","namespace":"Flow\\Telemetry\\Resource\\Detector","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFByb2Nlc3NEZXRlY3Rvci4KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":1015,"slug":"environment-detector","name":"environment_detector","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"EnvironmentDetector","namespace":"Flow\\Telemetry\\Resource\\Detector","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBFbnZpcm9ubWVudERldGVjdG9yLgogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":1024,"slug":"composer-detector","name":"composer_detector","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"ComposerDetector","namespace":"Flow\\Telemetry\\Resource\\Detector","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENvbXBvc2VyRGV0ZWN0b3IuCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":1036,"slug":"git-detector","name":"git_detector","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"workingDirectory","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":"gitBinary","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'git'"}],"return_type":[{"name":"GitDetector","namespace":"Flow\\Telemetry\\Resource\\Detector","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEdpdERldGVjdG9yLgogKgogKiBAcGFyYW0gbnVsbHxzdHJpbmcgJHdvcmtpbmdEaXJlY3RvcnkgRGlyZWN0b3J5IHRvIHJ1biBnaXQgaW4gKGRlZmF1bHQ6IGN1cnJlbnQgd29ya2luZyBkaXJlY3RvcnkpCiAqIEBwYXJhbSBzdHJpbmcgJGdpdEJpbmFyeSBQYXRoIHRvIHRoZSBnaXQgYmluYXJ5IChkZWZhdWx0OiAiZ2l0IiwgcmVzb2x2ZWQgZnJvbSAkUEFUSCkKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":1047,"slug":"manual-detector","name":"manual_detector","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"attributes","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":"ManualDetector","namespace":"Flow\\Telemetry\\Resource\\Detector","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIE1hbnVhbERldGVjdG9yLgogKgogKiBAcGFyYW0gYXJyYXk8c3RyaW5nLCBhcnJheTxhcnJheS1rZXksIG1peGVkPnxib29sfFxEYXRlVGltZUludGVyZmFjZXxmbG9hdHxpbnR8c3RyaW5nfFxUaHJvd2FibGU+ICRhdHRyaWJ1dGVzIFJlc291cmNlIGF0dHJpYnV0ZXMKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":1059,"slug":"caching-detector","name":"caching_detector","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"detector","type":[{"name":"ResourceDetector","namespace":"Flow\\Telemetry\\Resource","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"cachePath","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"CachingDetector","namespace":"Flow\\Telemetry\\Resource\\Detector","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENhY2hpbmdEZXRlY3Rvci4KICoKICogQHBhcmFtIFJlc291cmNlRGV0ZWN0b3IgJGRldGVjdG9yIFRoZSBkZXRlY3RvciB0byB3cmFwCiAqIEBwYXJhbSBudWxsfHN0cmluZyAkY2FjaGVQYXRoIENhY2hlIGZpbGUgcGF0aCAoZGVmYXVsdDogc3lzX2dldF90ZW1wX2RpcigpL2Zsb3dfdGVsZW1ldHJ5X3Jlc291cmNlLmNhY2hlKQogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":1070,"slug":"resource-detector","name":"resource_detector","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"detectors","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"ChainDetector","namespace":"Flow\\Telemetry\\Resource\\Detector","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHJlc291cmNlIGRldGVjdG9yIGNoYWluLgogKgogKiBAcGFyYW0gYXJyYXk8UmVzb3VyY2VEZXRlY3Rvcj4gJGRldGVjdG9ycyBPcHRpb25hbCBjdXN0b20gZGV0ZWN0b3JzIChlbXB0eSA9IHVzZSBkZWZhdWx0cykKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":1089,"slug":"error-log-handler","name":"error_log_handler","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"messageType","type":[{"name":"ErrorLogMessageType","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\ErrorHandler\\ErrorLogMessageType::..."},{"name":"expandNewlines","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"messagePrefix","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'[flow-telemetry]'"}],"return_type":[{"name":"ErrorLogHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSB0aGUgZGVmYXVsdCBFcnJvckxvZ0hhbmRsZXIuIFdyaXRlcyB2aWEgUEhQJ3MgZXJyb3JfbG9nKCkuCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":1102,"slug":"stream-error-handler","name":"stream_error_handler","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"destination","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":"filePermissions","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"420"},{"name":"createDirectories","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"messagePrefix","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'[flow-telemetry]'"}],"return_type":[{"name":"StreamHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFN0cmVhbUhhbmRsZXIuIEFwcGVuZHMgZm9ybWF0dGVkIFRocm93YWJsZXMgKG9uZSBwZXIgbGluZSkgdG8gYSBmaWxlCiAqIHBhdGggb3IgcGhwOi8vIHN0cmVhbSB3cmFwcGVyLgogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":1115,"slug":"syslog-error-handler","name":"syslog_error_handler","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"ident","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'flow-telemetry'"},{"name":"facility","type":[{"name":"SyslogFacility","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\ErrorHandler\\SyslogFacility::..."},{"name":"logOpts","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"1"},{"name":"severity","type":[{"name":"SyslogSeverity","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\ErrorHandler\\SyslogSeverity::..."}],"return_type":[{"name":"SyslogHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFN5c2xvZ0hhbmRsZXIuIFdyaXRlcyB2aWEgb3BlbmxvZy9zeXNsb2cvY2xvc2Vsb2cuCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":1128,"slug":"udp-syslog-error-handler","name":"udp_syslog_error_handler","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"host","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":"port","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"514"},{"name":"ident","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'flow-telemetry'"},{"name":"facility","type":[{"name":"SyslogFacility","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\ErrorHandler\\SyslogFacility::..."},{"name":"severity","type":[{"name":"SyslogSeverity","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\ErrorHandler\\SyslogSeverity::..."}],"return_type":[{"name":"UdpSyslogHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFVkcFN5c2xvZ0hhbmRsZXIuIFNlbmRzIFJGQyA1NDI0LXN0eWxlIHN5c2xvZyBmcmFtZXMgb3ZlciBVRFAuCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":1142,"slug":"composite-error-handler","name":"composite_error_handler","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"handlers","type":[{"name":"ErrorHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"CompositeErrorHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEZhbiBlcnJvcnMgb3V0IHRvIG11bHRpcGxlIGhhbmRsZXJzLgogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":1151,"slug":"null-error-handler","name":"null_error_handler","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"NullErrorHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIERpc2NhcmQgZXZlcnkgZXJyb3IuIFVzZSBvbmx5IGluIHRlc3RzIG9yIGZvciBleHBsaWNpdCBzaWxlbmNlLgogKi8="},{"repository_path":"src\/lib\/azure-sdk\/src\/Flow\/Azure\/SDK\/DSL\/functions.php","start_line_in_file":29,"slug":"azurite-url-factory","name":"azurite_url_factory","namespace":"Flow\\Azure\\SDK\\DSL","parameters":[{"name":"host","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'localhost'"},{"name":"port","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'10000'"},{"name":"secure","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":"AzuriteURLFactory","namespace":"Flow\\Azure\\SDK\\BlobService\\URLFactory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"AZURE_SDK","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/azure-sdk\/src\/Flow\/Azure\/SDK\/DSL\/functions.php","start_line_in_file":38,"slug":"azure-shared-key-authorization-factory","name":"azure_shared_key_authorization_factory","namespace":"Flow\\Azure\\SDK\\DSL","parameters":[{"name":"account","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":"key","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":"SharedKeyFactory","namespace":"Flow\\Azure\\SDK\\AuthorizationFactory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"AZURE_SDK","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/azure-sdk\/src\/Flow\/Azure\/SDK\/DSL\/functions.php","start_line_in_file":48,"slug":"azure-blob-service-config","name":"azure_blob_service_config","namespace":"Flow\\Azure\\SDK\\DSL","parameters":[{"name":"account","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":"container","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":"Configuration","namespace":"Flow\\Azure\\SDK\\BlobService","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"AZURE_SDK","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/azure-sdk\/src\/Flow\/Azure\/SDK\/DSL\/functions.php","start_line_in_file":54,"slug":"azure-url-factory","name":"azure_url_factory","namespace":"Flow\\Azure\\SDK\\DSL","parameters":[{"name":"host","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'blob.core.windows.net'"}],"return_type":[{"name":"AzureURLFactory","namespace":"Flow\\Azure\\SDK\\BlobService\\URLFactory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"AZURE_SDK","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/azure-sdk\/src\/Flow\/Azure\/SDK\/DSL\/functions.php","start_line_in_file":60,"slug":"azure-http-factory","name":"azure_http_factory","namespace":"Flow\\Azure\\SDK\\DSL","parameters":[{"name":"request_factory","type":[{"name":"RequestFactoryInterface","namespace":"Psr\\Http\\Message","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"stream_factory","type":[{"name":"StreamFactoryInterface","namespace":"Psr\\Http\\Message","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"HttpFactory","namespace":"Flow\\Azure\\SDK","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"AZURE_SDK","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/azure-sdk\/src\/Flow\/Azure\/SDK\/DSL\/functions.php","start_line_in_file":68,"slug":"azure-blob-service","name":"azure_blob_service","namespace":"Flow\\Azure\\SDK\\DSL","parameters":[{"name":"configuration","type":[{"name":"Configuration","namespace":"Flow\\Azure\\SDK\\BlobService","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"azure_authorization_factory","type":[{"name":"AuthorizationFactory","namespace":"Flow\\Azure\\SDK","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"client","type":[{"name":"ClientInterface","namespace":"Psr\\Http\\Client","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"azure_http_factory","type":[{"name":"HttpFactory","namespace":"Flow\\Azure\\SDK","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"azure_url_factory","type":[{"name":"URLFactory","namespace":"Flow\\Azure\\SDK","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"logger","type":[{"name":"LoggerInterface","namespace":"Psr\\Log","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"BlobServiceInterface","namespace":"Flow\\Azure\\SDK","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"AZURE_SDK","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/bridge\/filesystem\/azure\/src\/Flow\/Filesystem\/Bridge\/Azure\/DSL\/functions.php","start_line_in_file":16,"slug":"azure-filesystem-options","name":"azure_filesystem_options","namespace":"Flow\\Filesystem\\Bridge\\Azure\\DSL","parameters":[],"return_type":[{"name":"Options","namespace":"Flow\\Filesystem\\Bridge\\Azure","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"AZURE_FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/bridge\/filesystem\/azure\/src\/Flow\/Filesystem\/Bridge\/Azure\/DSL\/functions.php","start_line_in_file":22,"slug":"azure-filesystem","name":"azure_filesystem","namespace":"Flow\\Filesystem\\Bridge\\Azure\\DSL","parameters":[{"name":"blob_service","type":[{"name":"BlobServiceInterface","namespace":"Flow\\Azure\\SDK","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"options","type":[{"name":"Options","namespace":"Flow\\Filesystem\\Bridge\\Azure","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Bridge\\Azure\\Options::..."},{"name":"protocol","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'azure-blob'"}],"return_type":[{"name":"AzureBlobFilesystem","namespace":"Flow\\Filesystem\\Bridge\\Azure","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"AZURE_FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/bridge\/filesystem\/async-aws\/src\/Flow\/Filesystem\/Bridge\/AsyncAWS\/DSL\/functions.php","start_line_in_file":20,"slug":"aws-s3-client","name":"aws_s3_client","namespace":"Flow\\Filesystem\\Bridge\\AsyncAWS\\DSL","parameters":[{"name":"configuration","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":"S3Client","namespace":"AsyncAws\\S3","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"S3_FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxDb25maWd1cmF0aW9uOjpPUFRJT05fKiwgbnVsbHxzdHJpbmc+ICRjb25maWd1cmF0aW9uIC0gZm9yIGRldGFpbHMgcGxlYXNlIHNlZSBodHRwczovL2FzeW5jLWF3cy5jb20vY2xpZW50cy9zMy5odG1sCiAqLw=="},{"repository_path":"src\/bridge\/filesystem\/async-aws\/src\/Flow\/Filesystem\/Bridge\/AsyncAWS\/DSL\/functions.php","start_line_in_file":26,"slug":"aws-s3-filesystem","name":"aws_s3_filesystem","namespace":"Flow\\Filesystem\\Bridge\\AsyncAWS\\DSL","parameters":[{"name":"bucket","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":"s3Client","type":[{"name":"S3Client","namespace":"AsyncAws\\S3","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"options","type":[{"name":"Options","namespace":"Flow\\Filesystem\\Bridge\\AsyncAWS","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Bridge\\AsyncAWS\\Options::..."},{"name":"protocol","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'aws-s3'"}],"return_type":[{"name":"AsyncAWSS3Filesystem","namespace":"Flow\\Filesystem\\Bridge\\AsyncAWS","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"S3_FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/bridge\/filesystem\/sftp\/src\/Flow\/Filesystem\/Bridge\/SFTP\/DSL\/functions.php","start_line_in_file":24,"slug":"sftp-client","name":"sftp_client","namespace":"Flow\\Filesystem\\Bridge\\SFTP\\DSL","parameters":[{"name":"host","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":"user","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":"credential","type":[{"name":"PrivateKey","namespace":"phpseclib4\\Crypt\\Common","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":"port","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"22"}],"return_type":[{"name":"SFTP","namespace":"phpseclib4\\Net","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"SFTP_FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0aHJvd3MgUnVudGltZUV4Y2VwdGlvbgogKi8="},{"repository_path":"src\/bridge\/filesystem\/sftp\/src\/Flow\/Filesystem\/Bridge\/SFTP\/DSL\/functions.php","start_line_in_file":46,"slug":"sftp-filesystem","name":"sftp_filesystem","namespace":"Flow\\Filesystem\\Bridge\\SFTP\\DSL","parameters":[{"name":"sftp","type":[{"name":"SFTP","namespace":"phpseclib4\\Net","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"options","type":[{"name":"Options","namespace":"Flow\\Filesystem\\Bridge\\SFTP","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Filesystem\\Bridge\\SFTP\\Options::..."},{"name":"protocol","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'sftp'"}],"return_type":[{"name":"SFTPFilesystem","namespace":"Flow\\Filesystem\\Bridge\\SFTP","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"SFTP_FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/bridge\/filesystem\/sftp\/src\/Flow\/Filesystem\/Bridge\/SFTP\/DSL\/functions.php","start_line_in_file":52,"slug":"sftp-filesystem-options","name":"sftp_filesystem_options","namespace":"Flow\\Filesystem\\Bridge\\SFTP\\DSL","parameters":[],"return_type":[{"name":"Options","namespace":"Flow\\Filesystem\\Bridge\\SFTP","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"SFTP_FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/bridge\/monolog\/telemetry\/src\/Flow\/Bridge\/Monolog\/Telemetry\/DSL\/functions.php","start_line_in_file":40,"slug":"value-normalizer","name":"value_normalizer","namespace":"Flow\\Bridge\\Monolog\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"ValueNormalizer","namespace":"Flow\\Bridge\\Monolog\\Telemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"MONOLOG_TELEMETRY_BRIDGE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFZhbHVlTm9ybWFsaXplciBmb3IgY29udmVydGluZyBhcmJpdHJhcnkgUEhQIHZhbHVlcyB0byBUZWxlbWV0cnkgYXR0cmlidXRlIHR5cGVzLgogKgogKiBUaGUgbm9ybWFsaXplciBoYW5kbGVzOgogKiAtIG51bGwg4oaSICdudWxsJyBzdHJpbmcKICogLSBzY2FsYXJzIChzdHJpbmcsIGludCwgZmxvYXQsIGJvb2wpIOKGkiB1bmNoYW5nZWQKICogLSBEYXRlVGltZUludGVyZmFjZSDihpIgdW5jaGFuZ2VkCiAqIC0gVGhyb3dhYmxlIOKGkiB1bmNoYW5nZWQKICogLSBhcnJheXMg4oaSIHJlY3Vyc2l2ZWx5IG5vcm1hbGl6ZWQKICogLSBvYmplY3RzIHdpdGggX190b1N0cmluZygpIOKGkiBzdHJpbmcgY2FzdAogKiAtIG9iamVjdHMgd2l0aG91dCBfX3RvU3RyaW5nKCkg4oaSIGNsYXNzIG5hbWUKICogLSBvdGhlciB0eXBlcyDihpIgZ2V0X2RlYnVnX3R5cGUoKSByZXN1bHQKICoKICogRXhhbXBsZSB1c2FnZToKICogYGBgcGhwCiAqICRub3JtYWxpemVyID0gdmFsdWVfbm9ybWFsaXplcigpOwogKiAkbm9ybWFsaXplZCA9ICRub3JtYWxpemVyLT5ub3JtYWxpemUoJHZhbHVlKTsKICogYGBgCiAqLw=="},{"repository_path":"src\/bridge\/monolog\/telemetry\/src\/Flow\/Bridge\/Monolog\/Telemetry\/DSL\/functions.php","start_line_in_file":73,"slug":"severity-mapper","name":"severity_mapper","namespace":"Flow\\Bridge\\Monolog\\Telemetry\\DSL","parameters":[{"name":"customMapping","type":[{"name":"array","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"SeverityMapper","namespace":"Flow\\Bridge\\Monolog\\Telemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"MONOLOG_TELEMETRY_BRIDGE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFNldmVyaXR5TWFwcGVyIGZvciBtYXBwaW5nIE1vbm9sb2cgbGV2ZWxzIHRvIFRlbGVtZXRyeSBzZXZlcml0aWVzLgogKgogKiBAcGFyYW0gbnVsbHxhcnJheTxpbnQsIFNldmVyaXR5PiAkY3VzdG9tTWFwcGluZyBPcHRpb25hbCBjdXN0b20gbWFwcGluZyAoTW9ub2xvZyBMZXZlbCB2YWx1ZSA9PiBUZWxlbWV0cnkgU2V2ZXJpdHkpCiAqCiAqIEV4YW1wbGUgd2l0aCBkZWZhdWx0IG1hcHBpbmc6CiAqIGBgYHBocAogKiAkbWFwcGVyID0gc2V2ZXJpdHlfbWFwcGVyKCk7CiAqIGBgYAogKgogKiBFeGFtcGxlIHdpdGggY3VzdG9tIG1hcHBpbmc6CiAqIGBgYHBocAogKiB1c2UgTW9ub2xvZ1xMZXZlbDsKICogdXNlIEZsb3dcVGVsZW1ldHJ5XExvZ2dlclxTZXZlcml0eTsKICoKICogJG1hcHBlciA9IHNldmVyaXR5X21hcHBlcihbCiAqICAgICBMZXZlbDo6RGVidWctPnZhbHVlID0+IFNldmVyaXR5OjpERUJVRywKICogICAgIExldmVsOjpJbmZvLT52YWx1ZSA9PiBTZXZlcml0eTo6SU5GTywKICogICAgIExldmVsOjpOb3RpY2UtPnZhbHVlID0+IFNldmVyaXR5OjpXQVJOLCAgLy8gQ3VzdG9tOiBOT1RJQ0Ug4oaSIFdBUk4gaW5zdGVhZCBvZiBJTkZPCiAqICAgICBMZXZlbDo6V2FybmluZy0+dmFsdWUgPT4gU2V2ZXJpdHk6OldBUk4sCiAqICAgICBMZXZlbDo6RXJyb3ItPnZhbHVlID0+IFNldmVyaXR5OjpFUlJPUiwKICogICAgIExldmVsOjpDcml0aWNhbC0+dmFsdWUgPT4gU2V2ZXJpdHk6OkZBVEFMLAogKiAgICAgTGV2ZWw6OkFsZXJ0LT52YWx1ZSA9PiBTZXZlcml0eTo6RkFUQUwsCiAqICAgICBMZXZlbDo6RW1lcmdlbmN5LT52YWx1ZSA9PiBTZXZlcml0eTo6RkFUQUwsCiAqIF0pOwogKiBgYGAKICov"},{"repository_path":"src\/bridge\/monolog\/telemetry\/src\/Flow\/Bridge\/Monolog\/Telemetry\/DSL\/functions.php","start_line_in_file":107,"slug":"log-record-converter","name":"log_record_converter","namespace":"Flow\\Bridge\\Monolog\\Telemetry\\DSL","parameters":[{"name":"severityMapper","type":[{"name":"SeverityMapper","namespace":"Flow\\Bridge\\Monolog\\Telemetry","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"valueNormalizer","type":[{"name":"ValueNormalizer","namespace":"Flow\\Bridge\\Monolog\\Telemetry","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"LogRecordConverter","namespace":"Flow\\Bridge\\Monolog\\Telemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"MONOLOG_TELEMETRY_BRIDGE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIExvZ1JlY29yZENvbnZlcnRlciBmb3IgY29udmVydGluZyBNb25vbG9nIExvZ1JlY29yZCB0byBUZWxlbWV0cnkgTG9nUmVjb3JkLgogKgogKiBUaGUgY29udmVydGVyIGhhbmRsZXM6CiAqIC0gU2V2ZXJpdHkgbWFwcGluZyBmcm9tIE1vbm9sb2cgTGV2ZWwgdG8gVGVsZW1ldHJ5IFNldmVyaXR5CiAqIC0gTWVzc2FnZSBib2R5IGNvbnZlcnNpb24KICogLSBDaGFubmVsIGFuZCBsZXZlbCBuYW1lIGFzIG1vbm9sb2cuKiBhdHRyaWJ1dGVzCiAqIC0gQ29udGV4dCB2YWx1ZXMgYXMgY29udGV4dC4qIGF0dHJpYnV0ZXMgKFRocm93YWJsZXMgdXNlIHNldEV4Y2VwdGlvbigpKQogKiAtIEV4dHJhIHZhbHVlcyBhcyBleHRyYS4qIGF0dHJpYnV0ZXMKICoKICogQHBhcmFtIG51bGx8U2V2ZXJpdHlNYXBwZXIgJHNldmVyaXR5TWFwcGVyIEN1c3RvbSBzZXZlcml0eSBtYXBwZXIgKGRlZmF1bHRzIHRvIHN0YW5kYXJkIG1hcHBpbmcpCiAqIEBwYXJhbSBudWxsfFZhbHVlTm9ybWFsaXplciAkdmFsdWVOb3JtYWxpemVyIEN1c3RvbSB2YWx1ZSBub3JtYWxpemVyIChkZWZhdWx0cyB0byBzdGFuZGFyZCBub3JtYWxpemVyKQogKgogKiBFeGFtcGxlIHVzYWdlOgogKiBgYGBwaHAKICogJGNvbnZlcnRlciA9IGxvZ19yZWNvcmRfY29udmVydGVyKCk7CiAqICR0ZWxlbWV0cnlSZWNvcmQgPSAkY29udmVydGVyLT5jb252ZXJ0KCRtb25vbG9nUmVjb3JkKTsKICogYGBgCiAqCiAqIEV4YW1wbGUgd2l0aCBjdXN0b20gbWFwcGVyOgogKiBgYGBwaHAKICogJGNvbnZlcnRlciA9IGxvZ19yZWNvcmRfY29udmVydGVyKAogKiAgICAgc2V2ZXJpdHlNYXBwZXI6IHNldmVyaXR5X21hcHBlcihbCiAqICAgICAgICAgTGV2ZWw6OkRlYnVnLT52YWx1ZSA9PiBTZXZlcml0eTo6VFJBQ0UsCiAqICAgICBdKQogKiApOwogKiBgYGAKICov"},{"repository_path":"src\/bridge\/monolog\/telemetry\/src\/Flow\/Bridge\/Monolog\/Telemetry\/DSL\/functions.php","start_line_in_file":149,"slug":"telemetry-handler","name":"telemetry_handler","namespace":"Flow\\Bridge\\Monolog\\Telemetry\\DSL","parameters":[{"name":"logger","type":[{"name":"Logger","namespace":"Flow\\Telemetry\\Logger","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"converter","type":[{"name":"LogRecordConverter","namespace":"Flow\\Bridge\\Monolog\\Telemetry","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Bridge\\Monolog\\Telemetry\\LogRecordConverter::..."},{"name":"level","type":[{"name":"Level","namespace":"Monolog","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Monolog\\Level::..."},{"name":"bubble","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"errorHandler","type":[{"name":"ErrorHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\ErrorHandler\\ErrorLogHandler::..."}],"return_type":[{"name":"TelemetryHandler","namespace":"Flow\\Bridge\\Monolog\\Telemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"MONOLOG_TELEMETRY_BRIDGE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFRlbGVtZXRyeUhhbmRsZXIgZm9yIGZvcndhcmRpbmcgTW9ub2xvZyBsb2dzIHRvIEZsb3cgVGVsZW1ldHJ5LgogKgogKiBAcGFyYW0gTG9nZ2VyICRsb2dnZXIgVGhlIEZsb3cgVGVsZW1ldHJ5IGxvZ2dlciB0byBmb3J3YXJkIGxvZ3MgdG8KICogQHBhcmFtIExvZ1JlY29yZENvbnZlcnRlciAkY29udmVydGVyIENvbnZlcnRlciB0byB0cmFuc2Zvcm0gTW9ub2xvZyBMb2dSZWNvcmQgdG8gVGVsZW1ldHJ5IExvZ1JlY29yZAogKiBAcGFyYW0gTGV2ZWwgJGxldmVsIFRoZSBtaW5pbXVtIGxvZ2dpbmcgbGV2ZWwgYXQgd2hpY2ggdGhpcyBoYW5kbGVyIHdpbGwgYmUgdHJpZ2dlcmVkCiAqIEBwYXJhbSBib29sICRidWJibGUgV2hldGhlciBtZXNzYWdlcyBoYW5kbGVkIGJ5IHRoaXMgaGFuZGxlciBzaG91bGQgYnViYmxlIHVwIHRvIG90aGVyIGhhbmRsZXJzCiAqCiAqIEV4YW1wbGUgdXNhZ2U6CiAqIGBgYHBocAogKiB1c2UgTW9ub2xvZ1xMb2dnZXIgYXMgTW9ub2xvZ0xvZ2dlcjsKICogdXNlIGZ1bmN0aW9uIEZsb3dcQnJpZGdlXE1vbm9sb2dcVGVsZW1ldHJ5XERTTFx0ZWxlbWV0cnlfaGFuZGxlcjsKICogdXNlIGZ1bmN0aW9uIEZsb3dcVGVsZW1ldHJ5XERTTFx0ZWxlbWV0cnk7CiAqCiAqICR0ZWxlbWV0cnkgPSB0ZWxlbWV0cnkoKTsKICogJGxvZ2dlciA9ICR0ZWxlbWV0cnktPmxvZ2dlcignbXktYXBwJyk7CiAqCiAqICRtb25vbG9nID0gbmV3IE1vbm9sb2dMb2dnZXIoJ2NoYW5uZWwnKTsKICogJG1vbm9sb2ctPnB1c2hIYW5kbGVyKHRlbGVtZXRyeV9oYW5kbGVyKCRsb2dnZXIpKTsKICoKICogJG1vbm9sb2ctPmluZm8oJ1VzZXIgbG9nZ2VkIGluJywgWyd1c2VyX2lkJyA9PiAxMjNdKTsKICogLy8g4oaSIEZvcndhcmRlZCB0byBGbG93IFRlbGVtZXRyeSB3aXRoIElORk8gc2V2ZXJpdHkKICogYGBgCiAqCiAqIEV4YW1wbGUgd2l0aCBjdXN0b20gY29udmVydGVyOgogKiBgYGBwaHAKICogJGNvbnZlcnRlciA9IGxvZ19yZWNvcmRfY29udmVydGVyKAogKiAgICAgc2V2ZXJpdHlNYXBwZXI6IHNldmVyaXR5X21hcHBlcihbCiAqICAgICAgICAgTGV2ZWw6OkRlYnVnLT52YWx1ZSA9PiBTZXZlcml0eTo6VFJBQ0UsCiAqICAgICBdKQogKiApOwogKiAkbW9ub2xvZy0+cHVzaEhhbmRsZXIodGVsZW1ldHJ5X2hhbmRsZXIoJGxvZ2dlciwgJGNvbnZlcnRlcikpOwogKiBgYGAKICov"},{"repository_path":"src\/bridge\/symfony\/http-foundation-telemetry\/src\/Flow\/Bridge\/Symfony\/HttpFoundationTelemetry\/DSL\/functions.php","start_line_in_file":16,"slug":"symfony-request-carrier","name":"symfony_request_carrier","namespace":"Flow\\Bridge\\Symfony\\HttpFoundationTelemetry\\DSL","parameters":[{"name":"request","type":[{"name":"Request","namespace":"Symfony\\Component\\HttpFoundation","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"RequestCarrier","namespace":"Flow\\Bridge\\Symfony\\HttpFoundationTelemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"SYMFONY_HTTP_FOUNDATION_TELEMETRY_BRIDGE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/bridge\/symfony\/http-foundation-telemetry\/src\/Flow\/Bridge\/Symfony\/HttpFoundationTelemetry\/DSL\/functions.php","start_line_in_file":22,"slug":"symfony-response-carrier","name":"symfony_response_carrier","namespace":"Flow\\Bridge\\Symfony\\HttpFoundationTelemetry\\DSL","parameters":[{"name":"response","type":[{"name":"Response","namespace":"Symfony\\Component\\HttpFoundation","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ResponseCarrier","namespace":"Flow\\Bridge\\Symfony\\HttpFoundationTelemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"SYMFONY_HTTP_FOUNDATION_TELEMETRY_BRIDGE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/bridge\/psr7\/telemetry\/src\/Flow\/Bridge\/Psr7\/Telemetry\/DSL\/functions.php","start_line_in_file":16,"slug":"psr7-request-carrier","name":"psr7_request_carrier","namespace":"Flow\\Bridge\\Psr7\\Telemetry\\DSL","parameters":[{"name":"request","type":[{"name":"ServerRequestInterface","namespace":"Psr\\Http\\Message","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"RequestCarrier","namespace":"Flow\\Bridge\\Psr7\\Telemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PSR7_TELEMETRY_BRIDGE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/bridge\/psr7\/telemetry\/src\/Flow\/Bridge\/Psr7\/Telemetry\/DSL\/functions.php","start_line_in_file":22,"slug":"psr7-response-carrier","name":"psr7_response_carrier","namespace":"Flow\\Bridge\\Psr7\\Telemetry\\DSL","parameters":[{"name":"response","type":[{"name":"ResponseInterface","namespace":"Psr\\Http\\Message","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ResponseCarrier","namespace":"Flow\\Bridge\\Psr7\\Telemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PSR7_TELEMETRY_BRIDGE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/bridge\/psr18\/telemetry\/src\/Flow\/Bridge\/Psr18\/Telemetry\/DSL\/functions.php","start_line_in_file":15,"slug":"psr18-traceable-client","name":"psr18_traceable_client","namespace":"Flow\\Bridge\\Psr18\\Telemetry\\DSL","parameters":[{"name":"client","type":[{"name":"ClientInterface","namespace":"Psr\\Http\\Client","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"telemetry","type":[{"name":"Telemetry","namespace":"Flow\\Telemetry","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"PSR18TraceableClient","namespace":"Flow\\Bridge\\Psr18\\Telemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"PSR18_TELEMETRY_BRIDGE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":49,"slug":"otlp-json-serializer","name":"otlp_json_serializer","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\DSL","parameters":[],"return_type":[{"name":"JsonSerializer","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Serializer","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEpTT04gc2VyaWFsaXplciBmb3IgT1RMUC4KICoKICogUmV0dXJucyBhIEpzb25TZXJpYWxpemVyIHRoYXQgY29udmVydHMgdGVsZW1ldHJ5IGRhdGEgdG8gT1RMUCBKU09OIHdpcmUgZm9ybWF0LgogKiBVc2UgdGhpcyB3aXRoIEN1cmxUcmFuc3BvcnQgZm9yIEpTT04gb3ZlciBIVFRQLgogKgogKiBFeGFtcGxlIHVzYWdlOgogKiBgYGBwaHAKICogJHNlcmlhbGl6ZXIgPSBvdGxwX2pzb25fc2VyaWFsaXplcigpOwogKiAkdHJhbnNwb3J0ID0gb3RscF9jdXJsX3RyYW5zcG9ydCgkZW5kcG9pbnQsICRzZXJpYWxpemVyKTsKICogYGBgCiAqLw=="},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":70,"slug":"otlp-protobuf-serializer","name":"otlp_protobuf_serializer","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\DSL","parameters":[],"return_type":[{"name":"ProtobufSerializer","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Serializer","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFByb3RvYnVmIHNlcmlhbGl6ZXIgZm9yIE9UTFAuCiAqCiAqIFJldHVybnMgYSBQcm90b2J1ZlNlcmlhbGl6ZXIgdGhhdCBjb252ZXJ0cyB0ZWxlbWV0cnkgZGF0YSB0byBPVExQIFByb3RvYnVmIGJpbmFyeSBmb3JtYXQuCiAqIFVzZSB0aGlzIHdpdGggQ3VybFRyYW5zcG9ydCBmb3IgUHJvdG9idWYgb3ZlciBIVFRQLCBvciB3aXRoIEdycGNUcmFuc3BvcnQuCiAqCiAqIFJlcXVpcmVzOgogKiAtIGdvb2dsZS9wcm90b2J1ZiBwYWNrYWdlCiAqCiAqIEV4YW1wbGUgdXNhZ2U6CiAqIGBgYHBocAogKiAkc2VyaWFsaXplciA9IG90bHBfcHJvdG9idWZfc2VyaWFsaXplcigpOwogKiAkdHJhbnNwb3J0ID0gb3RscF9jdXJsX3RyYW5zcG9ydCgkZW5kcG9pbnQsICRzZXJpYWxpemVyKTsKICogYGBgCiAqLw=="},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":94,"slug":"otlp-grpc-transport","name":"otlp_grpc_transport","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\DSL","parameters":[{"name":"endpoint","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":"headers","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"insecure","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"name":"timeoutMs","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"250"},{"name":"shutdownTimeoutMs","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"5000"},{"name":"failover","type":[{"name":"Transport","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Transport","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Transport","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Transport","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGdSUEMgdHJhbnNwb3J0IGZvciBPVExQIGVuZHBvaW50cy4KICoKICogQ3JlYXRlcyBhIEdycGNUcmFuc3BvcnQgY29uZmlndXJlZCB0byBzZW5kIHRlbGVtZXRyeSBkYXRhIHRvIGFuIE9UTFAtY29tcGF0aWJsZQogKiBlbmRwb2ludCB1c2luZyBnUlBDIHByb3RvY29sIHdpdGggUHJvdG9idWYgc2VyaWFsaXphdGlvbi4gT1RMUC9nUlBDIG1hbmRhdGVzCiAqIFByb3RvYnVmLCBzbyB0aGUgc2VyaWFsaXplciBpcyBidWlsdCBpbnRlcm5hbGx5IGFuZCBub3QgY29uZmlndXJhYmxlLgogKgogKiBSZXF1aXJlczoKICogLSBleHQtZ3JwYyBQSFAgZXh0ZW5zaW9uCiAqIC0gZ29vZ2xlL3Byb3RvYnVmIHBhY2thZ2UKICoKICogQHBhcmFtIHN0cmluZyAkZW5kcG9pbnQgZ1JQQyBlbmRwb2ludCAoZS5nLiwgJ2xvY2FsaG9zdDo0MzE3JykKICogQHBhcmFtIGFycmF5PHN0cmluZywgc3RyaW5nPiAkaGVhZGVycyBBZGRpdGlvbmFsIGhlYWRlcnMgKG1ldGFkYXRhKSB0byBpbmNsdWRlIGluIHJlcXVlc3RzCiAqIEBwYXJhbSBib29sICRpbnNlY3VyZSBXaGV0aGVyIHRvIHVzZSBpbnNlY3VyZSBjaGFubmVsIGNyZWRlbnRpYWxzIChkZWZhdWx0IHRydWUgZm9yIGxvY2FsIGRldikKICogQHBhcmFtIGludCAkdGltZW91dE1zIFBlci1jYWxsIGRlYWRsaW5lIGluIG1pbGxpc2Vjb25kcyAoY292ZXJzIGNvbm5lY3QgKyBzZW5kICsgcmVjZWl2ZSkKICogQHBhcmFtIGludCAkc2h1dGRvd25UaW1lb3V0TXMgV2FsbC1jbG9jayBidWRnZXQgZm9yIGRyYWluaW5nIHBlbmRpbmcgY2FsbHMgYXQgc2h1dGRvd24KICogQHBhcmFtID9UcmFuc3BvcnQgJGZhaWxvdmVyIE9wdGlvbmFsIGZhaWxvdmVyIHRyYW5zcG9ydCByZWNlaXZpbmcgcHJpb3IgYmF0Y2hlcyB3aGVuIHByaW1hcnkgZmFpbHMKICov"},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":109,"slug":"otlp-curl-options","name":"otlp_curl_options","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\DSL","parameters":[],"return_type":[{"name":"CurlTransportOptions","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Transport","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBjdXJsIHRyYW5zcG9ydCBvcHRpb25zIGZvciBPVExQLgogKi8="},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":130,"slug":"otlp-curl-transport","name":"otlp_curl_transport","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\DSL","parameters":[{"name":"endpoint","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":"serializer","type":[{"name":"JsonSerializer","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Serializer","is_nullable":false,"is_variadic":false},{"name":"ProtobufSerializer","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Serializer","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Bridge\\Telemetry\\OTLP\\Serializer\\JsonSerializer::..."},{"name":"options","type":[{"name":"CurlTransportOptions","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Transport","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Bridge\\Telemetry\\OTLP\\Transport\\CurlTransportOptions::..."},{"name":"failover","type":[{"name":"Transport","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Transport","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Transport","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Transport","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHN5bmNocm9ub3VzIGN1cmwgdHJhbnNwb3J0IGZvciBPVExQIGVuZHBvaW50cy4KICoKICogQ3JlYXRlcyBhIEN1cmxUcmFuc3BvcnQgdGhhdCBkcml2ZXMgZWFjaCByZXF1ZXN0IHRvIGNvbXBsZXRpb24gYW5kIHJlcG9ydHMgdGhlCiAqIG91dGNvbWUgaW1tZWRpYXRlbHkgKHJldHVybnMgb24gc3VjY2VzcywgdGhyb3dzIG9uIGZhaWx1cmUpLiBPVExQL0hUVFAgYWxsb3dzCiAqIEpTT04gb3IgUHJvdG9idWYgZW5jb2Rpbmc7IGRlZmF1bHRzIHRvIEpTT04uIEtlZXBpbmcgZXhwb3J0IG9mZiB0aGUgYXBwbGljYXRpb24KICogaG90IHBhdGggaXMgdGhlIGpvYiBvZiB0aGUgYmF0Y2hpbmcgcHJvY2Vzc29yIGluIGZyb250IG9mIHRoZSBleHBvcnRlci4KICoKICogUmVxdWlyZXM6IGV4dC1jdXJsIFBIUCBleHRlbnNpb24KICoKICogQHBhcmFtIHN0cmluZyAkZW5kcG9pbnQgT1RMUCBlbmRwb2ludCBVUkwgKGUuZy4sICdodHRwOi8vbG9jYWxob3N0OjQzMTgnKQogKiBAcGFyYW0gSnNvblNlcmlhbGl6ZXJ8UHJvdG9idWZTZXJpYWxpemVyICRzZXJpYWxpemVyIFNlcmlhbGl6ZXIgZm9yIGVuY29kaW5nIHRlbGVtZXRyeSBkYXRhIChKU09OIG9yIFByb3RvYnVmKQogKiBAcGFyYW0gQ3VybFRyYW5zcG9ydE9wdGlvbnMgJG9wdGlvbnMgVHJhbnNwb3J0IGNvbmZpZ3VyYXRpb24gb3B0aW9ucwogKiBAcGFyYW0gP1RyYW5zcG9ydCAkZmFpbG92ZXIgT3B0aW9uYWwgZmFpbG92ZXIgdHJhbnNwb3J0IHJlY2VpdmluZyB0aGUgYmF0Y2ggd2hlbiB0aGUgcHJpbWFyeSBmYWlscwogKi8="},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":143,"slug":"otlp-async-curl-options","name":"otlp_async_curl_options","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\DSL","parameters":[],"return_type":[{"name":"AsyncCurlTransportOptions","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Transport","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhc3luYyBjdXJsIHRyYW5zcG9ydCBvcHRpb25zIGZvciBPVExQLgogKi8="},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":158,"slug":"otlp-async-curl-transport","name":"otlp_async_curl_transport","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\DSL","parameters":[{"name":"endpoint","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":"serializer","type":[{"name":"JsonSerializer","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Serializer","is_nullable":false,"is_variadic":false},{"name":"ProtobufSerializer","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Serializer","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Bridge\\Telemetry\\OTLP\\Serializer\\JsonSerializer::..."},{"name":"options","type":[{"name":"AsyncCurlTransportOptions","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Transport","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Bridge\\Telemetry\\OTLP\\Transport\\AsyncCurlTransportOptions::..."},{"name":"failover","type":[{"name":"Transport","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Transport","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"error_handler","type":[{"name":"ErrorHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\ErrorHandler\\ErrorLogHandler::..."}],"return_type":[{"name":"AsyncCurlTransport","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Transport","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBhc3luY2hyb25vdXMgY3VybCB0cmFuc3BvcnQgZm9yIE9UTFAgZW5kcG9pbnRzLgogKgogKiBAcGFyYW0gc3RyaW5nICRlbmRwb2ludCBPVExQIGVuZHBvaW50IFVSTCAoZS5nLiwgJ2h0dHA6Ly9sb2NhbGhvc3Q6NDMxOCcpCiAqIEBwYXJhbSBKc29uU2VyaWFsaXplcnxQcm90b2J1ZlNlcmlhbGl6ZXIgJHNlcmlhbGl6ZXIgU2VyaWFsaXplciBmb3IgZW5jb2RpbmcgdGVsZW1ldHJ5IGRhdGEgKEpTT04gb3IgUHJvdG9idWYpCiAqIEBwYXJhbSBBc3luY0N1cmxUcmFuc3BvcnRPcHRpb25zICRvcHRpb25zIFRyYW5zcG9ydCBjb25maWd1cmF0aW9uIG9wdGlvbnMKICogQHBhcmFtID9UcmFuc3BvcnQgJGZhaWxvdmVyIE9wdGlvbmFsIGZhaWxvdmVyIHRyYW5zcG9ydCByZWNlaXZpbmcgcHJpb3IgYmF0Y2hlcyB3aGVuIHByaW1hcnkgZmFpbHMKICogQHBhcmFtIEVycm9ySGFuZGxlciAkZXJyb3JfaGFuZGxlciBIYW5kbGVyIGZvciBmYWlsdXJlcyByZWFwZWQgb24gc2VuZCgpL3RpY2soKS9zaHV0ZG93bigpIChubyBmYWlsb3ZlcikKICov"},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":180,"slug":"otlp-stream-transport","name":"otlp_stream_transport","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\DSL","parameters":[{"name":"destination","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":"filePermissions","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"420"},{"name":"createDirectories","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":"Transport","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Transport","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHN0cmVhbSB0cmFuc3BvcnQgZm9yIE9UTFAgdGhhdCB3cml0ZXMgSlNPTkwgdG8gYSBzaW5nbGUgZGVzdGluYXRpb24uCiAqCiAqIEFjY2VwdHMgYW4gYWJzb2x1dGUgZmlsZSBwYXRoIG9yIGEgcGhwOi8vIHN0cmVhbSB3cmFwcGVyIHN1Y2ggYXMKICogJ3BocDovL3N0ZG91dCcsICdwaHA6Ly9zdGRlcnInLCAncGhwOi8vbWVtb3J5Jywgb3IgJ3BocDovL3RlbXAnLiBFYWNoCiAqIGV4cG9ydCgpIGNhbGwgYXBwZW5kcyBvbmUgSlNPTiBMaW5lIHVuZGVyIExPQ0tfRVggc28gY29uY3VycmVudCB3cml0ZXJzCiAqIGludGVybGVhdmUgYXQgbGluZSBib3VuZGFyaWVzLiBUaGUgJGZpbGVQZXJtaXNzaW9ucyBhbmQgJGNyZWF0ZURpcmVjdG9yaWVzCiAqIHBhcmFtZXRlcnMgYXBwbHkgb25seSB3aGVuIHRoZSBkZXN0aW5hdGlvbiBpcyBhIGZpbGUgcGF0aC4KICoKICogUGVyIHRoZSBPVExQIEZpbGUgRXhwb3J0ZXIgc3BlYyBvbmx5IEpTT04gZW5jb2RpbmcgaXMgc3VwcG9ydGVkLgogKi8="},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":203,"slug":"otlp-exporter","name":"otlp_exporter","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\DSL","parameters":[{"name":"transport","type":[{"name":"Transport","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Transport","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"errorHandler","type":[{"name":"ErrorHandler","namespace":"Flow\\Telemetry\\ErrorHandler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\ErrorHandler\\ErrorLogHandler::..."}],"return_type":[{"name":"OTLPExporter","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Exporter","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBPVExQIGV4cG9ydGVyIHRoYXQgZGlzcGF0Y2hlcyBsb2dzLCBtZXRyaWNzLCBhbmQgc3BhbnMgdGhyb3VnaCBhIHNpbmdsZSB0cmFuc3BvcnQuCiAqCiAqIEV4YW1wbGUgdXNhZ2U6CiAqIGBgYHBocAogKiAkZXhwb3J0ZXIgPSBvdGxwX2V4cG9ydGVyKCR0cmFuc3BvcnQpOwogKiAkc3BhblByb2Nlc3NvciA9IGJhdGNoaW5nX3NwYW5fcHJvY2Vzc29yKCRleHBvcnRlcik7CiAqICRtZXRyaWNQcm9jZXNzb3IgPSBiYXRjaGluZ19tZXRyaWNfcHJvY2Vzc29yKCRleHBvcnRlcik7CiAqICRsb2dQcm9jZXNzb3IgPSBiYXRjaGluZ19sb2dfcHJvY2Vzc29yKCRleHBvcnRlcik7CiAqIGBgYAogKgogKiBAcGFyYW0gVHJhbnNwb3J0ICR0cmFuc3BvcnQgVGhlIHRyYW5zcG9ydCBmb3Igc2VuZGluZyB0ZWxlbWV0cnkgZGF0YQogKiBAcGFyYW0gRXJyb3JIYW5kbGVyICRlcnJvckhhbmRsZXIgSGFuZGxlciBmb3IgVGhyb3dhYmxlcyByYWlzZWQgYnkgdGhlIHRyYW5zcG9ydAogKi8="},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":217,"slug":"otlp-tracer-provider","name":"otlp_tracer_provider","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\DSL","parameters":[{"name":"processor","type":[{"name":"SpanProcessor","namespace":"Flow\\Telemetry\\Tracer","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"clock","type":[{"name":"ClockInterface","namespace":"Psr\\Clock","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"sampler","type":[{"name":"Sampler","namespace":"Flow\\Telemetry\\Tracer\\Sampler","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\Tracer\\Sampler\\ParentBasedSampler::..."},{"name":"contextStorage","type":[{"name":"ContextStorage","namespace":"Flow\\Telemetry\\Context","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\Context\\MemoryContextStorage::..."}],"return_type":[{"name":"TracerProvider","namespace":"Flow\\Telemetry\\Tracer","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHRyYWNlciBwcm92aWRlciBjb25maWd1cmVkIGZvciBPVExQIGV4cG9ydC4KICoKICogQHBhcmFtIFNwYW5Qcm9jZXNzb3IgJHByb2Nlc3NvciBUaGUgcHJvY2Vzc29yIGZvciBoYW5kbGluZyBzcGFucwogKiBAcGFyYW0gQ2xvY2tJbnRlcmZhY2UgJGNsb2NrIFRoZSBjbG9jayBmb3IgdGltZXN0YW1wcwogKiBAcGFyYW0gU2FtcGxlciAkc2FtcGxlciBUaGUgc2FtcGxlciBmb3IgZGVjaWRpbmcgd2hldGhlciB0byByZWNvcmQgc3BhbnMKICogQHBhcmFtIENvbnRleHRTdG9yYWdlICRjb250ZXh0U3RvcmFnZSBUaGUgY29udGV4dCBzdG9yYWdlIGZvciBwcm9wYWdhdGluZyB0cmFjZSBjb250ZXh0CiAqLw=="},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":234,"slug":"otlp-meter-provider","name":"otlp_meter_provider","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\DSL","parameters":[{"name":"processor","type":[{"name":"MetricProcessor","namespace":"Flow\\Telemetry\\Meter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"clock","type":[{"name":"ClockInterface","namespace":"Psr\\Clock","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"temporality","type":[{"name":"AggregationTemporality","namespace":"Flow\\Telemetry\\Meter","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\Meter\\AggregationTemporality::..."}],"return_type":[{"name":"MeterProvider","namespace":"Flow\\Telemetry\\Meter","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIG1ldGVyIHByb3ZpZGVyIGNvbmZpZ3VyZWQgZm9yIE9UTFAgZXhwb3J0LgogKgogKiBAcGFyYW0gTWV0cmljUHJvY2Vzc29yICRwcm9jZXNzb3IgVGhlIHByb2Nlc3NvciBmb3IgaGFuZGxpbmcgbWV0cmljcwogKiBAcGFyYW0gQ2xvY2tJbnRlcmZhY2UgJGNsb2NrIFRoZSBjbG9jayBmb3IgdGltZXN0YW1wcwogKiBAcGFyYW0gQWdncmVnYXRpb25UZW1wb3JhbGl0eSAkdGVtcG9yYWxpdHkgVGhlIGFnZ3JlZ2F0aW9uIHRlbXBvcmFsaXR5IGZvciBtZXRyaWNzCiAqLw=="},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":250,"slug":"otlp-logger-provider","name":"otlp_logger_provider","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\DSL","parameters":[{"name":"processor","type":[{"name":"LogProcessor","namespace":"Flow\\Telemetry\\Logger","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"clock","type":[{"name":"ClockInterface","namespace":"Psr\\Clock","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"contextStorage","type":[{"name":"ContextStorage","namespace":"Flow\\Telemetry\\Context","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Telemetry\\Context\\MemoryContextStorage::..."}],"return_type":[{"name":"LoggerProvider","namespace":"Flow\\Telemetry\\Logger","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\Documentation\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGxvZ2dlciBwcm92aWRlciBjb25maWd1cmVkIGZvciBPVExQIGV4cG9ydC4KICoKICogQHBhcmFtIExvZ1Byb2Nlc3NvciAkcHJvY2Vzc29yIFRoZSBwcm9jZXNzb3IgZm9yIGhhbmRsaW5nIGxvZyByZWNvcmRzCiAqIEBwYXJhbSBDbG9ja0ludGVyZmFjZSAkY2xvY2sgVGhlIGNsb2NrIGZvciB0aW1lc3RhbXBzCiAqIEBwYXJhbSBDb250ZXh0U3RvcmFnZSAkY29udGV4dFN0b3JhZ2UgVGhlIGNvbnRleHQgc3RvcmFnZSBmb3IgcHJvcGFnYXRpbmcgY29udGV4dAogKi8="}] \ No newline at end of file

gvJ~zc)K&djWUDfQ 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 z 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%0A8c$3)RC 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